chellow 1731435800.0.0__py3-none-any.whl → 1732281664.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/general_import.py CHANGED
@@ -149,11 +149,13 @@ def general_import_era(sess, action, vals, args):
149
149
  comm_code = add_arg(args, "Comms Type", vals, 12)
150
150
  comm = era.comm if comm_code == NO_CHANGE else Comm.get_by_code(sess, comm_code)
151
151
 
152
- ssc_code = add_arg(args, "SSC", vals, 13)
153
- if ssc_code == NO_CHANGE:
154
- ssc_code = era.ssc.code
155
- elif len(ssc_code) == 0:
152
+ ssc_code_str = add_arg(args, "SSC", vals, 13)
153
+ if ssc_code_str == NO_CHANGE:
154
+ ssc_code = None if era.ssc is None else era.ssc.code
155
+ elif len(ssc_code_str) == 0:
156
156
  ssc_code = None
157
+ else:
158
+ ssc_code = ssc_code_str
157
159
 
158
160
  es_code = add_arg(args, "Energisation Status", vals, 14)
159
161
  if es_code == NO_CHANGE:
@@ -1702,21 +1704,43 @@ for k in tuple(globals().keys()):
1702
1704
  typ_funcs[k[len(PREFIX) :]] = globals()[k]
1703
1705
 
1704
1706
 
1707
+ def _process_line(sess, hh_data, line, args):
1708
+
1709
+ action = add_arg(args, "action", line, 0).lower()
1710
+ if action not in ALLOWED_ACTIONS:
1711
+ raise BadRequest(f"The 'action' field must be one of {ALLOWED_ACTIONS}")
1712
+ typ = add_arg(args, "type", line, 1).lower()
1713
+ vals = line[2:]
1714
+ if typ == "hh_datum":
1715
+ if action == "insert":
1716
+ hh_data.append(
1717
+ {
1718
+ "mpan_core": parse_mpan_core(add_arg(args, "MPAN Core", vals, 0)),
1719
+ "start_date": parse_hh_start(add_arg(args, "Start Date", vals, 1)),
1720
+ "channel_type": parse_channel_type(
1721
+ add_arg(args, "Channel Type", vals, 2)
1722
+ ),
1723
+ "value": Decimal(add_arg(args, "Value", vals, 3)),
1724
+ "status": add_arg(args, "Status", vals, 4),
1725
+ }
1726
+ )
1727
+ else:
1728
+ try:
1729
+ typ_func = typ_funcs[typ]
1730
+ typ_func(sess, action, vals, args)
1731
+ except KeyError:
1732
+ raise BadRequest(f"The type {typ} is not recognized.")
1733
+
1734
+
1705
1735
  class GeneralImporter(threading.Thread):
1706
1736
  def __init__(self, f):
1707
1737
  threading.Thread.__init__(self)
1708
1738
  self.line_number = None
1709
1739
  self.f = f
1710
- self.rd_lock = threading.Lock()
1711
1740
  self.error_message = None
1712
1741
  self.args = []
1713
- self.hh_data = []
1714
-
1715
- def get_fields(self):
1716
- fields = {"line_number": self.line_number, "error_message": self.error_message}
1717
- if self.error_message is not None:
1718
- fields["csv_line"] = self.args
1719
- return fields
1742
+ self.failed_args = []
1743
+ self.failed_lines = []
1720
1744
 
1721
1745
  def run(self):
1722
1746
  try:
@@ -1733,63 +1757,32 @@ class GeneralImporter(threading.Thread):
1733
1757
  if len(line) > 0 and line[0].startswith("#"):
1734
1758
  continue
1735
1759
 
1736
- action = add_arg(self.args, "action", line, 0).lower()
1737
- if action not in ALLOWED_ACTIONS:
1738
- raise BadRequest(
1739
- f"The 'action' field must be one of {ALLOWED_ACTIONS}"
1740
- )
1741
- typ = add_arg(self.args, "type", line, 1).lower()
1742
- vals = line[2:]
1743
- if typ == "hh_datum":
1744
- if action == "insert":
1745
- hh_data.append(
1746
- {
1747
- "mpan_core": parse_mpan_core(
1748
- add_arg(self.args, "MPAN Core", vals, 0)
1749
- ),
1750
- "start_date": parse_hh_start(
1751
- add_arg(self.args, "Start Date", vals, 1)
1752
- ),
1753
- "channel_type": parse_channel_type(
1754
- add_arg(self.args, "Channel Type", vals, 2)
1755
- ),
1756
- "value": Decimal(
1757
- add_arg(self.args, "Value", vals, 3)
1758
- ),
1759
- "status": add_arg(self.args, "Status", vals, 4),
1760
- }
1761
- )
1762
- else:
1763
- try:
1764
- typ_func = typ_funcs[typ]
1765
- typ_func(sess, action, vals, self.args)
1766
- except KeyError:
1767
- raise BadRequest(f"The type {typ} is not recognized.")
1760
+ try:
1761
+ with sess.begin_nested():
1762
+ _process_line(sess, hh_data, line, self.args)
1763
+
1764
+ except BadRequest as e:
1765
+ self.args.insert(0, ("Error", e.description))
1766
+ self.failed_args.append(self.args)
1767
+ self.failed_lines.append(line)
1768
1768
 
1769
1769
  HhDatum.insert(sess, hh_data)
1770
- sess.commit()
1770
+
1771
+ if len(self.failed_lines) == 0:
1772
+ sess.commit()
1773
+ else:
1774
+ sess.rollback()
1771
1775
  except BadRequest as e:
1772
- try:
1773
- self.rd_lock.acquire()
1774
- self.error_message = e.description
1775
- finally:
1776
- self.rd_lock.release()
1776
+ self.error_message = e.description
1777
1777
  except BaseException:
1778
- try:
1779
- self.rd_lock.acquire()
1780
- self.error_message = traceback.format_exc()
1781
- finally:
1782
- self.rd_lock.release()
1778
+ self.error_message = traceback.format_exc()
1783
1779
 
1784
1780
 
1785
1781
  def start_process(f):
1786
- try:
1782
+ with process_lock:
1787
1783
  global process_id
1788
- process_lock.acquire()
1789
1784
  proc_id = process_id
1790
1785
  process_id += 1
1791
- finally:
1792
- process_lock.release()
1793
1786
 
1794
1787
  process = GeneralImporter(f)
1795
1788
  processes[proc_id] = process
@@ -1798,16 +1791,9 @@ def start_process(f):
1798
1791
 
1799
1792
 
1800
1793
  def get_process_ids():
1801
- try:
1802
- process_lock.acquire()
1794
+ with process_lock:
1803
1795
  return processes.keys()
1804
- finally:
1805
- process_lock.release()
1806
1796
 
1807
1797
 
1808
1798
  def get_process(id):
1809
- try:
1810
- process_lock.acquire()
1811
- return processes[id]
1812
- finally:
1813
- process_lock.release()
1799
+ return processes[id]
@@ -178,6 +178,7 @@ def content(
178
178
  "bill-kwh",
179
179
  "bill-net-gbp",
180
180
  "bill-vat-gbp",
181
+ "bill-gross-gbp",
181
182
  "bill-start-date",
182
183
  "bill-finish-date",
183
184
  "imp-mpan-core",
@@ -371,7 +372,13 @@ def _process_supply(
371
372
 
372
373
  covered_start = bill_start
373
374
  covered_finish = bill_start
374
- covered_bdown = {"sum-msp-kwh": 0, "net-gbp": 0, "vat-gbp": 0, "problem": ""}
375
+ covered_bdown = {
376
+ "sum-msp-kwh": 0,
377
+ "net-gbp": 0,
378
+ "vat-gbp": 0,
379
+ "gross-gbp": 0,
380
+ "problem": "",
381
+ }
375
382
 
376
383
  vb_elems = set()
377
384
  enlarged = True
@@ -439,9 +446,23 @@ def _process_supply(
439
446
  primary_covered_bill = None
440
447
  for covered_bill in covered_bills.values():
441
448
  bill_ids.discard(covered_bill.id)
442
- covered_bdown["net-gbp"] += float(covered_bill.net)
443
- covered_bdown["vat-gbp"] += float(covered_bill.vat)
444
449
  covered_bdown["sum-msp-kwh"] += float(covered_bill.kwh)
450
+ for elem, val in (
451
+ ("net", covered_bill.net),
452
+ ("vat", covered_bill.vat),
453
+ ("gross", covered_bill.gross),
454
+ ):
455
+ covered_bdown[f"{elem}-gbp"] += float(val)
456
+ covered_elems.add(elem)
457
+ add_gap(
458
+ caches,
459
+ gaps,
460
+ elem,
461
+ covered_bill.start_date,
462
+ covered_bill.finish_date,
463
+ False,
464
+ val,
465
+ )
445
466
  for k, v in loads(covered_bill.breakdown).items():
446
467
  if k in ("raw_lines", "raw-lines", "vat"):
447
468
  continue
@@ -599,7 +620,7 @@ def _process_supply(
599
620
 
600
621
  for dt, bl in vb_hhs.items():
601
622
  for k, v in bl.items():
602
- if all((k.endswith("-gbp"), k != "net-gbp", v != 0)):
623
+ if k.endswith("-gbp") and v != 0:
603
624
  add_gap(caches, gaps, k[:-4], dt, dt, True, v)
604
625
 
605
626
  for k in virtual_bill.keys():
@@ -625,13 +646,13 @@ def _process_supply(
625
646
  f"virtual bill. "
626
647
  )
627
648
 
628
- try:
629
- del virtual_bill["net-gbp"]
630
- except KeyError:
631
- pass
632
-
649
+ virtual_bill.pop("net-gbp", None)
650
+ virtual_bill.pop("gross-gbp", None)
633
651
  virtual_bill["net-gbp"] = sum(
634
- v for k, v in virtual_bill.items() if k.endswith("-gbp")
652
+ v for k, v in virtual_bill.items() if k.endswith("-gbp") and k != "vat-gbp"
653
+ )
654
+ virtual_bill["gross-gbp"] = virtual_bill["net-gbp"] + virtual_bill.get(
655
+ "vat-gbp", 0
635
656
  )
636
657
 
637
658
  era = supply.find_era_at(sess, bill_finish)
@@ -665,6 +686,7 @@ def _process_supply(
665
686
  "bill-kwh": bill.kwh,
666
687
  "bill-net-gbp": bill.net,
667
688
  "bill-vat-gbp": bill.vat,
689
+ "bill-gross-gbp": bill.gross,
668
690
  "bill-start-date": bill_start,
669
691
  "bill-finish-date": bill_finish,
670
692
  "imp-mpan-core": imp_mpan_core,
@@ -1,47 +1,64 @@
1
1
  {% extends "base.html" %}
2
2
 
3
3
  {% block title %}
4
- » General Imports » {{process_id}}
4
+ » General Imports » {{import_id}}
5
5
  {% endblock %}
6
6
 
7
7
  {% block nav %}
8
8
  <a href="/general_imports">General Imports</a> &raquo;
9
- {{process_id}}
9
+ {{import_id}}
10
10
  {% endblock %}
11
11
 
12
12
  {% block content %}
13
- {% if line_number %}
14
- <p>Line number {{line_number}}.</p>
13
+ {% if importer.line_number %}
14
+ <p>Line number {{importer.line_number}}.</p>
15
15
  {% endif %}
16
16
 
17
- {% if is_alive %}
17
+ {% if importer.is_alive() %}
18
18
  <p>Still running. Refresh the page to see latest progress.</p>
19
19
  {% else %}
20
- {% if error_message %}
21
- <p>
22
- The import has failed and so the whole import has been rolled
23
- back. The reason for the failure is:</p>
24
- <pre>{{error_message}}</pre>
20
+ {% if importer.failed_args|length > 0 %}
21
+ <p>
22
+ The import has failed and so the whole import has been rolled back.
23
+ </p>
24
+
25
+ <h3>Failed Lines</h3>
26
+
27
+ {% for line in importer.failed_args %}
28
+
29
+ <table>
30
+ <tbody>
31
+ <tr>
32
+ {% for title, value in line %}
33
+ <th>{{title}}</th>
34
+ {% endfor %}
35
+ </tr>
36
+ <tr>
37
+ {% for title, value in line %}
38
+ <td>{{value}}</td>
39
+ {% endfor %}
40
+ </tr>
41
+ </tbody>
42
+ </table>
43
+ {% endfor %}
44
+
45
+ <h3>Failed Input</h3>
46
+
47
+ <table>
48
+ <tbody>
49
+ {% for line in importer.failed_lines %}
50
+ <tr>
51
+ {% for value in line %}
52
+ <td>{{value}}</td>
53
+ {% endfor %}
54
+ </tr>
55
+ {% endfor %}
56
+ </tbody>
57
+ </table>
58
+ {% elif importer.error_message %}
59
+ <p>{{importer.error_message}}</p>
25
60
  {% else %}
26
- <p>The file has been imported successfully.</p>
61
+ <p>The file has been imported successfully.</p>
27
62
  {% endif %}
28
63
  {% endif %}
29
-
30
- {% if csv_line %}
31
- <table>
32
- <caption>Failed Line</caption>
33
- <tbody>
34
- <tr>
35
- {% for title, value in csv_line %}
36
- <th>{{title}}</th>
37
- {% endfor %}
38
- </tr>
39
- <tr>
40
- {% for title, value in csv_line %}
41
- <td>{{value}}</td>
42
- {% endfor %}
43
- </tr>
44
- </tbody>
45
- </table>
46
- {% endif %}
47
64
  {% endblock %}
chellow/views.py CHANGED
@@ -755,14 +755,13 @@ def general_imports_post():
755
755
  @home.route("/general_imports/<int:import_id>")
756
756
  def general_import_get(import_id):
757
757
  try:
758
- proc = chellow.general_import.get_process(import_id)
759
- fields = proc.get_fields()
760
- fields["is_alive"] = proc.is_alive()
761
- fields["process_id"] = import_id
762
- return render_template("general_import.html", **fields)
758
+ importer = chellow.general_import.get_process(import_id)
759
+ return render_template(
760
+ "general_import.html", import_id=import_id, importer=importer
761
+ )
763
762
  except BadRequest as e:
764
763
  flash(e.description)
765
- return render_template("general_import.html", process_id=import_id)
764
+ return render_template("general_import.html", import_id=import_id)
766
765
 
767
766
 
768
767
  @home.route("/edi_viewer")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chellow
3
- Version: 1731435800.0.0
3
+ Version: 1732281664.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)
@@ -4,7 +4,7 @@ chellow/bank_holidays.py,sha256=T_utYMwe_g1dz5X-aOTdIPryg49SvB7QsWM1yphlqG8,4423
4
4
  chellow/commands.py,sha256=ESBe9ZWj1c3vdZgqMZ9gFvYAB3hRag2R1PzOwuw9yFo,1302
5
5
  chellow/dloads.py,sha256=dixp-O0MF2_mlwrnKx3D9DH09Qu05BjTo0rZfigTjR4,5534
6
6
  chellow/edi_lib.py,sha256=alu20x9ZX06iPfnNI9dEJzuP6RIf4We3Y_M_bl7RrcY,51789
7
- chellow/general_import.py,sha256=Ia2Y40NEwqOYBHUwafJRcI34EO0WMX6FSBQJtGHeY0M,65874
7
+ chellow/general_import.py,sha256=tcYZK2N7HOFJSkYyy3MMxVBEvMFjfB9pjF0ksujtkFA,65113
8
8
  chellow/models.py,sha256=9LLROzS6gXZGICk0ITXhCyTtKaIY7HW4bMqWg4Mc-xw,244221
9
9
  chellow/national_grid.py,sha256=czwIZqzJndSGhEMQ5YzI6hRBhvjkM6VRVYXybf4_KXg,4377
10
10
  chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
@@ -12,7 +12,7 @@ chellow/rate_server.py,sha256=fg-Pf_9Hk3bXmC9riPQNGQxBvLvBa_WtNYdwDCjnCSg,5678
12
12
  chellow/rrun.py,sha256=1Kt2q_K9UoDG_nsZz-Q6XJiMNKroWqlqFdxn2M6Q8CA,2088
13
13
  chellow/testing.py,sha256=Od4HHH6pZrhJ_De118_F55RJEKmAvhUH2S24QE9qFQk,3635
14
14
  chellow/utils.py,sha256=32qPWEGzCPKPhSM7ztpzcR6ZG74sVZanScDIdK50Rq4,19308
15
- chellow/views.py,sha256=eb7WUqqu7LmAX5m_9ICJFVpo0i8WZ9GV89AkqRA3aac,84383
15
+ chellow/views.py,sha256=qJrvhVjb3KL_sHDQl5dLhi0aqUe_IUYhrjiPjdk4lQI,84317
16
16
  chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
18
18
  chellow/e/bill_importer.py,sha256=7UcnqNlKbJc2GhW9gy8sDp9GuqambJVpZLvbafOZztA,7411
@@ -75,7 +75,7 @@ chellow/gas/transportation.py,sha256=Bkg8TWOs-v0ES-4qqwbleiOhqbE_t2KauUx9JYMZELM
75
75
  chellow/gas/views.py,sha256=R4Ky8syioWSQJLTuSKVLsc266eDv8a6WEo_e60u_4ug,59021
76
76
  chellow/reports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
77
  chellow/reports/report_109.py,sha256=FmRWG8wQC97cj0nqQH7mrfbYesRIKWXQLh6ERHvtHrU,11212
78
- chellow/reports/report_111.py,sha256=rgwoOPfvbfwIC_IjBqs2e8umF_YTtpyejLrX_uCgyHE,28145
78
+ chellow/reports/report_111.py,sha256=MBXMABwHonjH2cvkqFYC0Vx7rU7LB2mJxXsEjI0RvTU,28828
79
79
  chellow/reports/report_169.py,sha256=tnTiHmhigcgZ7E8rUSfgzsVYUCW947xBZZq04-KqfK8,9287
80
80
  chellow/reports/report_181.py,sha256=mCL6vXfrj8r0kL-LilDS0SnSu5tJOzCq7eMJVx9zpEw,4999
81
81
  chellow/reports/report_183.py,sha256=DZX-hHJPl_Tbgkt31C_cuLZg_5L2b6iCPQ5foOZizR0,8817
@@ -121,7 +121,7 @@ chellow/templates/chain.html,sha256=iOnSoDQOO_-1tfcxUHQKDAUnV4QbCYu5PPNmS4RkOg4,
121
121
  chellow/templates/csv_sites_monthly_duration.html,sha256=59gErG6KwA57z-qh2EJsVGvTUazqm85CSXefSfqPWcQ,486
122
122
  chellow/templates/downloads.html,sha256=R9QPcFz-PLJOX7rDlmquIk-Hp9Iq-thzWCTfOexSpXg,937
123
123
  chellow/templates/edi_viewer.html,sha256=szUthgHOdph6Of-7f_1LeC_zYlNJaMeS5ctn6xTAeiM,1437
124
- chellow/templates/general_import.html,sha256=SMemHGu466Be3_cAWSS6Hn-Kv-1psbEMDD6NQG6bfbI,1013
124
+ chellow/templates/general_import.html,sha256=9ezzieDjaPBZ0nUJkMkzoDxWVzYtr4D-Dr2UCA5xV8U,1370
125
125
  chellow/templates/general_imports.html,sha256=VRmBqYsXsirm880WiFrJ3CknAXAoLR9Mnpz9cKjIeM8,13069
126
126
  chellow/templates/home.html,sha256=illtSabepcScYwmKss0o2gwvjXGBtr6LkfwmeL6ezSA,5655
127
127
  chellow/templates/input_date.html,sha256=rpgB5n0LfN8Y5djN_ZiuSxqdskxzCoKrEqI7hyJkVQo,1248
@@ -377,6 +377,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
377
377
  chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
378
378
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
379
379
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
380
- chellow-1731435800.0.0.dist-info/METADATA,sha256=ilPn6kcxryT74lMCin7HXAJqf48jbjfuyV1Y3qmf9dA,12204
381
- chellow-1731435800.0.0.dist-info/WHEEL,sha256=WJ9WQ4-pUYxfD_tEj5GvKSG9KSULNumqkTQdolV8mME,87
382
- chellow-1731435800.0.0.dist-info/RECORD,,
380
+ chellow-1732281664.0.0.dist-info/METADATA,sha256=6kGXaB73s2rZ4c_deiOhKUWc_n1lJjFA6vIJa_ToVYE,12204
381
+ chellow-1732281664.0.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
382
+ chellow-1732281664.0.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.26.2
2
+ Generator: hatchling 1.26.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any