def test_process_sites(sess): site_code = "109" Site.insert(sess, site_code, "A Site") report_run = ReportRun.insert(sess, "asset", None, "asset", {}) sess.commit() asset_str = "\n".join(("code,,,status", )) file_like = StringIO(asset_str) output = StringIO() writer = csv.writer(output, lineterminator="\n") props = {"asset_comparison": {"ignore_site_codes": []}} _process_sites(sess, file_like, writer, props, report_run.id) assert output.getvalue() == "site_code,asset_status,chellow_status\n"
def test_process_sites(sess): site_code = "109" Site.insert(sess, site_code, "A Site") sess.commit() asset_str = "\n".join(("code,,,status", )) file_like = StringIO(asset_str) output = StringIO() writer = csv.writer(output, lineterminator="\n") props = {"asset_comparison": {"ignore_site_codes": []}} _process_sites(sess, file_like, writer, props) assert output.getvalue( ) == "Site Code,Asset Status,Chellow Status,Problem\n"
def content(start_date, finish_date, site_id, typ, user): sess = f = writer = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( "site_hh_data_" + start_date.strftime("%Y%m%d%H%M") + ".csv", user) f = open(running_name, mode='w', newline='') writer = csv.writer(f, lineterminator='\n') writer.writerow( ('Site Code', 'Type', 'Date') + tuple(map(str, range(1, 49)))) site = Site.get_by_id(sess, site_id) line = None for hh in site.hh_data(sess, start_date, finish_date): hh_start = hh['start_date'] if (hh_start.hour, hh_start.minute) == (0, 0): if line is not None: writer.writerow(line) line = [site.code, typ, hh_start.strftime("%Y-%m-%d")] line.append(str(hh[typ])) if line is not None: writer.writerow(line) except: msg = traceback.format_exc() sys.stderr.write(msg) writer.writerow([msg]) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def content(start_date, finish_date, site_id, typ, user): sess = f = writer = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( "site_hh_data_" + to_ct(start_date).strftime("%Y%m%d%H%M") + ".csv", user) f = open(running_name, mode="w", newline="") writer = csv.writer(f, lineterminator="\n") writer.writerow(("Site Code", "Type", "HH Start Clock-Time") + tuple(map(str, range(1, 51)))) site = Site.get_by_id(sess, site_id) line = None for hh in site.hh_data(sess, start_date, finish_date): hh_start_ct = to_ct(hh["start_date"]) if (hh_start_ct.hour, hh_start_ct.minute) == (0, 0): if line is not None: writer.writerow(line) line = [site.code, typ, hh_start_ct.strftime("%Y-%m-%d")] line.append(str(hh[typ])) if line is not None: writer.writerow(line) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg) writer.writerow([msg]) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def test_with_scenario(mocker, sess, client): mock_Thread = mocker.patch("chellow.reports.report_247.threading.Thread") properties = """{ "scenario_start_year": 2009, "scenario_start_month": 8, "scenario_duration": 1, "era_maps": { 2000-08-01T00:00:00Z: { "llfcs": { "22": { "new_export": "521" } }, "supplier_contracts": { "new_export": 10 } } }, "hh_data": { "CI017": { "generated": " 2009-08-01 00:00, 40 2009-08-15 00:00, 40" } } }""" scenario_props = loads(properties) scenario = Scenario.insert(sess, "New Gen", scenario_props) sess.commit() now = utc_datetime(2020, 1, 1) mocker.patch("chellow.reports.report_247.utc_datetime_now", return_value=now) site_code = "CI017" site = Site.insert(sess, site_code, "Water Works") data = { "site_id": site.id, "scenario_id": scenario.id, "compression": False, } response = client.post("/reports/247", data=data) match(response, 303) base_name = ["New Gen"] args = scenario_props, base_name, site.id, None, None, False, [], now mock_Thread.assert_called_with(target=content, args=args)
def long_process(start_date, finish_date, st_id, months, year, month, user): caches = {} tmp_file = sess = None try: sess = Session() if st_id is None: st = None base_name = "site_monthly_duration_for_all_site_for_" + \ str(months) + "_to_" + str(year) + "_" + str(month) + ".csv" else: st = Site.get_by_id(sess, st_id) base_name = "site_monthly_duration_for_" + st.code + "_" + \ str(months) + "_to_" + str(year) + "_" + str(month) + ".csv" running_name, finished_name = chellow.dloads.make_names( base_name, user) tmp_file = open(running_name, "w") forecast_date = chellow.computer.forecast_date() tmp_file.write( "Site Id,Site Name,Associated Site Ids,Sources," "Generator Types,Month,Metered Imported kWh," "Metered Displaced kWh,Metered Exported kWh,Metered Used kWh," "Metered Parasitic kWh,Metered Generated kWh," "Metered 3rd Party Import kWh,Metered 3rd Party Export kWh," "Metered Imported GBP,Metered Displaced GBP,Metered Exported GBP," "Metered Used GBP,Metered 3rd Party Import GBP," "Billed Imported kWh,Billed Imported GBP,Metering Type,Problem") for i in range(months): sites = sess.query(Site).order_by(Site.code) if st is not None: sites = sites.filter(Site.id == st.id) for site in sites: month_start = start_date + relativedelta(months=i) month_finish = month_start + relativedelta(months=1) - HH tmp_file.write( '\r\n' + ','.join( '"' + str(value) + '"' for value in process_site( sess, site, month_start, month_finish, forecast_date, tmp_file, start_date, finish_date, caches))) tmp_file.flush() except: msg = traceback.format_exc() sys.stderr.write(msg + '\n') tmp_file.write("Problem " + msg) finally: if sess is not None: sess.close() tmp_file.close() os.rename(running_name, finished_name)
def content(start_date, finish_date, site_id, typ, sess): try: site = Site.get_by_id(sess, site_id) yield ','.join( ('Site Code', 'Type', 'Date') + tuple(map(str, range(1, 49)))) for group in site.groups(sess, start_date, finish_date, True): for hh in group.hh_data(sess): hh_start = hh['start_date'] if (hh_start.hour, hh_start.minute) == (0, 0): yield '\r\n' + ','.join( (site.code, typ, hh_start.strftime("%Y-%m-%d"))) yield "," + str(hh[typ]) except: yield traceback.format_exc()
def test_https_handler(mocker, sess): site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_hhdc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) era = supply.eras[0] era.insert_channel(sess, True, "ACTIVE") sess.commit() mock_requests = mocker.patch("chellow.hh_importer.requests") mock_response = mocker.Mock() mock_requests.get.return_value = mock_response mock_response.json.return_value = { "DataPoints": [{ "Flags": 0, "Time": 636188256000000000, "Value": 21 }] } log = [] def log_f(msg): log.append(msg) properties = { "enabled": True, "protocol": "https", "download_days": 8, "url_template": "https://example.com/?from=" "{{chunk_start.strftime('%d/%m/%Y')}}&to=" "{{chunk_finish.strftime('%d/%m/%Y')}}", "url_values": { "22 7907 4116 080": { "api_key": "768234ht" } }, } now = utc_datetime(2020, 12, 22) https_handler(sess, log_f, properties, dc_contract, now=now) expected_log = [ "Window start: 2020-12-14 00:00", "Window finish: 2020-12-21 23:30", "Looking at MPAN core 22 7867 6232 781.", "Retrieving data from " "https://example.com/?from=14/12/2020&to=21/12/2020.", "Finished loading.", ] assert log == expected_log
def test_general_import_era_insert(sess): site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_dc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") insert_comms(sess) comm = Comm.get_by_code(sess, "GSM") exp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, comm, None, energisation_status, {}, None, None, None, None, None, "22 7867 6232 781", "521", exp_supplier_contract, "7748", 361, ) sess.commit() action = "insert" vals = [ "22 7867 6232 781", "2020-10-01 00:00", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "{no change}", "Fusion Supplier 2000", "{no change}", "{no change}", "{no change}", "{no change}", ] args = [] chellow.general_import.general_import_era(sess, action, vals, args)
def content(scenario_props, base_name, site_id, supply_id, user, compression, site_codes, now): report_context = {} try: comp = report_context["computer"] except KeyError: comp = report_context["computer"] = {} try: rate_cache = comp["rates"] except KeyError: rate_cache = comp["rates"] = {} try: ind_cont = report_context["contract_names"] except KeyError: ind_cont = report_context["contract_names"] = {} sess = None try: sess = Session() start_year = scenario_props["scenario_start_year"] start_month = scenario_props["scenario_start_month"] months = scenario_props["scenario_duration"] month_pairs = list( c_months_u(start_year=start_year, start_month=start_month, months=months)) start_date_utc = month_pairs[0][0] finish_date_utc = month_pairs[-1][-1] base_name.append( hh_format(start_date_utc).replace(" ", "_").replace(":", "").replace( "-", "")) base_name.append("for") base_name.append(str(months)) base_name.append("months") if "forecast_from" in scenario_props: forecast_from = scenario_props["forecast_from"] else: forecast_from = None if forecast_from is None: forecast_from = chellow.computer.forecast_date() else: forecast_from = to_utc(forecast_from) sites = sess.query(Site).distinct().order_by(Site.code) if site_id is not None: site = Site.get_by_id(sess, site_id) sites = sites.filter(Site.id == site.id) base_name.append("site") base_name.append(site.code) if supply_id is not None: supply = Supply.get_by_id(sess, supply_id) base_name.append("supply") base_name.append(str(supply.id)) sites = sites.join(SiteEra).join(Era).filter(Era.supply == supply) if len(site_codes) > 0: base_name.append("sitecodes") sites = sites.filter(Site.code.in_(site_codes)) running_name, finished_name = chellow.dloads.make_names( "_".join(base_name) + ".ods", user) rf = open(running_name, "wb") site_rows = [] era_rows = [] for rate_script in scenario_props.get("local_rates", []): contract_id = rate_script["contract_id"] try: cont_cache = rate_cache[contract_id] except KeyError: cont_cache = rate_cache[contract_id] = {} try: rate_script_start = rate_script["start_date"] except KeyError: raise BadRequest( f"Problem in the scenario properties. Can't find the " f"'start_date' key of the contract {contract_id} in " f"the 'local_rates' map.") try: rate_script_start = rate_script["start_date"] except KeyError: raise BadRequest( f"Problem in the scenario properties. Can't find the " f"'start_date' key of the contract {contract_id} in " f"the 'local_rates' map.") props = PropDict("scenario properties", rate_script["script"]) for dt in hh_range(report_context, rate_script_start, rate_script["finish_date"]): cont_cache[dt] = props for rate_script in scenario_props.get("industry_rates", []): contract_name = rate_script["contract_name"] try: cont_cache = ind_cont[contract_name] except KeyError: cont_cache = ind_cont[contract_name] = {} rfinish = rate_script["finish_date"] if rfinish is None: raise BadRequest( f"For the industry rate {contract_name} the finish_date " f"can't be null.") for dt in hh_range(report_context, rate_script["start_date"], rfinish): cont_cache[dt] = PropDict("scenario properties", rate_script["script"]) era_maps = scenario_props.get("era_maps", {}) by_hh = scenario_props.get("by_hh", False) scenario_hh = scenario_props.get("hh_data", {}) era_header_titles = [ "creation-date", "imp-mpan-core", "imp-supplier-contract", "exp-mpan-core", "exp-supplier-contract", "metering-type", "source", "generator-type", "supply-name", "msn", "pc", "site-id", "site-name", "associated-site-ids", "month", ] site_header_titles = [ "creation-date", "site-id", "site-name", "associated-site-ids", "month", "metering-type", "sources", "generator-types", ] summary_titles = [ "import-net-kwh", "export-net-kwh", "import-gen-kwh", "export-gen-kwh", "import-3rd-party-kwh", "export-3rd-party-kwh", "displaced-kwh", "used-kwh", "used-3rd-party-kwh", "import-net-gbp", "export-net-gbp", "import-gen-gbp", "export-gen-gbp", "import-3rd-party-gbp", "export-3rd-party-gbp", "displaced-gbp", "used-gbp", "used-3rd-party-gbp", "billed-import-net-kwh", "billed-import-net-gbp", "billed-supplier-import-net-gbp", "billed-dc-import-net-gbp", "billed-mop-import-net-gbp", ] title_dict = {} for cont_type, con_attr in ( ("mop", Era.mop_contract), ("dc", Era.dc_contract), ("imp-supplier", Era.imp_supplier_contract), ("exp-supplier", Era.exp_supplier_contract), ): titles = [] title_dict[cont_type] = titles conts = (sess.query(Contract).join(con_attr).join( Era.supply).join(Source).filter( Era.start_date <= finish_date_utc, or_(Era.finish_date == null(), Era.finish_date >= start_date_utc), ).distinct().order_by(Contract.id)) if supply_id is not None: conts = conts.filter(Era.supply_id == supply_id) for cont in conts: title_func = chellow.computer.contract_func( report_context, cont, "virtual_bill_titles") if title_func is None: raise Exception( f"For the contract {cont.name} there doesn't seem to " f"be a 'virtual_bill_titles' function.") for title in title_func(): if title not in titles: titles.append(title) tpr_query = (sess.query(Tpr).join(MeasurementRequirement).join( Ssc).join(Era).filter( Era.start_date <= finish_date_utc, or_(Era.finish_date == null(), Era.finish_date >= start_date_utc), ).order_by(Tpr.code).distinct()) for tpr in tpr_query.filter(Era.imp_supplier_contract != null()): for suffix in ("-kwh", "-rate", "-gbp"): title_dict["imp-supplier"].append(tpr.code + suffix) for tpr in tpr_query.filter(Era.exp_supplier_contract != null()): for suffix in ("-kwh", "-rate", "-gbp"): title_dict["exp-supplier"].append(tpr.code + suffix) era_rows.append( era_header_titles + summary_titles + [None] + ["mop-" + t for t in title_dict["mop"]] + [None] + ["dc-" + t for t in title_dict["dc"]] + [None] + ["imp-supplier-" + t for t in title_dict["imp-supplier"]] + [None] + ["exp-supplier-" + t for t in title_dict["exp-supplier"]]) site_rows.append(site_header_titles + summary_titles) sites = sites.all() deltas = {} normal_reads = set() normal_read_rows = [] for site in sites: deltas[site.id] = _make_site_deltas(sess, report_context, site, scenario_hh, forecast_from, supply_id) for month_start, month_finish in month_pairs: for site in sites: if by_hh: sf = [(d, d) for d in hh_range(report_context, month_start, month_finish)] else: sf = [(month_start, month_finish)] for start, finish in sf: normal_reads = normal_reads | _process_site( sess, report_context, forecast_from, start, finish, site, deltas[site.id], supply_id, era_maps, now, summary_titles, title_dict, era_rows, site_rows, ) normal_read_rows = [[ "mpan_core", "date", "msn", "type", "registers" ]] for mpan_core, r in sorted(list(normal_reads)): row = [mpan_core, r.date, r.msn, r.type] + list(r.reads) normal_read_rows.append(row) write_spreadsheet(rf, compression, site_rows, era_rows, normal_read_rows) except BadRequest as e: msg = e.description + traceback.format_exc() sys.stderr.write(msg + "\n") site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, era_rows, normal_read_rows) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg + "\n") site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, era_rows, normal_read_rows) finally: if sess is not None: sess.close() try: rf.close() os.rename(running_name, finished_name) except BaseException: msg = traceback.format_exc() r_name, f_name = chellow.dloads.make_names("error.txt", user) ef = open(r_name, "w") ef.write(msg + "\n") ef.close()
def test_scenario_new_generation(mocker, sess): site = Site.insert(sess, "CI017", "Water Works") start_date = utc_datetime(2009, 7, 31, 23, 00) finish_date = utc_datetime(2009, 8, 31, 22, 30) supply_id = None report_context = {} forecast_from = utc_datetime(2020, 1, 1) market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_dc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") insert_comms(sess) comm = Comm.get_by_code(sess, "GSM") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, comm, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) sess.commit() scenario_hh = { "CI017": { "generated": """ 2009-08-01 00:00, 40 2009-08-15 00:00, 40""" } } era_maps = { utc_datetime(2000, 8, 1): { "llfcs": { "22": { "new_export": "521" } }, "supplier_contracts": { "new_export": 4 }, } } site_deltas = _make_site_deltas(sess, report_context, site, scenario_hh, forecast_from, supply_id) calcs, _, _ = _make_calcs( sess, site, start_date, finish_date, supply_id, site_deltas, forecast_from, report_context, era_maps, ) assert calcs[1][1] == "CI017_extra_gen_TRUE" assert calcs[2][2] == "CI017_extra_net_export"
def test_init_hh_data(sess, mocker): """New style channels""" site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_hhdc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) era = supply.eras[0] channel = era.insert_channel(sess, True, "ACTIVE") data_raw = [{ "start_date": utc_datetime(2009, 8, 10), "value": 10, "status": "A", }] channel.add_hh_data(sess, data_raw) sess.commit() caches = {} chunk_start = utc_datetime(2009, 7, 31, 23, 00) chunk_finish = utc_datetime(2009, 8, 31, 22, 30) is_import = True full_channels, hhd = chellow.computer._init_hh_data( sess, caches, era, chunk_start, chunk_finish, is_import) assert full_channels expected_hhd = { utc_datetime(2009, 8, 10): { "imp-msp-kvarh": 0.0, "imp-msp-kvar": 0.0, "exp-msp-kvarh": 0.0, "exp-msp-kvar": 0.0, "status": "A", "hist-kwh": 10.0, "msp-kwh": 10.0, "msp-kw": 20.0, } } assert hhd == expected_hhd
def test_bill_after_end_supply(mocker, sess): site = Site.insert(sess, "CI017", "Water Works") start_date = utc_datetime(2009, 7, 31, 23, 00) months = 1 supply_id = None market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_charge_script = """ from chellow.utils import reduce_bill_hhs def virtual_bill_titles(): return ['net-gbp', 'problem'] def virtual_bill(ds): for hh in ds.hh_data: hh_start = hh['start-date'] bill_hh = ds.supplier_bill_hhs[hh_start] bill_hh['net-gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) ds.mop_bill = reduce_bill_hhs(ds.supplier_bill_hhs) """ mop_contract = Contract.insert_mop( sess, "Fusion Mop Contract", participant, mop_charge_script, {}, utc_datetime(2000, 1, 1), None, {}, ) dc_charge_script = """ from chellow.utils import reduce_bill_hhs def virtual_bill_titles(): return ['net-gbp', 'problem'] def virtual_bill(ds): for hh in ds.hh_data: hh_start = hh['start-date'] bill_hh = ds.supplier_bill_hhs[hh_start] bill_hh['net-gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) ds.dc_bill = reduce_bill_hhs(ds.supplier_bill_hhs) """ dc_contract = Contract.insert_dc( sess, "Fusion DC 2000", participant, dc_charge_script, {}, utc_datetime(2000, 1, 1), None, {}, ) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") insert_comms(sess) comm = Comm.get_by_code(sess, "GSM") supplier_charge_script = """ import chellow.ccl from chellow.utils import HH, reduce_bill_hhs, utc_datetime def virtual_bill_titles(): return [ 'ccl-kwh', 'ccl-rate', 'ccl-gbp', 'net-gbp', 'vat-gbp', 'gross-gbp', 'sum-msp-kwh', 'sum-msp-gbp', 'problem'] def virtual_bill(ds): for hh in ds.hh_data: hh_start = hh['start-date'] bill_hh = ds.supplier_bill_hhs[hh_start] bill_hh['sum-msp-kwh'] = hh['msp-kwh'] bill_hh['sum-msp-gbp'] = hh['msp-kwh'] * 0.1 bill_hh['net-gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) bill_hh['vat-gbp'] = 0 bill_hh['gross-gbp'] = bill_hh['net-gbp'] + bill_hh['vat-gbp'] ds.supplier_bill = reduce_bill_hhs(ds.supplier_bill_hhs) """ imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, supplier_charge_script, {}, utc_datetime(2000, 1, 1), None, {}, ) batch = imp_supplier_contract.insert_batch(sess, "a b", "") dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") gsp_group = GspGroup.insert(sess, "_L", "South Western") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), utc_datetime(2000, 1, 31, 23, 30), gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, comm, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) insert_bill_types(sess) bill_type = sess.execute( select(BillType).where(BillType.code == "N")).scalar_one() batch.insert_bill( sess, "dd", "hjk", start_date, utc_datetime(2009, 7, 10), utc_datetime(2009, 7, 10), Decimal("10.00"), Decimal("10.00"), Decimal("10.00"), Decimal("10.00"), bill_type, {}, supply, ) sess.commit() scenario_props = { "scenario_start_year": start_date.year, "scenario_start_month": start_date.month, "scenario_duration": months, "by_hh": False, } base_name = ["monthly_duration"] site_id = site.id user = mocker.Mock() compression = False site_codes = [] now = utc_datetime(2020, 1, 1) mock_file = BytesIO() mock_file.close = mocker.Mock() mocker.patch("chellow.reports.report_247.open", return_value=mock_file) mocker.patch("chellow.reports.report_247.chellow.dloads.make_names", return_value=("a", "b")) mocker.patch("chellow.reports.report_247.os.rename") content( scenario_props, base_name, site_id, supply_id, user, compression, site_codes, now, ) sheet = odio.parse_spreadsheet(mock_file) table = list(sheet.tables[0].rows) expected = [ [ "creation-date", "site-id", "site-name", "associated-site-ids", "month", "metering-type", "sources", "generator-types", "import-net-kwh", "export-net-kwh", "import-gen-kwh", "export-gen-kwh", "import-3rd-party-kwh", "export-3rd-party-kwh", "displaced-kwh", "used-kwh", "used-3rd-party-kwh", "import-net-gbp", "export-net-gbp", "import-gen-gbp", "export-gen-gbp", "import-3rd-party-gbp", "export-3rd-party-gbp", "displaced-gbp", "used-gbp", "used-3rd-party-gbp", "billed-import-net-kwh", "billed-import-net-gbp", "billed-supplier-import-net-gbp", "billed-dc-import-net-gbp", "billed-mop-import-net-gbp", ], [ Datetime(2020, 1, 1, 0, 0), "CI017", "Water Works", "", Datetime(2009, 7, 31, 23, 30), None, "", "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.0, 10.0, 0.0, 0.0, ], ] assert expected == table
def test_bill_http(mocker, sess, client): site = Site.insert(sess, "22488", "Water Works") g_dn = GDn.insert(sess, "EE", "East of England") g_ldz = g_dn.insert_g_ldz(sess, "EA") g_exit_zone = g_ldz.insert_g_exit_zone(sess, "EA1") insert_g_units(sess) g_unit_M3 = GUnit.get_by_code(sess, "M3") participant = Participant.insert(sess, "CALB", "AK Industries") market_role_Z = MarketRole.get_by_code(sess, "Z") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) g_contract = GContract.insert(sess, "Fusion 2020", "", {}, utc_datetime(2000, 1, 1), None, {}) insert_g_reading_frequencies(sess) g_reading_frequency_M = GReadingFrequency.get_by_code(sess, "M") g_supply = site.insert_g_supply( sess, "87614362", "main", g_exit_zone, utc_datetime(2018, 1, 1), None, "hgeu8rhg", 1, g_unit_M3, g_contract, "d7gthekrg", g_reading_frequency_M, ) g_batch = g_contract.insert_g_batch(sess, "b1", "Jan batch") breakdown = {"units_consumed": 771} insert_bill_types(sess) bill_type_n = BillType.get_by_code(sess, "N") g_bill = g_batch.insert_g_bill( sess, g_supply, bill_type_n, "55h883", "dhgh883", utc_datetime(2019, 4, 3), utc_datetime(2020, 1, 1), utc_datetime(2020, 1, 31, 23, 30), Decimal("45"), Decimal("12.40"), Decimal("1.20"), Decimal("14.52"), "", breakdown, ) sess.commit() data = {"g_bill_id": g_bill.id} mock_Thread = mocker.patch("chellow.reports.report_429.threading.Thread", autospec=True) response = client.get("/reports/429", data=data) match(response, 303) user = None args = (None, g_bill.id, user) mock_Thread.assert_called_with(target=chellow.reports.report_429.content, args=args)
def test_Supply_insert_era_at(sess): """Where an era is inserted in the last HH of another era, check the template era is the one at the insertion date. """ site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_hhdc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) mtc_845 = Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") era1_msn = "e1msn" imp_mpan_core = "22 7867 6232 781" supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", era1_msn, pc, "845", cop, None, energisation_status, {}, imp_mpan_core, "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) era1 = supply.eras[0] era2_start_date = utc_datetime(2009, 7, 31, 23, 30) era2 = supply.insert_era_at(sess, era2_start_date) era2_msn = "e2msn" era2.update( sess, era2_start_date, None, mop_contract, "379540", dc_contract, "547yt", era2_msn, pc, mtc_845, cop, None, energisation_status, {}, imp_mpan_core, "510", imp_supplier_contract, "9745y6", 361, None, None, None, None, None, ) sess.commit() start_date = utc_datetime(2009, 7, 31, 23, 00) era3 = supply.insert_era_at(sess, start_date) assert era3.msn == era1.msn
def test_supply(mocker, sess, client): site = Site.insert(sess, "22488", "Water Works") g_dn = GDn.insert(sess, "EE", "East of England") g_ldz = g_dn.insert_g_ldz(sess, "EA") g_exit_zone = g_ldz.insert_g_exit_zone(sess, "EA1") insert_g_units(sess) g_unit_M3 = GUnit.get_by_code(sess, "M3") participant = Participant.insert(sess, "CALB", "AK Industries") market_role_Z = MarketRole.get_by_code(sess, "Z") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) g_cv_rate_script = { "cvs": { "EA": { 1: { "applicable_at": utc_datetime(2020, 10, 3), "cv": 39.2000 }, } } } Contract.insert_non_core(sess, "g_cv", "", {}, utc_datetime(2000, 1, 1), None, g_cv_rate_script) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) charge_script = """ import chellow.g_ccl from chellow.g_engine import g_rates from chellow.utils import reduce_bill_hhs def virtual_bill_titles(): return [ 'units_consumed', 'correction_factor', 'unit_code', 'unit_factor', 'calorific_value', 'kwh', 'gas_rate', 'gas_gbp', 'ccl_rate', 'standing_rate', 'standing_gbp', 'net_gbp', 'vat_gbp', 'gross_gbp', 'problem'] def virtual_bill(ds): chellow.g_ccl.vb(ds) for hh in ds.hh_data: start_date = hh['start_date'] bill_hh = ds.bill_hhs[start_date] bill_hh['units_consumed'] = hh['units_consumed'] bill_hh['correction_factor'] = {hh['correction_factor']} bill_hh['unit_code'] = {hh['unit_code']} bill_hh['unit_factor'] = {hh['unit_factor']} bill_hh['calorific_value'] = {hh['calorific_value']} kwh = hh['kwh'] bill_hh['kwh'] = kwh gas_rate = float( g_rates(ds.sess, ds.caches, db_id, start_date)['gas_rate']) bill_hh['gas_rate'] = {gas_rate} bill_hh['gas_gbp'] = gas_rate * kwh bill_hh['ccl_kwh'] = kwh ccl_rate = hh['ccl'] bill_hh['ccl_rate'] = {ccl_rate} bill_hh['ccl_kwh'] = kwh bill_hh['ccl_gbp'] = kwh * ccl_rate if hh['utc_is_month_end']: standing_rate = float( g_rates( ds.sess, ds.caches, db_id, start_date)['standing_rate']) bill_hh['standing_rate'] = {standing_rate} bill_hh['standing_gbp'] = standing_rate if hh['utc_decimal_hour'] == 0: pass bill_hh['net_gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) bill_hh['vat_gbp'] = 0 bill_hh['gross_gbp'] = bill_hh['net_gbp'] + bill_hh['vat_gbp'] ds.bill = reduce_bill_hhs(ds.bill_hhs) """ g_contract_rate_script = { "gas_rate": 0.1, "standing_rate": 0.1, } g_contract = GContract.insert( sess, "Fusion 2020", charge_script, {}, utc_datetime(2000, 1, 1), None, g_contract_rate_script, ) insert_g_reading_frequencies(sess) g_reading_frequency_M = GReadingFrequency.get_by_code(sess, "M") msn = "hgeu8rhg" g_supply = site.insert_g_supply( sess, "87614362", "main", g_exit_zone, utc_datetime(2010, 1, 1), None, msn, 1, g_unit_M3, g_contract, "d7gthekrg", g_reading_frequency_M, ) g_batch = g_contract.insert_g_batch(sess, "b1", "Jan batch") breakdown = {"units_consumed": 771} insert_bill_types(sess) bill_type_N = BillType.get_by_code(sess, "N") insert_g_read_types(sess) g_read_type_A = GReadType.get_by_code(sess, "A") g_bill = g_batch.insert_g_bill( sess, g_supply, bill_type_N, "55h883", "dhgh883", utc_datetime(2019, 4, 3), utc_datetime(2015, 9, 1), utc_datetime(2015, 9, 30, 22, 30), Decimal("45"), Decimal("12.40"), Decimal("1.20"), Decimal("14.52"), "", breakdown, ) g_bill.insert_g_read( sess, msn, g_unit_M3, Decimal("1"), Decimal("37"), Decimal("90"), utc_datetime(2015, 9, 1), g_read_type_A, Decimal("890"), utc_datetime(2015, 9, 25), g_read_type_A, ) sess.commit() mock_file = BytesIO() mock_file.close = mocker.Mock() mocker.patch("chellow.reports.report_g_monthly_duration.open", return_value=mock_file) mocker.patch( "chellow.reports.report_g_monthly_duration.chellow.dloads.make_names", return_value=("a", "b"), ) mocker.patch("chellow.reports.report_g_monthly_duration.os.rename") user = mocker.Mock() site_id = site.id g_supply_id = g_supply.id compression = False finish_year = 2015 finish_month = 9 months = 1 now = utc_datetime(2020, 9, 1) chellow.reports.report_g_monthly_duration.content( site_id, g_supply_id, user, compression, finish_year, finish_month, months, now=now, ) sheet = odio.parse_spreadsheet(mock_file) table = list(sheet.tables[1].rows) expected = [ [ "creation_date", "mprn", "supply_name", "exit_zone", "msn", "unit", "contract", "site_id", "site_name", "associated_site_ids", "month", "kwh", "gbp", "billed_kwh", "billed_gbp", "units_consumed", "correction_factor", "unit_code", "unit_factor", "calorific_value", "kwh", "gas_rate", "gas_gbp", "ccl_rate", "standing_rate", "standing_gbp", "net_gbp", "vat_gbp", "gross_gbp", "problem", ], [ Datetime(2020, 9, 1, 1), "87614362", "main", "EA1", "hgeu8rhg", "M3", "Fusion 2020", "22488", "Water Works", "", Datetime(2015, 9, 30, 23, 30), 10888.888888888665, 1146.1869155555785, 45.0, 12.4, 1000.0000000000156, 1.0, "M3", 1.0, 39.2, 10888.888888888665, 0.1, 1088.8888888888619, 0.00525288, 0.1, 0.1, 1146.1869155555785, 0.0, 1146.1869155555785, None, ], ] assert expected == table
def get(self, site_id): return Site.get_by_id(g.sess, site_id)
def content(base_name, site_id, g_supply_id, user, compression, start_date, months): now = utc_datetime_now() report_context = {} sess = None try: sess = Session() base_name.append( hh_format(start_date).replace(' ', '_').replace(':', '').replace('-', '')) base_name.append('for') base_name.append(str(months)) base_name.append('months') finish_date = start_date + relativedelta(months=months) forecast_from = chellow.computer.forecast_date() sites = sess.query(Site).distinct().order_by(Site.code) if site_id is not None: site = Site.get_by_id(sess, site_id) sites = sites.filter(Site.id == site.id) base_name.append('site') base_name.append(site.code) if g_supply_id is not None: g_supply = GSupply.get_by_id(sess, g_supply_id) base_name.append('g_supply') base_name.append(str(g_supply.id)) sites = sites.join(SiteGEra).join(GEra).filter( GEra.g_supply == g_supply) running_name, finished_name = chellow.dloads.make_names( '_'.join(base_name) + '.ods', user) rf = open(running_name, "wb") site_rows = [] g_era_rows = [] era_header_titles = [ 'creation_date', 'mprn', 'supply_name', 'exit_zone', 'msn', 'unit', 'contract', 'site_id', 'site_name', 'associated_site_ids', 'month' ] site_header_titles = [ 'creation_date', 'site_id', 'site_name', 'associated_site_ids', 'month' ] summary_titles = ['kwh', 'gbp', 'billed_kwh', 'billed_gbp'] vb_titles = [] conts = sess.query(GContract).join(GEra).join(GSupply).filter( GEra.start_date <= finish_date, or_(GEra.finish_date == null(), GEra.finish_date >= start_date)).distinct().order_by( GContract.id) if g_supply_id is not None: conts = conts.filter(GEra.g_supply_id == g_supply_id) for cont in conts: title_func = chellow.computer.contract_func( report_context, cont, 'virtual_bill_titles') if title_func is None: raise Exception("For the contract " + cont.name + " there doesn't seem " + "to be a 'virtual_bill_titles' function.") for title in title_func(): if title not in vb_titles: vb_titles.append(title) g_era_rows.append(era_header_titles + summary_titles + vb_titles) site_rows.append(site_header_titles + summary_titles) sites = sites.all() month_start = start_date while month_start < finish_date: month_finish = month_start + relativedelta(months=1) - HH for site in sites: site_kwh = site_gbp = site_billed_kwh = site_billed_gbp = 0 for g_era in sess.query(GEra).join(SiteGEra).filter( SiteGEra.site == site, SiteGEra.is_physical == true(), GEra.start_date <= month_finish, or_(GEra.finish_date == null(), GEra.finish_date >= month_start)).options( joinedload(GEra.g_contract), joinedload(GEra.g_supply), joinedload(GEra.g_supply).joinedload( GSupply.g_exit_zone)).order_by(GEra.id): g_supply = g_era.g_supply if g_supply_id is not None and g_supply.id != g_supply_id: continue ss_start = hh_max(g_era.start_date, month_start) ss_finish = hh_min(g_era.finish_date, month_finish) ss = GDataSource(sess, ss_start, ss_finish, forecast_from, g_era, report_context, None) contract = g_era.g_contract vb_function = contract_func(report_context, contract, 'virtual_bill') if vb_function is None: raise BadRequest( "The contract " + contract.name + " doesn't have the virtual_bill() function.") vb_function(ss) bill = ss.bill try: gbp = bill['net_gbp'] except KeyError: gbp = 0 bill['problem'] += 'For the supply ' + ss.mprn + \ ' the virtual bill ' + str(bill) + \ ' from the contract ' + contract.name + \ ' does not contain the net_gbp key.' try: kwh = bill['kwh'] except KeyError: kwh = 0 bill['problem'] += "For the supply " + ss.mprn + \ " the virtual bill " + str(bill) + \ " from the contract " + contract.name + \ " does not contain the 'kwh' key." billed_kwh = billed_gbp = 0 g_era_associates = { s.site.code for s in g_era.site_g_eras if not s.is_physical } for g_bill in sess.query(GBill).filter( GBill.g_supply == g_supply, GBill.start_date <= ss_finish, GBill.finish_date >= ss_start): bill_start = g_bill.start_date bill_finish = g_bill.finish_date bill_duration = ( bill_finish - bill_start).total_seconds() + \ (30 * 60) overlap_duration = (min(bill_finish, ss_finish) - max( bill_start, ss_start)).total_seconds() + (30 * 60) overlap_proportion = overlap_duration / bill_duration billed_kwh += overlap_proportion * float(g_bill.kwh) billed_gbp += overlap_proportion * float(g_bill.net) associated_site_ids = ','.join(sorted(g_era_associates)) g_era_rows.append([ now, g_supply.mprn, g_supply.name, g_supply.g_exit_zone .code, g_era.msn, g_era.g_unit.code, contract.name, site.code, site.name, associated_site_ids, month_finish, kwh, gbp, billed_kwh, billed_gbp ] + [make_val(bill.get(t)) for t in vb_titles]) site_kwh += kwh site_gbp += gbp site_billed_kwh += billed_kwh site_billed_gbp += billed_gbp linked_sites = ', '.join(s.code for s in site.find_linked_sites( sess, month_start, month_finish)) site_rows.append([ now, site.code, site.name, linked_sites, month_finish, site_kwh, site_gbp, site_billed_kwh, site_billed_gbp ]) sess.rollback() write_spreadsheet(rf, compression, site_rows, g_era_rows) month_start += relativedelta(months=1) except BadRequest as e: msg = e.description + traceback.format_exc() sys.stderr.write(msg + '\n') site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, g_era_rows) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg + '\n') site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, g_era_rows) finally: if sess is not None: sess.close() try: rf.close() os.rename(running_name, finished_name) except BaseException: msg = traceback.format_exc() r_name, f_name = chellow.dloads.make_names('error.txt', user) ef = open(r_name, "w") ef.write(msg + '\n') ef.close()
def test_process(mocker, sess): site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party( sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None ) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party( sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None ) participant.insert_party( sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None ) participant.insert_party( sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None ) mop_contract = Contract.insert_mop( sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {} ) dc_contract = Contract.insert_dc( sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {} ) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") insert_comms(sess) comm = Comm.get_by_code(sess, "GSM") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party( sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22" ) meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert( sess, "CR", "Credit", utc_datetime(1996, 1, 1), None ) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") gsp_group = GspGroup.insert(sess, "_L", "South Western") site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, comm, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) site.insert_e_supply( sess, source, None, "Dave", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, comm, None, energisation_status, {}, "22 7868 6232 789", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) report_run = ReportRun.insert( sess, "ecoes_comparison", None, "ecoes_comparison", {}, ) sess.commit() f = StringIO() ecoes_lines = [ "titles", ",".join( ( "2278676232781", "address-line-1", "address-line-2", "address-line-3", "address-line-4", "address-line-5", "address-line-6", "address-line-7", "address-line-8", "address-line-9", "post-code", "supplier", "registration-from", "mtc", "mtc-date", "llfc", "llfc-from", "pc", "", "measurement-class", "energisation-status", "da", "dc", "mop", "mop-appoint-date", "gsp-group", "gsp-effective-from", "dno", "msn", "meter-install-date", "meter-type", "map-id", ), ), ",".join( ( "2278686232789", "address-line-1", "address-line-2", "address-line-3", "address-line-4", "address-line-5", "address-line-6", "address-line-7", "address-line-8", "address-line-9", "post-code", "supplier", "registration-from", "mtc", "mtc-date", "llfc", "llfc-from", "pc", "", "measurement-class", "energisation-status", "da", "dc", "mop", "mop-appoint-date", "gsp-group", "gsp-effective-from", "dno", "msn", "meter-install-date", "meter-type", "map-id", ), ), ] exclude_mpan_cores = [] ignore_mpan_cores_msn = [] show_ignored = True _process( sess, ecoes_lines, exclude_mpan_cores, ignore_mpan_cores_msn, f, show_ignored, report_run, ) expected = [ [ "mpan_core", "mpan_core_no_spaces", "ecoes_pc", "chellow_pc", "ecoes_mtc", "chellow_mtc", "ecoes_llfc", "chellow_llfc", "ecoes_ssc", "chellow_ssc", "ecoes_es", "chellow_es", "ecoes_supplier", "chellow_supplier", "chellow_supplier_contract_name", "ecoes_dc", "chellow_dc", "ecoes_mop", "chellow_mop", "ecoes_gsp_group", "chellow_gsp_group", "ecoes_msn", "chellow_msn", "ecoes_msn_install_date", "ecoes_meter_type", "chellow_meter_type", "ignored", "problem", ], [ "22 7867 6232 781", "2278676232781", "pc", "00", "mtc", "845", "llfc", "510", "", "", "energisation-status", "E", "supplier", "CALB", "Fusion Supplier 2000", "dc", "CALB", "mop", "CALB", "gsp-group", "_L", "msn", "hgjeyhuw", "meter-install-date", "meter-type", "H", "False", "The energisation statuses don't match. Can't parse the PC. Can't parse " "the MTC. The LLFCs don't match. The supplier codes don't match. The DC " "codes don't match. The MOP codes don't match. The GSP group codes don't " "match. The meter serial numbers don't match. The meter types don't match. " "See https://dtc.mrasco.com/DataItem.aspx?ItemCounter=0483 ", ], [ "22 7868 6232 789", "2278686232789", "pc", "00", "mtc", "845", "llfc", "510", "", "", "energisation-status", "E", "supplier", "CALB", "Fusion Supplier 2000", "dc", "CALB", "mop", "CALB", "gsp-group", "_L", "msn", "hgjeyhuw", "meter-install-date", "meter-type", "H", "False", "The energisation statuses don't match. Can't parse the PC. Can't parse " "the MTC. The LLFCs don't match. The supplier codes don't match. The DC " "codes don't match. The MOP codes don't match. The GSP group codes don't " "match. The meter serial numbers don't match. The meter types don't match. " "See https://dtc.mrasco.com/DataItem.aspx?ItemCounter=0483 ", ], ] assert f.getvalue() == "\n".join(",".join(line) for line in expected) + "\n"
def content(site_id, g_supply_id, user, compression, finish_year, finish_month, months, now=None): if now is None: now = ct_datetime_now() report_context = {} sess = None month_list = list( c_months_u(finish_year=finish_year, finish_month=finish_month, months=months)) start_date, finish_date = month_list[0][0], month_list[-1][-1] try: sess = Session() base_name = [ "g_monthly_duration", hh_format(start_date).replace(" ", "_").replace(":", "").replace("-", ""), "for", str(months), "months", ] forecast_from = chellow.computer.forecast_date() sites = (sess.query(Site).join(SiteGEra).join(GEra).filter( SiteGEra.is_physical == true()).distinct().order_by(Site.code)) if site_id is not None: site = Site.get_by_id(sess, site_id) sites = sites.filter(Site.id == site.id) base_name.append("site") base_name.append(site.code) if g_supply_id is not None: g_supply = GSupply.get_by_id(sess, g_supply_id) base_name.append("g_supply") base_name.append(str(g_supply.id)) sites = sites.filter(GEra.g_supply == g_supply) running_name, finished_name = chellow.dloads.make_names( "_".join(base_name) + ".ods", user) rf = open(running_name, "wb") site_rows = [] g_era_rows = [] era_header_titles = [ "creation_date", "mprn", "supply_name", "exit_zone", "msn", "unit", "contract", "site_id", "site_name", "associated_site_ids", "month", ] site_header_titles = [ "creation_date", "site_id", "site_name", "associated_site_ids", "month", ] summary_titles = ["kwh", "gbp", "billed_kwh", "billed_gbp"] vb_titles = [] conts = (sess.query(GContract).join(GEra).join(GSupply).filter( GEra.start_date <= finish_date, or_(GEra.finish_date == null(), GEra.finish_date >= start_date), ).distinct().order_by(GContract.id)) if g_supply_id is not None: conts = conts.filter(GEra.g_supply_id == g_supply_id) for cont in conts: title_func = chellow.computer.contract_func( report_context, cont, "virtual_bill_titles") if title_func is None: raise Exception("For the contract " + cont.name + " there doesn't seem " + "to be a 'virtual_bill_titles' function.") for title in title_func(): if title not in vb_titles: vb_titles.append(title) g_era_rows.append(era_header_titles + summary_titles + vb_titles) site_rows.append(site_header_titles + summary_titles) for month_start, month_finish in month_list: for site in sites.filter( GEra.start_date <= month_finish, or_(GEra.finish_date == null(), GEra.finish_date >= month_start), ): site_kwh = site_gbp = site_billed_kwh = site_billed_gbp = 0 for g_era in (sess.query(GEra).join(SiteGEra).filter( SiteGEra.site == site, SiteGEra.is_physical == true(), GEra.start_date <= month_finish, or_(GEra.finish_date == null(), GEra.finish_date >= month_start), ).options( joinedload(GEra.g_contract), joinedload(GEra.g_supply), joinedload(GEra.g_supply).joinedload( GSupply.g_exit_zone), ).order_by(GEra.id)): g_supply = g_era.g_supply if g_supply_id is not None and g_supply.id != g_supply_id: continue ss_start = hh_max(g_era.start_date, month_start) ss_finish = hh_min(g_era.finish_date, month_finish) ss = GDataSource( sess, ss_start, ss_finish, forecast_from, g_era, report_context, None, ) contract = g_era.g_contract vb_function = contract_func(report_context, contract, "virtual_bill") if vb_function is None: raise BadRequest( "The contract " + contract.name + " doesn't have the virtual_bill() function.") vb_function(ss) bill = ss.bill try: gbp = bill["net_gbp"] except KeyError: gbp = 0 bill["problem"] += ( "For the supply " + ss.mprn + " the virtual bill " + str(bill) + " from the contract " + contract.name + " does not contain the net_gbp key.") try: kwh = bill["kwh"] except KeyError: kwh = 0 bill["problem"] += ("For the supply " + ss.mprn + " the virtual bill " + str(bill) + " from the contract " + contract.name + " does not contain the 'kwh' key.") billed_kwh = billed_gbp = 0 g_era_associates = { s.site.code for s in g_era.site_g_eras if not s.is_physical } for g_bill in sess.query(GBill).filter( GBill.g_supply == g_supply, GBill.start_date <= ss_finish, GBill.finish_date >= ss_start, ): bill_start = g_bill.start_date bill_finish = g_bill.finish_date bill_duration = (bill_finish - bill_start ).total_seconds() + (30 * 60) overlap_duration = (min(bill_finish, ss_finish) - max( bill_start, ss_start)).total_seconds() + (30 * 60) overlap_proportion = overlap_duration / bill_duration billed_kwh += overlap_proportion * float(g_bill.kwh) billed_gbp += overlap_proportion * float(g_bill.net) associated_site_ids = ",".join(sorted(g_era_associates)) g_era_rows.append([ make_val(v) for v in [ now, g_supply.mprn, g_supply.name, g_supply.g_exit_zone.code, g_era.msn, g_era.g_unit.code, contract.name, site.code, site.name, associated_site_ids, month_finish, kwh, gbp, billed_kwh, billed_gbp, ] ] + [make_val(bill.get(t)) for t in vb_titles]) site_kwh += kwh site_gbp += gbp site_billed_kwh += billed_kwh site_billed_gbp += billed_gbp linked_sites = ", ".join(s.code for s in site.find_linked_sites( sess, month_start, month_finish)) site_rows.append([ make_val(v) for v in [ now, site.code, site.name, linked_sites, month_finish, site_kwh, site_gbp, site_billed_kwh, site_billed_gbp, ] ]) sess.rollback() write_spreadsheet(rf, compression, site_rows, g_era_rows) except BadRequest as e: site_rows.append(["Problem " + e.description]) write_spreadsheet(rf, compression, site_rows, g_era_rows) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg + "\n") site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, g_era_rows) finally: if sess is not None: sess.close() try: rf.close() os.rename(running_name, finished_name) except BaseException: msg = traceback.format_exc() r_name, f_name = chellow.dloads.make_names("error.txt", user) ef = open(r_name, "w") ef.write(msg + "\n") ef.close()
def content(end_year, end_month, months, site_id, sess): caches = {} try: finish_date = Datetime(end_year, end_month, 1, tzinfo=pytz.utc) + \ relativedelta(months=1) - HH start_date = Datetime(end_year, end_month, 1, tzinfo=pytz.utc) - \ relativedelta(months=months-1) forecast_date = chellow.computer.forecast_date() site = Site.get_by_id(sess, site_id) month_start = start_date month_finish = month_start + relativedelta(months=1) - HH while not month_finish > finish_date: for group in site.groups(sess, month_start, month_finish, True): if group.start_date > month_start: chunk_start = group.start_date else: chunk_start = month_start if group.finish_date > month_finish: chunk_finish = month_finish else: chunk_finish = group.finish_date displaced_era = chellow.computer.displaced_era( sess, group, chunk_start, chunk_finish) if displaced_era is None: continue supplier_contract = displaced_era.imp_supplier_contract linked_sites = ','.join( a_site.code for a_site in group.sites if not a_site == site) generator_types = ' '.join( sorted( [ supply.generator_type.code for supply in group.supplies if supply.generator_type is not None])) total_gen_breakdown = {} results = iter( sess.execute( "select supply.id, hh_datum.value, " "hh_datum.start_date, channel.imp_related, " "source.code, generator_type.code as gen_type_code " "from hh_datum, channel, source, era, supply left " "outer join generator_type on " "supply.generator_type_id = generator_type.id where " "hh_datum.channel_id = channel.id and " "channel.era_id = era.id and era.supply_id = " "supply.id and supply.source_id = source.id and " "channel.channel_type = 'ACTIVE' and not " "(source.code = 'net' and channel.imp_related is " "true) and hh_datum.start_date >= :chunk_start and " "hh_datum.start_date <= :chunk_finish and " "supply.id = any(:supply_ids) order by " "hh_datum.start_date, supply.id", params={ 'chunk_start': chunk_start, 'chunk_finish': chunk_finish, 'supply_ids': [s.id for s in group.supplies]})) try: res = next(results) hhChannelValue = res.value hhChannelStartDate = res.start_date imp_related = res.imp_related source_code = res.code gen_type = res.gen_type_code hh_date = chunk_start while hh_date <= finish_date: gen_breakdown = {} exported = 0 while hhChannelStartDate == hh_date: if not imp_related and source_code in ( 'net', 'gen-net'): exported += hhChannelValue if (imp_related and source_code == 'gen') or ( not imp_related and source_code == 'gen-net'): gen_breakdown[gen_type] = \ gen_breakdown.setdefault(gen_type, 0) + \ hhChannelValue if (not imp_related and source_code == 'gen') or \ (imp_related and source_code == 'gen-net'): gen_breakdown[gen_type] = \ gen_breakdown.setdefault(gen_type, 0) - \ hhChannelValue try: res = next(results) source_code = res.code hhChannelValue = res.value hhChannelStartDate = res.start_date imp_related = res.imp_related gen_type = res.gen_type_code except StopIteration: hhChannelStartDate = None displaced = sum(gen_breakdown.values()) - exported added_so_far = 0 for key in sorted(gen_breakdown.keys()): kwh = gen_breakdown[key] if kwh + added_so_far > displaced: total_gen_breakdown[key] = \ total_gen_breakdown.get(key, 0) + \ displaced - added_so_far break else: total_gen_breakdown[key] = \ total_gen_breakdown.get(key, 0) + kwh added_so_far += kwh hh_date += HH except StopIteration: pass site_ds = chellow.computer.SiteSource( sess, site, chunk_start, chunk_finish, forecast_date, None, caches, displaced_era) disp_func = chellow.computer.contract_func( caches, supplier_contract, 'displaced_virtual_bill', None) disp_func(site_ds) bill = site_ds.supplier_bill bill_titles = chellow.computer.contract_func( caches, supplier_contract, 'displaced_virtual_bill_titles', None)() yield ','.join( [ 'Site Code', 'Site Name', 'Associated Site Ids', 'From', 'To', 'Gen Types', 'CHP kWh', 'LM kWh', 'Turbine kWh', 'PV kWh'] + bill_titles) + '\n' yield ','.join('"' + str(value) + '"' for value in [ site.code, site.name, linked_sites, hh_format(chunk_start), hh_format(chunk_finish), generator_types] + [ total_gen_breakdown.get(t, '') for t in [ 'chp', 'lm', 'turb', 'pv']]) for title in bill_titles: if title in bill: v = bill[title] if isinstance(v, Datetime): val = hh_format(v) else: val = str(v) del bill[title] else: val = '' yield ',"' + val + '"' for k in sorted(bill.keys()): v = bill[k] if isinstance(v, Datetime): val = hh_format(v) else: val = str(v) yield ',"' + k + '","' + val + '"' yield '\n' month_start += relativedelta(months=1) month_finish = month_start + relativedelta(months=1) - HH except: yield traceback.format_exc()
def test_supply(mocker, sess, client): site = Site.insert(sess, "22488", "Water Works") g_dn = GDn.insert(sess, "EE", "East of England") g_ldz = g_dn.insert_g_ldz(sess, "EA") g_exit_zone = g_ldz.insert_g_exit_zone(sess, "EA1") insert_g_units(sess) g_unit_M3 = GUnit.get_by_code(sess, "M3") participant = Participant.insert(sess, "CALB", "AK Industries") market_role_Z = MarketRole.get_by_code(sess, "Z") participant.insert_party( sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None ) g_contract = GContract.insert( sess, "Fusion 2020", "", {}, utc_datetime(2000, 1, 1), None, {} ) insert_g_reading_frequencies(sess) g_reading_frequency_M = GReadingFrequency.get_by_code(sess, "M") msn = "hgeu8rhg" g_supply = site.insert_g_supply( sess, "87614362", "main", g_exit_zone, utc_datetime(2010, 1, 1), None, msn, 1, g_unit_M3, g_contract, "d7gthekrg", g_reading_frequency_M, ) sess.commit() mock_file = StringIO() mock_file.close = mocker.Mock() mocker.patch( "chellow.reports.report_g_supplies_snapshot.open", return_value=mock_file ) mocker.patch( "chellow.reports.report_g_supplies_snapshot.chellow.dloads.make_names", return_value=("a", "b"), ) mocker.patch("chellow.reports.report_g_supplies_snapshot.os.rename") user = mocker.Mock() g_supply_id = g_supply.id date = utc_datetime(2020, 9, 1) chellow.reports.report_g_supplies_snapshot.content(date, g_supply_id, user) mock_file.seek(0) sheet = csv.reader(mock_file) table = list(sheet) expected = [ [ "Date", "Physical Site Id", "Physical Site Name", "Other Site Ids", "Other Site Names", "MPRN", "Exit Zone", "Meter Serial Number", "Correction Factor", "Unit", "Contract", "Account", "Supply Start", "Supply Finish", ], [ "2020-09-01 01:00", "22488", "Water Works", "", "", "87614362", "EA1", "hgeu8rhg", "1", "M3", "Fusion 2020", "d7gthekrg", "2010-01-01 00:00", "", ], ] assert expected == table
def site_content(site_id, start_date, finish_date, user, file_name): sess = f = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( file_name, user) f = open(running_name, mode='w', newline='') writer = csv.writer(f, lineterminator='\n') site = Site.get_by_id(sess, site_id) sites = sess.query(Site).filter(Site.id == site_id) start_date_str = hh_format(start_date) finish_date_str = hh_format(finish_date) for site in sites: writer.writerow( [ "Site Code", "Site Name", "Associated Site Codes", "Sources", "Generator Types", "From", "To", "Type", "Date"] + list(map(str, range(1, 49)))) associates = ' '.join( s.code for s in site.find_linked_sites( sess, start_date, finish_date)) source_codes = set() gen_types = set() for supply in sess.query(Supply).join(Era).join(SiteEra).filter( SiteEra.is_physical == true(), SiteEra.site == site, Era.start_date <= finish_date, or_( Era.finish_date == null(), Era.finish_date >= start_date)).distinct().options( joinedload(Supply.source), joinedload(Supply.generator_type)): source_codes.add(supply.source.code) gen_type = supply.generator_type if gen_type is not None: gen_types.add(gen_type.code) source_codes_str = ', '.join(sorted(source_codes)) gen_types_str = ', '.join(sorted(gen_types)) vals = None for hh in site.hh_data(sess, start_date, finish_date): hh_start = hh['start_date'] if hh_start.hour == 0 and hh_start.minute == 0: if vals is not None: writer.writerow(vals) vals = [ site.code, site.name, associates, source_codes_str, gen_types_str, start_date_str, finish_date_str, 'used', hh_start.strftime('%Y-%m-%d')] used_gen_kwh = hh['imp_gen'] - hh['exp_net'] - hh['exp_gen'] used_3p_kwh = hh['imp_3p'] - hh['exp_3p'] used_kwh = hh['imp_net'] + used_gen_kwh + used_3p_kwh vals.append(str(round(used_kwh, 2))) if vals is not None: writer.writerow(vals) except: msg = traceback.format_exc() sys.stderr.write(msg) f.write(msg) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def test_batch(mocker, sess, client): site = Site.insert(sess, "22488", "Water Works") g_dn = GDn.insert(sess, "EE", "East of England") g_ldz = g_dn.insert_g_ldz(sess, "EA") g_exit_zone = g_ldz.insert_g_exit_zone(sess, "EA1") insert_g_units(sess) g_unit_M3 = GUnit.get_by_code(sess, "M3") participant = Participant.insert(sess, "CALB", "AK Industries") market_role_Z = MarketRole.get_by_code(sess, "Z") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) g_cv_rate_script = { "cvs": { "EA": { 1: { "applicable_at": utc_datetime(2020, 10, 3), "cv": 39.2000 }, } } } Contract.insert_non_core(sess, "g_cv", "", {}, utc_datetime(2000, 1, 1), None, g_cv_rate_script) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) charge_script = """ import chellow.g_ccl from chellow.g_engine import g_rates from chellow.utils import reduce_bill_hhs def virtual_bill_titles(): return [ 'units_consumed', 'correction_factor', 'unit_code', 'unit_factor', 'calorific_value', 'kwh', 'gas_rate', 'gas_gbp', 'ccl_rate', 'standing_rate', 'standing_gbp', 'net_gbp', 'vat_gbp', 'gross_gbp', 'problem'] def virtual_bill(ds): chellow.g_ccl.vb(ds) for hh in ds.hh_data: start_date = hh['start_date'] bill_hh = ds.bill_hhs[start_date] bill_hh['units_consumed'] = hh['units_consumed'] bill_hh['correction_factor'] = {hh['correction_factor']} bill_hh['unit_code'] = {hh['unit_code']} bill_hh['unit_factor'] = {hh['unit_factor']} bill_hh['calorific_value'] = {hh['calorific_value']} kwh = hh['kwh'] bill_hh['kwh'] = kwh gas_rate = float( g_rates(ds.sess, ds.caches, db_id, start_date)['gas_rate']) bill_hh['gas_rate'] = {gas_rate} bill_hh['gas_gbp'] = gas_rate * kwh bill_hh['ccl_kwh'] = kwh ccl_rate = hh['ccl'] bill_hh['ccl_rate'] = {ccl_rate} bill_hh['ccl_kwh'] = kwh bill_hh['ccl_gbp'] = kwh * ccl_rate if hh['utc_is_month_end']: standing_rate = float( g_rates( ds.sess, ds.caches, db_id, start_date)['standing_rate']) bill_hh['standing_rate'] = {standing_rate} bill_hh['standing_gbp'] = standing_rate if hh['utc_decimal_hour'] == 0: pass bill_hh['net_gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) bill_hh['vat_gbp'] = 0 bill_hh['gross_gbp'] = bill_hh['net_gbp'] + bill_hh['vat_gbp'] ds.bill = reduce_bill_hhs(ds.bill_hhs) """ g_contract_rate_script = { "gas_rate": 0.1, "standing_rate": 0.1, } g_contract = GContract.insert( sess, "Fusion 2020", charge_script, {}, utc_datetime(2000, 1, 1), None, g_contract_rate_script, ) insert_g_reading_frequencies(sess) g_reading_frequency_M = GReadingFrequency.get_by_code(sess, "M") g_supply = site.insert_g_supply( sess, "87614362", "main", g_exit_zone, utc_datetime(2018, 1, 1), None, "hgeu8rhg", 1, g_unit_M3, g_contract, "d7gthekrg", g_reading_frequency_M, ) g_batch = g_contract.insert_g_batch(sess, "b1", "Jan batch") breakdown = {"units_consumed": 771} insert_bill_types(sess) bill_type_n = BillType.get_by_code(sess, "N") g_bill = g_batch.insert_g_bill( sess, g_supply, bill_type_n, "55h883", "dhgh883", utc_datetime(2019, 4, 3), utc_datetime(2020, 1, 1), utc_datetime(2020, 1, 31, 23, 30), Decimal("45"), Decimal("12.40"), Decimal("1.20"), Decimal("14.52"), "", breakdown, ) sess.commit() mock_file = StringIO() mock_file.close = mocker.Mock() mocker.patch("chellow.reports.report_429.open", return_value=mock_file) mocker.patch("chellow.reports.report_429.chellow.dloads.make_names", return_value=("a", "b")) mocker.patch("chellow.reports.report_429.os.rename") user = mocker.Mock() chellow.reports.report_429.content(g_batch.id, g_bill.id, user) actual = mock_file.getvalue() expected = [ "batch,bill_reference,bill_type,bill_start_date,bill_finish_date," "mprn,supply_name,site_code,site_name,covered_start,covered_finish," "covered_bill_ids,covered_units_consumed,virtual_units_consumed," "covered_correction_factor,virtual_correction_factor," "covered_unit_code,virtual_unit_code,covered_unit_factor," "virtual_unit_factor,covered_calorific_value,virtual_calorific_value," "covered_kwh,virtual_kwh,covered_gas_rate,virtual_gas_rate," "covered_gas_gbp,virtual_gas_gbp,difference_gas_gbp,covered_ccl_rate," "virtual_ccl_rate,covered_standing_rate,virtual_standing_rate," "covered_standing_gbp,virtual_standing_gbp,difference_standing_gbp," "covered_net_gbp,virtual_net_gbp,difference_net_gbp,covered_vat_gbp," "virtual_vat_gbp,difference_vat_gbp,covered_gross_gbp," "virtual_gross_gbp,difference_gross_gbp,covered_problem," "virtual_problem", "b1,55h883,N,2020-01-01 00:00,2020-01-31 23:30,87614362,main,22488," "Water Works,2020-01-01 00:00,2020-01-31 23:30,1,771,0,,1.0,,M3,,1.0" ",,39.2,45,0.0,,0.1,,0.0,,,0.00339,,0.1,,0.1,,12.40,0.1,12.3,1.20,0," "1.2,14.52,0.1,14.42,,", ] expected_str = "\r\n".join(expected) + "\r\n" assert actual == expected_str
def content(year, site_id, user): caches = {} sess = f = writer = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( 'output.csv', user) f = open(running_name, mode='w', newline='') writer = csv.writer(f, lineterminator='\n') writer.writerow(("Site Code", "Site Name", "Displaced TRIAD 1 Date", "Displaced TRIAD 1 MSP kW", "Displaced TRIAD LAF", "Displaced TRIAD 1 GSP kW", "Displaced TRIAD 2 Date", "Displaced TRIAD 2 MSP kW", "Displaced TRIAD 2 LAF", "Displaced TRIAD 2 GSP kW", "Displaced TRIAD 3 Date", "Displaced TRIAD 3 MSP kW", "Displaced TRIAD 3 LAF", "Displaced TRIAD 3 GSP kW", "Displaced GSP kW", "Displaced Rate GBP / kW", "GBP")) march_finish = datetime.datetime(year, 4, 1, tzinfo=pytz.utc) - HH march_start = datetime.datetime(year, 3, 1, tzinfo=pytz.utc) forecast_date = chellow.computer.forecast_date() if site_id is None: sites = sess.query(Site).join(SiteEra).join(Era).join(Supply).join( Source).filter( Source.code.in_(('gen', 'gen-net')), Era.start_date <= march_finish, or_(Era.finish_date == null(), Era.finish_date >= march_start)).distinct() else: site = Site.get_by_id(sess, site_id) sites = sess.query(Site).filter(Site.id == site.id) for site in sites.order_by(Site.code): displaced_era = chellow.computer.displaced_era( sess, caches, site, march_start, march_finish, forecast_date) if displaced_era is None: continue site_ds = chellow.computer.SiteSource(sess, site, march_start, march_finish, forecast_date, caches, displaced_era) chellow.duos.duos_vb(site_ds) chellow.triad.hh(site_ds) chellow.triad.bill(site_ds) bill = site_ds.supplier_bill for rname, rset in site_ds.supplier_rate_sets.items(): if len(rset) == 1: bill[rname] = rset.pop() values = [site.code, site.name] for i in range(1, 4): triad_prefix = 'triad-actual-' + str(i) values.append(hh_format(bill[triad_prefix + '-date'])) for suffix in ['-msp-kw', '-laf', '-gsp-kw']: values.append(bill[triad_prefix + suffix]) values += [ str(bill['triad-actual-' + suf]) for suf in ['gsp-kw', 'rate', 'gbp'] ] writer.writerow(values) # Avoid long-running transaction sess.rollback() except BadRequest as e: writer.writerow([e.description]) except BaseException: writer.writerow([traceback.format_exc()]) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def site_content(site_id, start_date, finish_date, user, file_name): sess = f = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( file_name, user) f = open(running_name, mode="w", newline="") writer = csv.writer(f, lineterminator="\n") site = Site.get_by_id(sess, site_id) sites = sess.query(Site).filter(Site.id == site_id) start_date_str = hh_format(start_date) finish_date_str = hh_format(finish_date) for site in sites: writer.writerow([ "Site Code", "Site Name", "Associated Site Codes", "Sources", "Generator Types", "From", "To", "Type", "Date", ] + list(map(str, range(1, 51)))) associates = " ".join( s.code for s in site.find_linked_sites(sess, start_date, finish_date)) source_codes = set() gen_types = set() for supply in (sess.query(Supply).join(Era).join(SiteEra).filter( SiteEra.is_physical == true(), SiteEra.site == site, Era.start_date <= finish_date, or_(Era.finish_date == null(), Era.finish_date >= start_date), ).distinct().options(joinedload(Supply.source), joinedload(Supply.generator_type))): source_codes.add(supply.source.code) gen_type = supply.generator_type if gen_type is not None: gen_types.add(gen_type.code) source_codes_str = ", ".join(sorted(source_codes)) gen_types_str = ", ".join(sorted(gen_types)) vals = None for hh in site.hh_data(sess, start_date, finish_date): hh_start_ct = to_ct(hh["start_date"]) if hh_start_ct.hour == 0 and hh_start_ct.minute == 0: if vals is not None: writer.writerow(vals) vals = [ site.code, site.name, associates, source_codes_str, gen_types_str, start_date_str, finish_date_str, "used", hh_start_ct.strftime("%Y-%m-%d"), ] used_gen_kwh = hh["imp_gen"] - hh["exp_net"] - hh["exp_gen"] used_3p_kwh = hh["imp_3p"] - hh["exp_3p"] used_kwh = hh["imp_net"] + used_gen_kwh + used_3p_kwh vals.append(str(round(used_kwh, 2))) if vals is not None: writer.writerow(vals) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg) f.write(msg) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def test_supply(mocker, sess, client): site = Site.insert(sess, "22488", "Water Works") g_dn = GDn.insert(sess, "EE", "East of England") g_ldz = g_dn.insert_g_ldz(sess, "EA") g_exit_zone = g_ldz.insert_g_exit_zone(sess, "EA1") insert_g_units(sess) g_unit_M3 = GUnit.get_by_code(sess, "M3") participant = Participant.insert(sess, "CALB", "AK Industries") market_role_Z = MarketRole.get_by_code(sess, "Z") participant.insert_party( sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None ) g_cv_rate_script = { "cvs": { "EA": { 1: {"applicable_at": utc_datetime(2020, 10, 3), "cv": 39.2000}, } } } Contract.insert_non_core( sess, "g_cv", "", {}, utc_datetime(2000, 1, 1), None, g_cv_rate_script ) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) charge_script = """ import chellow.g_ccl from chellow.g_engine import g_rates from chellow.utils import reduce_bill_hhs def virtual_bill_titles(): return [ 'units_consumed', 'correction_factor', 'unit_code', 'unit_factor', 'calorific_value', 'kwh', 'gas_rate', 'gas_gbp', 'ccl_rate', 'standing_rate', 'standing_gbp', 'net_gbp', 'vat_gbp', 'gross_gbp', 'problem'] def virtual_bill(ds): chellow.g_ccl.vb(ds) for hh in ds.hh_data: start_date = hh['start_date'] bill_hh = ds.bill_hhs[start_date] bill_hh['units_consumed'] = hh['units_consumed'] bill_hh['correction_factor'] = {hh['correction_factor']} bill_hh['unit_code'] = {hh['unit_code']} bill_hh['unit_factor'] = {hh['unit_factor']} bill_hh['calorific_value'] = {hh['calorific_value']} kwh = hh['kwh'] bill_hh['kwh'] = kwh gas_rate = float( g_rates(ds.sess, ds.caches, db_id, start_date)['gas_rate']) bill_hh['gas_rate'] = {gas_rate} bill_hh['gas_gbp'] = gas_rate * kwh bill_hh['ccl_kwh'] = kwh ccl_rate = hh['ccl'] bill_hh['ccl_rate'] = {ccl_rate} bill_hh['ccl_kwh'] = kwh bill_hh['ccl_gbp'] = kwh * ccl_rate if hh['utc_is_month_end']: standing_rate = float( g_rates( ds.sess, ds.caches, db_id, start_date)['standing_rate']) bill_hh['standing_rate'] = {standing_rate} bill_hh['standing_gbp'] = standing_rate if hh['utc_decimal_hour'] == 0: pass bill_hh['net_gbp'] = sum( v for k, v in bill_hh.items() if k.endswith('gbp')) bill_hh['vat_gbp'] = 0 bill_hh['gross_gbp'] = bill_hh['net_gbp'] + bill_hh['vat_gbp'] ds.bill = reduce_bill_hhs(ds.bill_hhs) """ g_contract_rate_script = { "gas_rate": 0.1, "standing_rate": 0.1, } g_contract = GContract.insert( sess, "Fusion 2020", charge_script, {}, utc_datetime(2000, 1, 1), None, g_contract_rate_script, ) insert_g_reading_frequencies(sess) g_reading_frequency_M = GReadingFrequency.get_by_code(sess, "M") msn = "hgeu8rhg" g_supply = site.insert_g_supply( sess, "87614362", "main", g_exit_zone, utc_datetime(2010, 1, 1), None, msn, 1, g_unit_M3, g_contract, "d7gthekrg", g_reading_frequency_M, ) g_batch = g_contract.insert_g_batch(sess, "b1", "Jan batch") breakdown = {"units_consumed": 771} insert_bill_types(sess) bill_type_N = BillType.get_by_code(sess, "N") insert_g_read_types(sess) g_read_type_A = GReadType.get_by_code(sess, "A") g_bill = g_batch.insert_g_bill( sess, g_supply, bill_type_N, "55h883", "dhgh883", utc_datetime(2019, 4, 3), utc_datetime(2015, 9, 1), utc_datetime(2015, 9, 30, 22, 30), Decimal("45"), Decimal("12.40"), Decimal("1.20"), Decimal("14.52"), "", breakdown, ) g_bill.insert_g_read( sess, msn, g_unit_M3, Decimal("1"), Decimal("37"), Decimal("90"), utc_datetime(2015, 9, 1), g_read_type_A, Decimal("890"), utc_datetime(2015, 9, 25), g_read_type_A, ) sess.commit() mock_file = StringIO() mock_file.close = mocker.Mock() mocker.patch( "chellow.reports.report_g_virtual_bills_hh.open", return_value=mock_file ) mocker.patch( "chellow.reports.report_g_virtual_bills_hh.chellow.dloads.make_names", return_value=("a", "b"), ) mocker.patch("chellow.reports.report_g_virtual_bills.os.rename") user = mocker.Mock() g_supply_id = g_supply.id start_date = to_utc(ct_datetime(2018, 2, 1)) finish_date = to_utc(ct_datetime(2018, 2, 1, 0, 30)) chellow.reports.report_g_virtual_bills_hh.content( g_supply_id, start_date, finish_date, user ) mock_file.seek(0) table = list(csv.reader(mock_file)) expected = [ [ "MPRN", "Site Code", "Site Name", "Account", "HH Start", "", "", "units_consumed", "correction_factor", "unit_code", "unit_factor", "calorific_value", "kwh", "gas_rate", "gas_gbp", "ccl_rate", "standing_rate", "standing_gbp", "net_gbp", "vat_gbp", "gross_gbp", "problem", ], [ "87614362", "22488", "Water Works", "d7gthekrg", "2018-02-01 00:00", "", "", "0.6944444444444444", "1.0", "M3", "1.0", "39.2", "7.561728395061729", "0.1", "0.7561728395061729", "0.00198", "", "", "0.7711450617283951", "0", "0.7711450617283951", "", "ccl_gbp", "0.014972222222222222", "ccl_kwh", "7.561728395061729", ], [ "87614362", "22488", "Water Works", "d7gthekrg", "2018-02-01 00:30", "", "", "0.6944444444444444", "1.0", "M3", "1.0", "39.2", "7.561728395061729", "0.1", "0.7561728395061729", "0.00198", "", "", "0.7711450617283951", "0", "0.7711450617283951", "", "ccl_gbp", "0.014972222222222222", "ccl_kwh", "7.561728395061729", ], ] match_tables(table, expected)
def test_get_era_bundles_bill_after_supply_end(sess, client): """Check that a bill starting after the end of a supply still gets shown. """ site = Site.insert(sess, "22488", "Water Works") insert_sources(sess) source = Source.get_by_code(sess, "net") gsp_group = GspGroup.insert(sess, "_L", "South Western") participant = Participant.insert(sess, "hhak", "AK Industries") market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_hhdc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "00", "hh", utc_datetime(2000, 1, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") imp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "E") supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2020, 1, 1), utc_datetime(2020, 1, 31), gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, None, energisation_status, {}, "22 7867 6232 781", "510", imp_supplier_contract, "7748", 361, None, None, None, None, None, ) batch = imp_supplier_contract.insert_batch(sess, "b1", "batch 1") insert_bill_types(sess) bill_type_N = BillType.get_by_code(sess, "N") batch.insert_bill( sess, "ytgeklf", "s77349", utc_datetime(2020, 2, 10), utc_datetime(2020, 2, 2), utc_datetime(2020, 3, 1), Decimal(0), Decimal("0.00"), Decimal("0.00"), Decimal("0.00"), bill_type_N, {}, supply, ) sess.commit() bundles = get_era_bundles(sess, supply) assert len(bundles[0]["imp_bills"]["bill_dicts"]) == 1
def content(scenario_props, scenario_id, base_name, site_id, supply_id, user): now = Datetime.now(pytz.utc) report_context = {} future_funcs = {} report_context['future_funcs'] = future_funcs sess = None try: sess = Session() if scenario_props is None: scenario_contract = Contract.get_supplier_by_id(sess, scenario_id) scenario_props = scenario_contract.make_properties() base_name.append(scenario_contract.name) for contract in sess.query(Contract).join(MarketRole).filter( MarketRole.code == 'Z'): try: props = scenario_props[contract.name] except KeyError: continue try: rate_start = props['start_date'] except KeyError: raise BadRequest( "In " + scenario_contract.name + " for the rate " + contract.name + " the start_date is missing.") if rate_start is not None: rate_start = rate_start.replace(tzinfo=pytz.utc) lib = importlib.import_module('chellow.' + contract.name) if hasattr(lib, 'create_future_func'): future_funcs[contract.id] = { 'start_date': rate_start, 'func': lib.create_future_func( props['multiplier'], props['constant'])} start_date = scenario_props['scenario_start'] if start_date is None: start_date = Datetime( now.year, now.month, 1, tzinfo=pytz.utc) else: start_date = start_date.replace(tzinfo=pytz.utc) base_name.append( hh_format(start_date).replace(' ', '_').replace(':', ''). replace('-', '')) months = scenario_props['scenario_duration'] base_name.append('for') base_name.append(str(months)) base_name.append('months') finish_date = start_date + relativedelta(months=months) if 'kwh_start' in scenario_props: kwh_start = scenario_props['kwh_start'] else: kwh_start = None if kwh_start is None: kwh_start = chellow.computer.forecast_date() else: kwh_start = kwh_start.replace(tzinfo=pytz.utc) sites = sess.query(Site).join(SiteEra).join(Era).filter( Era.start_date <= finish_date, or_( Era.finish_date == null(), Era.finish_date >= start_date)).distinct().order_by(Site.code) if site_id is not None: site = Site.get_by_id(sess, site_id) sites = sites.filter(Site.id == site.id) base_name.append('site') base_name.append(site.code) if supply_id is not None: supply = Supply.get_by_id(sess, supply_id) base_name.append('supply') base_name.append(str(supply.id)) sites = sites.filter(Era.supply == supply) running_name, finished_name = chellow.dloads.make_names( '_'.join(base_name) + '.ods', user) rf = open(running_name, "wb") f = odswriter.writer(rf, '1.1') group_tab = f.new_sheet("Site Level") sup_tab = f.new_sheet("Supply Level") changes = defaultdict(list, {}) try: kw_changes = scenario_props['kw_changes'] except KeyError: kw_changes = '' for row in csv.reader(io.StringIO(kw_changes)): if len(''.join(row).strip()) == 0: continue if len(row) != 4: raise BadRequest( "Can't interpret the row " + str(row) + " it should be of " "the form SITE_CODE, USED / GENERATED, DATE, MULTIPLIER") site_code, typ, date_str, kw_str = row date = Datetime.strptime(date_str.strip(), "%Y-%m-%d").replace( tzinfo=pytz.utc) changes[site_code.strip()].append( { 'type': typ.strip(), 'date': date, 'multiplier': float(kw_str)}) sup_header_titles = [ 'imp-mpan-core', 'exp-mpan-core', 'metering-type', 'source', 'generator-type', 'supply-name', 'msn', 'pc', 'site-id', 'site-name', 'associated-site-ids', 'month'] site_header_titles = [ 'site-id', 'site-name', 'associated-site-ids', 'month', 'metering-type', 'sources', 'generator-types'] summary_titles = [ 'import-net-kwh', 'export-net-kwh', 'import-gen-kwh', 'export-gen-kwh', 'import-3rd-party-kwh', 'export-3rd-party-kwh', 'displaced-kwh', 'used-kwh', 'used-3rd-party-kwh', 'import-net-gbp', 'export-net-gbp', 'import-gen-gbp', 'export-gen-gbp', 'import-3rd-party-gbp', 'export-3rd-party-gbp', 'displaced-gbp', 'used-gbp', 'used-3rd-party-gbp', 'billed-import-net-kwh', 'billed-import-net-gbp'] title_dict = {} for cont_type, con_attr in ( ('mop', Era.mop_contract), ('dc', Era.hhdc_contract), ('imp-supplier', Era.imp_supplier_contract), ('exp-supplier', Era.exp_supplier_contract)): titles = [] title_dict[cont_type] = titles conts = sess.query(Contract).join(con_attr) \ .join(Era.supply).join(Source).filter( Era.start_date <= start_date, or_( Era.finish_date == null(), Era.finish_date >= start_date), Source.code.in_(('net', '3rd-party')) ).distinct().order_by(Contract.id) if supply_id is not None: conts = conts.filter(Era.supply_id == supply_id) for cont in conts: title_func = chellow.computer.contract_func( report_context, cont, 'virtual_bill_titles', None) if title_func is None: raise Exception( "For the contract " + cont.name + " there doesn't seem to be a " "'virtual_bill_titles' function.") for title in title_func(): if title not in titles: titles.append(title) sup_tab.writerow( sup_header_titles + summary_titles + [None] + ['mop-' + t for t in title_dict['mop']] + [None] + ['dc-' + t for t in title_dict['dc']] + [None] + ['imp-supplier-' + t for t in title_dict['imp-supplier']] + [None] + ['exp-supplier-' + t for t in title_dict['exp-supplier']]) group_tab.writerow(site_header_titles + summary_titles) sites = sites.all() month_start = start_date while month_start < finish_date: month_finish = month_start + relativedelta(months=1) - HH for site in sites: site_changes = changes[site.code] site_associates = set() site_category = None site_sources = set() site_gen_types = set() site_month_data = defaultdict(int) for group in site.groups( sess, month_start, month_finish, False): site_associates.update( set( s.code for s in group.sites if s.code != site.code)) for cand_supply in group.supplies: site_sources.add(cand_supply.source.code) if cand_supply.generator_type is not None: site_gen_types.add(cand_supply.generator_type.code) for cand_era in sess.query(Era).filter( Era.supply == cand_supply, Era.start_date <= group.finish_date, or_( Era.finish_date == null(), Era.finish_date >= group.start_date)). \ options( joinedload(Era.channels), joinedload(Era.pc), joinedload(Era.mtc).joinedload( Mtc.meter_type)): if site_category != 'hh': if cand_era.pc.code == '00': site_category = 'hh' elif site_category != 'amr': if len(cand_era.channels) > 0: site_category = 'amr' elif site_category != 'nhh': if cand_era.mtc.meter_type.code \ not in ['UM', 'PH']: site_category = 'nhh' else: site_category = 'unmetered' for group in site.groups( sess, month_start, month_finish, True): calcs = [] deltas = defaultdict(int) group_associates = set( s.code for s in group.sites if s.code != site.code) for supply in group.supplies: if supply_id is not None and supply.id != supply_id: continue for era in sess.query(Era).join(Supply) \ .join(Source).filter( Era.supply == supply, Era.start_date <= group.finish_date, or_( Era.finish_date == null(), Era.finish_date >= group.start_date)) \ .options( joinedload(Era.ssc), joinedload(Era.hhdc_contract), joinedload(Era.mop_contract), joinedload(Era.imp_supplier_contract), joinedload(Era.exp_supplier_contract), joinedload(Era.channels), joinedload(Era.imp_llfc).joinedload( Llfc.voltage_level), joinedload(Era.exp_llfc).joinedload( Llfc.voltage_level), joinedload(Era.cop), joinedload(Era.supply).joinedload( Supply.dno_contract), joinedload(Era.mtc).joinedload( Mtc.meter_type)): if era.start_date > group.start_date: ss_start = era.start_date else: ss_start = group.start_date if hh_before(era.finish_date, group.finish_date): ss_finish = era.finish_date else: ss_finish = group.finish_date if era.imp_mpan_core is None: imp_ss = None else: imp_ss = SupplySource( sess, ss_start, ss_finish, kwh_start, era, True, None, report_context) if era.exp_mpan_core is None: exp_ss = None measurement_type = imp_ss.measurement_type else: exp_ss = SupplySource( sess, ss_start, ss_finish, kwh_start, era, False, None, report_context) measurement_type = exp_ss.measurement_type order = meter_order[measurement_type] calcs.append( ( order, era.imp_mpan_core, era.exp_mpan_core, imp_ss, exp_ss)) if imp_ss is not None and len(era.channels) == 0: for hh in imp_ss.hh_data: deltas[hh['start-date']] += hh['msp-kwh'] imp_net_delts = defaultdict(int) exp_net_delts = defaultdict(int) imp_gen_delts = defaultdict(int) displaced_era = chellow.computer.displaced_era( sess, group, group.start_date, group.finish_date) site_ds = chellow.computer.SiteSource( sess, site, group.start_date, group.finish_date, kwh_start, None, report_context, displaced_era) for hh in site_ds.hh_data: try: delta = deltas[hh['start-date']] hh['import-net-kwh'] += delta hh['used-kwh'] += delta except KeyError: pass for hh in site_ds.hh_data: for change in site_changes: if change['type'] == 'used' and \ change['date'] <= hh['start-date']: used = change['multiplier'] * hh['used-kwh'] exp_net = max( 0, hh['import-gen-kwh'] - hh['export-gen-kwh'] - used) exp_net_delt = exp_net - hh['export-net-kwh'] exp_net_delts[hh['start-date']] += exp_net_delt displaced = hh['import-gen-kwh'] - \ hh['export-gen-kwh'] - exp_net imp_net = used - displaced imp_delt = imp_net - hh['import-net-kwh'] imp_net_delts[hh['start-date']] += imp_delt hh['import-net-kwh'] = imp_net hh['used-kwh'] = used hh['export-net-kwh'] = exp_net hh['msp-kwh'] = displaced elif change['type'] == 'generated' and \ change['date'] <= hh['start-date']: imp_gen = change['multiplier'] * \ hh['import-gen-kwh'] imp_gen_delt = imp_gen - hh['import-gen-kwh'] exp_net = max( 0, imp_gen - hh['export-gen-kwh'] - hh['used-kwh']) exp_net_delt = exp_net - hh['export-net-kwh'] exp_net_delts[hh['start-date']] += exp_net_delt displaced = imp_gen - hh['export-gen-kwh'] - \ exp_net imp_net = hh['used-kwh'] - displaced imp_net_delt = imp_net - hh['import-net-kwh'] imp_net_delts[hh['start-date']] += imp_net_delt imp_gen_delts[hh['start-date']] += imp_gen_delt hh['import-net-kwh'] = imp_net hh['export-net-kwh'] = exp_net hh['import-gen-kwh'] = imp_gen hh['msp-kwh'] = displaced if displaced_era is not None and supply_id is None: month_data = {} for sname in ( 'import-net', 'export-net', 'import-gen', 'export-gen', 'import-3rd-party', 'export-3rd-party', 'msp', 'used', 'used-3rd-party', 'billed-import-net'): for xname in ('kwh', 'gbp'): month_data[sname + '-' + xname] = 0 month_data['used-kwh'] = \ month_data['displaced-kwh'] = \ sum(hh['msp-kwh'] for hh in site_ds.hh_data) disp_supplier_contract = \ displaced_era.imp_supplier_contract disp_vb_function = chellow.computer.contract_func( report_context, disp_supplier_contract, 'displaced_virtual_bill', None) if disp_vb_function is None: raise BadRequest( "The supplier contract " + disp_supplier_contract.name + " doesn't have the displaced_virtual_bill() " "function.") disp_vb_function(site_ds) disp_supplier_bill = site_ds.supplier_bill try: gbp = disp_supplier_bill['net-gbp'] except KeyError: disp_supplier_bill['problem'] += \ 'For the supply ' + \ site_ds.mpan_core + \ ' the virtual bill ' + \ str(disp_supplier_bill) + \ ' from the contract ' + \ disp_supplier_contract.name + \ ' does not contain the net-gbp key.' month_data['used-gbp'] = \ month_data['displaced-gbp'] = \ site_ds.supplier_bill['net-gbp'] out = [ None, None, displaced_era.make_meter_category(), 'displaced', None, None, None, None, site.code, site.name, ','.join(sorted(list(group_associates))), month_finish] + \ [month_data[t] for t in summary_titles] sup_tab.writerow(out) for k, v in month_data.items(): site_month_data[k] += v for i, ( order, imp_mpan_core, exp_mpan_core, imp_ss, exp_ss) in enumerate(sorted(calcs, key=str)): if imp_ss is None: era = exp_ss.era else: era = imp_ss.era supply = era.supply source = supply.source source_code = source.code site_sources.add(source_code) month_data = {} for name in ( 'import-net', 'export-net', 'import-gen', 'export-gen', 'import-3rd-party', 'export-3rd-party', 'displaced', 'used', 'used-3rd-party', 'billed-import-net'): for sname in ('kwh', 'gbp'): month_data[name + '-' + sname] = 0 if source_code == 'net': delts = imp_net_delts elif source_code == 'gen': delts = imp_gen_delts else: delts = [] if len(delts) > 0 and imp_ss is not None: for hh in imp_ss.hh_data: diff = hh['msp-kwh'] + delts[hh['start-date']] if diff < 0: hh['msp-kwh'] = 0 hh['msp-kw'] = 0 delts[hh['start-date']] -= hh['msp-kwh'] else: hh['msp-kwh'] += delts[hh['start-date']] hh['msp-kw'] += hh['msp-kwh'] / 2 del delts[hh['start-date']] left_kwh = sum(delts.values()) if left_kwh > 0: first_hh = imp_ss.hh_data[0] first_hh['msp-kwh'] += left_kwh first_hh['msp-kw'] += left_kwh / 2 imp_supplier_contract = era.imp_supplier_contract if imp_supplier_contract is not None: import_vb_function = contract_func( report_context, imp_supplier_contract, 'virtual_bill', None) if import_vb_function is None: raise BadRequest( "The supplier contract " + imp_supplier_contract.name + " doesn't have the virtual_bill() " "function.") import_vb_function(imp_ss) imp_supplier_bill = imp_ss.supplier_bill try: gbp = imp_supplier_bill['net-gbp'] except KeyError: imp_supplier_bill['problem'] += \ 'For the supply ' + \ imp_ss.mpan_core + \ ' the virtual bill ' + \ str(imp_supplier_bill) + \ ' from the contract ' + \ imp_supplier_contract.name + \ ' does not contain the net-gbp key.' if source_code in ('net', 'gen-net'): month_data['import-net-gbp'] += gbp month_data['used-gbp'] += gbp elif source_code == '3rd-party': month_data['import-3rd-party-gbp'] += gbp month_data['used-gbp'] += gbp elif source_code == '3rd-party-reverse': month_data['export-3rd-party-gbp'] += gbp month_data['used-gbp'] -= gbp kwh = sum( hh['msp-kwh'] for hh in imp_ss.hh_data) if source_code in ('net', 'gen-net'): month_data['import-net-kwh'] += kwh month_data['used-kwh'] += kwh elif source_code == '3rd-party': month_data['import-3rd-party-kwh'] += kwh month_data['used-kwh'] += kwh elif source_code == '3rd-party-reverse': month_data['export-3rd-party-kwh'] += kwh month_data['used-kwh'] -= kwh elif source_code in ('gen', 'gen-net'): month_data['import-gen-kwh'] += kwh exp_supplier_contract = era.exp_supplier_contract if exp_supplier_contract is None: kwh = sess.query( func.coalesce( func.sum( cast(HhDatum.value, Float)), 0)). \ join(Channel).filter( Channel.era == era, Channel.channel_type == 'ACTIVE', Channel.imp_related == false()).scalar() if source_code == 'gen': month_data['export-net-kwh'] += kwh else: export_vb_function = contract_func( report_context, exp_supplier_contract, 'virtual_bill', None) export_vb_function(exp_ss) exp_supplier_bill = exp_ss.supplier_bill try: gbp = exp_supplier_bill['net-gbp'] except KeyError: exp_supplier_bill['problem'] += \ 'For the supply ' + \ imp_ss.mpan_core + \ ' the virtual bill ' + \ str(imp_supplier_bill) + \ ' from the contract ' + \ imp_supplier_contract.name + \ ' does not contain the net-gbp key.' kwh = sum(hh['msp-kwh'] for hh in exp_ss.hh_data) if source_code in ('net', 'gen-net'): month_data['export-net-kwh'] += kwh month_data['export-net-gbp'] += gbp elif source_code in \ ('3rd-party', '3rd-party-reverse'): month_data['export-3rd-party-kwh'] += kwh month_data['export-3rd-party-gbp'] += gbp month_data['used-kwh'] -= kwh month_data['used-gbp'] -= gbp elif source_code == 'gen': month_data['export-gen-kwh'] += kwh sss = exp_ss if imp_ss is None else imp_ss dc_contract = era.hhdc_contract sss.contract_func( dc_contract, 'virtual_bill')(sss) dc_bill = sss.dc_bill gbp = dc_bill['net-gbp'] mop_contract = era.mop_contract mop_bill_function = sss.contract_func( mop_contract, 'virtual_bill') mop_bill_function(sss) mop_bill = sss.mop_bill gbp += mop_bill['net-gbp'] if source_code in ('3rd-party', '3rd-party-reverse'): month_data['import-3rd-party-gbp'] += gbp else: month_data['import-net-gbp'] += gbp month_data['used-gbp'] += gbp if source_code in ('gen', 'gen-net'): generator_type = supply.generator_type.code site_gen_types.add(generator_type) else: generator_type = None sup_category = era.make_meter_category() if CATEGORY_ORDER[site_category] < \ CATEGORY_ORDER[sup_category]: site_category = sup_category for bill in sess.query(Bill).filter( Bill.supply == supply, Bill.start_date <= sss.finish_date, Bill.finish_date >= sss.start_date): bill_start = bill.start_date bill_finish = bill.finish_date bill_duration = ( bill_finish - bill_start).total_seconds() + \ (30 * 60) overlap_duration = ( min(bill_finish, sss.finish_date) - max(bill_start, sss.start_date) ).total_seconds() + (30 * 60) overlap_proportion = \ float(overlap_duration) / bill_duration month_data['billed-import-net-kwh'] += \ overlap_proportion * float(bill.kwh) month_data['billed-import-net-gbp'] += \ overlap_proportion * float(bill.net) out = [ era.imp_mpan_core, era.exp_mpan_core, sup_category, source_code, generator_type, supply.name, era.msn, era.pc.code, site.code, site.name, ','.join(sorted(list(site_associates))), month_finish] + [ month_data[t] for t in summary_titles] + [None] + [ (mop_bill[t] if t in mop_bill else None) for t in title_dict['mop']] + [None] + \ [(dc_bill[t] if t in dc_bill else None) for t in title_dict['dc']] if imp_supplier_contract is None: out += [None] * \ (len(title_dict['imp-supplier']) + 1) else: out += [None] + [ ( imp_supplier_bill[t] if t in imp_supplier_bill else None) for t in title_dict['imp-supplier']] if exp_supplier_contract is not None: out += [None] + [ ( exp_supplier_bill[t] if t in exp_supplier_bill else None) for t in title_dict['exp-supplier']] for k, v in month_data.items(): site_month_data[k] += v sup_tab.writerow(out) group_tab.writerow( [ site.code, site.name, ''.join(sorted(list(site_associates))), month_finish, site_category, ', '.join(sorted(list(site_sources))), ', '.join(sorted(list(site_gen_types)))] + [site_month_data[k] for k in summary_titles]) sess.rollback() month_start += relativedelta(months=1) except BadRequest as e: msg = e.description + traceback.format_exc() sys.stderr.write(msg + '\n') group_tab.writerow(["Problem " + msg]) except: msg = traceback.format_exc() sys.stderr.write(msg + '\n') group_tab.writerow(["Problem " + msg]) finally: if sess is not None: sess.close() try: f.close() rf.close() os.rename(running_name, finished_name) except: msg = traceback.format_exc() r_name, f_name = chellow.dloads.make_names('error.txt', user) ef = open(r_name, "w") ef.write(msg + '\n') ef.close()
def content(year, site_id, user): caches = {} sess = f = writer = None try: sess = Session() running_name, finished_name = chellow.dloads.make_names( 'output.csv', user) f = open(running_name, mode='w', newline='') writer = csv.writer(f, lineterminator='\n') writer.writerow( ( "Site Code", "Site Name", "Displaced TRIAD 1 Date", "Displaced TRIAD 1 MSP kW", "Displaced TRIAD LAF", "Displaced TRIAD 1 GSP kW", "Displaced TRIAD 2 Date", "Displaced TRIAD 2 MSP kW", "Displaced TRIAD 2 LAF", "Displaced TRIAD 2 GSP kW", "Displaced TRIAD 3 Date", "Displaced TRIAD 3 MSP kW", "Displaced TRIAD 3 LAF", "Displaced TRIAD 3 GSP kW", "Displaced GSP kW", "Displaced Rate GBP / kW", "GBP")) march_finish = datetime.datetime(year, 4, 1, tzinfo=pytz.utc) - HH march_start = datetime.datetime(year, 3, 1, tzinfo=pytz.utc) forecast_date = chellow.computer.forecast_date() if site_id is None: sites = sess.query(Site).join(SiteEra).join(Era).join(Supply).join( Source).filter( Source.code.in_(('gen', 'gen-net')), Era.start_date <= march_finish, or_( Era.finish_date == null(), Era.finish_date >= march_start)).distinct() else: site = Site.get_by_id(sess, site_id) sites = sess.query(Site).filter(Site.id == site.id) for site in sites.order_by(Site.code): displaced_era = chellow.computer.displaced_era( sess, caches, site, march_start, march_finish, forecast_date) if displaced_era is None: continue site_ds = chellow.computer.SiteSource( sess, site, march_start, march_finish, forecast_date, caches, displaced_era) chellow.duos.duos_vb(site_ds) chellow.triad.hh(site_ds) chellow.triad.bill(site_ds) bill = site_ds.supplier_bill for rname, rset in site_ds.supplier_rate_sets.items(): if len(rset) == 1: bill[rname] = rset.pop() values = [site.code, site.name] for i in range(1, 4): triad_prefix = 'triad-actual-' + str(i) values.append(hh_format(bill[triad_prefix + '-date'])) for suffix in ['-msp-kw', '-laf', '-gsp-kw']: values.append(bill[triad_prefix + suffix]) values += [ str(bill['triad-actual-' + suf]) for suf in [ 'gsp-kw', 'rate', 'gbp']] writer.writerow(values) except BadRequest as e: writer.writerow([e.description]) except: writer.writerow([traceback.format_exc()]) finally: if sess is not None: sess.close() if f is not None: f.close() os.rename(running_name, finished_name)
def content(year, site_id, sess): caches = {} try: march_finish = datetime.datetime(year, 4, 1, tzinfo=pytz.utc) - HH march_start = datetime.datetime(year, 3, 1, tzinfo=pytz.utc) yield ', '.join( ( "Site Code", "Site Name", "Displaced TRIAD 1 Date", "Displaced TRIAD 1 MSP kW", "Displaced TRIAD LAF", "Displaced TRIAD 1 GSP kW", "Displaced TRIAD 2 Date", "Displaced TRIAD 2 MSP kW", "Displaced TRIAD 2 LAF", "Displaced TRIAD 2 GSP kW", "Displaced TRIAD 3 Date", "Displaced TRIAD 3 MSP kW", "Displaced TRIAD 3 LAF", "Displaced TRIAD 3 GSP kW", "Displaced GSP kW", "Displaced Rate GBP / kW", "GBP")) + '\n' forecast_date = chellow.computer.forecast_date() if site_id is None: sites = sess.query(Site).join(SiteEra).join(Era).join(Supply).join( Source).filter( Source.code.in_(('gen', 'gen-net')), Era.start_date <= march_finish, or_( Era.finish_date == null(), Era.finish_date >= march_start)).distinct() else: site = Site.get_by_id(sess, site_id) sites = sess.query(Site).filter(Site.id == site.id) for site in sites: for site_group in site.groups( sess, march_start, march_finish, True): if site_group.start_date > march_start: chunk_start = site_group.start_date else: chunk_start = march_start if not site_group.finish_date < march_finish: chunk_finish = march_finish else: continue yield '"' + site.code + '","' + site.name + '"' displaced_era = chellow.computer.displaced_era( sess, site_group, chunk_start, chunk_finish) if displaced_era is None: continue site_ds = chellow.computer.SiteSource( sess, site, chunk_start, chunk_finish, forecast_date, None, caches, displaced_era) chellow.duos.duos_vb(site_ds) chellow.triad.hh(site_ds) chellow.triad.bill(site_ds) bill = site_ds.supplier_bill for rname, rset in site_ds.supplier_rate_sets.items(): if len(rset) == 1: bill[rname] = rset.pop() values = [] for i in range(1, 4): triad_prefix = 'triad-actual-' + str(i) for suffix in ['-date', '-msp-kw', '-laf', '-gsp-kw']: values.append(bill[triad_prefix + suffix]) values += [ bill['triad-actual-' + suf] for suf in [ 'gsp-kw', 'rate', 'gbp']] for value in values: if isinstance(value, datetime.datetime): yield "," + hh_format(value) else: yield "," + str(value) yield '\n' except: yield traceback.format_exc()
def _process_sites(sess, file_like, writer, props, report_run): ASSET_KEY = "asset_comparison" try: asset_props = props[ASSET_KEY] except KeyError: raise BadRequest( f"The property {ASSET_KEY} cannot be found in the configuration properties." ) if not isinstance(asset_props, dict): raise BadRequest("The {ASSET_KEY} property must be a map.") for key in ("ignore_site_codes", ): try: asset_props[key] except KeyError: raise BadRequest( f"The property {key} cannot be found in the '{ASSET_KEY}' section of " f"the configuration properties.") ignore_site_codes = asset_props["ignore_site_codes"] site_codes_select = (select(Site.code).filter( Site.code.notin_(ignore_site_codes)).order_by(Site.code)) site_codes = [s[0] for s in sess.execute(site_codes_select)] titles = ( "site_code", "asset_status", "chellow_status", ) writer.writerow(titles) parser = iter(csv.reader(file_like)) next(parser) # Skip titles for values in parser: if len(values) == 0: continue asset_code = values[0].strip() asset_status = values[3].strip() if asset_code in ignore_site_codes: continue if asset_code in site_codes: site_codes.remove(asset_code) eras = sess.execute( select(Era).join(SiteEra).join(Site).filter( Site.code == asset_code, Era.finish_date == null()).options( joinedload(Era.energisation_status))).all() if len(eras) == 0: is_energised = None is_energised_str = "no supplies" else: energised_eras = [ r for r in eras if r[0].energisation_status.code == "E" ] is_energised = len(energised_eras) > 0 is_energised_str = "energised" if is_energised is True else "de-energised" if asset_status in STATUSES_ACTIVE: active_asset = True elif asset_status in STATUSES_INACTIVE: active_asset = False elif asset_status in STATUSES_IGNORE: active_asset = None else: raise BadRequest(f"Asset status '{asset_status}' not recognized.") if active_asset is False and is_energised is not None: values = { "site_code": asset_code, "asset_status": asset_status, "chellow_status": is_energised_str, } writer.writerow([values[t] for t in titles]) site = Site.find_by_code(sess, asset_code) values["site_id"] = None if site is None else site.id report_run.insert_row(sess, "", titles, values, {}) sess.commit() for site_code in site_codes: eras = sess.execute( select(Era).join(SiteEra).join(Site).filter( Site.code == site_code, Era.finish_date == null()).options( joinedload(Era.energisation_status))).all() if len(eras) > 0: e_eras = [r for r in eras if r[0].energisation_status.code == "E"] is_energised_str = "energised" if len( e_eras) > 0 else "de-energised" values = { "site_code": site_code, "asset_status": None, "chellow_status": is_energised_str, } writer.writerow([values[t] for t in titles]) site = Site.find_by_code(sess, site_code) values["site_id"] = None if site is None else site.id report_run.insert_row(sess, "", titles, values, {}) sess.commit()
def do_post(sess): base_name = [] now = utc_datetime_now() if "scenario_id" in request.values: scenario_id = req_int("scenario_id") scenario = Scenario.get_by_id(sess, scenario_id) scenario_props = scenario.props base_name.append(scenario.name) start_year = scenario_props["scenario_start_year"] start_month = scenario_props["scenario_start_month"] start_date_ct = ct_datetime(now.year, now.month, 1) if start_year is None: scenario_props["scenario_start_year"] = start_date_ct.year if start_month is None: scenario_props["scenario_start_month"] = start_date_ct.month else: year = req_int("finish_year") month = req_int("finish_month") months = req_int("months") start_date, _ = next( c_months_c(finish_year=year, finish_month=month, months=months)) by_hh = req_bool("by_hh") scenario_props = { "scenario_start_year": start_date.year, "scenario_start_month": start_date.month, "scenario_duration": months, "by_hh": by_hh, } base_name.append("monthly_duration") try: site_id = req_int("site_id") if "site_id" in request.values else None if "site_codes" in request.values: site_codes = req_str("site_codes").splitlines() # Check sites codes are valid for site_code in site_codes: Site.get_by_code(sess, site_code) else: site_codes = [] if "supply_id" in request.values: supply_id = req_int("supply_id") else: supply_id = None if "compression" in request.values: compression = req_bool("compression") else: compression = True user = g.user args = ( scenario_props, base_name, site_id, supply_id, user, compression, site_codes, now, ) threading.Thread(target=content, args=args).start() return chellow_redirect("/downloads", 303) except BadRequest as e: flash(e.description) now = Datetime.utcnow() month_start = Datetime(now.year, now.month, 1) - relativedelta(months=1) month_finish = Datetime(now.year, now.month, 1) - HH return make_response( render_template( "ods_monthly_duration.html", month_start=month_start, month_finish=month_finish, ), 400, )
def test_SupplySource_init_nhh(sess, mocker): """Old style channels""" site = Site.insert(sess, "CI017", "Water Works") market_role_Z = MarketRole.insert(sess, "Z", "Non-core") participant = Participant.insert(sess, "CALB", "AK Industries") participant.insert_party(sess, market_role_Z, "None core", utc_datetime(2000, 1, 1), None, None) bank_holiday_rate_script = {"bank_holidays": []} Contract.insert_non_core( sess, "bank_holidays", "", {}, utc_datetime(2000, 1, 1), None, bank_holiday_rate_script, ) market_role_X = MarketRole.insert(sess, "X", "Supplier") market_role_M = MarketRole.insert(sess, "M", "Mop") market_role_C = MarketRole.insert(sess, "C", "HH Dc") market_role_R = MarketRole.insert(sess, "R", "Distributor") participant.insert_party(sess, market_role_M, "Fusion Mop Ltd", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_X, "Fusion Ltc", utc_datetime(2000, 1, 1), None, None) participant.insert_party(sess, market_role_C, "Fusion DC", utc_datetime(2000, 1, 1), None, None) mop_contract = Contract.insert_mop(sess, "Fusion", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) dc_contract = Contract.insert_hhdc(sess, "Fusion DC 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}) pc = Pc.insert(sess, "03", "nhh", utc_datetime(2000, 1, 1), None) ssc = Ssc.insert(sess, "0393", "unrestricted", True, utc_datetime(2000, 1), None) insert_cops(sess) cop = Cop.get_by_code(sess, "5") exp_supplier_contract = Contract.insert_supplier( sess, "Fusion Supplier 2000", participant, "", {}, utc_datetime(2000, 1, 1), None, {}, ) dno = participant.insert_party(sess, market_role_R, "WPD", utc_datetime(2000, 1, 1), None, "22") meter_type = MeterType.insert(sess, "C5", "COP 1-5", utc_datetime(2000, 1, 1), None) meter_payment_type = MeterPaymentType.insert(sess, "CR", "Credit", utc_datetime(1996, 1, 1), None) Mtc.insert( sess, None, "845", "HH COP5 And Above With Comms", False, False, True, meter_type, meter_payment_type, 0, utc_datetime(1996, 1, 1), None, ) insert_voltage_levels(sess) voltage_level = VoltageLevel.get_by_code(sess, "HV") dno.insert_llfc( sess, "510", "PC 5-8 & HH HV", voltage_level, False, True, utc_datetime(1996, 1, 1), None, ) dno.insert_llfc( sess, "521", "Export (HV)", voltage_level, False, False, utc_datetime(1996, 1, 1), None, ) insert_sources(sess) source = Source.get_by_code(sess, "net") insert_energisation_statuses(sess) energisation_status = EnergisationStatus.get_by_code(sess, "D") gsp_group = GspGroup.insert(sess, "_L", "South Western") supply = site.insert_e_supply( sess, source, None, "Bob", utc_datetime(2000, 1, 1), None, gsp_group, mop_contract, "773", dc_contract, "ghyy3", "hgjeyhuw", pc, "845", cop, ssc, energisation_status, {}, None, None, None, None, None, "22 7867 6232 781", "521", exp_supplier_contract, "7748", 361, ) era = supply.eras[0] active_channel = era.insert_channel(sess, False, "ACTIVE") active_data_raw = [{ "start_date": utc_datetime(2009, 8, 10), "value": 10, "status": "A", }] active_channel.add_hh_data(sess, active_data_raw) era.insert_channel(sess, True, "REACTIVE_IMP") sess.commit() caches = {} start_date = utc_datetime(2009, 7, 31, 23, 00) finish_date = utc_datetime(2009, 8, 31, 22, 30) forecast_date = utc_datetime(2019, 8, 31, 22, 30) is_import = False chellow.computer.SupplySource(sess, start_date, finish_date, forecast_date, era, is_import, caches)
def content(scenario_props, scenario_id, base_name, site_id, supply_id, user, compression): now = utc_datetime_now() report_context = {} try: comp = report_context['computer'] except KeyError: comp = report_context['computer'] = {} try: rate_cache = comp['rates'] except KeyError: rate_cache = comp['rates'] = {} try: ind_cont = report_context['contract_names'] except KeyError: ind_cont = report_context['contract_names'] = {} sess = None try: sess = Session() if scenario_props is None: scenario_contract = Contract.get_supplier_by_id(sess, scenario_id) scenario_props = scenario_contract.make_properties() base_name.append(scenario_contract.name) start_date = scenario_props['scenario_start'] if start_date is None: start_date = utc_datetime(now.year, now.month, 1) else: start_date = to_utc(start_date) base_name.append( hh_format(start_date).replace(' ', '_').replace(':', '').replace('-', '')) months = scenario_props['scenario_duration'] base_name.append('for') base_name.append(str(months)) base_name.append('months') finish_date = start_date + relativedelta(months=months) if 'forecast_from' in scenario_props: forecast_from = scenario_props['forecast_from'] else: forecast_from = None if forecast_from is None: forecast_from = chellow.computer.forecast_date() else: forecast_from = to_utc(forecast_from) sites = sess.query(Site).distinct().order_by(Site.code) if site_id is not None: site = Site.get_by_id(sess, site_id) sites = sites.filter(Site.id == site.id) base_name.append('site') base_name.append(site.code) if supply_id is not None: supply = Supply.get_by_id(sess, supply_id) base_name.append('supply') base_name.append(str(supply.id)) sites = sites.join(SiteEra).join(Era).filter(Era.supply == supply) running_name, finished_name = chellow.dloads.make_names( '_'.join(base_name) + '.ods', user) rf = open(running_name, "wb") site_rows = [] era_rows = [] for rate_script in get_map_list(scenario_props, 'local_rates'): contract_id = rate_script['contract_id'] try: cont_cache = rate_cache[contract_id] except KeyError: cont_cache = rate_cache[contract_id] = {} try: rate_script_start = rate_script['start_date'] except KeyError: raise BadRequest( "Problem in the scenario properties. Can't find the " + "'start_date' key of the contract " + str(contract_id) + " in the 'local_rates' map.") try: rate_script_start = rate_script['start_date'] except KeyError: raise BadRequest( "Problem in the scenario properties. Can't find the " + "'start_date' key of the contract " + str(contract_id) + " in the 'local_rates' map.") for dt in hh_range(report_context, rate_script_start, rate_script['finish_date']): cont_cache[dt] = PropDict('scenario properties', rate_script['script']) for rate_script in get_map_list(scenario_props, 'industry_rates'): contract_name = rate_script['contract_name'] try: cont_cache = ind_cont[contract_name] except KeyError: cont_cache = ind_cont[contract_name] = {} rfinish = rate_script['finish_date'] if rfinish is None: raise BadRequest("For the industry rate " + contract_name + " the " "finish_date can't be null.") for dt in hh_range(report_context, rate_script['start_date'], rfinish): cont_cache[dt] = PropDict('scenario properties', rate_script['script']) era_maps = scenario_props.get('era_maps', {}) scenario_hh = scenario_props.get('hh_data', {}) era_header_titles = [ 'creation-date', 'imp-mpan-core', 'imp-supplier-contract', 'exp-mpan-core', 'exp-supplier-contract', 'metering-type', 'source', 'generator-type', 'supply-name', 'msn', 'pc', 'site-id', 'site-name', 'associated-site-ids', 'month' ] site_header_titles = [ 'creation-date', 'site-id', 'site-name', 'associated-site-ids', 'month', 'metering-type', 'sources', 'generator-types' ] summary_titles = [ 'import-net-kwh', 'export-net-kwh', 'import-gen-kwh', 'export-gen-kwh', 'import-3rd-party-kwh', 'export-3rd-party-kwh', 'displaced-kwh', 'used-kwh', 'used-3rd-party-kwh', 'import-net-gbp', 'export-net-gbp', 'import-gen-gbp', 'export-gen-gbp', 'import-3rd-party-gbp', 'export-3rd-party-gbp', 'displaced-gbp', 'used-gbp', 'used-3rd-party-gbp', 'billed-import-net-kwh', 'billed-import-net-gbp' ] title_dict = {} for cont_type, con_attr in (('mop', Era.mop_contract), ('dc', Era.dc_contract), ('imp-supplier', Era.imp_supplier_contract), ('exp-supplier', Era.exp_supplier_contract)): titles = [] title_dict[cont_type] = titles conts = sess.query(Contract).join(con_attr).join(Era.supply). \ join(Source).filter( Era.start_date <= finish_date, or_( Era.finish_date == null(), Era.finish_date >= start_date), Source.code.in_(('net', '3rd-party')) ).distinct().order_by(Contract.id) if supply_id is not None: conts = conts.filter(Era.supply_id == supply_id) for cont in conts: title_func = chellow.computer.contract_func( report_context, cont, 'virtual_bill_titles') if title_func is None: raise Exception("For the contract " + cont.name + " there doesn't seem to be a " "'virtual_bill_titles' function.") for title in title_func(): if title not in titles: titles.append(title) tpr_query = sess.query(Tpr).join(MeasurementRequirement).join(Ssc). \ join(Era).filter( Era.start_date <= finish_date, or_( Era.finish_date == null(), Era.finish_date >= start_date) ).order_by(Tpr.code).distinct() for tpr in tpr_query.filter(Era.imp_supplier_contract != null()): for suffix in ('-kwh', '-rate', '-gbp'): title_dict['imp-supplier'].append(tpr.code + suffix) for tpr in tpr_query.filter(Era.exp_supplier_contract != null()): for suffix in ('-kwh', '-rate', '-gbp'): title_dict['exp-supplier'].append(tpr.code + suffix) era_rows.append( era_header_titles + summary_titles + [None] + ['mop-' + t for t in title_dict['mop']] + [None] + ['dc-' + t for t in title_dict['dc']] + [None] + ['imp-supplier-' + t for t in title_dict['imp-supplier']] + [None] + ['exp-supplier-' + t for t in title_dict['exp-supplier']]) site_rows.append(site_header_titles + summary_titles) sites = sites.all() deltas = {} for site in sites: try: site_scenario_hh = scenario_hh[site.code] except KeyError: site_scenario_hh = scenario_hh[site.code] = {} site_deltas = deltas[site.code] = {'hhs': {}} delts = site_deltas['supply_deltas'] = {} for is_import in (True, False): delts[is_import] = {} for src in ('gen', 'net', 'gen-net', '3rd-party', '3rd-party-reverse', 'sub'): delts[is_import][src] = {'site': {}} earliest_delta = to_utc(Datetime.max) latest_delta = to_utc(Datetime.min) found_hh = False for typ in ('used', 'generated', 'parasitic', 'gen_net'): hh_str = site_scenario_hh.get(typ, '') hh_data = site_scenario_hh[typ] = {} for row in csv.reader(StringIO(hh_str)): cells = [cell.strip() for cell in row] if len(''.join(cells)) == 0: continue if len(cells) != 2: raise BadRequest( "Can't interpret the row " + str(cells) + " it should be of the form 'timestamp, kWh'") date_str, kw_str = cells ts = parse_hh_start(date_str) earliest_delta = min(ts, earliest_delta) latest_delta = max(ts, latest_delta) hh_data[ts] = float(kw_str) found_hh = True if not found_hh: continue scenario_used = site_scenario_hh['used'] scenario_generated = site_scenario_hh['generated'] scenario_parasitic = site_scenario_hh['parasitic'] scenario_gen_net = site_scenario_hh['gen_net'] month_start = utc_datetime(earliest_delta.year, earliest_delta.month) while month_start <= latest_delta: month_finish = month_start + relativedelta(months=1) - HH chunk_start = hh_max(month_start, earliest_delta) chunk_finish = hh_min(month_finish, latest_delta) site_ds = chellow.computer.SiteSource(sess, site, chunk_start, chunk_finish, forecast_from, report_context) hh_map = dict((h['start-date'], h) for h in site_ds.hh_data) for era in sess.query(Era).join(SiteEra).join(Pc).filter( SiteEra.site == site, SiteEra.is_physical == true(), Era.imp_mpan_core != null(), Pc.code != '00', Era.start_date <= chunk_finish, or_(Era.finish_date == null(), Era.finish_date >= chunk_start), ~Era.channels.any()): if supply_id is not None and era.supply_id != supply_id: continue ss_start = hh_max(era.start_date, chunk_start) ss_finish = hh_min(era.finish_date, chunk_finish) ss = SupplySource(sess, ss_start, ss_finish, forecast_from, era, True, report_context) for hh in ss.hh_data: sdatum = hh_map[hh['start-date']] sdatum['import-net-kwh'] += hh['msp-kwh'] sdatum['used-kwh'] += hh['msp-kwh'] for era in sess.query(Era).join(SiteEra).join(Pc).join( Supply).join(Source).filter( SiteEra.site == site, SiteEra.is_physical == true(), Era.imp_mpan_core != null(), Era.start_date <= chunk_finish, or_(Era.finish_date == null(), Era.finish_date >= chunk_start), Source.code == 'gen-net'): if supply_id is not None and era.supply_id != supply_id: continue ss_start = hh_max(era.start_date, chunk_start) ss_finish = hh_min(era.finish_date, chunk_finish) ss = SupplySource(sess, ss_start, ss_finish, forecast_from, era, False, report_context) for hh in ss.hh_data: sdatum = hh_map[hh['start-date']] try: sdatum['gen-net-kwh'] += hh['msp-kwh'] except KeyError: sdatum['gen-net-kwh'] = hh['msp-kwh'] for hh in site_ds.hh_data: hh_start = hh['start-date'] if hh_start in scenario_used: used_delt = scenario_used[hh_start] - hh['used-kwh'] imp_net_delt = 0 exp_net_delt = 0 if used_delt < 0: diff = hh['import-net-kwh'] + used_delt if diff < 0: imp_net_delt -= hh['import-net-kwh'] exp_net_delt -= diff else: imp_net_delt += used_delt else: diff = hh['export-net-kwh'] - used_delt if diff < 0: exp_net_delt -= hh['export-net-kwh'] imp_net_delt -= diff else: exp_net_delt -= used_delt try: delts[False]['net']['site'][hh_start] += \ exp_net_delt except KeyError: delts[False]['net']['site'][hh_start] = \ exp_net_delt try: delts[True]['net']['site'][hh_start] += \ imp_net_delt except KeyError: delts[True]['net']['site'][hh_start] = imp_net_delt hh['import-net-kwh'] += imp_net_delt hh['export-net-kwh'] += exp_net_delt hh['used-kwh'] += used_delt hh['msp-kwh'] -= exp_net_delt if hh_start in scenario_generated: imp_gen_delt = scenario_generated[hh_start] - \ hh['import-gen-kwh'] imp_net_delt = 0 exp_net_delt = 0 if imp_gen_delt < 0: diff = hh['export-net-kwh'] + imp_gen_delt if diff < 0: exp_net_delt -= hh['export-net-kwh'] imp_net_delt -= diff else: exp_net_delt += imp_gen_delt else: diff = hh['import-net-kwh'] - imp_gen_delt if diff < 0: imp_net_delt -= hh['import-net-kwh'] exp_net_delt -= diff else: imp_net_delt -= imp_gen_delt try: delts[True]['gen']['site'][hh_start] += \ imp_gen_delt except KeyError: delts[True]['gen']['site'][hh_start] = imp_gen_delt try: delts[False]['net']['site'][hh_start] += \ exp_net_delt except KeyError: delts[False]['net']['site'][hh_start] = \ exp_net_delt try: delts[True]['net']['site'][hh_start] += \ imp_net_delt except KeyError: delts[True]['net']['site'][hh_start] = imp_net_delt hh['import-net-kwh'] += imp_net_delt hh['export-net-kwh'] += exp_net_delt hh['import-gen-kwh'] += imp_gen_delt hh['msp-kwh'] -= imp_net_delt if hh_start in scenario_parasitic: exp_gen_delt = scenario_parasitic[hh_start] - \ hh['export-gen-kwh'] imp_net_delt = 0 exp_net_delt = 0 if exp_gen_delt < 0: diff = hh['import-net-kwh'] + exp_gen_delt if diff < 0: imp_net_delt -= hh['import-net-kwh'] exp_net_delt -= diff else: imp_net_delt += exp_gen_delt else: diff = hh['export-net-kwh'] - exp_gen_delt if diff < 0: exp_net_delt -= hh['export-net-kwh'] imp_net_delt -= diff else: exp_net_delt -= exp_gen_delt try: delts[False]['gen']['site'][hh_start] += \ imp_gen_delt except KeyError: delts[False]['gen']['site'][hh_start] = \ exp_gen_delt try: delts[False]['net']['site'][hh_start] += \ exp_net_delt except KeyError: delts[False]['net']['site'][hh_start] = \ exp_net_delt try: delts[True]['net']['site'][hh_start] += \ imp_net_delt except KeyError: delts[True]['net']['site'][hh_start] = imp_net_delt hh['import-net-kwh'] += imp_net_delt hh['export-net-kwh'] += exp_net_delt hh['export-gen-kwh'] += exp_gen_delt hh['msp-kwh'] -= imp_net_delt if hh_start in scenario_gen_net: gen_net_delt = scenario_gen_net[hh_start] - \ hh['gen-net-kwh'] try: delts[False]['gen-net']['site'][hh_start] += \ gen_net_delt except KeyError: delts[False]['gen-net']['site'][hh_start] = \ gen_net_delt hh['import-gen-kwh'] += gen_net_delt hh['export-net-kwh'] += gen_net_delt site_deltas['hhs'][hh_start] = hh month_start += relativedelta(months=1) month_start = start_date while month_start < finish_date: month_finish = month_start + relativedelta(months=1) - HH for site in sites: site_category = None site_sources = set() site_gen_types = set() site_month_data = defaultdict(int) calcs = [] for era in sess.query(Era).join(SiteEra).join(Pc).filter( SiteEra.site == site, SiteEra.is_physical == true(), Era.start_date <= month_finish, or_(Era.finish_date == null(), Era.finish_date >= month_start)).options( joinedload(Era.ssc), joinedload(Era.dc_contract), joinedload(Era.mop_contract), joinedload(Era.imp_supplier_contract), joinedload(Era.exp_supplier_contract), joinedload(Era.channels), joinedload(Era.imp_llfc).joinedload( Llfc.voltage_level), joinedload(Era.exp_llfc).joinedload( Llfc.voltage_level), joinedload(Era.cop), joinedload(Era.supply).joinedload(Supply.dno), joinedload(Era.supply).joinedload( Supply.gsp_group), joinedload(Era.supply).joinedload( Supply.source), joinedload(Era.mtc).joinedload(Mtc.meter_type), joinedload(Era.pc), joinedload(Era.site_eras)).order_by(Pc.code): supply = era.supply if supply.generator_type is not None: site_gen_types.add(supply.generator_type.code) if supply_id is not None and supply.id != supply_id: continue ss_start = hh_max(era.start_date, month_start) ss_finish = hh_min(era.finish_date, month_finish) if era.imp_mpan_core is None: imp_ss = None else: sup_deltas = site_deltas['supply_deltas'][True][ supply.source.code] imp_ss = SupplySource(sess, ss_start, ss_finish, forecast_from, era, True, report_context, era_maps=era_maps, deltas=sup_deltas) if era.exp_mpan_core is None: exp_ss = None measurement_type = imp_ss.measurement_type else: sup_deltas = site_deltas['supply_deltas'][False][ supply.source.code] exp_ss = SupplySource(sess, ss_start, ss_finish, forecast_from, era, False, report_context, era_maps=era_maps, deltas=sup_deltas) measurement_type = exp_ss.measurement_type order = meter_order[measurement_type] calcs.append((order, era.imp_mpan_core, era.exp_mpan_core, imp_ss, exp_ss)) # Check if gen deltas haven't been consumed extra_sss = set() for is_imp in (True, False): sup_deltas = site_deltas['supply_deltas'][is_imp]['gen'] if len( list(t for t in sup_deltas['site'] if month_start <= t <= month_finish)) > 0: extra_sss.add(is_imp) displaced_era = chellow.computer.displaced_era( sess, report_context, site, month_start, month_finish, forecast_from, has_scenario_generation=len(extra_sss) > 0) if len(extra_sss) > 0: if True in extra_sss: sup_deltas = site_deltas['supply_deltas'][True]['gen'] imp_ss_name = site.code + "_extra_gen_TRUE" imp_ss = ScenarioSource( sess, month_start, month_finish, True, report_context, sup_deltas, displaced_era.imp_supplier_contract, imp_ss_name) else: imp_ss_name = imp_ss = None if False in extra_sss: exp_ss_name = site.code + "_extra_gen_FALSE" sup_deltas = site_deltas['supply_deltas'][False]['gen'] exp_ss = ScenarioSource( sess, month_start, month_finish, False, report_context, sup_deltas, displaced_era.imp_supplier_contract, imp_ss_name) else: exp_ss_name = exp_ss = None calcs.append((0, imp_ss_name, exp_ss_name, imp_ss, exp_ss)) # Check if exp net deltas haven't been consumed sup_deltas = site_deltas['supply_deltas'][False]['net'] if len( list(t for t in sup_deltas['site'] if month_start <= t <= month_finish)) > 0: ss_name = site.code + "_extra_net_export" ss = SupplySource(sess, month_start, month_finish, forecast_from, displaced_era, False, report_context, era_maps=era_maps, deltas=sup_deltas) calcs.append((0, None, ss_name, None, ss)) site_ds = chellow.computer.SiteSource(sess, site, month_start, month_finish, forecast_from, report_context, displaced_era, deltas=site_deltas) if displaced_era is not None and supply_id is None: month_data = {} for sname in ('import-net', 'export-net', 'import-gen', 'export-gen', 'import-3rd-party', 'export-3rd-party', 'msp', 'used', 'used-3rd-party', 'billed-import-net'): for xname in ('kwh', 'gbp'): month_data[sname + '-' + xname] = 0 month_data['used-kwh'] = month_data['displaced-kwh'] = sum( hh['msp-kwh'] for hh in site_ds.hh_data) disp_supplier_contract = \ displaced_era.imp_supplier_contract disp_vb_function = chellow.computer.contract_func( report_context, disp_supplier_contract, 'displaced_virtual_bill') if disp_vb_function is None: raise BadRequest( "The supplier contract " + disp_supplier_contract.name + " doesn't have the displaced_virtual_bill() " "function.") disp_vb_function(site_ds) disp_supplier_bill = site_ds.supplier_bill try: gbp = disp_supplier_bill['net-gbp'] except KeyError: disp_supplier_bill['problem'] += 'For the supply ' + \ site_ds.mpan_core + ' the virtual bill ' + \ str(disp_supplier_bill) + ' from the contract ' + \ disp_supplier_contract.name + \ ' does not contain the net-gbp key.' month_data['used-gbp'] = month_data['displaced-gbp'] = \ site_ds.supplier_bill['net-gbp'] out = [ now, None, disp_supplier_contract.name, None, None, displaced_era.meter_category, 'displaced', None, None, None, None, site.code, site.name, '', month_finish ] + [month_data[t] for t in summary_titles ] + [None] + [None] * len(title_dict['mop']) + [ None ] + [None] * len(title_dict['dc']) + [ None ] + make_bill_row(title_dict['imp-supplier'], disp_supplier_bill) era_rows.append(out) for k, v in month_data.items(): site_month_data[k] += v for i, (order, imp_mpan_core, exp_mpan_core, imp_ss, exp_ss) in enumerate(sorted(calcs, key=str)): if imp_ss is None: source_code = exp_ss.source_code supply = exp_ss.supply else: source_code = imp_ss.source_code supply = imp_ss.supply site_sources.add(source_code) month_data = {} for name in ('import-net', 'export-net', 'import-gen', 'export-gen', 'import-3rd-party', 'export-3rd-party', 'displaced', 'used', 'used-3rd-party', 'billed-import-net'): for sname in ('kwh', 'gbp'): month_data[name + '-' + sname] = 0 if imp_ss is not None: imp_supplier_contract = imp_ss.supplier_contract if imp_supplier_contract is not None: import_vb_function = contract_func( report_context, imp_supplier_contract, 'virtual_bill') if import_vb_function is None: raise BadRequest( "The supplier contract " + imp_supplier_contract.name + " doesn't have the virtual_bill() " "function.") import_vb_function(imp_ss) kwh = sum(hh['msp-kwh'] for hh in imp_ss.hh_data) imp_supplier_bill = imp_ss.supplier_bill try: gbp = imp_supplier_bill['net-gbp'] except KeyError: gbp = 0 imp_supplier_bill['problem'] += \ 'For the supply ' + \ imp_ss.mpan_core + \ ' the virtual bill ' + \ str(imp_supplier_bill) + \ ' from the contract ' + \ imp_supplier_contract.name + \ ' does not contain the net-gbp key.' if source_code in ('net', 'gen-net'): month_data['import-net-gbp'] += gbp month_data['import-net-kwh'] += kwh month_data['used-gbp'] += gbp month_data['used-kwh'] += kwh if source_code == 'gen-net': month_data['export-gen-kwh'] += kwh elif source_code == '3rd-party': month_data['import-3rd-party-gbp'] += gbp month_data['import-3rd-party-kwh'] += kwh month_data['used-3rd-party-gbp'] += gbp month_data['used-3rd-party-kwh'] += kwh month_data['used-gbp'] += gbp month_data['used-kwh'] += kwh elif source_code == '3rd-party-reverse': month_data['export-3rd-party-gbp'] += gbp month_data['export-3rd-party-kwh'] += kwh month_data['used-3rd-party-gbp'] -= gbp month_data['used-3rd-party-kwh'] -= kwh month_data['used-gbp'] -= gbp month_data['used-kwh'] -= kwh elif source_code == 'gen': month_data['import-gen-kwh'] += kwh if exp_ss is not None: exp_supplier_contract = exp_ss.supplier_contract if exp_supplier_contract is not None: export_vb_function = contract_func( report_context, exp_supplier_contract, 'virtual_bill') export_vb_function(exp_ss) kwh = sum(hh['msp-kwh'] for hh in exp_ss.hh_data) exp_supplier_bill = exp_ss.supplier_bill try: gbp = exp_supplier_bill['net-gbp'] except KeyError: exp_supplier_bill['problem'] += \ 'For the supply ' + imp_ss.mpan_core + \ ' the virtual bill ' + \ str(imp_supplier_bill) + \ ' from the contract ' + \ imp_supplier_contract.name + \ ' does not contain the net-gbp key.' if source_code in ('net', 'gen-net'): month_data['export-net-gbp'] += gbp month_data['export-net-kwh'] += kwh if source_code == 'gen-net': month_data['import-gen-kwh'] += kwh elif source_code == '3rd-party': month_data['export-3rd-party-gbp'] += gbp month_data['export-3rd-party-kwh'] += kwh month_data['used-3rd-party-gbp'] -= gbp month_data['used-3rd-party-kwh'] -= kwh month_data['used-gbp'] -= gbp month_data['used-kwh'] -= kwh elif source_code == '3rd-party-reverse': month_data['import-3rd-party-gbp'] += gbp month_data['import-3rd-party-kwh'] += kwh month_data['used-3rd-party-gbp'] += gbp month_data['used-3rd-party-kwh'] += kwh month_data['used-gbp'] += gbp month_data['used-kwh'] += kwh elif source_code == 'gen': month_data['export-gen-kwh'] += kwh sss = exp_ss if imp_ss is None else imp_ss dc_contract = sss.dc_contract if dc_contract is not None: sss.contract_func(dc_contract, 'virtual_bill')(sss) dc_bill = sss.dc_bill gbp = dc_bill['net-gbp'] mop_contract = sss.mop_contract if mop_contract is not None: mop_bill_function = sss.contract_func( mop_contract, 'virtual_bill') mop_bill_function(sss) mop_bill = sss.mop_bill gbp += mop_bill['net-gbp'] if source_code in ('3rd-party', '3rd-party-reverse'): month_data['import-3rd-party-gbp'] += gbp month_data['used-3rd-party-gbp'] += gbp else: month_data['import-net-gbp'] += gbp month_data['used-gbp'] += gbp generator_type = sss.generator_type_code if source_code in ('gen', 'gen-net'): site_gen_types.add(generator_type) era_category = sss.measurement_type if CATEGORY_ORDER[site_category] < \ CATEGORY_ORDER[era_category]: site_category = era_category era_associates = set() if mop_contract is not None: era_associates.update({ s.site.code for s in era.site_eras if not s.is_physical }) for bill in sess.query(Bill).filter( Bill.supply == supply, Bill.start_date <= sss.finish_date, Bill.finish_date >= sss.start_date): bill_start = bill.start_date bill_finish = bill.finish_date bill_duration = ( bill_finish - bill_start).total_seconds() + \ (30 * 60) overlap_duration = ( min(bill_finish, sss.finish_date) - max(bill_start, sss.start_date) ).total_seconds() + (30 * 60) overlap_proportion = overlap_duration / \ bill_duration month_data['billed-import-net-kwh'] += \ overlap_proportion * float(bill.kwh) month_data['billed-import-net-gbp'] += \ overlap_proportion * float(bill.net) if imp_ss is None: imp_supplier_contract_name = None pc_code = exp_ss.pc_code else: if imp_supplier_contract is None: imp_supplier_contract_name = '' else: imp_supplier_contract_name = \ imp_supplier_contract.name pc_code = imp_ss.pc_code if exp_ss is None: exp_supplier_contract_name = None else: if exp_supplier_contract is None: exp_supplier_contract_name = '' else: exp_supplier_contract_name = \ exp_supplier_contract.name out = [ now, imp_mpan_core, imp_supplier_contract_name, exp_mpan_core, exp_supplier_contract_name, era_category, source_code, generator_type, sss.supply_name, sss.msn, pc_code, site.code, site.name, ','.join(sorted(list(era_associates))), month_finish] + [ month_data[t] for t in summary_titles] + [None] + \ make_bill_row(title_dict['mop'], mop_bill) + [None] + \ make_bill_row(title_dict['dc'], dc_bill) if imp_ss is None: out += [None] * (len(title_dict['imp-supplier']) + 1) else: out += [None] + make_bill_row( title_dict['imp-supplier'], imp_supplier_bill) if exp_ss is not None: out += [None] + make_bill_row( title_dict['exp-supplier'], exp_supplier_bill) for k, v in month_data.items(): site_month_data[k] += v era_rows.append(out) site_rows.append([ now, site.code, site.name, ', '.join( s.code for s in site.find_linked_sites( sess, month_start, month_finish)), month_finish, site_category, ', '.join(sorted(list(site_sources))), ', '.join(sorted(list(site_gen_types))) ] + [site_month_data[k] for k in summary_titles]) sess.rollback() write_spreadsheet(rf, compression, site_rows, era_rows) month_start += relativedelta(months=1) except BadRequest as e: msg = e.description + traceback.format_exc() sys.stderr.write(msg + '\n') site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, era_rows) except BaseException: msg = traceback.format_exc() sys.stderr.write(msg + '\n') site_rows.append(["Problem " + msg]) write_spreadsheet(rf, compression, site_rows, era_rows) finally: if sess is not None: sess.close() try: rf.close() os.rename(running_name, finished_name) except BaseException: msg = traceback.format_exc() r_name, f_name = chellow.dloads.make_names('error.txt', user) ef = open(r_name, "w") ef.write(msg + '\n') ef.close()