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
|
@@ -3,9 +3,9 @@ from decimal import Decimal
|
|
|
3
3
|
|
|
4
4
|
from werkzeug.exceptions import BadRequest
|
|
5
5
|
|
|
6
|
-
from chellow.edi_lib import parse_edi,
|
|
7
|
-
from chellow.models import
|
|
8
|
-
from chellow.utils import
|
|
6
|
+
from chellow.edi_lib import parse_edi, to_date, to_decimal, to_finish_date
|
|
7
|
+
from chellow.models import Session
|
|
8
|
+
from chellow.utils import parse_mpan_core
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
read_type_map = {
|
|
@@ -35,14 +35,39 @@ def _process_BCD(elements, headers):
|
|
|
35
35
|
|
|
36
36
|
sumo = elements["SUMO"]
|
|
37
37
|
headers["start_date"] = to_date(sumo[0])
|
|
38
|
-
headers["
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
headers["finish_date"] = to_finish_date(sumo[1])
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _process_BTL(elements, headers):
|
|
42
|
+
uvlt = elements["UVLT"]
|
|
43
|
+
utva = elements["UTVA"]
|
|
44
|
+
tbtl = elements["TBTL"]
|
|
45
|
+
|
|
46
|
+
dup_reads = set()
|
|
47
|
+
new_reads = []
|
|
48
|
+
for r in headers["reads"]:
|
|
49
|
+
k = tuple(v for n, v in sorted(r.items()))
|
|
50
|
+
if k in dup_reads:
|
|
51
|
+
continue
|
|
52
|
+
dup_reads.add(k)
|
|
53
|
+
new_reads.append(r)
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
"bill_type_code": headers["bill_type_code"],
|
|
57
|
+
"account": headers["account"],
|
|
58
|
+
"mpan_core": headers["mpan_core"],
|
|
59
|
+
"reference": headers["reference"],
|
|
60
|
+
"issue_date": headers["issue_date"],
|
|
61
|
+
"start_date": headers["start_date"],
|
|
62
|
+
"finish_date": headers["finish_date"],
|
|
63
|
+
"kwh": headers["kwh"],
|
|
64
|
+
"net": Decimal("0.00") + to_decimal(uvlt) / Decimal("100"),
|
|
65
|
+
"vat": Decimal("0.00") + to_decimal(utva) / Decimal("100"),
|
|
66
|
+
"gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
|
|
67
|
+
"breakdown": headers["breakdown"],
|
|
68
|
+
"reads": new_reads,
|
|
69
|
+
"elements": headers["elements"],
|
|
70
|
+
}
|
|
46
71
|
|
|
47
72
|
|
|
48
73
|
def _process_MHD(elements, headers):
|
|
@@ -52,6 +77,7 @@ def _process_MHD(elements, headers):
|
|
|
52
77
|
headers.clear()
|
|
53
78
|
headers["kwh"] = Decimal("0")
|
|
54
79
|
headers["reads"] = []
|
|
80
|
+
headers["elements"] = []
|
|
55
81
|
headers["breakdown"] = defaultdict(int, {"raw-lines": []})
|
|
56
82
|
headers["bill_elements"] = []
|
|
57
83
|
headers["errors"] = []
|
|
@@ -83,7 +109,6 @@ def _process_CCD1(elements, headers):
|
|
|
83
109
|
|
|
84
110
|
mpan = mloc[0]
|
|
85
111
|
mpan_core = parse_mpan_core(f"{mpan[:2]}{mpan[2:6]}{mpan[6:10]}{mpan[10:13]}")
|
|
86
|
-
headers["mpan_core"] = mpan_core
|
|
87
112
|
mpan = f"{mpan[13:15]} {mpan[15:18]} {mpan[18:]} {mpan_core}"
|
|
88
113
|
|
|
89
114
|
prrd = elements["PRRD"]
|
|
@@ -199,7 +224,7 @@ def _decimal(elements, element_name):
|
|
|
199
224
|
|
|
200
225
|
|
|
201
226
|
def _process_CCD3(elements, headers):
|
|
202
|
-
breakdown =
|
|
227
|
+
breakdown = {}
|
|
203
228
|
|
|
204
229
|
tcod = elements["TCOD"]
|
|
205
230
|
tcod0 = tcod[1]
|
|
@@ -234,28 +259,45 @@ def _process_CCD3(elements, headers):
|
|
|
234
259
|
|
|
235
260
|
if not ignore_kwh and "NUCT" in elements and len(elements["NUCT"][0]) > 0:
|
|
236
261
|
kwh = _decimal(elements, "NUCT") / Decimal("1000")
|
|
237
|
-
breakdown[
|
|
262
|
+
breakdown["kwh"] = kwh
|
|
238
263
|
if prefix == tmod0:
|
|
239
264
|
headers["kwh"] += kwh
|
|
240
265
|
|
|
241
266
|
if not ignore_rate and "CPPU" in elements and len(elements["CPPU"][0]) > 0:
|
|
242
|
-
|
|
243
|
-
if rate_key not in breakdown:
|
|
244
|
-
breakdown[rate_key] = set()
|
|
245
|
-
breakdown[rate_key].add(_decimal(elements, "CPPU") / Decimal("100000"))
|
|
267
|
+
breakdown["rate"] = {_decimal(elements, "CPPU") / Decimal("100000")}
|
|
246
268
|
|
|
269
|
+
net = Decimal("0.00")
|
|
247
270
|
if "CTOT" in elements:
|
|
248
|
-
|
|
271
|
+
net += _decimal(elements, "CTOT") / Decimal("100")
|
|
272
|
+
|
|
273
|
+
headers["elements"].append(
|
|
274
|
+
{
|
|
275
|
+
"name": prefix,
|
|
276
|
+
"start_date": to_date(elements["CSDT"][0]),
|
|
277
|
+
"finish_date": to_finish_date(elements["CEDT"][0]),
|
|
278
|
+
"net": net,
|
|
279
|
+
"breakdown": breakdown,
|
|
280
|
+
}
|
|
281
|
+
)
|
|
249
282
|
|
|
250
283
|
|
|
251
284
|
def _process_CCD4(elements, headers):
|
|
252
285
|
ndrp = elements["NDRP"]
|
|
253
|
-
breakdown =
|
|
286
|
+
breakdown = {}
|
|
254
287
|
if len(ndrp[0]) > 0:
|
|
255
|
-
breakdown["
|
|
288
|
+
breakdown["days"] += to_decimal(ndrp)
|
|
256
289
|
ctot = elements["CTOT"]
|
|
290
|
+
net = Decimal("0.00")
|
|
257
291
|
if len(ctot[0]) > 0:
|
|
258
|
-
|
|
292
|
+
net += to_decimal(ctot) / Decimal("100")
|
|
293
|
+
|
|
294
|
+
headers["elements"].append(
|
|
295
|
+
{
|
|
296
|
+
"name": "standing",
|
|
297
|
+
"net": net,
|
|
298
|
+
"breakdown": breakdown,
|
|
299
|
+
}
|
|
300
|
+
)
|
|
259
301
|
|
|
260
302
|
|
|
261
303
|
def _process_CLO(elements, headers):
|
|
@@ -264,54 +306,12 @@ def _process_CLO(elements, headers):
|
|
|
264
306
|
|
|
265
307
|
|
|
266
308
|
def _process_MTR(elements, headers):
|
|
267
|
-
|
|
268
|
-
if headers["mpan_core"] is None:
|
|
269
|
-
sess = headers["sess"]
|
|
270
|
-
era = (
|
|
271
|
-
sess.query(Era)
|
|
272
|
-
.filter(Era.imp_supplier_account == headers["account"])
|
|
273
|
-
.first()
|
|
274
|
-
)
|
|
275
|
-
if era is not None:
|
|
276
|
-
headers["mpan_core"] = era.imp_mpan_core
|
|
277
|
-
sess.close()
|
|
278
|
-
|
|
279
|
-
reads = headers["reads"]
|
|
280
|
-
if headers["is_ebatch"]:
|
|
281
|
-
for r in headers["reads"]:
|
|
282
|
-
if r["pres_type_code"] == "C":
|
|
283
|
-
r["pres_type_code"] = "E"
|
|
284
|
-
|
|
285
|
-
dup_reads = set()
|
|
286
|
-
new_reads = []
|
|
287
|
-
for r in reads:
|
|
288
|
-
k = tuple(v for n, v in sorted(r.items()))
|
|
289
|
-
if k in dup_reads:
|
|
290
|
-
continue
|
|
291
|
-
dup_reads.add(k)
|
|
292
|
-
new_reads.append(r)
|
|
293
|
-
|
|
294
|
-
raw_bill = {
|
|
295
|
-
"bill_type_code": headers["bill_type_code"],
|
|
296
|
-
"account": headers["account"],
|
|
297
|
-
"mpan_core": headers["mpan_core"],
|
|
298
|
-
"reference": headers["reference"],
|
|
299
|
-
"issue_date": headers["issue_date"],
|
|
300
|
-
"start_date": headers["start_date"],
|
|
301
|
-
"finish_date": headers["finish_date"],
|
|
302
|
-
"kwh": headers["kwh"],
|
|
303
|
-
"net": headers["net"],
|
|
304
|
-
"vat": headers["vat"],
|
|
305
|
-
"gross": headers["gross"],
|
|
306
|
-
"breakdown": headers["breakdown"],
|
|
307
|
-
"reads": new_reads,
|
|
308
|
-
}
|
|
309
|
-
return raw_bill
|
|
309
|
+
pass
|
|
310
310
|
|
|
311
311
|
|
|
312
312
|
def _process_MAN(elements, headers):
|
|
313
313
|
madn = elements["MADN"]
|
|
314
|
-
headers["mpan_core"] = parse_mpan_core("".join(
|
|
314
|
+
headers["mpan_core"] = parse_mpan_core("".join(madn[:3]))
|
|
315
315
|
|
|
316
316
|
|
|
317
317
|
def _process_VAT(elements, headers):
|
|
@@ -354,7 +354,7 @@ def _process_NOOP(elements, headers):
|
|
|
354
354
|
|
|
355
355
|
CODE_FUNCS = {
|
|
356
356
|
"BCD": _process_BCD,
|
|
357
|
-
"BTL":
|
|
357
|
+
"BTL": _process_BTL,
|
|
358
358
|
"CCD1": _process_CCD1,
|
|
359
359
|
"CCD2": _process_CCD2,
|
|
360
360
|
"CCD3": _process_CCD3,
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
from decimal import Decimal, InvalidOperation
|
|
2
2
|
|
|
3
3
|
from openpyxl import load_workbook
|
|
4
|
+
from openpyxl.utils.datetime import from_excel
|
|
4
5
|
|
|
5
6
|
from werkzeug.exceptions import BadRequest
|
|
6
7
|
|
|
7
8
|
from chellow.e.computer import hh_rate
|
|
8
9
|
from chellow.models import Session
|
|
9
|
-
from chellow.utils import ct_datetime, parse_mpan_core, to_utc
|
|
10
|
+
from chellow.utils import ct_datetime, parse_mpan_core, to_ct, to_utc
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def get_ct_date(title_row, row, name):
|
|
13
|
-
|
|
14
|
+
val_raw = get_value(title_row, row, name)
|
|
15
|
+
if isinstance(val_raw, int):
|
|
16
|
+
val = from_excel(val_raw)
|
|
17
|
+
else:
|
|
18
|
+
val = val_raw
|
|
19
|
+
return to_ct(val)
|
|
14
20
|
|
|
15
21
|
|
|
16
22
|
def get_start_date(title_row, row, name):
|
|
@@ -56,6 +62,69 @@ def get_int(title_row, row, name):
|
|
|
56
62
|
return int(get_value(title_row, row, name))
|
|
57
63
|
|
|
58
64
|
|
|
65
|
+
def _process_row(caches, sess, title_row, row):
|
|
66
|
+
msn = str(get_value(title_row, row, "meter")).strip()
|
|
67
|
+
mpan_core = parse_mpan_core(str(get_int(title_row, row, "mpan ref")))
|
|
68
|
+
start_date_ct = get_ct_date(title_row, row, "start")
|
|
69
|
+
start_date = to_utc(start_date_ct)
|
|
70
|
+
issue_date = start_date
|
|
71
|
+
finish_date_ct = get_ct_date(title_row, row, "end")
|
|
72
|
+
finish_date = to_utc(
|
|
73
|
+
ct_datetime(
|
|
74
|
+
finish_date_ct.year, finish_date_ct.month, finish_date_ct.day, 23, 30
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
rates = hh_rate(sess, caches, 0, start_date)
|
|
78
|
+
meter_rate = rates["annual_rates"]["non_settlement"]["*"]["IP"]["*"][
|
|
79
|
+
"gbp_per_meter"
|
|
80
|
+
]
|
|
81
|
+
months = (finish_date_ct.year - start_date_ct.year) * 12 + (
|
|
82
|
+
finish_date_ct.month - start_date_ct.month + 1
|
|
83
|
+
)
|
|
84
|
+
net = round(Decimal(float(meter_rate) / 12 * months), 2)
|
|
85
|
+
vat = round(net * Decimal("0.2"), 2)
|
|
86
|
+
elements = [
|
|
87
|
+
{
|
|
88
|
+
"name": "meter",
|
|
89
|
+
"start_date": start_date,
|
|
90
|
+
"finish_date": finish_date,
|
|
91
|
+
"net": net,
|
|
92
|
+
"breakdown": {
|
|
93
|
+
"rate": {meter_rate},
|
|
94
|
+
"months": months,
|
|
95
|
+
"settlement-status": {"non_settlement"},
|
|
96
|
+
"comm": {"IP"},
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
breakdown = {"raw_lines": [], "cop": ["5"], "msn": [msn]}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
"bill_type_code": "N",
|
|
105
|
+
"kwh": Decimal(0),
|
|
106
|
+
"vat": vat,
|
|
107
|
+
"net": net,
|
|
108
|
+
"gross": net + vat,
|
|
109
|
+
"reads": [],
|
|
110
|
+
"breakdown": breakdown,
|
|
111
|
+
"account": mpan_core,
|
|
112
|
+
"issue_date": issue_date,
|
|
113
|
+
"start_date": start_date,
|
|
114
|
+
"finish_date": finish_date,
|
|
115
|
+
"mpan_core": mpan_core,
|
|
116
|
+
"reference": "_".join(
|
|
117
|
+
(
|
|
118
|
+
start_date_ct.strftime("%Y%m%d"),
|
|
119
|
+
finish_date_ct.strftime("%Y%m%d"),
|
|
120
|
+
start_date_ct.strftime("%Y%m%d"),
|
|
121
|
+
mpan_core,
|
|
122
|
+
)
|
|
123
|
+
),
|
|
124
|
+
"elements": elements,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
59
128
|
class Parser:
|
|
60
129
|
def __init__(self, f):
|
|
61
130
|
self.book = load_workbook(f)
|
|
@@ -88,72 +157,12 @@ class Parser:
|
|
|
88
157
|
val = get_value(title_row, row, "mpan ref")
|
|
89
158
|
if val is None or val == "":
|
|
90
159
|
break
|
|
160
|
+
if get_str(title_row, row, "check") != "Billed":
|
|
161
|
+
continue
|
|
91
162
|
|
|
92
163
|
self._set_last_line(row_index, val)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
str(get_int(title_row, row, "mpan ref"))
|
|
96
|
-
)
|
|
97
|
-
start_date_ct = get_ct_date(title_row, row, "start")
|
|
98
|
-
start_date = to_utc(start_date_ct)
|
|
99
|
-
issue_date = start_date
|
|
100
|
-
finish_date_ct = get_ct_date(title_row, row, "end")
|
|
101
|
-
finish_date = to_utc(
|
|
102
|
-
ct_datetime(
|
|
103
|
-
finish_date_ct.year,
|
|
104
|
-
finish_date_ct.month,
|
|
105
|
-
finish_date_ct.day,
|
|
106
|
-
23,
|
|
107
|
-
30,
|
|
108
|
-
)
|
|
109
|
-
)
|
|
110
|
-
check = get_str(title_row, row, "check")
|
|
111
|
-
if check != "Billed":
|
|
112
|
-
continue
|
|
113
|
-
rates = hh_rate(sess, caches, 0, start_date)
|
|
114
|
-
meter_rate = rates["annual_rates"]["non_settlement"]["*"]["IP"][
|
|
115
|
-
"*"
|
|
116
|
-
]["gbp_per_meter"]
|
|
117
|
-
months = (finish_date_ct.year - start_date_ct.year) * 12 + (
|
|
118
|
-
finish_date_ct.month - start_date_ct.month + 1
|
|
119
|
-
)
|
|
120
|
-
net = round(Decimal(float(meter_rate) / 12 * months), 2)
|
|
121
|
-
vat = round(net * Decimal("0.2"), 2)
|
|
122
|
-
|
|
123
|
-
breakdown = {
|
|
124
|
-
"raw_lines": [],
|
|
125
|
-
"cop": ["5"],
|
|
126
|
-
"settlement-status": ["non_settlement"],
|
|
127
|
-
"msn": [msn],
|
|
128
|
-
"meter-rate": [meter_rate],
|
|
129
|
-
"months": months,
|
|
130
|
-
"meter-gbp": net,
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
bills.append(
|
|
134
|
-
{
|
|
135
|
-
"bill_type_code": "N",
|
|
136
|
-
"kwh": Decimal(0),
|
|
137
|
-
"vat": vat,
|
|
138
|
-
"net": net,
|
|
139
|
-
"gross": net + vat,
|
|
140
|
-
"reads": [],
|
|
141
|
-
"breakdown": breakdown,
|
|
142
|
-
"account": mpan_core,
|
|
143
|
-
"issue_date": issue_date,
|
|
144
|
-
"start_date": start_date,
|
|
145
|
-
"finish_date": finish_date,
|
|
146
|
-
"mpan_core": mpan_core,
|
|
147
|
-
"reference": "_".join(
|
|
148
|
-
(
|
|
149
|
-
start_date.strftime("%Y%m%d"),
|
|
150
|
-
finish_date.strftime("%Y%m%d"),
|
|
151
|
-
issue_date.strftime("%Y%m%d"),
|
|
152
|
-
mpan_core,
|
|
153
|
-
)
|
|
154
|
-
),
|
|
155
|
-
}
|
|
156
|
-
)
|
|
164
|
+
bill = _process_row(caches, sess, title_row, row)
|
|
165
|
+
bills.append(bill)
|
|
157
166
|
sess.rollback()
|
|
158
167
|
except BadRequest as e:
|
|
159
168
|
raise BadRequest(f"Row number: {row_index} {e.description}")
|