chellow 1716370405.0.0__py3-none-any.whl → 1716564585.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.

@@ -1,12 +1,222 @@
1
1
  import datetime
2
+ from collections import defaultdict
2
3
  from decimal import Decimal
3
4
  from io import StringIO
4
5
 
5
- from chellow.utils import parse_mpan_core, validate_hh_start
6
+ from werkzeug.exceptions import BadRequest
6
7
 
8
+ from chellow.utils import HH, to_ct, to_utc
7
9
 
8
- def parse_date(date_string):
9
- return validate_hh_start(datetime.datetime.strptime(date_string, "%Y%m%d"))
10
+
11
+ def parse_date(date_str):
12
+ return to_utc(to_ct(parse_date_naive(date_str)))
13
+
14
+
15
+ def parse_date_naive(date_str):
16
+ return datetime.datetime.strptime(date_str, "%Y%m%d")
17
+
18
+
19
+ def _chop_record(record, **kwargs):
20
+ parts = {}
21
+ idx = 0
22
+ for name, length in kwargs.items():
23
+ parts[name] = record[idx : idx + length]
24
+ idx += length
25
+ return parts
26
+
27
+
28
+ DATE_LENGTH = 8
29
+
30
+
31
+ def _handle_0000(headers, pre_record, record):
32
+ parts = _chop_record(record, unknown_1=9, issue_date=DATE_LENGTH)
33
+ headers["issue_date"] = parse_date(parts["issue_date"])
34
+
35
+
36
+ def _handle_0050(headers, pre_record, record):
37
+ pass
38
+
39
+
40
+ def _handle_0051(headers, pre_record, record):
41
+ pass
42
+
43
+
44
+ def _handle_0100(headers, pre_record, record):
45
+ issue_date = headers["issue_date"]
46
+ headers.clear()
47
+ headers["issue_date"] = issue_date
48
+ headers["account"] = pre_record[33:41]
49
+ headers["reference"] = pre_record[41:46]
50
+ headers["kwh"] = Decimal("0")
51
+ headers["breakdown"] = defaultdict(int, {"vat": {}})
52
+ headers["reads"] = []
53
+
54
+
55
+ def _handle_0101(headers, pre_record, record):
56
+ parts = _chop_record(record, start_date=DATE_LENGTH, finish_date=DATE_LENGTH)
57
+ headers["start_date"] = parse_date(parts["start_date"])
58
+ headers["finish_date"] = to_utc(to_ct(parse_date_naive(parts["finish_date"]) - HH))
59
+
60
+
61
+ CHARGE_LOOKUP = {
62
+ "STDG": "days",
63
+ "UNIT": "kwh",
64
+ }
65
+
66
+ ELEMENT_LOOKUP = {"10ANNUAL": "standing", "20RS0108": "0001", "9WANNUAL": "site_fee"}
67
+
68
+
69
+ def _handle_0460(headers, pre_record, record):
70
+ parts = _chop_record(
71
+ record,
72
+ unknown_1=12,
73
+ gbp=12,
74
+ code=8,
75
+ quantity=12,
76
+ charge=4,
77
+ unknown_2=18,
78
+ rate=16,
79
+ unknown_date=DATE_LENGTH,
80
+ another_gbp=12,
81
+ charge_description=35,
82
+ )
83
+ units = CHARGE_LOOKUP[parts["charge"]]
84
+ gbp = Decimal(parts["gbp"]) / 100
85
+ quantity = Decimal(parts["quantity"])
86
+ rate = Decimal(parts["rate"])
87
+ element_name = ELEMENT_LOOKUP[parts["code"]]
88
+ breakdown = headers["breakdown"]
89
+ breakdown[f"{element_name}-{units}"] += quantity
90
+ rate_name = f"{element_name}-rate"
91
+ if rate_name in breakdown:
92
+ rates = breakdown[rate_name]
93
+ else:
94
+ rates = breakdown[rate_name] = set()
95
+
96
+ rates.add(rate)
97
+ breakdown[f"{element_name}-gbp"] += gbp
98
+
99
+
100
+ UNITS_LOOKUP = {"KWH": "kwh"}
101
+
102
+ REGISTER_CODE_LOOKUP = {"000001": "0001"}
103
+
104
+
105
+ def _handle_0461(headers, pre_record, record):
106
+ parts = _chop_record(
107
+ record,
108
+ msn=11,
109
+ unknown_1=2,
110
+ prev_read_value=12,
111
+ pres_read_value=12,
112
+ register_code=6,
113
+ units=6,
114
+ quantity=12,
115
+ charge=6,
116
+ prev_read_type=1,
117
+ pres_read_type=1,
118
+ mpan_core=13,
119
+ mpan_top=8,
120
+ tariff_code=19,
121
+ pres_read_date=DATE_LENGTH,
122
+ prev_read_date=DATE_LENGTH,
123
+ )
124
+ mpan_core = parts["mpan_core"]
125
+ headers["mpan_core"] = mpan_core
126
+ units = UNITS_LOOKUP[parts["units"].strip()]
127
+ if units == "kwh":
128
+ headers["kwh"] += Decimal(parts["quantity"])
129
+ tpr_code = REGISTER_CODE_LOOKUP[parts["register_code"]]
130
+
131
+ headers["reads"].append(
132
+ {
133
+ "msn": parts["msn"].strip(),
134
+ "mpan": f"{parts['mpan_top']} {mpan_core}",
135
+ "coefficient": 1,
136
+ "units": units,
137
+ "tpr_code": tpr_code,
138
+ "prev_date": parse_date(parts["prev_read_date"]),
139
+ "prev_value": Decimal(parts["prev_read_value"]),
140
+ "prev_type_code": parts["prev_read_type"],
141
+ "pres_date": parse_date(parts["pres_read_date"]),
142
+ "pres_value": Decimal(parts["pres_read_value"]),
143
+ "pres_type_code": parts["pres_read_type"],
144
+ }
145
+ )
146
+
147
+
148
+ def _handle_0470(headers, pre_record, record):
149
+ pass
150
+
151
+
152
+ def _handle_1460(headers, pre_record, record):
153
+ parts = _chop_record(record, unknown_1=1, net=12, vat_rate=5, vat=12)
154
+ net = Decimal(parts["net"]) / Decimal(100)
155
+ vat_rate = int(Decimal(parts["vat_rate"]))
156
+ vat = Decimal(parts["vat"]) / Decimal(100)
157
+
158
+ vat_breakdown = headers["breakdown"]["vat"]
159
+ try:
160
+ vat_bd = vat_breakdown[vat_rate]
161
+ except KeyError:
162
+ vat_bd = vat_breakdown[vat_rate] = {"vat": Decimal("0"), "net": Decimal("0")}
163
+
164
+ vat_bd["vat"] += vat
165
+ vat_bd["net"] += net
166
+
167
+
168
+ def _handle_1500(headers, pre_record, record):
169
+ parts = _chop_record(
170
+ record,
171
+ unknown_1=8,
172
+ unknown_2=10,
173
+ net=10,
174
+ unknown_3=10,
175
+ unknown_4=20,
176
+ vat=10,
177
+ unknown_5=10,
178
+ unknown_6=20,
179
+ gross=12,
180
+ )
181
+ return {
182
+ "bill_type_code": "N",
183
+ "mpan_core": headers["mpan_core"],
184
+ "account": headers["account"],
185
+ "reference": headers["reference"],
186
+ "issue_date": headers["issue_date"],
187
+ "start_date": headers["start_date"],
188
+ "finish_date": headers["finish_date"],
189
+ "kwh": headers["kwh"],
190
+ "net": Decimal(parts["net"]),
191
+ "vat": Decimal(parts["vat"]),
192
+ "gross": Decimal(parts["gross"]),
193
+ "breakdown": headers["breakdown"],
194
+ "reads": headers["reads"],
195
+ }
196
+
197
+
198
+ def _handle_2000(headers, pre_record, record):
199
+ pass
200
+
201
+
202
+ def _handle_9999(headers, pre_record, record):
203
+ pass
204
+
205
+
206
+ LINE_HANDLERS = {
207
+ "0000": _handle_0000,
208
+ "0050": _handle_0050,
209
+ "0051": _handle_0051,
210
+ "0100": _handle_0100,
211
+ "0101": _handle_0101,
212
+ "0460": _handle_0460,
213
+ "0461": _handle_0461,
214
+ "0470": _handle_0470,
215
+ "1460": _handle_1460,
216
+ "1500": _handle_1500,
217
+ "2000": _handle_2000,
218
+ "9999": _handle_9999,
219
+ }
10
220
 
11
221
 
12
222
  class Parser:
@@ -16,41 +226,28 @@ class Parser:
16
226
 
17
227
  def make_raw_bills(self):
18
228
  raw_bills = []
19
- for i, line in enumerate(self.f):
20
- self.line_number = i
21
- record_type = line[62:66]
22
- if record_type == "0100":
23
- account = line[33:41]
24
- reference = line[41:46]
25
- start_date = None
26
- finish_date = None
27
- net = Decimal(0)
28
- vat = Decimal(0)
29
- mpan_core = None
30
- elif record_type == "1460":
31
- net += Decimal(line[67:79]) / Decimal(100)
32
- vat += Decimal(line[85:97]) / Decimal(100)
33
- elif record_type == "0461":
34
- mpan_core = parse_mpan_core(line[135:148])
35
- elif record_type == "0101":
36
- start_date = parse_date(line[66:74])
37
- finish_date = parse_date(line[74:82])
38
- elif record_type == "1500":
39
- raw_bill = {
40
- "bill_type_code": "N",
41
- "mpan_core": mpan_core,
42
- "account": account,
43
- "reference": reference,
44
- "issue_date": start_date,
45
- "start_date": start_date,
46
- "finish_date": finish_date,
47
- "kwh": Decimal("0.00"),
48
- "net": net,
49
- "vat": vat,
50
- "gross": Decimal("0.00"),
51
- "breakdown": {},
52
- "reads": [],
53
- }
54
- raw_bills.append(raw_bill)
229
+ headers = {}
230
+ for self.line_number, line in enumerate(self.f, 1):
231
+ pre_record, record_type, record = line[:80], line[80:84], line[84:]
232
+ try:
233
+ handler = LINE_HANDLERS[record_type]
234
+ except KeyError:
235
+ raise BadRequest(
236
+ f"Record type {record_type} not recognized on line "
237
+ f"{self.line_number} {line}"
238
+ )
239
+
240
+ try:
241
+ bill = handler(headers, pre_record, record)
242
+ except BadRequest as e:
243
+ raise BadRequest(
244
+ f"Problem at line {self.line_number} {line}: {e.description}"
245
+ )
246
+ except BaseException as e:
247
+ raise Exception(
248
+ f"Problem at line {self.line_number} {line}: {e}"
249
+ ) from e
250
+ if bill is not None:
251
+ raw_bills.append(bill)
55
252
 
56
253
  return raw_bills
chellow/e/views.py CHANGED
@@ -5252,6 +5252,10 @@ def supplier_bill_import_get(import_id):
5252
5252
  fields["successful_max_registers"] = max(
5253
5253
  len(bill["reads"]) for bill in imp_fields["successful_bills"]
5254
5254
  )
5255
+ if "failed_bills" in imp_fields and len(imp_fields["failed_bills"]) > 0:
5256
+ fields["failed_max_registers"] = max(
5257
+ len(bill["reads"]) for bill in imp_fields["failed_bills"]
5258
+ )
5255
5259
  fields.update(imp_fields)
5256
5260
  fields["status"] = importer.status()
5257
5261
  return render_template(
chellow/models.py CHANGED
@@ -6400,8 +6400,23 @@ class ReportRun(Base, PersistentClass):
6400
6400
  def insert(sess, name, user, title, data):
6401
6401
  report_run = ReportRun(name, user, title, data)
6402
6402
  sess.add(report_run)
6403
+ sess.flush()
6403
6404
  return report_run
6404
6405
 
6406
+ @staticmethod
6407
+ def w_update(report_run_id, state):
6408
+ with Session() as wsess:
6409
+ report_run = ReportRun.get_by_id(wsess, report_run_id)
6410
+ report_run.update(state)
6411
+ wsess.commit()
6412
+
6413
+ @staticmethod
6414
+ def w_insert_row(report_run_id, tab, titles, values, properties):
6415
+ with Session() as wsess:
6416
+ report_run = ReportRun.get_by_id(wsess, report_run_id)
6417
+ report_run.insert_row(wsess, tab, titles, values, properties)
6418
+ wsess.commit()
6419
+
6405
6420
 
6406
6421
  def _jsonize(val):
6407
6422
  if isinstance(val, dict):
@@ -29,9 +29,9 @@ from chellow.models import (
29
29
  Llfc,
30
30
  MarketRole,
31
31
  MtcParticipant,
32
+ RSession,
32
33
  RegisterRead,
33
34
  ReportRun,
34
- Session,
35
35
  Site,
36
36
  SiteEra,
37
37
  Supply,
@@ -102,19 +102,17 @@ def content(
102
102
  report_run_id,
103
103
  ):
104
104
  caches = {}
105
- tmp_file = sess = supply_id = report_run = None
105
+ tmp_file = sess = supply_id = None
106
106
  forecast_date = to_utc(Datetime.max)
107
107
 
108
108
  try:
109
- with Session() as sess:
109
+ with RSession() as sess:
110
110
  user = User.get_by_id(sess, user_id)
111
111
  tmp_file = open_file(
112
112
  f"bill_check_{fname_additional}.csv", user, mode="w", newline=""
113
113
  )
114
114
  writer = csv.writer(tmp_file, lineterminator="\n")
115
115
 
116
- report_run = ReportRun.get_by_id(sess, report_run_id)
117
-
118
116
  bills = (
119
117
  sess.query(Bill)
120
118
  .order_by(Bill.supply_id, Bill.reference)
@@ -216,30 +214,26 @@ def content(
216
214
  virtual_bill_titles,
217
215
  writer,
218
216
  titles,
219
- report_run,
217
+ report_run_id,
220
218
  )
221
-
222
- report_run.update("finished")
223
- sess.commit()
219
+ ReportRun.w_update(report_run_id, "finished")
224
220
 
225
221
  except BadRequest as e:
226
- if report_run is not None:
227
- report_run.update("problem")
228
222
  if supply_id is None:
229
223
  prefix = "Problem: "
230
224
  else:
231
225
  prefix = f"Problem with supply {supply_id}:"
232
226
  tmp_file.write(prefix + e.description)
227
+ ReportRun.w_update(report_run_id, "problem")
233
228
  except BaseException:
234
- if report_run is not None:
235
- report_run.update("interrupted")
229
+ msg = traceback.format_exc()
230
+ sys.stderr.write(msg + "\n")
236
231
  if supply_id is None:
237
232
  prefix = "Problem: "
238
233
  else:
239
234
  prefix = f"Problem with supply {supply_id}:"
240
- msg = traceback.format_exc()
241
- sys.stderr.write(msg + "\n")
242
235
  tmp_file.write(prefix + msg)
236
+ ReportRun.w_update(report_run_id, "interrupted")
243
237
  finally:
244
238
  if tmp_file is not None:
245
239
  tmp_file.close()
@@ -318,7 +312,7 @@ def _process_supply(
318
312
  virtual_bill_titles,
319
313
  writer,
320
314
  titles,
321
- report_run,
315
+ report_run_id,
322
316
  ):
323
317
  gaps = {}
324
318
  data_sources = {}
@@ -761,8 +755,8 @@ def _process_supply(
761
755
  values["batch_id"] = bill.batch.id
762
756
  values["supply_id"] = supply.id
763
757
  values["site_id"] = None if site_code is None else site.id
764
- report_run.insert_row(
765
- sess, "", report_run_titles, values, {"is_checked": False}
758
+ ReportRun.w_insert_row(
759
+ report_run_id, "", report_run_titles, values, {"is_checked": False}
766
760
  )
767
761
 
768
762
  for bill in sess.query(Bill).filter(
@@ -783,7 +777,7 @@ def _process_supply(
783
777
  )
784
778
 
785
779
  # Avoid long-running transactions
786
- sess.commit()
780
+ sess.rollback()
787
781
 
788
782
  clumps = []
789
783
  for element, elgap in sorted(gaps.items()):
@@ -837,7 +831,7 @@ def _process_supply(
837
831
  vals["supply_id"] = supply.id
838
832
  vals["site_id"] = None if site_code is None else site.id
839
833
 
840
- report_run.insert_row(sess, "", titles, vals, {"is_checked": False})
834
+ ReportRun.w_insert_row(report_run_id, "", titles, vals, {"is_checked": False})
841
835
 
842
836
  # Avoid long-running transactions
843
- sess.commit()
837
+ sess.rollback()
@@ -10,7 +10,7 @@ from sqlalchemy.sql.expression import null, true
10
10
 
11
11
  from chellow.dloads import open_file
12
12
  from chellow.e.computer import SupplySource, forecast_date
13
- from chellow.models import Era, Session, Site, SiteEra, Supply
13
+ from chellow.models import Era, RSession, Site, SiteEra, Supply
14
14
  from chellow.utils import (
15
15
  csv_make_val,
16
16
  hh_format,
@@ -25,7 +25,7 @@ def content(supply_id, start_date, finish_date, user):
25
25
  caches = {}
26
26
  f = None
27
27
  try:
28
- with Session() as sess:
28
+ with RSession() as sess:
29
29
  supply = Supply.get_by_id(sess, supply_id)
30
30
 
31
31
  f_date = forecast_date()
@@ -50,7 +50,19 @@
50
50
  <th>VAT</th>
51
51
  <th>Gross</th>
52
52
  <th>Breakdown</th>
53
- <th>Reads</th>
53
+ {% for i in range(failed_max_registers) %}
54
+ <th>R{{loop.index}} MPAN</th>
55
+ <th>R{{loop.index}} Meter Serial Number</th>
56
+ <th>R{{loop.index}} Coefficient</th>
57
+ <th>R{{loop.index}} Units</th>
58
+ <th>R{{loop.index}} TPR</th>
59
+ <th>R{{loop.index}} Previous Read Date</th>
60
+ <th>R{{loop.index}} Previous Read Value</th>
61
+ <th>R{{loop.index}} Previous Read Type</th>
62
+ <th>R{{loop.index}} Present Read Date</th>
63
+ <th>R{{loop.index}} Present Read Value</th>
64
+ <th>R{{loop.index}} Present Read Type</th>
65
+ {% endfor %}
54
66
  </tr>
55
67
  </thead>
56
68
  <tbody>
@@ -87,7 +99,19 @@
87
99
  <pre>{{bill.breakdown|dumps}}</pre>
88
100
  {% endif %}
89
101
  </td>
90
- <td>{{bill.reads}}</td>
102
+ {% for read in bill.reads %}
103
+ <td>{{read.mpan}}</td>
104
+ <td>{{read.msn}}</td>
105
+ <td>{{read.coefficient}}</td>
106
+ <td>{{read.units}}</td>
107
+ <td>{{read.tpr_code}}</td>
108
+ <td>{{read.prev_date|hh_format}}</td>
109
+ <td>{{read.prev_value}}</td>
110
+ <td>{{read.prev_type_code}}</td>
111
+ <td>{{read.pres_date|hh_format}}</td>
112
+ <td>{{read.pres_value}}</td>
113
+ <td>{{read.pres_type_code}}</td>
114
+ {% endfor %}
91
115
  </tr>
92
116
  {% endfor %}
93
117
  </tbody>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chellow
3
- Version: 1716370405.0.0
3
+ Version: 1716564585.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)
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
9
9
  Requires-Python: >=3.9
10
10
  Requires-Dist: flask-restx==1.2.0
11
11
  Requires-Dist: flask==2.3.3
12
- Requires-Dist: odio==0.0.22
12
+ Requires-Dist: odio==0.0.23
13
13
  Requires-Dist: openpyxl==3.1.2
14
14
  Requires-Dist: paramiko==3.4.0
15
15
  Requires-Dist: pep3143daemon==0.0.6
@@ -21,7 +21,7 @@ Requires-Dist: pypdf==3.17.0
21
21
  Requires-Dist: python-dateutil==2.8.2
22
22
  Requires-Dist: pytz==2022.6
23
23
  Requires-Dist: requests==2.32.2
24
- Requires-Dist: sqlalchemy==2.0.28
24
+ Requires-Dist: sqlalchemy==2.0.30
25
25
  Requires-Dist: waitress==2.1.2
26
26
  Requires-Dist: xlrd==2.0.1
27
27
  Requires-Dist: zish==0.1.11
@@ -5,7 +5,7 @@ chellow/commands.py,sha256=ESBe9ZWj1c3vdZgqMZ9gFvYAB3hRag2R1PzOwuw9yFo,1302
5
5
  chellow/dloads.py,sha256=5SmP-0QPK6xCkd_wjIWh_8FAzN5OxNHCzyEQ1Xb-Y-M,5256
6
6
  chellow/edi_lib.py,sha256=alu20x9ZX06iPfnNI9dEJzuP6RIf4We3Y_M_bl7RrcY,51789
7
7
  chellow/general_import.py,sha256=l3EHq9zG9Vfl5Ee6XTVrC1nusXo4YGGB4VBmZ_JaJR8,65798
8
- chellow/models.py,sha256=2YSRKOt89mgawuz1CV02FsjLi5ue9Np38PGOIS-yoc4,242202
8
+ chellow/models.py,sha256=uS4GHh4RF6yD7aSsN4nOC3hdNakHUjW1nVzrhM_79mQ,242736
9
9
  chellow/national_grid.py,sha256=uxcv0qisHPyzw9AVIYPzsRqwt2XPAcZL-SBR12qcrS0,4364
10
10
  chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
11
11
  chellow/rate_server.py,sha256=fg-Pf_9Hk3bXmC9riPQNGQxBvLvBa_WtNYdwDCjnCSg,5678
@@ -38,7 +38,7 @@ chellow/e/system_price.py,sha256=6w5J7bzwFAZubE2zdOFRiS8IIrVP8hkoIOaG2yCt-Ic,623
38
38
  chellow/e/tlms.py,sha256=M33D6YpMixu2KkwSCzDRM3kThLgShg8exp63Obo75l8,8905
39
39
  chellow/e/tnuos.py,sha256=XseYztPUsQXNKuBmystO2kzzwAG9ehCZgpGBTdgSk-A,4313
40
40
  chellow/e/triad.py,sha256=lIQj7EdUrcFwEqleuHZXYU_bfzIwNOqUVVxB3NPQt4A,13710
41
- chellow/e/views.py,sha256=es1lQWgZjCcHQ7AR_98SM9hLJjX8UUarePuBHnkkJ_4,215037
41
+ chellow/e/views.py,sha256=RQLiAzzWm5RUumvhR1rub1yFTMZ9uksqJIc1IShnXsQ,215256
42
42
  chellow/e/bill_parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=UgWXDPzQkQghyj_lfgBqoSJpHB-t-qOdSaB8qY6GLog,4071
44
44
  chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=-HMoIfa_utXYKA44RuC0Xqv3vd2HLeQU_4P0iBUd3WA,4219
@@ -51,7 +51,7 @@ chellow/e/bill_parsers/gdf_csv.py,sha256=ZfK3Oc6oP28p_P9DIevLNB_zW2WLcEJ3Lvb1gL3
51
51
  chellow/e/bill_parsers/haven_csv.py,sha256=0uENq8IgVNqdxfBQMBxLTSZWCOuDHXZC0xzk52SbfyE,13652
52
52
  chellow/e/bill_parsers/haven_edi.py,sha256=YGPHRxPOhje9s32jqPHHELni2tooOYj3cMC_qaZVPq4,16107
53
53
  chellow/e/bill_parsers/haven_edi_tprs.py,sha256=ZVX9CCqUybsot_Z0BEOJPvl9x5kSr7fEWyuJXvZDcz4,11841
54
- chellow/e/bill_parsers/mm.py,sha256=P4CdkskDrjmFMSDp0ehE_ichTBHGywbT_dckMxuAqQQ,1929
54
+ chellow/e/bill_parsers/mm.py,sha256=b4Tzil_iXyKGvJSSbmMtBwH-4oiwIZthnvueU7CxNwg,6875
55
55
  chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py,sha256=yogXTuQHGRL7IiqvRWr2C9V24ez1j9Yx0128UygPE_k,4723
56
56
  chellow/e/bill_parsers/settlement_dc_stark_xlsx.py,sha256=gKeYMdUO4bVycV8n1lWs5AIfF3bHZLkM6tkasD4rhHs,6239
57
57
  chellow/e/bill_parsers/sse_edi.py,sha256=L85DOfNkqexeEIEr8pCBn_2sHJI-zEaw6cogpE3YyYM,15204
@@ -68,7 +68,7 @@ chellow/gas/transportation.py,sha256=Bkg8TWOs-v0ES-4qqwbleiOhqbE_t2KauUx9JYMZELM
68
68
  chellow/gas/views.py,sha256=ZIMqByN0uBpf3y9wkMi-VogC1-NaHs-oO7WRVDk9Kkw,57428
69
69
  chellow/reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
70
  chellow/reports/report_109.py,sha256=S8fsOwh-jVWGL0RsgyYLdqn00BAvlkBbi4VfTSGI-Mc,11181
71
- chellow/reports/report_111.py,sha256=qU5MYPQzZ_cEvuERE8bxq93D-dN1yd4oML6FIqd0Jdk,28278
71
+ chellow/reports/report_111.py,sha256=AlYjvCDpGNe1qBuzW52EONWDsFaIVElug0Vpe9qm1PY,28169
72
72
  chellow/reports/report_169.py,sha256=tnTiHmhigcgZ7E8rUSfgzsVYUCW947xBZZq04-KqfK8,9287
73
73
  chellow/reports/report_181.py,sha256=mCL6vXfrj8r0kL-LilDS0SnSu5tJOzCq7eMJVx9zpEw,4999
74
74
  chellow/reports/report_183.py,sha256=DZX-hHJPl_Tbgkt31C_cuLZg_5L2b6iCPQ5foOZizR0,8817
@@ -81,7 +81,7 @@ chellow/reports/report_247.py,sha256=ozgCcee8XeqYbOpZCyU2STJKaz6h2x7TYQogagTaYLw
81
81
  chellow/reports/report_29.py,sha256=KDFjgrLBv4WbG9efCdu_geMR7gT_QV9N97Wfdt7aDc4,2736
82
82
  chellow/reports/report_291.py,sha256=rqBXy6s7hMeYWw-yNX6w_L5t2yz6rNEeos_4xO7wf90,7519
83
83
  chellow/reports/report_33.py,sha256=laVz-itDbJTdvC6LxLEeuY0eKpYx43Un4adiExPTEEE,16730
84
- chellow/reports/report_387.py,sha256=KcClrEOK5IRvePp0Jgbzs1Gwf-_CqYmEtFFlXrr_Z3E,5670
84
+ chellow/reports/report_387.py,sha256=kmBZopb0AOivcowO2nPjRj6LnV0_QjCDXLwqPL7IGVE,5672
85
85
  chellow/reports/report_41.py,sha256=QQeTshA1Og7N3wPaoZ8ynJzwsvZ1mgSFc7DDkVqIZoM,7447
86
86
  chellow/reports/report_429.py,sha256=0GCc0rQnOSG0fusw69yMMOCxnWApBd3P2sGWIg1py9M,12359
87
87
  chellow/reports/report_59.py,sha256=CCFPUspUFgoMt6sMFsdtLYW-inA9rN6D-6Kted6vskA,45458
@@ -299,7 +299,7 @@ chellow/templates/e/supplier_batches.html,sha256=ij8LuHc2HzxovBn34aHCMra4pm3Himk
299
299
  chellow/templates/e/supplier_bill.html,sha256=7q79XfUSFPLR5npIXhRpTciQ9rGtNHhp9ryFZWXBhPc,4142
300
300
  chellow/templates/e/supplier_bill_add.html,sha256=BsD-Zh7d9auiqJ61VPHiQrP8u8rTcw09mEKuKH9dxaA,2100
301
301
  chellow/templates/e/supplier_bill_edit.html,sha256=oxZrMcMwrvluJSPxD4yfM9mWNeugoguAwT_ai9Ynl88,2732
302
- chellow/templates/e/supplier_bill_import.html,sha256=XSDURJKvXvI3ee15VqYoUpmF8Ng61Puybwexzk1AFF0,4291
302
+ chellow/templates/e/supplier_bill_import.html,sha256=2_VvBoNE838UwuN0AiMwIrzqxQmWBo5DGY0lY833Bpk,5265
303
303
  chellow/templates/e/supplier_bill_imports.html,sha256=9iTNGWKn9XjQTBP1Sepbo0QVNlgKh7EfizXapam7I6s,9356
304
304
  chellow/templates/e/supplier_contract.html,sha256=oVGrYGIbCb-7MmpFQaXeTNRKBKy8GoGCWICWgo5E4xI,2863
305
305
  chellow/templates/e/supplier_contract_add.html,sha256=gsozEtF24lzYi_Bb4LTenvh62tCt7dQ4CwaIz7rFck4,899
@@ -364,6 +364,6 @@ chellow/templates/g/supply_note_edit.html,sha256=6UQf_qbhFDys3cVsTp-c7ABWZpggW9R
364
364
  chellow/templates/g/supply_notes.html,sha256=WR3YwGh_qqTklSJ7JqWX6BKBc9rk_jMff4RiWZiF2CM,936
365
365
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
366
366
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
367
- chellow-1716370405.0.0.dist-info/METADATA,sha256=TuaScYTcnRt-YAdvw014lKjfOAS9GaelicnQ1FPdkjI,12205
368
- chellow-1716370405.0.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
369
- chellow-1716370405.0.0.dist-info/RECORD,,
367
+ chellow-1716564585.0.0.dist-info/METADATA,sha256=xaQbUGAclcjTkpSWGRS8X8pIe8pSo17WT6dFKZX4nwE,12205
368
+ chellow-1716564585.0.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
369
+ chellow-1716564585.0.0.dist-info/RECORD,,