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
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
from collections import defaultdict
|
|
2
1
|
from decimal import Decimal
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
from werkzeug.exceptions import BadRequest
|
|
6
5
|
|
|
7
6
|
from chellow.edi_lib import (
|
|
8
|
-
ct_datetime,
|
|
9
7
|
parse_edi,
|
|
10
8
|
to_date,
|
|
11
9
|
to_decimal,
|
|
12
10
|
to_finish_date,
|
|
13
|
-
to_utc,
|
|
14
11
|
)
|
|
15
|
-
from chellow.utils import HH
|
|
12
|
+
from chellow.utils import HH, parse_mpan_core
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
read_type_map = {
|
|
@@ -30,86 +27,78 @@ read_type_map = {
|
|
|
30
27
|
|
|
31
28
|
|
|
32
29
|
TCOD_MAP = {
|
|
33
|
-
"140114": ("reconciliation
|
|
34
|
-
"255204": ("meter-rental
|
|
35
|
-
"345065": ("op-weekend
|
|
36
|
-
"350293": ("capacity
|
|
37
|
-
"425779": ("ro
|
|
38
|
-
"534342": ("reconciliation
|
|
39
|
-
"583174": ("meter-rental
|
|
40
|
-
"584867": ("aahedc
|
|
41
|
-
"946827": ("meter-rental
|
|
42
|
-
"989534": ("bsuos
|
|
43
|
-
"117220": ("capacity
|
|
44
|
-
"579387": ("capacity
|
|
45
|
-
"558147": ("capacity
|
|
46
|
-
"030025": ("ccl
|
|
47
|
-
"066540": ("ccl
|
|
48
|
-
"154164": ("cfd-fit
|
|
49
|
-
"281170": ("cfd-fit
|
|
50
|
-
"342094": ("cfd-fit
|
|
51
|
-
"378809": ("cfd-fit
|
|
52
|
-
"574015": ("cfd-fit
|
|
53
|
-
"810016": ("cfd-fit
|
|
54
|
-
"839829": ("cfd-fit
|
|
55
|
-
"649282": ("cfd-fit
|
|
56
|
-
"068476": ("day
|
|
57
|
-
"133186": ("nrg
|
|
58
|
-
"400434": ("day
|
|
59
|
-
"219182": (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
),
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
),
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"790618": ("tnuos-gbp", None, None),
|
|
106
|
-
"447769": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
107
|
-
"647721": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
108
|
-
"276631": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
109
|
-
"220894": ("winter-night-gbp", "winter-night-rate", "winter-night-kwh"),
|
|
110
|
-
"264929": ("winter-weekday-gbp", "winter-weekday-rate", "winter-weekday-kwh"),
|
|
111
|
-
"638187": ("winter-weekend-gbp", "winter-weekend-rate", "winter-weekend-kwh"),
|
|
112
|
-
"700285": ("standing-gbp", "standing-rate", "standing-days"),
|
|
30
|
+
"140114": ("reconciliation", None, None),
|
|
31
|
+
"255204": ("meter-rental", "rate", "days"),
|
|
32
|
+
"345065": ("op-weekend", "rate", "kwh"),
|
|
33
|
+
"350293": ("capacity", "rate", "kwh"),
|
|
34
|
+
"425779": ("ro", "rate", "kwh"),
|
|
35
|
+
"534342": ("reconciliation", None, None),
|
|
36
|
+
"583174": ("meter-rental", "rate", "days"),
|
|
37
|
+
"584867": ("aahedc", "rate", "kwh"),
|
|
38
|
+
"946827": ("meter-rental", "rate", "days"),
|
|
39
|
+
"989534": ("bsuos", "rate", "kwh"),
|
|
40
|
+
"117220": ("capacity", "rate", "kwh"),
|
|
41
|
+
"579387": ("capacity", "rate", "kwh"),
|
|
42
|
+
"558147": ("capacity", "rate", "kwh"),
|
|
43
|
+
"030025": ("ccl", "rate", "kwh"),
|
|
44
|
+
"066540": ("ccl", "rate", "kwh"),
|
|
45
|
+
"154164": ("cfd-fit", "rate", "kwh"),
|
|
46
|
+
"281170": ("cfd-fit", "rate", "fit-kwh"),
|
|
47
|
+
"342094": ("cfd-fit", "rate", "kwh"),
|
|
48
|
+
"378809": ("cfd-fit", "rate", "kwh"),
|
|
49
|
+
"574015": ("cfd-fit", "rate", "kwh"),
|
|
50
|
+
"810016": ("cfd-fit", "rate", "kwh"),
|
|
51
|
+
"839829": ("cfd-fit", "rate", "kwh"),
|
|
52
|
+
"649282": ("cfd-fit", "rate", "kwh"),
|
|
53
|
+
"068476": ("day", "rate", "kwh"),
|
|
54
|
+
"133186": ("nrg", "rate", "kwh"),
|
|
55
|
+
"400434": ("day", "rate", "kwh"),
|
|
56
|
+
"219182": ("duos-availability", "rate", "kva"),
|
|
57
|
+
"144424": ("duos-excess-availability", "rate", "kva"),
|
|
58
|
+
"301541": ("duos-fixed", None, None),
|
|
59
|
+
"099335": ("duos-fixed", None, None),
|
|
60
|
+
"873562": ("duos-fixed", None, None),
|
|
61
|
+
"986159": ("duos-fixed", "rate", "days"),
|
|
62
|
+
"838286": ("duos-reactive", "rate", "kvarh"),
|
|
63
|
+
"242643": ("duos-fixed", "rate", "days"),
|
|
64
|
+
"257304": ("duos-amber", "rate", "kwh"),
|
|
65
|
+
"661440": ("duos-amber", "rate", "kwh"),
|
|
66
|
+
"257305": ("duos-green", "rate", "kwh"),
|
|
67
|
+
"661441": ("duos-green", "rate", "kwh"),
|
|
68
|
+
"257303": ("duos-red", "rate", "kwh"),
|
|
69
|
+
"661439": ("duos-red", "rate", "kwh"),
|
|
70
|
+
"504364": ("ebrs", None, "kwh"),
|
|
71
|
+
"563023": ("ebrs", None, "kwh"),
|
|
72
|
+
"823408": ("ebrs", None, "kwh"),
|
|
73
|
+
"871593": ("ebrs", "rate", "kwh"),
|
|
74
|
+
"873894": ("ebrs", "rate", "kwh"),
|
|
75
|
+
"309707": ("fit", "rate", "kwh"),
|
|
76
|
+
"310129": ("meter-rental", None, None),
|
|
77
|
+
"452415": ("meter-rental", None, None),
|
|
78
|
+
"371265": ("meter-rental", None, None),
|
|
79
|
+
"544936": ("meter-rental", "rate", "days"),
|
|
80
|
+
"265091": ("night", "rate", "kwh"),
|
|
81
|
+
"483457": ("peak", "rate", "kwh"),
|
|
82
|
+
"975901": ("peak-shoulder", "rate", "kwh"),
|
|
83
|
+
"994483": ("reconciliation", None, None),
|
|
84
|
+
"637176": ("reconciliation", None, None),
|
|
85
|
+
"913821": ("reconciliation", None, None),
|
|
86
|
+
"307660": ("ro", "rate", "kwh"),
|
|
87
|
+
"364252": ("ro", "rate", "kwh"),
|
|
88
|
+
"378246": ("ro", "rate", "kwh"),
|
|
89
|
+
"708848": ("ro", None, None),
|
|
90
|
+
"632209": ("summer-night", "rate", "kwh"),
|
|
91
|
+
"663682": ("summer-weekday", "rate", "kwh"),
|
|
92
|
+
"299992": ("summer-weekend", "rate", "kwh"),
|
|
93
|
+
"211000": ("tnuos", "rate", "days"),
|
|
94
|
+
"790618": ("tnuos", None, None),
|
|
95
|
+
"447769": ("triad", "rate", "kw"),
|
|
96
|
+
"647721": ("triad", "rate", "kw"),
|
|
97
|
+
"276631": ("triad", "rate", "kw"),
|
|
98
|
+
"220894": ("winter-night", "rate", "kwh"),
|
|
99
|
+
"264929": ("winter-weekday", "rate", "kwh"),
|
|
100
|
+
"638187": ("winter-weekend", "rate", "kwh"),
|
|
101
|
+
"700285": ("standing", "rate", "days"),
|
|
113
102
|
}
|
|
114
103
|
|
|
115
104
|
TPR_LOOKUP = {
|
|
@@ -125,10 +114,40 @@ def _process_BCD(elements, headers):
|
|
|
125
114
|
issue_date = to_date(elements["IVDT"][0])
|
|
126
115
|
reference = elements["INVN"][0]
|
|
127
116
|
bill_type_code = elements["BTCD"][0]
|
|
117
|
+
sumo = elements["SUMO"]
|
|
128
118
|
|
|
129
119
|
headers["issue_date"] = issue_date
|
|
120
|
+
headers["start_date"] = to_date(sumo[0])
|
|
121
|
+
headers["finish_date"] = to_date(sumo[1]) - HH
|
|
130
122
|
headers["bill_type_code"] = bill_type_code
|
|
131
123
|
headers["reference"] = reference
|
|
124
|
+
headers["elements"] = []
|
|
125
|
+
headers["reads"] = []
|
|
126
|
+
headers["breakdown"] = {}
|
|
127
|
+
headers["kwh"] = Decimal("0")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _process_BTL(elements, headers):
|
|
131
|
+
uvlt = elements["UVLT"]
|
|
132
|
+
utva = elements["UTVA"]
|
|
133
|
+
tbtl = elements["TBTL"]
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
"bill_type_code": headers["bill_type_code"],
|
|
137
|
+
"reference": headers["reference"],
|
|
138
|
+
"issue_date": headers["issue_date"],
|
|
139
|
+
"mpan_core": headers["mpan_core"],
|
|
140
|
+
"account": headers["account"],
|
|
141
|
+
"start_date": headers["start_date"],
|
|
142
|
+
"finish_date": headers["finish_date"],
|
|
143
|
+
"kwh": headers["kwh"],
|
|
144
|
+
"net": Decimal("0.00") + to_decimal(uvlt) / Decimal("100"),
|
|
145
|
+
"vat": Decimal("0.00") + to_decimal(utva) / Decimal("100"),
|
|
146
|
+
"gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
|
|
147
|
+
"breakdown": headers["breakdown"],
|
|
148
|
+
"reads": headers["reads"],
|
|
149
|
+
"elements": headers["elements"],
|
|
150
|
+
}
|
|
132
151
|
|
|
133
152
|
|
|
134
153
|
def _process_CCD1(elements, headers):
|
|
@@ -161,12 +180,7 @@ def _process_CCD1(elements, headers):
|
|
|
161
180
|
units = "kWh"
|
|
162
181
|
tpr_code = TPR_LOOKUP[tcod[1]]
|
|
163
182
|
|
|
164
|
-
|
|
165
|
-
reads = headers["reads"]
|
|
166
|
-
except KeyError:
|
|
167
|
-
reads = headers["reads"] = []
|
|
168
|
-
|
|
169
|
-
reads.append(
|
|
183
|
+
headers["reads"].append(
|
|
170
184
|
{
|
|
171
185
|
"msn": msn,
|
|
172
186
|
"mpan": mpan,
|
|
@@ -184,189 +198,112 @@ def _process_CCD1(elements, headers):
|
|
|
184
198
|
|
|
185
199
|
|
|
186
200
|
def _process_CCD2(elements, headers):
|
|
187
|
-
breakdown =
|
|
201
|
+
breakdown = {}
|
|
188
202
|
|
|
189
203
|
element_code = elements["TCOD"][0]
|
|
190
|
-
headers["element_code"] = element_code
|
|
191
204
|
try:
|
|
192
|
-
|
|
205
|
+
eln_name, eln_rate, eln_cons = TCOD_MAP[element_code]
|
|
193
206
|
except KeyError:
|
|
194
207
|
raise BadRequest(f"Can't find the element code {element_code} in the TCOD_MAP.")
|
|
195
208
|
|
|
196
|
-
m = elements["MLOC"][0]
|
|
197
|
-
mpan_core = " ".join((m[:2], m[2:6], m[6:10], m[10:]))
|
|
198
|
-
|
|
199
209
|
cons = elements["CONS"]
|
|
200
|
-
kwh = Decimal("0")
|
|
201
210
|
if eln_cons is not None and len(cons[0]) > 0:
|
|
202
211
|
el_cons = to_decimal(cons) / Decimal("1000")
|
|
203
|
-
if
|
|
204
|
-
breakdown[eln_cons] =
|
|
212
|
+
if eln_name == "duos-availability":
|
|
213
|
+
breakdown[eln_cons] = {el_cons}
|
|
205
214
|
else:
|
|
206
|
-
breakdown[eln_cons] =
|
|
215
|
+
breakdown[eln_cons] = el_cons
|
|
216
|
+
if eln_name == "ro":
|
|
217
|
+
headers["kwh"] += el_cons
|
|
207
218
|
|
|
208
219
|
if eln_rate is not None:
|
|
209
220
|
rate = to_decimal(elements["BPRI"]) / Decimal("100000")
|
|
210
|
-
breakdown[eln_rate] =
|
|
211
|
-
|
|
212
|
-
start_date = to_date(elements["CSDT"][0])
|
|
213
|
-
headers["bill_start_date"] = start_date
|
|
214
|
-
|
|
215
|
-
finish_date = to_date(elements["CEDT"][0]) - HH
|
|
216
|
-
headers["bill_finish_date"] = finish_date
|
|
221
|
+
breakdown[eln_rate] = {rate}
|
|
217
222
|
|
|
223
|
+
net = Decimal("0.00")
|
|
218
224
|
if "CTOT" in elements:
|
|
219
|
-
net
|
|
220
|
-
else:
|
|
221
|
-
net = Decimal("0.00")
|
|
222
|
-
|
|
223
|
-
breakdown[eln_gbp] = net
|
|
224
|
-
|
|
225
|
-
headers["mpan_core"] = mpan_core
|
|
226
|
-
|
|
227
|
-
try:
|
|
228
|
-
reads = headers["reads"]
|
|
229
|
-
headers["reads"] = []
|
|
230
|
-
except KeyError:
|
|
231
|
-
reads = []
|
|
225
|
+
net += to_decimal(elements["CTOT"]) / Decimal("100")
|
|
232
226
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
"net": net,
|
|
243
|
-
"vat": Decimal("0.00"),
|
|
244
|
-
"gross": net,
|
|
245
|
-
"breakdown": breakdown,
|
|
246
|
-
"reads": reads,
|
|
247
|
-
}
|
|
227
|
+
headers["elements"].append(
|
|
228
|
+
{
|
|
229
|
+
"name": eln_name,
|
|
230
|
+
"start_date": to_date(elements["CSDT"][0]),
|
|
231
|
+
"finish_date": to_date(elements["CEDT"][0]) - HH,
|
|
232
|
+
"net": net,
|
|
233
|
+
"breakdown": breakdown,
|
|
234
|
+
}
|
|
235
|
+
)
|
|
248
236
|
|
|
249
237
|
|
|
250
238
|
def _process_CCD3(elements, headers):
|
|
251
|
-
breakdown =
|
|
239
|
+
breakdown = {}
|
|
252
240
|
|
|
253
241
|
element_code = elements["TCOD"][0]
|
|
254
|
-
headers["element_code"] = element_code
|
|
255
242
|
try:
|
|
256
|
-
|
|
243
|
+
eln_name, eln_rate, eln_cons = TCOD_MAP[element_code]
|
|
257
244
|
except KeyError:
|
|
258
245
|
raise BadRequest(f"Can't find the element code {element_code} in the TCOD_MAP.")
|
|
259
246
|
|
|
260
|
-
m = elements["MLOC"][0]
|
|
261
|
-
mpan_core = " ".join((m[:2], m[2:6], m[6:10], m[10:]))
|
|
262
|
-
|
|
263
247
|
cons = elements["CONS"]
|
|
264
248
|
if eln_cons is not None and len(cons[0]) > 0:
|
|
265
249
|
el_cons = to_decimal(cons) / Decimal("1000")
|
|
266
|
-
breakdown[eln_cons] =
|
|
267
|
-
|
|
268
|
-
|
|
250
|
+
breakdown[eln_cons] = el_cons
|
|
251
|
+
if eln_name == "ro":
|
|
252
|
+
headers["kwh"] += el_cons
|
|
269
253
|
|
|
270
254
|
if eln_rate is not None:
|
|
271
255
|
rate = to_decimal(elements["BPRI"]) / Decimal("100000")
|
|
272
|
-
breakdown[eln_rate] =
|
|
273
|
-
|
|
274
|
-
start_date = to_date(elements["CSDT"][0])
|
|
275
|
-
headers["bill_start_date"] = start_date
|
|
276
|
-
|
|
277
|
-
finish_date = to_date(elements["CEDT"][0]) - HH
|
|
278
|
-
headers["bill_finish_date"] = finish_date
|
|
256
|
+
breakdown[eln_rate] = {rate}
|
|
279
257
|
|
|
258
|
+
net = Decimal("0.00")
|
|
280
259
|
if "CTOT" in elements:
|
|
281
|
-
net
|
|
282
|
-
else:
|
|
283
|
-
net = Decimal("0.00")
|
|
284
|
-
|
|
285
|
-
breakdown[eln_gbp] = net
|
|
260
|
+
net += to_decimal(elements["CTOT"]) / Decimal("100")
|
|
286
261
|
|
|
287
|
-
headers["
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
"bill_type_code": headers["bill_type_code"],
|
|
297
|
-
"issue_date": headers["issue_date"],
|
|
298
|
-
"reference": headers["reference"] + "_" + eln_gbp[:-4],
|
|
299
|
-
"mpan_core": mpan_core,
|
|
300
|
-
"account": mpan_core,
|
|
301
|
-
"start_date": start_date,
|
|
302
|
-
"finish_date": finish_date,
|
|
303
|
-
"net": net,
|
|
304
|
-
"kwh": kwh if eln_gbp == "ro-gbp" else Decimal("0"),
|
|
305
|
-
"vat": Decimal("0.00"),
|
|
306
|
-
"gross": net,
|
|
307
|
-
"breakdown": breakdown,
|
|
308
|
-
"reads": reads,
|
|
309
|
-
}
|
|
262
|
+
headers["elements"].append(
|
|
263
|
+
{
|
|
264
|
+
"name": eln_name,
|
|
265
|
+
"start_date": to_date(elements["CSDT"][0]),
|
|
266
|
+
"finish_date": to_date(elements["CEDT"][0]) - HH,
|
|
267
|
+
"net": net,
|
|
268
|
+
"breakdown": breakdown,
|
|
269
|
+
}
|
|
270
|
+
)
|
|
310
271
|
|
|
311
272
|
|
|
312
273
|
def _process_CCD4(elements, headers):
|
|
313
|
-
breakdown =
|
|
274
|
+
breakdown = {}
|
|
314
275
|
|
|
315
276
|
element_code = elements["TCOD"][0]
|
|
316
|
-
|
|
277
|
+
|
|
317
278
|
try:
|
|
318
|
-
|
|
279
|
+
eln_name, eln_rate, eln_cons = TCOD_MAP[element_code]
|
|
319
280
|
except KeyError:
|
|
320
281
|
raise BadRequest(f"Can't find the element code {element_code} in the TCOD_MAP.")
|
|
321
282
|
|
|
322
|
-
m = elements["MLOC"][0]
|
|
323
|
-
mpan_core = " ".join((m[:2], m[2:6], m[6:10], m[10:]))
|
|
324
|
-
|
|
325
283
|
cons = elements["CONS"]
|
|
326
284
|
if eln_cons is not None and len(cons[0]) > 0:
|
|
327
285
|
el_cons = to_decimal(cons, "1000")
|
|
328
|
-
breakdown[eln_cons] =
|
|
286
|
+
breakdown[eln_cons] = el_cons
|
|
287
|
+
if eln_name == "ro":
|
|
288
|
+
headers["kwh"] += el_cons
|
|
329
289
|
|
|
330
290
|
if eln_rate is not None:
|
|
331
291
|
rate = to_decimal(elements["BPRI"], "100000")
|
|
332
292
|
breakdown[eln_rate] = [rate]
|
|
333
293
|
|
|
334
|
-
|
|
335
|
-
headers["bill_start_date"] = start_date
|
|
336
|
-
|
|
337
|
-
finish_date = to_date(elements["CEDT"][0]) - HH
|
|
338
|
-
headers["bill_finish_date"] = finish_date
|
|
339
|
-
|
|
294
|
+
net = Decimal("0.00")
|
|
340
295
|
if "CTOT" in elements:
|
|
341
|
-
net
|
|
342
|
-
else:
|
|
343
|
-
net = Decimal("0.00")
|
|
344
|
-
|
|
345
|
-
breakdown[eln_gbp] = net
|
|
346
|
-
|
|
347
|
-
headers["mpan_core"] = mpan_core
|
|
348
|
-
|
|
349
|
-
try:
|
|
350
|
-
reads = headers["reads"]
|
|
351
|
-
del headers["reads"][:]
|
|
352
|
-
except KeyError:
|
|
353
|
-
reads = []
|
|
296
|
+
net += to_decimal(elements["CTOT"], "100")
|
|
354
297
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
"vat": Decimal("0.00"),
|
|
365
|
-
"gross": net,
|
|
366
|
-
"breakdown": breakdown,
|
|
367
|
-
"reads": reads,
|
|
368
|
-
"bill_type_code": headers["bill_type_code"],
|
|
369
|
-
}
|
|
298
|
+
headers["elements"].append(
|
|
299
|
+
{
|
|
300
|
+
"name": eln_name,
|
|
301
|
+
"start_date": to_date(elements["CSDT"][0]),
|
|
302
|
+
"finish_date": to_date(elements["CEDT"][0]) - HH,
|
|
303
|
+
"net": net,
|
|
304
|
+
"breakdown": breakdown,
|
|
305
|
+
}
|
|
306
|
+
)
|
|
370
307
|
|
|
371
308
|
|
|
372
309
|
def _process_CDT(elements, headers):
|
|
@@ -374,10 +311,20 @@ def _process_CDT(elements, headers):
|
|
|
374
311
|
headers["customer_number"] = customer_id
|
|
375
312
|
|
|
376
313
|
|
|
314
|
+
def _process_CLO(elements, headers):
|
|
315
|
+
cloc = elements["CLOC"]
|
|
316
|
+
headers["account"] = cloc[2]
|
|
317
|
+
|
|
318
|
+
|
|
377
319
|
def _process_END(elements, headers):
|
|
378
320
|
pass
|
|
379
321
|
|
|
380
322
|
|
|
323
|
+
def _process_MAN(elements, headers):
|
|
324
|
+
madn = elements["MADN"]
|
|
325
|
+
headers["mpan_core"] = parse_mpan_core("".join(madn[:3]))
|
|
326
|
+
|
|
327
|
+
|
|
381
328
|
def _process_MHD(elements, headers):
|
|
382
329
|
message_type = elements["TYPE"][0]
|
|
383
330
|
if message_type == "UTLBIL":
|
|
@@ -396,21 +343,14 @@ def _process_VAT(elements, headers):
|
|
|
396
343
|
vat_percentage = to_decimal(elements["VATP"]) / Decimal("1000")
|
|
397
344
|
vat_net = Decimal("0.00") + to_decimal(elements["UVLA"]) / Decimal("100")
|
|
398
345
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
"kwh": Decimal("0.00"),
|
|
408
|
-
"net": Decimal("0.00"),
|
|
409
|
-
"vat": vat,
|
|
410
|
-
"gross": vat,
|
|
411
|
-
"breakdown": {"vat": {vat_percentage: {"vat": vat, "net": vat_net}}},
|
|
412
|
-
"reads": [],
|
|
413
|
-
}
|
|
346
|
+
breakdown = headers["breakdown"]
|
|
347
|
+
|
|
348
|
+
try:
|
|
349
|
+
vat_bd = breakdown["vat"]
|
|
350
|
+
except KeyError:
|
|
351
|
+
vat_bd = breakdown["vat"] = {}
|
|
352
|
+
|
|
353
|
+
vat_bd[vat_percentage] = {"vat": vat, "net": vat_net}
|
|
414
354
|
|
|
415
355
|
|
|
416
356
|
def _process_NOOP(elements, headers):
|
|
@@ -419,17 +359,17 @@ def _process_NOOP(elements, headers):
|
|
|
419
359
|
|
|
420
360
|
CODE_FUNCS = {
|
|
421
361
|
"BCD": _process_BCD,
|
|
422
|
-
"BTL":
|
|
362
|
+
"BTL": _process_BTL,
|
|
423
363
|
"CCD1": _process_CCD1,
|
|
424
364
|
"CCD2": _process_CCD2,
|
|
425
365
|
"CCD3": _process_CCD3,
|
|
426
366
|
"CCD4": _process_CCD4,
|
|
427
367
|
"CDT": _process_CDT,
|
|
428
|
-
"CLO":
|
|
368
|
+
"CLO": _process_CLO,
|
|
429
369
|
"DNA": _process_NOOP,
|
|
430
370
|
"END": _process_END,
|
|
431
371
|
"FIL": _process_NOOP,
|
|
432
|
-
"MAN":
|
|
372
|
+
"MAN": _process_MAN,
|
|
433
373
|
"MHD": _process_MHD,
|
|
434
374
|
"MTR": _process_MTR,
|
|
435
375
|
"SDT": _process_NOOP,
|
|
@@ -441,21 +381,6 @@ CODE_FUNCS = {
|
|
|
441
381
|
}
|
|
442
382
|
|
|
443
383
|
|
|
444
|
-
def _customer_mods(headers, bill):
|
|
445
|
-
if headers["customer_number"] == "WESSEXWAT":
|
|
446
|
-
if (
|
|
447
|
-
headers["element_code"] == "307660"
|
|
448
|
-
and "ro-gbp" in bill["breakdown"]
|
|
449
|
-
and bill["issue_date"] == to_utc(ct_datetime(2023, 4, 14))
|
|
450
|
-
and bill["start_date"] == to_utc(ct_datetime(2023, 3, 1))
|
|
451
|
-
and bill["finish_date"] == to_utc(ct_datetime(2023, 3, 31, 23, 30))
|
|
452
|
-
):
|
|
453
|
-
bill["start_date"] = to_utc(ct_datetime(2021, 4, 1))
|
|
454
|
-
bill["finish_date"] = to_utc(ct_datetime(2022, 3, 31, 23, 30))
|
|
455
|
-
|
|
456
|
-
return bill
|
|
457
|
-
|
|
458
|
-
|
|
459
384
|
class Parser:
|
|
460
385
|
def __init__(self, f):
|
|
461
386
|
self.edi_str = str(f.read(), "utf-8", errors="ignore")
|
|
@@ -465,7 +390,12 @@ class Parser:
|
|
|
465
390
|
bills = []
|
|
466
391
|
headers = {}
|
|
467
392
|
bill = None
|
|
393
|
+
lines = []
|
|
468
394
|
for self.line_number, line, seg_name, elements in parse_edi(self.edi_str):
|
|
395
|
+
if seg_name == "MHD":
|
|
396
|
+
lines = []
|
|
397
|
+
lines.append(line)
|
|
398
|
+
|
|
469
399
|
try:
|
|
470
400
|
func = CODE_FUNCS[seg_name]
|
|
471
401
|
except KeyError:
|
|
@@ -485,7 +415,9 @@ class Parser:
|
|
|
485
415
|
) from e
|
|
486
416
|
|
|
487
417
|
if bill is not None:
|
|
488
|
-
bill["breakdown"]["raw-lines"] =
|
|
489
|
-
bills.append(
|
|
418
|
+
bill["breakdown"]["raw-lines"] = lines
|
|
419
|
+
bills.append(bill)
|
|
420
|
+
if seg_name == "MTR":
|
|
421
|
+
lines = []
|
|
490
422
|
|
|
491
423
|
return bills
|