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.

Files changed (75) hide show
  1. chellow/e/bill_importer.py +136 -80
  2. chellow/e/bill_parsers/activity_mop_stark_xlsx.py +99 -86
  3. chellow/e/bill_parsers/annual_mop_stark_xlsx.py +78 -61
  4. chellow/e/bill_parsers/csv.py +139 -101
  5. chellow/e/bill_parsers/drax_edi.py +65 -88
  6. chellow/e/bill_parsers/engie_edi.py +187 -255
  7. chellow/e/bill_parsers/engie_xls.py +153 -167
  8. chellow/e/bill_parsers/haven_edi.py +189 -228
  9. chellow/e/bill_parsers/haven_edi_tprs.py +67 -67
  10. chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py +75 -66
  11. chellow/e/bill_parsers/settlement_dc_stark_xlsx.py +229 -126
  12. chellow/e/bill_parsers/sse_edi.py +107 -75
  13. chellow/e/bill_parsers/sww_xls.py +78 -91
  14. chellow/e/computer.py +1 -1
  15. chellow/e/views.py +626 -281
  16. chellow/edi_lib.py +4 -27
  17. chellow/models.py +92 -3
  18. chellow/reports/report_111.py +478 -616
  19. chellow/reports/report_247.py +96 -137
  20. chellow/templates/e/dc_batch.html +110 -157
  21. chellow/templates/e/dc_batch_add.html +2 -3
  22. chellow/templates/e/dc_batch_edit.html +42 -46
  23. chellow/templates/e/dc_batch_file.html +2 -3
  24. chellow/templates/e/dc_batch_file_edit.html +28 -40
  25. chellow/templates/e/dc_batch_upload_file.html +68 -0
  26. chellow/templates/e/dc_batches.html +2 -1
  27. chellow/templates/e/dc_batches_edit.html +26 -0
  28. chellow/templates/e/dc_bill.html +27 -5
  29. chellow/templates/e/dc_bill_add.html +4 -4
  30. chellow/templates/e/dc_bill_edit.html +43 -63
  31. chellow/templates/e/dc_bill_import.html +1 -1
  32. chellow/templates/e/dc_bill_import_contract.html +130 -0
  33. chellow/templates/e/dc_contract.html +1 -1
  34. chellow/templates/e/dc_element.html +41 -0
  35. chellow/templates/e/dc_element_add.html +36 -0
  36. chellow/templates/e/dc_element_edit.html +49 -0
  37. chellow/templates/e/dc_rate_script_edit.html +27 -43
  38. chellow/templates/e/mop_batch.html +105 -152
  39. chellow/templates/e/mop_batch_add.html +2 -3
  40. chellow/templates/e/mop_batch_edit.html +43 -51
  41. chellow/templates/e/mop_batch_upload_file.html +71 -5
  42. chellow/templates/e/mop_batches.html +2 -1
  43. chellow/templates/e/mop_batches_edit.html +26 -0
  44. chellow/templates/e/mop_bill.html +31 -8
  45. chellow/templates/e/mop_bill_add.html +7 -27
  46. chellow/templates/e/mop_bill_import.html +1 -1
  47. chellow/templates/e/mop_bill_import_contract.html +130 -0
  48. chellow/templates/e/mop_contract.html +4 -5
  49. chellow/templates/e/mop_element.html +41 -0
  50. chellow/templates/e/mop_element_add.html +36 -0
  51. chellow/templates/e/mop_element_edit.html +49 -0
  52. chellow/templates/e/supplier_batch.html +3 -7
  53. chellow/templates/e/supplier_batch_add.html +2 -2
  54. chellow/templates/e/supplier_batch_edit.html +1 -1
  55. chellow/templates/e/supplier_batch_file.html +3 -5
  56. chellow/templates/e/supplier_batch_file_add.html +18 -11
  57. chellow/templates/e/supplier_batch_upload_file.html +83 -9
  58. chellow/templates/e/supplier_batches.html +4 -4
  59. chellow/templates/e/supplier_batches_edit.html +26 -0
  60. chellow/templates/e/supplier_bill.html +29 -6
  61. chellow/templates/e/supplier_bill_add.html +3 -3
  62. chellow/templates/e/supplier_bill_import.html +1 -1
  63. chellow/templates/e/supplier_bill_import_contract.html +118 -0
  64. chellow/templates/e/supplier_contract.html +1 -1
  65. chellow/templates/e/supplier_element.html +45 -0
  66. chellow/templates/e/supplier_element_add.html +36 -0
  67. chellow/templates/e/supplier_element_edit.html +51 -0
  68. chellow/templates/report_run_bill_check.html +137 -179
  69. chellow/templates/report_run_row_bill_check.html +182 -179
  70. chellow/views.py +55 -65
  71. {chellow-1755614564.0.0.dist-info → chellow-1759155233.0.0.dist-info}/METADATA +2 -2
  72. {chellow-1755614564.0.0.dist-info → chellow-1759155233.0.0.dist-info}/RECORD +73 -60
  73. chellow/e/bill_parsers/drax_element_edi.py +0 -459
  74. chellow/templates/e/supplier_bill_imports.html +0 -421
  75. {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, to_ct_date, to_date, to_decimal, to_finish_date
7
- from chellow.models import Era, Session
8
- from chellow.utils import HH, ct_datetime, parse_mpan_core
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["is_ebatch"] = to_ct_date(sumo[1]) in (
39
- ct_datetime(2020, 4, 1),
40
- ct_datetime(2020, 3, 16),
41
- )
42
- if headers["is_ebatch"]:
43
- headers["finish_date"] = to_date(sumo[1]) - HH
44
- else:
45
- headers["finish_date"] = to_finish_date(sumo[1])
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 = headers["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[f"{prefix}-kwh"] += kwh
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
- rate_key = f"{prefix}-rate"
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
- breakdown[f"{prefix}-gbp"] += _decimal(elements, "CTOT") / Decimal("100")
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 = headers["breakdown"]
286
+ breakdown = {}
254
287
  if len(ndrp[0]) > 0:
255
- breakdown["standing-days"] += to_decimal(ndrp)
288
+ breakdown["days"] += to_decimal(ndrp)
256
289
  ctot = elements["CTOT"]
290
+ net = Decimal("0.00")
257
291
  if len(ctot[0]) > 0:
258
- breakdown["standing-gbp"] += to_decimal(ctot) / Decimal("100")
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
- if headers["message_type"] == "UTLBIL":
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((madn[0], madn[1], madn[2])))
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": _process_NOOP,
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
- return get_value(title_row, row, name)
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
- msn = str(get_value(title_row, row, "meter")).strip()
94
- mpan_core = parse_mpan_core(
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}")