Api reference
components.price_provider.public.api ¶
InsuranceCostProviderService ¶
Computing insurance costs.
get_insurance_cost
staticmethod
¶
get_insurance_cost(
*,
on_date: date,
policy_id: UUID | int,
contract_identifier: None = None,
rounding_strategy: RoundingStrategy = RoundingStrategy.ARITHMETIC
) -> InsuranceCost
get_insurance_cost(
*,
on_date,
policy_id=None,
contract_identifier=None,
beneficiary_specs=None,
rounding_strategy=RoundingStrategy.ARITHMETIC
)
Compute insurance costs.
This insurance costs are evaluated based on
- all coverage modules active on the given date, and the corresponding price grids
- all beneficiaries active on the given date
- all discounts active on the given date
When evaluating costs for a policy, if several coverage modules are active, the costs returned contain the aggregated cost breakdowns of all the coverage modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_date
|
date
|
The reference date for coverage and affiliation data. |
required |
policy_id
|
UUID | int | None
|
The unique identifier of the policy to compute costs for. Must be provided if contract_identifier is None. |
None
|
contract_identifier
|
ContractIdentifier | None
|
The contract identifier to compute costs for. Must be provided if policy_id is None. Currently not implemented. |
None
|
beneficiary_specs
|
Sequence[BeneficiarySpec] | None
|
Optional list of beneficiary specifications to use instead of the policy's current beneficiaries. When provided with policy_id, uses these beneficiaries with the policy's price grids. |
None
|
rounding_strategy
|
RoundingStrategy
|
Strategy for rounding monetary amounts when splitting costs between entities. Defaults to arithmetic rounding. |
ARITHMETIC
|
Returns:
| Type | Description |
|---|---|
InsuranceCost
|
An InsuranceCost object containing a detailed cost breakdown for 30 days of |
InsuranceCost
|
coverage. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither policy_id nor contract_identifier |
ValueError
|
If no price grids are found for the policy on this date |
NotImplementedError
|
If contract_identifier is used (not yet supported). |
Examples:
# Use the beneficiary information corresponding to the state of the policy
# at the date of on_date.
# Use the price grid active on the policy's contract at the date of on_date
InsuranceCostProviderService.get_insurance_costs(policy_id=policy_id, on_date=on_date)
# Use an arbitrary list of beneficiaries.
# Use the price grid active on the policy's contract at the date of on_date
InsuranceCostProviderService.get_insurance_costs(
beneficiarySpec=[BeneficiarySpec(...), BeneficiarySpec(...)]
policy_id=policy_id,
on_date=on_date
)
Source code in components/price_provider/public/api.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
components.price_provider.public.dependencies ¶
COMPONENT_NAME
module-attribute
¶
Canonical name of the price provider component.
PriceProviderDependency ¶
Bases: ABC
Dependencies injected into the price provider component. Every component depending on the price provider component is responsible for injecting its own implementation of these dependencies.
get_beneficiary_specs_from_policy
abstractmethod
¶
Retrieve the beneficiary specifications for a given policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy_id
|
int | UUID
|
The unique identifier of the policy. |
required |
on_date
|
date
|
The date for which to retrieve beneficiary specifications. |
required |
Returns:
| Type | Description |
|---|---|
Sequence[BeneficiarySpec]
|
A list of beneficiary specifications containing the beneficiary type, |
Sequence[BeneficiarySpec]
|
age, and other characteristics relevant for pricing calculations. |
Source code in components/price_provider/public/dependencies.py
get_pricing_scheme_for_policy
abstractmethod
¶
Retrieve the pricing scheme and price grid descriptor for a given policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
policy_id
|
int | UUID
|
The unique identifier of the policy. |
required |
on_date
|
date
|
The date for which to retrieve the pricing information. |
required |
Returns:
| Type | Description |
|---|---|
PricingScheme
|
A tuple containing: |
Sequence[PriceGridDescriptor]
|
|
tuple[PricingScheme, Sequence[PriceGridDescriptor]]
|
|
Source code in components/price_provider/public/dependencies.py
get_app_dependency ¶
Function used to fetch the dependencies from the flask app.
Source code in components/price_provider/public/dependencies.py
set_app_dependency ¶
Function used to actually inject the dependency class in the component.
Source code in components/price_provider/public/dependencies.py
components.price_provider.public.entities ¶
PriceGridDescriptor ¶
Bases: Protocol
Identifies which specific price grid to use for cost calculations.
At the moment, price grid have very local implementations and it is complicated to find a common global abstraction. Because the differences are so strong and we don't yet have the correct mental model in place, this protocol voluntarily very shallow. All we impose is that there is a class returning the ID of the entity to use to access price. For the moment, local implementations are responsible for coping with the complexity.
In France, it will be the ID of a PriceGrid. In Belgium, it will be the ID of a HealthSubscriptionPayload.
🇧🇪 Belgium Structure: Plan → Coverage Modules → Price Grids → Age-based Rules - 1 plan has many coverage modules - 1 coverage module has one price grid - 1 price grid has many age-based rules - Different beneficiaries can be on different coverage modules - Enrollment.coverage_module_name routes to the correct coverage module - Options are separate coverage modules (base + option modules coexist)
Belgian beneficiaries from the same policy can be on different coverage modules
Each beneficiary on a different coverage module implies they can be a on different grid. Pricing an entire policy using a single grid is not guaranteed to work !
🇫🇷 France Structure: Plan → Coverage Modules → Price Grids → Age-based Rules - 1 plan has many coverage modules (1 base + N options) - 1 coverage module can have up to 2 price grids: * Base modules: standard grid + optional Alsace-Moselle grid * Option modules: only standard grid - All beneficiaries always use the same coverage module - Policy with options = multiple active modules simultaneously (base + options) - Pricing entire policy = price multiple grids and merge results
French policies may have several active coverage modules at once
If a policy has an option, there are two coverage modules: 1 for the base and 1 for the option. The implication is that to retrieve the entire costs for a policy, we need to price two on two grids.
🇪🇸 Spain Structure: Hardcoded Product Types → Static Pricing Tables - No traditional grid system - uses hardcoded pricing matrices ?
🇨🇦 Canada Structure: Contract → Health Plan → Price Grid - Each contract has its own plan and price grid - Ultra-simple: only single_price_in_cents vs family_price_in_cents - No age-based rules, no options, no modules - Only 2 coverage types available (bear, marmot)
unique_identifier
property
¶
ID of the object to fetch in order to resolves prices. In Belgium, it is the ID of HealthSubscriptionPayload as it gives us access to: - all coverage modules and their associated price grids - participation data
PricingScheme ¶
Bases: Protocol
Encapsulates price grids and price rules. Local implementations are responsible for bringing their own PricingScheme and PriceGridDescriptor.
computed_cost_for_beneficiaries ¶
computed_cost_for_beneficiaries(
on_date,
beneficiary_specs,
price_grid_descriptor,
rounding_strategy=RoundingStrategy.ARITHMETIC,
)
Compute monthly insurance costs for beneficiaries according to the grid pointed to by the descriptor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_date
|
date
|
Date for which we are projecting costs. The date is relevant because some discounts are date-based, and some grids have prices depending on the age of the beneficiary. |
required |
beneficiary_specs
|
Sequence[BeneficiarySpec]
|
A description of beneficiaries with emphasis on the characteristics relevant to pricing, |
required |
price_grid_descriptor
|
PriceGridDescriptor
|
A vague object pointing to a concrete price grid. |
required |
rounding_strategy
|
RoundingStrategy
|
Strategy for rounding monetary amounts when splitting costs between various entities. |
ARITHMETIC
|
Returns:
| Type | Description |
|---|---|
InsuranceCost
|
Insurance costs. |
Source code in components/price_provider/public/entities.py
RoundingStrategy ¶
Bases: AlanBaseEnum
Strategy for rounding monetary amounts.
components.price_provider.public.insurance_entities ¶
BeneficiarySpec ¶
Currencies ¶
Common currencies supported by this component.
EUR
class-attribute
instance-attribute
¶
from_alphabetic_code
classmethod
¶
Get a Currency instance by its ISO4217 alphabetic code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
The ISO4217 alphabetic code (e.g., "EUR") |
required |
Returns:
| Type | Description |
|---|---|
Currency
|
The Currency instance matching the code |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the currency code is not supported |
Examples:
Source code in components/price_provider/public/insurance_entities.py
Currency
dataclass
¶
Represents a currency. Attempting to comply with ISO4217.
format_amount ¶
Format an amount in minor units as a string with currency code.
Examples:
Source code in components/price_provider/public/insurance_entities.py
from_minor_unit ¶
Convert from integer representation of the currency to a decimal representation.
Examples:
Source code in components/price_provider/public/insurance_entities.py
minor_unit
instance-attribute
¶
The number of digits after the decimal separator to represent as the minor unit. Helps us represent amounts as integers instead of floats, for example representing euros as cents.
Certain currenceis are naturally representable as ints and have 0 digits after the decimal place.
Examples: Japanese yen, South Korean won
to_minor_unit ¶
Convert from floating point representation of the currency to an integer representation.
Useful to avoid precision errors of large floats.
Examples:
integer_representation = Currencies.EUR.to_minor_unit(10.32)
print(integer_representation) # 1032 cents
Source code in components/price_provider/public/insurance_entities.py
InsuranceBeneficiary ¶
Bases: AlanBaseEnum
Represents the different types of insurance beneficiaries.
from_enrollment_type
classmethod
¶
Convert EnrollmentType to InsuranceBeneficiary.
Source code in components/price_provider/public/insurance_entities.py
to_enrollment_type ¶
Convert InsuranceBeneficiary to EnrollmentType.
Source code in components/price_provider/public/insurance_entities.py
InsuranceBilledEntity ¶
InsuranceCollectionMethod ¶
Bases: AlanBaseEnum
Methods for collecting an employee's participation.
InsuranceContribution ¶
Bases: AlanBaseEnum
Represents how an amount is used, what the money is going towards.
InsuranceCost
dataclass
¶
Represents the entire cost of an insurance service.
No safeties on cost components
There are no checks verifying there are no duplicates in components. The caller is responsible for ensuring the components represent a valid cost breakdown.
Source code in components/price_provider/public/insurance_entities.py
__setattr__ ¶
Setting attributes once the dataclass is initialized is forbidden. Reproducing the behavior of frozen=True.
Source code in components/price_provider/public/insurance_entities.py
from_components
staticmethod
¶
Construct an InsuranceCost from several cost components.
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
if the billed entity is not implemented yet |
ValueError
|
if the currency used by all the components is not the same |
Source code in components/price_provider/public/insurance_entities.py
merge
staticmethod
¶
Merge several costs into the same cost objects.
When we evaluate the costs of coverage modules individually, merging them is useful to get the total aggregated costs.
Source code in components/price_provider/public/insurance_entities.py
monthly_taxed_amount_billed_to_company
instance-attribute
¶
monthly_taxed_amount_billed_to_primary
instance-attribute
¶
monthly_untaxed_amount_billed_to_company
instance-attribute
¶
monthly_untaxed_amount_billed_to_primary
instance-attribute
¶
InsuranceCostComponent
dataclass
¶
InsuranceCostComponent(
*,
service_type,
contribution_type,
beneficiary_type,
billed_entity,
collection_method=None,
enrollment_id=None,
currency,
monthly_amount
)
Represents part of a cost of insurance service.
__post_init__ ¶
Validate that collection method is set when billed entity is not company.
Source code in components/price_provider/public/insurance_entities.py
beneficiary_type
instance-attribute
¶
Who's coverage does this cost correspond to ?
collection_method
class-attribute
instance-attribute
¶
If an employee is responsible for paying this cost, how is the payment collected ?
compare_component_lists
staticmethod
¶
Compare two lists of insurance cost components for equality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
list[InsuranceCostComponent]
|
First list of components to compare |
required |
right
|
list[InsuranceCostComponent]
|
Second list of components to compare |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if both lists contain the same components in any order, False otherwise |
Source code in components/price_provider/public/insurance_entities.py
contribution_type
instance-attribute
¶
What part of the service is paid for by this cost?
enrollment_id
class-attribute
instance-attribute
¶
An optional enrollment ID, in case the component corresponds to an enrolled member. It would typically be set when computing the prices for an existing policy. It would be None when a member projects the cost of adding their partner to their policy.
group_by_beneficiary_id
staticmethod
¶
Groups insurance cost components by enrollment ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
components
|
list[InsuranceCostComponent]
|
List of InsuranceCostComponent to group |
required |
Returns:
| Type | Description |
|---|---|
dict[int | UUID, list[InsuranceCostComponent]]
|
Dictionary mapping enrollment ID (int or UUID) to list of components |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any component does not have an enrollment ID |
Source code in components/price_provider/public/insurance_entities.py
monthly_amount
instance-attribute
¶
The amount for a month of service, independantly of the month's duration.
Can be negative, for example if the amount corresponds to a discount. Must be expressed in the minor unit of the chosen currency.
service_type
instance-attribute
¶
What insurance service does this cost correspond to ?