diff --git a/reoptjl/src/process_results.py b/reoptjl/src/process_results.py index dd22d08e5..5b5732d69 100644 --- a/reoptjl/src/process_results.py +++ b/reoptjl/src/process_results.py @@ -141,8 +141,10 @@ def update_inputs_in_database(inputs_to_update: dict, run_uuid: str) -> None: else: ExistingChillerInputs.objects.filter(meta__run_uuid=run_uuid).update(**inputs_to_update["ExistingChiller"]) if inputs_to_update["ASHPSpaceHeater"]: + prune_update_fields(ASHPSpaceHeaterInputs, inputs_to_update["ASHPSpaceHeater"]) ASHPSpaceHeaterInputs.objects.filter(meta__run_uuid=run_uuid).update(**inputs_to_update["ASHPSpaceHeater"]) if inputs_to_update["ASHPWaterHeater"]: + prune_update_fields(ASHPWaterHeaterInputs, inputs_to_update["ASHPWaterHeater"]) ASHPWaterHeaterInputs.objects.filter(meta__run_uuid=run_uuid).update(**inputs_to_update["ASHPWaterHeater"]) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() @@ -152,3 +154,13 @@ def update_inputs_in_database(inputs_to_update: dict, run_uuid: str) -> None: tb.format_tb(exc_traceback) ) log.debug(debug_msg) + +def prune_update_fields(model_obj, dict_to_update): + """ + REopt.jl may return more fields than the API has to update, so prune those extra ones before updating the model/db object + """ + field_names = [field.name for field in model_obj._meta.get_fields()] + dict_to_update_keys = list(dict_to_update.keys()) + for key in dict_to_update_keys: + if key not in field_names: + del dict_to_update[key] \ No newline at end of file diff --git a/reoptjl/test/posts/ashp_defaults_update.json b/reoptjl/test/posts/ashp_defaults_update.json new file mode 100644 index 000000000..d3302c1d6 --- /dev/null +++ b/reoptjl/test/posts/ashp_defaults_update.json @@ -0,0 +1,51 @@ +{ + "user_uuid": "1d2ef71e-fd93-4c4a-b5c3-1485a87f772e", + "webtool_uuid": "1ab7530f-74b8-4ea8-b8ed-f11bd953f61f", + "Settings": { + "optimality_tolerance": 0.001, + "solver_name": "HiGHS", + "off_grid_flag": false, + "include_climate_in_objective": false, + "include_health_in_objective": false + }, + "Meta": { + "address": "San Francisco CA USA" + }, + "Site": { + "latitude": 37.7749295, + "longitude": -122.4194155, + "include_exported_renewable_electricity_in_total": true, + "include_exported_elec_emissions_in_total": true, + "land_acres": 1000000.0, + "roof_squarefeet": 0 + }, + "ElectricLoad": { + "doe_reference_name": "Hospital" + }, + "ElectricTariff": { + "blended_annual_energy_rate": 0.15, + "blended_annual_demand_rate": 0.0 + }, + "ElectricUtility": { + "cambium_location_type": "GEA Regions", + "cambium_metric_col": "lrmer_co2e", + "cambium_scenario": "Mid-case", + "cambium_grid_level": "enduse" + }, + "SpaceHeatingLoad": { + "annual_mmbtu": 11570.916, + "doe_reference_name": "Hospital" + }, + "DomesticHotWaterLoad": { + "annual_mmbtu": 671.405, + "doe_reference_name": "Hospital" + }, + "ExistingBoiler": { + "fuel_type": "natural_gas", + "fuel_cost_per_mmbtu": 25.0 + }, + "ASHPSpaceHeater": { + "force_into_system": true, + "can_serve_cooling": false + } +} \ No newline at end of file diff --git a/reoptjl/test/test_job_endpoint.py b/reoptjl/test/test_job_endpoint.py index aebd2bf7a..579e16806 100644 --- a/reoptjl/test/test_job_endpoint.py +++ b/reoptjl/test/test_job_endpoint.py @@ -311,4 +311,19 @@ def test_centralghp(self): resp = self.api_client.get(f'/v3/job/{run_uuid}/results') r = json.loads(resp.content) - self.assertAlmostEqual(r["outputs"]["Financial"]["lifecycle_capital_costs"], 1046066.8, delta=1000) \ No newline at end of file + self.assertAlmostEqual(r["outputs"]["Financial"]["lifecycle_capital_costs"], 1046066.8, delta=1000) + + def test_ashp_defaults_update_from_julia(self): + # Test that the inputs_with_defaults_set_in_julia feature worked for ASHPSpaceHeater + post_file = os.path.join('reoptjl', 'test', 'posts', 'ashp_defaults_update.json') + post = json.load(open(post_file, 'r')) + resp = self.api_client.post('/stable/job/', format='json', data=post) + self.assertHttpCreated(resp) + r = json.loads(resp.content) + run_uuid = r.get('run_uuid') + + resp = self.api_client.get(f'/stable/job/{run_uuid}/results') + r = json.loads(resp.content) + + self.assertEquals(r["inputs"]["ASHPSpaceHeater"]["om_cost_per_ton"], 0.0) + self.assertEquals(r["inputs"]["ASHPSpaceHeater"]["sizing_factor"], 1.1) \ No newline at end of file