Functional Weave
Code in Python

finance.late-payment-interest@1.0.0

vectors.json

6,379 bytes · view raw

[
  {"name": "GBP 1,000 fifty days late in 2026: 11.75% on the 31 December 2025 rate, and GBP 70", "args": [{"minor": 100000, "currency": "GBP"}, "2026-01-31", "2026-03-22"], "expect": {"daysLate": 50, "referenceDate": "2025-12-31", "referenceRateBasisPoints": 375, "interestRateBasisPoints": 1175, "interest": {"minor": 1610, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 8610, "currency": "GBP"}}},
  {"name": "gov.uk's example at 8.5%: exactly 11.64, not 50 days at a rounded 23p (11.50)", "args": [{"minor": 100000, "currency": "GBP"}, "2010-06-15", "2010-08-04"], "expect": {"daysLate": 50, "referenceDate": "2009-12-31", "referenceRateBasisPoints": 50, "interestRateBasisPoints": 850, "interest": {"minor": 1164, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 8164, "currency": "GBP"}}},
  {"name": "the reference rate is fixed when interest starts, however Bank Rate moves after", "args": [{"minor": 500000, "currency": "GBP"}, "2022-06-30", "2023-06-30"], "expect": {"daysLate": 365, "referenceDate": "2022-06-30", "referenceRateBasisPoints": 125, "interestRateBasisPoints": 925, "interest": {"minor": 46250, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 53250, "currency": "GBP"}}},
  {"name": "due 29 June 2023: interest starts 30 June, so the reference date is 31 December 2022", "args": [{"minor": 100000, "currency": "GBP"}, "2023-06-29", "2023-07-09"], "expect": {"daysLate": 10, "referenceDate": "2022-12-31", "referenceRateBasisPoints": 350, "interestRateBasisPoints": 1150, "interest": {"minor": 315, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 7315, "currency": "GBP"}}},
  {"name": "due a day later: interest starts 1 July, so the reference date is 30 June 2023", "args": [{"minor": 100000, "currency": "GBP"}, "2023-06-30", "2023-07-10"], "expect": {"daysLate": 10, "referenceDate": "2023-06-30", "referenceRateBasisPoints": 500, "interestRateBasisPoints": 1300, "interest": {"minor": 356, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 7356, "currency": "GBP"}}},
  {"name": "one day late on a debt under GBP 1,000: GBP 40", "args": [{"minor": 99999, "currency": "GBP"}, "2026-07-31", "2026-08-01"], "expect": {"daysLate": 1, "referenceDate": "2026-06-30", "referenceRateBasisPoints": 375, "interestRateBasisPoints": 1175, "interest": {"minor": 32, "currency": "GBP"}, "compensation": {"minor": 4000, "currency": "GBP"}, "total": {"minor": 4032, "currency": "GBP"}}},
  {"name": "GBP 10,000 exactly is in the GBP 100 band, at 8.1% after the 2020 cut", "args": [{"minor": 1000000, "currency": "GBP"}, "2020-12-31", "2021-01-31"], "expect": {"daysLate": 31, "referenceDate": "2020-12-31", "referenceRateBasisPoints": 10, "interestRateBasisPoints": 810, "interest": {"minor": 6879, "currency": "GBP"}, "compensation": {"minor": 10000, "currency": "GBP"}, "total": {"minor": 16879, "currency": "GBP"}}},
  {"name": "GBP 9,999.99 is still in the GBP 70 band", "args": [{"minor": 999999, "currency": "GBP"}, "2026-01-31", "2026-02-01"], "expect": {"daysLate": 1, "referenceDate": "2025-12-31", "referenceRateBasisPoints": 375, "interestRateBasisPoints": 1175, "interest": {"minor": 322, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 7322, "currency": "GBP"}}},
  {"name": "a year spanning 29 February is 366 days, each 1/365 of the yearly rate", "args": [{"minor": 100000, "currency": "GBP"}, "2024-02-01", "2025-02-01"], "expect": {"daysLate": 366, "referenceDate": "2023-12-31", "referenceRateBasisPoints": 525, "interestRateBasisPoints": 1325, "interest": {"minor": 13286, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 20286, "currency": "GBP"}}},
  {"name": "an exact half penny rounds up", "args": [{"minor": 146, "currency": "GBP"}, "2006-01-10", "2006-01-20"], "expect": {"daysLate": 10, "referenceDate": "2005-12-31", "referenceRateBasisPoints": 450, "interestRateBasisPoints": 1250, "interest": {"minor": 1, "currency": "GBP"}, "compensation": {"minor": 4000, "currency": "GBP"}, "total": {"minor": 4001, "currency": "GBP"}}},
  {"name": "paid on the due date: nothing is due", "args": [{"minor": 100000, "currency": "GBP"}, "2026-03-31", "2026-03-31"], "expect": {"daysLate": 0, "referenceDate": null, "referenceRateBasisPoints": null, "interestRateBasisPoints": null, "interest": {"minor": 0, "currency": "GBP"}, "compensation": {"minor": 0, "currency": "GBP"}, "total": {"minor": 0, "currency": "GBP"}}},
  {"name": "paid early: nothing is due", "args": [{"minor": 100000, "currency": "GBP"}, "2026-03-31", "2026-03-01"], "expect": {"daysLate": 0, "referenceDate": null, "referenceRateBasisPoints": null, "interestRateBasisPoints": null, "interest": {"minor": 0, "currency": "GBP"}, "compensation": {"minor": 0, "currency": "GBP"}, "total": {"minor": 0, "currency": "GBP"}}},
  {"name": "the earliest start the 2002 rules cover", "args": [{"minor": 100000, "currency": "GBP"}, "2002-08-06", "2002-08-07"], "expect": {"daysLate": 1, "referenceDate": "2002-06-30", "referenceRateBasisPoints": 400, "interestRateBasisPoints": 1200, "interest": {"minor": 33, "currency": "GBP"}, "compensation": {"minor": 7000, "currency": "GBP"}, "total": {"minor": 7033, "currency": "GBP"}}},
  {"name": "a debt in another currency is refused", "args": [{"minor": 100000, "currency": "EUR"}, "2026-01-31", "2026-03-22"], "expectError": "late payment interest is defined for GBP debts, received EUR"},
  {"name": "a zero debt is refused", "args": [{"minor": 0, "currency": "GBP"}, "2026-01-31", "2026-03-22"], "expectError": "debt must be greater than zero"},
  {"name": "before the 2002 rules there is no fixed sum", "args": [{"minor": 100000, "currency": "GBP"}, "2002-01-01", "2002-02-01"], "expectError": "no Late Payment Act fixed sum in force on 2002-01-02"},
  {"name": "an impossible payment date is refused", "args": [{"minor": 100000, "currency": "GBP"}, "2026-01-31", "2026-02-30"], "expectError": "not a real calendar date"},
  {"name": "a product beyond exact integers is refused", "args": [{"minor": 900000000000000, "currency": "GBP"}, "2026-01-31", "2026-03-22"], "expectError": "the interest calculation exceeds the exact integer range"}
]