chellow 1738691248.0.0__py3-none-any.whl → 1739889885.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/gas/views.py +7 -7
- chellow/models.py +7 -0
- chellow/reports/report_429.py +82 -18
- chellow/static/css/chellow.css +1 -1
- chellow/templates/report_run_g_bill_check.html +182 -0
- chellow/templates/report_run_row_g_bill_check.html +191 -0
- chellow/views.py +113 -0
- {chellow-1738691248.0.0.dist-info → chellow-1739889885.0.0.dist-info}/METADATA +1 -1
- {chellow-1738691248.0.0.dist-info → chellow-1739889885.0.0.dist-info}/RECORD +10 -8
- {chellow-1738691248.0.0.dist-info → chellow-1739889885.0.0.dist-info}/WHEEL +0 -0
chellow/gas/views.py
CHANGED
|
@@ -170,20 +170,20 @@ def supply_get(g_supply_id):
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
g_bills = (
|
|
173
|
-
|
|
174
|
-
.
|
|
173
|
+
select(GBill)
|
|
174
|
+
.where(GBill.g_supply == g_supply)
|
|
175
175
|
.order_by(
|
|
176
176
|
GBill.start_date.desc(),
|
|
177
177
|
GBill.issue_date.desc(),
|
|
178
178
|
GBill.reference.desc(),
|
|
179
179
|
)
|
|
180
180
|
)
|
|
181
|
-
if g_era
|
|
182
|
-
g_bills = g_bills.
|
|
181
|
+
if g_era != g_eras[0]:
|
|
182
|
+
g_bills = g_bills.where(GBill.start_date < g_era.finish_date)
|
|
183
183
|
if g_era != g_eras[-1]:
|
|
184
|
-
g_bills = g_bills.
|
|
184
|
+
g_bills = g_bills.where(GBill.start_date >= g_era.start_date)
|
|
185
185
|
|
|
186
|
-
for g_bill in g_bills:
|
|
186
|
+
for g_bill in g.sess.scalars(g_bills):
|
|
187
187
|
g_reads = (
|
|
188
188
|
g.sess.query(GRegisterRead)
|
|
189
189
|
.filter(GRegisterRead.g_bill == g_bill)
|
|
@@ -220,7 +220,7 @@ def supply_get(g_supply_id):
|
|
|
220
220
|
|
|
221
221
|
RELATIVE_YEAR = relativedelta(years=1)
|
|
222
222
|
|
|
223
|
-
now =
|
|
223
|
+
now = utc_datetime_now()
|
|
224
224
|
triad_year = (now - RELATIVE_YEAR).year if now.month < 3 else now.year
|
|
225
225
|
this_month_start = Datetime(now.year, now.month, 1)
|
|
226
226
|
last_month_start = this_month_start - relativedelta(months=1)
|
chellow/models.py
CHANGED
|
@@ -6416,6 +6416,13 @@ class ReportRun(Base, PersistentClass):
|
|
|
6416
6416
|
report_run.update(state)
|
|
6417
6417
|
wsess.commit()
|
|
6418
6418
|
|
|
6419
|
+
@staticmethod
|
|
6420
|
+
def w_update_data(report_run_id, data):
|
|
6421
|
+
with Session() as wsess:
|
|
6422
|
+
report_run = ReportRun.get_by_id(wsess, report_run_id)
|
|
6423
|
+
report_run.update_data(data)
|
|
6424
|
+
wsess.commit()
|
|
6425
|
+
|
|
6419
6426
|
@staticmethod
|
|
6420
6427
|
def w_insert_row(report_run_id, tab, titles, values, properties):
|
|
6421
6428
|
with Session() as wsess:
|
chellow/reports/report_429.py
CHANGED
|
@@ -16,16 +16,34 @@ from werkzeug.exceptions import BadRequest
|
|
|
16
16
|
|
|
17
17
|
import chellow.gas.engine
|
|
18
18
|
from chellow.dloads import open_file
|
|
19
|
-
from chellow.models import
|
|
19
|
+
from chellow.models import (
|
|
20
|
+
GBatch,
|
|
21
|
+
GBill,
|
|
22
|
+
GContract,
|
|
23
|
+
GEra,
|
|
24
|
+
RSession,
|
|
25
|
+
ReportRun,
|
|
26
|
+
Site,
|
|
27
|
+
SiteGEra,
|
|
28
|
+
User,
|
|
29
|
+
)
|
|
20
30
|
from chellow.utils import csv_make_val, hh_max, hh_min, req_date, req_int, to_utc
|
|
21
31
|
|
|
22
32
|
|
|
23
|
-
def content(
|
|
33
|
+
def content(
|
|
34
|
+
g_batch_id,
|
|
35
|
+
g_bill_id,
|
|
36
|
+
g_contract_id,
|
|
37
|
+
start_date,
|
|
38
|
+
finish_date,
|
|
39
|
+
user_id,
|
|
40
|
+
report_run_id,
|
|
41
|
+
):
|
|
24
42
|
forecast_date = to_utc(Datetime.max)
|
|
25
43
|
report_context = {}
|
|
26
44
|
sess = tmp_file = None
|
|
27
45
|
try:
|
|
28
|
-
with
|
|
46
|
+
with RSession() as sess:
|
|
29
47
|
user = User.get_by_id(sess, user_id)
|
|
30
48
|
|
|
31
49
|
tmp_file = open_file("g_bill_check.csv", user, mode="w")
|
|
@@ -108,13 +126,17 @@ def content(g_batch_id, g_bill_id, g_contract_id, start_date, finish_date, user_
|
|
|
108
126
|
vbf,
|
|
109
127
|
titles,
|
|
110
128
|
csv_writer,
|
|
129
|
+
report_run_id,
|
|
111
130
|
)
|
|
131
|
+
ReportRun.w_update(report_run_id, "finished")
|
|
112
132
|
except BadRequest as e:
|
|
113
133
|
tmp_file.write(f"Problem: {e.description}")
|
|
134
|
+
ReportRun.w_update(report_run_id, "problem")
|
|
114
135
|
except BaseException:
|
|
115
136
|
msg = traceback.format_exc()
|
|
116
137
|
sys.stderr.write(msg + "\n")
|
|
117
138
|
tmp_file.write(f"Problem {msg}")
|
|
139
|
+
ReportRun.w_update(report_run_id, "interrupted")
|
|
118
140
|
finally:
|
|
119
141
|
tmp_file.close()
|
|
120
142
|
|
|
@@ -129,6 +151,7 @@ def _process_g_bill_ids(
|
|
|
129
151
|
vbf,
|
|
130
152
|
titles,
|
|
131
153
|
csv_writer,
|
|
154
|
+
report_run_id,
|
|
132
155
|
):
|
|
133
156
|
g_bill_id = list(sorted(g_bill_ids))[0]
|
|
134
157
|
g_bill_ids.remove(g_bill_id)
|
|
@@ -144,6 +167,7 @@ def _process_g_bill_ids(
|
|
|
144
167
|
"covered_bill_ids": [],
|
|
145
168
|
"virtual_problem": "",
|
|
146
169
|
}
|
|
170
|
+
site_id = None
|
|
147
171
|
read_dict = defaultdict(set)
|
|
148
172
|
for g_read in g_bill.g_reads:
|
|
149
173
|
if not all(
|
|
@@ -264,7 +288,7 @@ def _process_g_bill_ids(
|
|
|
264
288
|
else:
|
|
265
289
|
v = getattr(g_read, title)
|
|
266
290
|
vals[k].add(v)
|
|
267
|
-
|
|
291
|
+
elements = set()
|
|
268
292
|
for g_era in sess.execute(
|
|
269
293
|
select(GEra).where(
|
|
270
294
|
GEra.g_supply == g_supply,
|
|
@@ -283,6 +307,7 @@ def _process_g_bill_ids(
|
|
|
283
307
|
.filter(SiteGEra.is_physical == true(), SiteGEra.g_era == g_era)
|
|
284
308
|
.one()
|
|
285
309
|
)
|
|
310
|
+
site_id = site.id
|
|
286
311
|
vals["site_code"] = site.code
|
|
287
312
|
vals["site_name"] = site.name
|
|
288
313
|
|
|
@@ -313,6 +338,9 @@ def _process_g_bill_ids(
|
|
|
313
338
|
except TypeError as detail:
|
|
314
339
|
raise BadRequest(f"For key {vk} and value {v}. {detail}")
|
|
315
340
|
|
|
341
|
+
if k.endswith("_gbp"):
|
|
342
|
+
elements.add(k[:-4])
|
|
343
|
+
|
|
316
344
|
if g_bill.id not in covered_bills.keys():
|
|
317
345
|
g_bill = covered_bills[sorted(covered_bills.keys())[0]]
|
|
318
346
|
|
|
@@ -324,22 +352,36 @@ def _process_g_bill_ids(
|
|
|
324
352
|
vals["mprn"] = g_supply.mprn
|
|
325
353
|
vals["supply_name"] = g_supply.name
|
|
326
354
|
|
|
327
|
-
for k, v in vals.items():
|
|
328
|
-
if k == "covered_bill_ids":
|
|
329
|
-
vals[k] = " | ".join(str(b) for b in v)
|
|
330
|
-
else:
|
|
331
|
-
vals[k] = csv_make_val(v)
|
|
332
|
-
|
|
333
355
|
for i, title in enumerate(titles):
|
|
334
356
|
if title.startswith("difference_"):
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
vals[title] = covered_val - virtual_val
|
|
339
|
-
except KeyError:
|
|
340
|
-
vals[title] = None
|
|
357
|
+
covered_val = float(vals.get(titles[i - 2], 0))
|
|
358
|
+
virtual_val = float(vals.get(titles[i - 1], 0))
|
|
359
|
+
vals[title] = covered_val - virtual_val
|
|
341
360
|
|
|
342
361
|
csv_writer.writerow([csv_make_val(vals.get(k)) for k in titles])
|
|
362
|
+
vals["g_bill_id"] = g_bill.id
|
|
363
|
+
vals["g_batch_id"] = g_bill.g_batch.id
|
|
364
|
+
vals["g_supply_id"] = g_supply.id
|
|
365
|
+
vals["site_id"] = site_id
|
|
366
|
+
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
|
+
)
|
|
374
|
+
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
|
|
383
|
+
|
|
384
|
+
ReportRun.w_insert_row(report_run_id, "", titles, vals, {"is_checked": False})
|
|
343
385
|
|
|
344
386
|
|
|
345
387
|
def do_get(sess):
|
|
@@ -347,17 +389,39 @@ def do_get(sess):
|
|
|
347
389
|
|
|
348
390
|
if "g_batch_id" in request.values:
|
|
349
391
|
g_batch_id = req_int("g_batch_id")
|
|
392
|
+
g_batch = GBatch.get_by_id(g.sess, g_batch_id)
|
|
393
|
+
run_g_contract_id = g_batch.g_contract.id
|
|
350
394
|
elif "g_bill_id" in request.values:
|
|
351
395
|
g_bill_id = req_int("g_bill_id")
|
|
396
|
+
g_bill = GBill.get_by_id(g.sess, g_bill_id)
|
|
397
|
+
run_g_contract_id = g_bill.g_batch.g_contract.id
|
|
352
398
|
elif "g_contract_id" in request.values:
|
|
353
399
|
g_contract_id = req_int("g_contract_id")
|
|
354
400
|
start_date = req_date("start_date")
|
|
355
401
|
finish_date = req_date("finish_date")
|
|
402
|
+
run_g_contract_id = g_contract_id
|
|
356
403
|
else:
|
|
357
404
|
raise BadRequest(
|
|
358
405
|
"The bill check needs a g_batch_id, g_bill_id or g_contract_id."
|
|
359
406
|
)
|
|
360
407
|
|
|
361
|
-
|
|
408
|
+
report_run = ReportRun.insert(
|
|
409
|
+
sess,
|
|
410
|
+
"g_bill_check",
|
|
411
|
+
g.user,
|
|
412
|
+
"g_bill_check",
|
|
413
|
+
{"g_contract_id": run_g_contract_id},
|
|
414
|
+
)
|
|
415
|
+
sess.commit()
|
|
416
|
+
|
|
417
|
+
args = (
|
|
418
|
+
g_batch_id,
|
|
419
|
+
g_bill_id,
|
|
420
|
+
g_contract_id,
|
|
421
|
+
start_date,
|
|
422
|
+
finish_date,
|
|
423
|
+
g.user.id,
|
|
424
|
+
report_run.id,
|
|
425
|
+
)
|
|
362
426
|
threading.Thread(target=content, args=args).start()
|
|
363
|
-
return redirect("/
|
|
427
|
+
return redirect(f"/report_runs/{report_run.id}", 303)
|
chellow/static/css/chellow.css
CHANGED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}
|
|
4
|
+
» Report Runs » {{run.id}}
|
|
5
|
+
{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block nav %}
|
|
8
|
+
<a href="/report_runs">Report Runs</a> » {{run.id}}
|
|
9
|
+
{% endblock %}
|
|
10
|
+
|
|
11
|
+
{% block content %}
|
|
12
|
+
{% if request.method == "GET" and request.values.delete %}
|
|
13
|
+
<form method="post" action="/report_runs/{{run.id}}">
|
|
14
|
+
<fieldset>
|
|
15
|
+
<legend>Are you sure you want to delete this report run?</legend>
|
|
16
|
+
<input type="submit" name="delete" value="delete">
|
|
17
|
+
<a href="/report_runs/{{run.id}}">Cancel</a>
|
|
18
|
+
</fieldset>
|
|
19
|
+
</form>
|
|
20
|
+
{% else %}
|
|
21
|
+
<table>
|
|
22
|
+
<caption>Bill Check</caption>
|
|
23
|
+
<thead>
|
|
24
|
+
<tr>
|
|
25
|
+
<th>Date Created</th>
|
|
26
|
+
<th>Created By</th>
|
|
27
|
+
<th>Title</th>
|
|
28
|
+
<th>State</th>
|
|
29
|
+
<th>Number Of Rows</th>
|
|
30
|
+
<th>Sum Of Difference GBP</th>
|
|
31
|
+
<th>Delete</th>
|
|
32
|
+
<th>Download Spreadsheet</th>
|
|
33
|
+
</tr>
|
|
34
|
+
</thead>
|
|
35
|
+
<tbody>
|
|
36
|
+
<tr>
|
|
37
|
+
<td>{{run.date_created|hh_format}}</td>
|
|
38
|
+
<td>{{run.creator}}</td>
|
|
39
|
+
<td>{{run.title}}</td>
|
|
40
|
+
<td>{{run.state}}</td>
|
|
41
|
+
<td>{{rows|length}} (truncated at {{ROW_LIMIT}})</td>
|
|
42
|
+
<td>
|
|
43
|
+
{% if 'sum_difference' in summary and summary.sum_difference is not none %}
|
|
44
|
+
{{"%.2f"|format(summary.sum_difference)}}</td>
|
|
45
|
+
{% endif %}
|
|
46
|
+
<td>
|
|
47
|
+
<form action="/report_runs/{{run.id}}">
|
|
48
|
+
<fieldset style="border: none;">
|
|
49
|
+
<input type="submit" name="delete" value="Delete">
|
|
50
|
+
</fieldset>
|
|
51
|
+
</form>
|
|
52
|
+
</td>
|
|
53
|
+
<td><a href="/report_runs/{{run.id}}/spreadsheet">Download</a></td>
|
|
54
|
+
</tr>
|
|
55
|
+
</tbody>
|
|
56
|
+
</table>
|
|
57
|
+
|
|
58
|
+
{% if summary.missing_bills|length > 0 %}
|
|
59
|
+
<table class="sticky">
|
|
60
|
+
<caption>
|
|
61
|
+
Some Missing Bills (<a href="/report_runs/{{report_run}}">x</a>)
|
|
62
|
+
</caption>
|
|
63
|
+
<thead>
|
|
64
|
+
<tr>
|
|
65
|
+
<th>View</th>
|
|
66
|
+
<th>Import MPAN Core</th>
|
|
67
|
+
<th>Export MPAN Core</th>
|
|
68
|
+
<th>Start</th>
|
|
69
|
+
<th>Finish</th>
|
|
70
|
+
<th>Problem</th>
|
|
71
|
+
<th>Estimated Difference GBP</th>
|
|
72
|
+
</tr>
|
|
73
|
+
</thead>
|
|
74
|
+
<tbody>
|
|
75
|
+
{% for row in rows %}
|
|
76
|
+
<tr>
|
|
77
|
+
<td><a href="/report_run_rows/{{row.id}}">View</a></td>
|
|
78
|
+
{% for title in row.data.titles %}
|
|
79
|
+
<td>{{row.data['values'][title]}}</td>
|
|
80
|
+
{% endfor %}
|
|
81
|
+
</tr>
|
|
82
|
+
{% endfor %}
|
|
83
|
+
</tbody>
|
|
84
|
+
</table>
|
|
85
|
+
{% endif %}
|
|
86
|
+
|
|
87
|
+
{% if show_elements %}
|
|
88
|
+
<table class="sticky">
|
|
89
|
+
<caption>Elements</caption>
|
|
90
|
+
<thead>
|
|
91
|
+
<tr>
|
|
92
|
+
<th>Element</th>
|
|
93
|
+
{% for elname, diff in elements %}
|
|
94
|
+
<th>{{elname}}</th>
|
|
95
|
+
{% endfor %}
|
|
96
|
+
</tr>
|
|
97
|
+
</thead>
|
|
98
|
+
<tbody>
|
|
99
|
+
<tr>
|
|
100
|
+
<td>Sum of differences (GBP)</td>
|
|
101
|
+
{% for elname, diff in elements %}
|
|
102
|
+
{% if diff is not none %}
|
|
103
|
+
<td>{{"%.2f"|format(diff)}}</td>
|
|
104
|
+
{% endif %}
|
|
105
|
+
{% endfor %}
|
|
106
|
+
</tr>
|
|
107
|
+
</tbody>
|
|
108
|
+
</table>
|
|
109
|
+
{% endif %}
|
|
110
|
+
|
|
111
|
+
<table class="sticky">
|
|
112
|
+
<caption>
|
|
113
|
+
Rows - Ordered By
|
|
114
|
+
{% if sort_absolute %}
|
|
115
|
+
Absolute
|
|
116
|
+
{% endif %}
|
|
117
|
+
{{order_by}}
|
|
118
|
+
</caption>
|
|
119
|
+
<thead>
|
|
120
|
+
<tr>
|
|
121
|
+
<th rowspan="2">View</th>
|
|
122
|
+
<th rowspan="2">Batch</th>
|
|
123
|
+
<th rowspan="2">Site</th>
|
|
124
|
+
<th rowspan="2">MPRN</th>
|
|
125
|
+
<th rowspan="2">Covered Bills</th>
|
|
126
|
+
<th rowspan="2">Covered Start</th>
|
|
127
|
+
<th rowspan="2">Covered Finish</th>
|
|
128
|
+
<th colspan="{{columns|length}}">Difference</th>
|
|
129
|
+
<th rowspan="2">Problem</th>
|
|
130
|
+
</tr>
|
|
131
|
+
<tr>
|
|
132
|
+
{% for column in columns %}
|
|
133
|
+
<th>
|
|
134
|
+
{{' '.join(column.split('_')[1:])}}
|
|
135
|
+
{% if order_by == column %}
|
|
136
|
+
↑
|
|
137
|
+
{% else %}
|
|
138
|
+
<a href="/report_runs/{{run.id}}?order_by={{column}}">↑</a>
|
|
139
|
+
{% endif %}
|
|
140
|
+
</th>
|
|
141
|
+
{% endfor %}
|
|
142
|
+
</tr>
|
|
143
|
+
</thead>
|
|
144
|
+
<tbody>
|
|
145
|
+
{% for row in rows %}
|
|
146
|
+
{% set values = row.data['values'] %}
|
|
147
|
+
<tr>
|
|
148
|
+
<td><a href="/report_run_rows/{{row.id}}">View</a></td>
|
|
149
|
+
<td><a href="/g/batches/{{values.g_batch_id}}">{{values.batch}}</a></td>
|
|
150
|
+
<td>
|
|
151
|
+
<a href="/sites/{{values.site_id}}" title="{{values.site_name}}">{{values.site_code}}</a>
|
|
152
|
+
</td>
|
|
153
|
+
<td>
|
|
154
|
+
<a href="/g/supplies/{{values.g_supply_id}}">{{values.mprn}}</a>
|
|
155
|
+
</td>
|
|
156
|
+
<td>
|
|
157
|
+
{% if values['covered_bill_ids'] is not none %}
|
|
158
|
+
{% for bill_id in values['covered_bill_ids'] %}
|
|
159
|
+
<a href="/g/bills/{{bill_id}}">{{bill_id}}</a>
|
|
160
|
+
{% if bill_id == values.g_bill_id %}
|
|
161
|
+
{% endif %}
|
|
162
|
+
{% endfor %}
|
|
163
|
+
{% endif %}
|
|
164
|
+
</td>
|
|
165
|
+
<td><span title="{{values.covered_start}}">{{values.covered_start[:10]}}</span></td>
|
|
166
|
+
<td><span title="{{values.covered_finish}}">{{values.covered_finish[:10]}}</span></td>
|
|
167
|
+
{% for title in columns %}
|
|
168
|
+
<td>
|
|
169
|
+
{% if title in values and values[title] is not none %}
|
|
170
|
+
{{"%.2f"|format(values[title])}}
|
|
171
|
+
{% endif %}
|
|
172
|
+
</td>
|
|
173
|
+
{% endfor %}
|
|
174
|
+
<td>
|
|
175
|
+
{{ values.covered_problem }} {{ values.virtual_problem }}
|
|
176
|
+
</td>
|
|
177
|
+
</tr>
|
|
178
|
+
{% endfor %}
|
|
179
|
+
</tbody>
|
|
180
|
+
</table>
|
|
181
|
+
{% endif %}
|
|
182
|
+
{% endblock %}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}
|
|
4
|
+
» Report Runs » {{row.report_run.id}} » Row {{row.id}}
|
|
5
|
+
{% endblock %}
|
|
6
|
+
|
|
7
|
+
{% block nav %}
|
|
8
|
+
<a href="/report_runs">Report Runs</a> »
|
|
9
|
+
<a href="/report_runs/{{row.report_run.id}}">{{row.report_run.id}}</a>
|
|
10
|
+
» Row {{row.id}}
|
|
11
|
+
{% endblock %}
|
|
12
|
+
|
|
13
|
+
{% block content %}
|
|
14
|
+
{% set values = row.data['values'] %}
|
|
15
|
+
{% set properties = row.data.get('properties', {}) %}
|
|
16
|
+
{% if row.report_run.name == 'bill_check' %}
|
|
17
|
+
<table>
|
|
18
|
+
<caption>Bill Check</caption>
|
|
19
|
+
<thead>
|
|
20
|
+
<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>
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
<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>
|
|
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>
|
|
113
|
+
</tr>
|
|
114
|
+
</thead>
|
|
115
|
+
<tbody>
|
|
116
|
+
<tr>
|
|
117
|
+
<td>{{values['covered-from']}}</td>
|
|
118
|
+
<td>{{values['covered-to']}}</td>
|
|
119
|
+
<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>
|
|
131
|
+
{% endif %}
|
|
132
|
+
</td>
|
|
133
|
+
<td>
|
|
134
|
+
{% if values['metered-kwh'] != None %}
|
|
135
|
+
{{"%.0f"|format(values['metered-kwh'])}}
|
|
136
|
+
{% endif %}
|
|
137
|
+
</td>
|
|
138
|
+
<td>{{values['covered-net-gbp']}}</td>
|
|
139
|
+
<td>
|
|
140
|
+
{% if values['virtual-net-gbp'] != None %}
|
|
141
|
+
{{"%.2f"|format(values['virtual-net-gbp'])}}
|
|
142
|
+
{% endif %}
|
|
143
|
+
</td>
|
|
144
|
+
<td>
|
|
145
|
+
{% if values['difference-net-gbp'] != None %}
|
|
146
|
+
{{"%.2f"|format(values['difference-net-gbp'])}}
|
|
147
|
+
{% endif %}
|
|
148
|
+
</td>
|
|
149
|
+
<td>{{values['covered-problem']}}</td>
|
|
150
|
+
<td>{{values['virtual-problem']}}</td>
|
|
151
|
+
</tr>
|
|
152
|
+
</tbody>
|
|
153
|
+
</table>
|
|
154
|
+
|
|
155
|
+
{% for table in tables %}
|
|
156
|
+
<table>
|
|
157
|
+
<caption>{{table.name}}</caption>
|
|
158
|
+
<thead>
|
|
159
|
+
<tr>
|
|
160
|
+
{% for title in table.titles %}
|
|
161
|
+
<th>{{title}}</th>
|
|
162
|
+
{% endfor %}
|
|
163
|
+
</tr>
|
|
164
|
+
</thead>
|
|
165
|
+
<tbody>
|
|
166
|
+
<tr>
|
|
167
|
+
{% for v in table['values'] %}
|
|
168
|
+
<td>{{v}}</td>
|
|
169
|
+
{% endfor %}
|
|
170
|
+
</tr>
|
|
171
|
+
</tbody>
|
|
172
|
+
</table>
|
|
173
|
+
{% endfor %}
|
|
174
|
+
|
|
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 %}
|
|
191
|
+
{% endblock %}
|
chellow/views.py
CHANGED
|
@@ -1365,6 +1365,74 @@ def report_run_get(run_id):
|
|
|
1365
1365
|
hide_checked=hide_checked,
|
|
1366
1366
|
ROW_LIMIT=ROW_LIMIT,
|
|
1367
1367
|
)
|
|
1368
|
+
elif run.name == "g_bill_check":
|
|
1369
|
+
row = (
|
|
1370
|
+
g.sess.query(ReportRunRow)
|
|
1371
|
+
.filter(ReportRunRow.report_run == run)
|
|
1372
|
+
.order_by(ReportRunRow.id)
|
|
1373
|
+
.first()
|
|
1374
|
+
)
|
|
1375
|
+
elements = []
|
|
1376
|
+
summary = {}
|
|
1377
|
+
if row is None:
|
|
1378
|
+
pass
|
|
1379
|
+
|
|
1380
|
+
else:
|
|
1381
|
+
titles = row.data["titles"]
|
|
1382
|
+
diff_titles = [
|
|
1383
|
+
t for t in titles if t.startswith("difference_") and t.endswith("_gbp")
|
|
1384
|
+
]
|
|
1385
|
+
diff_selects = [
|
|
1386
|
+
func.sum(ReportRunRow.data["values"][t].as_float()) for t in diff_titles
|
|
1387
|
+
]
|
|
1388
|
+
sum_diffs = (
|
|
1389
|
+
g.sess.query(*diff_selects).filter(ReportRunRow.report_run == run).one()
|
|
1390
|
+
)
|
|
1391
|
+
|
|
1392
|
+
for t, sum_diff in zip(diff_titles, sum_diffs):
|
|
1393
|
+
elem = t[11:-4]
|
|
1394
|
+
sdiff = 0 if sum_diff is None else sum_diff
|
|
1395
|
+
if elem == "net":
|
|
1396
|
+
summary["sum_difference"] = sdiff
|
|
1397
|
+
else:
|
|
1398
|
+
elements.append((elem, sdiff))
|
|
1399
|
+
|
|
1400
|
+
elements.sort(key=lambda x: abs(x[1]), reverse=True)
|
|
1401
|
+
elements.insert(0, ("net", summary["sum_difference"]))
|
|
1402
|
+
|
|
1403
|
+
if "order_by" in request.values:
|
|
1404
|
+
order_by = req_str("order_by")
|
|
1405
|
+
else:
|
|
1406
|
+
order_by = "difference_net_gbp"
|
|
1407
|
+
|
|
1408
|
+
g_contract = GContract.get_by_id(g.sess, run.data["g_contract_id"])
|
|
1409
|
+
g_contract_props = g_contract.make_properties()
|
|
1410
|
+
props = g_contract_props.get("report_run", {})
|
|
1411
|
+
sort_absolute = props.get("sort_absolute", True)
|
|
1412
|
+
show_elements = props.get("show_elements", True)
|
|
1413
|
+
columns = props.get("columns", [f"difference_{el[0]}_gbp" for el in elements])
|
|
1414
|
+
|
|
1415
|
+
ROW_LIMIT = 200
|
|
1416
|
+
q = select(ReportRunRow).where(ReportRunRow.report_run == run).limit(ROW_LIMIT)
|
|
1417
|
+
if sort_absolute:
|
|
1418
|
+
q = q.order_by(
|
|
1419
|
+
func.abs(ReportRunRow.data["values"][order_by].as_float()).desc()
|
|
1420
|
+
)
|
|
1421
|
+
else:
|
|
1422
|
+
q = q.order_by(ReportRunRow.data["values"][order_by].as_float().desc())
|
|
1423
|
+
rows = g.sess.scalars(q).all()
|
|
1424
|
+
return render_template(
|
|
1425
|
+
"report_run_g_bill_check.html",
|
|
1426
|
+
run=run,
|
|
1427
|
+
rows=rows,
|
|
1428
|
+
summary=summary,
|
|
1429
|
+
elements=elements,
|
|
1430
|
+
order_by=order_by,
|
|
1431
|
+
ROW_LIMIT=ROW_LIMIT,
|
|
1432
|
+
sort_absolute=sort_absolute,
|
|
1433
|
+
show_elements=show_elements,
|
|
1434
|
+
columns=columns,
|
|
1435
|
+
)
|
|
1368
1436
|
|
|
1369
1437
|
elif run.name == "asset_comparison":
|
|
1370
1438
|
rows = (
|
|
@@ -1548,6 +1616,51 @@ def report_run_row_get(row_id):
|
|
|
1548
1616
|
return render_template(
|
|
1549
1617
|
"report_run_row_bill_check.html", row=row, raw_data=raw_data, tables=tables
|
|
1550
1618
|
)
|
|
1619
|
+
elif row.report_run.name == "g_bill_check":
|
|
1620
|
+
values = row.data["values"]
|
|
1621
|
+
elements = {}
|
|
1622
|
+
for t in row.data["values"].keys():
|
|
1623
|
+
|
|
1624
|
+
if (
|
|
1625
|
+
t.startswith("covered_")
|
|
1626
|
+
or t.startswith("virtual_")
|
|
1627
|
+
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
|
+
):
|
|
1635
|
+
toks = t.split("_")
|
|
1636
|
+
name = "_".join(toks[1:-1])
|
|
1637
|
+
try:
|
|
1638
|
+
table = elements[name]
|
|
1639
|
+
except KeyError:
|
|
1640
|
+
table = elements[name] = {"order": 0}
|
|
1641
|
+
|
|
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])
|
|
1650
|
+
|
|
1651
|
+
for k, v in elements.items():
|
|
1652
|
+
if k == "net":
|
|
1653
|
+
continue
|
|
1654
|
+
v["name"] = k
|
|
1655
|
+
tables.append(v)
|
|
1656
|
+
|
|
1657
|
+
tables.sort(key=lambda t: t["order"], reverse=True)
|
|
1658
|
+
return render_template(
|
|
1659
|
+
"report_run_row_g_bill_check.html",
|
|
1660
|
+
row=row,
|
|
1661
|
+
raw_data=raw_data,
|
|
1662
|
+
tables=tables,
|
|
1663
|
+
)
|
|
1551
1664
|
|
|
1552
1665
|
else:
|
|
1553
1666
|
return render_template(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chellow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1739889885.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)
|
|
@@ -5,14 +5,14 @@ chellow/commands.py,sha256=ESBe9ZWj1c3vdZgqMZ9gFvYAB3hRag2R1PzOwuw9yFo,1302
|
|
|
5
5
|
chellow/dloads.py,sha256=dixp-O0MF2_mlwrnKx3D9DH09Qu05BjTo0rZfigTjR4,5534
|
|
6
6
|
chellow/edi_lib.py,sha256=alu20x9ZX06iPfnNI9dEJzuP6RIf4We3Y_M_bl7RrcY,51789
|
|
7
7
|
chellow/general_import.py,sha256=tcYZK2N7HOFJSkYyy3MMxVBEvMFjfB9pjF0ksujtkFA,65113
|
|
8
|
-
chellow/models.py,sha256=
|
|
8
|
+
chellow/models.py,sha256=GVuPnDUGJqPbdD8Z4Ccoiw4ZLeuEXFgAkrTLS_znTQw,244452
|
|
9
9
|
chellow/national_grid.py,sha256=czwIZqzJndSGhEMQ5YzI6hRBhvjkM6VRVYXybf4_KXg,4377
|
|
10
10
|
chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
|
|
11
11
|
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=
|
|
15
|
+
chellow/views.py,sha256=82V1OtdscrAmbiT3B5MDZoCe50fDSJwfBF-PpbB5tm8,83513
|
|
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
|
|
@@ -72,7 +72,7 @@ chellow/gas/cv.py,sha256=4cdYYQ8Qak6NeYdBCB4YaQ0jX8-UkaydIIdibCQuXxM,7344
|
|
|
72
72
|
chellow/gas/dn_rate_parser.py,sha256=Mq8rAcUEUxIQOks59bsCKl8GrefvoHbrTCHqon9N0z0,11340
|
|
73
73
|
chellow/gas/engine.py,sha256=d2rR1y8b3u2QhmfqyFwwLu_loeZxY_3WwwtDyGJfam0,25282
|
|
74
74
|
chellow/gas/transportation.py,sha256=Bkg8TWOs-v0ES-4qqwbleiOhqbE_t2KauUx9JYMZELM,5300
|
|
75
|
-
chellow/gas/views.py,sha256=
|
|
75
|
+
chellow/gas/views.py,sha256=GeCvi6BGTUN7bu7sVkypNckwG3Crl6AbUcRob9qMi0E,59733
|
|
76
76
|
chellow/reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
77
|
chellow/reports/report_109.py,sha256=Exb-FQ5f70-ier_h15CgHGysQ7vJ7k3gFZ1001zM3iM,11171
|
|
78
78
|
chellow/reports/report_111.py,sha256=o_wWyrtmxpTnmT9DVlsG5h5wdm3JqojirRlx_7W5_kQ,28787
|
|
@@ -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=
|
|
93
|
+
chellow/reports/report_429.py,sha256=SbFlBsHXWMWRlMbY_e0zco2R8tMG9XVulr56E3mRalU,14287
|
|
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
|
|
@@ -108,7 +108,7 @@ chellow/reports/report_g_virtual_bills.py,sha256=20vHa5LGQwOAlJlaGJaGszZrrbT0PMO
|
|
|
108
108
|
chellow/reports/report_g_virtual_bills_hh.py,sha256=gaiLEmKTpq6JsfZ1p0SdCDuPvzvigXp6z88gHRCA63w,3416
|
|
109
109
|
chellow/reports/report_sscs.py,sha256=fQWyVG-gdg37DyNHgpNARpSxIwTl7mCn20fDLwx9oHg,3214
|
|
110
110
|
chellow/reports/report_supply_contacts.py,sha256=pvwlInaPYV_pa9MMK6vh854plHFwv3m5zo5xulR1g5I,3599
|
|
111
|
-
chellow/static/css/chellow.css,sha256=
|
|
111
|
+
chellow/static/css/chellow.css,sha256=dnkuj9Z1BCOV_L2Y26lDd2QlTmFFhATa1YvwPVch1Oc,5375
|
|
112
112
|
chellow/static/images/favicon.svg,sha256=ySFHoVJYmr-xU93QrE-jLYn-ZNythh2vsemnR8dkvg0,2339
|
|
113
113
|
chellow/static/images/favicon_test.svg,sha256=HnLS_BjNt8M0Ikko5Z-f_E2aed7y6RRU6j3K6XADciE,2346
|
|
114
114
|
chellow/static/images/logo.png,sha256=XMW2XwukTicKVJ46E2SnbHJYh77uFLVYlwR4xN43YKg,1569
|
|
@@ -142,9 +142,11 @@ chellow/templates/report_run.html,sha256=O_wjIu43S-mKVyZyku3dJJdvyck3rAgEdhw59Ts
|
|
|
142
142
|
chellow/templates/report_run_asset_comparison.html,sha256=VYCCUmIC7Mfe7uuaAHb6ihiK6zsqeTlQbzgtzLqR3zg,2305
|
|
143
143
|
chellow/templates/report_run_bill_check.html,sha256=H2ayoBL7EgKMq2Nwq5VjE_TNvcIKcqeCm0alQWLIw78,5084
|
|
144
144
|
chellow/templates/report_run_ecoes_comparison.html,sha256=VmkT5ypWLP8qZS6NbDTC4yDaG7mnUlxZz7EV8xkHGZw,4086
|
|
145
|
+
chellow/templates/report_run_g_bill_check.html,sha256=tOXl_mjR__foYKiOYflJbK-459actAtjzv8rfuL3TwM,4851
|
|
145
146
|
chellow/templates/report_run_monthly_duration_org.html,sha256=gGNGJ4Q50q4BtIMi98rhO-7NqRHcsFUmbj2qzeOLejw,1713
|
|
146
147
|
chellow/templates/report_run_row.html,sha256=bmtcdqJaS1CXpL0i8PuqvmeF98jKNYX5-mnQu-OuDKQ,3791
|
|
147
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
|
|
148
150
|
chellow/templates/report_run_supply_contacts.html,sha256=JNzwz9M6qbLRDMkCzFCxxANapUer5klxo7t5a48nAzg,2117
|
|
149
151
|
chellow/templates/report_runs.html,sha256=ecoIkl2WtfYtifiTxnslmpMGYYGVQW-CVSBpqhXyiE4,1131
|
|
150
152
|
chellow/templates/scenario.html,sha256=tCoq1wBq4l9PRS-zFtPcCWXlxD_SSFvFFkERf4FWVNU,2055
|
|
@@ -376,6 +378,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
|
|
|
376
378
|
chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
|
|
377
379
|
chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
|
|
378
380
|
chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
|
|
379
|
-
chellow-
|
|
380
|
-
chellow-
|
|
381
|
-
chellow-
|
|
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,,
|
|
File without changes
|