chellow 1722002880.0.0__py3-none-any.whl → 1723041465.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of chellow might be problematic. Click here for more details.
- chellow/e/bill_parsers/edf_export_xlsx.py +217 -0
- chellow/e/bill_parsers/mm.py +6 -1
- chellow/views.py +1 -1
- {chellow-1722002880.0.0.dist-info → chellow-1723041465.0.0.dist-info}/METADATA +1 -1
- {chellow-1722002880.0.0.dist-info → chellow-1723041465.0.0.dist-info}/RECORD +6 -5
- {chellow-1722002880.0.0.dist-info → chellow-1723041465.0.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from datetime import datetime as Datetime
|
|
2
|
+
from decimal import Decimal, InvalidOperation
|
|
3
|
+
|
|
4
|
+
from dateutil.relativedelta import relativedelta
|
|
5
|
+
|
|
6
|
+
from openpyxl import load_workbook
|
|
7
|
+
|
|
8
|
+
from werkzeug.exceptions import BadRequest
|
|
9
|
+
|
|
10
|
+
from chellow.utils import HH, ct_datetime, parse_mpan_core, to_ct, to_utc
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_cell(sheet, col, row):
|
|
14
|
+
try:
|
|
15
|
+
coordinates = f"{col}{row}"
|
|
16
|
+
return sheet[coordinates]
|
|
17
|
+
except IndexError:
|
|
18
|
+
raise BadRequest(f"Can't find the cell {coordinates} on sheet {sheet}.")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_date(sheet, col, row):
|
|
22
|
+
cell = get_cell(sheet, col, row)
|
|
23
|
+
val = cell.value
|
|
24
|
+
if not isinstance(val, Datetime):
|
|
25
|
+
raise BadRequest(
|
|
26
|
+
f"Problem reading {val} (of type {type(val)}) as a timestamp at "
|
|
27
|
+
f"{cell.coordinate}."
|
|
28
|
+
)
|
|
29
|
+
return val
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_str(sheet, col, row):
|
|
33
|
+
return get_cell(sheet, col, row).value.strip()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_dec(sheet, col, row):
|
|
37
|
+
cell = get_cell(sheet, col, row)
|
|
38
|
+
try:
|
|
39
|
+
return Decimal(str(cell.value))
|
|
40
|
+
except InvalidOperation as e:
|
|
41
|
+
raise BadRequest(f"Problem parsing the number at {cell.coordinate}. {e}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_int(sheet, col, row):
|
|
45
|
+
return int(get_cell(sheet, col, row).value)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
ELEM_LOOKUP = {
|
|
49
|
+
"Capacity": {
|
|
50
|
+
"name": "duos-availability",
|
|
51
|
+
"gbp": "duos-availability-gbp",
|
|
52
|
+
"units": "duos-availability-kva",
|
|
53
|
+
"rate": "duos-availability-rate",
|
|
54
|
+
},
|
|
55
|
+
"Fixed Charge": {
|
|
56
|
+
"name": "duos-fixed",
|
|
57
|
+
"gbp": "duos-fixed-gbp",
|
|
58
|
+
"units": "duos-fixed-days",
|
|
59
|
+
"rate": "duos-fixed-rate",
|
|
60
|
+
},
|
|
61
|
+
"Unit Rate Zero": None,
|
|
62
|
+
"Excess Reactive Power": {
|
|
63
|
+
"name": "duos-reactive",
|
|
64
|
+
"gbp": "duos-reactive-gbp",
|
|
65
|
+
"units": "duos-reactive-kvarh",
|
|
66
|
+
"rate": "duos-reactive-gbp-per-kvarh",
|
|
67
|
+
},
|
|
68
|
+
"Unit Rate Amber": {
|
|
69
|
+
"name": "duos-amber",
|
|
70
|
+
"gbp": "duos-amber-gbp",
|
|
71
|
+
"units": "duos-amber-kwh",
|
|
72
|
+
"rate": "duos-amber-gbp-per-kwh",
|
|
73
|
+
},
|
|
74
|
+
"Unit Rate Green": {
|
|
75
|
+
"name": "duos-green",
|
|
76
|
+
"gbp": "duos-green-gbp",
|
|
77
|
+
"units": "duos-green-kwh",
|
|
78
|
+
"rate": "duos-green-gbp-per-kwh",
|
|
79
|
+
},
|
|
80
|
+
"Unit Rate Red": {
|
|
81
|
+
"name": "duos-red",
|
|
82
|
+
"gbp": "duos-red-gbp",
|
|
83
|
+
"units": "duos-red-kwh",
|
|
84
|
+
"rate": "duos-red-gbp-per-kwh",
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _make_raw_bills(book):
|
|
90
|
+
bills = []
|
|
91
|
+
sheet = book.worksheets[0]
|
|
92
|
+
issue_date_raw = get_date(sheet, "H", 24)
|
|
93
|
+
issue_date = to_utc(
|
|
94
|
+
ct_datetime(issue_date_raw.year, issue_date_raw.month, issue_date_raw.day)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
mpan_core = parse_mpan_core(str(get_int(sheet, "D", 25)))
|
|
98
|
+
start_date_str = get_str(sheet, "D", 22)
|
|
99
|
+
start_date_ct = to_ct(Datetime.strptime(start_date_str, "%d-%b-%Y"))
|
|
100
|
+
start_date = to_utc(start_date_ct)
|
|
101
|
+
finish_date_str = get_str(sheet, "F", 22)
|
|
102
|
+
finish_date_ct = to_ct(Datetime.strptime(finish_date_str, "%d-%b-%Y"))
|
|
103
|
+
finish_date = to_utc(finish_date_ct + relativedelta(hours=23, minutes=30))
|
|
104
|
+
net = round(get_dec(sheet, "H", 33), 2)
|
|
105
|
+
kwh = get_dec(sheet, "D", 33)
|
|
106
|
+
|
|
107
|
+
breakdown = {
|
|
108
|
+
"ssp-kwh": kwh,
|
|
109
|
+
"ssp-gbp": net,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
bills.append(
|
|
113
|
+
{
|
|
114
|
+
"bill_type_code": "N",
|
|
115
|
+
"kwh": kwh,
|
|
116
|
+
"vat": Decimal("0.00"),
|
|
117
|
+
"net": net,
|
|
118
|
+
"gross": net,
|
|
119
|
+
"reads": [],
|
|
120
|
+
"breakdown": breakdown,
|
|
121
|
+
"account": mpan_core,
|
|
122
|
+
"issue_date": issue_date,
|
|
123
|
+
"start_date": start_date,
|
|
124
|
+
"finish_date": finish_date,
|
|
125
|
+
"mpan_core": mpan_core,
|
|
126
|
+
"reference": "_".join(
|
|
127
|
+
(
|
|
128
|
+
to_ct(start_date).strftime("%Y%m%d"),
|
|
129
|
+
to_ct(finish_date).strftime("%Y%m%d"),
|
|
130
|
+
to_ct(issue_date).strftime("%Y%m%d"),
|
|
131
|
+
mpan_core,
|
|
132
|
+
"ssp",
|
|
133
|
+
)
|
|
134
|
+
),
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
sheet = book.worksheets[3]
|
|
138
|
+
for row in range(2, len(sheet["A"]) + 1):
|
|
139
|
+
val = get_cell(sheet, "A", row).value
|
|
140
|
+
if val is None or val == "":
|
|
141
|
+
break
|
|
142
|
+
|
|
143
|
+
start_date_str = get_str(sheet, "B", row)
|
|
144
|
+
start_date_ct = to_ct(Datetime.strptime(start_date_str, "%Y-%m"))
|
|
145
|
+
start_date = to_utc(start_date_ct)
|
|
146
|
+
finish_date = to_utc(start_date_ct + relativedelta(months=1) - HH)
|
|
147
|
+
|
|
148
|
+
element_desc = get_str(sheet, "D", row).strip()
|
|
149
|
+
units = get_dec(sheet, "E", row)
|
|
150
|
+
rate = get_dec(sheet, "F", row)
|
|
151
|
+
net = round(get_dec(sheet, "G", row), 2)
|
|
152
|
+
|
|
153
|
+
titles = ELEM_LOOKUP[element_desc]
|
|
154
|
+
if titles is None:
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
breakdown = {
|
|
158
|
+
titles["gbp"]: net,
|
|
159
|
+
titles["units"]: units,
|
|
160
|
+
titles["rate"]: [rate],
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
bills.append(
|
|
164
|
+
{
|
|
165
|
+
"bill_type_code": "N",
|
|
166
|
+
"kwh": Decimal(0),
|
|
167
|
+
"vat": Decimal("0.00"),
|
|
168
|
+
"net": net,
|
|
169
|
+
"gross": net,
|
|
170
|
+
"reads": [],
|
|
171
|
+
"breakdown": breakdown,
|
|
172
|
+
"account": mpan_core,
|
|
173
|
+
"issue_date": issue_date,
|
|
174
|
+
"start_date": start_date,
|
|
175
|
+
"finish_date": finish_date,
|
|
176
|
+
"mpan_core": mpan_core,
|
|
177
|
+
"reference": "_".join(
|
|
178
|
+
(
|
|
179
|
+
to_ct(start_date).strftime("%Y%m%d"),
|
|
180
|
+
to_ct(finish_date).strftime("%Y%m%d"),
|
|
181
|
+
to_ct(issue_date).strftime("%Y%m%d"),
|
|
182
|
+
mpan_core,
|
|
183
|
+
titles["name"],
|
|
184
|
+
)
|
|
185
|
+
),
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
return bills
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Parser:
|
|
192
|
+
def __init__(self, f):
|
|
193
|
+
self.book = load_workbook(f, data_only=True)
|
|
194
|
+
|
|
195
|
+
self.last_line = None
|
|
196
|
+
self._line_number = None
|
|
197
|
+
self._title_line = None
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def line_number(self):
|
|
201
|
+
return None if self._line_number is None else self._line_number + 1
|
|
202
|
+
|
|
203
|
+
def _set_last_line(self, i, line):
|
|
204
|
+
self._line_number = i
|
|
205
|
+
self.last_line = line
|
|
206
|
+
if i == 0:
|
|
207
|
+
self._title_line = line
|
|
208
|
+
return line
|
|
209
|
+
|
|
210
|
+
def make_raw_bills(self):
|
|
211
|
+
row = bills = None
|
|
212
|
+
try:
|
|
213
|
+
bills = _make_raw_bills(self.book)
|
|
214
|
+
except BadRequest as e:
|
|
215
|
+
raise BadRequest(f"Row number: {row} {e.description}")
|
|
216
|
+
|
|
217
|
+
return bills
|
chellow/e/bill_parsers/mm.py
CHANGED
|
@@ -80,6 +80,11 @@ CHARGE_UNITS_LOOKUP = {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
ELEMENT_LOOKUP = {
|
|
83
|
+
"1ANNUAL": "duos-red",
|
|
84
|
+
"2ANNUAL": "duos-amber",
|
|
85
|
+
"3ANNUAL": "duos-green",
|
|
86
|
+
"7ANNUAL": "duos-fixed",
|
|
87
|
+
"9ANNUAL": "duos-reactive",
|
|
83
88
|
"10ANNUAL": "standing",
|
|
84
89
|
"20RS0108": "single",
|
|
85
90
|
"30ANNUAL": "mop",
|
|
@@ -119,7 +124,7 @@ def _handle_0460(headers, pre_record, record):
|
|
|
119
124
|
gbp = Decimal(parts["gbp"]) / 100
|
|
120
125
|
quantity = Decimal(parts["quantity"])
|
|
121
126
|
rate = Decimal(parts["rate"])
|
|
122
|
-
element_name = ELEMENT_LOOKUP[parts["code"]]
|
|
127
|
+
element_name = ELEMENT_LOOKUP[parts["code"].strip()]
|
|
123
128
|
breakdown = headers["breakdown"]
|
|
124
129
|
breakdown[f"{element_name}-{units}"] += quantity
|
|
125
130
|
rate_name = f"{element_name}-rate"
|
chellow/views.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: chellow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1723041465.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)
|
|
@@ -11,7 +11,7 @@ chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
|
|
|
11
11
|
chellow/rate_server.py,sha256=fg-Pf_9Hk3bXmC9riPQNGQxBvLvBa_WtNYdwDCjnCSg,5678
|
|
12
12
|
chellow/testing.py,sha256=Od4HHH6pZrhJ_De118_F55RJEKmAvhUH2S24QE9qFQk,3635
|
|
13
13
|
chellow/utils.py,sha256=32qPWEGzCPKPhSM7ztpzcR6ZG74sVZanScDIdK50Rq4,19308
|
|
14
|
-
chellow/views.py,sha256=
|
|
14
|
+
chellow/views.py,sha256=s_pKNpBkiegxevAWEjowJKAtUPXpowOTbXI5473em4Y,79597
|
|
15
15
|
chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
|
|
17
17
|
chellow/e/bill_importer.py,sha256=7UcnqNlKbJc2GhW9gy8sDp9GuqambJVpZLvbafOZztA,7411
|
|
@@ -44,6 +44,7 @@ chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=UgWXDPzQkQghyj_lfgBqoSJ
|
|
|
44
44
|
chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=-HMoIfa_utXYKA44RuC0Xqv3vd2HLeQU_4P0iBUd3WA,4219
|
|
45
45
|
chellow/e/bill_parsers/bgb_edi.py,sha256=GuwHeYbAGk7BVg5n19FcTANFDyKI-y0z3f9niQaPSSw,4828
|
|
46
46
|
chellow/e/bill_parsers/csv.py,sha256=U5zcIaZ6B5QTTpFDAcBnk4G2r8B3j5kJhDPL4AJNkEk,5640
|
|
47
|
+
chellow/e/bill_parsers/edf_export_xlsx.py,sha256=t-M9-dGNWXu3VDI1DbS5Ez1oHW33oopJryNgMTvTjys,6307
|
|
47
48
|
chellow/e/bill_parsers/engie_edi.py,sha256=CTobTskDjzdcqqf_qk2ukDSaTLrVpGZMM0sYlwehog4,14985
|
|
48
49
|
chellow/e/bill_parsers/engie_xls.py,sha256=jrut2heH_ZWmSjcn7celOydZS9Y49GfpYjDk_EKwamI,14453
|
|
49
50
|
chellow/e/bill_parsers/engie_xlsx.py,sha256=4Hu3ls1uNMH7vjDHgcP6QARlGlvb616CqG3xZVjAKWo,16888
|
|
@@ -51,7 +52,7 @@ chellow/e/bill_parsers/gdf_csv.py,sha256=ZfK3Oc6oP28p_P9DIevLNB_zW2WLcEJ3Lvb1gL3
|
|
|
51
52
|
chellow/e/bill_parsers/haven_csv.py,sha256=0uENq8IgVNqdxfBQMBxLTSZWCOuDHXZC0xzk52SbfyE,13652
|
|
52
53
|
chellow/e/bill_parsers/haven_edi.py,sha256=YGPHRxPOhje9s32jqPHHELni2tooOYj3cMC_qaZVPq4,16107
|
|
53
54
|
chellow/e/bill_parsers/haven_edi_tprs.py,sha256=ZVX9CCqUybsot_Z0BEOJPvl9x5kSr7fEWyuJXvZDcz4,11841
|
|
54
|
-
chellow/e/bill_parsers/mm.py,sha256=
|
|
55
|
+
chellow/e/bill_parsers/mm.py,sha256=KhAwF8o3cdabTBmc2pbZgm9MlkAachwNsy4bsivTSrM,9459
|
|
55
56
|
chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py,sha256=yogXTuQHGRL7IiqvRWr2C9V24ez1j9Yx0128UygPE_k,4723
|
|
56
57
|
chellow/e/bill_parsers/settlement_dc_stark_xlsx.py,sha256=PlEqCZuJ9DfQXeeYQ64jtf3ML7sUt_tt61QOOTnkE5c,6380
|
|
57
58
|
chellow/e/bill_parsers/sse_edi.py,sha256=L85DOfNkqexeEIEr8pCBn_2sHJI-zEaw6cogpE3YyYM,15204
|
|
@@ -364,6 +365,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
|
|
|
364
365
|
chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
|
|
365
366
|
chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
|
|
366
367
|
chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
|
|
367
|
-
chellow-
|
|
368
|
-
chellow-
|
|
369
|
-
chellow-
|
|
368
|
+
chellow-1723041465.0.0.dist-info/METADATA,sha256=97E2o-6rhdaB00zicHeZC1x2945uPxYqRtm-K1m1uLo,12241
|
|
369
|
+
chellow-1723041465.0.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
370
|
+
chellow-1723041465.0.0.dist-info/RECORD,,
|
|
File without changes
|