chellow 1755614564.0.0__py3-none-any.whl → 1759155233.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 -88
- 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 +478 -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 +182 -179
- chellow/views.py +55 -65
- {chellow-1755614564.0.0.dist-info → chellow-1759155233.0.0.dist-info}/METADATA +2 -2
- {chellow-1755614564.0.0.dist-info → chellow-1759155233.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-1755614564.0.0.dist-info → chellow-1759155233.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,131 +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
|
-
"
|
|
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"),
|
|
36
37
|
},
|
|
37
38
|
},
|
|
38
39
|
"BUS": {
|
|
39
40
|
"BSUOS": {
|
|
40
|
-
"269100": ("bsuos
|
|
41
|
+
"269100": ("bsuos", "rate", "kwh"),
|
|
41
42
|
},
|
|
42
43
|
},
|
|
43
44
|
"CCL": {
|
|
44
45
|
"CCL": {
|
|
45
|
-
"422733": ("ccl
|
|
46
|
+
"422733": ("ccl", "rate", "kwh"),
|
|
46
47
|
},
|
|
47
48
|
},
|
|
48
49
|
"CFD": {
|
|
49
50
|
"CFD001": {
|
|
50
|
-
"273237": (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
),
|
|
55
|
-
"954379": ("cfd-interim-gbp", "cfd-interim-rate", "cfd-interim-kwh"),
|
|
56
|
-
"538249": (
|
|
57
|
-
"cm-settlement-levy-gbp",
|
|
58
|
-
"cm-settlement-levy-rate",
|
|
59
|
-
"cm-settlement-levy-kwh",
|
|
60
|
-
),
|
|
61
|
-
"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"),
|
|
62
55
|
},
|
|
63
56
|
},
|
|
64
57
|
"DCA": {
|
|
65
58
|
"DCDA": {
|
|
66
|
-
"095469": ("meter-rental
|
|
59
|
+
"095469": ("meter-rental", "rate", "days"),
|
|
67
60
|
},
|
|
68
61
|
},
|
|
69
62
|
"DUS": {
|
|
70
63
|
"DUS001": {
|
|
71
|
-
"794486": (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
),
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
"duos-reactive-rate",
|
|
80
|
-
"duos-reactive-kvarh",
|
|
81
|
-
),
|
|
82
|
-
"806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
83
|
-
"716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
84
|
-
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
85
|
-
"709522": (
|
|
86
|
-
"duos-excess-availability-gbp",
|
|
87
|
-
"duos-excess-availability-rate",
|
|
88
|
-
"duos-excess-availability-kva",
|
|
89
|
-
),
|
|
90
|
-
"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"),
|
|
91
72
|
},
|
|
92
73
|
"DUS002": {
|
|
93
|
-
"185913": ("duos-yellow
|
|
94
|
-
"517270": ("duos-black
|
|
95
|
-
"797790": (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
),
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
"duos-excess-availability-rate",
|
|
105
|
-
"duos-excess-availability-kva",
|
|
106
|
-
),
|
|
107
|
-
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
108
|
-
"644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
109
|
-
"794486": (
|
|
110
|
-
"duos-availability-gbp",
|
|
111
|
-
"duos-availability-rate",
|
|
112
|
-
"duos-availability-kva",
|
|
113
|
-
),
|
|
114
|
-
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
115
|
-
"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"),
|
|
116
85
|
},
|
|
117
86
|
"DUSDIS": {
|
|
118
|
-
"122568": ("nrg-gsp-losses
|
|
87
|
+
"122568": ("nrg-gsp-losses", "rate", "kwh"),
|
|
119
88
|
},
|
|
120
89
|
"DUSTRN": {
|
|
121
|
-
"122568": ("nrg-nbp-losses
|
|
90
|
+
"122568": ("nrg-nbp-losses", "rate", "kwh"),
|
|
122
91
|
},
|
|
123
92
|
},
|
|
124
93
|
"ELX": {
|
|
125
94
|
"ELEXON": {
|
|
126
|
-
"489920": ("elexon
|
|
95
|
+
"489920": ("elexon", "rate", "kwh"),
|
|
127
96
|
},
|
|
128
97
|
},
|
|
129
98
|
"FIT": {
|
|
130
99
|
"FIT_LV": {
|
|
131
|
-
"704107": ("fit
|
|
100
|
+
"704107": ("fit", "rate", "kwh"),
|
|
132
101
|
},
|
|
133
102
|
},
|
|
134
103
|
"NRG": {
|
|
135
104
|
"HH0002": {
|
|
136
|
-
"033667": ("management
|
|
137
|
-
"091890": ("shape
|
|
138
|
-
"122568": ("nrg-msp
|
|
105
|
+
"033667": ("management", "rate", "kwh"),
|
|
106
|
+
"091890": ("shape", "rate", "kwh"),
|
|
107
|
+
"122568": ("nrg-msp", "rate", "kwh"),
|
|
139
108
|
},
|
|
140
109
|
},
|
|
141
110
|
"REN": {
|
|
142
111
|
"REN001": {
|
|
143
|
-
"229128": ("ro
|
|
112
|
+
"229128": ("ro", "rate", "kwh"),
|
|
144
113
|
},
|
|
145
114
|
"REN002": {
|
|
146
|
-
"019090": ("rego
|
|
115
|
+
"019090": ("rego", "rate", "kwh"),
|
|
147
116
|
},
|
|
148
117
|
},
|
|
149
118
|
"TUS": {
|
|
150
119
|
"TNUOS": {
|
|
151
|
-
"012069": ("triad
|
|
120
|
+
"012069": ("triad", "rate", "kw"),
|
|
152
121
|
},
|
|
153
122
|
},
|
|
154
123
|
}
|
|
@@ -173,6 +142,7 @@ def _process_BCD(elements, headers):
|
|
|
173
142
|
headers["issue_date"] = issue_date
|
|
174
143
|
headers["bill_type_code"] = bill_type_code
|
|
175
144
|
headers["reference"] = reference
|
|
145
|
+
headers["elements"] = []
|
|
176
146
|
|
|
177
147
|
|
|
178
148
|
def _process_BTL(elements, headers):
|
|
@@ -194,6 +164,7 @@ def _process_BTL(elements, headers):
|
|
|
194
164
|
"gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
|
|
195
165
|
"breakdown": headers["breakdown"],
|
|
196
166
|
"reads": headers["reads"],
|
|
167
|
+
"elements": headers["elements"],
|
|
197
168
|
}
|
|
198
169
|
|
|
199
170
|
|
|
@@ -311,13 +282,13 @@ def _process_CCD2(elements, headers):
|
|
|
311
282
|
|
|
312
283
|
|
|
313
284
|
def _process_CCD3(elements, headers):
|
|
314
|
-
|
|
285
|
+
elem_bd = {}
|
|
315
286
|
|
|
316
287
|
supplier_code = elements["CCDE"][2]
|
|
317
288
|
tariff_code = elements["TCOD"][0]
|
|
318
289
|
mod_code = elements["TMOD"][0]
|
|
319
290
|
try:
|
|
320
|
-
|
|
291
|
+
eln_name, eln_rate, eln_cons = ELEMENT_MAP[supplier_code][tariff_code][mod_code]
|
|
321
292
|
except KeyError:
|
|
322
293
|
raise BadRequest(
|
|
323
294
|
f"Can't find the element key {supplier_code} -> {tariff_code} -> "
|
|
@@ -325,29 +296,35 @@ def _process_CCD3(elements, headers):
|
|
|
325
296
|
)
|
|
326
297
|
|
|
327
298
|
cons = elements["CONS"]
|
|
328
|
-
kwh = Decimal("0")
|
|
329
299
|
if len(cons[0]) > 0:
|
|
330
300
|
el_cons = to_decimal(cons) / Decimal("1000")
|
|
331
|
-
|
|
332
|
-
|
|
301
|
+
elem_bd[eln_cons] = el_cons
|
|
302
|
+
if eln_name == "nrg-msp":
|
|
303
|
+
headers["kwh"] += el_cons
|
|
333
304
|
|
|
334
305
|
bpri = elements["BPRI"]
|
|
335
306
|
if len(bpri[0]) > 0:
|
|
336
307
|
rate = to_decimal(bpri) / Decimal("100000")
|
|
337
|
-
|
|
338
|
-
breakdown[eln_rate].add(rate)
|
|
339
|
-
else:
|
|
340
|
-
breakdown[eln_rate] = {rate}
|
|
308
|
+
elem_bd[eln_rate] = {rate}
|
|
341
309
|
|
|
310
|
+
net = Decimal("0.00")
|
|
342
311
|
if "CTOT" in elements:
|
|
343
|
-
net
|
|
344
|
-
else:
|
|
345
|
-
net = Decimal("0.00")
|
|
312
|
+
net += to_decimal(elements["CTOT"]) / Decimal("100")
|
|
346
313
|
|
|
347
|
-
|
|
314
|
+
csdt = elements["CSDT"]
|
|
315
|
+
start_date = to_date(csdt[0])
|
|
316
|
+
cedt = elements["CEDT"]
|
|
317
|
+
finish_date = to_finish_date(cedt[0])
|
|
348
318
|
|
|
349
|
-
|
|
350
|
-
|
|
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
|
+
)
|
|
351
328
|
|
|
352
329
|
|
|
353
330
|
def _process_CCD4(elements, headers):
|