chellow 1757320031.0.0__py3-none-any.whl → 1759155233.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.

Files changed (75) hide show
  1. chellow/e/bill_importer.py +136 -80
  2. chellow/e/bill_parsers/activity_mop_stark_xlsx.py +99 -86
  3. chellow/e/bill_parsers/annual_mop_stark_xlsx.py +78 -61
  4. chellow/e/bill_parsers/csv.py +139 -101
  5. chellow/e/bill_parsers/drax_edi.py +65 -89
  6. chellow/e/bill_parsers/engie_edi.py +187 -255
  7. chellow/e/bill_parsers/engie_xls.py +153 -167
  8. chellow/e/bill_parsers/haven_edi.py +189 -228
  9. chellow/e/bill_parsers/haven_edi_tprs.py +67 -67
  10. chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py +75 -66
  11. chellow/e/bill_parsers/settlement_dc_stark_xlsx.py +229 -126
  12. chellow/e/bill_parsers/sse_edi.py +107 -75
  13. chellow/e/bill_parsers/sww_xls.py +78 -91
  14. chellow/e/computer.py +1 -1
  15. chellow/e/views.py +626 -281
  16. chellow/edi_lib.py +4 -27
  17. chellow/models.py +92 -3
  18. chellow/reports/report_111.py +478 -616
  19. chellow/reports/report_247.py +96 -137
  20. chellow/templates/e/dc_batch.html +110 -157
  21. chellow/templates/e/dc_batch_add.html +2 -3
  22. chellow/templates/e/dc_batch_edit.html +42 -46
  23. chellow/templates/e/dc_batch_file.html +2 -3
  24. chellow/templates/e/dc_batch_file_edit.html +28 -40
  25. chellow/templates/e/dc_batch_upload_file.html +68 -0
  26. chellow/templates/e/dc_batches.html +2 -1
  27. chellow/templates/e/dc_batches_edit.html +26 -0
  28. chellow/templates/e/dc_bill.html +27 -5
  29. chellow/templates/e/dc_bill_add.html +4 -4
  30. chellow/templates/e/dc_bill_edit.html +43 -63
  31. chellow/templates/e/dc_bill_import.html +1 -1
  32. chellow/templates/e/dc_bill_import_contract.html +130 -0
  33. chellow/templates/e/dc_contract.html +1 -1
  34. chellow/templates/e/dc_element.html +41 -0
  35. chellow/templates/e/dc_element_add.html +36 -0
  36. chellow/templates/e/dc_element_edit.html +49 -0
  37. chellow/templates/e/dc_rate_script_edit.html +27 -43
  38. chellow/templates/e/mop_batch.html +105 -152
  39. chellow/templates/e/mop_batch_add.html +2 -3
  40. chellow/templates/e/mop_batch_edit.html +43 -51
  41. chellow/templates/e/mop_batch_upload_file.html +71 -5
  42. chellow/templates/e/mop_batches.html +2 -1
  43. chellow/templates/e/mop_batches_edit.html +26 -0
  44. chellow/templates/e/mop_bill.html +31 -8
  45. chellow/templates/e/mop_bill_add.html +7 -27
  46. chellow/templates/e/mop_bill_import.html +1 -1
  47. chellow/templates/e/mop_bill_import_contract.html +130 -0
  48. chellow/templates/e/mop_contract.html +4 -5
  49. chellow/templates/e/mop_element.html +41 -0
  50. chellow/templates/e/mop_element_add.html +36 -0
  51. chellow/templates/e/mop_element_edit.html +49 -0
  52. chellow/templates/e/supplier_batch.html +3 -7
  53. chellow/templates/e/supplier_batch_add.html +2 -2
  54. chellow/templates/e/supplier_batch_edit.html +1 -1
  55. chellow/templates/e/supplier_batch_file.html +3 -5
  56. chellow/templates/e/supplier_batch_file_add.html +18 -11
  57. chellow/templates/e/supplier_batch_upload_file.html +83 -9
  58. chellow/templates/e/supplier_batches.html +4 -4
  59. chellow/templates/e/supplier_batches_edit.html +26 -0
  60. chellow/templates/e/supplier_bill.html +29 -6
  61. chellow/templates/e/supplier_bill_add.html +3 -3
  62. chellow/templates/e/supplier_bill_import.html +1 -1
  63. chellow/templates/e/supplier_bill_import_contract.html +118 -0
  64. chellow/templates/e/supplier_contract.html +1 -1
  65. chellow/templates/e/supplier_element.html +45 -0
  66. chellow/templates/e/supplier_element_add.html +36 -0
  67. chellow/templates/e/supplier_element_edit.html +51 -0
  68. chellow/templates/report_run_bill_check.html +137 -179
  69. chellow/templates/report_run_row_bill_check.html +182 -179
  70. chellow/views.py +55 -65
  71. {chellow-1757320031.0.0.dist-info → chellow-1759155233.0.0.dist-info}/METADATA +2 -2
  72. {chellow-1757320031.0.0.dist-info → chellow-1759155233.0.0.dist-info}/RECORD +73 -60
  73. chellow/e/bill_parsers/drax_element_edi.py +0 -459
  74. chellow/templates/e/supplier_bill_imports.html +0 -421
  75. {chellow-1757320031.0.0.dist-info → chellow-1759155233.0.0.dist-info}/WHEEL +0 -0
@@ -28,124 +28,162 @@ def parse_date(row, idx, is_finish=False):
28
28
  else:
29
29
  dt = to_utc(ct_datetime_parse(date_str, "%Y-%m-%d %H:%M"))
30
30
  return validate_hh_start(dt)
31
- except ValueError as e:
31
+ except BaseException as e:
32
32
  raise BadRequest(
33
33
  f"Can't parse the date at column {idx}. The required spreadsheet format is "
34
34
  f"'YYYY-MM-DD HH:MM'. {e}"
35
35
  )
36
36
 
37
37
 
38
+ def to_decimal(vals, dec_index, dec_name, is_money=False):
39
+ try:
40
+ dec_str = vals[dec_index]
41
+ dec_str = dec_str.replace(",", "")
42
+ dec = Decimal(dec_str)
43
+ if is_money:
44
+ dec += Decimal("0.00")
45
+ dec = round(dec, 2)
46
+ return dec
47
+ except InvalidOperation as e:
48
+ raise BadRequest(
49
+ f"The value '{dec_str}' can't be parsed as a decimal: {e}. It's in "
50
+ f"the '{dec_name}' column at position {dec_index} in {vals}."
51
+ )
52
+ except IndexError:
53
+ raise BadRequest(
54
+ f"The field '{dec_name}' can't be found. It's expected at "
55
+ f"position {dec_index} in the list of fields."
56
+ )
57
+ except ValueError:
58
+ raise BadRequest(
59
+ f"The {dec_name} field '{dec_str}' cannot be parsed as a number. The "
60
+ f"{dec_name} field is the {dec_index} field of {vals}."
61
+ )
62
+
63
+
64
+ def _process_row(vals):
65
+ bill_type_code = vals[0]
66
+ account = vals[1]
67
+ mpan_core = parse_mpan_core(vals[2])
68
+ reference = vals[3]
69
+ issue_date = parse_date(vals, 4)
70
+ start_date = parse_date(vals, 5)
71
+ finish_date = parse_date(vals, 6, True)
72
+
73
+ kwh = to_decimal(vals, 7, "kwh")
74
+ net = to_decimal(vals, 8, "net", is_money=True)
75
+ vat = to_decimal(vals, 9, "vat", is_money=True)
76
+ gross = to_decimal(vals, 10, "gross", is_money=True)
77
+
78
+ if len(vals) > 11:
79
+ breakdown_str = vals[11].strip()
80
+ if len(breakdown_str) == 0:
81
+ breakdown = {}
82
+ else:
83
+ try:
84
+ breakdown = loads(breakdown_str)
85
+ except ZishLocationException as e:
86
+ raise BadRequest(str(e))
87
+ else:
88
+ raise BadRequest("There isn't a 'breakdown' field on the end.")
89
+
90
+ while vals[-1] == "" and len(vals) > 12:
91
+ del vals[-1]
92
+
93
+ reads = []
94
+ elements = []
95
+ i = 12
96
+ while i < len(vals):
97
+ typ = vals[i].strip().lower()
98
+ if typ == "read":
99
+ tpr_str = vals[i + 5].strip()
100
+ tpr_code = None if len(tpr_str) == 0 else tpr_str.zfill(5)
101
+ reads.append(
102
+ {
103
+ "msn": vals[i + 1],
104
+ "mpan": vals[i + 2],
105
+ "coefficient": to_decimal(vals, i + 3, "coefficient"),
106
+ "units": vals[i + 4],
107
+ "tpr_code": tpr_code,
108
+ "prev_date": parse_date(vals, i + 6),
109
+ "prev_value": Decimal(vals[i + 7]),
110
+ "prev_type_code": vals[i + 8],
111
+ "pres_date": parse_date(vals, i + 9),
112
+ "pres_value": Decimal(vals[i + 10]),
113
+ "pres_type_code": vals[i + 11],
114
+ }
115
+ )
116
+ i += 12
117
+ elif typ == "element":
118
+ breakdown_str = vals[i + 5].strip()
119
+ if len(breakdown_str) == 0:
120
+ breakdown = {}
121
+ else:
122
+ try:
123
+ breakdown = loads(breakdown_str)
124
+ except ZishLocationException as e:
125
+ raise BadRequest(str(e))
126
+ elements.append(
127
+ {
128
+ "name": vals[i + 1],
129
+ "start_date": parse_date(vals, i + 2),
130
+ "finish_date": parse_date(vals, i + 3),
131
+ "net": to_decimal(vals, i + 4, "net", is_money=True),
132
+ "breakdown": breakdown,
133
+ }
134
+ )
135
+ i += 6
136
+ else:
137
+ raise BadRequest("Record type {type} not recognized.")
138
+
139
+ if len(elements) == 0:
140
+ elements.append(
141
+ {
142
+ "name": "net",
143
+ "start_date": start_date,
144
+ "finish_date": finish_date,
145
+ "net": net,
146
+ "breakdown": {},
147
+ }
148
+ )
149
+
150
+ return {
151
+ "bill_type_code": bill_type_code,
152
+ "account": account,
153
+ "mpan_core": mpan_core,
154
+ "reference": reference,
155
+ "issue_date": issue_date,
156
+ "start_date": start_date,
157
+ "finish_date": finish_date,
158
+ "kwh": kwh,
159
+ "net": net,
160
+ "vat": vat,
161
+ "gross": gross,
162
+ "breakdown": breakdown,
163
+ "reads": reads,
164
+ "elements": elements,
165
+ }
166
+
167
+
38
168
  class Parser:
39
169
  def __init__(self, f):
40
170
  self.reader = csv.reader(
41
- StringIO(str(f.read(), "utf-8", errors="ignore")), skipinitialspace=True
171
+ StringIO(str(f.read(), "utf-8-sig", errors="ignore")), skipinitialspace=True
42
172
  )
43
173
  self.line_number = None
44
174
 
45
175
  def make_raw_bills(self):
46
- raw_bills = []
47
- next(iter(self.reader)) # skip title row
48
- blank_set = set(("",))
49
176
  for self.line_number, self.vals in enumerate(self.reader, start=2):
50
177
  try:
51
- # skip blank lines
52
- if len(self.vals) == 0 or set(self.vals) == blank_set:
178
+ # skip blank lines and comment lines
179
+ if (
180
+ len(self.vals) == 0
181
+ or set(self.vals) == {""}
182
+ or self.vals[0].strip().startswith("#")
183
+ ):
53
184
  continue
54
-
55
- bill_type_code = self.vals[0]
56
- if bill_type_code.startswith("#"):
57
- continue # skip comment lines
58
- account = self.vals[1]
59
- mpan_core = parse_mpan_core(self.vals[2])
60
- reference = self.vals[3]
61
- issue_date = parse_date(self.vals, 4)
62
- start_date = parse_date(self.vals, 5)
63
- finish_date = parse_date(self.vals, 6, True)
64
-
65
- kwh = self.to_decimal(7, "kwh")
66
- net = self.to_decimal(8, "net", True)
67
- vat = self.to_decimal(9, "vat", True)
68
- gross = self.to_decimal(10, "gross", True)
69
-
70
- if len(self.vals) > 11:
71
- breakdown_str = self.vals[11].strip()
72
- if len(breakdown_str) == 0:
73
- breakdown = {}
74
- else:
75
- try:
76
- breakdown = loads(breakdown_str)
77
- except ZishLocationException as e:
78
- raise BadRequest(str(e))
79
- else:
80
- raise BadRequest("There isn't a 'breakdown' field on the end.")
81
-
82
- while self.vals[-1] == "" and len(self.vals) > 12:
83
- del self.vals[-1]
84
-
85
- reads = []
86
- for i in range(12, len(self.vals), 11):
87
- tpr_str = self.vals[i + 4].strip()
88
- tpr_code = None if len(tpr_str) == 0 else tpr_str.zfill(5)
89
- reads.append(
90
- {
91
- "msn": self.vals[i],
92
- "mpan": self.vals[i + 1],
93
- "coefficient": self.to_decimal(i + 2, "coefficient"),
94
- "units": self.vals[i + 3],
95
- "tpr_code": tpr_code,
96
- "prev_date": parse_date(self.vals, i + 5),
97
- "prev_value": Decimal(self.vals[i + 6]),
98
- "prev_type_code": self.vals[i + 7],
99
- "pres_date": parse_date(self.vals, i + 8),
100
- "pres_value": Decimal(self.vals[i + 9]),
101
- "pres_type_code": self.vals[i + 10],
102
- }
103
- )
104
-
105
- raw_bill = {
106
- "bill_type_code": bill_type_code,
107
- "account": account,
108
- "mpan_core": mpan_core,
109
- "reference": reference,
110
- "issue_date": issue_date,
111
- "start_date": start_date,
112
- "finish_date": finish_date,
113
- "kwh": kwh,
114
- "net": net,
115
- "vat": vat,
116
- "gross": gross,
117
- "breakdown": breakdown,
118
- "reads": reads,
119
- }
120
- raw_bills.append(raw_bill)
185
+ yield _process_row(self.vals)
121
186
  except BadRequest as e:
122
187
  raise BadRequest(
123
188
  f"Problem at line {self.line_number} {self.vals}: {e.description}"
124
189
  )
125
-
126
- return raw_bills
127
-
128
- def to_decimal(self, dec_index, dec_name, is_money=False):
129
- try:
130
- dec_str = self.vals[dec_index]
131
- dec_str = dec_str.replace(",", "")
132
- dec = Decimal(dec_str)
133
- if is_money:
134
- dec += Decimal("0.00")
135
- return dec
136
- except InvalidOperation as e:
137
- raise BadRequest(
138
- f"The value '{dec_str}' can't be parsed as a decimal: {e}. It's in "
139
- f"the '{dec_name}' column at position {dec_index} in {self.vals}."
140
- )
141
- except IndexError:
142
- raise BadRequest(
143
- f"The field '{dec_name}' can't be found. It's expected at "
144
- f"position {dec_index} in the list of fields."
145
- )
146
- except ValueError:
147
- raise BadRequest(
148
- f"The {dec_name} field '{dec_str}' cannot be parsed as a "
149
- f"number. The {dec_name} field is the {dec_index} field of "
150
- f"{self.vals}."
151
- )
@@ -24,132 +24,100 @@ read_type_map = {
24
24
  ELEMENT_MAP = {
25
25
  "AAH": {
26
26
  "AAHEDC": {
27
- "139039": ("aahedc-gbp", "aahedc-rate", "aahedc-kwh"),
27
+ "139039": ("aahedc", "rate", "kwh"),
28
28
  },
29
29
  },
30
30
  "ADH": {
31
31
  "ADHOC": {
32
- "020330": ("eii-gbp", None, None),
33
- "064305": ("fit-gbp", None, None),
34
- "590346": ("cfd-operational-gbp", None, None),
35
- "637050": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
36
- "493988": ("reconciliation-gbp", None, None),
32
+ "020330": ("eii", None, None),
33
+ "064305": ("fit", None, None),
34
+ "590346": ("cfd-operational", None, None),
35
+ "493988": ("reconciliation", None, None),
36
+ "637050": ("meter-rental", "rate", "days"),
37
37
  },
38
38
  },
39
39
  "BUS": {
40
40
  "BSUOS": {
41
- "269100": ("bsuos-gbp", "bsuos-rate", "bsuos-kwh"),
41
+ "269100": ("bsuos", "rate", "kwh"),
42
42
  },
43
43
  },
44
44
  "CCL": {
45
45
  "CCL": {
46
- "422733": ("ccl-gbp", "ccl-rate", "ccl-kwh"),
46
+ "422733": ("ccl", "rate", "kwh"),
47
47
  },
48
48
  },
49
49
  "CFD": {
50
50
  "CFD001": {
51
- "273237": (
52
- "cfd-operational-gbp",
53
- "cfd-operational-rate",
54
- "cfd-operational-kwh",
55
- ),
56
- "954379": ("cfd-interim-gbp", "cfd-interim-rate", "cfd-interim-kwh"),
57
- "538249": (
58
- "cm-settlement-levy-gbp",
59
- "cm-settlement-levy-rate",
60
- "cm-settlement-levy-kwh",
61
- ),
62
- "568307": ("capacity-gbp", "capacity-rate", "capacity-kwh"),
51
+ "273237": ("cfd-operational", "rate", "kwh"),
52
+ "954379": ("cfd-interim", "rate", "kwh"),
53
+ "538249": ("cm-settlement-levy", "rate", "kwh"),
54
+ "568307": ("capacity", "rate", "kwh"),
63
55
  },
64
56
  },
65
57
  "DCA": {
66
58
  "DCDA": {
67
- "095469": ("meter-rental-gbp", "meter-rental-rate", "meter-rental-days"),
59
+ "095469": ("meter-rental", "rate", "days"),
68
60
  },
69
61
  },
70
62
  "DUS": {
71
63
  "DUS001": {
72
- "794486": (
73
- "duos-availability-gbp",
74
- "duos-availability-rate",
75
- "duos-availability-kva",
76
- ),
77
- "644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
78
- "797790": (
79
- "duos-reactive-gbp",
80
- "duos-reactive-rate",
81
- "duos-reactive-kvarh",
82
- ),
83
- "806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
84
- "716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
85
- "769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
86
- "709522": (
87
- "duos-excess-availability-gbp",
88
- "duos-excess-availability-rate",
89
- "duos-excess-availability-kva",
90
- ),
91
- "209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
64
+ "794486": ("duos-availability", "rate", "kva"),
65
+ "644819": ("duos-fixed", "rate", "days"),
66
+ "797790": ("duos-reactive", "rate", "kvarh"),
67
+ "806318": ("duos-green", "rate", "kwh"),
68
+ "716514": ("duos-amber", "rate", "kwh"),
69
+ "769979": ("duos-red", "rate", "kwh"),
70
+ "709522": ("duos-excess-availability", "rate", "kva"),
71
+ "209269": ("tnuos", "rate", "days"),
92
72
  },
93
73
  "DUS002": {
94
- "185913": ("duos-yellow-gbp", "duos-yellow-rate", "duos-yellow-kwh"),
95
- "517270": ("duos-black-gbp", "duos-black-rate", "duos-black-kwh"),
96
- "797790": (
97
- "duos-reactive-gbp",
98
- "duos-reactive-rate",
99
- "duos-reactive-kvarh",
100
- ),
101
- "806318": ("duos-green-gbp", "duos-green-rate", "duos-green-kwh"),
102
- "716514": ("duos-amber-gbp", "duos-amber-rate", "duos-amber-kwh"),
103
- "709522": (
104
- "duos-excess-availability-gbp",
105
- "duos-excess-availability-rate",
106
- "duos-excess-availability-kva",
107
- ),
108
- "769979": ("duos-red-gbp", "duos-red-rate", "duos-red-kwh"),
109
- "644819": ("duos-fixed-gbp", "duos-fixed-rate", "duos-fixed-days"),
110
- "794486": (
111
- "duos-availability-gbp",
112
- "duos-availability-rate",
113
- "duos-availability-kva",
114
- ),
115
- "209269": ("tnuos-gbp", "tnuos-rate", "tnuos-days"),
116
- "065950": ("eii-gbp", "eii-rate", "eii-kwh"),
74
+ "185913": ("duos-yellow", "rate", "kwh"),
75
+ "517270": ("duos-black", "rate", "kwh"),
76
+ "797790": ("duos-reactive", "rate", "kvarh"),
77
+ "806318": ("duos-green", "rate", "kwh"),
78
+ "716514": ("duos-amber", "rate", "kwh"),
79
+ "709522": ("duos-excess-availability", "rate", "kva"),
80
+ "769979": ("duos-red", "rate", "kwh"),
81
+ "644819": ("duos-fixed", "rate", "days"),
82
+ "794486": ("duos-availability", "rate", "kva"),
83
+ "209269": ("tnuos", "rate", "days"),
84
+ "065950": ("eii", "rate", "kwh"),
117
85
  },
118
86
  "DUSDIS": {
119
- "122568": ("nrg-gsp-losses-gbp", "nrg-rate", "nrg-gsp-losses-kwh"),
87
+ "122568": ("nrg-gsp-losses", "rate", "kwh"),
120
88
  },
121
89
  "DUSTRN": {
122
- "122568": ("nrg-nbp-losses-gbp", "nrg-rate", "nrg-nbp-losses-kwh"),
90
+ "122568": ("nrg-nbp-losses", "rate", "kwh"),
123
91
  },
124
92
  },
125
93
  "ELX": {
126
94
  "ELEXON": {
127
- "489920": ("elexon-gbp", "elexon-rate", "elexon-nbp-kwh"),
95
+ "489920": ("elexon", "rate", "kwh"),
128
96
  },
129
97
  },
130
98
  "FIT": {
131
99
  "FIT_LV": {
132
- "704107": ("fit-gbp", "fit-rate", "fit-kwh"),
100
+ "704107": ("fit", "rate", "kwh"),
133
101
  },
134
102
  },
135
103
  "NRG": {
136
104
  "HH0002": {
137
- "033667": ("management-gbp", "management-rate", "management-kwh"),
138
- "091890": ("shape-gbp", "shape-rate", "shape-kwh"),
139
- "122568": ("nrg-msp-gbp", "nrg-rate", "nrg-msp-kwh"),
105
+ "033667": ("management", "rate", "kwh"),
106
+ "091890": ("shape", "rate", "kwh"),
107
+ "122568": ("nrg-msp", "rate", "kwh"),
140
108
  },
141
109
  },
142
110
  "REN": {
143
111
  "REN001": {
144
- "229128": ("ro-gbp", "ro-rate", "ro-kwh"),
112
+ "229128": ("ro", "rate", "kwh"),
145
113
  },
146
114
  "REN002": {
147
- "019090": ("rego-gbp", "rego-rate", "rego-kwh"),
115
+ "019090": ("rego", "rate", "kwh"),
148
116
  },
149
117
  },
150
118
  "TUS": {
151
119
  "TNUOS": {
152
- "012069": ("triad-gbp", "triad-rate", "triad-kw"),
120
+ "012069": ("triad", "rate", "kw"),
153
121
  },
154
122
  },
155
123
  }
@@ -174,6 +142,7 @@ def _process_BCD(elements, headers):
174
142
  headers["issue_date"] = issue_date
175
143
  headers["bill_type_code"] = bill_type_code
176
144
  headers["reference"] = reference
145
+ headers["elements"] = []
177
146
 
178
147
 
179
148
  def _process_BTL(elements, headers):
@@ -195,6 +164,7 @@ def _process_BTL(elements, headers):
195
164
  "gross": Decimal("0.00") + to_decimal(tbtl) / Decimal("100"),
196
165
  "breakdown": headers["breakdown"],
197
166
  "reads": headers["reads"],
167
+ "elements": headers["elements"],
198
168
  }
199
169
 
200
170
 
@@ -312,13 +282,13 @@ def _process_CCD2(elements, headers):
312
282
 
313
283
 
314
284
  def _process_CCD3(elements, headers):
315
- breakdown = headers["breakdown"]
285
+ elem_bd = {}
316
286
 
317
287
  supplier_code = elements["CCDE"][2]
318
288
  tariff_code = elements["TCOD"][0]
319
289
  mod_code = elements["TMOD"][0]
320
290
  try:
321
- eln_gbp, eln_rate, eln_cons = ELEMENT_MAP[supplier_code][tariff_code][mod_code]
291
+ eln_name, eln_rate, eln_cons = ELEMENT_MAP[supplier_code][tariff_code][mod_code]
322
292
  except KeyError:
323
293
  raise BadRequest(
324
294
  f"Can't find the element key {supplier_code} -> {tariff_code} -> "
@@ -326,29 +296,35 @@ def _process_CCD3(elements, headers):
326
296
  )
327
297
 
328
298
  cons = elements["CONS"]
329
- kwh = Decimal("0")
330
299
  if len(cons[0]) > 0:
331
300
  el_cons = to_decimal(cons) / Decimal("1000")
332
- kwh = el_cons
333
- breakdown[eln_cons] += kwh
301
+ elem_bd[eln_cons] = el_cons
302
+ if eln_name == "nrg-msp":
303
+ headers["kwh"] += el_cons
334
304
 
335
305
  bpri = elements["BPRI"]
336
306
  if len(bpri[0]) > 0:
337
307
  rate = to_decimal(bpri) / Decimal("100000")
338
- if eln_rate in breakdown:
339
- breakdown[eln_rate].add(rate)
340
- else:
341
- breakdown[eln_rate] = {rate}
308
+ elem_bd[eln_rate] = {rate}
342
309
 
310
+ net = Decimal("0.00")
343
311
  if "CTOT" in elements:
344
- net = Decimal("0.00") + to_decimal(elements["CTOT"]) / Decimal("100")
345
- else:
346
- net = Decimal("0.00")
312
+ net += to_decimal(elements["CTOT"]) / Decimal("100")
347
313
 
348
- breakdown[eln_gbp] += net
314
+ csdt = elements["CSDT"]
315
+ start_date = to_date(csdt[0])
316
+ cedt = elements["CEDT"]
317
+ finish_date = to_finish_date(cedt[0])
349
318
 
350
- if eln_gbp == "nrg-msp-gbp":
351
- headers["kwh"] += kwh
319
+ headers["elements"].append(
320
+ {
321
+ "name": eln_name,
322
+ "start_date": start_date,
323
+ "finish_date": finish_date,
324
+ "net": net,
325
+ "breakdown": elem_bd,
326
+ }
327
+ )
352
328
 
353
329
 
354
330
  def _process_CCD4(elements, headers):