chellow 1739889885.0.0__py3-none-any.whl → 1740736363.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/computer.py CHANGED
@@ -119,11 +119,15 @@ def contract_func(caches, contract, func_name):
119
119
  return ns.get(func_name, None)
120
120
 
121
121
 
122
- def non_core_rate(sess, caches, contract_id_or_name, date):
123
- return hh_rate(sess, caches, contract_id_or_name, date, market_role_code="Z")
122
+ def non_core_rate(sess, caches, contract_id_or_name, date, exact=False):
123
+ return hh_rate(
124
+ sess, caches, contract_id_or_name, date, market_role_code="Z", exact=exact
125
+ )
124
126
 
125
127
 
126
- def hh_rate(sess, caches, contract_id_or_name, date, market_role_code=None):
128
+ def hh_rate(
129
+ sess, caches, contract_id_or_name, date, market_role_code=None, exact=False
130
+ ):
127
131
  try:
128
132
  ccache = caches["computer"]
129
133
  except KeyError:
@@ -181,18 +185,20 @@ def hh_rate(sess, caches, contract_id_or_name, date, market_role_code=None):
181
185
  )
182
186
 
183
187
  if rs is None:
184
- rs = (
188
+ last_rs = (
185
189
  sess.query(RateScript)
186
190
  .filter(RateScript.contract == contract)
187
191
  .order_by(RateScript.start_date.desc())
188
192
  .first()
189
193
  )
190
- if date < rs.start_date:
194
+ if date < last_rs.start_date:
191
195
  cstart = year_before
192
- cfinish = min(year_after, rs.start_date - HH)
196
+ cfinish = min(year_after, last_rs.start_date - HH)
193
197
  else:
194
- cstart = max(rs.finish_date + HH, year_before)
198
+ cstart = max(last_rs.finish_date + HH, year_before)
195
199
  cfinish = year_after
200
+ if not exact:
201
+ rs = last_rs
196
202
  else:
197
203
  cstart = max(rs.start_date, year_before)
198
204
  if rs.finish_date is None:
@@ -200,23 +206,26 @@ def hh_rate(sess, caches, contract_id_or_name, date, market_role_code=None):
200
206
  else:
201
207
  cfinish = min(rs.finish_date, year_after)
202
208
 
203
- market_role_code = rs.contract.market_role.code
204
- if market_role_code == "M":
205
- seg = "/e/mop_rate_scripts/"
206
- elif market_role_code == "C":
207
- seg = "/e/dc_rate_scripts/"
208
- elif market_role_code == "X":
209
- seg = "/e/supplier_rate_scripts/"
210
- elif market_role_code == "Z":
211
- seg = "/non_core_rate_scripts/"
212
- elif market_role_code == "R":
213
- seg = "/e/dno_rate_scripts/"
209
+ if rs is None:
210
+ vals = None
214
211
  else:
215
- raise Exception(
216
- f"The market role code {market_role_code} isn't recognized."
217
- )
212
+ market_role_code = rs.contract.market_role.code
213
+ if market_role_code == "M":
214
+ seg = "/e/mop_rate_scripts/"
215
+ elif market_role_code == "C":
216
+ seg = "/e/dc_rate_scripts/"
217
+ elif market_role_code == "X":
218
+ seg = "/e/supplier_rate_scripts/"
219
+ elif market_role_code == "Z":
220
+ seg = "/non_core_rate_scripts/"
221
+ elif market_role_code == "R":
222
+ seg = "/e/dno_rate_scripts/"
223
+ else:
224
+ raise Exception(
225
+ f"The market role code {market_role_code} isn't recognized."
226
+ )
218
227
 
219
- vals = PropDict(f"the rate script {seg}{rs.id} ", loads(rs.script), [])
228
+ vals = PropDict(f"the rate script {seg}{rs.id} ", loads(rs.script), [])
220
229
  for dt in hh_range(caches, cstart, cfinish):
221
230
  if dt not in cont_cache:
222
231
  cont_cache[dt] = vals
@@ -572,8 +581,10 @@ class DataSource:
572
581
  self.rate_cache = self.caches["computer"]["rates"]
573
582
  return val
574
583
 
575
- def non_core_rate(self, contract_name_or_id, date):
576
- return non_core_rate(self.sess, self.caches, contract_name_or_id, date)
584
+ def non_core_rate(self, contract_name_or_id, date, exact=False):
585
+ return non_core_rate(
586
+ self.sess, self.caches, contract_name_or_id, date, exact=exact
587
+ )
577
588
 
578
589
  def _add_problem(self, problem):
579
590
  self.supplier_bill["problem"] += problem
chellow/e/tlms.py CHANGED
@@ -36,7 +36,11 @@ def hh(data_source, run="DF"):
36
36
  h["tlm"] = tlm = cache[h["start-date"]][gsp_group_code][run]
37
37
  except KeyError:
38
38
  h_start = h["start-date"]
39
- rates = data_source.non_core_rate("tlms", h_start)["tlms"]
39
+ vals = data_source.non_core_rate("tlms", h_start, exact=True)
40
+ if vals is None:
41
+ vals = data_source.non_core_rate("tlms", h["hist-start"])
42
+
43
+ rates = vals["tlms"]
40
44
 
41
45
  key = key_format(h_start)
42
46
  try:
@@ -6,6 +6,7 @@ from collections import OrderedDict, defaultdict
6
6
  from datetime import datetime as Datetime
7
7
  from decimal import Decimal
8
8
  from itertools import combinations
9
+ from numbers import Number
9
10
 
10
11
  from flask import g, redirect, request
11
12
 
@@ -364,22 +365,61 @@ def _process_g_bill_ids(
364
365
  vals["g_supply_id"] = g_supply.id
365
366
  vals["site_id"] = site_id
366
367
  for element in sorted(elements):
367
- rate_name = f"difference_{element}_rate"
368
- covered_rates = vals.get(f"covered_{element}_rate", [0])
369
- virtual_rates = vals.get(f"virtual_{element}_rate", [0])
370
- if len(covered_rates) == 1 and len(virtual_rates) == 1:
371
- vals[rate_name] = (
372
- float(covered_rates.pop()) * 100 - float(virtual_rates.pop()) * 100
373
- )
368
+ for key in tuple(vals.keys()):
369
+ if not key.endswith("_gbp"):
370
+ covered_prefix = f"covered_{element}_"
371
+ virtual_prefix = f"virtual_{element}_"
372
+ if key.startswith(covered_prefix):
373
+ part_name = key[len(covered_prefix) :]
374
+ elif key.startswith(virtual_prefix):
375
+ part_name = key[len(virtual_prefix) :]
376
+ else:
377
+ continue
378
+ virtual_part = vals.get(f"virtual_{element}_{part_name}", {0})
379
+ covered_part = vals.get(f"covered_{element}_{part_name}", {0})
380
+ if isinstance(virtual_part, set) and len(virtual_part) == 1:
381
+ virtual_part = float(next(iter(virtual_part)))
382
+ if isinstance(covered_part, set) and len(covered_part) == 1:
383
+ covered_part = float(next(iter(covered_part)))
384
+
385
+ if isinstance(virtual_part, Number) and isinstance(
386
+ covered_part, Number
387
+ ):
388
+ diff = float(covered_part) - float(virtual_part)
389
+ else:
390
+ diff = 0
391
+
392
+ vals[f"difference_{element}_{part_name}"] = diff
393
+
394
+ for suffix in (
395
+ "kwh",
396
+ "units_consumed",
397
+ ):
398
+ try:
399
+ covered = float(vals[f"covered_{suffix}"])
400
+ virtual = float(vals[f"virtual_{suffix}"])
401
+ vals[f"difference_{suffix}"] = covered - virtual
402
+ except KeyError:
403
+ vals[f"difference_{suffix}"] = 0
404
+
405
+ for prefix in (
406
+ "correction_factor",
407
+ "unit_code",
408
+ "calorific_value",
409
+ ):
410
+ covered = vals.get(f"covered_{prefix}", [0])
411
+ virtual = vals.get(f"virtual_{prefix}", [0])
412
+ if len(covered) == 1 and len(virtual) == 1:
413
+ if covered == virtual:
414
+ diff = 0
415
+ else:
416
+ try:
417
+ diff = float(next(iter(covered))) - float(next(iter(virtual)))
418
+ except ValueError:
419
+ diff = False
374
420
  else:
375
- vals[rate_name] = 0
376
-
377
- try:
378
- covered_kwh = float(vals["covered_kwh"])
379
- virtual_kwh = float(vals["virtual_kwh"])
380
- vals["difference_kwh"] = covered_kwh - virtual_kwh
381
- except KeyError:
382
- vals["difference_kwh"] = None
421
+ diff = False
422
+ vals[f"difference_{prefix}"] = diff
383
423
 
384
424
  ReportRun.w_insert_row(report_run_id, "", titles, vals, {"is_checked": False})
385
425
 
@@ -1,5 +1,16 @@
1
1
  {% extends "base.html" %}
2
2
 
3
+ {% block inside_head %}
4
+ <style>
5
+ section.elements {
6
+ display: flex;
7
+ flex-wrap: wrap;
8
+ gap: 4em;
9
+ align-items: flex-start;
10
+ }
11
+ </style>
12
+ {% endblock %}
13
+
3
14
  {% block title %}
4
15
  &raquo; Report Runs &raquo; {{row.report_run.id}} &raquo; Row {{row.id}}
5
16
  {% endblock %}
@@ -10,146 +21,173 @@
10
21
  &raquo; Row {{row.id}}
11
22
  {% endblock %}
12
23
 
24
+
13
25
  {% block content %}
14
26
  {% set values = row.data['values'] %}
15
27
  {% set properties = row.data.get('properties', {}) %}
16
- {% if row.report_run.name == 'bill_check' %}
28
+ <table>
29
+ <caption>Bill Check</caption>
30
+ <thead>
31
+ <tr>
32
+ <th>Batch</th>
33
+ <th>Site</th>
34
+ <th>MPRN</th>
35
+ <th>Covered Bills</th>
36
+ <th>Covered Start</th>
37
+ <th>Covered Finish</th>
38
+ <th>Problem</th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr>
43
+ <td><a href="/g/batches/{{values.g_batch_id}}">{{values.batch}}</a></td>
44
+ <td>
45
+ <a href="/sites/{{values.site_id}}">{{values.site_code}} {{values.site_name}}</a>
46
+ </td>
47
+ <td>
48
+ <a href="/g/supplies/{{values.g_supply_id}}">{{values.mprn}}</a>
49
+ </td>
50
+ <td>
51
+ {% if values['covered_bill_ids'] is not none %}
52
+ {% for bill_id in values['covered_bill_ids'] %}
53
+ <a href="/g/bills/{{bill_id}}">{{bill_id}}</a>
54
+ {% if bill_id == values.g_bill_id %}
55
+ {% endif %}
56
+ {% endfor %}
57
+ {% endif %}
58
+ </td>
59
+ <td><span title="{{values.covered_start}}">{{values.covered_start[:10]}}</span></td>
60
+ <td><span title="{{values.covered_finish}}">{{values.covered_finish[:10]}}</span></td>
61
+ {% for title in columns %}
62
+ <td>
63
+ {% if title in values and values[title] is not none %}
64
+ {{"%.2f"|format(values[title])}}
65
+ {% endif %}
66
+ </td>
67
+ {% endfor %}
68
+ <td>
69
+ {{ values.covered_problem }} {{ values.virtual_problem }}
70
+ </td>
71
+ </tr>
72
+ </tbody>
73
+ </table>
74
+
75
+ <section class="elements">
17
76
  <table>
18
- <caption>Bill Check</caption>
77
+ <caption>GBP</caption>
19
78
  <thead>
20
79
  <tr>
21
- <th rowspan="2">Batch</th>
22
- <th colspan="8">Bill</th>
23
- <th colspan="2">MPAN Core</th>
24
- <th colspan="2">Site</th>
25
- <th rowspan="2">Checking</th>
26
- </tr>
27
- <tr>
28
- <th>Reference</th>
29
- <th>Type</th>
30
- <th>kWh</th>
31
- <th>Net GBP</th>
32
- <th>VAT GBP</th>
33
- <th>Gross GBP</th>
34
- <th>Start</th>
35
- <th>Finish</th>
36
- <th>Import</th>
37
- <th>Export</th>
38
- <th>Code</th>
39
- <th>Name</th>
80
+ <th>Part</th>
81
+ <th>Covered</th>
82
+ <th>Virtual</th>
83
+ <th>Difference</th>
40
84
  </tr>
41
85
  </thead>
42
86
  <tbody>
43
- <tr>
44
- <td>
45
- {% if values.batch_id != None %}
46
- <a href="/e/supplier_batches/{{values.batch_id}}">{{values['batch']}}</a>
47
- {% endif %}
48
- </td>
49
- <td>
50
- {% if values.bill_id != None %}
51
- <a href="/e/supplier_bills/{{values.bill_id}}">{{
52
- values['bill-reference']}}</a>
53
- {% endif %}
54
- </td>
55
- <td>{{values['bill-type']}}</td>
56
- <td>{{values['bill-kwh']}}</td>
57
- <td>{{values['bill-net-gbp']}}</td>
58
- <td>{{values['bill-vat-gbp']}}</td>
59
- <td>{{values['bill-gross-gbp']}}</td>
60
- <td>{{values['bill-start-date']}}</td>
61
- <td>{{values['bill-finish-date']}}</td>
62
- <td>
63
- {% if values['imp-mpan-core'] != None %}
64
- <a href="/e/supplies/{{values.supply_id}}">{{
65
- values['imp-mpan-core']}}</a>
66
- {% endif %}
67
- </td>
68
- <td>
69
- {% if values['exp-mpan-core'] != None %}
70
- <a href="/e/supplies/{{values.supply_id}}">{{
71
- values['exp-mpan-core']}}</a>
72
- {% endif %}
73
- </td>
74
- <td>
75
- {% if values.site_id != None %}
76
- <a href="/sites/{{values.site_id}}">{{
77
- values['site-code']}}</a>
78
- {% endif %}
79
- </td>
80
- <td>{{values['site-name']}}</td>
81
- <td>
82
- <form action="/report_run_rows/{{row.id}}" method="post">
83
- <fieldset>
84
- {{input_textarea(
85
- 'note', properties.note, 5, 40,
86
- placeholder='Notes on checking go here...')}}
87
- <br>
88
- <br>
89
- <label>Checked?
90
- {{input_checkbox('is_checked', properties.is_checked)}}
91
- </label>
92
- <input type="submit" name="update" value="Update">
93
- </fieldset>
94
- </form>
95
- </td>
96
- </tr>
97
- </tbody>
87
+ {% if 'difference_gross_gbp' in values %}
88
+ <tr>
89
+ <td>gross</td>
90
+ <td>{{"{:0,.2f}".format(values.covered_gross_gbp)}}</td>
91
+ <td>{{"{:0,.2f}".format(values.virtual_gross_gbp)}}</td>
92
+ <td>{{"{:0,.2f}".format(values.difference_gross_gbp)}}</td>
93
+ </tr>
94
+ {% endif %}
95
+ <tr>
96
+ <td>net</td>
97
+ <td>{{"{:0,.2f}".format(values.covered_net_gbp)}}</td>
98
+ <td>{{"{:0,.2f}".format(values.virtual_net_gbp)}}</td>
99
+ <td>{{"{:0,.2f}".format(values.difference_net_gbp)}}</td>
100
+ </tr>
101
+ {% if 'difference_vat_gbp' in values %}
102
+ <tr>
103
+ <td>vat</td>
104
+ <td>{{"{:0,.2f}".format(values.covered_vat_gbp)}}</td>
105
+ <td>{{"{:0,.2f}".format(values.virtual_vat_gbp)}}</td>
106
+ <td>{{"{:0,.2f}".format(values.difference_vat_gbp)}}</td>
107
+ </tr>
108
+ {% endif %}
109
+ {% if 'difference_vat_rate' in values and values.difference_vat_rate != 0 %}
110
+ <tr>
111
+ <td>vat_rate</td>
112
+ <td>{{values.covered_vat_rate}}</td>
113
+ <td>{{values.virtual_vat_rate}}</td>
114
+ <td>{{"{:0,.2f}".format(values.difference_vat_rate)}}</td>
115
+ </tr>
116
+ {% endif %}
117
+ {% if 'difference_is_commercial' in values %}
118
+ <tr>
119
+ <td>is_commercial</td>
120
+ <td>{{values.covered_is_commercial}}</td>
121
+ <td>{{values.virtual_is_commercial}}</td>
122
+ <td>{{values.difference_is_commercial}}</td>
123
+ </tr>
124
+ {% endif %}
125
+
98
126
  </table>
99
127
 
100
128
  <table>
101
- <caption>Covered</caption>
129
+ <caption>kWh</caption>
102
130
  <thead>
103
131
  <tr>
104
- <th>From</th>
105
- <th>To</th>
106
- <th>Bills</th>
107
- <th>Metered kWh</th>
108
- <th>Net GBP</th>
109
- <th>Virtual Net GBP</th>
110
- <th>Difference GBP</th>
111
- <th>Problem</th>
112
- <th>Virtual Problem</th>
132
+ <th>Part</th>
133
+ <th>Covered</th>
134
+ <th>Virtual</th>
135
+ <th>Difference</th>
113
136
  </tr>
114
137
  </thead>
115
138
  <tbody>
116
139
  <tr>
117
- <td>{{values['covered-from']}}</td>
118
- <td>{{values['covered-to']}}</td>
140
+ <td>kwh</td>
141
+ <td>{{"{:0,.2f}".format(values.covered_kwh)}}</td>
142
+ <td>{{"{:0,.2f}".format(values.virtual_kwh)}}</td>
143
+ <td>{{"{:0,.2f}".format(values.difference_kwh)}}</td>
144
+ </tr>
145
+ <tr>
146
+ <td>units_consumed</td>
119
147
  <td>
120
- {% if values['covered-bills'] != None %}
121
- <ul>
122
- {% for bill_id in values['covered-bills'] %}
123
- <li>
124
- <a href="/e/supplier_bills/{{bill_id}}">{{bill_id}}</a>
125
- {% if bill_id == values.bill_id %}
126
- (This bill)
127
- {% endif %}
128
- </li>
129
- {% endfor %}
130
- </ul>
148
+ {% if 'covered_units_consumed' in values %}
149
+ {{"{:0,.2f}".format(values.covered_units_consumed)}}
131
150
  {% endif %}
132
151
  </td>
152
+ <td>{{"{:0,.2f}".format(values.virtual_units_consumed)}}</td>
153
+ <td>{{"{:0,.2f}".format(values.difference_units_consumed)}}</td>
154
+ </tr>
155
+ <tr>
156
+ <td>correction_factor</td>
133
157
  <td>
134
- {% if values['metered-kwh'] != None %}
135
- {{"%.0f"|format(values['metered-kwh'])}}
158
+ {% if values.covered_correction_factor is number %}
159
+ {{"{:0,.2f}".format(values.covered_correction_factor)}}
160
+ {% else %}
161
+ {{values.covered_correction_factor|join(' | ')}}
136
162
  {% endif %}
137
163
  </td>
138
- <td>{{values['covered-net-gbp']}}</td>
139
164
  <td>
140
- {% if values['virtual-net-gbp'] != None %}
141
- {{"%.2f"|format(values['virtual-net-gbp'])}}
165
+ {% if values.virtual_correction_factor is number %}
166
+ {{"{:0,.2f}".format(values.virtual_correction_factor)}}
167
+ {% else %}
168
+ {{values.virtual_correction_factor|join(' | ')}}
142
169
  {% endif %}
143
170
  </td>
144
171
  <td>
145
- {% if values['difference-net-gbp'] != None %}
146
- {{"%.2f"|format(values['difference-net-gbp'])}}
172
+ {% if values.difference_correction_factor is number %}
173
+ {{"{:0,.2f}".format(values.difference_correction_factor)}}</td>
174
+ {% else %}
175
+ {{values.difference_correction_factor|join(' | ')}}
147
176
  {% endif %}
148
177
  </td>
149
- <td>{{values['covered-problem']}}</td>
150
- <td>{{values['virtual-problem']}}</td>
151
178
  </tr>
152
- </tbody>
179
+ <tr>
180
+ <td>unit_code</td>
181
+ <td>{{values.covered_unit_code|join(' | ')}}</td>
182
+ <td>{{values.virtual_unit_code|join(' | ')}}</td>
183
+ <td>{{values.difference_unit_code}}</td>
184
+ </tr>
185
+ <tr>
186
+ <td>calorific_value</td>
187
+ <td>{{values.covered_calorific_value|join(' | ')}}</td>
188
+ <td>{{values.virtual_calorific_value|join(' | ')}}</td>
189
+ <td>{{values.difference_calorific_value}}</td>
190
+ </tr>
153
191
  </table>
154
192
 
155
193
  {% for table in tables %}
@@ -157,35 +195,67 @@
157
195
  <caption>{{table.name}}</caption>
158
196
  <thead>
159
197
  <tr>
160
- {% for title in table.titles %}
161
- <th>{{title}}</th>
162
- {% endfor %}
198
+ <th>Part</th>
199
+ <th>Covered</th>
200
+ <th>Virtual</th>
201
+ <th>Difference</th>
163
202
  </tr>
164
203
  </thead>
165
204
  <tbody>
166
205
  <tr>
167
- {% for v in table['values'] %}
168
- <td>{{v}}</td>
206
+ <td>gbp</td>
207
+ {% for pref in ('covered_', 'virtual_', 'difference_') %}
208
+ <td>
209
+ {% set k = pref + table.name + "_gbp" %}
210
+ {% if k in values %}
211
+ {% set val = values[k] %}
212
+ {% else %}
213
+ {% set val = '' %}
214
+ {% endif %}
215
+ {% if val is number %}
216
+ {{"{:0,.2f}".format(val)}}
217
+ {% else %}
218
+ {{val}}
219
+ {% endif %}
220
+ </td>
169
221
  {% endfor %}
170
222
  </tr>
223
+ {% for part in table['parts']|sort %}
224
+ <tr>
225
+ <td>{{part}}</td>
226
+ {% for pref in ('covered_', 'virtual_', 'difference_') %}
227
+ <td>
228
+ {% set k = pref + table.name + "_" + part %}
229
+ {% if k in values %}
230
+ {% set val = values[k] %}
231
+ {% else %}
232
+ {% set val = '' %}
233
+ {% endif %}
234
+ {% if val is number %}
235
+ {{"{:0,.2f}".format(val)}}
236
+ {% elif (val is string) or (val is boolean) %}
237
+ {{val}}
238
+ {% else %}
239
+ {% for v in val %}
240
+ {% if v is number %}
241
+ {{"{:0,.2f}".format(v)}}
242
+ {% else %}
243
+ {{v}}
244
+ {% endif %}
245
+ {% if not loop.last %}
246
+ |
247
+ {% endif %}
248
+ {% endfor %}
249
+ {% endif %}
250
+ </td>
251
+ {% endfor %}
252
+ </tr>
253
+ {% endfor %}
171
254
  </tbody>
172
255
  </table>
173
256
  {% endfor %}
257
+ </section>
174
258
 
175
- <h2>Raw</h2>
176
- <pre>{{raw_data}}</pre>
177
-
178
- {% else %}
179
- <table>
180
- <caption>Report Run Row</caption>
181
- <tbody>
182
- {% for title in row.data.titles %}
183
- <tr>
184
- <th>{{title}}</th>
185
- <td>{{row.data['values'][title]}}</td>
186
- </tr>
187
- {% endfor %}
188
- </tbody>
189
- </table>
190
- {% endif %}
259
+ <h2>Raw</h2>
260
+ <pre>{{raw_data}}</pre>
191
261
  {% endblock %}
chellow/views.py CHANGED
@@ -1617,6 +1617,11 @@ def report_run_row_get(row_id):
1617
1617
  "report_run_row_bill_check.html", row=row, raw_data=raw_data, tables=tables
1618
1618
  )
1619
1619
  elif row.report_run.name == "g_bill_check":
1620
+ g_contract = GContract.get_by_id(g.sess, row.report_run.data["g_contract_id"])
1621
+ g_contract_props = g_contract.make_properties()
1622
+ props = g_contract_props.get("report_run", {})
1623
+ table_names_hide = props.get("table_names_hide", [])
1624
+
1620
1625
  values = row.data["values"]
1621
1626
  elements = {}
1622
1627
  for t in row.data["values"].keys():
@@ -1625,34 +1630,31 @@ def report_run_row_get(row_id):
1625
1630
  t.startswith("covered_")
1626
1631
  or t.startswith("virtual_")
1627
1632
  or t.startswith("difference_")
1628
- ) and t not in (
1629
- "covered_from",
1630
- "covered_to",
1631
- "covered_bills",
1632
- "covered_problem",
1633
- "virtual_problem",
1634
- ):
1633
+ ) and t.endswith("_gbp"):
1635
1634
  toks = t.split("_")
1636
1635
  name = "_".join(toks[1:-1])
1636
+ if name in ("vat", "gross", "net") or name in table_names_hide:
1637
+ continue
1637
1638
  try:
1638
1639
  table = elements[name]
1639
1640
  except KeyError:
1640
- table = elements[name] = {"order": 0}
1641
+ table = elements[name] = {"order": 0, "name": name, "parts": set()}
1642
+ tables.append(table)
1641
1643
 
1642
- if "titles" not in table:
1643
- table["titles"] = []
1644
- table["titles"].append(toks[0] + "_" + "_".join(toks[2:]))
1645
- if "values" not in table:
1646
- table["values"] = []
1647
- table["values"].append(values[t])
1648
- if t.startswith("difference_") and t.endswith("-gbp"):
1649
- table["order"] = abs(values[t])
1644
+ for t in row.data["values"].keys():
1650
1645
 
1651
- for k, v in elements.items():
1652
- if k == "net":
1653
- continue
1654
- v["name"] = k
1655
- tables.append(v)
1646
+ toks = t.split("_")
1647
+ if toks[0] in ("covered", "virtual", "difference"):
1648
+ tail = "_".join(toks[1:])
1649
+ for element in elements.keys():
1650
+ table = elements[element]
1651
+ elstr = f"{element}_"
1652
+ if tail.startswith(elstr):
1653
+ part = tail[len(elstr) :]
1654
+ if part != "gbp":
1655
+ table["parts"].add(part)
1656
+ if t.startswith("difference_") and t.endswith("_gbp"):
1657
+ table["order"] = abs(values[t])
1656
1658
 
1657
1659
  tables.sort(key=lambda t: t["order"], reverse=True)
1658
1660
  return render_template(
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chellow
3
- Version: 1739889885.0.0
3
+ Version: 1740736363.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)
7
7
  Classifier: Operating System :: OS Independent
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Requires-Python: >=3.9
10
- Requires-Dist: flask-restx==1.2.0
11
- Requires-Dist: flask==2.3.3
10
+ Requires-Dist: flask-restx==1.3.0
11
+ Requires-Dist: flask==3.1.0
12
+ Requires-Dist: jsonschema==4.17.3
12
13
  Requires-Dist: odio==0.0.23
13
14
  Requires-Dist: openpyxl==3.1.2
14
15
  Requires-Dist: paramiko==3.4.1
@@ -12,7 +12,7 @@ chellow/rate_server.py,sha256=fg-Pf_9Hk3bXmC9riPQNGQxBvLvBa_WtNYdwDCjnCSg,5678
12
12
  chellow/rrun.py,sha256=1Kt2q_K9UoDG_nsZz-Q6XJiMNKroWqlqFdxn2M6Q8CA,2088
13
13
  chellow/testing.py,sha256=Od4HHH6pZrhJ_De118_F55RJEKmAvhUH2S24QE9qFQk,3635
14
14
  chellow/utils.py,sha256=Ej7dsbQ6Ee8X2aZ7B2Vs-hUFCsMABioAdOV1DJjwY-0,19293
15
- chellow/views.py,sha256=82V1OtdscrAmbiT3B5MDZoCe50fDSJwfBF-PpbB5tm8,83513
15
+ chellow/views.py,sha256=2WCU-_8lDuSDROvNlCGsAQVLSMh5qrD2wmeSr2G-umA,83872
16
16
  chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
18
18
  chellow/e/bill_importer.py,sha256=7UcnqNlKbJc2GhW9gy8sDp9GuqambJVpZLvbafOZztA,7411
@@ -20,7 +20,7 @@ chellow/e/bmarketidx.py,sha256=C0BaHn2RxIuWH2QzA-OmSP0fbUGvW9tqEUhLnzOEdmA,7968
20
20
  chellow/e/bsuos.py,sha256=hdP9vnOJSuZl46OAkJeUg1XJYvYIBj4J6Sqce1Hy9Vs,15542
21
21
  chellow/e/ccl.py,sha256=30dh_SvlgzsTQPPAJNZWILaMvbeDsv9-P-S1JxS5_SQ,3184
22
22
  chellow/e/cfd.py,sha256=Gm435c42LFwZx1n-1UY1Tdx6mL1is7E0vRLWQe8RPOo,14184
23
- chellow/e/computer.py,sha256=Fq4SpEvCLArZHOGgSGqvm7mdAVLiswnNWspuuft4h70,67460
23
+ chellow/e/computer.py,sha256=KkYNaD4W13s_BvtyPrYbfZ9MU73hKi-IIL-g4OOQxBA,67787
24
24
  chellow/e/dno_rate_parser.py,sha256=A5TP6KjyfT5lVWh7dX4SiXRi6wnf2lGv-H_T4Sod8CI,21731
25
25
  chellow/e/duos.py,sha256=nwviRjz-qIt3GxIMHk0hItIT4dtKsxOWq9TUC1z-hO8,30864
26
26
  chellow/e/elexon.py,sha256=ALhXS9Es7PV0z9ukPbIramn3cf3iLyFi-PMWPSm5iOs,5487
@@ -40,7 +40,7 @@ chellow/e/rcrc.py,sha256=92CA1uIotIHd1epQ_jEPdJKzXqDFV-AoJOJeRO6MEyA,4274
40
40
  chellow/e/ro.py,sha256=dZKZv_9wXSWuwcb3jiKavoD_9ot-PZseNVeEEe0siLo,596
41
41
  chellow/e/scenario.py,sha256=FLgh03r_SgXx0hMWFbAvwsz2ScDL8LUwYWSWVv2rQlg,24973
42
42
  chellow/e/system_price.py,sha256=6w5J7bzwFAZubE2zdOFRiS8IIrVP8hkoIOaG2yCt-Ic,6232
43
- chellow/e/tlms.py,sha256=M33D6YpMixu2KkwSCzDRM3kThLgShg8exp63Obo75l8,8905
43
+ chellow/e/tlms.py,sha256=Wb9ZuxscMzxXs0FT06Iu5YXeccmO6ai_mUjnJGJwTM4,9045
44
44
  chellow/e/tnuos.py,sha256=NBmc-f3oezrl4gviAKobljHfICTpBKxxxEGBGJi_lRk,4927
45
45
  chellow/e/triad.py,sha256=lIQj7EdUrcFwEqleuHZXYU_bfzIwNOqUVVxB3NPQt4A,13710
46
46
  chellow/e/views.py,sha256=ZDVUirf0fMLO8aS5gF3xpPnRDmNqYxxGHkGjxm0_AY4,220901
@@ -90,7 +90,7 @@ chellow/reports/report_291.py,sha256=BnWtxe0eWN2QKKWpwjs5-RI5LbReBKL119QbkrkNhV8
90
90
  chellow/reports/report_33.py,sha256=lt1EN_LNx6u-AgdaS3YRkPMZA33JgMcELolHF4oJUMw,16689
91
91
  chellow/reports/report_387.py,sha256=bBqtnGGDWIXzXe2zVm9yeDRZKNgkUaOS3XTX6k09f18,5631
92
92
  chellow/reports/report_41.py,sha256=8xUIN9D5dtT0Dn1RmbnWsLRmM-QbGA5xGhWCK3ljAzA,7406
93
- chellow/reports/report_429.py,sha256=SbFlBsHXWMWRlMbY_e0zco2R8tMG9XVulr56E3mRalU,14287
93
+ chellow/reports/report_429.py,sha256=1LzrhfePeLg98eczzxy9HrR0EYcPYINw1LSJKk9kKAM,15812
94
94
  chellow/reports/report_59.py,sha256=PkdRA6ctvDGWTQd5vb9cQH6MG920TxcD6aHh268zrj8,42221
95
95
  chellow/reports/report_81.py,sha256=bBpV6MtvKGtoLiqzZoK2h21KDs4vfDwy-etpfL9oiEI,5570
96
96
  chellow/reports/report_87.py,sha256=udzbCuXcckWD-OHmfJCT6bwg_paYhm4vfDWlL8WM-jA,6933
@@ -146,7 +146,7 @@ chellow/templates/report_run_g_bill_check.html,sha256=tOXl_mjR__foYKiOYflJbK-459
146
146
  chellow/templates/report_run_monthly_duration_org.html,sha256=gGNGJ4Q50q4BtIMi98rhO-7NqRHcsFUmbj2qzeOLejw,1713
147
147
  chellow/templates/report_run_row.html,sha256=bmtcdqJaS1CXpL0i8PuqvmeF98jKNYX5-mnQu-OuDKQ,3791
148
148
  chellow/templates/report_run_row_bill_check.html,sha256=aC2LMu_6NvmTN3ZdxHJPPPczyxPN6hg0F-PPcqIWUws,4683
149
- chellow/templates/report_run_row_g_bill_check.html,sha256=aC2LMu_6NvmTN3ZdxHJPPPczyxPN6hg0F-PPcqIWUws,4683
149
+ chellow/templates/report_run_row_g_bill_check.html,sha256=2Ym9mkwvA_DGDrgktDDwXQXlUK7tR2aR3gp3KUqMLoI,7017
150
150
  chellow/templates/report_run_supply_contacts.html,sha256=JNzwz9M6qbLRDMkCzFCxxANapUer5klxo7t5a48nAzg,2117
151
151
  chellow/templates/report_runs.html,sha256=ecoIkl2WtfYtifiTxnslmpMGYYGVQW-CVSBpqhXyiE4,1131
152
152
  chellow/templates/scenario.html,sha256=tCoq1wBq4l9PRS-zFtPcCWXlxD_SSFvFFkERf4FWVNU,2055
@@ -378,6 +378,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
378
378
  chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
379
379
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
380
380
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
381
- chellow-1739889885.0.0.dist-info/METADATA,sha256=iQJxsDUYm0NRHUc8O70ShLjSedd-0j5cjZh_5ojdJuw,12204
382
- chellow-1739889885.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
383
- chellow-1739889885.0.0.dist-info/RECORD,,
381
+ chellow-1740736363.0.0.dist-info/METADATA,sha256=qWpHKbIMKoTX4yjpi3XczaOvWuvWo2PVOHgflg919HY,12238
382
+ chellow-1740736363.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
383
+ chellow-1740736363.0.0.dist-info/RECORD,,