Reviewers (PMD-3665):
- Oleksandr Zaluhovskyi
- Dev
- Yuliia Hrabar
- Mike Kidik
- Tetiana Savchenko as part of DOCS-7277 task
User Story
As a service provider operating under Lithuanian Communications Regulatory Authority (RRT), I want PortaBilling to automatically calculate the early commitment termination fee as the lesser of: (a) total discounts granted as of the termination date, or (b) total remaining monthly payments - so that every early-termination charge complies with RRT requirements, is transparent, and is always calculated in the subscriber's favour (the termination fee never exceeds what the subscriber would have paid to complete the contract term).
Example of use
A subscriber (John Doe) has a 24-month commitment with two components:
One-time component: device purchased at €0.01 instead of €50.00 (discount = €49.99).
Monthly recurring component: base price €12.00, discount €2.00 (subscriber pays €10.00/month).
Scenario A — termination at month 10:
Calculation A (discounts granted): €49.99 one-time + 10 × €2.00 = €69.99
Calculation B (remaining payments): (24 − 10) × €10.00 = €140.00
Result: A < B → penalty = €69.99 (more favourable to customer).
Scenario B — termination at month 20:
Calculation A (discounts granted): €49.99 + 20 × €2.00 = €89.99
Calculation B (remaining payments): (24 − 20) × €10.00 = €40.00
Result: B < A → penalty = €40.00 (more favourable to customer).
Business model
This feature is applicable to any business model where services are delivered under fixed-term contracts with minimum commitment periods.
Technology
Current Solution
The existing PortaBilling commitment termination penalty is calculated exclusively as the sum of all discounts applied to the subscriber since the commitment start date till the commitment termination date. The system never computes or compares the remaining monthly payments, but always applies the full discount-sum regardless of whether that amount exceeds remaining contract value — violating the latest RRT regulation.
Stakeholders and their benefits
Who are the users / whom we bring value to?
| Benefit / Stakeholders | More Comfort | Increased Efficiency | Saves Time | Tighter Control | Replaces Human | Regulatory Requirement |
|---|---|---|---|---|---|---|
| CSP | ✓ | ✓ | ||||
| Sales/marketing of CSP | ✓ | |||||
| Network operations / Support of CSP | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 3rd party | ||||||
| End user | ✓ |
Use Cases
Use case #1: Early Termination — Discount Sum (A) is Lower
Roles: Billing Admin, PortaBilling system, Odoo CRM
Preconditions:
Customer John Doe has the commitment assigned to his account 10001: "IPTV Basic" - 24-month fixed-term contract, start date 2023-11-15, minimum end date 2025-11-14.
Recurring term: Monthly subscription — base price €12.00/month, discount €2.00/month (subscriber pays €10.00/month). No suspension periods during contract.
One-time term: Equipment purchase — list price €50.00, sold for €0.01 under commitment (discount = €49.99).
Termination request received: 2024-09-15 (month 10 of 24, i.e. 10 full months elapsed, 14 months remaining).
- Billing Admin manages customer requests from Odoo CRM, which communicates with PortaBilling via PortaBilling API.
Use scenario #1.1 Termination with the penalties applied based on discounts
On 2024-09-15, Admin terminates the "IPTV Basic" commitment assigned to John's account from Odoo CRM.
- PortaBilling receives the termination request, detects that the commitment is not open-ended, but has an end date, so the calculation of the early commitment cancellation penalty starts.
PortaBilling computes Value A (discount sum): one-time discount €49.99 + 10 months × €2.00/month = €49.99 + €20.00 = €69.99.
PortaBilling computes Value B1 (remaining monthly payments): 14 remaining months × €10.00/month = €140.00. Remaining payments for one-time term commitments are not calculated.
PortaBilling selects the lower value: A = €69.99 < B1 = €140.00 → proposed penalty = €69.99.
PortaBilling records the termination date as 2024-09-15, closes the commitment, and applies penalties:
Penalties based on recurring fees: €20.00
Penalties based on one-time fees: €49.99
On 2024-10-01, PortaBilling generates a regular invoice for John Doe including early commitment termination penalties:
Contract performance costs: monthly fee discount (i_service = 4, i_dest = 19): €20.00.
Contract performance costs: equipment purchase price discount (i_service = 111, i_dest = 47): €49.99.
Use Case #2: Early Termination — Remaining Payments (B1) is Lower
Roles: Billing Admin, PortaBilling system, Odoo CRM
Preconditions:
Customer Alice Smith has the commitment assigned to her account 10002: "IPTV Basic" - 24-month fixed-term contract, start date 2023-11-15, minimum end date 2025-11-14.
Recurring term: Monthly subscription — base price €12.00/month, discount €2.00/month (subscriber pays €10.00/month).
One-time term: Equipment purchase — list price €50.00, sold for €0.01 (discount = €49.99).
Termination request received: 2025-07-15 (20 full months elapsed, 4 months remaining).
- Billing Admin manages customer requests from Odoo CRM, which communicates with PortaBilling via PortaBilling API.
Use scenario #2.1 Termination with the penalties apllied based on remaining payments
On 2025-07-15, Admin terminates the “IPTV Basic” commitment assigned to Alice’s account from Odoo CRM.
- PortaBilling receives the termination request, detects that the commitment is not open-ended, but has an end date, so the calculation of the early commitment cancellation penalty starts.
PortaBilling computes Value A (discount sum): €49.99 + 20 months × €2.00 = €49.99 + €40.00 = €89.99.
PortaBilling computes Value B1 (remaining payments): 4 remaining months × €10.00/month = €40.00. Remaining payments for one-time term commitments are not calculated.
PortaBilling selects the lower value: B1 = €40.00 < A = €89.99 → proposed penalty = €40.00.
PortaBilling records the termination date as 2025-07-15, closes the commitment, and applies penalties:
Penalties based on recurring fees: €40.00
On 2025-08-01, PortaBilling generates a regular invoice for Alice Smith including early commitment termination penalty:
Contract performance costs: total remaining monthly fees (new i_service, new i_dest): €40.00.
Use Case #3: Early Termination — Remaining Payments (B2) is Lower, with Suspension Period
Roles: Billing Admin, PortaBilling system, Odoo CRM
Preconditions:
Customer Robert Brown has the commitment assigned to his account 10003: “IPTV Basic” — 24-month fixed-term contract, start date 2023-11-15, minimum end date 2025-11-14.
Recurring term: Monthly subscription — base price €12.00/month, discount €2.00/month (subscriber pays €10.00/month).
One-time term: Equipment purchase — list price €50.00, sold for €0.01 under commitment (discount = €49.99).
Robert’s account was suspended for non-payment between 2025-04-10 and 2025-04-15 (5 days). The subscription fee was not charged and no discount was applied during that period.
Termination request received: 2025-07-15 (20 full months elapsed, 4 months remaining; effective remaining term extended to 4 months 5 days due to 5 suspension days).
Billing Admin manages customer requests from Odoo CRM, which communicates with PortaBilling via PortaBilling API.
Use scenario #3.1: Termination with penalties applied based on remaining payments (B2 is lower)
On 2025-07-15, Admin terminates the “IPTV Basic” commitment assigned to Robert’s account from Odoo CRM.
PortaBilling receives the termination request, detects that the commitment is not open-ended, but has an end date, so the calculation of the early commitment cancellation penalty starts.
PortaBilling detects a 5-day suspension period (2025-04-10 to 2025-04-15) during which no subscription fee was charged and no discount was applied. The discount accumulation counter excludes those 5 days.
PortaBilling computes Value A (discount sum): one-time discount €49.99 + (20 months − 5 suspended days) × €2.00/month. The 5 suspended days are excluded from the discount accumulation period (no discount was applied then): 5 days × (€2.00 / 30 days in April) = €0.33. Recurring discount = €40.00 − €0.33 = €39.67. Value A = €49.99 + €39.67 = €89.66.
PortaBilling computes Value B2 (remaining payments, suspension-adjusted): baseline 4 months × €10.00/month = €40.00, plus 5 suspended days pro-rated using the day count of the month in which the suspension fell (April = 30 days): €10.00 / 30 × 5 = €1.67. Value B2 = €40.00 + €1.67 = €41.67. Remaining payments for one-time term commitments are not calculated.
PortaBilling selects the lower value: B2 = €41.67 < A = €89.66 → penalty = €41.67.
PortaBilling records the termination date as 2025-07-15, closes the commitment, and applies penalties:
Penalties based on recurring fees: €41.67.
On 2025-08-01, PortaBilling generates a regular invoice for Robert Brown including early commitment termination penalty:
Contract performance costs: total remaining monthly fees (new i_service, new i_dest): €41.67.
Use Case #4: Early Termination of a Transferred Commitment
Roles: Billing Admin, PortaBilling system, Odoo CRM
Preconditions:
Customer Robert Brown has been using the “IPTV Basic” commitment — 24-month fixed-term contract, start date 2023-11-15, minimum end date 2025-11-14 — for 6 months.
Recurring term: Monthly subscription — base price €12.00/month, discount €2.00/month (subscriber pays €10.00/month).
One-time term: Equipment purchase — list price €50.00, sold for €0.01 under commitment (discount = €49.99).
Robert decides to move out of his flat. A new renter, Emily Clark (account 10004), asks to take over the IPTV service immediately without starting a new contract.
Billing Admin creates a customer record for Emily Clark in PortaBilling and transfers the “IPTV Basic” commitment from Robert’s account to Emily’s account on 2024-05-15. The commitment retains its original start date (2023-11-15) and minimum end date (2025-11-14).
Emily uses the service for 2 months after the transfer, then requests termination on 2024-07-15 (8 full months elapsed in total: 6 by Robert + 2 by Emily; 16 months remaining).
Billing Admin manages customer requests from Odoo CRM, which communicates with PortaBilling via PortaBilling API.
Use scenario #4.1 Termination of a transferred commitment with penalties covering the full contract history
On 2024-07-15, Admin terminates the “IPTV Basic” commitment assigned to Emily’s account from Odoo CRM.
PortaBilling receives the termination request, detects that the commitment is not open-ended but has an end date, and that the commitment was previously held by Robert Brown. The penalty calculation covers the full commitment history (apply_prev_penalty = “Y”): 6 months used by Robert + 2 months used by Emily = 8 months total elapsed.
PortaBilling computes Value A (discount sum across full history): one-time equipment discount €49.99 + 8 months × €2.00/month = €49.99 + €16.00 = €65.99.
PortaBilling computes Value B (remaining monthly payments): 16 remaining months × €10.00/month = €160.00. Remaining payments for one-time term commitments are not calculated.
PortaBilling selects the lower value: A = €65.99 < B = €160.00 → penalty = €65.99.
PortaBilling records the termination date as 2024-07-15, closes the commitment, and applies penalties:
Penalties based on recurring fees: €16.00
Penalties based on one-time fees (previous account): €49.99
On 2024-08-01, PortaBilling generates a regular invoice for Emily Clark including early commitment termination penalties:
Contract performance costs: monthly fee discount (i_service = 4, i_dest = 19): €16.00.
Contract performance costs: equipment purchase price discount (i_service = 111, i_dest = 47): €49.99.
Use Case #5: Early Termination after Commitment Replacement
Roles: Billing Admin, PortaBilling system, Odoo CRM
Preconditions:
Customer Alice Smith has been using the “IPTV Basic” commitment — 24-month fixed-term contract, start date 2023-11-15, minimum end date 2025-11-14 — for 10 months (base price €12.00/month, discount €2.00/month, pays €10.00/month; one-time equipment discount €49.99).
On 2024-09-15, Alice downgrades to “IPTV Lite”. Billing Admin replaces the commitment in PortaBilling: “IPTV Basic” is closed and “IPTV Lite” is assigned, retaining the original start date and minimum end date.
“IPTV Lite” recurring term: base price €8.00/month, discount €1.00/month. No new one-time fee.
2 months after the replacement, Alice requests termination.
Billing Admin manages customer requests from Odoo CRM, which communicates with PortaBilling via PortaBilling API.
Use scenario #5.1 Termination with penalties covering both commitment periods
On 2024-11-15, Admin terminates the “IPTV Lite” commitment assigned to Alice’s account from Odoo CRM.
PortaBilling receives the termination request, detects that the commitment has an end date and carries previous penalty from the replaced “IPTV Basic” commitment. The penalty covers the full contract history: 10 months under “IPTV Basic” + 2 months under “IPTV Lite” = 12 months elapsed.
PortaBilling computes Value A (discount sum across full history): €49.99 one-time + 10 × €2.00 (IPTV Basic) + 2 × €1.00 (IPTV Lite) = €49.99 + €20.00 + €2.00 = €71.99.
PortaBilling computes Value B (remaining payments under “IPTV Lite”): 12 × €7.00 = €84.00. Remaining payments for one-time term commitments are not calculated.
PortaBilling selects the lower value: A = €71.99 < B = €84.00 → penalty = €71.99.
PortaBilling records termination date 2024-11-15, closes the commitment, and applies penalties:
Penalties based on recurring fees: €22.00
Penalties based on one-time fees: €49.99
On 2024-12-01, PortaBilling generates a regular invoice for Alice Smith including early commitment termination penalties:
Contract performance costs: monthly fee discount (i_service = 4, i_dest = 19): €22.00.
Contract performance costs: equipment purchase price discount (i_service = 111, i_dest = 47): €49.99.
Non-functional requirements
N/A
Peculiarities
One-time fees are always path A: one-time charge discounts (equipment purchase, activation/installation fee) are only ever included in Value A (discount sum). They do not contribute to Value B (remaining payments), since no recurring future payments are owed for them.
No change to manual override: The existing mechanism for an admin to set apply_penalties = "N" (waiving any penalty) remains fully intact and takes precedence over both calculation paths. No automated logic may override a manually set waiver.
- The new penalty calculation logic should be appiled no matter what is the reason for early commitment termination (whether it is terminated upon customer request or automatic termination due to unpaid invoices).
B2 vs B1 selection:
B2 (suspension-adjusted) must be used whenever the account had one or more "suspended" status periods during the contract.
B1 is used only when there were zero suspension days. The system must sum all individual suspension intervals (in calendar days) and add them to the unfulfilled remaining term.
Invoice line mapping:
When path A is selected, up to three separate invoice lines are generated (monthly discount, activation/installation discount, equipment discount — each with its existing i_service/i_dest codes).
When path B is selected, exactly one invoice line is generated using the new i_service and new i_dest codes to be provisioned as part of this change.
- According to CSP, the implementation of the new calculation for early commitment termination fees does not require any changes to the CSP's reporting (IFRS or Rivile or iSAF).
Performance / Clustering, Geo Redundancy/ Dual-Version, Porter / Call Control API / ESPF / Monitoring
N/A