Utility Specific Calculation
Overview
This document explains the architecture of the utility billing calculation system, focusing on how the BaseCalculatorComponent
class serves as a foundation that is extended by utility-specific implementations in the UtilitySpecificCalculation
class.
BaseCalculatorComponent
The BaseCalculatorComponent
provides a reusable foundation for utility billing calculations with standardized methods for:
- Base charge calculations - Computing the fundamental usage charges
- Variable rate handling - Supporting tiered pricing, time-of-use rates, and fixed rates
- Extra charge calculations - Managing additional fees, taxes, and service charges
This design follows the Template Method pattern, where the base class defines the skeleton of operations while allowing subclasses to override specific steps without changing the overall algorithm structure.
Component Hierarchy
BaseCalculatorComponent
↑
|
UtilitySpecificCalculation
|
├── RoshanCalculatorComponent
├── SamoaCalculatorComponent
└── AxisCalculatorComponent
Extension Mechanism
UtilitySpecificCalculation
This class acts as a factory that creates and manages calculator components for different utilities:
def __init__(self, plan_data):
self.plan_data = plan_data
self.calculation_functions_for_utilities = {
"Roshan Energy": self.RoshanCalculatorComponent(self.plan_data),
"Samoa Water Utility": self.SamoaCalculatorComponent(self.plan_data),
"Axis Meter Solution": self.AxisCalculatorComponent(self.plan_data),
"Default Calculator Utility": {
"samoa": self.SamoaCalculatorComponent(self.plan_data),
"roshan": self.RoshanCalculatorComponent(self.plan_data),
"axis": self.AxisCalculatorComponent(self.plan_data)
}
}
Each utility implementation extends BaseCalculatorComponent
while adding utility-specific logic.
Detailed Extension Analysis
Common Inheritance Pattern
Each utility-specific component follows the same pattern:
- Initialize with a reference to the outer instance (for access to plan data)
- Override the
base_calculator
method to customize the calculation flow - Add utility-specific methods for specialized charge calculations
Roshan Energy Implementation
The Roshan implementation adds specialized handling for:
- Water service charges with waste water calculations
- Electric service with delivery rates and state regulatory fees
- Discount calculations specific to their billing model
Samoa Water Utility Implementation
This implementation relies entirely on the base component's calculations without adding extra logic.
Axis Meter Solution Implementation
The Axis implementation specializes in:
- Electric-specific charges including regulatory and delivery charges
- Ontario Electricity Rebate calculations
- Late payment charge calculations based on balance and payment
Key Extension Points
1. Rate Type Handling
The base component supports three main rate types:
- FIXED - A constant charge regardless of consumption
- VARIABLE - Further divided into:
- Time of Use - Different rates based on time periods
- Tiered - Different rates based on consumption thresholds
Utility-specific implementations can customize how these are applied.
2. Extra Charge Calculation
The _calculate_extra_charges
method is a primary extension point where each utility adds:
- Service-specific fees
- Regulatory charges
- Delivery fees
- Discounts and rebates
3. Late Charge Calculation
The calculate_late_charges
method provides utility-specific late payment handling.
Calculation Flow
- Base charge calculation for all meters
- Utility-specific extra charge calculation
- Service-specific charges (Water, Electricity)
- Meter-specific charges
- Common extra charges applicable to all services
- Late charge calculation (if applicable)
Benefits of This Architecture
- Code Reuse - Common calculation logic is defined once in the base component
- Extensibility - New utilities can be added by creating a new component class
- Consistency - All utilities follow the same calculation structure
- Maintainability - Changes to the base calculation logic are automatically inherited by all utilities
Adding a New Utility Calculator Component
To extend the system with a new utility billing calculator, follow these steps:
- Create a new component class
- Define a new nested class within the
UtilitySpecificCalculation
class - Inherit from
BaseCalculatorComponent
- Implement the
__init__
method with a reference to the outer instance
- Define a new nested class within the
- Implement required methods
- Override the
base_calculator
method to implement the main calculation flow - Call the parent
base_calculator
method to leverage the existing logic - Add utility-specific extra charge calculations
- Override the
- Add specialized methods
- Implement service-specific methods (e.g., for water or electricity)
- Override the
_calculate_extra_charges
method for custom fees - If needed, implement
calculate_late_charges
for custom late payment handling
- Register the new calculator
- Add the new calculator to the
calculation_functions_for_utilities
dictionary in theUtilitySpecificCalculation
constructor - Use the utility name as the key and an instance of your new calculator as the value
- Add a reference in the "Default Calculator Utility" dictionary if applicable
- Add the new calculator to the
- Implement utility-specific business logic
- Add methods for service-specific calculations
- Ensure all required charges are computed and added to the bill JSON
- Follow the established patterns for consistency
- Test thoroughly
- Verify that calculations work with different rate types
- Ensure all required charges are included
- Check that rounding is handled correctly
Conclusion
The BaseCalculatorComponent
provides a flexible foundation for utility billing calculations that can be extended to accommodate the specific billing requirements of different utility providers. The inheritance-based design enables code reuse while allowing for customization where needed, creating a maintainable and extensible billing system.
No Comments