[ { "name": "\u00a310,000 off a new \u00a3100,000 5% 25-year mortgage", "args": [ { "minor": 10000000, "currency": "GBP" }, 500, 300, 12, { "minor": 58459, "currency": "GBP" }, { "minor": 1000000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 9000000, "currency": "GBP" }, "baselinePayments": 300, "baselineInterest": { "minor": 7537705, "currency": "GBP" }, "reducedTermPayments": 247, "reducedTermFinalPayment": { "minor": 40629, "currency": "GBP" }, "reducedTermInterest": { "minor": 5421543, "currency": "GBP" }, "paymentsSaved": 53, "reducedPayment": { "minor": 52613, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 6783966, "currency": "GBP" } } }, { "name": "\u00a3200 off \u00a31,000 at 12% with a year left", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 8885, "currency": "GBP" }, { "minor": 20000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 80000, "currency": "GBP" }, "baselinePayments": 12, "baselineInterest": { "minor": 6619, "currency": "GBP" }, "reducedTermPayments": 10, "reducedTermFinalPayment": { "minor": 4299, "currency": "GBP" }, "reducedTermInterest": { "minor": 4264, "currency": "GBP" }, "paymentsSaved": 2, "reducedPayment": { "minor": 7108, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 5294, "currency": "GBP" } } }, { "name": "the recalculated payment rounded down", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 8885, "currency": "GBP" }, { "minor": 20000, "currency": "GBP" }, "down" ], "expect": { "newBalance": { "minor": 80000, "currency": "GBP" }, "baselinePayments": 12, "baselineInterest": { "minor": 6619, "currency": "GBP" }, "reducedTermPayments": 10, "reducedTermFinalPayment": { "minor": 4299, "currency": "GBP" }, "reducedTermInterest": { "minor": 4264, "currency": "GBP" }, "paymentsSaved": 2, "reducedPayment": { "minor": 7107, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 5294, "currency": "GBP" } } }, { "name": "interest-free: the term shortens by whole payments only", "args": [ { "minor": 120000, "currency": "GBP" }, 0, 12, 12, { "minor": 10000, "currency": "GBP" }, { "minor": 25000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 95000, "currency": "GBP" }, "baselinePayments": 12, "baselineInterest": { "minor": 0, "currency": "GBP" }, "reducedTermPayments": 10, "reducedTermFinalPayment": { "minor": 5000, "currency": "GBP" }, "reducedTermInterest": { "minor": 0, "currency": "GBP" }, "paymentsSaved": 2, "reducedPayment": { "minor": 7917, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 0, "currency": "GBP" } } }, { "name": "a penny overpayment saves no payments", "args": [ { "minor": 500000, "currency": "GBP" }, 600, 6, 12, { "minor": 84798, "currency": "GBP" }, { "minor": 1, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 499999, "currency": "GBP" }, "baselinePayments": 6, "baselineInterest": { "minor": 8787, "currency": "GBP" }, "reducedTermPayments": 6, "reducedTermFinalPayment": { "minor": 84796, "currency": "GBP" }, "reducedTermInterest": { "minor": 8787, "currency": "GBP" }, "paymentsSaved": 0, "reducedPayment": { "minor": 84798, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 8787, "currency": "GBP" } } }, { "name": "quarterly loan, half the balance overpaid", "args": [ { "minor": 1000000, "currency": "GBP" }, 800, 24, 4, { "minor": 136510, "currency": "GBP" }, { "minor": 500000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 500000, "currency": "GBP" }, "baselinePayments": 8, "baselineInterest": { "minor": 92080, "currency": "GBP" }, "reducedTermPayments": 4, "reducedTermFinalPayment": { "minor": 115086, "currency": "GBP" }, "reducedTermInterest": { "minor": 24616, "currency": "GBP" }, "paymentsSaved": 4, "reducedPayment": { "minor": 68255, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 46039, "currency": "GBP" } } }, { "name": "a payment above the level payment clears even the baseline early", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 10000, "currency": "GBP" }, { "minor": 10000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 90000, "currency": "GBP" }, "baselinePayments": 11, "baselineInterest": { "minor": 5898, "currency": "GBP" }, "reducedTermPayments": 10, "reducedTermFinalPayment": { "minor": 4794, "currency": "GBP" }, "reducedTermInterest": { "minor": 4794, "currency": "GBP" }, "paymentsSaved": 1, "reducedPayment": { "minor": 7996, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 5956, "currency": "GBP" } } }, { "name": "mid-term: 10 years left on \u00a360,000 at 4%", "args": [ { "minor": 6000000, "currency": "GBP" }, 400, 120, 12, { "minor": 60747, "currency": "GBP" }, { "minor": 500000, "currency": "GBP" }, "half-up" ], "expect": { "newBalance": { "minor": 5500000, "currency": "GBP" }, "baselinePayments": 120, "baselineInterest": { "minor": 1289651, "currency": "GBP" }, "reducedTermPayments": 108, "reducedTermFinalPayment": { "minor": 57932, "currency": "GBP" }, "reducedTermInterest": { "minor": 1057861, "currency": "GBP" }, "paymentsSaved": 12, "reducedPayment": { "minor": 55685, "currency": "GBP" }, "reducedPaymentInterest": { "minor": 1182177, "currency": "GBP" } } }, { "name": "an overpayment of the whole balance is a settlement, not an overpayment", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 8885, "currency": "GBP" }, { "minor": 100000, "currency": "GBP" }, "half-up" ], "expectError": "overpayment must be less than the balance" }, { "name": "a zero overpayment is refused", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 8885, "currency": "GBP" }, { "minor": 0, "currency": "GBP" }, "half-up" ], "expectError": "overpayment must be greater than zero" }, { "name": "mixed currencies are refused", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 8885, "currency": "GBP" }, { "minor": 1000, "currency": "EUR" }, "half-up" ], "expectError": "currency mismatch" }, { "name": "a payment that does not cover the interest never repays", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 1000, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, "half-up" ], "expectError": "does not cover the interest" }, { "name": "a zero payment is refused", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 12, 12, { "minor": 0, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, "half-up" ], "expectError": "payment must be greater than zero" }, { "name": "the remaining term must hold whole payments", "args": [ { "minor": 100000, "currency": "GBP" }, 1200, 13, 4, { "minor": 8885, "currency": "GBP" }, { "minor": 1000, "currency": "GBP" }, "half-up" ], "expectError": "is not a whole number of payments" } ]