Coverage for backend/django/Economics/costing/operating/resource_classification.py: 91%

43 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-07-22 05:22 +0000

1"""High-level resource classifications for persisted operating result lines.""" 

2 

3from __future__ import annotations 

4 

5from Economics.costing.operating.line_calculation import AnnualBasisQuantity 

6from Economics.costing.models import OperatingCostLine 

7from Economics.costing.operating.resource_basis import ( 

8 AnnualResourceQuantity, 

9 RESOURCE_CATEGORY_ANNUAL_COOLING_DUTY, 

10 RESOURCE_CATEGORY_ANNUAL_HEATING_DUTY, 

11 annual_resource_quantity, 

12 steam_fuel_energy_from_default_rate, 

13) 

14from Economics.shared.choices import DefaultRateType 

15 

16RESOURCE_CLASSIFICATION_ELECTRICITY = "electricity" 

17RESOURCE_CLASSIFICATION_NATURAL_GAS = "natural_gas" 

18RESOURCE_CLASSIFICATION_STEAM_ELECTRICITY = "steam_electricity" 

19RESOURCE_CLASSIFICATION_STEAM_NATURAL_GAS = "steam_natural_gas" 

20RESOURCE_CLASSIFICATION_HEATING_DUTY = "heating_duty" 

21RESOURCE_CLASSIFICATION_COOLING_DUTY = "cooling_duty" 

22RESOURCE_CLASSIFICATION_OTHER = "other" 

23 

24 

25def operating_resource_classification( 

26 *, 

27 line: OperatingCostLine, 

28 resource_category: str, 

29) -> str: 

30 """Classify an operating line for high-level resource metrics.""" 

31 if line.rate_type == DefaultRateType.ELECTRICITY: 

32 return RESOURCE_CLASSIFICATION_ELECTRICITY 

33 if line.rate_type == DefaultRateType.NATURAL_GAS: 

34 return RESOURCE_CLASSIFICATION_NATURAL_GAS 

35 if line.rate_type == DefaultRateType.STEAM: 

36 return _steam_resource_classification(line) 

37 if resource_category == RESOURCE_CATEGORY_ANNUAL_HEATING_DUTY: 

38 return RESOURCE_CLASSIFICATION_HEATING_DUTY 

39 if resource_category == RESOURCE_CATEGORY_ANNUAL_COOLING_DUTY: 

40 return RESOURCE_CLASSIFICATION_COOLING_DUTY 

41 return RESOURCE_CLASSIFICATION_OTHER 

42 

43 

44def operating_resource_metric_quantity( 

45 *, 

46 line: OperatingCostLine, 

47 classification: str, 

48 annual_basis: AnnualBasisQuantity | None, 

49) -> AnnualResourceQuantity | None: 

50 """Snapshot the annual resource quantity consumed by high-level metrics.""" 

51 if annual_basis is None: 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true

52 return None 

53 if classification in { 

54 RESOURCE_CLASSIFICATION_ELECTRICITY, 

55 RESOURCE_CLASSIFICATION_NATURAL_GAS, 

56 RESOURCE_CLASSIFICATION_HEATING_DUTY, 

57 RESOURCE_CLASSIFICATION_COOLING_DUTY, 

58 RESOURCE_CLASSIFICATION_OTHER, 

59 }: 

60 return annual_resource_quantity( 

61 annual_basis_quantity=annual_basis.quantity, 

62 annual_basis_unit=annual_basis.unit, 

63 ) 

64 if classification in { 64 ↛ 77line 64 didn't jump to line 77 because the condition on line 64 was always true

65 RESOURCE_CLASSIFICATION_STEAM_ELECTRICITY, 

66 RESOURCE_CLASSIFICATION_STEAM_NATURAL_GAS, 

67 }: 

68 fuel_energy = steam_fuel_energy_from_default_rate( 

69 annual_basis_quantity=annual_basis.quantity, 

70 annual_basis_unit=annual_basis.unit, 

71 source_default_rate=line.source_default_rate, 

72 target_unit="GJ/year", 

73 ) 

74 if fuel_energy is None: 74 ↛ 75line 74 didn't jump to line 75 because the condition on line 74 was never true

75 return None 

76 return AnnualResourceQuantity(quantity=fuel_energy, unit="GJ/year") 

77 return None 

78 

79 

80def _steam_resource_classification(line: OperatingCostLine) -> str: 

81 source_default_rate = line.source_default_rate 

82 source_key = source_default_rate.key if source_default_rate is not None else "" 

83 if source_key.startswith("steam_electric_"): 

84 return RESOURCE_CLASSIFICATION_STEAM_ELECTRICITY 

85 if source_key.startswith("steam_natural_gas_"): 

86 return RESOURCE_CLASSIFICATION_STEAM_NATURAL_GAS 

87 return RESOURCE_CLASSIFICATION_OTHER