Ejemplo n.º 1
0
def test_Supply_get_by_MPAN_core(sess):
    mpan_core = "22 1737 1873 221"

    with pytest.raises(
            BadRequest,
            match=f"The MPAN core {mpan_core} is not set up in Chellow."):

        Supply.get_by_mpan_core(sess, mpan_core)
Ejemplo n.º 2
0
def _process_MTR(elements, headers):
    if headers["message_type"] != "UTLBIL":
        return

    sess = headers["sess"]
    try:
        mpan_core = headers["mpan_core"]
    except KeyError:
        raise BadRequest("The mpan_core can't be found for this bill.")

    start_date = headers["start_date"]
    reads = headers["reads"]
    supply = Supply.get_by_mpan_core(sess, mpan_core)
    era = supply.find_era_at(sess, start_date)
    bill_elements = []
    if era is None:
        era = supply.find_last_era(sess)

    if era is None:
        imp_mpan_core = ""
        ssc = Ssc.get_by_code(sess, "0393")
    else:
        imp_mpan_core = era.imp_mpan_core
        ssc = Ssc.get_by_code(sess, "0393") if era.ssc is None else era.ssc

    try:
        ssc_lookup = imp_mpan_core
        tpr_map = SSC_MAP[ssc_lookup]
    except KeyError:
        ssc_lookup = ssc.code
        try:
            tpr_map = SSC_MAP[ssc_lookup]
        except KeyError:
            raise BadRequest(f"The SSC {ssc_lookup} isn't in the SSC_MAP.")

    for read in reads:
        desc = read["tpr_code"]
        try:
            read["tpr_code"] = tpr_map[desc]
        except KeyError:
            raise BadRequest(f"The description {desc} isn't in the SSC_MAP "
                             f"for the SSC {ssc_lookup}.")

    for el in headers["bill_elements"]:
        if el.desc == "Energy Charges":
            # If it's an unmetered supply there is only one charge
            # line in the EDI, no mater how many TPRs there are.
            # Therefore we split the charge evenly between the
            # TPRs.
            mrs = ssc.measurement_requirements
            num_mrs = len(mrs)
            gbp = el.gbp / num_mrs
            cons = el.cons / num_mrs
            for mr in mrs:
                tpr_code = mr.tpr.code
                titles = (tpr_code + "-gbp", tpr_code + "-rate",
                          tpr_code + "-kwh")
                bill_elements.append(
                    BillElement(gbp=gbp,
                                rate=el.rate,
                                cons=cons,
                                titles=titles,
                                desc=None))
        else:
            if el.titles is None:
                try:
                    tpr = tpr_map[el.desc]
                except KeyError:
                    raise BadRequest(
                        f"The billing element description {el.desc} "
                        f"isn't in the SSC_MAP for the SSC {ssc_lookup}.")

                titles = (tpr + "-gbp", tpr + "-rate", tpr + "-kwh")
            else:
                titles = el.titles

            bill_elements.append(
                BillElement(gbp=el.gbp,
                            titles=titles,
                            rate=el.rate,
                            cons=el.cons,
                            desc=None))

    breakdown = headers["breakdown"]
    for bill_el in bill_elements:
        eln_gbp, eln_rate, eln_cons = bill_el.titles

        try:
            breakdown[eln_gbp] += bill_el.gbp
        except KeyError:
            breakdown[eln_gbp] = bill_el.gbp

        rate = bill_el.rate
        if eln_rate is not None and rate is not None:
            try:
                rates = breakdown[eln_rate]
            except KeyError:
                rates = breakdown[eln_rate] = set()

            rates.add(rate)

        cons = bill_el.cons
        if eln_cons is not None and cons is not None:
            try:
                breakdown[eln_cons] += cons
            except KeyError:
                breakdown[eln_cons] = cons

    return {
        "kwh": headers["kwh"],
        "reference": headers["reference"],
        "mpan_core": mpan_core,
        "issue_date": headers["issue_date"],
        "account": headers["account"],
        "start_date": start_date,
        "finish_date": headers["finish_date"],
        "net": headers["net"],
        "vat": headers["vat"],
        "gross": headers["gross"],
        "breakdown": breakdown,
        "reads": reads,
        "bill_type_code": headers["bill_type_code"],
    }
Ejemplo n.º 3
0
    def run(self):
        sess = None
        try:
            sess = Session()
            batch = Batch.get_by_id(sess, self.batch_id)

            bill_types = keydefaultdict(
                lambda k: BillType.get_by_code(sess, k))

            tprs = keydefaultdict(lambda k: None
                                  if k is None else Tpr.get_by_code(sess, k))

            read_types = keydefaultdict(
                lambda k: ReadType.get_by_code(sess, k))

            for bf in (sess.query(BatchFile).filter(
                    BatchFile.batch == batch).order_by(
                        BatchFile.upload_timestamp)):

                self.parser = _process_batch_file(sess, bf, self._log)
                for self.bill_num, raw_bill in enumerate(
                        self.parser.make_raw_bills()):

                    if "error" in raw_bill:
                        self.failed_bills.append(raw_bill)
                    else:
                        try:
                            mpan_core = raw_bill["mpan_core"]
                            supply = Supply.get_by_mpan_core(sess, mpan_core)
                            with sess.begin_nested():
                                bill = batch.insert_bill(
                                    sess,
                                    raw_bill["account"],
                                    raw_bill["reference"],
                                    raw_bill["issue_date"],
                                    raw_bill["start_date"],
                                    raw_bill["finish_date"],
                                    raw_bill["kwh"],
                                    raw_bill["net"],
                                    raw_bill["vat"],
                                    raw_bill["gross"],
                                    bill_types[raw_bill["bill_type_code"]],
                                    raw_bill["breakdown"],
                                    supply,
                                )
                                for raw_read in raw_bill["reads"]:
                                    bill.insert_read(
                                        sess,
                                        tprs[raw_read["tpr_code"]],
                                        raw_read["coefficient"],
                                        raw_read["units"],
                                        raw_read["msn"],
                                        raw_read["mpan"],
                                        raw_read["prev_date"],
                                        raw_read["prev_value"],
                                        read_types[raw_read["prev_type_code"]],
                                        raw_read["pres_date"],
                                        raw_read["pres_value"],
                                        read_types[raw_read["pres_type_code"]],
                                    )
                                self.successful_bills.append(raw_bill)
                        except KeyError as e:
                            err = raw_bill.get("error", "")
                            raw_bill["error"] = err + " " + str(e)
                            self.failed_bills.append(raw_bill)
                        except BadRequest as e:
                            raw_bill["error"] = str(e.description)
                            self.failed_bills.append(raw_bill)

            if len(self.failed_bills) == 0:
                sess.commit()
                self._log(
                    "All the bills have been successfully loaded and attached "
                    "to the batch.")
            else:
                sess.rollback()
                self._log(f"The import has finished, but there were "
                          f"{len(self.failed_bills)} failures, and so the "
                          f"whole import has been rolled back.")

        except BadRequest as e:
            sess.rollback()
            self._log(f"Problem: {e.description}")
        except BaseException:
            sess.rollback()
            self._log(f"I've encountered a problem: {traceback.format_exc()}")
        finally:
            if sess is not None:
                sess.close()
Ejemplo n.º 4
0
def _process(
    sess,
    ecoes_lines,
    exclude_mpan_cores,
    ignore_mpan_cores_msn,
    f,
    show_ignored,
    report_run,
):
    writer = csv.writer(f, lineterminator="\n")

    mpans = []

    for exp in (Era.imp_mpan_core, Era.exp_mpan_core):
        for (v,) in sess.execute(
            select(exp)
            .join(Supply)
            .join(Source)
            .join(Supply.dno)
            .filter(
                Party.dno_code.notin_(("88", "99")),
                Era.finish_date == null(),
                Source.code != "3rd-party",
                exp.notin_(exclude_mpan_cores),
                exp != null(),
            )
            .distinct()
            .order_by(exp)
        ):
            mpans.append(v)

    ecoes_mpans = {}

    parser = iter(csv.reader(ecoes_lines))
    next(parser)  # Skip titles

    for values in parser:
        ecoes_titles = [
            "mpan-core",
            "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",
            "ssc",
            "measurement-class",
            "energisation-status",
            "da",
            "dc",
            "mop",
            "mop-appoint-date",
            "gsp-group",
            "gsp-effective-from",
            "dno",
            "msn",
            "meter-install-date",
            "meter-type",
            "map-id",
        ]

        ecoes_row = dict(zip(ecoes_titles, map(str.strip, values)))
        mpan_core = ecoes_row["mpan-core"]
        mpan_spaces = " ".join(
            (
                mpan_core[:2],
                mpan_core[2:6],
                mpan_core[6:10],
                mpan_core[-3:],
            )
        )
        if mpan_spaces in exclude_mpan_cores:
            continue

        ecoes_row["mpan_spaces"] = mpan_spaces
        if mpan_spaces in ecoes_mpans:
            prev_row = ecoes_mpans[mpan_spaces]
            prev_row["meter_count"] += 1
        else:
            ecoes_row["meter_count"] = 1
            ecoes_mpans[mpan_spaces] = ecoes_row

    titles = (
        "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",
    )
    writer.writerow(titles)

    for mpan_spaces, ecoes in sorted(ecoes_mpans.items()):
        problem = ""
        ignore = True
        diffs = []

        try:
            ecoes_es = ecoes["energisation-status"]
        except KeyError as e:
            raise e

        ecoes_disconnected = ecoes_es == ""
        current_chell = mpan_spaces in mpans

        if ecoes["meter_count"] > 1:
            problem += (
                f"There are {ecoes['meter_count']} meters associated with this MPAN "
                f"core in ECOES, but Chellow only supports one meter per supply at the "
                f"moment. If there really should be multiple meters for this supply, "
                f"let me know and I'll add support for it in Chellow."
            )
            ignore = False

        if ecoes_disconnected and current_chell:
            problem += "Disconnected in ECOES, but current in Chellow. "
            ignore = False

        elif not ecoes_disconnected and not current_chell:
            problem += f"In ECOES (as {ecoes_es}) but disconnected in Chellow. "
            ignore = False

        if current_chell:
            mpans.remove(mpan_spaces)
            era = sess.execute(
                select(Era)
                .filter(
                    Era.finish_date == null(),
                    or_(
                        Era.imp_mpan_core == mpan_spaces,
                        Era.exp_mpan_core == mpan_spaces,
                    ),
                )
                .options(
                    joinedload(Era.supply).joinedload(Supply.gsp_group),
                    joinedload(Era.mop_contract)
                    .joinedload(Contract.party)
                    .joinedload(Party.participant),
                    joinedload(Era.dc_contract)
                    .joinedload(Contract.party)
                    .joinedload(Party.participant),
                    joinedload(Era.imp_supplier_contract)
                    .joinedload(Contract.party)
                    .joinedload(Party.participant),
                    joinedload(Era.exp_supplier_contract)
                    .joinedload(Contract.party)
                    .joinedload(Party.participant),
                    joinedload(Era.pc),
                    joinedload(Era.imp_llfc),
                    joinedload(Era.exp_llfc),
                    joinedload(Era.mtc).joinedload(Mtc.meter_type),
                    joinedload(Era.ssc),
                    joinedload(Era.energisation_status),
                    joinedload(Era.channels),
                )
            ).scalar()
            chellow_supply_id = era.supply.id
            chellow_era_id = era.id
            chellow_es = era.energisation_status.code
            if ecoes_es != chellow_es:
                problem += "The energisation statuses don't match. "
                ignore = False
                diffs.append("es")

            if not (ecoes_es == "D" and chellow_es == "D"):
                if era.imp_mpan_core == mpan_spaces:
                    supplier_contract = era.imp_supplier_contract
                    llfc = era.imp_llfc
                else:
                    supplier_contract = era.exp_supplier_contract
                    llfc = era.exp_llfc

                chellow_pc = era.pc.code
                try:
                    if int(ecoes["pc"]) != int(chellow_pc):
                        problem += "The PCs don't match. "
                        ignore = False
                        diffs.append("pc")
                except ValueError:
                    problem += "Can't parse the PC. "
                    ignore = False

                chellow_mtc = era.mtc.code
                try:
                    if int(ecoes["mtc"]) != int(chellow_mtc):
                        problem += "The MTCs don't match. "
                        ignore = False
                        diffs.append("mtc")
                except ValueError:
                    problem += "Can't parse the MTC. "
                    ignore = False

                chellow_llfc = llfc.code
                if ecoes["llfc"].zfill(3) != chellow_llfc:
                    problem += "The LLFCs don't match. "
                    ignore = False
                    diffs.append("llfc")

                chellow_ssc = era.ssc
                if chellow_ssc is None:
                    chellow_ssc = ""
                    chellow_ssc_int = None
                else:
                    chellow_ssc = chellow_ssc.code
                    chellow_ssc_int = int(chellow_ssc)

                if len(ecoes["ssc"]) > 0:
                    ecoes_ssc_int = int(ecoes["ssc"])
                else:
                    ecoes_ssc_int = None

                if ecoes_ssc_int != chellow_ssc_int and not (
                    ecoes_ssc_int is None and chellow_ssc_int is None
                ):
                    problem += "The SSCs don't match. "
                    ignore = False
                    diffs.append("ssc")

                chellow_supplier = supplier_contract.party.participant.code
                chellow_supplier_contract_name = supplier_contract.name
                chellow_supplier_contract_id = supplier_contract.id
                if chellow_supplier != ecoes["supplier"]:
                    problem += "The supplier codes don't match. "
                    ignore = False
                    diffs.append("supplier")

                dc_contract = era.dc_contract
                if dc_contract is None:
                    chellow_dc = ""
                else:
                    chellow_dc = dc_contract.party.participant.code

                if chellow_dc != ecoes["dc"]:
                    problem += "The DC codes don't match. "
                    ignore = False
                    diffs.append("dc")

                mop_contract = era.mop_contract
                if mop_contract is None:
                    chellow_mop = ""
                else:
                    chellow_mop = mop_contract.party.participant.code

                if chellow_mop != ecoes["mop"]:
                    problem += "The MOP codes don't match. "
                    ignore = False
                    diffs.append("mop")

                chellow_gsp_group = era.supply.gsp_group.code
                if chellow_gsp_group != ecoes["gsp-group"]:
                    problem += "The GSP group codes don't match. "
                    ignore = False
                    diffs.append("gsp_group")

                chellow_msn = era.msn
                if chellow_msn is None:
                    chellow_msn = ""

                if chellow_msn != ecoes["msn"]:
                    problem += "The meter serial numbers don't match. "
                    diffs.append("msn")
                    if mpan_spaces not in ignore_mpan_cores_msn:
                        ignore = False
                elif mpan_spaces in ignore_mpan_cores_msn:
                    problem += (
                        "This MPAN core is in mpan_cores_ignore and yet the meter "
                        "serial numbers do match. "
                    )

                chellow_meter_type = _meter_type(era)

                if chellow_meter_type != ecoes["meter-type"]:
                    problem += (
                        "The meter types don't match. See "
                        "https://dtc.mrasco.com/DataItem.aspx?ItemCounter=0483 "
                    )
                    ignore = False
                    diffs.append("meter_type")
        else:
            chellow_pc = ""
            chellow_mtc = ""
            chellow_llfc = ""
            chellow_ssc = ""
            chellow_es = ""
            chellow_supplier = ""
            chellow_supplier_contract_name = ""
            chellow_supplier_contract_id = None
            chellow_dc = ""
            chellow_mop = ""
            chellow_gsp_group = ""
            chellow_msn = ""
            chellow_meter_type = ""
            chellow_supply_id = None
            chellow_era_id = None

        if len(problem) > 0 and not (not show_ignored and ignore):
            values = {
                "mpan_core": mpan_spaces,
                "mpan_core_no_spaces": ecoes["mpan-core"],
                "ecoes_pc": ecoes["pc"],
                "chellow_pc": chellow_pc,
                "ecoes_mtc": ecoes["mtc"],
                "chellow_mtc": chellow_mtc,
                "chellow_mtc_date": ecoes["mtc-date"],
                "ecoes_llfc": ecoes["llfc"],
                "ecoes_llfc_from": ecoes["llfc-from"],
                "chellow_llfc": chellow_llfc,
                "ecoes_ssc": ecoes["ssc"],
                "chellow_ssc": chellow_ssc,
                "ecoes_es": ecoes["energisation-status"],
                "chellow_es": chellow_es,
                "ecoes_supplier": ecoes["supplier"],
                "ecoes_supplier_registration_from": ecoes["registration-from"],
                "chellow_supplier": chellow_supplier,
                "chellow_supplier_contract_name": chellow_supplier_contract_name,
                "ecoes_dc": ecoes["dc"],
                "chellow_dc": chellow_dc,
                "ecoes_mop": ecoes["mop"],
                "ecoes_mop_appoint_date": ecoes["mop-appoint-date"],
                "chellow_mop": chellow_mop,
                "ecoes_gsp_group": ecoes["gsp-group"],
                "ecoes_gsp_effective_from": ecoes["gsp-effective-from"],
                "chellow_gsp_group": chellow_gsp_group,
                "ecoes_msn": ecoes["msn"],
                "chellow_msn": chellow_msn,
                "ecoes_msn_install_date": ecoes["meter-install-date"],
                "ecoes_meter_type": ecoes["meter-type"],
                "chellow_meter_type": chellow_meter_type,
                "ignored": ignore,
                "problem": problem,
            }
            writer.writerow(values[t] for t in titles)
            values["chellow_supplier_contract_id"] = chellow_supplier_contract_id
            values["chellow_supply_id"] = chellow_supply_id
            values["diffs"] = diffs
            values["chellow_era_id"] = chellow_era_id
            report_run.insert_row(sess, "", titles, values, {})
            sess.commit()
        sess.expunge_all()

    for mpan_core in mpans:
        supply = Supply.get_by_mpan_core(sess, mpan_core)
        era = supply.find_era_at(sess, None)
        if era.imp_mpan_core == mpan_core:
            supplier_contract = era.imp_supplier_contract
            llfc = era.imp_llfc
        else:
            supplier_contract = era.exp_supplier_contract
            llfc = era.exp_llfc

        ssc = "" if era.ssc is None else era.ssc.code

        es = era.energisation_status.code

        dc_contract = era.dc_contract
        dc = "" if dc_contract is None else dc_contract.party.participant.code

        mop_contract = era.mop_contract
        mop = "" if mop_contract is None else mop_contract.party.participant.code

        msn = "" if era.msn is None else era.msn

        meter_type = _meter_type(era)

        values = {
            "mpan_core": mpan_core,
            "mpan_core_no_spaces": mpan_core.replace(" ", ""),
            "ecoes_pc": "",
            "chellow_pc": era.pc.code,
            "ecoes_mtc": "",
            "chellow_mtc": era.mtc.code,
            "ecoes_llfc": "",
            "chellow_llfc": llfc.code,
            "ecoes_ssc": "",
            "chellow_ssc": ssc,
            "ecoes_es": "",
            "chellow_es": es,
            "ecoes_supplier": "",
            "chellow_supplier": supplier_contract.party.participant.code,
            "chellow_supplier_contract_name": supplier_contract.name,
            "ecoes_dc": "",
            "chellow_dc": dc,
            "ecoes_mop": "",
            "chellow_mop": mop,
            "ecoes_gsp_group": "",
            "chellow_gsp_group": supply.gsp_group.code,
            "ecoes_msn": "",
            "chellow_msn": msn,
            "ecoes_msn_install_date": "",
            "ecoes_meter_type": "",
            "chellow_meter_type": meter_type,
            "ignored": False,
            "problem": "In Chellow, but not in ECOES.",
        }
        writer.writerow(values[t] for t in titles)
        values["chellow_supplier_contract_id"] = supplier_contract.id
        values["chellow_supply_id"] = era.supply.id
        values["diffs"] = []
        values["chellow_era_id"] = era.id
        report_run.insert_row(sess, "", titles, values, {})
Ejemplo n.º 5
0
def content(user):
    sess = None
    try:
        sess = Session()
        running_name, finished_name = chellow.dloads.make_names(
            "ecoes_comparison.csv", user)
        f = open(running_name, mode="w", newline="")
        writer = csv.writer(f, lineterminator="\n")

        props = Contract.get_non_core_by_name(
            sess, "configuration").make_properties()

        ECOES_KEY = "ecoes"
        try:
            ecoes_props = props[ECOES_KEY]
        except KeyError:
            raise BadRequest(
                f"The property {ECOES_KEY} cannot be found in the configuration "
                f"properties.")

        for key in ("user_name", "password", "prefix", "ignore_mpan_cores"):
            try:
                ecoes_props[key]
            except KeyError:
                raise BadRequest(
                    f"The property {key} cannot be found in the 'ecoes' section of "
                    f"the configuration properties.")

        ignore_mpan_cores = ecoes_props["ignore_mpan_cores"]

        proxies = props.get("proxies", {})
        s = requests.Session()
        s.verify = False
        r = s.get(ecoes_props["prefix"], proxies=proxies)
        r = s.post(
            ecoes_props["prefix"],
            data={
                "Username": ecoes_props["user_name"],
                "Password": ecoes_props["password"],
            },
            allow_redirects=False,
        )

        imp_mpans = [
            v.imp_mpan_core for (v, ) in sess.execute(
                select(Era).join(Supply).join(Source).join(Supply.dno).filter(
                    Party.dno_code.notin_(("88", "99")),
                    Era.finish_date == null(),
                    Source.code != "3rd-party",
                    Era.imp_mpan_core.notin_(ignore_mpan_cores),
                    Era.imp_mpan_core != null(),
                ).distinct().order_by(Era.imp_mpan_core))
        ]
        exp_mpans = [
            v.exp_mpan_core for (v, ) in sess.execute(
                select(Era).join(Supply).join(Source).join(Supply.dno).filter(
                    Party.dno_code.notin_(("88", "99")),
                    Era.finish_date == null(),
                    Source.code != "3rd-party",
                    Era.exp_mpan_core != null(),
                    Era.exp_mpan_core.notin_(ignore_mpan_cores),
                ).distinct().order_by(Era.exp_mpan_core))
        ]
        mpans = imp_mpans + exp_mpans

        r = s.get(
            ecoes_props["prefix"] +
            "NonDomesticCustomer/ExportPortfolioMPANs?fileType=csv",
            proxies=proxies,
        )

        titles = (
            "MPAN Core",
            "MPAN Core No Spaces",
            "ECOES PC",
            "Chellow PC",
            "ECOES MTC",
            "Chellow MTC",
            "ECOES LLFC",
            "Chellow LLFC",
            "ECOES SSC",
            "Chellow SSC",
            "ECOES Energisation Status",
            "Chellow Energisation Status",
            "ECOES Supplier",
            "Chellow Supplier",
            "ECOES DC",
            "Chellow DC",
            "ECOES MOP",
            "Chellow MOP",
            "ECOES GSP Group",
            "Chellow GSP Group",
            "ECOES MSN",
            "Chellow MSN",
            "ECOES Meter Type",
            "Chellow Meter Type",
            "Problem",
        )
        writer.writerow(titles)

        parser = iter(csv.reader(r.text.splitlines(True)))
        next(parser)  # Skip titles

        for values in parser:
            problem = ""

            ecoes_titles = [
                "mpan-core",
                "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",
                "ssc",
                "measurement-class",
                "energisation-status",
                "da",
                "dc",
                "mop",
                "mop-appoint-date",
                "gsp-group",
                "gsp-effective-from",
                "dno",
                "msn",
                "meter-install-date",
                "meter-type",
                "map-id",
            ]

            ecoes = dict(zip(ecoes_titles, map(str.strip, values)))

            mpan_spaces = " ".join((
                ecoes["mpan-core"][:2],
                ecoes["mpan-core"][2:6],
                ecoes["mpan-core"][6:10],
                ecoes["mpan-core"][-3:],
            ))
            if mpan_spaces in ignore_mpan_cores:
                continue

            try:
                ecoes_es = ecoes["energisation-status"]
            except KeyError as e:
                print(r.text)
                raise e

            ecoes_disconnected = ecoes_es == ""
            current_chell = mpan_spaces in mpans

            if ecoes_disconnected and current_chell:
                problem += "Disconnected in ECOES, but current in Chellow. "
            elif not ecoes_disconnected and not current_chell:
                problem += f"In ECOES (as {ecoes_es}) but disconnected in Chellow. "

            if current_chell:
                mpans.remove(mpan_spaces)
                era = sess.execute(
                    select(Era).filter(
                        Era.finish_date == null(),
                        or_(
                            Era.imp_mpan_core == mpan_spaces,
                            Era.exp_mpan_core == mpan_spaces,
                        ),
                    ).options(
                        joinedload(Era.supply).joinedload(Supply.gsp_group),
                        joinedload(Era.mop_contract).joinedload(
                            Contract.party).joinedload(Party.participant),
                        joinedload(Era.dc_contract).joinedload(
                            Contract.party).joinedload(Party.participant),
                        joinedload(Era.imp_supplier_contract).joinedload(
                            Contract.party).joinedload(Party.participant),
                        joinedload(Era.exp_supplier_contract).joinedload(
                            Contract.party).joinedload(Party.participant),
                        joinedload(Era.pc),
                        joinedload(Era.imp_llfc),
                        joinedload(Era.exp_llfc),
                        joinedload(Era.mtc).joinedload(Mtc.meter_type),
                        joinedload(Era.ssc),
                        joinedload(Era.energisation_status),
                        joinedload(Era.channels),
                    )).scalar()

                if era.imp_mpan_core == mpan_spaces:
                    supplier_contract = era.imp_supplier_contract
                    llfc = era.imp_llfc
                else:
                    supplier_contract = era.exp_supplier_contract
                    llfc = era.exp_llfc

                chellow_pc = era.pc.code
                try:
                    if int(ecoes["pc"]) != int(chellow_pc):
                        problem += "The PCs don't match. "
                except ValueError:
                    problem += "Can't parse the PC. "

                chellow_mtc = era.mtc.code
                try:
                    if int(ecoes["mtc"]) != int(chellow_mtc):
                        problem += "The MTCs don't match. "
                except ValueError:
                    problem += "Can't parse the MTC. "

                chellow_llfc = llfc.code
                if ecoes["llfc"].zfill(3) != chellow_llfc:
                    problem += "The LLFCs don't match. "

                chellow_ssc = era.ssc
                if chellow_ssc is None:
                    chellow_ssc = ""
                    chellow_ssc_int = None
                else:
                    chellow_ssc = chellow_ssc.code
                    chellow_ssc_int = int(chellow_ssc)

                if len(ecoes["ssc"]) > 0:
                    ecoes_ssc_int = int(ecoes["ssc"])
                else:
                    ecoes_ssc_int = None

                if ecoes_ssc_int != chellow_ssc_int and not (
                        ecoes_ssc_int is None and chellow_ssc_int is None):
                    problem += "The SSCs don't match. "

                chellow_es = era.energisation_status.code
                if ecoes_es != chellow_es:
                    problem += "The energisation statuses don't match. "

                chellow_supplier = supplier_contract.party.participant.code
                if chellow_supplier != ecoes["supplier"]:
                    problem += "The supplier codes don't match. "

                dc_contract = era.dc_contract
                if dc_contract is None:
                    chellow_dc = ""
                else:
                    chellow_dc = dc_contract.party.participant.code

                if chellow_dc != ecoes["dc"]:
                    problem += "The DC codes don't match. "

                mop_contract = era.mop_contract
                if mop_contract is None:
                    chellow_mop = ""
                else:
                    chellow_mop = mop_contract.party.participant.code

                if chellow_mop != ecoes["mop"]:
                    problem += "The MOP codes don't match. "

                chellow_gsp_group = era.supply.gsp_group.code
                if chellow_gsp_group != ecoes["gsp-group"]:
                    problem += "The GSP group codes don't match. "

                chellow_msn = era.msn
                if chellow_msn is None:
                    chellow_msn = ""
                if chellow_msn != ecoes["msn"]:
                    problem += "The meter serial numbers don't match. "

                chellow_meter_type = _meter_type(era)

                if chellow_meter_type != ecoes["meter-type"]:
                    problem += (
                        "The meter types don't match. See "
                        "https://dtc.mrasco.com/DataItem.aspx?ItemCounter=0483 "
                    )
            else:
                chellow_pc = ""
                chellow_mtc = ""
                chellow_llfc = ""
                chellow_ssc = ""
                chellow_es = ""
                chellow_supplier = ""
                chellow_dc = ""
                chellow_mop = ""
                chellow_gsp_group = ""
                chellow_msn = ""
                chellow_meter_type = ""

            if len(problem) > 0:
                writer.writerow([
                    mpan_spaces,
                    ecoes["mpan-core"],
                    ecoes["pc"],
                    chellow_pc,
                    ecoes["mtc"],
                    chellow_mtc,
                    ecoes["llfc"],
                    chellow_llfc,
                    ecoes["ssc"],
                    chellow_ssc,
                    ecoes["energisation-status"],
                    chellow_es,
                    ecoes["supplier"],
                    chellow_supplier,
                    ecoes["dc"],
                    chellow_dc,
                    ecoes["mop"],
                    chellow_mop,
                    ecoes["gsp-group"],
                    chellow_gsp_group,
                    ecoes["msn"],
                    chellow_msn,
                    ecoes["meter-type"],
                    chellow_meter_type,
                    problem,
                ])
            sess.expunge_all()

        for mpan_core in mpans:
            supply = Supply.get_by_mpan_core(sess, mpan_core)
            era = supply.find_era_at(sess, None)
            if era.imp_mpan_core == mpan_core:
                supplier_contract = era.imp_supplier_contract
                llfc = era.imp_llfc
            else:
                supplier_contract = era.exp_supplier_contract
                llfc = era.exp_llfc

            ssc = "" if era.ssc is None else era.ssc.code

            es = era.energisation_status.code

            dc_contract = era.dc_contract
            if dc_contract is None:
                dc = ""
            else:
                dc = dc_contract.party.participant.code

            mop_contract = era.mop_contract
            if mop_contract is None:
                mop = ""
            else:
                mop = mop_contract.party.participant.code

            msn = "" if era.msn is None else era.msn

            meter_type = _meter_type(era)

            writer.writerow([
                mpan_core,
                mpan_core.replace(" ", ""),
                "",
                era.pc.code,
                "",
                era.mtc.code,
                "",
                llfc.code,
                "",
                ssc,
                "",
                es,
                "",
                supplier_contract.party.participant.code,
                "",
                dc,
                "",
                mop,
                "",
                supply.gsp_group.code,
                "",
                msn,
                "",
                meter_type,
                "In Chellow, but not in ECOES.",
            ])
    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)
Ejemplo n.º 6
0
def _process_VAT(rows, headers):
    sess = headers["sess"]
    mpan_core = headers["mpan_core"]
    start_date = headers["start_date"]
    reads = headers["reads"]
    supply = Supply.get_by_mpan_core(sess, mpan_core)
    era = supply.find_era_at(sess, start_date)
    bill_elements = []
    if era is None:
        era = supply.find_last_era(sess)
    if era is not None and era.ssc is not None:
        try:
            ssc_lookup = era.imp_mpan_core
            tpr_map = SSC_MAP[ssc_lookup]
        except KeyError:
            ssc_lookup = era.ssc.code
            try:
                tpr_map = SSC_MAP[ssc_lookup]
            except KeyError:
                raise BadRequest("The SSC " + ssc_lookup +
                                 " isn't in the SSC_MAP.")

        for read in reads:
            desc = read["tpr_code"]
            try:
                read["tpr_code"] = tpr_map[desc]
            except KeyError:
                raise BadRequest("The description " + desc +
                                 " isn't in the SSC_MAP "
                                 "for the SSC " + ssc_lookup + ".")

        for el in headers["bill_elements"]:
            if el.titles is None:
                try:
                    tpr = tpr_map[el.desc]
                except KeyError:
                    raise BadRequest(
                        f"The billing element description {el.desc} isn't in "
                        f"the SSC_MAP for the SSC {ssc_lookup}.")

                titles = (tpr + "-gbp", tpr + "-rate", tpr + "-kwh")
            else:
                titles = el.titles

            bill_elements.append(
                BillElement(gbp=el.gbp,
                            titles=titles,
                            rate=el.rate,
                            cons=el.cons,
                            desc=None))
    else:
        for read in reads:
            read["tpr_code"] = "00001"

        for el in headers["bill_elements"]:
            if el.titles is None:
                des = el.desc
                titles = (des + "-kwh", des + "-rate", des + "-gbp")
            else:
                titles = el.titles

            bill_elements.append(
                BillElement(gbp=el.gbp,
                            titles=titles,
                            rate=el.rate,
                            cons=el.cons,
                            desc=None))

    breakdown = headers["breakdown"]
    for bill_el in bill_elements:
        eln_gbp, eln_rate, eln_cons = bill_el.titles
        breakdown[eln_gbp] = bill_el.gbp
        rate = bill_el.rate
        if eln_rate is not None and rate is not None:
            try:
                rates = breakdown[eln_rate]
            except KeyError:
                rates = breakdown[eln_rate] = set()

            rates.add(rate)

        cons = bill_el.cons
        if eln_cons is not None and cons is not None:
            breakdown[eln_cons] = cons

    return {
        "kwh": headers["kwh"],
        "reference": headers["reference"],
        "mpan_core": mpan_core,
        "issue_date": headers["issue_date"],
        "account": headers["account"],
        "start_date": start_date,
        "finish_date": headers["finish_date"],
        "net": headers["net"],
        "vat": headers["vat"],
        "gross": headers["gross"],
        "breakdown": breakdown,
        "reads": reads,
        "bill_type_code": headers["bill_type_code"],
    }