Api reference
components.core_price.public.api ¶
PricingService ¶
Service for computing price breakdowns.
get_breakdown
staticmethod
¶
get_breakdown(
*,
on_date: date,
pricing_source: PricingSource,
contract_identifier: None = None,
rounding_strategy: RoundingStrategy = RoundingStrategy.ARITHMETIC
) -> PriceBreakdown
get_breakdown(
*,
on_date: date,
pricing_source: None = None,
contract_identifier: ContractIdentifier,
rounding_strategy: RoundingStrategy = RoundingStrategy.ARITHMETIC
) -> PriceBreakdown
get_breakdown(
*,
on_date,
pricing_source=None,
contract_identifier=None,
member_specs=None,
additional_member_specs=None,
rounding_strategy=RoundingStrategy.ARITHMETIC
)
Compute a price breakdown.
This price breakdown is evaluated based on
- all coverage modules active on the given date
- all beneficiaries active on the given date
- all discounts active on the given date
When evaluating prices for a policy, if several coverage modules are active, the breakdown contains the aggregated price components of all the coverage modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_date
|
date
|
The reference date for coverage and affiliation data. |
required |
pricing_source
|
PricingSource | None
|
Abstract identifier for pricing resolution (policy_id, enrollment_id, etc.). Must be provided if contract_identifier is None. |
None
|
contract_identifier
|
ContractIdentifier | None
|
The contract identifier to compute prices for. Must be provided if pricing_source is None. Currently not implemented. |
None
|
member_specs
|
Sequence[MemberSpec] | None
|
Optional list of enrollment specs to use instead of the source's current beneficiaries. When provided with pricing_source, uses these beneficiaries with the source's pricing function. |
None
|
additional_member_specs
|
Sequence[MemberSpec] | None
|
Optional list of specs to append to the source's existing beneficiaries. Resolves current members from pricing_source, then appends these specs before computing. Useful for simulating adding a new dependent to an existing policy. |
None
|
rounding_strategy
|
RoundingStrategy
|
Strategy for rounding monetary amounts when splitting prices between entities. Defaults to arithmetic rounding. |
ARITHMETIC
|
Returns:
| Type | Description |
|---|---|
PriceBreakdown
|
A PriceBreakdown containing detailed price breakdown for 30 days of coverage. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither pricing_source nor contract_identifier is provided. |
ValueError
|
If both member_specs and additional_member_specs are provided. |
ValueError
|
If no price breakdown is found for the source on this date. |
NotImplementedError
|
If contract_identifier is used (not yet supported). |
Examples:
# Use the beneficiary information corresponding to the state of the source
# at the date of on_date.
PricingService.get_breakdown(
pricing_source=PolicyPricingSource(policy_id), on_date=on_date
)
# Use an arbitrary list of beneficiaries.
PricingService.get_breakdown(
member_specs=[
MemberSpec(...),
MemberSpec(...),
],
pricing_source=PolicyPricingSource(policy_id),
on_date=on_date,
)
# Simulate adding a new member to an existing policy.
PricingService.get_breakdown(
additional_member_specs=[MemberSpec(...)],
pricing_source=PolicyPricingSource(policy_id),
on_date=on_date,
)
Source code in components/core_price/public/api.py
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 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | |
components.core_price.public.dependencies ¶
COMPONENT_NAME
module-attribute
¶
Canonical name of the core price component.
CorePriceDependency ¶
Bases: ABC
Dependencies injected into the core price component.
Every component depending on the core price component is responsible for injecting its own implementation of these dependencies.
get_price_breakdown
abstractmethod
¶
Compute price breakdown.
Implementation handles module -> PricingFunction resolution internally using pricing_context.pricing_source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pricing_context
|
PricingContext
|
Inputs required to compute prices, including pricing_source, date, beneficiaries, and rounding strategy. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
PriceBreakdown |
PriceBreakdown
|
A price breakdown with price components. |
Source code in components/core_price/public/dependencies.py
resolve_pricing_context
abstractmethod
¶
Resolve a pricing context from a pricing source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pricing_source
|
PricingSource
|
Abstract identifier (policy_id, enrollment_id, etc.) |
required |
on_date
|
date
|
The date for which to resolve the context. |
required |
Returns:
| Type | Description |
|---|---|
PricingContext
|
A complete PricingContext with source, date, enrollment specs, |
PricingContext
|
and implementation-specific rounding strategy. |
Source code in components/core_price/public/dependencies.py
get_app_dependency ¶
Function used to fetch the dependencies from the flask app.
Source code in components/core_price/public/dependencies.py
set_app_dependency ¶
Function used to actually inject the dependency class in the component.
Source code in components/core_price/public/dependencies.py
components.core_price.public.entities ¶
Pricing API domain entities.
These types define the pricing-domain shapes used at component boundaries.
Consumers should prefer local domain equivalents and map at adapters. For shared
technical primitives (currency, rounding strategy), import from
components.core_price.public.primitives.
Note: Entities are defined in internal and re-exported here for external consumers.
CollectionMethod ¶
Bases: AlanBaseEnum
Methods for collecting a member's contribution.
direct_billing
class-attribute
instance-attribute
¶
The amount is paid directly by the employee or their partner, using the payment method of their choice.
flexben_fund
class-attribute
instance-attribute
¶
The amount is paid from the employee's flexben fund.
payroll
class-attribute
instance-attribute
¶
The amount is paid by the company but automatically deducted from the employee's payslip.
ContributionType ¶
Bases: AlanBaseEnum
Represents how an amount is used, what the money is going towards.
Debtor ¶
MemberSpec ¶
MemberType ¶
Bases: AlanBaseEnum
Represents the different member types.
from_enrollment_type
classmethod
¶
Convert EnrollmentType to member type.
Source code in components/core_price/internal/entities.py
to_enrollment_type ¶
Convert member type to EnrollmentType.
Source code in components/core_price/internal/entities.py
Module ¶
PolicyPricingSource
dataclass
¶
Resolve pricing from a policy_id directly.
PriceBreakdown
dataclass
¶
Represents the full price breakdown.
No safeties on price components
There are no checks verifying there are no duplicates in components. The caller is responsible for ensuring the components represent a valid price breakdown.
Source code in components/core_price/internal/entities.py
__setattr__ ¶
Setting attributes once the dataclass is initialized is forbidden. Reproducing the behavior of frozen=True.
Source code in components/core_price/internal/entities.py
for_member ¶
Return a new PriceBreakdown containing only components for the given member.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
member_id
|
int | UUID | None
|
The enrollment_id identifying the member. Use None for simulated (not-yet-enrolled) members. |
required |
Source code in components/core_price/internal/entities.py
from_components
staticmethod
¶
Construct a PriceBreakdown from several price 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/core_price/internal/entities.py
merge
staticmethod
¶
Merge several price breakdowns into a single one.
When we evaluate the prices of coverage modules individually, merging them is useful to get the total aggregated prices.
Source code in components/core_price/internal/entities.py
taxed_amount_billed_to_company
instance-attribute
¶
taxed_amount_billed_to_primary
instance-attribute
¶
untaxed_amount_billed_to_company
instance-attribute
¶
untaxed_amount_billed_to_primary
instance-attribute
¶
PriceComponent
dataclass
¶
PriceComponent(
*,
service_type,
contribution_type,
beneficiary_type,
debtor,
collection_method=None,
enrollment_id=None,
currency,
amount,
periodicity="monthly"
)
Represents part of a price.
__post_init__ ¶
Validate that collection method is set when billed entity is not company.
Source code in components/core_price/internal/entities.py
amount
instance-attribute
¶
The amount for an entire period of service.
Can be negative, for example if the amount corresponds to a discount. Must be expressed in the minor unit of the chosen currency.
collection_method
class-attribute
instance-attribute
¶
If a member is responsible for paying, how is the payment collected?
compare_component_lists
staticmethod
¶
Compare two lists of price components for equality.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
list[PriceComponent]
|
First list of components to compare |
required |
right
|
list[PriceComponent]
|
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/core_price/internal/entities.py
contribution_type
instance-attribute
¶
What part of the price does this component correspond to?
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 price of adding their partner to their policy.
group_by_beneficiary_id
staticmethod
¶
Groups price components by enrollment ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
components
|
list[PriceComponent]
|
List of PriceComponent to group |
required |
Returns:
| Type | Description |
|---|---|
dict[int | UUID, list[PriceComponent]]
|
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/core_price/internal/entities.py
PricingContext
dataclass
¶
Shared inputs required to compute a price breakdown.
primary_spec
property
¶
Return the primary member spec.
Uses first instead of one because the BE coverage upgrade flow
can inject a simulated primary spec (with enrollment_id=None) via
additional_member_specs, resulting in 2 primaries in the list.
Real specs always come first (api.py merges policy specs before additional ones).
TODO @cfollet: revert to one once upgrade flow uses dedicated pricing endpoint.
PricingFunction ¶
Bases: Protocol
Encapsulates price rules. Local implementations are responsible for bringing their own pricing function implementation and resolving pricing sources internally.
get_price_breakdown ¶
Compute monthly prices for beneficiaries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pricing_context
|
PricingContext
|
Inputs required to compute prices, including date, beneficiaries, and rounding strategy. |
required |
Returns:
| Type | Description |
|---|---|
PriceBreakdown
|
Price breakdown. |
Source code in components/core_price/internal/entities.py
PricingSource
module-attribute
¶
Abstract identifier for pricing resolution.
components.core_price.public.primitives ¶
Shared primitives for pricing.
These are stable, cross-component technical types (currency, rounding strategy, etc.). It is OK to import these broadly.
Currencies ¶
Common currencies supported by this component.
EUR
class-attribute
instance-attribute
¶
EUR = Currency(
alphabetic_code="EUR",
numeric_code=978,
minor_unit=2,
symbol="€",
locale_formats={
"fr": LocaleFormat(
decimal_separator=",",
thousands_separator="\u202f",
display_format="{amount}\xa0{symbol}",
negative_sign_position="before_number",
),
"nl": LocaleFormat(
decimal_separator=",",
thousands_separator=".",
display_format="{symbol}\xa0{amount}",
negative_sign_position="after_symbol",
),
"en": LocaleFormat(
decimal_separator=".",
thousands_separator=",",
display_format="{symbol}{amount}",
negative_sign_position="before_symbol",
),
},
)
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/core_price/public/primitives.py
Currency
dataclass
¶
Represents a currency. Attempting to comply with ISO4217.
__hash__ ¶
Hash the currency using its alphabetic code.
The alphabetic code (e.g., "EUR", "USD") uniquely identifies each currency according to ISO4217 standards, making it the ideal hash key.
Source code in components/core_price/public/primitives.py
format_amount ¶
Format an amount in minor units as a string with currency code.
Examples:
Source code in components/core_price/public/primitives.py
format_amount_with_symbol ¶
Format an amount in minor units with currency symbol for display.
Trailing zeros after the decimal point are removed unless needed. The formatting respects the currency's ISO 4217 minor unit specification. Negative amounts are formatted according to locale-specific conventions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amount
|
int
|
The amount in minor units (e.g., cents for EUR) |
required |
locale
|
str
|
The locale to use for formatting ("fr", "nl", or "en") |
required |
Returns:
| Type | Description |
|---|---|
str
|
Formatted string with locale-specific symbol position and |
str
|
separators |
Examples:
# French locale: symbol after with space, comma as decimal, thin
# space as thousands
formatted = Currencies.EUR.format_amount_with_symbol(12020, "fr")
print(formatted) # "120,20 €"
formatted = Currencies.EUR.format_amount_with_symbol(10000, "fr")
print(formatted) # "100 €"
formatted = Currencies.EUR.format_amount_with_symbol(-12020, "fr")
print(formatted) # "-120,20 €"
# English locale: symbol before no space, dot as decimal, comma as
# thousands
formatted = Currencies.EUR.format_amount_with_symbol(12020, "en")
print(formatted) # "€120.20"
formatted = Currencies.EUR.format_amount_with_symbol(-12020, "en")
print(formatted) # "-€120.20"
# Dutch locale: symbol before with space, comma as decimal, dot as
# thousands
formatted = Currencies.EUR.format_amount_with_symbol(12020, "nl")
print(formatted) # "€ 120,20"
formatted = Currencies.EUR.format_amount_with_symbol(-12020, "nl")
print(formatted) # "€ -120,20"
formatted = Currencies.EUR.format_amount_with_symbol(
12345678900, "fr"
)
print(formatted) # "123 456 789 €"
Source code in components/core_price/public/primitives.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
from_minor_unit ¶
Convert from integer representation of the currency to a decimal representation.
Examples:
Source code in components/core_price/public/primitives.py
locale_formats
instance-attribute
¶
Locale-specific formatting configuration for displaying amounts.
Examples:
- "fr": LocaleFormat(decimal=",", thousands=" ", format="{amount} {symbol}") produces "123 456,78 €"
- "nl": LocaleFormat(decimal=",", thousands=".", format="{symbol} {amount}") produces "€ 123.456,78"
- "en": LocaleFormat(decimal=".", thousands=",", format="{symbol}{amount}") produces "€123,456.78"
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/core_price/public/primitives.py
LocaleFormat
dataclass
¶
Configuration for locale-specific number and currency formatting.
decimal_separator
instance-attribute
¶
Character used as decimal separator (e.g., "." or ",")
display_format
instance-attribute
¶
Template for displaying amount with symbol. Should contain {amount} and {symbol} placeholders. Example: "{amount} {symbol}" or "{symbol}{amount}"
negative_sign_position
instance-attribute
¶
Where to place the minus sign for negative amounts.
Examples:
- "before_symbol": -€120.20 (English)
- "after_symbol": € -120,20 (Dutch)
- "before_number": -120,20 € (French)
thousands_separator
instance-attribute
¶
Character used as thousands separator (e.g., ",", ".", or " ")
RoundingStrategy ¶
Bases: AlanBaseEnum
Strategy for rounding monetary amounts.