chellow 1726564344.0.0__py3-none-any.whl → 1726664509.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.

@@ -217,7 +217,7 @@ def _handle_0860(headers, pre_record, record):
217
217
 
218
218
  def _handle_1455(headers, pre_record, record):
219
219
  parts = _chop_record(
220
- record, ccl_kwh=13, unknown_1=8, ccl_rate=15, ccl_gbp=12, unkown_2=8
220
+ record, ccl_kwh=13, unknown_1=10, ccl_rate=13, ccl_gbp=12, unkown_2=8
221
221
  )
222
222
  bd = headers["breakdown"]
223
223
  bd["ccl-kwh"] += Decimal(parts["ccl_kwh"])
chellow/e/hh_importer.py CHANGED
@@ -8,7 +8,7 @@ import traceback
8
8
  from collections import defaultdict, deque
9
9
  from datetime import datetime as Datetime, timedelta as Timedelta
10
10
  from decimal import Decimal
11
- from io import StringIO, TextIOWrapper
11
+ from io import StringIO
12
12
  from pathlib import Path
13
13
 
14
14
  import jinja2
@@ -40,7 +40,7 @@ from chellow.utils import (
40
40
  processes = defaultdict(list)
41
41
  tasks = {}
42
42
 
43
- extensions = [".df2", ".simple.csv", ".bg.csv"]
43
+ extensions = [".df2", ".simple.csv", ".bg.csv", ".vital.xlsx"]
44
44
 
45
45
 
46
46
  class HhDataImportProcess(threading.Thread):
@@ -277,7 +277,7 @@ class HhImportTask(threading.Thread):
277
277
  self.log(f"File size is {fsize} bytes.")
278
278
  self.log(f"Treating files as type {file_type}")
279
279
  self.importer = HhDataImportProcess(
280
- self.contract_id, 0, TextIOWrapper(f, "utf8"), fpath + file_type, fsize
280
+ self.contract_id, 0, f, fpath + file_type, fsize
281
281
  )
282
282
 
283
283
  self.importer.run()
@@ -412,7 +412,7 @@ class HhImportTask(threading.Thread):
412
412
  self.log(f"File size is {fsize} bytes.")
413
413
  self.log(f"Treating files as type {file_type}")
414
414
  self.importer = HhDataImportProcess(
415
- self.contract_id, 0, TextIOWrapper(f, "utf8"), fpath + file_type, fsize
415
+ self.contract_id, 0, f, fpath + file_type, fsize
416
416
  )
417
417
 
418
418
  self.importer.run()
@@ -1,5 +1,6 @@
1
1
  import decimal
2
2
  import itertools
3
+ from codecs import iterdecode
3
4
 
4
5
  from werkzeug.exceptions import BadRequest
5
6
 
@@ -13,7 +14,7 @@ def create_parser(reader, mpan_map, messages):
13
14
  class StarkDf2HhParser:
14
15
  def __init__(self, reader, mpan_map, messages):
15
16
  self.line = self.line_number = None
16
- self.reader = zip(itertools.count(1), reader)
17
+ self.reader = zip(itertools.count(1), iterdecode(reader, "utf-8"))
17
18
 
18
19
  self.line_number, self.line = next(self.reader)
19
20
  if self.line.strip().upper() != "#F2":
@@ -1,5 +1,6 @@
1
1
  import csv
2
2
  import itertools
3
+ from codecs import iterdecode
3
4
  from datetime import datetime as Datetime
4
5
  from decimal import Decimal
5
6
 
@@ -14,7 +15,8 @@ def create_parser(reader, mpan_map, messages):
14
15
 
15
16
  class HhParserCsvSimple:
16
17
  def __init__(self, reader, mpan_map, messages):
17
- self.shredder = zip(itertools.count(1), csv.reader(reader))
18
+ s = iterdecode(reader, "utf-8")
19
+ self.shredder = zip(itertools.count(1), csv.reader(s))
18
20
  next(self.shredder) # skip the title line
19
21
  self.values = None
20
22
 
@@ -0,0 +1,132 @@
1
+ from datetime import datetime as Datetime
2
+
3
+ from decimal import Decimal, InvalidOperation
4
+ from openpyxl import load_workbook
5
+
6
+ from werkzeug.exceptions import BadRequest
7
+
8
+ from chellow.utils import HH, ct_datetime, hh_before, hh_range, to_utc
9
+
10
+
11
+ def create_parser(input_stream, mpan_map, messages):
12
+ return HhParserVital(input_stream, mpan_map, messages)
13
+
14
+
15
+ def get_cell(sheet, col, row):
16
+ try:
17
+ coordinates = f"{col}{row}"
18
+ return sheet[coordinates]
19
+ except IndexError:
20
+ raise BadRequest(f"Can't find the cell {coordinates} on sheet {sheet}.")
21
+
22
+
23
+ def get_date(sheet, col, row):
24
+ cell = get_cell(sheet, col, row)
25
+ val = cell.value
26
+ if not isinstance(val, Datetime):
27
+ raise BadRequest(
28
+ f"Problem reading {val} (of type {type(val)}) as a timestamp at "
29
+ f"{cell.coordinate}."
30
+ )
31
+ return val
32
+
33
+
34
+ def get_str(sheet, col, row):
35
+ return get_cell(sheet, col, row).value.strip()
36
+
37
+
38
+ def get_dec(sheet, col, row):
39
+ return get_dec_from_cell(get_cell(sheet, col, row))
40
+
41
+
42
+ def get_dec_from_cell(cell):
43
+ try:
44
+ return Decimal(str(cell.value))
45
+ except InvalidOperation as e:
46
+ raise BadRequest(f"Problem parsing the number at {cell.coordinate}. {e}")
47
+
48
+
49
+ def get_int(sheet, col, row):
50
+ return int(get_cell(sheet, col, row).value)
51
+
52
+
53
+ def find_hhs(sheet, imp_mpan, exp_mpan):
54
+ row = pres_readings = pres_ts = None
55
+ caches = {}
56
+ try:
57
+ for row in range(2, len(sheet["A"]) + 1):
58
+ imp_read_cell = get_cell(sheet, "H", row)
59
+ imp_read_val = imp_read_cell.value
60
+ if imp_read_val is None or imp_read_val == "":
61
+ break
62
+
63
+ exp_read_cell = get_cell(sheet, "I", row)
64
+ exp_read_val = exp_read_cell.value
65
+ if exp_read_val is None or exp_read_val == "":
66
+ break
67
+
68
+ # '16/09/2024 14:45:00
69
+ ts_str = get_str(sheet, "A", row)
70
+ ts_naive = Datetime.strptime(ts_str, "%d/%m/%Y %H:%M:%S")
71
+ ts_ct = ct_datetime(
72
+ ts_naive.year,
73
+ ts_naive.month,
74
+ ts_naive.day,
75
+ ts_naive.hour,
76
+ ts_naive.minute,
77
+ )
78
+
79
+ imp_read = get_dec_from_cell(imp_read_cell)
80
+ exp_read = get_dec_from_cell(exp_read_cell)
81
+ ts = to_utc(ts_ct)
82
+
83
+ if ts_naive.minute in (0, 30) and hh_before(ts, pres_ts):
84
+ if pres_readings is not None:
85
+ pres_imp_read, pres_exp_read = pres_readings
86
+ hhs = hh_range(caches, ts, pres_ts - HH)
87
+ num_hhs = len(hhs)
88
+ val_imp = (pres_imp_read - imp_read) / num_hhs
89
+ val_exp = (pres_exp_read - exp_read) / num_hhs
90
+ for hh in hhs:
91
+
92
+ yield {
93
+ "mpan_core": imp_mpan,
94
+ "channel_type": "ACTIVE",
95
+ "start_date": hh,
96
+ "value": val_imp,
97
+ "status": "A",
98
+ }
99
+ yield {
100
+ "mpan_core": exp_mpan,
101
+ "channel_type": "ACTIVE",
102
+ "start_date": hh,
103
+ "value": val_exp,
104
+ "status": "A",
105
+ }
106
+
107
+ pres_readings = imp_read, exp_read
108
+ pres_ts = ts
109
+
110
+ except BadRequest as e:
111
+ e.description = (f"Problem at row: {row}: {e.description}",)
112
+ raise e
113
+
114
+
115
+ class HhParserVital:
116
+ def __init__(self, input_stream, mpan_map, messages):
117
+ book = load_workbook(input_stream, data_only=True)
118
+ sheet = book.worksheets[0]
119
+ imp_name = get_str(sheet, "H", 1).strip()
120
+ imp_mpan = mpan_map[imp_name]
121
+ exp_name = get_str(sheet, "I", 1).strip()
122
+ exp_mpan = mpan_map[exp_name]
123
+ self.data = iter(find_hhs(sheet, imp_mpan, exp_mpan))
124
+
125
+ def __iter__(self):
126
+ return self
127
+
128
+ def __next__(self):
129
+ return next(self.data)
130
+
131
+ def close(self):
132
+ pass
chellow/e/views.py CHANGED
@@ -3,7 +3,7 @@ import os
3
3
  import threading
4
4
  from collections import defaultdict
5
5
  from datetime import datetime as Datetime
6
- from io import StringIO
6
+ from io import BytesIO, StringIO
7
7
  from itertools import chain, islice
8
8
  from random import random
9
9
 
@@ -1233,7 +1233,7 @@ def dc_contracts_hh_imports_post(contract_id):
1233
1233
  contract = Contract.get_dc_by_id(g.sess, contract_id)
1234
1234
 
1235
1235
  file_item = req_file("import_file")
1236
- f = StringIO(str(file_item.stream.read(), "utf-8"))
1236
+ f = BytesIO(file_item.stream.read())
1237
1237
  f.seek(0, os.SEEK_END)
1238
1238
  file_size = f.tell()
1239
1239
  f.seek(0)
@@ -21,15 +21,16 @@
21
21
  Reached line number {{process.converter.line_number}}.
22
22
  {% endif %}
23
23
  </p>
24
- {% elif process.messages|length == 0 %}
24
+ {% elif process.error is none %}
25
25
  <p>The import has completed successfully.</p>
26
26
  {% else %}
27
- <p>The import failed:</p>
28
- <ul>
29
- {% for message in process.messages %}
30
- <li>{{message}}</li>
31
- {% endfor %}
32
- </ul>
27
+ <p>The import failed. {{process.error}}</p>
33
28
  {% endif %}
29
+
30
+ <ul>
31
+ {% for message in process.messages %}
32
+ <li>{{message}}</li>
33
+ {% endfor %}
34
+ </ul>
34
35
 
35
36
  {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chellow
3
- Version: 1726564344.0.0
3
+ Version: 1726664509.0.0
4
4
  Summary: Web Application for checking UK energy bills.
5
5
  Project-URL: Homepage, https://github.com/WessexWater/chellow
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
@@ -24,10 +24,11 @@ chellow/e/dno_rate_parser.py,sha256=A5TP6KjyfT5lVWh7dX4SiXRi6wnf2lGv-H_T4Sod8CI,
24
24
  chellow/e/duos.py,sha256=nwviRjz-qIt3GxIMHk0hItIT4dtKsxOWq9TUC1z-hO8,30864
25
25
  chellow/e/elexon.py,sha256=ALhXS9Es7PV0z9ukPbIramn3cf3iLyFi-PMWPSm5iOs,5487
26
26
  chellow/e/energy_management.py,sha256=aXC2qlGt3FAODlNl_frWzVYAQrJLP8FFOiNX3m-QE_Y,12388
27
- chellow/e/hh_importer.py,sha256=-jvJaex756NpygSapsWxXl6RK0Z4ymkz3QA6ETrdnac,21476
27
+ chellow/e/hh_importer.py,sha256=vD2PRMSBhxmsyJ4xEq2N7Ib5Ohmf1FmQk8-APw8vBEs,21430
28
28
  chellow/e/hh_parser_bg_csv.py,sha256=W5SU2MSpa8BGA0VJw1JXF-IwbCNLFy8fe35yxLZ7gEw,2453
29
- chellow/e/hh_parser_df2.py,sha256=7gaVidyIqeqprm3zYPtHvRLLn08nph04N0cKlveNTV0,4279
30
- chellow/e/hh_parser_simple_csv.py,sha256=RN4QOLvTQeoPrpvXvQ9hkOBZnR5piybLfjCiSJdjpjs,2112
29
+ chellow/e/hh_parser_df2.py,sha256=tRAoVUUoJDlfPopm6usEBnhJz7dXMc2_KEWbkW9Gyq4,4330
30
+ chellow/e/hh_parser_simple_csv.py,sha256=lJx9tw9BWFSoBmns1Cws_vY-OIn90LPt2yvIN_CFcTE,2177
31
+ chellow/e/hh_parser_vital_xlsx.py,sha256=g9-CElfH1PPfwpuUcVvD6WQpBlNxCo8j9pq_0Yza0ZM,4125
31
32
  chellow/e/laf_import.py,sha256=aqkcbjnvfBPszBLSNg6getP7iW1uWiTVHy6N5Z5x39U,5514
32
33
  chellow/e/lcc.py,sha256=OkpynN8_iAdHRlu-yyU6BhRUqYYOZsUnl0HbHULYo_4,4670
33
34
  chellow/e/mdd_importer.py,sha256=NugJr2JhuzkPTsEMl_5UdQuw5K2p8lVJ-hyz4MK6Hfg,35762
@@ -38,7 +39,7 @@ chellow/e/system_price.py,sha256=6w5J7bzwFAZubE2zdOFRiS8IIrVP8hkoIOaG2yCt-Ic,623
38
39
  chellow/e/tlms.py,sha256=M33D6YpMixu2KkwSCzDRM3kThLgShg8exp63Obo75l8,8905
39
40
  chellow/e/tnuos.py,sha256=XseYztPUsQXNKuBmystO2kzzwAG9ehCZgpGBTdgSk-A,4313
40
41
  chellow/e/triad.py,sha256=lIQj7EdUrcFwEqleuHZXYU_bfzIwNOqUVVxB3NPQt4A,13710
41
- chellow/e/views.py,sha256=aljiDbLvO_rUl00ohDDxs-3-xPmsuguaOyo69lcXcBA,220624
42
+ chellow/e/views.py,sha256=LG9KeYfXDkOvd7GrywuQPG1qDnpFvKe1oa95H0wRlqY,220618
42
43
  chellow/e/bill_parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
44
  chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=UgWXDPzQkQghyj_lfgBqoSJpHB-t-qOdSaB8qY6GLog,4071
44
45
  chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=-HMoIfa_utXYKA44RuC0Xqv3vd2HLeQU_4P0iBUd3WA,4219
@@ -52,7 +53,7 @@ chellow/e/bill_parsers/gdf_csv.py,sha256=ZfK3Oc6oP28p_P9DIevLNB_zW2WLcEJ3Lvb1gL3
52
53
  chellow/e/bill_parsers/haven_csv.py,sha256=0uENq8IgVNqdxfBQMBxLTSZWCOuDHXZC0xzk52SbfyE,13652
53
54
  chellow/e/bill_parsers/haven_edi.py,sha256=YGPHRxPOhje9s32jqPHHELni2tooOYj3cMC_qaZVPq4,16107
54
55
  chellow/e/bill_parsers/haven_edi_tprs.py,sha256=ZVX9CCqUybsot_Z0BEOJPvl9x5kSr7fEWyuJXvZDcz4,11841
55
- chellow/e/bill_parsers/mm.py,sha256=W_n7xlXrSH6QewkCnNQpMAxWUocXctIHo7XR-t95Aas,9543
56
+ chellow/e/bill_parsers/mm.py,sha256=mXghmH_gLx82O20CUMBnUysAJqh-OMkR_-CGEcKrzhs,9544
56
57
  chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py,sha256=yogXTuQHGRL7IiqvRWr2C9V24ez1j9Yx0128UygPE_k,4723
57
58
  chellow/e/bill_parsers/settlement_dc_stark_xlsx.py,sha256=PlEqCZuJ9DfQXeeYQ64jtf3ML7sUt_tt61QOOTnkE5c,6380
58
59
  chellow/e/bill_parsers/sse_edi.py,sha256=L85DOfNkqexeEIEr8pCBn_2sHJI-zEaw6cogpE3YyYM,15204
@@ -187,7 +188,7 @@ chellow/templates/e/dc_bill_import.html,sha256=NHjMSoFizvFQIaPWuVE3nTCtMDTzJB0Xm
187
188
  chellow/templates/e/dc_bill_imports.html,sha256=lCaUR47r9KPr0VrQhEvVEaKexM5R_nmkxtzgpWZ0e9s,2135
188
189
  chellow/templates/e/dc_contract.html,sha256=b6DLDrGdzN9Rri56pFvfpE7QZKYXGHib2veYAztuHlg,2352
189
190
  chellow/templates/e/dc_contract_edit.html,sha256=IObmbHQmeZ_LSpnYgabmhoSNUR3aPmm-Jk5nJLM_u74,1706
190
- chellow/templates/e/dc_contract_hh_import.html,sha256=UODiBFNohb60MjH1w-9JW1JE0O9GR2uKPGw-lD7Da5g,848
191
+ chellow/templates/e/dc_contract_hh_import.html,sha256=JncR3L6cOK4jghsGyr-itEqlIemXBXt3kL09wpqnQSE,856
191
192
  chellow/templates/e/dc_contract_hh_imports.html,sha256=eXFDGyzSgag4JRism81_p5yTzQOjCIXaVkQ8tl3dDcM,8172
192
193
  chellow/templates/e/dc_contract_properties.html,sha256=2EmA91gYWZcTOHQ3PxXQrpTOb8dm0OGjwRWsW6qNI9s,455
193
194
  chellow/templates/e/dc_contract_properties_edit.html,sha256=TGYcHTlWbk5WmjZPkdbHhRVZcOpEfhowCp2penZcGiE,1704
@@ -365,6 +366,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
365
366
  chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
366
367
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
367
368
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
368
- chellow-1726564344.0.0.dist-info/METADATA,sha256=OH6pGKFudqcxiUUQ7qIvzgp-iO_kS7m6T0CjY-ywzh8,12204
369
- chellow-1726564344.0.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
370
- chellow-1726564344.0.0.dist-info/RECORD,,
369
+ chellow-1726664509.0.0.dist-info/METADATA,sha256=PhQBcuYRWYyJltXJBei7Jl22-HKANq4qi5Nae4hRNhs,12204
370
+ chellow-1726664509.0.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
371
+ chellow-1726664509.0.0.dist-info/RECORD,,