[
{
"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"
}
]