chellow 1759823276.0.0__py3-none-any.whl → 1761056531.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/dloads.py +2 -2
- chellow/e/lcc.py +1 -1
- chellow/e/rab.py +75 -0
- chellow/e/views.py +1 -1
- chellow/reports/report_247.py +1 -4
- chellow/reports/report_channel_snags.py +288 -0
- chellow/templates/e/channel_snags.html +32 -100
- chellow/templates/macros.html +14 -4
- chellow/templates/reports/channel_snags.html +91 -0
- chellow/utils.py +14 -3
- {chellow-1759823276.0.0.dist-info → chellow-1761056531.0.0.dist-info}/METADATA +1 -1
- {chellow-1759823276.0.0.dist-info → chellow-1761056531.0.0.dist-info}/RECORD +13 -11
- chellow/reports/report_233.py +0 -150
- {chellow-1759823276.0.0.dist-info → chellow-1761056531.0.0.dist-info}/WHEEL +0 -0
chellow/dloads.py
CHANGED
|
@@ -91,7 +91,7 @@ class DloadFile:
|
|
|
91
91
|
def open_file(base, user, mode="r", newline=None, is_zip=False):
|
|
92
92
|
global download_id
|
|
93
93
|
|
|
94
|
-
base =
|
|
94
|
+
base = "".join(x if (x.isalnum() or x in "_.") else "_" for x in base)
|
|
95
95
|
try:
|
|
96
96
|
lock.acquire()
|
|
97
97
|
if len(list(download_path.iterdir())) == 0:
|
|
@@ -108,7 +108,7 @@ def open_file(base, user, mode="r", newline=None, is_zip=False):
|
|
|
108
108
|
un = user.proxy_username
|
|
109
109
|
else:
|
|
110
110
|
un = user.email_address
|
|
111
|
-
uname =
|
|
111
|
+
uname = "".join(x if (x.isalnum() or x in "_") else "_" for x in un)
|
|
112
112
|
|
|
113
113
|
names = tuple("_".join((serial, v, uname, base)) for v in ("RUNNING", "FINISHED"))
|
|
114
114
|
running_name, finished_name = tuple(download_path / name for name in names)
|
chellow/e/lcc.py
CHANGED
|
@@ -46,7 +46,7 @@ def run_import(sess, log, set_progress):
|
|
|
46
46
|
s = requests.Session()
|
|
47
47
|
s.verify = False
|
|
48
48
|
|
|
49
|
-
for mod_name in ("chellow.e.cfd",):
|
|
49
|
+
for mod_name in ("chellow.e.cfd", "chellow.e.rab"):
|
|
50
50
|
mod = import_module(mod_name)
|
|
51
51
|
mod.lcc_import(sess, log, set_progress, s)
|
|
52
52
|
|
chellow/e/rab.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from datetime import datetime as Datetime
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import select
|
|
6
|
+
|
|
7
|
+
from chellow.e.lcc import api_records
|
|
8
|
+
from chellow.models import Contract, RateScript
|
|
9
|
+
from chellow.utils import ct_datetime, to_ct, to_utc
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def hh(data_source):
|
|
13
|
+
try:
|
|
14
|
+
rab_cache = data_source.caches["rab"]
|
|
15
|
+
except KeyError:
|
|
16
|
+
rab_cache = data_source.caches["rab"] = {}
|
|
17
|
+
|
|
18
|
+
for h in data_source.hh_data:
|
|
19
|
+
try:
|
|
20
|
+
h["rab"] = rab_cache[h["start-date"]]
|
|
21
|
+
except KeyError:
|
|
22
|
+
h_start = h["start-date"]
|
|
23
|
+
rate_str = data_source.non_core_rate("rab_forecast_ilr_tra", h_start)[
|
|
24
|
+
"record"
|
|
25
|
+
]["Interim_Levy_Rate_GBP_MWh"]
|
|
26
|
+
if rate_str == "":
|
|
27
|
+
base_rate_dec = Decimal("0")
|
|
28
|
+
else:
|
|
29
|
+
base_rate_dec = Decimal(rate_str) / Decimal(1000)
|
|
30
|
+
|
|
31
|
+
base_rate = float(base_rate_dec)
|
|
32
|
+
|
|
33
|
+
h["rab"] = rab_cache[h_start] = {
|
|
34
|
+
"interim": base_rate,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def lcc_import(sess, log, set_progress, s):
|
|
39
|
+
import_forecast_ilr_tra(sess, log, set_progress, s)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _parse_date(date_str):
|
|
43
|
+
return to_utc(to_ct(Datetime.strptime(date_str[:10], "%Y-%m-%d")))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def import_forecast_ilr_tra(sess, log, set_progress, s):
|
|
47
|
+
log("Starting to check for new LCC RAB Forecast ILR TRA")
|
|
48
|
+
|
|
49
|
+
contract_name = "rab_forecast_ilr_tra"
|
|
50
|
+
contract = Contract.find_non_core_by_name(sess, contract_name)
|
|
51
|
+
if contract is None:
|
|
52
|
+
contract = Contract.insert_non_core(
|
|
53
|
+
sess, contract_name, "", {}, to_utc(ct_datetime(1996, 4, 1)), None, {}
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
for record in api_records(log, s, "1231fbb3-93ee-4a33-87a9-f15bb377346d"):
|
|
57
|
+
period_start_str = record["Month"]
|
|
58
|
+
if len(period_start_str) == 0:
|
|
59
|
+
continue
|
|
60
|
+
period_start = _parse_date(period_start_str)
|
|
61
|
+
|
|
62
|
+
rs = sess.execute(
|
|
63
|
+
select(RateScript).where(
|
|
64
|
+
RateScript.contract == contract,
|
|
65
|
+
RateScript.start_date == period_start,
|
|
66
|
+
)
|
|
67
|
+
).scalar_one_or_none()
|
|
68
|
+
if rs is None:
|
|
69
|
+
rs = contract.insert_rate_script(sess, period_start, {})
|
|
70
|
+
|
|
71
|
+
rs_script = rs.make_script()
|
|
72
|
+
rs_script["record"] = record
|
|
73
|
+
rs.update(rs_script)
|
|
74
|
+
sess.commit()
|
|
75
|
+
log("Finished LCC RAB Forecast ILR TRA")
|
chellow/e/views.py
CHANGED
|
@@ -381,7 +381,7 @@ def channel_snags_get():
|
|
|
381
381
|
total_snags_q = total_snags_q.where(Era.dc_contract == contract)
|
|
382
382
|
snags_q = snags_q.where(Era.dc_contract == contract)
|
|
383
383
|
|
|
384
|
-
total_snags = g.sess.
|
|
384
|
+
total_snags = g.sess.scalars(total_snags_q).one()
|
|
385
385
|
|
|
386
386
|
snag_groups = []
|
|
387
387
|
prev_snag = None
|
chellow/reports/report_247.py
CHANGED
|
@@ -1116,10 +1116,7 @@ def do_post(sess):
|
|
|
1116
1116
|
exp_mpan_core if imp_mpan_core is None else imp_mpan_core
|
|
1117
1117
|
]
|
|
1118
1118
|
|
|
1119
|
-
|
|
1120
|
-
compression = req_bool("compression")
|
|
1121
|
-
else:
|
|
1122
|
-
compression = True
|
|
1119
|
+
compression = req_bool("compression")
|
|
1123
1120
|
|
|
1124
1121
|
user = g.user
|
|
1125
1122
|
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import sys
|
|
3
|
+
import threading
|
|
4
|
+
import traceback
|
|
5
|
+
|
|
6
|
+
from dateutil.relativedelta import relativedelta
|
|
7
|
+
|
|
8
|
+
from flask import g, redirect, render_template
|
|
9
|
+
|
|
10
|
+
from sqlalchemy.orm import joinedload
|
|
11
|
+
from sqlalchemy.sql.expression import false, select, true
|
|
12
|
+
|
|
13
|
+
from werkzeug.exceptions import BadRequest
|
|
14
|
+
|
|
15
|
+
from chellow.dloads import open_file
|
|
16
|
+
from chellow.models import (
|
|
17
|
+
Channel,
|
|
18
|
+
Contract,
|
|
19
|
+
Era,
|
|
20
|
+
Party,
|
|
21
|
+
RSession,
|
|
22
|
+
Site,
|
|
23
|
+
SiteEra,
|
|
24
|
+
Snag,
|
|
25
|
+
Supply,
|
|
26
|
+
User,
|
|
27
|
+
)
|
|
28
|
+
from chellow.utils import (
|
|
29
|
+
csv_make_val,
|
|
30
|
+
hh_before,
|
|
31
|
+
req_bool,
|
|
32
|
+
req_int,
|
|
33
|
+
req_int_none,
|
|
34
|
+
req_str,
|
|
35
|
+
utc_datetime_now,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _make_rows(
|
|
40
|
+
sess,
|
|
41
|
+
now,
|
|
42
|
+
contract,
|
|
43
|
+
days_hidden,
|
|
44
|
+
is_ignored,
|
|
45
|
+
show_settlement,
|
|
46
|
+
only_ongoing,
|
|
47
|
+
days_long_hidden,
|
|
48
|
+
limit=None,
|
|
49
|
+
):
|
|
50
|
+
cutoff_date = now - relativedelta(days=days_hidden)
|
|
51
|
+
q = (
|
|
52
|
+
select(Snag, Channel, Era, Supply, SiteEra, Site, Contract)
|
|
53
|
+
.join(Channel, Snag.channel_id == Channel.id)
|
|
54
|
+
.join(Era, Channel.era_id == Era.id)
|
|
55
|
+
.join(Supply, Era.supply_id == Supply.id)
|
|
56
|
+
.join(SiteEra, Era.site_eras)
|
|
57
|
+
.join(Site, SiteEra.site_id == Site.id)
|
|
58
|
+
.join(Contract, Era.dc_contract_id == Contract.id)
|
|
59
|
+
.where(
|
|
60
|
+
SiteEra.is_physical == true(),
|
|
61
|
+
Snag.start_date < cutoff_date,
|
|
62
|
+
)
|
|
63
|
+
.order_by(
|
|
64
|
+
Site.code,
|
|
65
|
+
Supply.id,
|
|
66
|
+
Channel.imp_related,
|
|
67
|
+
Channel.channel_type,
|
|
68
|
+
Snag.description,
|
|
69
|
+
Snag.start_date,
|
|
70
|
+
Snag.id,
|
|
71
|
+
)
|
|
72
|
+
.options(joinedload(Era.dc_contract))
|
|
73
|
+
)
|
|
74
|
+
if contract is not None:
|
|
75
|
+
q = q.where(Era.dc_contract == contract)
|
|
76
|
+
|
|
77
|
+
if not is_ignored:
|
|
78
|
+
q = q.where(Snag.is_ignored == false())
|
|
79
|
+
|
|
80
|
+
if show_settlement == "yes":
|
|
81
|
+
q = q.join(Party, Supply.dno_id == Party.id).where(Party.dno_code != "99")
|
|
82
|
+
elif show_settlement == "no":
|
|
83
|
+
q = q.join(Party, Supply.dno_id == Party.id).where(Party.dno_code == "99")
|
|
84
|
+
elif show_settlement == "both":
|
|
85
|
+
pass
|
|
86
|
+
else:
|
|
87
|
+
raise BadRequest("show_settlement must be 'yes', 'no' or 'both'.")
|
|
88
|
+
|
|
89
|
+
snag_groups = []
|
|
90
|
+
prev_snag = None
|
|
91
|
+
for snag, channel, era, supply, site_era, site, contract in sess.execute(q):
|
|
92
|
+
snag_start = snag.start_date
|
|
93
|
+
snag_finish = snag.finish_date
|
|
94
|
+
|
|
95
|
+
if snag_finish is None:
|
|
96
|
+
duration = now - snag_start
|
|
97
|
+
age_of_snag = None
|
|
98
|
+
else:
|
|
99
|
+
duration = snag_finish - snag_start
|
|
100
|
+
if hh_before(cutoff_date, snag_finish):
|
|
101
|
+
age_of_snag = None
|
|
102
|
+
else:
|
|
103
|
+
delta = now - snag_finish
|
|
104
|
+
age_of_snag = delta.days
|
|
105
|
+
|
|
106
|
+
if only_ongoing and age_of_snag is not None:
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
if days_long_hidden is not None and duration < days_long_hidden:
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
if (
|
|
113
|
+
prev_snag is None
|
|
114
|
+
or channel.era != prev_snag.channel.era
|
|
115
|
+
or snag.start_date != prev_snag.start_date
|
|
116
|
+
or snag.finish_date != prev_snag.finish_date
|
|
117
|
+
or snag.description != prev_snag.description
|
|
118
|
+
):
|
|
119
|
+
if limit is not None and len(snag_groups) > limit:
|
|
120
|
+
break
|
|
121
|
+
|
|
122
|
+
snag_group = {
|
|
123
|
+
"snags": [],
|
|
124
|
+
"site": site,
|
|
125
|
+
"era": era,
|
|
126
|
+
"supply": supply,
|
|
127
|
+
"description": snag.description,
|
|
128
|
+
"start_date": snag.start_date,
|
|
129
|
+
"finish_date": snag.finish_date,
|
|
130
|
+
"contract": contract,
|
|
131
|
+
"contract_name": contract.name,
|
|
132
|
+
"hidden_days": days_hidden,
|
|
133
|
+
"chellow_id": snag.id,
|
|
134
|
+
"imp_mpan_core": era.imp_mpan_core,
|
|
135
|
+
"exp_mpan_core": era.exp_mpan_core,
|
|
136
|
+
"site_code": site.code,
|
|
137
|
+
"site_name": site.name,
|
|
138
|
+
"snag_description": snag.description,
|
|
139
|
+
"channel_type": channel.channel_type,
|
|
140
|
+
"is_ignored": snag.is_ignored,
|
|
141
|
+
"days_since_finished": age_of_snag,
|
|
142
|
+
"duration": duration.days,
|
|
143
|
+
}
|
|
144
|
+
snag_groups.append(snag_group)
|
|
145
|
+
snag_group["snags"].append(snag)
|
|
146
|
+
prev_snag = snag
|
|
147
|
+
|
|
148
|
+
def make_key(item):
|
|
149
|
+
return item["duration"]
|
|
150
|
+
|
|
151
|
+
snag_groups.sort(key=make_key, reverse=True)
|
|
152
|
+
return snag_groups
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def content(
|
|
156
|
+
contract_id,
|
|
157
|
+
days_hidden,
|
|
158
|
+
is_ignored,
|
|
159
|
+
user_id,
|
|
160
|
+
only_ongoing,
|
|
161
|
+
show_settlement,
|
|
162
|
+
days_long_hidden,
|
|
163
|
+
):
|
|
164
|
+
f = writer = None
|
|
165
|
+
try:
|
|
166
|
+
with RSession() as sess:
|
|
167
|
+
user = User.get_by_id(sess, user_id)
|
|
168
|
+
if contract_id is None:
|
|
169
|
+
contract = None
|
|
170
|
+
namef = "all"
|
|
171
|
+
else:
|
|
172
|
+
contract = Contract.get_dc_by_id(sess, contract_id)
|
|
173
|
+
namef = contract.name
|
|
174
|
+
|
|
175
|
+
f = open_file(f"channel_snags_{namef}.csv", user, mode="w", newline="")
|
|
176
|
+
writer = csv.writer(f, lineterminator="\n")
|
|
177
|
+
titles = (
|
|
178
|
+
"contract",
|
|
179
|
+
"hidden_days",
|
|
180
|
+
"chellow_ids",
|
|
181
|
+
"imp_mpan_core",
|
|
182
|
+
"exp_mpan_core",
|
|
183
|
+
"site_code",
|
|
184
|
+
"site_name",
|
|
185
|
+
"snag_description",
|
|
186
|
+
"channel_types",
|
|
187
|
+
"start_date",
|
|
188
|
+
"finish_date",
|
|
189
|
+
"is_ignored",
|
|
190
|
+
"days_since_finished",
|
|
191
|
+
"duration",
|
|
192
|
+
)
|
|
193
|
+
writer.writerow(titles)
|
|
194
|
+
|
|
195
|
+
now = utc_datetime_now()
|
|
196
|
+
for snag_group in _make_rows(
|
|
197
|
+
sess,
|
|
198
|
+
now,
|
|
199
|
+
contract,
|
|
200
|
+
days_hidden,
|
|
201
|
+
is_ignored,
|
|
202
|
+
show_settlement,
|
|
203
|
+
only_ongoing,
|
|
204
|
+
days_long_hidden,
|
|
205
|
+
):
|
|
206
|
+
|
|
207
|
+
vals = {
|
|
208
|
+
"contract": snag_group["contract"].name,
|
|
209
|
+
"hidden_days": days_hidden,
|
|
210
|
+
"chellow_ids": [snag.id for snag in snag_group["snags"]],
|
|
211
|
+
"imp_mpan_core": snag_group["imp_mpan_core"],
|
|
212
|
+
"exp_mpan_core": snag_group["exp_mpan_core"],
|
|
213
|
+
"site": snag_group["site"],
|
|
214
|
+
"site_code": snag_group["site"].code,
|
|
215
|
+
"site_name": snag_group["site"].name,
|
|
216
|
+
"snag_description": snag_group["description"],
|
|
217
|
+
"channel_types": [
|
|
218
|
+
f"{s.channel.imp_related}_{s.channel.channel_type}"
|
|
219
|
+
for s in snag_group["snags"]
|
|
220
|
+
],
|
|
221
|
+
"start_date": snag_group["start_date"],
|
|
222
|
+
"finish_date": snag_group["finish_date"],
|
|
223
|
+
"is_ignored": snag_group["is_ignored"],
|
|
224
|
+
"days_since_finished": snag_group["days_since_finished"],
|
|
225
|
+
"duration": snag_group["duration"],
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
writer.writerow(csv_make_val(vals[t]) for t in titles)
|
|
229
|
+
except BaseException:
|
|
230
|
+
msg = traceback.format_exc()
|
|
231
|
+
sys.stderr.write(msg)
|
|
232
|
+
writer.writerow([msg])
|
|
233
|
+
finally:
|
|
234
|
+
if f is not None:
|
|
235
|
+
f.close()
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
LIMIT = 200
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def do_get(sess):
|
|
242
|
+
contract_id = req_int_none("dc_contract_id")
|
|
243
|
+
days_hidden = req_int("days_hidden")
|
|
244
|
+
is_ignored = req_bool("is_ignored")
|
|
245
|
+
only_ongoing = req_bool("only_ongoing")
|
|
246
|
+
show_settlement = req_str("show_settlement")
|
|
247
|
+
as_csv = req_bool("as_csv")
|
|
248
|
+
days_long_hidden = req_int_none("days_long_hidden")
|
|
249
|
+
|
|
250
|
+
if as_csv:
|
|
251
|
+
args = (
|
|
252
|
+
contract_id,
|
|
253
|
+
days_hidden,
|
|
254
|
+
is_ignored,
|
|
255
|
+
g.user.id,
|
|
256
|
+
only_ongoing,
|
|
257
|
+
show_settlement,
|
|
258
|
+
)
|
|
259
|
+
threading.Thread(target=content, args=args).start()
|
|
260
|
+
return redirect("/downloads", 303)
|
|
261
|
+
else:
|
|
262
|
+
if contract_id is None:
|
|
263
|
+
contract = None
|
|
264
|
+
else:
|
|
265
|
+
contract = Contract.get_dc_by_id(sess, contract_id)
|
|
266
|
+
now = utc_datetime_now()
|
|
267
|
+
snag_groups = _make_rows(
|
|
268
|
+
sess,
|
|
269
|
+
now,
|
|
270
|
+
contract,
|
|
271
|
+
days_hidden,
|
|
272
|
+
is_ignored,
|
|
273
|
+
show_settlement,
|
|
274
|
+
only_ongoing,
|
|
275
|
+
days_long_hidden,
|
|
276
|
+
limit=LIMIT,
|
|
277
|
+
)
|
|
278
|
+
return render_template(
|
|
279
|
+
"reports/channel_snags.html",
|
|
280
|
+
contract=contract,
|
|
281
|
+
limit=LIMIT,
|
|
282
|
+
snag_groups=snag_groups,
|
|
283
|
+
days_hidden=days_hidden,
|
|
284
|
+
is_ignored=is_ignored,
|
|
285
|
+
only_ongoing=only_ongoing,
|
|
286
|
+
show_settlement=show_settlement,
|
|
287
|
+
days_long_hidden=days_long_hidden,
|
|
288
|
+
)
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
Channel Snags
|
|
9
9
|
{% endblock %}
|
|
10
10
|
|
|
11
|
+
{% block inside_head %}
|
|
12
|
+
<style>
|
|
13
|
+
#snags.htmx-swapping {
|
|
14
|
+
opacity: 0;
|
|
15
|
+
transition: opacity 1s ease-out;
|
|
16
|
+
}
|
|
17
|
+
</style>
|
|
18
|
+
{% endblock %}
|
|
19
|
+
|
|
11
20
|
{% block nav %}
|
|
12
21
|
<a href="/e/dc_contracts">DC Contracts</a> »
|
|
13
22
|
{% if contract %}
|
|
@@ -17,113 +26,36 @@
|
|
|
17
26
|
{% endblock %}
|
|
18
27
|
|
|
19
28
|
{% block content %}
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
<form hx-get="/reports/channel_snags" hx-params="*" hx-include="this" hx-trigger="load, change"
|
|
30
|
+
hx-target="#snags" hx-swap="outerHTML swap:1s">
|
|
22
31
|
<fieldset>
|
|
23
|
-
<legend>
|
|
32
|
+
<legend>Filters</legend>
|
|
24
33
|
<input type="hidden" name="dc_contract_id" value="{{contract.id}}">
|
|
25
34
|
<label>Hide snags < days old</label>
|
|
26
|
-
|
|
35
|
+
{{input_text('days_hidden', initial='5', size=3, maxlength=3)}}
|
|
27
36
|
<label>Include ignored snags</label> {{input_checkbox('is_ignored', False)}}
|
|
28
|
-
<input type="submit" value="Download">
|
|
29
|
-
</fieldset>
|
|
30
|
-
</form>
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
finish date is 'ongoing' or if it finished less than 'Days Hidden' ago).
|
|
35
|
-
</p>
|
|
38
|
+
<label>Only show ongoing snags</label>
|
|
39
|
+
{{input_checkbox('only_ongoing', initial=True)}}
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
">
|
|
45
|
-
<label>Hide snags < days old</label>
|
|
46
|
-
{{input_text('days_hidden', '0', 3, 3)}}
|
|
47
|
-
<label>Include ignored snags</label> {{input_checkbox('is_ignored', False)}}
|
|
48
|
-
<input type="submit" value="Show">
|
|
49
|
-
</fieldset>
|
|
50
|
-
</form>
|
|
41
|
+
<fieldset>
|
|
42
|
+
|
|
43
|
+
<label>Show settlement only</label>
|
|
44
|
+
{{input_radio('show_settlement', 'yes', initial=False)}}
|
|
45
|
+
|
|
46
|
+
<label>Show non-settlement only</label>
|
|
47
|
+
{{input_radio('show_settlement', 'no', initial=False)}}
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{%- if not is_ignored %}
|
|
55
|
-
that aren't ignored
|
|
56
|
-
{%- endif -%}.
|
|
57
|
-
</p>
|
|
49
|
+
<label>Show both</label>
|
|
50
|
+
{{input_radio('show_settlement', 'both', initial=True)}}
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<th>Export MPAN Core</th>
|
|
67
|
-
<th>Sites</th>
|
|
68
|
-
<th>Snag Description</th>
|
|
69
|
-
<th>Channels</th>
|
|
70
|
-
<th>Duration</th>
|
|
71
|
-
</tr>
|
|
72
|
-
</thead>
|
|
73
|
-
<tbody>
|
|
74
|
-
{% for snag_group in snag_groups %}
|
|
75
|
-
<tr>
|
|
76
|
-
<td>
|
|
77
|
-
<ul>
|
|
78
|
-
{% for snag in snag_group.snags %}
|
|
79
|
-
<li>
|
|
80
|
-
<a href="/e/channel_snags/{{snag.id}}">view</a>
|
|
81
|
-
[<a href="/e/channel_snags/{{snag.id}}/edit">edit</a>]
|
|
82
|
-
{% if snag.is_ignored %} ignored{% endif %}
|
|
83
|
-
</li>
|
|
84
|
-
{% endfor %}
|
|
85
|
-
</ul>
|
|
86
|
-
</td>
|
|
87
|
-
<td>{{snag_group.era.dc_contract.name}}</td>
|
|
88
|
-
<td>
|
|
89
|
-
{% if snag_group.era.imp_mpan_core %}
|
|
90
|
-
{{snag_group.era.imp_mpan_core}}
|
|
91
|
-
{% endif %}
|
|
92
|
-
</td>
|
|
93
|
-
<td>
|
|
94
|
-
{% if snag_group.era.exp_mpan_core %}
|
|
95
|
-
{{snag_group.era.exp_mpan_core}}
|
|
96
|
-
{% endif %}
|
|
97
|
-
</td>
|
|
98
|
-
<td>
|
|
99
|
-
<ul>
|
|
100
|
-
{% for site in snag_group.sites %}
|
|
101
|
-
<li>{{site.code}} {{site.name}}</li>
|
|
102
|
-
{% endfor %}
|
|
103
|
-
</ul>
|
|
104
|
-
</td>
|
|
105
|
-
<td>{{snag_group.description}}</td>
|
|
106
|
-
<td>
|
|
107
|
-
<ul>
|
|
108
|
-
{% for snag in snag_group.snags %}
|
|
109
|
-
<li>
|
|
110
|
-
{% if snag.channel.imp_related %}
|
|
111
|
-
Import
|
|
112
|
-
{% else %}
|
|
113
|
-
Export
|
|
114
|
-
{% endif %}
|
|
115
|
-
{{snag.channel.channel_type}}
|
|
116
|
-
</li>
|
|
117
|
-
{% endfor %}
|
|
118
|
-
</ul>
|
|
119
|
-
</td>
|
|
120
|
-
<td>
|
|
121
|
-
{{snag_group.start_date|hh_format}} to
|
|
122
|
-
{{snag_group.finish_date|hh_format}}
|
|
123
|
-
</td>
|
|
124
|
-
</tr>
|
|
125
|
-
{% endfor %}
|
|
126
|
-
</tbody>
|
|
127
|
-
</table>
|
|
52
|
+
</fieldset>
|
|
53
|
+
|
|
54
|
+
<label>Hide snags < days long</label>
|
|
55
|
+
{{input_text('days_long_hidden', initial='', size=3, maxlength=3)}}
|
|
56
|
+
|
|
57
|
+
</fieldset>
|
|
58
|
+
</form>
|
|
128
59
|
|
|
60
|
+
<div id="snags"></div>
|
|
129
61
|
{% endblock %}
|
chellow/templates/macros.html
CHANGED
|
@@ -124,13 +124,23 @@
|
|
|
124
124
|
</div>
|
|
125
125
|
{%- endmacro -%}
|
|
126
126
|
|
|
127
|
-
{%- macro input_checkbox(name, initial) %}
|
|
128
|
-
<input type="checkbox" name="{{ name }}" value="
|
|
127
|
+
{%- macro input_checkbox(name, initial=False, value='true') %}
|
|
128
|
+
<input type="checkbox" name="{{ name }}" value="{{value}}"
|
|
129
129
|
{%- if request.values[name] -%}
|
|
130
|
-
{%- if request.values[name] ==
|
|
130
|
+
{%- if request.values[name] == value %} checked
|
|
131
131
|
{%- endif -%}
|
|
132
132
|
{%- else -%}
|
|
133
|
-
{%- if initial
|
|
133
|
+
{%- if initial %} checked{% endif -%}
|
|
134
|
+
{%- endif -%}>
|
|
135
|
+
{%- endmacro -%}
|
|
136
|
+
|
|
137
|
+
{%- macro input_radio(name, value, initial=False) %}
|
|
138
|
+
<input type="radio" name="{{ name }}" value="{{value}}"
|
|
139
|
+
{%- if request.values[name] -%}
|
|
140
|
+
{%- if request.values[name] == value %} checked
|
|
141
|
+
{%- endif -%}
|
|
142
|
+
{%- else -%}
|
|
143
|
+
{%- if initial %} checked{% endif -%}
|
|
134
144
|
{%- endif -%}>
|
|
135
145
|
{%- endmacro -%}
|
|
136
146
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{% extends "macros.html" %}
|
|
2
|
+
|
|
3
|
+
{% block html %}
|
|
4
|
+
<table class="sticky" id="snags">
|
|
5
|
+
<caption>
|
|
6
|
+
Snags (truncated after 200)
|
|
7
|
+
<a href="/reports/channel_snags?dc_contract_id={{contract.id}}&days_hidden={{days_hidden}}&is_ignored={{is_ignored}}&only_ongoing={{only_ongoing}}&show_settlement={{show_settlement}}&as_csv=true">Download as CSV</a>
|
|
8
|
+
</caption>
|
|
9
|
+
<thead>
|
|
10
|
+
<tr>
|
|
11
|
+
<th>View</th>
|
|
12
|
+
<th>Contract</th>
|
|
13
|
+
<th>Import MPAN Core</th>
|
|
14
|
+
<th>Export MPAN Core</th>
|
|
15
|
+
<th>Site</th>
|
|
16
|
+
<th>Description</th>
|
|
17
|
+
<th>Channels</th>
|
|
18
|
+
<th>Start Date</th>
|
|
19
|
+
<th>Finish Date</th>
|
|
20
|
+
<th>
|
|
21
|
+
<span title="Blank if the snag is ongoing (ie. if the finish date is 'ongoing' or if it finished less than 'Days Hidden' ago).">Days Since Finished</span>
|
|
22
|
+
</th>
|
|
23
|
+
<th>Duration</th>
|
|
24
|
+
<th>Comm</th>
|
|
25
|
+
</tr>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody>
|
|
28
|
+
{% for snag_group in snag_groups %}
|
|
29
|
+
<tr>
|
|
30
|
+
<td>
|
|
31
|
+
<ul>
|
|
32
|
+
{% for snag in snag_group.snags %}
|
|
33
|
+
<li>
|
|
34
|
+
<a href="/e/channel_snags/{{snag.id}}">view</a>
|
|
35
|
+
[<a href="/e/channel_snags/{{snag.id}}/edit">edit</a>]
|
|
36
|
+
{% if snag.is_ignored %} ignored{% endif %}
|
|
37
|
+
</li>
|
|
38
|
+
{% endfor %}
|
|
39
|
+
</ul>
|
|
40
|
+
</td>
|
|
41
|
+
<td>
|
|
42
|
+
<a href="/e/dc_contracts/{{snag_group.contract.id}}">{{snag_group.contract.name}}</a>
|
|
43
|
+
</td>
|
|
44
|
+
<td>
|
|
45
|
+
{% if snag_group.era.imp_mpan_core %}
|
|
46
|
+
<a href="/e/supplies/{{snag_group.supply.id}}">{{snag_group.era.imp_mpan_core}}</a>
|
|
47
|
+
{% endif %}
|
|
48
|
+
</td>
|
|
49
|
+
<td>
|
|
50
|
+
{% if snag_group.era.exp_mpan_core %}
|
|
51
|
+
<a href="/e/supplies/{{snag_group.supply.id}}">{{snag_group.era.exp_mpan_core}}</a>
|
|
52
|
+
{% endif %}
|
|
53
|
+
</td>
|
|
54
|
+
<td>
|
|
55
|
+
<a href="/sites/{{snag_group.site.id}}">{{snag_group.site.code}} {{snag_group.site.name}}</a>
|
|
56
|
+
</td>
|
|
57
|
+
<td>{{snag_group.description}}</td>
|
|
58
|
+
<td>
|
|
59
|
+
<ul>
|
|
60
|
+
{% for snag in snag_group.snags %}
|
|
61
|
+
<li>
|
|
62
|
+
{% if snag.channel.imp_related %}
|
|
63
|
+
Import
|
|
64
|
+
{% else %}
|
|
65
|
+
Export
|
|
66
|
+
{% endif %}
|
|
67
|
+
{{snag.channel.channel_type}}
|
|
68
|
+
</li>
|
|
69
|
+
{% endfor %}
|
|
70
|
+
</ul>
|
|
71
|
+
</td>
|
|
72
|
+
<td>
|
|
73
|
+
{{snag_group.start_date|hh_format}}
|
|
74
|
+
</td>
|
|
75
|
+
<td>
|
|
76
|
+
{{snag_group.finish_date|hh_format}}
|
|
77
|
+
</td>
|
|
78
|
+
<td>
|
|
79
|
+
{% if snag_group.days_since_finished %}
|
|
80
|
+
{{snag_group.days_since_finished}}
|
|
81
|
+
{% endif %}
|
|
82
|
+
</td>
|
|
83
|
+
<td>{{snag_group.duration}}</td>
|
|
84
|
+
<td>
|
|
85
|
+
<a href="/e/comms/{{snag_group.era.comm.id}}" title="{{snag_group.era.comm.description}}">{{snag_group.era.comm.code}}</a>
|
|
86
|
+
</td>
|
|
87
|
+
</tr>
|
|
88
|
+
{% endfor %}
|
|
89
|
+
</tbody>
|
|
90
|
+
</table>
|
|
91
|
+
{% endblock %}
|
chellow/utils.py
CHANGED
|
@@ -29,11 +29,15 @@ def req_str(name):
|
|
|
29
29
|
raise BadRequest(f"The field {name} is required.")
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def
|
|
32
|
+
def req_strs(name):
|
|
33
33
|
try:
|
|
34
|
-
return request.values
|
|
34
|
+
return request.values.getlist(name)
|
|
35
35
|
except KeyError:
|
|
36
|
-
|
|
36
|
+
raise BadRequest(f"The field {name} is required.")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def req_bool(name):
|
|
40
|
+
return name in request.values
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
def req_int(name):
|
|
@@ -43,6 +47,13 @@ def req_int(name):
|
|
|
43
47
|
raise BadRequest(f"Problem parsing the field {name} as an integer: {e}")
|
|
44
48
|
|
|
45
49
|
|
|
50
|
+
def req_ints(name):
|
|
51
|
+
try:
|
|
52
|
+
return [int(v) for v in req_strs(name)]
|
|
53
|
+
except ValueError as e:
|
|
54
|
+
raise BadRequest(f"Problem parsing the field {name} as an integer: {e}")
|
|
55
|
+
|
|
56
|
+
|
|
46
57
|
def req_int_none(name):
|
|
47
58
|
val = req_str(name)
|
|
48
59
|
if val == "":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chellow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1761056531.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)
|
|
@@ -2,7 +2,7 @@ chellow/__init__.py,sha256=9aoSbGmHCIHwzI_c_TLSg5CeKwqAq0I6kKaMvTrTMqg,10936
|
|
|
2
2
|
chellow/api.py,sha256=mk17TfweR76DPFC8lX2SArTjai6y6YshASxqO1w-_-s,11036
|
|
3
3
|
chellow/bank_holidays.py,sha256=T_utYMwe_g1dz5X-aOTdIPryg49SvB7QsWM1yphlqG8,4423
|
|
4
4
|
chellow/commands.py,sha256=ESBe9ZWj1c3vdZgqMZ9gFvYAB3hRag2R1PzOwuw9yFo,1302
|
|
5
|
-
chellow/dloads.py,sha256=
|
|
5
|
+
chellow/dloads.py,sha256=sNAPMe4LeHqfisEubGXvraDsUS0F-ujI3WG0Md8DywM,5565
|
|
6
6
|
chellow/edi_lib.py,sha256=Lq70TUJuogoP5KGrphzUEUfyfgftEclg_iA3mpNAaDI,51324
|
|
7
7
|
chellow/fake_batch_updater.py,sha256=khAmvSUn9qN04w8C92kRg1UeyQvfLztE7QXv9tUz6nE,11611
|
|
8
8
|
chellow/general_import.py,sha256=ghybbden66VT4q5J0vYwiNg-6G2vg71EgCN_x3fvhW0,69200
|
|
@@ -12,7 +12,7 @@ chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
|
|
|
12
12
|
chellow/rate_server.py,sha256=RwJo-AzBIdzxx7PAtboZEUH1nUjAeJckw0bk06-9oyM,5672
|
|
13
13
|
chellow/rrun.py,sha256=sWm_tuJ_6xH3T28TY1w63k1Q44N_S_p_pYF5YCeztqU,2226
|
|
14
14
|
chellow/testing.py,sha256=Dj2c1NX8lVlygueOrh2eyYawLW6qKEHxNhXVVUaNRO0,3637
|
|
15
|
-
chellow/utils.py,sha256=
|
|
15
|
+
chellow/utils.py,sha256=x6yReQkhFaFGnsuhs6PqrEkE1OfZSPrrC7IqstRXKKU,19701
|
|
16
16
|
chellow/views.py,sha256=9IUUbYjqEmQQzbYQB4w-ygCo25gecIxYVbxTXRF-YfY,86078
|
|
17
17
|
chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
18
|
chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
|
|
@@ -35,8 +35,9 @@ chellow/e/hh_parser_schneider_xlsx.py,sha256=Vtq0TNz-oojoKJm4PeH4ZwBp2I-mjArB9-F
|
|
|
35
35
|
chellow/e/hh_parser_simple_csv.py,sha256=lJx9tw9BWFSoBmns1Cws_vY-OIn90LPt2yvIN_CFcTE,2177
|
|
36
36
|
chellow/e/hh_parser_vital_xlsx.py,sha256=g9-CElfH1PPfwpuUcVvD6WQpBlNxCo8j9pq_0Yza0ZM,4125
|
|
37
37
|
chellow/e/lafs.py,sha256=SUUFtvn_IQQTrZue1zefCYgzuscA0FVX2ySZ9u8BDPw,7776
|
|
38
|
-
chellow/e/lcc.py,sha256=
|
|
38
|
+
chellow/e/lcc.py,sha256=VqwKBE6N6wXv_xu0o-1CRtJripoFGCZ8Q8e1hvce_34,4686
|
|
39
39
|
chellow/e/mdd_importer.py,sha256=NugJr2JhuzkPTsEMl_5UdQuw5K2p8lVJ-hyz4MK6Hfg,35762
|
|
40
|
+
chellow/e/rab.py,sha256=8buWWqo7CPzAqenI8zEnKDMVxzXZzQZUFAWY9sdGH3s,2320
|
|
40
41
|
chellow/e/rcrc.py,sha256=92CA1uIotIHd1epQ_jEPdJKzXqDFV-AoJOJeRO6MEyA,4274
|
|
41
42
|
chellow/e/ro.py,sha256=cpeJQMY_6SpVxL1nySSj9we58A6E2KwJEAb6fK7cZKY,626
|
|
42
43
|
chellow/e/scenario.py,sha256=FLgh03r_SgXx0hMWFbAvwsz2ScDL8LUwYWSWVv2rQlg,24973
|
|
@@ -44,7 +45,7 @@ chellow/e/system_price.py,sha256=6w5J7bzwFAZubE2zdOFRiS8IIrVP8hkoIOaG2yCt-Ic,623
|
|
|
44
45
|
chellow/e/tlms.py,sha256=pyL32hPiYd09FbpXVMnBjHsWFEQHs-Az945V7EShGiY,9116
|
|
45
46
|
chellow/e/tnuos.py,sha256=NBmc-f3oezrl4gviAKobljHfICTpBKxxxEGBGJi_lRk,4927
|
|
46
47
|
chellow/e/triad.py,sha256=uQIngSrz8irBXQ0Rp_s8nAUzu-y2Ms7aj4B38_Ff8y8,13720
|
|
47
|
-
chellow/e/views.py,sha256=
|
|
48
|
+
chellow/e/views.py,sha256=7WKLrqYtk018oXjmx9YBv72B5hpgOV0eTJYqsIoBYsE,234251
|
|
48
49
|
chellow/e/bill_parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
50
|
chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=hcbjxqLOe7qkDjS7enCpmfyGwm3d-pq3u5VQIaUmVTw,3796
|
|
50
51
|
chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=yoEGQS0qcrv3TWFfxELIIi8f1CyKcIzh0xVaPoz2w2s,4191
|
|
@@ -85,9 +86,8 @@ chellow/reports/report_183.py,sha256=fGONpKEIXTqIT_3dE5jZKBIesWPgLq-chHO6X22dIv0
|
|
|
85
86
|
chellow/reports/report_187.py,sha256=RCvxDnkfRu7ocKUPEX0qtVphGOBEl9RULy790uteXcQ,9915
|
|
86
87
|
chellow/reports/report_219.py,sha256=3Zs16ka6dWWY_lCDoA-ZFrlPb4vHk1LQoa2yrlTMntA,7117
|
|
87
88
|
chellow/reports/report_231.py,sha256=WARLztV2HzBFSi5_xvY_DTXVyuBBbBYiU0RazfjKw-Y,5270
|
|
88
|
-
chellow/reports/report_233.py,sha256=qJdPFuBgQAWD24BsljgGJ44L_RGdHOA1RqsxGjTWhFc,4975
|
|
89
89
|
chellow/reports/report_241.py,sha256=lfivElRkV_CZAhck0rxAuhqzgponj3aWwmwGMNQvUxg,5343
|
|
90
|
-
chellow/reports/report_247.py,sha256=
|
|
90
|
+
chellow/reports/report_247.py,sha256=pbWfM-fUeuakZxH1Ovlx7-XfUg6SL9t51swK3yMc1lc,43253
|
|
91
91
|
chellow/reports/report_29.py,sha256=ZXnq6Kg5on-IPquUsH4bn46mBVESY_WhwqDWZPXOJwo,2695
|
|
92
92
|
chellow/reports/report_291.py,sha256=BnWtxe0eWN2QKKWpwjs5-RI5LbReBKL119QbkrkNhV8,7478
|
|
93
93
|
chellow/reports/report_33.py,sha256=lt1EN_LNx6u-AgdaS3YRkPMZA33JgMcELolHF4oJUMw,16689
|
|
@@ -100,6 +100,7 @@ chellow/reports/report_87.py,sha256=udzbCuXcckWD-OHmfJCT6bwg_paYhm4vfDWlL8WM-jA,
|
|
|
100
100
|
chellow/reports/report_asset_comparison.py,sha256=Cl2NgvbclqhOVvKuUu3sajTVO2JupMfzK3bV0_K8eNs,6077
|
|
101
101
|
chellow/reports/report_batches.py,sha256=MoCv2dE-JgaJzaMjMA-kZrPkYR13uDoXer5UuF12OYc,4757
|
|
102
102
|
chellow/reports/report_bills.py,sha256=LP7XDxzO0Fp10c8xDE67e4tHTEc7nN74ESQBy762Nx4,3401
|
|
103
|
+
chellow/reports/report_channel_snags.py,sha256=RV5L3zRwFmuZws7w9H9VzLCFlQ6U3-ZU6jn4j5VydNc,8626
|
|
103
104
|
chellow/reports/report_csv_llfcs.py,sha256=mMB06b6Jems5kcQU4H4Le_fyKgVr8THP8BCx3pkvg5E,1903
|
|
104
105
|
chellow/reports/report_csv_site_hh_data.py,sha256=ik0OkGVo1bfTXLdcT3gPUHnxSkSdorzZheP3qgnOR5c,4331
|
|
105
106
|
chellow/reports/report_csv_site_snags.py,sha256=AuAy6vjL0g7vwPPAZhBqxOyITL9_jnyFj012MnUcxxk,2627
|
|
@@ -133,7 +134,7 @@ chellow/templates/home.html,sha256=7xiD6QLju3ugALzMlzTJosRyMUmQGWPK6jDF7oZbnAQ,5
|
|
|
133
134
|
chellow/templates/input_date.html,sha256=rpgB5n0LfN8Y5djN_ZiuSxqdskxzCoKrEqI7hyJkVQo,1248
|
|
134
135
|
chellow/templates/local_report.html,sha256=pV7_0QwyQ-D3OS9LXrly5pq3qprZnwTCoq6vCnMTkS4,1332
|
|
135
136
|
chellow/templates/local_reports.html,sha256=4wbfVkY4wUfSSfWjxqIsvCpIsa9k7H_dGAjznrG5jNM,701
|
|
136
|
-
chellow/templates/macros.html,sha256=
|
|
137
|
+
chellow/templates/macros.html,sha256=FlRTl9W2avRXErnS3vzeOxciGXJYoKptiR08iVmSpfw,5353
|
|
137
138
|
chellow/templates/national_grid.html,sha256=8W92tsjlqPSB0J--nyFIi-wzFae9CyDr6fODXLZp8ic,991
|
|
138
139
|
chellow/templates/non_core_auto_importer.html,sha256=s9SluRN1bHTHjd8GP6uFhk6LrZYG8dqBG3y94zUKe5Q,944
|
|
139
140
|
chellow/templates/non_core_contract.html,sha256=BdGtxErTvw4DwXLb6B2vimuU6ode3fFA-90kBmHCwYc,1754
|
|
@@ -180,7 +181,7 @@ chellow/templates/e/channel_add.html,sha256=szwQJBHx2kAoSFomXDHD0N_7PSd4drqOoAWh
|
|
|
180
181
|
chellow/templates/e/channel_edit.html,sha256=OUkdiS2NBQ_w4gmxRxXAcRToM5BT8DWWJrtQMFs-GUU,2198
|
|
181
182
|
chellow/templates/e/channel_snag.html,sha256=wBJ5KBfeJdAeRmaB0qu0AD9Z4nM5fn6tJ_8bNqTWtoo,1477
|
|
182
183
|
chellow/templates/e/channel_snag_edit.html,sha256=sUFI4Ml3F1B35x8_t_Pz3hWuQN9Xtxr3kt4u8hdxNwY,1911
|
|
183
|
-
chellow/templates/e/channel_snags.html,sha256=
|
|
184
|
+
chellow/templates/e/channel_snags.html,sha256=TgRhS6DcOMyoAowwrCjPtq9iuX6lpvG3uchcd3g80kk,1593
|
|
184
185
|
chellow/templates/e/comm.html,sha256=DSlAaDg1r4KYq9VUgDtt2lgW6apZjZvwhMujIJINmps,383
|
|
185
186
|
chellow/templates/e/comms.html,sha256=bUXZePnMfpKk1E71qLGOSkx8r3GxdPPD_-MosIXXq4s,434
|
|
186
187
|
chellow/templates/e/cop.html,sha256=ULv7ALFJHMUgPX96hQNm2irc3edtKYHS6fYAxvmzj8M,376
|
|
@@ -399,6 +400,7 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
|
|
|
399
400
|
chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
|
|
400
401
|
chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
|
|
401
402
|
chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
|
|
402
|
-
chellow
|
|
403
|
-
chellow-
|
|
404
|
-
chellow-
|
|
403
|
+
chellow/templates/reports/channel_snags.html,sha256=_aAgFgMlTkK2HuKFU8YisAIcUYfg6Hqhgyf5MZpdK8c,2629
|
|
404
|
+
chellow-1761056531.0.0.dist-info/METADATA,sha256=x465BtJg_0nCB84ep2IVjHyEpTTyZZixgcyJ_zKU7fk,12500
|
|
405
|
+
chellow-1761056531.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
406
|
+
chellow-1761056531.0.0.dist-info/RECORD,,
|
chellow/reports/report_233.py
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import csv
|
|
2
|
-
import sys
|
|
3
|
-
import threading
|
|
4
|
-
import traceback
|
|
5
|
-
|
|
6
|
-
from dateutil.relativedelta import relativedelta
|
|
7
|
-
|
|
8
|
-
from flask import g, redirect
|
|
9
|
-
|
|
10
|
-
from sqlalchemy.orm import joinedload
|
|
11
|
-
from sqlalchemy.sql.expression import false, select, true
|
|
12
|
-
|
|
13
|
-
from chellow.dloads import open_file
|
|
14
|
-
from chellow.models import (
|
|
15
|
-
Channel,
|
|
16
|
-
Contract,
|
|
17
|
-
Era,
|
|
18
|
-
Session,
|
|
19
|
-
Site,
|
|
20
|
-
SiteEra,
|
|
21
|
-
Snag,
|
|
22
|
-
Supply,
|
|
23
|
-
User,
|
|
24
|
-
)
|
|
25
|
-
from chellow.utils import (
|
|
26
|
-
csv_make_val,
|
|
27
|
-
hh_before,
|
|
28
|
-
req_bool,
|
|
29
|
-
req_int,
|
|
30
|
-
req_int_none,
|
|
31
|
-
utc_datetime_now,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def content(contract_id, days_hidden, is_ignored, user_id):
|
|
36
|
-
f = writer = None
|
|
37
|
-
try:
|
|
38
|
-
with Session() as sess:
|
|
39
|
-
user = User.get_by_id(sess, user_id)
|
|
40
|
-
if contract_id is None:
|
|
41
|
-
contract = None
|
|
42
|
-
namef = "all"
|
|
43
|
-
else:
|
|
44
|
-
contract = Contract.get_dc_by_id(sess, contract_id)
|
|
45
|
-
namef = "".join(x if x.isalnum() else "_" for x in contract.name)
|
|
46
|
-
|
|
47
|
-
f = open_file(f"channel_snags_{namef}.csv", user, mode="w", newline="")
|
|
48
|
-
writer = csv.writer(f, lineterminator="\n")
|
|
49
|
-
titles = (
|
|
50
|
-
"contract",
|
|
51
|
-
"Hidden Days",
|
|
52
|
-
"Chellow Id",
|
|
53
|
-
"Imp MPAN Core",
|
|
54
|
-
"Exp MPAN Core",
|
|
55
|
-
"Site Code",
|
|
56
|
-
"Site Name",
|
|
57
|
-
"Snag Description",
|
|
58
|
-
"Import Related?",
|
|
59
|
-
"Channel Type",
|
|
60
|
-
"Start Date",
|
|
61
|
-
"Finish Date",
|
|
62
|
-
"Is Ignored?",
|
|
63
|
-
"Days Since Snag Finished",
|
|
64
|
-
"Duration Of Snag (Days)",
|
|
65
|
-
)
|
|
66
|
-
writer.writerow(titles)
|
|
67
|
-
|
|
68
|
-
now = utc_datetime_now()
|
|
69
|
-
cutoff_date = now - relativedelta(days=days_hidden)
|
|
70
|
-
q = (
|
|
71
|
-
select(Snag, Channel, Era, Supply, SiteEra, Site)
|
|
72
|
-
.join(Channel, Snag.channel_id == Channel.id)
|
|
73
|
-
.join(Era, Channel.era_id == Era.id)
|
|
74
|
-
.join(Supply, Era.supply_id == Supply.id)
|
|
75
|
-
.join(SiteEra, Era.site_eras)
|
|
76
|
-
.join(Site, SiteEra.site_id == Site.id)
|
|
77
|
-
.where(
|
|
78
|
-
SiteEra.is_physical == true(),
|
|
79
|
-
Snag.start_date < cutoff_date,
|
|
80
|
-
)
|
|
81
|
-
.order_by(
|
|
82
|
-
Site.code,
|
|
83
|
-
Supply.id,
|
|
84
|
-
Channel.imp_related,
|
|
85
|
-
Channel.channel_type,
|
|
86
|
-
Snag.description,
|
|
87
|
-
Snag.start_date,
|
|
88
|
-
Snag.id,
|
|
89
|
-
)
|
|
90
|
-
.options(joinedload(Era.dc_contract))
|
|
91
|
-
)
|
|
92
|
-
if contract is not None:
|
|
93
|
-
q = q.where(Era.dc_contract == contract)
|
|
94
|
-
|
|
95
|
-
if not is_ignored:
|
|
96
|
-
q = q.where(Snag.is_ignored == false())
|
|
97
|
-
|
|
98
|
-
for snag, channel, era, supply, site_era, site in sess.execute(q):
|
|
99
|
-
snag_start = snag.start_date
|
|
100
|
-
snag_finish = snag.finish_date
|
|
101
|
-
imp_mc = "" if era.imp_mpan_core is None else era.imp_mpan_core
|
|
102
|
-
exp_mc = "" if era.exp_mpan_core is None else era.exp_mpan_core
|
|
103
|
-
|
|
104
|
-
if snag_finish is None:
|
|
105
|
-
duration = now - snag_start
|
|
106
|
-
age_of_snag = None
|
|
107
|
-
else:
|
|
108
|
-
duration = snag_finish - snag_start
|
|
109
|
-
if hh_before(cutoff_date, snag_finish):
|
|
110
|
-
age_of_snag = None
|
|
111
|
-
else:
|
|
112
|
-
delta = now - snag_finish
|
|
113
|
-
age_of_snag = delta.days
|
|
114
|
-
|
|
115
|
-
vals = {
|
|
116
|
-
"contract": era.dc_contract.name,
|
|
117
|
-
"Hidden Days": days_hidden,
|
|
118
|
-
"Chellow Id": snag.id,
|
|
119
|
-
"Imp MPAN Core": imp_mc,
|
|
120
|
-
"Exp MPAN Core": exp_mc,
|
|
121
|
-
"Site Code": site.code,
|
|
122
|
-
"Site Name": site.name,
|
|
123
|
-
"Snag Description": snag.description,
|
|
124
|
-
"Import Related?": channel.imp_related,
|
|
125
|
-
"Channel Type": channel.channel_type,
|
|
126
|
-
"Start Date": snag_start,
|
|
127
|
-
"Finish Date": snag_finish,
|
|
128
|
-
"Is Ignored?": snag.is_ignored,
|
|
129
|
-
"Days Since Snag Finished": age_of_snag,
|
|
130
|
-
"Duration Of Snag (Days)": duration.days,
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
writer.writerow(csv_make_val(vals[t]) for t in titles)
|
|
134
|
-
except BaseException:
|
|
135
|
-
msg = traceback.format_exc()
|
|
136
|
-
sys.stderr.write(msg)
|
|
137
|
-
writer.writerow([msg])
|
|
138
|
-
finally:
|
|
139
|
-
if f is not None:
|
|
140
|
-
f.close()
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
def do_get(sess):
|
|
144
|
-
contract_id = req_int_none("dc_contract_id")
|
|
145
|
-
days_hidden = req_int("days_hidden")
|
|
146
|
-
is_ignored = req_bool("is_ignored")
|
|
147
|
-
|
|
148
|
-
args = contract_id, days_hidden, is_ignored, g.user.id
|
|
149
|
-
threading.Thread(target=content, args=args).start()
|
|
150
|
-
return redirect("/downloads", 303)
|
|
File without changes
|