chellow 1750675713.0.0__py3-none-any.whl → 1751459327.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/drax_edi.py +210 -225
- chellow/e/bill_parsers/drax_element_edi.py +459 -0
- chellow/e/views.py +72 -51
- chellow/gas/bill_parser_bgs_xlsx.py +41 -56
- chellow/general_import.py +72 -0
- chellow/templates/g/bill_import.html +4 -4
- chellow/templates/general_imports.html +18 -0
- chellow/views.py +3 -1
- {chellow-1750675713.0.0.dist-info → chellow-1751459327.0.0.dist-info}/METADATA +2 -2
- {chellow-1750675713.0.0.dist-info → chellow-1751459327.0.0.dist-info}/RECORD +11 -10
- {chellow-1750675713.0.0.dist-info → chellow-1751459327.0.0.dist-info}/WHEEL +0 -0
|
@@ -4,15 +4,8 @@ from decimal import Decimal
|
|
|
4
4
|
|
|
5
5
|
from werkzeug.exceptions import BadRequest
|
|
6
6
|
|
|
7
|
-
from chellow.edi_lib import
|
|
8
|
-
|
|
9
|
-
parse_edi,
|
|
10
|
-
to_date,
|
|
11
|
-
to_decimal,
|
|
12
|
-
to_finish_date,
|
|
13
|
-
to_utc,
|
|
14
|
-
)
|
|
15
|
-
from chellow.utils import HH
|
|
7
|
+
from chellow.edi_lib import parse_edi, to_date, to_decimal, to_finish_date
|
|
8
|
+
from chellow.utils import HH, parse_mpan_core
|
|
16
9
|
|
|
17
10
|
|
|
18
11
|
read_type_map = {
|
|
@@ -28,127 +21,136 @@ read_type_map = {
|
|
|
28
21
|
"12": "IF",
|
|
29
22
|
}
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
ELEMENT_MAP = {
|
|
25
|
+
"AAH": {
|
|
26
|
+
"AAHEDC": {
|
|
27
|
+
"139039": ("aahedc-gbp", "aahedc-rate", "aahedc-kwh"),
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
"ADH": {
|
|
31
|
+
"ADHOC": {
|
|
32
|
+
"020330": ("eii-gbp", None, None),
|
|
33
|
+
"637050": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
"BUS": {
|
|
37
|
+
"BSUOS": {
|
|
38
|
+
"269100": ("bsuos-gbp", "bsuos-rate", "bsuos-kwh"),
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
"CCL": {
|
|
42
|
+
"CCL": {
|
|
43
|
+
"422733": ("ccl-gbp", "ccl-rate", "ccl-kwh"),
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
"CFD": {
|
|
47
|
+
"CFD001": {
|
|
48
|
+
"273237": (
|
|
49
|
+
"cfd-operational-gbp",
|
|
50
|
+
"cfd-operational-rate",
|
|
51
|
+
"cfd-operational-kwh",
|
|
52
|
+
),
|
|
53
|
+
"954379": ("cfd-interim-gbp", "cfd-interim-rate", "cfd-interim-kwh"),
|
|
54
|
+
"538249": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
55
|
+
"568307": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
"DCA": {
|
|
59
|
+
"DCDA": {
|
|
60
|
+
"095469": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
"DUS": {
|
|
64
|
+
"DUS001": {
|
|
65
|
+
"794486": (
|
|
66
|
+
"duos-availability-gbp",
|
|
67
|
+
"duos-availability-rate",
|
|
68
|
+
"duos-availability-kva",
|
|
69
|
+
),
|
|
70
|
+
"644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
71
|
+
"797790": (
|
|
72
|
+
"duos-reactive-gbp",
|
|
73
|
+
"duos-reactive-rate",
|
|
74
|
+
"duos-reactive-kvarh",
|
|
75
|
+
),
|
|
76
|
+
"806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
77
|
+
"716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
78
|
+
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
79
|
+
"709522": (
|
|
80
|
+
"duos-excess-availability-gbp",
|
|
81
|
+
"duos-excess-availability-rate",
|
|
82
|
+
"duos-excess-availability-kva",
|
|
83
|
+
),
|
|
84
|
+
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
85
|
+
},
|
|
86
|
+
"DUS002": {
|
|
87
|
+
"797790": (
|
|
88
|
+
"duos-reactive-gbp",
|
|
89
|
+
"duos-reactive-rate",
|
|
90
|
+
"duos-reactive-kvarh",
|
|
91
|
+
),
|
|
92
|
+
"806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
93
|
+
"716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
94
|
+
"709522": (
|
|
95
|
+
"duos-excess-availability-gbp",
|
|
96
|
+
"duos-excess-availability-rate",
|
|
97
|
+
"duos-excess-availability-kva",
|
|
98
|
+
),
|
|
99
|
+
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
100
|
+
"644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
101
|
+
"794486": (
|
|
102
|
+
"duos-availability-gbp",
|
|
103
|
+
"duos-availability-rate",
|
|
104
|
+
"duos-availability-kva",
|
|
105
|
+
),
|
|
106
|
+
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
107
|
+
},
|
|
108
|
+
"DUSDIS": {
|
|
109
|
+
"122568": ("nrg-gsp-losses-gbp", "nrg-rate", "nrg-gsp-losses-kwh"),
|
|
110
|
+
},
|
|
111
|
+
"DUSTRN": {
|
|
112
|
+
"122568": ("nrg-nbp-losses-gbp", "nrg-rate", "nrg-bp-losses-kwh"),
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
"ELX": {
|
|
116
|
+
"ELEXON": {
|
|
117
|
+
"489920": ("elexon-gbp", "elexon-rate", "elexon-nbp-kwh"),
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
"FIT": {
|
|
121
|
+
"FIT_LV": {
|
|
122
|
+
"704107": ("fit-gbp", "fit-rate", "fit-kwh"),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
"NRG": {
|
|
126
|
+
"HH0002": {
|
|
127
|
+
"033667": ("management-gbp", "management-rate", "management-kwh"),
|
|
128
|
+
"091890": ("shape-gbp", "shape-rate", "shape-kwh"),
|
|
129
|
+
"122568": ("nrg-msp-gbp", "nrg-rate", "nrg-msp-kwh"),
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
"REN": {
|
|
133
|
+
"REN001": {
|
|
134
|
+
"229128": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
135
|
+
},
|
|
136
|
+
"REN002": {
|
|
137
|
+
"019090": ("rego-gbp", "rego-rate", "rego-kwh"),
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
"TUS": {
|
|
141
|
+
"TNUOS": {
|
|
142
|
+
"012069": ("tnuos-gbp", "tnuos-rate", None),
|
|
143
|
+
},
|
|
144
|
+
},
|
|
34
145
|
"064305": ("fit-gbp", None, None),
|
|
35
146
|
"590346": ("cfd-operational-gbp", None, None),
|
|
36
|
-
"269100": ("bsuos-gbp", "bsuos-rate", "bsuos-kwh"),
|
|
37
|
-
"422733": ("ccl-gbp", "ccl-rate", "ccl-kwh"),
|
|
38
|
-
"273237": ("cfd-operational-gbp", "cfd-operational-rate", "cfd-operational-kwh"),
|
|
39
|
-
"954379": ("cfd-interim-gbp", "cfd-interim-rate", "cfd-interim-kwh"),
|
|
40
|
-
"538249": ("capaity-gbp", None, None),
|
|
41
|
-
"568307": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
42
147
|
"439724": ("eii-gbp", None, None),
|
|
43
148
|
"247610": ("eii-gbp", None, None),
|
|
44
149
|
"930504": ("eii-gbp", None, None),
|
|
45
150
|
"331201": ("eii-gbp", None, None),
|
|
46
151
|
"307253": ("eii-gbp", "eii-rate", "eii-kwh"),
|
|
47
152
|
"065950": ("eii-gbp", "eii-rate", "eii-kwh"),
|
|
48
|
-
"095469": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
49
|
-
"489920": ("elexon-gbp", "elexon-rate", "elexon-nbp-kwh"),
|
|
50
|
-
"704107": ("fit-gbp", None, None),
|
|
51
|
-
"019090": ("rego-gbp", "rego-rate", "rego-kwh"),
|
|
52
|
-
"033667": ("management-gbp", "management-rate", "management-kwh"),
|
|
53
|
-
"091890": ("shape-gbp", "shape-rate", "shape-kwh"),
|
|
54
|
-
"122568": ("nrg-msp-gbp", "nrg-rate", "nrg-msp-kwh"),
|
|
55
|
-
"716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
56
|
-
"769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
57
|
-
"794486": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
58
|
-
"797790": ("duos-reactive-gbp", "duos-reactive-rate", "duos-reactive-kvarh"),
|
|
59
|
-
"709522": (
|
|
60
|
-
"duos-excess-availability-gbp",
|
|
61
|
-
"duos-excess-availability-rate",
|
|
62
|
-
"duos-excess-availability-kva",
|
|
63
|
-
),
|
|
64
|
-
"644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
65
|
-
"806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
66
|
-
"209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
67
|
-
"229128": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
68
|
-
"012069": ("tnuos-gbp", None, None),
|
|
69
153
|
}
|
|
70
|
-
"""
|
|
71
|
-
"140114": ("reconciliation-gbp", None, None),
|
|
72
|
-
"255204": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
73
|
-
"345065": ("op-weekend-gbp", "op-weekend-rate", "op-weekend-kwh"),
|
|
74
|
-
"350293": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
75
|
-
"425779": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
76
|
-
"534342": ("reconciliation-gbp", None, None),
|
|
77
|
-
"583174": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
78
|
-
"584867": ("aahedc-gbp", "aahedc-rate", "aahedc-kwh"),
|
|
79
|
-
"946827": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
80
|
-
"989534": ("bsuos-gbp", "bsuos-rate", "bsuos-kwh"),
|
|
81
|
-
"117220": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
82
|
-
"579387": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
83
|
-
"558147": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
|
|
84
|
-
"030025": ("ccl-gbp", "ccl-rate", "ccl-kwh"),
|
|
85
|
-
"066540": ("ccl-gbp", "ccl-rate", "ccl-kwh"),
|
|
86
|
-
"154164": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
87
|
-
"281170": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
88
|
-
"342094": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
89
|
-
"378809": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
90
|
-
"574015": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
91
|
-
"810016": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
92
|
-
"839829": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
93
|
-
"649282": ("cfd-fit-gbp", "cfd-fit-rate", "cfd-fit-kwh"),
|
|
94
|
-
"068476": ("day-gbp", "day-rate", "day-kwh"),
|
|
95
|
-
"133186": ("day-gbp", "day-rate", "day-kwh"),
|
|
96
|
-
"400434": ("day-gbp", "day-rate", "day-kwh"),
|
|
97
|
-
"219182": (
|
|
98
|
-
"duos-availability-gbp",
|
|
99
|
-
"duos-availability-rate",
|
|
100
|
-
"duos-availability-kva",
|
|
101
|
-
),
|
|
102
|
-
"144424": (
|
|
103
|
-
"duos-excess-availability-gbp",
|
|
104
|
-
"duos-excess-availability-rate",
|
|
105
|
-
"duos-excess-availability-kva",
|
|
106
|
-
),
|
|
107
|
-
"301541": ("duos-fixed-gbp", None, None),
|
|
108
|
-
"099335": ("duos-fixed-gbp", None, None),
|
|
109
|
-
"873562": ("duos-fixed-gbp", None, None),
|
|
110
|
-
"986159": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
111
|
-
"838286": ("duos-reactive-gbp", "duos-reactive-rate", "duos-reactive-kvarh"),
|
|
112
|
-
"242643": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
113
|
-
"257304": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
114
|
-
"661440": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
|
|
115
|
-
"257305": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
116
|
-
"661441": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
|
|
117
|
-
"257303": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
118
|
-
"661439": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
|
|
119
|
-
"504364": ("ebrs-gbp", None, "ebrs-kwh"),
|
|
120
|
-
"563023": ("ebrs-gbp", None, "ebrs-kwh"),
|
|
121
|
-
"823408": ("ebrs-gbp", None, "ebrs-kwh"),
|
|
122
|
-
"871593": ("ebrs-gbp", "ebrs-rate", "ebrs-kwh"),
|
|
123
|
-
"873894": ("ebrs-gbp", "ebrs-rate", "ebrs-kwh"),
|
|
124
|
-
"309707": ("fit-gbp", "fit-rate", "fit-kwh"),
|
|
125
|
-
"310129": ("meter-rental-gbp", None, None),
|
|
126
|
-
"452415": ("meter-rental-gbp", None, None),
|
|
127
|
-
"371265": ("meter-rental-gbp", None, None),
|
|
128
|
-
"544936": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
|
|
129
|
-
"265091": ("night-gbp", "night-rate", "night-kwh"),
|
|
130
|
-
"483457": ("peak-gbp", "peak-rate", "peak-kwh"),
|
|
131
|
-
"975901": ("peak-shoulder-gbp", "peak-shoulder-rate", "peak-shoulder-kwh"),
|
|
132
|
-
"994483": ("reconciliation-gbp", None, None),
|
|
133
|
-
"637176": ("reconciliation-gbp", None, None),
|
|
134
|
-
"913821": ("reconciliation-gbp", None, None),
|
|
135
|
-
"307660": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
136
|
-
"364252": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
137
|
-
"378246": ("ro-gbp", "ro-rate", "ro-kwh"),
|
|
138
|
-
"708848": ("ro-gbp", None, None),
|
|
139
|
-
"632209": ("summer-night-gbp", "summer-night-rate", "summer-night-kwh"),
|
|
140
|
-
"663682": ("summer-weekday-gbp", "summer-weekday-rate", "summer-weekday-kwh"),
|
|
141
|
-
"299992": ("summer-weekend-gbp", "summer-weekend-rate", "summer-weekend-kwh"),
|
|
142
|
-
"211000": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
|
|
143
|
-
"790618": ("tnuos-gbp", None, None),
|
|
144
|
-
"447769": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
145
|
-
"647721": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
146
|
-
"276631": ("triad-gbp", "triad-rate", "triad-kw"),
|
|
147
|
-
"220894": ("winter-night-gbp", "winter-night-rate", "winter-night-kwh"),
|
|
148
|
-
"264929": ("winter-weekday-gbp", "winter-weekday-rate", "winter-weekday-kwh"),
|
|
149
|
-
"638187": ("winter-weekend-gbp", "winter-weekend-rate", "winter-weekend-kwh"),
|
|
150
|
-
"700285": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
|
|
151
|
-
"""
|
|
152
154
|
|
|
153
155
|
TPR_LOOKUP = {
|
|
154
156
|
"Day": "00043",
|
|
@@ -163,12 +165,37 @@ def _process_BCD(elements, headers):
|
|
|
163
165
|
issue_date = to_date(elements["IVDT"][0])
|
|
164
166
|
reference = elements["INVN"][0]
|
|
165
167
|
bill_type_code = elements["BTCD"][0]
|
|
168
|
+
sumo = elements["SUMO"]
|
|
169
|
+
headers["start_date"] = to_date(sumo[0])
|
|
170
|
+
headers["finish_date"] = to_date(sumo[1]) - HH
|
|
166
171
|
|
|
167
172
|
headers["issue_date"] = issue_date
|
|
168
173
|
headers["bill_type_code"] = bill_type_code
|
|
169
174
|
headers["reference"] = reference
|
|
170
175
|
|
|
171
176
|
|
|
177
|
+
def _process_BTL(elements, headers):
|
|
178
|
+
uvlt = elements["UVLT"]
|
|
179
|
+
utva = elements["UTVA"]
|
|
180
|
+
tbtl = elements["TBTL"]
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
"mpan_core": headers["mpan_core"],
|
|
184
|
+
"account": headers["account"],
|
|
185
|
+
"bill_type_code": headers["bill_type_code"],
|
|
186
|
+
"reference": headers["reference"],
|
|
187
|
+
"issue_date": headers["issue_date"],
|
|
188
|
+
"start_date": headers["start_date"],
|
|
189
|
+
"finish_date": headers["finish_date"],
|
|
190
|
+
"kwh": headers["kwh"],
|
|
191
|
+
"net": Decimal("0.00") + to_decimal(uvlt) / Decimal("100"),
|
|
192
|
+
"vat": Decimal("0.00") + to_decimal(utva) / Decimal("100"),
|
|
193
|
+
"gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
|
|
194
|
+
"breakdown": headers["breakdown"],
|
|
195
|
+
"reads": headers["reads"],
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
172
199
|
def _process_CCD1(elements, headers):
|
|
173
200
|
tcod = elements["TCOD"]
|
|
174
201
|
pres_read_date = to_finish_date(elements["PRDT"][0])
|
|
@@ -227,12 +254,11 @@ def _process_CCD2(elements, headers):
|
|
|
227
254
|
element_code = elements["TMOD"][0]
|
|
228
255
|
headers["element_code"] = element_code
|
|
229
256
|
try:
|
|
230
|
-
eln_gbp, eln_rate, eln_cons =
|
|
257
|
+
eln_gbp, eln_rate, eln_cons = ELEMENT_MAP[element_code]
|
|
231
258
|
except KeyError:
|
|
232
|
-
raise BadRequest(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
mpan_core = " ".join((m[:2], m[2:6], m[6:10], m[10:]))
|
|
259
|
+
raise BadRequest(
|
|
260
|
+
f"Can't find the element code {element_code} in the ELEMENT_MAP."
|
|
261
|
+
)
|
|
236
262
|
|
|
237
263
|
cons = elements["CONS"]
|
|
238
264
|
kwh = Decimal("0")
|
|
@@ -259,8 +285,7 @@ def _process_CCD2(elements, headers):
|
|
|
259
285
|
net = Decimal("0.00")
|
|
260
286
|
|
|
261
287
|
breakdown[eln_gbp] = net
|
|
262
|
-
|
|
263
|
-
headers["mpan_core"] = mpan_core
|
|
288
|
+
breakdown["raw-lines"] = [headers["line"]]
|
|
264
289
|
|
|
265
290
|
try:
|
|
266
291
|
reads = headers["reads"]
|
|
@@ -268,12 +293,10 @@ def _process_CCD2(elements, headers):
|
|
|
268
293
|
except KeyError:
|
|
269
294
|
reads = []
|
|
270
295
|
|
|
271
|
-
|
|
296
|
+
bill = {
|
|
272
297
|
"bill_type_code": headers["bill_type_code"],
|
|
273
298
|
"reference": headers["reference"] + "_" + eln_gbp[:-4],
|
|
274
299
|
"issue_date": headers["issue_date"],
|
|
275
|
-
"mpan_core": mpan_core,
|
|
276
|
-
"account": mpan_core,
|
|
277
300
|
"start_date": start_date,
|
|
278
301
|
"finish_date": finish_date,
|
|
279
302
|
"kwh": kwh if eln_gbp == "ro-gbp" else Decimal("0"),
|
|
@@ -283,83 +306,59 @@ def _process_CCD2(elements, headers):
|
|
|
283
306
|
"breakdown": breakdown,
|
|
284
307
|
"reads": reads,
|
|
285
308
|
}
|
|
309
|
+
headers["bills"].append(bill)
|
|
286
310
|
|
|
287
311
|
|
|
288
312
|
def _process_CCD3(elements, headers):
|
|
289
|
-
breakdown =
|
|
313
|
+
breakdown = headers["breakdown"]
|
|
290
314
|
|
|
291
|
-
|
|
292
|
-
|
|
315
|
+
supplier_code = elements["CCDE"][2]
|
|
316
|
+
tariff_code = elements["TCOD"][0]
|
|
317
|
+
mod_code = elements["TMOD"][0]
|
|
293
318
|
try:
|
|
294
|
-
eln_gbp, eln_rate, eln_cons =
|
|
319
|
+
eln_gbp, eln_rate, eln_cons = ELEMENT_MAP[supplier_code][tariff_code][mod_code]
|
|
295
320
|
except KeyError:
|
|
296
|
-
raise BadRequest(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
321
|
+
raise BadRequest(
|
|
322
|
+
f"Can't find the element key {supplier_code} -> {tariff_code} -> "
|
|
323
|
+
f"{mod_code} in the ELEMENT_MAP."
|
|
324
|
+
)
|
|
300
325
|
|
|
301
326
|
cons = elements["CONS"]
|
|
302
|
-
|
|
327
|
+
kwh = Decimal("0")
|
|
328
|
+
if len(cons[0]) > 0:
|
|
303
329
|
el_cons = to_decimal(cons) / Decimal("1000")
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if
|
|
309
|
-
rate = to_decimal(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
finish_date = to_date(elements["CEDT"][0]) - HH
|
|
316
|
-
headers["bill_finish_date"] = finish_date
|
|
330
|
+
kwh = el_cons
|
|
331
|
+
breakdown[eln_cons] += kwh
|
|
332
|
+
|
|
333
|
+
bpri = elements["BPRI"]
|
|
334
|
+
if len(bpri[0]) > 0:
|
|
335
|
+
rate = to_decimal(bpri) / Decimal("100000")
|
|
336
|
+
if eln_rate in breakdown:
|
|
337
|
+
breakdown[eln_rate].add(rate)
|
|
338
|
+
else:
|
|
339
|
+
breakdown[eln_rate] = {rate}
|
|
317
340
|
|
|
318
341
|
if "CTOT" in elements:
|
|
319
342
|
net = Decimal("0.00") + to_decimal(elements["CTOT"]) / Decimal("100")
|
|
320
343
|
else:
|
|
321
344
|
net = Decimal("0.00")
|
|
322
345
|
|
|
323
|
-
breakdown[eln_gbp]
|
|
324
|
-
|
|
325
|
-
headers["mpan_core"] = mpan_core
|
|
326
|
-
|
|
327
|
-
try:
|
|
328
|
-
reads = headers["reads"]
|
|
329
|
-
headers["reads"] = []
|
|
330
|
-
except KeyError:
|
|
331
|
-
reads = []
|
|
346
|
+
breakdown[eln_gbp] += net
|
|
332
347
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
"issue_date": headers["issue_date"],
|
|
336
|
-
"reference": headers["reference"] + "_" + eln_gbp[:-4],
|
|
337
|
-
"mpan_core": mpan_core,
|
|
338
|
-
"account": mpan_core,
|
|
339
|
-
"start_date": start_date,
|
|
340
|
-
"finish_date": finish_date,
|
|
341
|
-
"net": net,
|
|
342
|
-
"kwh": kwh if eln_gbp == "ro-gbp" else Decimal("0"),
|
|
343
|
-
"vat": Decimal("0.00"),
|
|
344
|
-
"gross": net,
|
|
345
|
-
"breakdown": breakdown,
|
|
346
|
-
"reads": reads,
|
|
347
|
-
}
|
|
348
|
+
if eln_gbp == "nrg-msp-gbp":
|
|
349
|
+
headers["kwh"] += kwh
|
|
348
350
|
|
|
349
351
|
|
|
350
352
|
def _process_CCD4(elements, headers):
|
|
351
|
-
breakdown =
|
|
353
|
+
breakdown = headers["breakdown"]
|
|
352
354
|
|
|
353
355
|
element_code = elements["TMOD"][0]
|
|
354
356
|
headers["element_code"] = element_code
|
|
355
357
|
try:
|
|
356
|
-
eln_gbp, eln_rate, eln_cons =
|
|
358
|
+
eln_gbp, eln_rate, eln_cons = ELEMENT_MAP[element_code]
|
|
357
359
|
except KeyError:
|
|
358
360
|
raise BadRequest(f"Can't find the element code {element_code} in the TMOD_MAP.")
|
|
359
361
|
|
|
360
|
-
m = elements["MLOC"][0]
|
|
361
|
-
mpan_core = " ".join((m[:2], m[2:6], m[6:10], m[10:]))
|
|
362
|
-
|
|
363
362
|
cons = elements["CONS"]
|
|
364
363
|
if eln_cons is not None and len(cons[0]) > 0:
|
|
365
364
|
el_cons = to_decimal(cons, "1000")
|
|
@@ -381,8 +380,7 @@ def _process_CCD4(elements, headers):
|
|
|
381
380
|
net = Decimal("0.00")
|
|
382
381
|
|
|
383
382
|
breakdown[eln_gbp] = net
|
|
384
|
-
|
|
385
|
-
headers["mpan_core"] = mpan_core
|
|
383
|
+
breakdown["raw-lines"] = [headers["line"]]
|
|
386
384
|
|
|
387
385
|
try:
|
|
388
386
|
reads = headers["reads"]
|
|
@@ -390,12 +388,10 @@ def _process_CCD4(elements, headers):
|
|
|
390
388
|
except KeyError:
|
|
391
389
|
reads = []
|
|
392
390
|
|
|
393
|
-
|
|
391
|
+
bill = {
|
|
394
392
|
"kwh": kwh if eln_gbp == "ro-gbp" else Decimal("0.00"),
|
|
395
393
|
"reference": headers["reference"] + "_" + eln_gbp[:-4],
|
|
396
394
|
"issue_date": headers["issue_date"],
|
|
397
|
-
"mpan_core": mpan_core,
|
|
398
|
-
"account": mpan_core,
|
|
399
395
|
"start_date": start_date,
|
|
400
396
|
"finish_date": finish_date,
|
|
401
397
|
"net": net,
|
|
@@ -405,6 +401,7 @@ def _process_CCD4(elements, headers):
|
|
|
405
401
|
"reads": reads,
|
|
406
402
|
"bill_type_code": headers["bill_type_code"],
|
|
407
403
|
}
|
|
404
|
+
headers["bills"].append(bill)
|
|
408
405
|
|
|
409
406
|
|
|
410
407
|
def _process_CDT(elements, headers):
|
|
@@ -412,21 +409,39 @@ def _process_CDT(elements, headers):
|
|
|
412
409
|
headers["customer_number"] = customer_id
|
|
413
410
|
|
|
414
411
|
|
|
412
|
+
def _process_CLO(elements, headers):
|
|
413
|
+
cloc = elements["CLOC"]
|
|
414
|
+
headers["account"] = cloc[1]
|
|
415
|
+
|
|
416
|
+
|
|
415
417
|
def _process_END(elements, headers):
|
|
416
418
|
pass
|
|
417
419
|
|
|
418
420
|
|
|
421
|
+
def _process_MAN(elements, headers):
|
|
422
|
+
madn = elements["MADN"]
|
|
423
|
+
|
|
424
|
+
headers["mpan_core"] = parse_mpan_core("".join(madn[0:3]))
|
|
425
|
+
|
|
426
|
+
|
|
419
427
|
def _process_MHD(elements, headers):
|
|
420
428
|
message_type = elements["TYPE"][0]
|
|
421
429
|
if message_type == "UTLBIL":
|
|
430
|
+
last_line = headers["lines"][-1]
|
|
422
431
|
keep_keys = {"customer_number"}
|
|
423
432
|
keep = {k: headers[k] for k in keep_keys}
|
|
424
433
|
headers.clear()
|
|
425
434
|
headers.update(keep)
|
|
435
|
+
headers["lines"] = [last_line]
|
|
436
|
+
headers["breakdown"] = defaultdict(
|
|
437
|
+
int, {"vat": {}, "raw-lines": headers["lines"]}
|
|
438
|
+
)
|
|
439
|
+
headers["kwh"] = Decimal(0)
|
|
440
|
+
headers["reads"] = []
|
|
426
441
|
|
|
427
442
|
|
|
428
443
|
def _process_MTR(elements, headers):
|
|
429
|
-
|
|
444
|
+
headers["lines"] = []
|
|
430
445
|
|
|
431
446
|
|
|
432
447
|
def _process_VAT(elements, headers):
|
|
@@ -434,21 +449,7 @@ def _process_VAT(elements, headers):
|
|
|
434
449
|
vat_percentage = to_decimal(elements["VATP"]) / Decimal("1000")
|
|
435
450
|
vat_net = Decimal("0.00") + to_decimal(elements["UVLA"]) / Decimal("100")
|
|
436
451
|
|
|
437
|
-
|
|
438
|
-
"bill_type_code": headers["bill_type_code"],
|
|
439
|
-
"account": headers["mpan_core"],
|
|
440
|
-
"mpan_core": headers["mpan_core"],
|
|
441
|
-
"reference": headers["reference"] + "_vat",
|
|
442
|
-
"issue_date": headers["issue_date"],
|
|
443
|
-
"start_date": headers["bill_start_date"],
|
|
444
|
-
"finish_date": headers["bill_finish_date"],
|
|
445
|
-
"kwh": Decimal("0.00"),
|
|
446
|
-
"net": Decimal("0.00"),
|
|
447
|
-
"vat": vat,
|
|
448
|
-
"gross": vat,
|
|
449
|
-
"breakdown": {"vat": {vat_percentage: {"vat": vat, "net": vat_net}}},
|
|
450
|
-
"reads": [],
|
|
451
|
-
}
|
|
452
|
+
headers["breakdown"]["vat"][vat_percentage] = {"vat": vat, "net": vat_net}
|
|
452
453
|
|
|
453
454
|
|
|
454
455
|
def _process_NOOP(elements, headers):
|
|
@@ -457,17 +458,17 @@ def _process_NOOP(elements, headers):
|
|
|
457
458
|
|
|
458
459
|
CODE_FUNCS = {
|
|
459
460
|
"BCD": _process_BCD,
|
|
460
|
-
"BTL":
|
|
461
|
+
"BTL": _process_BTL,
|
|
461
462
|
"CCD1": _process_CCD1,
|
|
462
463
|
"CCD2": _process_CCD2,
|
|
463
464
|
"CCD3": _process_CCD3,
|
|
464
465
|
"CCD4": _process_CCD4,
|
|
465
466
|
"CDT": _process_CDT,
|
|
466
|
-
"CLO":
|
|
467
|
+
"CLO": _process_CLO,
|
|
467
468
|
"DNA": _process_NOOP,
|
|
468
469
|
"END": _process_END,
|
|
469
470
|
"FIL": _process_NOOP,
|
|
470
|
-
"MAN":
|
|
471
|
+
"MAN": _process_MAN,
|
|
471
472
|
"MHD": _process_MHD,
|
|
472
473
|
"MTR": _process_MTR,
|
|
473
474
|
"SDT": _process_NOOP,
|
|
@@ -479,21 +480,6 @@ CODE_FUNCS = {
|
|
|
479
480
|
}
|
|
480
481
|
|
|
481
482
|
|
|
482
|
-
def _customer_mods(headers, bill):
|
|
483
|
-
if headers["customer_number"] == "WESSEXWAT":
|
|
484
|
-
if (
|
|
485
|
-
headers["element_code"] == "307660"
|
|
486
|
-
and "ro-gbp" in bill["breakdown"]
|
|
487
|
-
and bill["issue_date"] == to_utc(ct_datetime(2023, 4, 14))
|
|
488
|
-
and bill["start_date"] == to_utc(ct_datetime(2023, 3, 1))
|
|
489
|
-
and bill["finish_date"] == to_utc(ct_datetime(2023, 3, 31, 23, 30))
|
|
490
|
-
):
|
|
491
|
-
bill["start_date"] = to_utc(ct_datetime(2021, 4, 1))
|
|
492
|
-
bill["finish_date"] = to_utc(ct_datetime(2022, 3, 31, 23, 30))
|
|
493
|
-
|
|
494
|
-
return bill
|
|
495
|
-
|
|
496
|
-
|
|
497
483
|
class Parser:
|
|
498
484
|
def __init__(self, f):
|
|
499
485
|
self.edi_str = str(f.read(), "utf-8", errors="ignore")
|
|
@@ -501,9 +487,9 @@ class Parser:
|
|
|
501
487
|
|
|
502
488
|
def make_raw_bills(self):
|
|
503
489
|
bills = []
|
|
504
|
-
headers = {}
|
|
505
|
-
bill = None
|
|
490
|
+
headers = {"lines": []}
|
|
506
491
|
for self.line_number, line, seg_name, elements in parse_edi(self.edi_str):
|
|
492
|
+
headers["lines"].append(line)
|
|
507
493
|
try:
|
|
508
494
|
func = CODE_FUNCS[seg_name]
|
|
509
495
|
except KeyError:
|
|
@@ -523,7 +509,6 @@ class Parser:
|
|
|
523
509
|
) from e
|
|
524
510
|
|
|
525
511
|
if bill is not None:
|
|
526
|
-
bill
|
|
527
|
-
bills.append(_customer_mods(headers, bill))
|
|
512
|
+
bills.append(bill)
|
|
528
513
|
|
|
529
514
|
return bills
|