Reviewers (PMD-3665):

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

Commitments

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.
  • Early commitment termination penalties:  When a commitment is terminated early and a penalty is charged, the system creates two different kinds of charge records, and each one gets its tax code and description differently.
    • For one-time fees (equipment, activation/installation, any other one-time fees) each one-time fee inside the commitment has its own service assigned to it by the Admin, set up individually when that one-time fee was configured. That service is what decides the tax code for the penalty charge tied to that item. The description on the invoice is also built individually per item, referencing that item’s own name. So, two different one-time items in the same commitment can end up with two different tax codes and two different descriptions, because each one carries its own service, independently of the others.
    • For the recurring monthly fee this works differently. Every recurring-discount penalty charge (which is currently calculated based on applied discounts) uses one single fixed service and one single fixed description. This is built into the code, not something an Admin configures. The only thing that can be set per subscription is which tax rate gets applied under that one fixed service — the service itself and the description text never change. While the CSP requires that penalties based on applied discounts and penalties applied based on remaining payments should be treated as separate services because they must be calculated separately using different tax/revenue codes and must have different descriptions on customer invoices.

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 Commitment Termination 

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 fee: Monthly subscription — base price €12.00/month, discount €2.00/month (subscriber pays €10.00/month). No suspension periods during contract.

    • One-time fee: Equipment purchase — list price €50.00, sold for €0.01 under commitment (discount = €49.99).

  • 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 - discount sum (A) is lower

  • On 2024-09-15, Admin terminates the "IPTV Basic" commitment assigned to John's account from Odoo CRM (month 10 of 24, i.e. 10 full months elapsed, 14 months remaining).

  • PortaBilling receives the termination request, and as the commitment is not open-ended, but has an end date, starts the calculation of the early commitment cancellation penalty.

  • 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.

  • 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:

    • Cancellation fee (penalties based on recurring fees): €20.00

    • Commitment one-time penalty: €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 scenario #1.2 Termination with the penalties apllied based on remaining payments - remaining payments (B1) is lower (alternative to #1.1)

  • On 2025-07-15, Admin terminates the “IPTV Basic” commitment assigned to John’s account from Odoo CRM (20 full months elapsed, 4 months remaining).

  • PortaBilling receives the termination request, and as the commitment is not open-ended, but has an end date, starts the calculation of the early commitment cancellation penalty.
  • 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. 

  • 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:

    • Cancellation fee (penalties based on recurring fees): €40.00

  • On 2025-08-01, PortaBilling generates a regular invoice for John Doe including early commitment termination penalty: 

    • Contract performance costs: total remaining monthly fees (new i_service, new i_dest): €40.00.

Use scenario #1.3: Termination with penalties applied based on remaining payments (B2 is lower) with a suspension period (alternative to #1.1)

  • On 2025-07-15, Admin terminates the “IPTV Basic” commitment assigned to John’s account from Odoo CRM (20 full months elapsed, 4 months remaining).

  • PortaBilling receives the termination request, and as the commitment is not open-ended, but has an end date, starts the calculation of the early commitment cancellation penalty.
  • PortaBilling takes into accont a 5-day suspension period (2025-04-10 to 2025-04-15) during which no subscription fee was charged and no discount was applied to John. 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. 

  • 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:

    • Cancellation fee (penalties based on recurring fees): €41.67.

  • On 2025-08-01, PortaBilling generates a regular invoice for John Doe including early commitment termination penalty:

    • Contract performance costs: total remaining monthly fees (new i_service, new i_dest): €41.67.

Use scenario #1.4 Termination of a transferred commitment with penalties covering the full contract history (alternative to #1.1)

  • After 6 months of usage, John transferes the “IPTV Basic” commitment to another customer Emily Clark on 2024-05-15.
  • 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).
  • On 2024-07-15, Admin terminates the “IPTV Basic” commitment assigned to Emily’s account from Odoo CRM.

  • PortaBilling receives the termination request, and starts the penalty calculation process considering that the commitment is not open-ended but has an end date, and that the commitment was previously held by John Doe. The penalty calculation covers the full commitment history (apply_prev_penalty = “Y”): 6 months used by John + 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. 

  • 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:

    • Cancellation fee (penalties based on recurring fees): €16.00

    • Commitment one-time penalty (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 scenario #1.5 Termination after commitment replacement with penalties covering both commitment periods (alternative to #1.1)

  • After 10 months of usage, John downgrades from the “IPTV Basic” commitment to “IPTV Lite” commitment with recurring fee: base price €8.00/month, discount €1.00/month. No new one-time fee.
  • On 2024-11-15 (2 months after downgrade), Admin terminates the “IPTV Lite” commitment assigned to John’s account from Odoo CRM.

  • PortaBilling receives the termination request, and starts the penalty calculation process considering 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. 

  • 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:

    • Cancellation fee (penalties based on recurring fees): €22.00

    • Commitment one-time penalty: €49.99

  • On 2024-12-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): €22.00.

    • Contract performance costs: equipment purchase price discount (i_service = 111, i_dest = 47): €49.99.

Non-functional requirements

N/A

Peculiarities

  1. 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.

  2. 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.

  3. The new penalty calculation logic should be applied no matter what is the reason for early commitment termination (whether it is terminated upon customer request or automatic termination due to unpaid invoices).
  4. 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.

  5. A and B2 use the same suspension interval and the same pro-rating basis (days in the calendar month where the suspension occurred).
  6. Invoice line mapping of applied penalties - penalties based on applied discounts and penalties applied based on remaining payments should be treated as separate services because they must be calculated separately using different tax/revenue codes and must have different descriptions on customer invoices:

    • When path A is selected (US#1.1), up to three separate invoice lines are generated (existing functionality):

      • monthly discount with its i_service/i_dest code (recurring fee)

      • activation/installation discount  with its i_service/i_dest code (one-time fee)

      • equipment discount with its i_service/i_dest codes (one-time fee)

    • When path B is selected (US#1.2), exactly one invoice line is generated:

      • total remaining monthly fees with its i_service and i_dest code (applicable only to recurring fee considering Peculiarity#1)

    • Therefore, according to CSP, four different services should be used for penalties for any commitments (no different services per specific commitment).
  7. 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).
  8. Service pause periods are treated identically to suspension periods for penalty calculation described in US#1.3: paused days are excluded from the discount accumulation window (reducing Value A) and added to the remaining contract term (increasing Value B). The difference from suspension is that pause is customer-initiated and the commitment minimum end date officially shifts forward by the number of paused days, whereas suspension does not change the end date.
  9. If a commitment has two (A and B) or more recurring fees configured, the system should calculate the penalty as a comparison of  summed A vs summed B. For example, a commitment contains:
    1. One-time fee: TV set for 50 EUR sold for €0.01 under commitment (discount = €49.99)
    2. Recurring fees:
      1. IPTV monthly subscription — base price €12.00/month, discount €2.00/month
      2. Internet monthly subscription — base price €17.00/month, discount €3.00/month


    3. If the commitment is terminated after 20 months, a penalty is calculated as summed A vs summed B:
      1. Value A = €49.99 + 20 × €2.00 + 20 × €3.00 = €49.99 + €40.00 + €60.00 = €149.99
      2. Value B = 4 × €10.00 + 4 × €14.00 = €40.00 + €56.00 = €96.00
      3. B < A → penalty = €96.00
  10. Changes to requirements for previous penalties described in US#1.4 and US#1.5 from 14.10.2026 according to CSP:
    • In the calculation mechanism itself (both Option A: previously granted discounts and Option B: charges for the remaining months until the end of the commitment term), the fees from both agreements should be included when comparing  options A and B in order to determine which one results in a lower penalty for the customer.
    • However, on the invoice, it is acceptable to display the penalties as separate lines (i.e., the penalty from the previous John's agreement = €12 and the penalty from the latest agreement = €4). Therefore, it is not necessary to combine them into a single amount of €16.
  11. According to CSP: if it happens that Value A is the same as Value B, we should apply the previous discount penalty logic i.e. related to Value A.

Performance / Clustering, Geo Redundancy/ Dual-Version, Porter / Call Control API / ESPF / Monitoring

N/A