Coverage for backend/django/Economics/costing/operating/unit_options.py: 73%
36 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
1from django.core.exceptions import ObjectDoesNotExist
3from core.auxiliary.enums.unitsOfMeasure import UnitOfMeasure
4from Economics.shared.choices import OperatingLineCategory
5from Economics.shared.unit_options import (
6 MAINTENANCE_RATE_UNIT,
7 MAINTENANCE_RATE_UNIT_OPTIONS,
8 UnitOption,
9 infer_physical_unit_type,
10 price_denominator_units,
11 price_unit_options_for_rate_unit as shared_price_unit_options_for_rate_unit,
12 registry_unit_values,
13 unit_options_for_unit_type,
14 with_current_unit,
15)
18ANNUAL_HEAT_BASIS_UNIT_OPTIONS: tuple[UnitOption, ...] = tuple(
19 {"value": f"{unit}/year", "label": f"{unit}/year"}
20 for unit in ("MWh", "kWh", "GJ")
21 if unit in set(registry_unit_values(UnitOfMeasure.energy)) | price_denominator_units(UnitOfMeasure.powerPrice)
22)
23ANNUAL_MASS_BASIS_UNIT_OPTIONS: tuple[UnitOption, ...] = tuple(
24 {"value": f"{unit}/year", "label": f"{unit}/year"}
25 for unit in ("kg", "g", "t", "lb")
26 if unit in set(registry_unit_values(UnitOfMeasure.mass))
27)
28def operating_basis_unit_options(line) -> list[UnitOption]:
29 unit_type = _source_property_unit_type(line)
30 if unit_type:
31 return with_current_unit(unit_options_for_unit_type(unit_type), line.basis_unit)
33 current = (line.basis_unit or "").strip()
34 if current in {option["value"] for option in ANNUAL_HEAT_BASIS_UNIT_OPTIONS}: 34 ↛ 35line 34 didn't jump to line 35 because the condition on line 34 was never true
35 return with_current_unit(ANNUAL_HEAT_BASIS_UNIT_OPTIONS, current)
36 if current in {option["value"] for option in ANNUAL_MASS_BASIS_UNIT_OPTIONS}:
37 return with_current_unit(ANNUAL_MASS_BASIS_UNIT_OPTIONS, current)
39 inferred_type = infer_physical_unit_type(current)
40 if inferred_type: 40 ↛ 42line 40 didn't jump to line 42 because the condition on line 40 was always true
41 return with_current_unit(unit_options_for_unit_type(inferred_type), current)
42 if line.category == OperatingLineCategory.ENERGY:
43 return with_current_unit(unit_options_for_unit_type(UnitOfMeasure.heatflow), current)
44 if line.category in {
45 OperatingLineCategory.FEEDSTOCK,
46 OperatingLineCategory.OUTPUT_REVENUE,
47 OperatingLineCategory.DISPOSAL,
48 }:
49 return with_current_unit(ANNUAL_MASS_BASIS_UNIT_OPTIONS, current)
50 return with_current_unit([], current)
53def operating_rate_unit_options(line) -> list[UnitOption]:
54 if line.category == OperatingLineCategory.MAINTENANCE: 54 ↛ 55line 54 didn't jump to line 55 because the condition on line 54 was never true
55 return with_current_unit(MAINTENANCE_RATE_UNIT_OPTIONS, line.rate_unit)
56 return price_unit_options_for_rate_unit(
57 line.rate_unit,
58 currency=(line.currency or "NZD"),
59 source_basis_unit=line.basis_unit,
60 category=line.category,
61 )
64def price_unit_options_for_rate_unit(
65 rate_unit: str,
66 *,
67 currency: str = "NZD",
68 source_basis_unit: str = "",
69 category: str = "",
70) -> list[UnitOption]:
71 return shared_price_unit_options_for_rate_unit(
72 rate_unit,
73 currency=currency,
74 source_basis_unit=source_basis_unit,
75 fixed_annual=category == OperatingLineCategory.FIXED_ANNUAL,
76 )
79def _source_property_unit_type(line) -> str:
80 try:
81 source_property = line.source_property_info
82 except (AttributeError, ObjectDoesNotExist): # pragma: no cover - defensive for partial model-like objects
83 return ""
84 unit_type = getattr(source_property, "unitType", "")
85 if unit_type in ("", UnitOfMeasure.none, UnitOfMeasure.unknown):
86 return ""
87 return str(unit_type)