chellow 1757320031.0.0__py3-none-any.whl → 1759411815.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of chellow might be problematic. Click here for more details.
- chellow/e/bill_importer.py +136 -80
- chellow/e/bill_parsers/activity_mop_stark_xlsx.py +99 -86
- chellow/e/bill_parsers/annual_mop_stark_xlsx.py +78 -61
- chellow/e/bill_parsers/csv.py +139 -101
- chellow/e/bill_parsers/drax_edi.py +65 -89
- chellow/e/bill_parsers/engie_edi.py +187 -255
- chellow/e/bill_parsers/engie_xls.py +153 -167
- chellow/e/bill_parsers/haven_edi.py +189 -228
- chellow/e/bill_parsers/haven_edi_tprs.py +67 -67
- chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py +75 -66
- chellow/e/bill_parsers/settlement_dc_stark_xlsx.py +229 -126
- chellow/e/bill_parsers/sse_edi.py +107 -75
- chellow/e/bill_parsers/sww_xls.py +78 -91
- chellow/e/computer.py +1 -1
- chellow/e/views.py +626 -281
- chellow/edi_lib.py +4 -27
- chellow/models.py +92 -3
- chellow/reports/report_111.py +514 -616
- chellow/reports/report_247.py +96 -137
- chellow/templates/e/dc_batch.html +110 -157
- chellow/templates/e/dc_batch_add.html +2 -3
- chellow/templates/e/dc_batch_edit.html +42 -46
- chellow/templates/e/dc_batch_file.html +2 -3
- chellow/templates/e/dc_batch_file_edit.html +28 -40
- chellow/templates/e/dc_batch_upload_file.html +68 -0
- chellow/templates/e/dc_batches.html +2 -1
- chellow/templates/e/dc_batches_edit.html +26 -0
- chellow/templates/e/dc_bill.html +27 -5
- chellow/templates/e/dc_bill_add.html +4 -4
- chellow/templates/e/dc_bill_edit.html +43 -63
- chellow/templates/e/dc_bill_import.html +1 -1
- chellow/templates/e/dc_bill_import_contract.html +130 -0
- chellow/templates/e/dc_contract.html +1 -1
- chellow/templates/e/dc_element.html +41 -0
- chellow/templates/e/dc_element_add.html +36 -0
- chellow/templates/e/dc_element_edit.html +49 -0
- chellow/templates/e/dc_rate_script_edit.html +27 -43
- chellow/templates/e/mop_batch.html +105 -152
- chellow/templates/e/mop_batch_add.html +2 -3
- chellow/templates/e/mop_batch_edit.html +43 -51
- chellow/templates/e/mop_batch_upload_file.html +71 -5
- chellow/templates/e/mop_batches.html +2 -1
- chellow/templates/e/mop_batches_edit.html +26 -0
- chellow/templates/e/mop_bill.html +31 -8
- chellow/templates/e/mop_bill_add.html +7 -27
- chellow/templates/e/mop_bill_import.html +1 -1
- chellow/templates/e/mop_bill_import_contract.html +130 -0
- chellow/templates/e/mop_contract.html +4 -5
- chellow/templates/e/mop_element.html +41 -0
- chellow/templates/e/mop_element_add.html +36 -0
- chellow/templates/e/mop_element_edit.html +49 -0
- chellow/templates/e/supplier_batch.html +3 -7
- chellow/templates/e/supplier_batch_add.html +2 -2
- chellow/templates/e/supplier_batch_edit.html +1 -1
- chellow/templates/e/supplier_batch_file.html +3 -5
- chellow/templates/e/supplier_batch_file_add.html +18 -11
- chellow/templates/e/supplier_batch_upload_file.html +83 -9
- chellow/templates/e/supplier_batches.html +4 -4
- chellow/templates/e/supplier_batches_edit.html +26 -0
- chellow/templates/e/supplier_bill.html +29 -6
- chellow/templates/e/supplier_bill_add.html +3 -3
- chellow/templates/e/supplier_bill_import.html +1 -1
- chellow/templates/e/supplier_bill_import_contract.html +118 -0
- chellow/templates/e/supplier_contract.html +1 -1
- chellow/templates/e/supplier_element.html +45 -0
- chellow/templates/e/supplier_element_add.html +36 -0
- chellow/templates/e/supplier_element_edit.html +51 -0
- chellow/templates/report_run_bill_check.html +137 -179
- chellow/templates/report_run_row_bill_check.html +187 -179
- chellow/views.py +57 -64
- {chellow-1757320031.0.0.dist-info → chellow-1759411815.0.0.dist-info}/METADATA +2 -2
- {chellow-1757320031.0.0.dist-info → chellow-1759411815.0.0.dist-info}/RECORD +73 -60
- chellow/e/bill_parsers/drax_element_edi.py +0 -459
- chellow/templates/e/supplier_bill_imports.html +0 -421
- {chellow-1757320031.0.0.dist-info → chellow-1759411815.0.0.dist-info}/WHEEL +0 -0
chellow/e/bill_parsers/csv.py
CHANGED
|
@@ -28,124 +28,162 @@ def parse_date(row, idx, is_finish=False):
|
|
|
28
28
|
else:
|
|
29
29
|
dt = to_utc(ct_datetime_parse(date_str, "%Y-%m-%d %H:%M"))
|
|
30
30
|
return validate_hh_start(dt)
|
|
31
|
-
except
|
|
31
|
+
except BaseException as e:
|
|
32
32
|
raise BadRequest(
|
|
33
33
|
f"Can't parse the date at column {idx}. The required spreadsheet format is "
|
|
34
34
|
f"'YYYY-MM-DD HH:MM'. {e}"
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def to_decimal(vals, dec_index, dec_name, is_money=False):
|
|
39
|
+
try:
|
|
40
|
+
dec_str = vals[dec_index]
|
|
41
|
+
dec_str = dec_str.replace(",", "")
|
|
42
|
+
dec = Decimal(dec_str)
|
|
43
|
+
if is_money:
|
|
44
|
+
dec += Decimal("0.00")
|
|
45
|
+
dec = round(dec, 2)
|
|
46
|
+
return dec
|
|
47
|
+
except InvalidOperation as e:
|
|
48
|
+
raise BadRequest(
|
|
49
|
+
f"The value '{dec_str}' can't be parsed as a decimal: {e}. It's in "
|
|
50
|
+
f"the '{dec_name}' column at position {dec_index} in {vals}."
|
|
51
|
+
)
|
|
52
|
+
except IndexError:
|
|
53
|
+
raise BadRequest(
|
|
54
|
+
f"The field '{dec_name}' can't be found. It's expected at "
|
|
55
|
+
f"position {dec_index} in the list of fields."
|
|
56
|
+
)
|
|
57
|
+
except ValueError:
|
|
58
|
+
raise BadRequest(
|
|
59
|
+
f"The {dec_name} field '{dec_str}' cannot be parsed as a number. The "
|
|
60
|
+
f"{dec_name} field is the {dec_index} field of {vals}."
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _process_row(vals):
|
|
65
|
+
bill_type_code = vals[0]
|
|
66
|
+
account = vals[1]
|
|
67
|
+
mpan_core = parse_mpan_core(vals[2])
|
|
68
|
+
reference = vals[3]
|
|
69
|
+
issue_date = parse_date(vals, 4)
|
|
70
|
+
start_date = parse_date(vals, 5)
|
|
71
|
+
finish_date = parse_date(vals, 6, True)
|
|
72
|
+
|
|
73
|
+
kwh = to_decimal(vals, 7, "kwh")
|
|
74
|
+
net = to_decimal(vals, 8, "net", is_money=True)
|
|
75
|
+
vat = to_decimal(vals, 9, "vat", is_money=True)
|
|
76
|
+
gross = to_decimal(vals, 10, "gross", is_money=True)
|
|
77
|
+
|
|
78
|
+
if len(vals) > 11:
|
|
79
|
+
breakdown_str = vals[11].strip()
|
|
80
|
+
if len(breakdown_str) == 0:
|
|
81
|
+
breakdown = {}
|
|
82
|
+
else:
|
|
83
|
+
try:
|
|
84
|
+
breakdown = loads(breakdown_str)
|
|
85
|
+
except ZishLocationException as e:
|
|
86
|
+
raise BadRequest(str(e))
|
|
87
|
+
else:
|
|
88
|
+
raise BadRequest("There isn't a 'breakdown' field on the end.")
|
|
89
|
+
|
|
90
|
+
while vals[-1] == "" and len(vals) > 12:
|
|
91
|
+
del vals[-1]
|
|
92
|
+
|
|
93
|
+
reads = []
|
|
94
|
+
elements = []
|
|
95
|
+
i = 12
|
|
96
|
+
while i < len(vals):
|
|
97
|
+
typ = vals[i].strip().lower()
|
|
98
|
+
if typ == "read":
|
|
99
|
+
tpr_str = vals[i + 5].strip()
|
|
100
|
+
tpr_code = None if len(tpr_str) == 0 else tpr_str.zfill(5)
|
|
101
|
+
reads.append(
|
|
102
|
+
{
|
|
103
|
+
"msn": vals[i + 1],
|
|
104
|
+
"mpan": vals[i + 2],
|
|
105
|
+
"coefficient": to_decimal(vals, i + 3, "coefficient"),
|
|
106
|
+
"units": vals[i + 4],
|
|
107
|
+
"tpr_code": tpr_code,
|
|
108
|
+
"prev_date": parse_date(vals, i + 6),
|
|
109
|
+
"prev_value": Decimal(vals[i + 7]),
|
|
110
|
+
"prev_type_code": vals[i + 8],
|
|
111
|
+
"pres_date": parse_date(vals, i + 9),
|
|
112
|
+
"pres_value": Decimal(vals[i + 10]),
|
|
113
|
+
"pres_type_code": vals[i + 11],
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
i += 12
|
|
117
|
+
elif typ == "element":
|
|
118
|
+
breakdown_str = vals[i + 5].strip()
|
|
119
|
+
if len(breakdown_str) == 0:
|
|
120
|
+
breakdown = {}
|
|
121
|
+
else:
|
|
122
|
+
try:
|
|
123
|
+
breakdown = loads(breakdown_str)
|
|
124
|
+
except ZishLocationException as e:
|
|
125
|
+
raise BadRequest(str(e))
|
|
126
|
+
elements.append(
|
|
127
|
+
{
|
|
128
|
+
"name": vals[i + 1],
|
|
129
|
+
"start_date": parse_date(vals, i + 2),
|
|
130
|
+
"finish_date": parse_date(vals, i + 3),
|
|
131
|
+
"net": to_decimal(vals, i + 4, "net", is_money=True),
|
|
132
|
+
"breakdown": breakdown,
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
i += 6
|
|
136
|
+
else:
|
|
137
|
+
raise BadRequest("Record type {type} not recognized.")
|
|
138
|
+
|
|
139
|
+
if len(elements) == 0:
|
|
140
|
+
elements.append(
|
|
141
|
+
{
|
|
142
|
+
"name": "net",
|
|
143
|
+
"start_date": start_date,
|
|
144
|
+
"finish_date": finish_date,
|
|
145
|
+
"net": net,
|
|
146
|
+
"breakdown": {},
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
"bill_type_code": bill_type_code,
|
|
152
|
+
"account": account,
|
|
153
|
+
"mpan_core": mpan_core,
|
|
154
|
+
"reference": reference,
|
|
155
|
+
"issue_date": issue_date,
|
|
156
|
+
"start_date": start_date,
|
|
157
|
+
"finish_date": finish_date,
|
|
158
|
+
"kwh": kwh,
|
|
159
|
+
"net": net,
|
|
160
|
+
"vat": vat,
|
|
161
|
+
"gross": gross,
|
|
162
|
+
"breakdown": breakdown,
|
|
163
|
+
"reads": reads,
|
|
164
|
+
"elements": elements,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
38
168
|
class Parser:
|
|
39
169
|
def __init__(self, f):
|
|
40
170
|
self.reader = csv.reader(
|
|
41
|
-
StringIO(str(f.read(), "utf-8", errors="ignore")), skipinitialspace=True
|
|
171
|
+
StringIO(str(f.read(), "utf-8-sig", errors="ignore")), skipinitialspace=True
|
|
42
172
|
)
|
|
43
173
|
self.line_number = None
|
|
44
174
|
|
|
45
175
|
def make_raw_bills(self):
|
|
46
|
-
raw_bills = []
|
|
47
|
-
next(iter(self.reader)) # skip title row
|
|
48
|
-
blank_set = set(("",))
|
|
49
176
|
for self.line_number, self.vals in enumerate(self.reader, start=2):
|
|
50
177
|
try:
|
|
51
|
-
# skip blank lines
|
|
52
|
-
if
|
|
178
|
+
# skip blank lines and comment lines
|
|
179
|
+
if (
|
|
180
|
+
len(self.vals) == 0
|
|
181
|
+
or set(self.vals) == {""}
|
|
182
|
+
or self.vals[0].strip().startswith("#")
|
|
183
|
+
):
|
|
53
184
|
continue
|
|
54
|
-
|
|
55
|
-
bill_type_code = self.vals[0]
|
|
56
|
-
if bill_type_code.startswith("#"):
|
|
57
|
-
continue # skip comment lines
|
|
58
|
-
account = self.vals[1]
|
|
59
|
-
mpan_core = parse_mpan_core(self.vals[2])
|
|
60
|
-
reference = self.vals[3]
|
|
61
|
-
issue_date = parse_date(self.vals, 4)
|
|
62
|
-
start_date = parse_date(self.vals, 5)
|
|
63
|
-
finish_date = parse_date(self.vals, 6, True)
|
|
64
|
-
|
|
65
|
-
kwh = self.to_decimal(7, "kwh")
|
|
66
|
-
net = self.to_decimal(8, "net", True)
|
|
67
|
-
vat = self.to_decimal(9, "vat", True)
|
|
68
|
-
gross = self.to_decimal(10, "gross", True)
|
|
69
|
-
|
|
70
|
-
if len(self.vals) > 11:
|
|
71
|
-
breakdown_str = self.vals[11].strip()
|
|
72
|
-
if len(breakdown_str) == 0:
|
|
73
|
-
breakdown = {}
|
|
74
|
-
else:
|
|
75
|
-
try:
|
|
76
|
-
breakdown = loads(breakdown_str)
|
|
77
|
-
except ZishLocationException as e:
|
|
78
|
-
raise BadRequest(str(e))
|
|
79
|
-
else:
|
|
80
|
-
raise BadRequest("There isn't a 'breakdown' field on the end.")
|
|
81
|
-
|
|
82
|
-
while self.vals[-1] == "" and len(self.vals) > 12:
|
|
83
|
-
del self.vals[-1]
|
|
84
|
-
|
|
85
|
-
reads = []
|
|
86
|
-
for i in range(12, len(self.vals), 11):
|
|
87
|
-
tpr_str = self.vals[i + 4].strip()
|
|
88
|
-
tpr_code = None if len(tpr_str) == 0 else tpr_str.zfill(5)
|
|
89
|
-
reads.append(
|
|
90
|
-
{
|
|
91
|
-
"msn": self.vals[i],
|
|
92
|
-
"mpan": self.vals[i + 1],
|
|
93
|
-
"coefficient": self.to_decimal(i + 2, "coefficient"),
|
|
94
|
-
"units": self.vals[i + 3],
|
|
95
|
-
"tpr_code": tpr_code,
|
|
96
|
-
"prev_date": parse_date(self.vals, i + 5),
|
|
97
|
-
"prev_value": Decimal(self.vals[i + 6]),
|
|
98
|
-
"prev_type_code": self.vals[i + 7],
|
|
99
|
-
"pres_date": parse_date(self.vals, i + 8),
|
|
100
|
-
"pres_value": Decimal(self.vals[i + 9]),
|
|
101
|
-
"pres_type_code": self.vals[i + 10],
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
raw_bill = {
|
|
106
|
-
"bill_type_code": bill_type_code,
|
|
107
|
-
"account": account,
|
|
108
|
-
"mpan_core": mpan_core,
|
|
109
|
-
"reference": reference,
|
|
110
|
-
"issue_date": issue_date,
|
|
111
|
-
"start_date": start_date,
|
|
112
|
-
"finish_date": finish_date,
|
|
113
|
-
"kwh": kwh,
|
|
114
|
-
"net": net,
|
|
115
|
-
"vat": vat,
|
|
116
|
-
"gross": gross,
|
|
117
|
-
"breakdown": breakdown,
|
|
118
|
-
"reads": reads,
|
|
119
|
-
}
|
|
120
|
-
raw_bills.append(raw_bill)
|
|
185
|
+
yield _process_row(self.vals)
|
|
121
186
|
except BadRequest as e:
|
|
122
187
|
raise BadRequest(
|
|
123
188
|
f"Problem at line {self.line_number} {self.vals}: {e.description}"
|
|
124
189
|
)
|
|
125
|
-
|
|
126
|
-
return raw_bills
|
|
127
|
-
|
|
128
|
-
def to_decimal(self, dec_index, dec_name, is_money=False):
|
|
129
|
-
try:
|
|
130
|
-
dec_str = self.vals[dec_index]
|
|
131
|
-
dec_str = dec_str.replace(",", "")
|
|
132
|
-
dec = Decimal(dec_str)
|
|
133
|
-
if is_money:
|
|
134
|
-
dec += Decimal("0.00")
|
|
135
|
-
return dec
|
|
136
|
-
except InvalidOperation as e:
|
|
137
|
-
raise BadRequest(
|
|
138
|
-
f"The value '{dec_str}' can't be parsed as a decimal: {e}. It's in "
|
|
139
|
-
f"the '{dec_name}' column at position {dec_index} in {self.vals}."
|
|
140
|
-
)
|
|
141
|
-
except IndexError:
|
|
142
|
-
raise BadRequest(
|
|
143
|
-
f"The field '{dec_name}' can't be found. It's expected at "
|
|
144
|
-
f"position {dec_index} in the list of fields."
|
|
145
|
-
)
|
|
146
|
-
except ValueError:
|
|
147
|
-
raise BadRequest(
|
|
148
|
-
f"The {dec_name} field '{dec_str}' cannot be parsed as a "
|
|
149
|
-
f"number. The {dec_name} field is the {dec_index} field of "
|
|
150
|
-
f"{self.vals}."
|
|
151
|
-
)
|
|
@@ -24,132 +24,100 @@ read_type_map = {
|
|
|
24
24
|
ELEMENT_MAP = {
|
|
25
25
|
"AAH": {
|
|
26
26
|
"AAHEDC": {
|
|
27
|
-
"139039": ("aahedc
|
|
27
|
+
"139039": ("aahedc", "rate", "kwh"),
|
|
28
28
|
},
|
|
29
29
|
},
|
|
30
30
|
"ADH": {
|
|
31
31
|
"ADHOC": {
|
|
32
|
-
"020330": ("eii
|
|
33
|
-
"064305": ("fit
|
|
34
|
-
"590346": ("cfd-operational
|
|
35
|
-
"
|
|
36
|
-
"
|
|
32
|
+
"020330": ("eii", None, None),
|
|
33
|
+
"064305": ("fit", None, None),
|
|
34
|
+
"590346": ("cfd-operational", None, None),
|
|
35
|
+
"493988": ("reconciliation", None, None),
|
|
36
|
+
"637050": ("meter-rental", "rate", "days"),
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
"BUS": {
|
|
40
40
|
"BSUOS": {
|
|
41
|
-
"269100": ("bsuos
|
|
41
|
+
"269100": ("bsuos", "rate", "kwh"),
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
"CCL": {
|
|
45
45
|
"CCL": {
|
|
46
|
-
"422733": ("ccl
|
|
46
|
+
"422733": ("ccl", "rate", "kwh"),
|
|
47
47
|
},
|
|
48
48
|
},
|
|
49
49
|
"CFD": {
|
|
50
50
|
"CFD001": {
|
|
51
|
-
"273237": (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
),
|
|
56
|
-
"954379": ("cfd-interim-gbp", "cfd-interim-rate", "cfd-interim-kwh"),
|
|
57
|
-
"538249": (
|
|
58
|
-
"cm-settlement-levy-gbp",
|
|
59
|
-
"cm-settlement-levy-rate",
|
|
60
|
-
"cm-settlement-levy-kwh",
|
|
61
|
-
),
|
|
62
|
-
"568307": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
51
|
+
"273237": ("cfd-operational", "rate", "kwh"),
|
|
52
|
+
"954379": ("cfd-interim", "rate", "kwh"),
|
|
53
|
+
"538249": ("cm-settlement-levy", "rate", "kwh"),
|
|
54
|
+
"568307": ("capacity", "rate", "kwh"),
|
|
63
55
|
},
|
|
64
56
|
},
|
|
65
57
|
"DCA": {
|
|
66
58
|
"DCDA": {
|
|
67
|
-
"095469": ("meter-rental
|
|
59
|
+
"095469": ("meter-rental", "rate", "days"),
|
|
68
60
|
},
|
|
69
61
|
},
|
|
70
62
|
"DUS": {
|
|
71
63
|
"DUS001": {
|
|
72
|
-
"794486": (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
),
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
"duos-reactive-rate",
|
|
81
|
-
"duos-reactive-kvarh",
|
|
82
|
-
),
|
|
83
|
-
"806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
84
|
-
"716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
85
|
-
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
86
|
-
"709522": (
|
|
87
|
-
"duos-excess-availability-gbp",
|
|
88
|
-
"duos-excess-availability-rate",
|
|
89
|
-
"duos-excess-availability-kva",
|
|
90
|
-
),
|
|
91
|
-
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
64
|
+
"794486": ("duos-availability", "rate", "kva"),
|
|
65
|
+
"644819": ("duos-fixed", "rate", "days"),
|
|
66
|
+
"797790": ("duos-reactive", "rate", "kvarh"),
|
|
67
|
+
"806318": ("duos-green", "rate", "kwh"),
|
|
68
|
+
"716514": ("duos-amber", "rate", "kwh"),
|
|
69
|
+
"769979": ("duos-red", "rate", "kwh"),
|
|
70
|
+
"709522": ("duos-excess-availability", "rate", "kva"),
|
|
71
|
+
"209269": ("tnuos", "rate", "days"),
|
|
92
72
|
},
|
|
93
73
|
"DUS002": {
|
|
94
|
-
"185913": ("duos-yellow
|
|
95
|
-
"517270": ("duos-black
|
|
96
|
-
"797790": (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
),
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
|
|
105
|
-
"duos-excess-availability-rate",
|
|
106
|
-
"duos-excess-availability-kva",
|
|
107
|
-
),
|
|
108
|
-
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
109
|
-
"644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
110
|
-
"794486": (
|
|
111
|
-
"duos-availability-gbp",
|
|
112
|
-
"duos-availability-rate",
|
|
113
|
-
"duos-availability-kva",
|
|
114
|
-
),
|
|
115
|
-
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
116
|
-
"065950": ("eii-gbp", "eii-rate", "eii-kwh"),
|
|
74
|
+
"185913": ("duos-yellow", "rate", "kwh"),
|
|
75
|
+
"517270": ("duos-black", "rate", "kwh"),
|
|
76
|
+
"797790": ("duos-reactive", "rate", "kvarh"),
|
|
77
|
+
"806318": ("duos-green", "rate", "kwh"),
|
|
78
|
+
"716514": ("duos-amber", "rate", "kwh"),
|
|
79
|
+
"709522": ("duos-excess-availability", "rate", "kva"),
|
|
80
|
+
"769979": ("duos-red", "rate", "kwh"),
|
|
81
|
+
"644819": ("duos-fixed", "rate", "days"),
|
|
82
|
+
"794486": ("duos-availability", "rate", "kva"),
|
|
83
|
+
"209269": ("tnuos", "rate", "days"),
|
|
84
|
+
"065950": ("eii", "rate", "kwh"),
|
|
117
85
|
},
|
|
118
86
|
"DUSDIS": {
|
|
119
|
-
"122568": ("nrg-gsp-losses
|
|
87
|
+
"122568": ("nrg-gsp-losses", "rate", "kwh"),
|
|
120
88
|
},
|
|
121
89
|
"DUSTRN": {
|
|
122
|
-
"122568": ("nrg-nbp-losses
|
|
90
|
+
"122568": ("nrg-nbp-losses", "rate", "kwh"),
|
|
123
91
|
},
|
|
124
92
|
},
|
|
125
93
|
"ELX": {
|
|
126
94
|
"ELEXON": {
|
|
127
|
-
"489920": ("elexon
|
|
95
|
+
"489920": ("elexon", "rate", "kwh"),
|
|
128
96
|
},
|
|
129
97
|
},
|
|
130
98
|
"FIT": {
|
|
131
99
|
"FIT_LV": {
|
|
132
|
-
"704107": ("fit
|
|
100
|
+
"704107": ("fit", "rate", "kwh"),
|
|
133
101
|
},
|
|
134
102
|
},
|
|
135
103
|
"NRG": {
|
|
136
104
|
"HH0002": {
|
|
137
|
-
"033667": ("management
|
|
138
|
-
"091890": ("shape
|
|
139
|
-
"122568": ("nrg-msp
|
|
105
|
+
"033667": ("management", "rate", "kwh"),
|
|
106
|
+
"091890": ("shape", "rate", "kwh"),
|
|
107
|
+
"122568": ("nrg-msp", "rate", "kwh"),
|
|
140
108
|
},
|
|
141
109
|
},
|
|
142
110
|
"REN": {
|
|
143
111
|
"REN001": {
|
|
144
|
-
"229128": ("ro
|
|
112
|
+
"229128": ("ro", "rate", "kwh"),
|
|
145
113
|
},
|
|
146
114
|
"REN002": {
|
|
147
|
-
"019090": ("rego
|
|
115
|
+
"019090": ("rego", "rate", "kwh"),
|
|
148
116
|
},
|
|
149
117
|
},
|
|
150
118
|
"TUS": {
|
|
151
119
|
"TNUOS": {
|
|
152
|
-
"012069": ("triad
|
|
120
|
+
"012069": ("triad", "rate", "kw"),
|
|
153
121
|
},
|
|
154
122
|
},
|
|
155
123
|
}
|
|
@@ -174,6 +142,7 @@ def _process_BCD(elements, headers):
|
|
|
174
142
|
headers["issue_date"] = issue_date
|
|
175
143
|
headers["bill_type_code"] = bill_type_code
|
|
176
144
|
headers["reference"] = reference
|
|
145
|
+
headers["elements"] = []
|
|
177
146
|
|
|
178
147
|
|
|
179
148
|
def _process_BTL(elements, headers):
|
|
@@ -195,6 +164,7 @@ def _process_BTL(elements, headers):
|
|
|
195
164
|
"gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
|
|
196
165
|
"breakdown": headers["breakdown"],
|
|
197
166
|
"reads": headers["reads"],
|
|
167
|
+
"elements": headers["elements"],
|
|
198
168
|
}
|
|
199
169
|
|
|
200
170
|
|
|
@@ -312,13 +282,13 @@ def _process_CCD2(elements, headers):
|
|
|
312
282
|
|
|
313
283
|
|
|
314
284
|
def _process_CCD3(elements, headers):
|
|
315
|
-
|
|
285
|
+
elem_bd = {}
|
|
316
286
|
|
|
317
287
|
supplier_code = elements["CCDE"][2]
|
|
318
288
|
tariff_code = elements["TCOD"][0]
|
|
319
289
|
mod_code = elements["TMOD"][0]
|
|
320
290
|
try:
|
|
321
|
-
|
|
291
|
+
eln_name, eln_rate, eln_cons = ELEMENT_MAP[supplier_code][tariff_code][mod_code]
|
|
322
292
|
except KeyError:
|
|
323
293
|
raise BadRequest(
|
|
324
294
|
f"Can't find the element key {supplier_code} -> {tariff_code} -> "
|
|
@@ -326,29 +296,35 @@ def _process_CCD3(elements, headers):
|
|
|
326
296
|
)
|
|
327
297
|
|
|
328
298
|
cons = elements["CONS"]
|
|
329
|
-
kwh = Decimal("0")
|
|
330
299
|
if len(cons[0]) > 0:
|
|
331
300
|
el_cons = to_decimal(cons) / Decimal("1000")
|
|
332
|
-
|
|
333
|
-
|
|
301
|
+
elem_bd[eln_cons] = el_cons
|
|
302
|
+
if eln_name == "nrg-msp":
|
|
303
|
+
headers["kwh"] += el_cons
|
|
334
304
|
|
|
335
305
|
bpri = elements["BPRI"]
|
|
336
306
|
if len(bpri[0]) > 0:
|
|
337
307
|
rate = to_decimal(bpri) / Decimal("100000")
|
|
338
|
-
|
|
339
|
-
breakdown[eln_rate].add(rate)
|
|
340
|
-
else:
|
|
341
|
-
breakdown[eln_rate] = {rate}
|
|
308
|
+
elem_bd[eln_rate] = {rate}
|
|
342
309
|
|
|
310
|
+
net = Decimal("0.00")
|
|
343
311
|
if "CTOT" in elements:
|
|
344
|
-
net
|
|
345
|
-
else:
|
|
346
|
-
net = Decimal("0.00")
|
|
312
|
+
net += to_decimal(elements["CTOT"]) / Decimal("100")
|
|
347
313
|
|
|
348
|
-
|
|
314
|
+
csdt = elements["CSDT"]
|
|
315
|
+
start_date = to_date(csdt[0])
|
|
316
|
+
cedt = elements["CEDT"]
|
|
317
|
+
finish_date = to_finish_date(cedt[0])
|
|
349
318
|
|
|
350
|
-
|
|
351
|
-
|
|
319
|
+
headers["elements"].append(
|
|
320
|
+
{
|
|
321
|
+
"name": eln_name,
|
|
322
|
+
"start_date": start_date,
|
|
323
|
+
"finish_date": finish_date,
|
|
324
|
+
"net": net,
|
|
325
|
+
"breakdown": elem_bd,
|
|
326
|
+
}
|
|
327
|
+
)
|
|
352
328
|
|
|
353
329
|
|
|
354
330
|
def _process_CCD4(elements, headers):
|