chellow 1753706177.0.0__py3-none-any.whl → 1754570085.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.

@@ -449,11 +449,18 @@ def _process_MTR(elements, headers):
449
449
 
450
450
 
451
451
  def _process_VAT(elements, headers):
452
+ breakdown = headers["breakdown"]
452
453
  vat = Decimal("0.00") + to_decimal(elements["UVTT"]) / Decimal("100")
453
454
  vat_percentage = to_decimal(elements["VATP"]) / Decimal("1000")
455
+
456
+ if "vat_rate" in breakdown:
457
+ vat_rate = breakdown["vat-rate"]
458
+ else:
459
+ vat_rate = breakdown["vat-rate"] = set()
460
+ vat_rate.add(vat_percentage / Decimal("100"))
454
461
  vat_net = Decimal("0.00") + to_decimal(elements["UVLA"]) / Decimal("100")
455
462
 
456
- headers["breakdown"]["vat"][vat_percentage] = {"vat": vat, "net": vat_net}
463
+ breakdown["vat"][vat_percentage] = {"vat": vat, "net": vat_net}
457
464
 
458
465
 
459
466
  def _process_NOOP(elements, headers):
@@ -54,7 +54,7 @@ TCOD_MAP = {
54
54
  "839829": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
55
55
  "649282": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
56
56
  "068476": ("day-gbp", "day-rate", "day-kwh"),
57
- "133186": ("day-gbp", "day-rate", "day-kwh"),
57
+ "133186": ("nrg-gbp", "nrg-rate", "nrg-kwh"),
58
58
  "400434": ("day-gbp", "day-rate", "day-kwh"),
59
59
  "219182": (
60
60
  "duos-availability-gbp",
@@ -109,7 +109,7 @@ TCOD_MAP = {
109
109
  "220894": ("winter-night-gbp", "winter-night-rate", "winter-night-kwh"),
110
110
  "264929": ("winter-weekday-gbp", "winter-weekday-rate", "winter-weekday-kwh"),
111
111
  "638187": ("winter-weekend-gbp", "winter-weekend-rate", "winter-weekend-kwh"),
112
- "700285": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
112
+ "700285": ("standing-gbp", "standing-rate", "standing-days"),
113
113
  }
114
114
 
115
115
  TPR_LOOKUP = {
@@ -330,6 +330,13 @@ def _process_VAT(elements, headers):
330
330
  else:
331
331
  vat_breakdown = bd["vat"] = {}
332
332
 
333
+ if "vat-rate" in bd:
334
+ vat_rate = bd["vat-rate"]
335
+ else:
336
+ vat_rate = bd["vat-rate"] = set()
337
+
338
+ vat_rate.add(vat_percentage / Decimal("100"))
339
+
333
340
  try:
334
341
  vat_values = vat_breakdown[vat_percentage]
335
342
  except KeyError:
chellow/e/ro.py CHANGED
@@ -15,4 +15,5 @@ def hh(supply_source):
15
15
 
16
16
  ro_kwh = hh["msp-kwh"]
17
17
  hh["ro-msp-kwh"] = ro_kwh
18
+ hh["ro-kwh"] = ro_kwh
18
19
  hh["ro-gbp"] = ro_kwh * ro_rate
@@ -6,6 +6,7 @@ from collections import 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 dateutil.relativedelta import relativedelta
11
12
 
@@ -775,6 +776,33 @@ def _process_supply(
775
776
  values["batch_id"] = bill.batch.id
776
777
  values["supply_id"] = supply.id
777
778
  values["site_id"] = None if site_code is None else site.id
779
+ for key in tuple(values.keys()):
780
+ for element in sorted(long_map.keys(), key=len, reverse=True):
781
+ if not key.endswith("-gbp"):
782
+ covered_prefix = f"covered-{element}-"
783
+ virtual_prefix = f"virtual-{element}-"
784
+ if key.startswith(covered_prefix):
785
+ part_name = key[len(covered_prefix) :]
786
+ elif key.startswith(virtual_prefix):
787
+ part_name = key[len(virtual_prefix) :]
788
+ else:
789
+ continue
790
+ virtual_part = values.get(f"virtual-{element}-{part_name}", {0})
791
+ covered_part = values.get(f"covered-{element}-{part_name}", {0})
792
+ if isinstance(virtual_part, set) and len(virtual_part) == 1:
793
+ virtual_part = next(iter(virtual_part))
794
+ if isinstance(covered_part, set) and len(covered_part) == 1:
795
+ covered_part = next(iter(covered_part))
796
+
797
+ if isinstance(virtual_part, Number) and isinstance(
798
+ covered_part, Number
799
+ ):
800
+ diff = float(covered_part) - float(virtual_part)
801
+ else:
802
+ diff = None
803
+
804
+ values[f"difference-{element}-{part_name}"] = diff
805
+ break
778
806
  ReportRun.w_insert_row(
779
807
  report_run_id, "", report_run_titles, values, {"is_checked": False}
780
808
  )
@@ -8,7 +8,7 @@ from dateutil.relativedelta import relativedelta
8
8
 
9
9
  from flask import flash, g, make_response, redirect, render_template, request
10
10
 
11
- import odio
11
+ from odio import create_spreadsheet
12
12
 
13
13
  from sqlalchemy import or_, select, true
14
14
  from sqlalchemy.sql.expression import null
@@ -63,10 +63,10 @@ def write_spreadsheet(
63
63
  ):
64
64
  fl.seek(0)
65
65
  fl.truncate()
66
- with odio.create_spreadsheet(fl, "1.2", compressed=compressed) as f:
67
- f.append_table("Site Level", site_rows)
68
- f.append_table("Era Level", era_rows)
69
- f.append_table("Normal Reads", read_rows)
66
+ with create_spreadsheet(fl, compressed=compressed) as sheet:
67
+ sheet.append_table("Site Level", site_rows)
68
+ sheet.append_table("Era Level", era_rows)
69
+ sheet.append_table("Normal Reads", read_rows)
70
70
 
71
71
 
72
72
  def make_bill_row(titles, bill):
@@ -7,7 +7,7 @@ from dateutil.relativedelta import relativedelta
7
7
 
8
8
  from flask import flash, g, make_response, redirect, render_template, request
9
9
 
10
- import odio
10
+ from odio import create_spreadsheet
11
11
 
12
12
  from sqlalchemy import or_, select, true
13
13
  from sqlalchemy.sql.expression import null
@@ -58,11 +58,11 @@ CATEGORY_ORDER = {None: 0, "unmetered": 1, "nhh": 2, "amr": 3, "hh": 4}
58
58
  def write_spreadsheet(fl, compressed, site_rows, supply_rows, era_rows, read_rows):
59
59
  fl.seek(0)
60
60
  fl.truncate()
61
- with odio.create_spreadsheet(fl, "1.2", compressed=compressed) as f:
62
- f.append_table("Site Level", site_rows)
63
- f.append_table("Supply Level", supply_rows)
64
- f.append_table("Era Level", era_rows)
65
- f.append_table("Normal Reads", read_rows)
61
+ with create_spreadsheet(fl, compressed=compressed) as sheet:
62
+ sheet.append_table("Site Level", site_rows)
63
+ sheet.append_table("Supply Level", supply_rows)
64
+ sheet.append_table("Era Level", era_rows)
65
+ sheet.append_table("Normal Reads", read_rows)
66
66
 
67
67
 
68
68
  def make_bill_row(titles, bill):
@@ -3,7 +3,7 @@ import traceback
3
3
 
4
4
  from flask import g, redirect, request
5
5
 
6
- import odio
6
+ from odio import create_spreadsheet
7
7
 
8
8
  from sqlalchemy import or_, select, true
9
9
  from sqlalchemy.orm import joinedload
@@ -47,9 +47,9 @@ from chellow.utils import (
47
47
  def write_spreadsheet(fl, compressed, site_rows, era_rows):
48
48
  fl.seek(0)
49
49
  fl.truncate()
50
- with odio.create_spreadsheet(fl, "1.2", compressed=compressed) as f:
51
- f.append_table("Site Level", site_rows)
52
- f.append_table("Era Level", era_rows)
50
+ with create_spreadsheet(fl, compressed=compressed) as sheet:
51
+ sheet.append_table("Site Level", site_rows)
52
+ sheet.append_table("Era Level", era_rows)
53
53
 
54
54
 
55
55
  def _process_era(
@@ -46,15 +46,12 @@ def content(user_id, report_run_id, contract_id, months_length, finish_date):
46
46
  writer.writerow(titles)
47
47
 
48
48
  finish_date_ct = to_ct(finish_date)
49
- months = list(
50
- c_months_u(
51
- finish_year=finish_date_ct.year,
52
- finish_month=finish_date_ct.month,
53
- months=months_length,
54
- )
55
- )
56
49
 
57
- for month_start, month_finish in months:
50
+ for month_start, month_finish in c_months_u(
51
+ finish_year=finish_date_ct.year,
52
+ finish_month=finish_date_ct.month,
53
+ months=months_length,
54
+ ):
58
55
  missing_bills = {}
59
56
  missing_account = {}
60
57
  account_missing_tuple = hh_range(caches, month_start, month_finish)
@@ -127,10 +124,10 @@ def content(user_id, report_run_id, contract_id, months_length, finish_date):
127
124
  "market_role_code": contract.market_role.code,
128
125
  }
129
126
  missing_bills[era.id] = values
130
- for era_id, values in missing_bills.items():
131
- if len(missing_account[values["account"]]) > 0:
132
- writer.writerow(csv_make_val(values[t]) for t in titles)
133
- ReportRun.w_insert_row(report_run_id, "", titles, values, {})
127
+ for era_id, values in missing_bills.items():
128
+ if len(missing_account[values["account"]]) > 0:
129
+ writer.writerow(csv_make_val(values[t]) for t in titles)
130
+ ReportRun.w_insert_row(report_run_id, "", titles, values, {})
134
131
 
135
132
  except BaseException:
136
133
  msg = traceback.format_exc()
@@ -5,7 +5,7 @@ import traceback
5
5
 
6
6
  from flask import g, redirect, request
7
7
 
8
- import odio
8
+ from odio import create_spreadsheet
9
9
 
10
10
  from sqlalchemy import select
11
11
  from sqlalchemy.orm import joinedload
@@ -26,10 +26,10 @@ def write_spreadsheet(
26
26
  ):
27
27
  fl.seek(0)
28
28
  fl.truncate()
29
- with odio.create_spreadsheet(fl, "1.2", compressed=compressed) as f:
30
- f.append_table("SSCs", ssc_rows)
31
- f.append_table("MRs", mr_rows)
32
- f.append_table("TPRs", tpr_rows)
29
+ with create_spreadsheet(fl, compressed=compressed) as sheet:
30
+ sheet.append_table("SSCs", ssc_rows)
31
+ sheet.append_table("MRs", mr_rows)
32
+ sheet.append_table("TPRs", tpr_rows)
33
33
 
34
34
 
35
35
  def content(
@@ -175,7 +175,7 @@
175
175
  </li>
176
176
  {% endfor %}
177
177
  </ul>
178
- {% else %}
178
+ {% elif values[title] is not none %}
179
179
  {{values[title]}}
180
180
  {% endif %}
181
181
  </td>
@@ -13,141 +13,214 @@
13
13
  {% block content %}
14
14
  {% set values = row.data['values'] %}
15
15
  {% set properties = row.data.get('properties', {}) %}
16
- {% if row.report_run.name == 'bill_check' %}
16
+ <table>
17
+ <caption>Bill Check</caption>
18
+ <thead>
19
+ <tr>
20
+ <th rowspan="2">Batch</th>
21
+ <th colspan="8">Bill</th>
22
+ <th colspan="2">MPAN Core</th>
23
+ <th colspan="2">Site</th>
24
+ <th rowspan="2">Checking</th>
25
+ </tr>
26
+ <tr>
27
+ <th>Reference</th>
28
+ <th>Type</th>
29
+ <th>kWh</th>
30
+ <th>Net GBP</th>
31
+ <th>VAT GBP</th>
32
+ <th>Gross GBP</th>
33
+ <th>Start</th>
34
+ <th>Finish</th>
35
+ <th>Import</th>
36
+ <th>Export</th>
37
+ <th>Code</th>
38
+ <th>Name</th>
39
+ </tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr>
43
+ <td>
44
+ {% if values.batch_id != None %}
45
+ <a href="/e/supplier_batches/{{values.batch_id}}">{{values['batch']}}</a>
46
+ {% endif %}
47
+ </td>
48
+ <td>
49
+ {% if values.bill_id != None %}
50
+ <a href="/e/supplier_bills/{{values.bill_id}}">{{
51
+ values['bill-reference']}}</a>
52
+ {% endif %}
53
+ </td>
54
+ <td>{{values['bill-type']}}</td>
55
+ <td>{{values['bill-kwh']}}</td>
56
+ <td>{{values['bill-net-gbp']}}</td>
57
+ <td>{{values['bill-vat-gbp']}}</td>
58
+ <td>{{values['bill-gross-gbp']}}</td>
59
+ <td>{{values['bill-start-date']}}</td>
60
+ <td>{{values['bill-finish-date']}}</td>
61
+ <td>
62
+ {% if values['imp-mpan-core'] != None %}
63
+ <a href="/e/supplies/{{values.supply_id}}">{{
64
+ values['imp-mpan-core']}}</a>
65
+ {% endif %}
66
+ </td>
67
+ <td>
68
+ {% if values['exp-mpan-core'] != None %}
69
+ <a href="/e/supplies/{{values.supply_id}}">{{
70
+ values['exp-mpan-core']}}</a>
71
+ {% endif %}
72
+ </td>
73
+ <td>
74
+ {% if values.site_id != None %}
75
+ <a href="/sites/{{values.site_id}}">{{
76
+ values['site-code']}}</a>
77
+ {% endif %}
78
+ </td>
79
+ <td>{{values['site-name']}}</td>
80
+ <td>
81
+ <form action="/report_run_rows/{{row.id}}" method="post">
82
+ <fieldset>
83
+ {{input_textarea(
84
+ 'note', properties.note, 5, 40,
85
+ placeholder='Notes on checking go here...')}}
86
+ <br>
87
+ <br>
88
+ <label>Checked?
89
+ {{input_checkbox('is_checked', properties.is_checked)}}
90
+ </label>
91
+ <input type="submit" name="update" value="Update">
92
+ </fieldset>
93
+ </form>
94
+ </td>
95
+ </tr>
96
+ </tbody>
97
+ </table>
98
+
99
+ <table>
100
+ <caption>Covered</caption>
101
+ <thead>
102
+ <tr>
103
+ <th>From</th>
104
+ <th>To</th>
105
+ <th>Bills</th>
106
+ <th>Metered kWh</th>
107
+ <th>Net GBP</th>
108
+ <th>Virtual Net GBP</th>
109
+ <th>Difference GBP</th>
110
+ <th>Problem</th>
111
+ <th>Virtual Problem</th>
112
+ </tr>
113
+ </thead>
114
+ <tbody>
115
+ <tr>
116
+ <td>{{values['covered-from']}}</td>
117
+ <td>{{values['covered-to']}}</td>
118
+ <td>
119
+ {% if values['covered-bills'] != None %}
120
+ <ul>
121
+ {% for bill_id in values['covered-bills'] %}
122
+ <li>
123
+ <a href="/e/supplier_bills/{{bill_id}}">{{bill_id}}</a>
124
+ {% if bill_id == values.bill_id %}
125
+ (This bill)
126
+ {% endif %}
127
+ </li>
128
+ {% endfor %}
129
+ </ul>
130
+ {% endif %}
131
+ </td>
132
+ <td>
133
+ {% if values['metered-kwh'] != None %}
134
+ {{"%.0f"|format(values['metered-kwh'])}}
135
+ {% endif %}
136
+ </td>
137
+ <td>{{values['covered-net-gbp']}}</td>
138
+ <td>
139
+ {% if values['virtual-net-gbp'] != None %}
140
+ {{"%.2f"|format(values['virtual-net-gbp'])}}
141
+ {% endif %}
142
+ </td>
143
+ <td>
144
+ {% if values['difference-net-gbp'] != None %}
145
+ {{"%.2f"|format(values['difference-net-gbp'])}}
146
+ {% endif %}
147
+ </td>
148
+ <td>{{values['covered-problem']}}</td>
149
+ <td>{{values['virtual-problem']}}</td>
150
+ </tr>
151
+ </tbody>
152
+ </table>
153
+
154
+ <section class="elements">
17
155
  <table>
18
- <caption>Bill Check</caption>
156
+ <caption>GBP</caption>
19
157
  <thead>
20
158
  <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>
159
+ <th>Part</th>
160
+ <th>Covered</th>
161
+ <th>Virtual</th>
162
+ <th>Difference</th>
40
163
  </tr>
41
164
  </thead>
42
165
  <tbody>
43
166
  <tr>
167
+ <td>gross</td>
44
168
  <td>
45
- {% if values.batch_id != None %}
46
- <a href="/e/supplier_batches/{{values.batch_id}}">{{values['batch']}}</a>
169
+ {% if 'covered-gross-gbp' in values and values['covered-gross-gbp'] is number %}
170
+ {{"{:0,.2f}".format(values['covered-gross-gbp'])}}
47
171
  {% endif %}
48
172
  </td>
49
173
  <td>
50
- {% if values.bill_id != None %}
51
- <a href="/e/supplier_bills/{{values.bill_id}}">{{
52
- values['bill-reference']}}</a>
174
+ {% if 'virtual-gross-gbp' in values and values['virtual-gross-gbp'] is number %}
175
+ {{"{:0,.2f}".format(values['virtual-gross-gbp'])}}
53
176
  {% endif %}
54
177
  </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
178
  <td>
63
- {% if values['imp-mpan-core'] != None %}
64
- <a href="/e/supplies/{{values.supply_id}}">{{
65
- values['imp-mpan-core']}}</a>
179
+ {% if 'difference-gross-gbp' in values and values['difference-gross-gbp'] is number %}
180
+ {{"{:0,.2f}".format(values['difference-gross-gbp'])}}
66
181
  {% endif %}
67
182
  </td>
183
+ </tr>
184
+ <tr>
185
+ <td>net</td>
68
186
  <td>
69
- {% if values['exp-mpan-core'] != None %}
70
- <a href="/e/supplies/{{values.supply_id}}">{{
71
- values['exp-mpan-core']}}</a>
187
+ {% if 'covered-net-gbp' in values and values['covered-net-gbp'] is number %}
188
+ {{"{:0,.2f}".format(values['covered-net-gbp'])}}</td>
72
189
  {% endif %}
73
- </td>
74
190
  <td>
75
- {% if values.site_id != None %}
76
- <a href="/sites/{{values.site_id}}">{{
77
- values['site-code']}}</a>
191
+ {% if 'virtual-net-gbp' in values and values['virtual-net-gbp'] is number %}
192
+ {{"{:0,.2f}".format(values['virtual-net-gbp'])}}</td>
78
193
  {% endif %}
79
- </td>
80
- <td>{{values['site-name']}}</td>
81
194
  <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>
98
- </table>
99
-
100
- <table>
101
- <caption>Covered</caption>
102
- <thead>
103
- <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>
195
+ {% if 'difference-net-gbp' in values and values['difference-net-gbp'] is number %}
196
+ {{"{:0,.2f}".format(values['difference-net-gbp'])}}</td>
197
+ {% endif %}
113
198
  </tr>
114
- </thead>
115
- <tbody>
116
199
  <tr>
117
- <td>{{values['covered-from']}}</td>
118
- <td>{{values['covered-to']}}</td>
200
+ <td>vat</td>
119
201
  <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>
202
+ {% if 'covered-vat-gbp' in values and values['covered-vat-gbp'] is number %}
203
+ {{"{:0,.2f}".format(values['covered-vat-gbp'])}}</td>
131
204
  {% endif %}
132
- </td>
133
205
  <td>
134
- {% if values['metered-kwh'] != None %}
135
- {{"%.0f"|format(values['metered-kwh'])}}
206
+ {% if 'virtual-vat-gbp' in values and values['virtual-vat-gbp'] is number %}
207
+ {{"{:0,.2f}".format(values['virtual-vat-gbp'])}}</td>
136
208
  {% endif %}
137
- </td>
138
- <td>{{values['covered-net-gbp']}}</td>
139
209
  <td>
140
- {% if values['virtual-net-gbp'] != None %}
141
- {{"%.2f"|format(values['virtual-net-gbp'])}}
210
+ {% if 'difference-vat-gbp' in values and values['difference-vat-gbp'] is number %}
211
+ {{"{:0,.2f}".format(values['difference-vat-gbp'])}}</td>
142
212
  {% endif %}
143
- </td>
213
+ </tr>
214
+ <tr>
215
+ <td>vat-rate</td>
144
216
  <td>
145
- {% if values['difference-net-gbp'] != None %}
146
- {{"%.2f"|format(values['difference-net-gbp'])}}
217
+ {{values['covered-vat-rate']}}</td>
218
+ <td>{{values['virtual-vat-rate']}}</td>
219
+ <td>
220
+ {% if values['difference-vat-rate'] is number %}
221
+ {{"{:0,.2f}".format(values['difference-vat-rate'])}}
147
222
  {% endif %}
148
223
  </td>
149
- <td>{{values['covered-problem']}}</td>
150
- <td>{{values['virtual-problem']}}</td>
151
224
  </tr>
152
225
  </tbody>
153
226
  </table>
@@ -157,35 +230,70 @@
157
230
  <caption>{{table.name}}</caption>
158
231
  <thead>
159
232
  <tr>
160
- {% for title in table.titles %}
161
- <th>{{title}}</th>
162
- {% endfor %}
233
+ <th>Part</th>
234
+ <th>Covered</th>
235
+ <th>Virtual</th>
236
+ <th>Difference</th>
163
237
  </tr>
164
238
  </thead>
165
239
  <tbody>
166
240
  <tr>
167
- {% for v in table['values'] %}
168
- <td>{{v}}</td>
241
+ <td>gbp</td>
242
+ {% for pref in ('covered-', 'virtual-', 'difference-') %}
243
+ <td>
244
+ {% set k = pref + table.name + "-gbp" %}
245
+ {% if k in values %}
246
+ {% set val = values[k] %}
247
+ {% else %}
248
+ {% set val = '' %}
249
+ {% endif %}
250
+ {% if val is none %}
251
+ {% elif val is number %}
252
+ {{"{:0,.2f}".format(val)}}
253
+ {% else %}
254
+ {{val}}
255
+ {% endif %}
256
+ </td>
169
257
  {% endfor %}
170
258
  </tr>
259
+ {% for part in table['parts']|sort %}
260
+ <tr>
261
+ <td>{{part}}</td>
262
+ {% for pref in ('covered-', 'virtual-', 'difference-') %}
263
+ <td>
264
+ {% set k = pref + table.name + "-" + part %}
265
+ {% if k in values %}
266
+ {% set val = values[k] %}
267
+ {% else %}
268
+ {% set val = '' %}
269
+ {% endif %}
270
+ {% if val is none %}
271
+ {% elif val is number %}
272
+ {{"{:0,.2f}".format(val)}}
273
+ {% elif (val is string) or (val is boolean) %}
274
+ {{val}}
275
+ {% else %}
276
+ {% for v in val %}
277
+ {% if v is number %}
278
+ {{"{:0,.2f}".format(v)}}
279
+ {% else %}
280
+ {{v}}
281
+ {% endif %}
282
+ {% if not loop.last %}
283
+ |
284
+ {% endif %}
285
+ {% endfor %}
286
+ {% endif %}
287
+ </td>
288
+ {% endfor %}
289
+ </tr>
290
+ {% endfor %}
171
291
  </tbody>
172
292
  </table>
173
293
  {% endfor %}
174
294
 
175
- <h2>Raw</h2>
176
- <pre>{{raw_data}}</pre>
295
+ </section>
177
296
 
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 %}
297
+ <h2>Raw</h2>
298
+ <pre>{{raw_data}}</pre>
191
299
  {% endblock %}
chellow/views.py CHANGED
@@ -1629,42 +1629,40 @@ def report_run_row_get(row_id):
1629
1629
  if row.report_run.name == "bill_check":
1630
1630
  values = row.data["values"]
1631
1631
  elements = {}
1632
- for t in row.data["values"].keys():
1633
- if t == "difference-tpr-gbp":
1634
- continue
1632
+ for t in values.keys():
1635
1633
 
1636
1634
  if (
1637
1635
  t.startswith("covered-")
1638
1636
  or t.startswith("virtual-")
1639
1637
  or t.startswith("difference-")
1640
- ) and t not in (
1641
- "covered-from",
1642
- "covered-to",
1643
- "covered-bills",
1644
- "covered-problem",
1645
- "virtual-problem",
1646
- ):
1638
+ ) and t.endswith("-gbp"):
1647
1639
  toks = t.split("-")
1648
1640
  name = "-".join(toks[1:-1])
1641
+ if name in ("vat", "gross", "net", "tpr"):
1642
+ continue
1649
1643
  try:
1650
1644
  table = elements[name]
1651
1645
  except KeyError:
1652
- table = elements[name] = {"order": 0}
1653
-
1654
- if "titles" not in table:
1655
- table["titles"] = []
1656
- table["titles"].append(toks[0] + "-" + "-".join(toks[2:]))
1657
- if "values" not in table:
1658
- table["values"] = []
1659
- table["values"].append(values[t])
1660
- if t.startswith("difference-") and t.endswith("-gbp"):
1646
+ table = elements[name] = {"order": 0, "name": name, "parts": set()}
1647
+ tables.append(table)
1648
+
1649
+ if t.startswith("difference-"):
1661
1650
  table["order"] = abs(values[t])
1662
1651
 
1663
- for k, v in elements.items():
1664
- if k == "net":
1665
- continue
1666
- v["name"] = k
1667
- tables.append(v)
1652
+ for t in values.keys():
1653
+
1654
+ toks = t.split("-")
1655
+ if toks[0] in ("covered", "virtual", "difference"):
1656
+ tail = "-".join(toks[1:])
1657
+ for element in sorted(elements.keys(), key=len, reverse=True):
1658
+
1659
+ table = elements[element]
1660
+ elstr = f"{element}-"
1661
+ if tail.startswith(elstr):
1662
+ part = tail[len(elstr) :]
1663
+ if part != "gbp":
1664
+ table["parts"].add(part)
1665
+ break
1668
1666
 
1669
1667
  tables.sort(key=lambda t: t["order"], reverse=True)
1670
1668
  return render_template(
@@ -1678,7 +1676,7 @@ def report_run_row_get(row_id):
1678
1676
 
1679
1677
  values = row.data["values"]
1680
1678
  elements = {}
1681
- for t in row.data["values"].keys():
1679
+ for t in values.keys():
1682
1680
 
1683
1681
  if (
1684
1682
  t.startswith("covered_")
@@ -1695,7 +1693,7 @@ def report_run_row_get(row_id):
1695
1693
  table = elements[name] = {"order": 0, "name": name, "parts": set()}
1696
1694
  tables.append(table)
1697
1695
 
1698
- for t in row.data["values"].keys():
1696
+ for t in values.keys():
1699
1697
 
1700
1698
  toks = t.split("_")
1701
1699
  if toks[0] in ("covered", "virtual", "difference"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chellow
3
- Version: 1753706177.0.0
3
+ Version: 1754570085.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)
@@ -13,7 +13,7 @@ chellow/rate_server.py,sha256=RwJo-AzBIdzxx7PAtboZEUH1nUjAeJckw0bk06-9oyM,5672
13
13
  chellow/rrun.py,sha256=1Kt2q_K9UoDG_nsZz-Q6XJiMNKroWqlqFdxn2M6Q8CA,2088
14
14
  chellow/testing.py,sha256=Dj2c1NX8lVlygueOrh2eyYawLW6qKEHxNhXVVUaNRO0,3637
15
15
  chellow/utils.py,sha256=i3GQK9MIcweosZk2gi-nX_IFq2DxURAJDyNoLBg6YwM,19421
16
- chellow/views.py,sha256=oVZTSQ7k-VCwxzeDpj9sAfERtFw0rEHc58IxtvrhBi0,85431
16
+ chellow/views.py,sha256=eFQTFnvz59_BC-lXIU7N8G6cpLCvTIszim-YN3n_Co8,85418
17
17
  chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
19
19
  chellow/e/bill_importer.py,sha256=7UcnqNlKbJc2GhW9gy8sDp9GuqambJVpZLvbafOZztA,7411
@@ -38,7 +38,7 @@ chellow/e/lafs.py,sha256=SUUFtvn_IQQTrZue1zefCYgzuscA0FVX2ySZ9u8BDPw,7776
38
38
  chellow/e/lcc.py,sha256=OkpynN8_iAdHRlu-yyU6BhRUqYYOZsUnl0HbHULYo_4,4670
39
39
  chellow/e/mdd_importer.py,sha256=NugJr2JhuzkPTsEMl_5UdQuw5K2p8lVJ-hyz4MK6Hfg,35762
40
40
  chellow/e/rcrc.py,sha256=92CA1uIotIHd1epQ_jEPdJKzXqDFV-AoJOJeRO6MEyA,4274
41
- chellow/e/ro.py,sha256=dZKZv_9wXSWuwcb3jiKavoD_9ot-PZseNVeEEe0siLo,596
41
+ chellow/e/ro.py,sha256=cpeJQMY_6SpVxL1nySSj9we58A6E2KwJEAb6fK7cZKY,626
42
42
  chellow/e/scenario.py,sha256=FLgh03r_SgXx0hMWFbAvwsz2ScDL8LUwYWSWVv2rQlg,24973
43
43
  chellow/e/system_price.py,sha256=6w5J7bzwFAZubE2zdOFRiS8IIrVP8hkoIOaG2yCt-Ic,6232
44
44
  chellow/e/tlms.py,sha256=pyL32hPiYd09FbpXVMnBjHsWFEQHs-Az945V7EShGiY,9116
@@ -50,17 +50,17 @@ chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=opjXRrqrgBTbSKzL0JfTLP0
50
50
  chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=-HMoIfa_utXYKA44RuC0Xqv3vd2HLeQU_4P0iBUd3WA,4219
51
51
  chellow/e/bill_parsers/bgb_edi.py,sha256=GuwHeYbAGk7BVg5n19FcTANFDyKI-y0z3f9niQaPSSw,4828
52
52
  chellow/e/bill_parsers/csv.py,sha256=U5zcIaZ6B5QTTpFDAcBnk4G2r8B3j5kJhDPL4AJNkEk,5640
53
- chellow/e/bill_parsers/drax_edi.py,sha256=PakbtmBEVvshJxZR_8LXeqPyUBrwtKO3GiNIlVFZETE,15191
53
+ chellow/e/bill_parsers/drax_edi.py,sha256=mzYaPYMVj2dFb1HIGV-HFtqYjhZ2g9V3xl_w8Z1ECfc,15400
54
54
  chellow/e/bill_parsers/drax_element_edi.py,sha256=kxjg1KA4UheMa8doGp9skXtQYrNK8Eisy9ksafR5TQo,13661
55
55
  chellow/e/bill_parsers/edf_export_xlsx.py,sha256=J4lY8epiSTIePZ6D1SGD76TXRoev35KrUC2sjHkNqlE,6632
56
- chellow/e/bill_parsers/engie_edi.py,sha256=PDMDI0aqUM1lalgzxih1YmMho11n1rMqE0vyL-aEIs8,15840
56
+ chellow/e/bill_parsers/engie_edi.py,sha256=yC5Tz5xFIcJmKZbvK_xcl0s-1fZsse1z4HEbwpC7fxU,15834
57
57
  chellow/e/bill_parsers/engie_export_xlsx.py,sha256=oZO0qHdDlOxjJ6J5Ate82CkAoX4bxed1EJyUKHxBcpk,4690
58
58
  chellow/e/bill_parsers/engie_xls.py,sha256=jrut2heH_ZWmSjcn7celOydZS9Y49GfpYjDk_EKwamI,14453
59
59
  chellow/e/bill_parsers/engie_xlsx.py,sha256=4Hu3ls1uNMH7vjDHgcP6QARlGlvb616CqG3xZVjAKWo,16888
60
60
  chellow/e/bill_parsers/gdf_csv.py,sha256=ZfK3Oc6oP28p_P9DIevLNB_zW2WLcEJ3Lvb1gL310YU,7382
61
61
  chellow/e/bill_parsers/haven_csv.py,sha256=0uENq8IgVNqdxfBQMBxLTSZWCOuDHXZC0xzk52SbfyE,13652
62
62
  chellow/e/bill_parsers/haven_edi.py,sha256=YGPHRxPOhje9s32jqPHHELni2tooOYj3cMC_qaZVPq4,16107
63
- chellow/e/bill_parsers/haven_edi_tprs.py,sha256=ZVX9CCqUybsot_Z0BEOJPvl9x5kSr7fEWyuJXvZDcz4,11841
63
+ chellow/e/bill_parsers/haven_edi_tprs.py,sha256=JtCSUM4h6QFB76KaHY5gGWhCOtlSEEy7MLCUtOrJjPY,12004
64
64
  chellow/e/bill_parsers/mm.py,sha256=1myKrms3yVAhKFCzk3swWJjCwepZYk8GkD0wK0bpsj4,11184
65
65
  chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py,sha256=YvQ0Q6HlZ4XSk6Phx1UWaTSj8FREVjwQe8nrpiLVzbU,5458
66
66
  chellow/e/bill_parsers/settlement_dc_stark_xlsx.py,sha256=osCpUYUdLcPtlo7ngXWGw0ImnxssLa1fOSejMwe51-k,6381
@@ -79,7 +79,7 @@ chellow/gas/transportation.py,sha256=Bkg8TWOs-v0ES-4qqwbleiOhqbE_t2KauUx9JYMZELM
79
79
  chellow/gas/views.py,sha256=GeCvi6BGTUN7bu7sVkypNckwG3Crl6AbUcRob9qMi0E,59733
80
80
  chellow/reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  chellow/reports/report_109.py,sha256=Exb-FQ5f70-ier_h15CgHGysQ7vJ7k3gFZ1001zM3iM,11171
82
- chellow/reports/report_111.py,sha256=o_wWyrtmxpTnmT9DVlsG5h5wdm3JqojirRlx_7W5_kQ,28787
82
+ chellow/reports/report_111.py,sha256=_ipuMuvhjWLBVjK4wV08tbDG6s8cspQ_bzRZu1mPuXE,30224
83
83
  chellow/reports/report_169.py,sha256=wortJyvgXTrnjjXhLzqwaksKKu63K5IgdzU5f4SkHMI,9246
84
84
  chellow/reports/report_181.py,sha256=ypfYWYVNC1X2fMlJyDzwNiNTTRrpPW49DirXE_xDKa0,4958
85
85
  chellow/reports/report_183.py,sha256=fGONpKEIXTqIT_3dE5jZKBIesWPgLq-chHO6X22dIv0,8768
@@ -88,14 +88,14 @@ chellow/reports/report_219.py,sha256=3Zs16ka6dWWY_lCDoA-ZFrlPb4vHk1LQoa2yrlTMntA
88
88
  chellow/reports/report_231.py,sha256=WARLztV2HzBFSi5_xvY_DTXVyuBBbBYiU0RazfjKw-Y,5270
89
89
  chellow/reports/report_233.py,sha256=qJdPFuBgQAWD24BsljgGJ44L_RGdHOA1RqsxGjTWhFc,4975
90
90
  chellow/reports/report_241.py,sha256=lfivElRkV_CZAhck0rxAuhqzgponj3aWwmwGMNQvUxg,5343
91
- chellow/reports/report_247.py,sha256=00a-shl3TRRWyana42OZHvPnjE803rQc_2HzlSA5xKE,46029
91
+ chellow/reports/report_247.py,sha256=FY0eFi5gPfN3LtL82eCpcaLXNh2PC8pHl8yyCPaZuNw,46057
92
92
  chellow/reports/report_29.py,sha256=ZXnq6Kg5on-IPquUsH4bn46mBVESY_WhwqDWZPXOJwo,2695
93
93
  chellow/reports/report_291.py,sha256=BnWtxe0eWN2QKKWpwjs5-RI5LbReBKL119QbkrkNhV8,7478
94
94
  chellow/reports/report_33.py,sha256=lt1EN_LNx6u-AgdaS3YRkPMZA33JgMcELolHF4oJUMw,16689
95
95
  chellow/reports/report_387.py,sha256=bBqtnGGDWIXzXe2zVm9yeDRZKNgkUaOS3XTX6k09f18,5631
96
96
  chellow/reports/report_41.py,sha256=8xUIN9D5dtT0Dn1RmbnWsLRmM-QbGA5xGhWCK3ljAzA,7406
97
97
  chellow/reports/report_429.py,sha256=1LzrhfePeLg98eczzxy9HrR0EYcPYINw1LSJKk9kKAM,15812
98
- chellow/reports/report_59.py,sha256=PkdRA6ctvDGWTQd5vb9cQH6MG920TxcD6aHh268zrj8,42221
98
+ chellow/reports/report_59.py,sha256=cnsAzelRwxzKuO0NTfOiNEPpREveK0goBxRLFN39a0s,42253
99
99
  chellow/reports/report_81.py,sha256=bBpV6MtvKGtoLiqzZoK2h21KDs4vfDwy-etpfL9oiEI,5570
100
100
  chellow/reports/report_87.py,sha256=udzbCuXcckWD-OHmfJCT6bwg_paYhm4vfDWlL8WM-jA,6933
101
101
  chellow/reports/report_asset_comparison.py,sha256=Cl2NgvbclqhOVvKuUu3sajTVO2JupMfzK3bV0_K8eNs,6077
@@ -105,13 +105,13 @@ chellow/reports/report_csv_llfcs.py,sha256=mMB06b6Jems5kcQU4H4Le_fyKgVr8THP8BCx3
105
105
  chellow/reports/report_csv_site_hh_data.py,sha256=ik0OkGVo1bfTXLdcT3gPUHnxSkSdorzZheP3qgnOR5c,4331
106
106
  chellow/reports/report_csv_site_snags.py,sha256=AuAy6vjL0g7vwPPAZhBqxOyITL9_jnyFj012MnUcxxk,2627
107
107
  chellow/reports/report_ecoes_comparison.py,sha256=u0L2D1z8j63btdypIRd1NMMqFKgeMz_zK-SAjn7b5b4,21401
108
- chellow/reports/report_g_monthly_duration.py,sha256=VQq5xTLvdu9Z_vqrgWNP2S4xm2uCSSZA9HVNiQv9Dus,18264
108
+ chellow/reports/report_g_monthly_duration.py,sha256=aEY3hSBaCxjOBgWZYWZH38TmZEO5MpOfpOQe2Lhfpmo,18288
109
109
  chellow/reports/report_g_supplies_snapshot.py,sha256=9xB6RDrnbgxuomMcP1b1yEP4kOnEJ34WgKpyxLTprOQ,3998
110
110
  chellow/reports/report_g_supply_virtual_bill.py,sha256=EaYrB8PHJIXrUuhiZ7dwUlbNBkuyJebQHrdc308_z1o,3653
111
111
  chellow/reports/report_g_virtual_bills.py,sha256=20vHa5LGQwOAlJlaGJaGszZrrbT0PMOZJf6hSxU2hIQ,4528
112
112
  chellow/reports/report_g_virtual_bills_hh.py,sha256=gaiLEmKTpq6JsfZ1p0SdCDuPvzvigXp6z88gHRCA63w,3416
113
- chellow/reports/report_missing_bills.py,sha256=aCgpVpwjN7jKg1S_pnmnHgo9FKFFSThSkiEKAUYvtSo,6021
114
- chellow/reports/report_sscs.py,sha256=fQWyVG-gdg37DyNHgpNARpSxIwTl7mCn20fDLwx9oHg,3214
113
+ chellow/reports/report_missing_bills.py,sha256=-hVjmWctLtHBEBfCmYjKlVD3YT3R50cyb_fp2Ah88qE,5973
114
+ chellow/reports/report_sscs.py,sha256=IZKSJJxWmqEV8PDs4YYGET0J_EKOQ6QHCKdVltA5haA,3242
115
115
  chellow/reports/report_supply_contacts.py,sha256=pvwlInaPYV_pa9MMK6vh854plHFwv3m5zo5xulR1g5I,3599
116
116
  chellow/static/css/chellow.css,sha256=dnkuj9Z1BCOV_L2Y26lDd2QlTmFFhATa1YvwPVch1Oc,5375
117
117
  chellow/static/images/favicon.svg,sha256=ySFHoVJYmr-xU93QrE-jLYn-ZNythh2vsemnR8dkvg0,2339
@@ -146,13 +146,13 @@ chellow/templates/object_summary.html,sha256=VGCAAYcWTzgNfL0mxEef2Fa8dP3FcBhzj0f
146
146
  chellow/templates/rate_server.html,sha256=SezuwdKhHRZ00-R_S6ttKiZ-nvRpwozV9QcIMf9StG8,5360
147
147
  chellow/templates/report_run.html,sha256=O_wjIu43S-mKVyZyku3dJJdvyck3rAgEdhw59TsCcK0,4040
148
148
  chellow/templates/report_run_asset_comparison.html,sha256=VYCCUmIC7Mfe7uuaAHb6ihiK6zsqeTlQbzgtzLqR3zg,2305
149
- chellow/templates/report_run_bill_check.html,sha256=H2ayoBL7EgKMq2Nwq5VjE_TNvcIKcqeCm0alQWLIw78,5084
149
+ chellow/templates/report_run_bill_check.html,sha256=I4VLSTOGE7cjjZggG3EAI9EW-2b7e0oOTs-S7FlknS4,5110
150
150
  chellow/templates/report_run_ecoes_comparison.html,sha256=VmkT5ypWLP8qZS6NbDTC4yDaG7mnUlxZz7EV8xkHGZw,4086
151
151
  chellow/templates/report_run_g_bill_check.html,sha256=tOXl_mjR__foYKiOYflJbK-459actAtjzv8rfuL3TwM,4851
152
152
  chellow/templates/report_run_missing_e_bills.html,sha256=l5idQhfaNhMvvzIRv-iqCpeDnYl_wgs6-mZMBOmuyR8,2447
153
153
  chellow/templates/report_run_monthly_duration_org.html,sha256=gGNGJ4Q50q4BtIMi98rhO-7NqRHcsFUmbj2qzeOLejw,1713
154
154
  chellow/templates/report_run_row.html,sha256=bmtcdqJaS1CXpL0i8PuqvmeF98jKNYX5-mnQu-OuDKQ,3791
155
- chellow/templates/report_run_row_bill_check.html,sha256=aC2LMu_6NvmTN3ZdxHJPPPczyxPN6hg0F-PPcqIWUws,4683
155
+ chellow/templates/report_run_row_bill_check.html,sha256=F3wkVO7fJgc2_66p4p91RB9AqcR6OaLx5zk7iCiwDxs,7779
156
156
  chellow/templates/report_run_row_g_bill_check.html,sha256=2Ym9mkwvA_DGDrgktDDwXQXlUK7tR2aR3gp3KUqMLoI,7017
157
157
  chellow/templates/report_run_supply_contacts.html,sha256=JNzwz9M6qbLRDMkCzFCxxANapUer5klxo7t5a48nAzg,2117
158
158
  chellow/templates/report_runs.html,sha256=ecoIkl2WtfYtifiTxnslmpMGYYGVQW-CVSBpqhXyiE4,1131
@@ -385,6 +385,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
385
385
  chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
386
386
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
387
387
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
388
- chellow-1753706177.0.0.dist-info/METADATA,sha256=hDTpywwjrBXlrUqUeORa0HKtxpXIs3ddk90kZhStmmw,12519
389
- chellow-1753706177.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
390
- chellow-1753706177.0.0.dist-info/RECORD,,
388
+ chellow-1754570085.0.0.dist-info/METADATA,sha256=cT0SgunJ0IL9NYi6VfbeqKP9zv6wvOrvhIOCz3t7v6U,12519
389
+ chellow-1754570085.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
390
+ chellow-1754570085.0.0.dist-info/RECORD,,