Functional Weave
Code in Rust

payroll.student-loan@1.0.2

vectors.json

5,619 bytes · view raw

[
 {
  "name": "plan 1, monthly, 2026-27: 9% over \u00a326,900 / 12, pence dropped",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 6800,
   "currency": "GBP"
  }
 },
 {
  "name": "HMRC's worked example: \u00a3700 a week on plan 1 repays \u00a316",
  "args": [
   {
    "minor": 70000,
    "currency": "GBP"
   },
   "plan-1",
   "weekly",
   "2026-05-29"
  ],
  "expect": {
   "minor": 1600,
   "currency": "GBP"
  }
 },
 {
  "name": "HMRC's worked example: \u00a32,800 a month on plan 1 repays \u00a350",
  "args": [
   {
    "minor": 280000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 5000,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 2, monthly, 2026-27",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-2",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 4900,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 4, monthly, 2026-27",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-4",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 1600,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 5 repays from 2026-27: exactly \u00a382.50 drops to \u00a382",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-5",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 8200,
   "currency": "GBP"
  }
 },
 {
  "name": "postgraduate loan: 6% over \u00a31,750 a month",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "postgraduate",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 7500,
   "currency": "GBP"
  }
 },
 {
  "name": "pay below the threshold repays nothing",
  "args": [
   {
    "minor": 200000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 0,
   "currency": "GBP"
  }
 },
 {
  "name": "the exact monthly threshold, not HMRC's printed \u00a32,241.66: \u00a32,341.66 repays \u00a38, not \u00a39",
  "args": [
   {
    "minor": 234166,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expect": {
   "minor": 800,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 1 in 2023-24, weekly",
  "args": [
   {
    "minor": 50000,
    "currency": "GBP"
   },
   "plan-1",
   "weekly",
   "2023-10-06"
  ],
  "expect": {
   "minor": 600,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 1 in 2024-25, monthly",
  "args": [
   {
    "minor": 250000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2024-07-26"
  ],
  "expect": {
   "minor": 3700,
   "currency": "GBP"
  }
 },
 {
  "name": "fortnightly in 2025-26 uses 2/52 of the annual threshold",
  "args": [
   {
    "minor": 150000,
    "currency": "GBP"
   },
   "plan-2",
   "fortnightly",
   "2025-10-10"
  ],
  "expect": {
   "minor": 3600,
   "currency": "GBP"
  }
 },
 {
  "name": "exactly the fortnightly threshold repays nothing",
  "args": [
   {
    "minor": 109500,
    "currency": "GBP"
   },
   "plan-2",
   "fortnightly",
   "2025-10-10"
  ],
  "expect": {
   "minor": 0,
   "currency": "GBP"
  }
 },
 {
  "name": "four-weekly in 2025-26 uses 4/52 of the annual threshold",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "four-weekly",
   "2025-11-14"
  ],
  "expect": {
   "minor": 8900,
   "currency": "GBP"
  }
 },
 {
  "name": "the new tax year's threshold applies from 6 April",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-04-06"
  ],
  "expect": {
   "minor": 6800,
   "currency": "GBP"
  }
 },
 {
  "name": "the day before, the old one does",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-04-05"
  ],
  "expect": {
   "minor": 7400,
   "currency": "GBP"
  }
 },
 {
  "name": "plan 5 has no threshold before 6 April 2026",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-5",
   "monthly",
   "2025-12-28"
  ],
  "expectError": "no student loan threshold for plan-5"
 },
 {
  "name": "a date before the rules this package carries",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2023-04-05"
  ],
  "expectError": "no student loan threshold for plan-1"
 },
 {
  "name": "an unknown plan is an error",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-3",
   "monthly",
   "2026-05-28"
  ],
  "expectError": "unknown student loan plan"
 },
 {
  "name": "negative earnings are refused",
  "args": [
   {
    "minor": -1,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expectError": "earnings must not be negative"
 },
 {
  "name": "another currency is refused",
  "args": [
   {
    "minor": 300000,
    "currency": "EUR"
   },
   "plan-1",
   "monthly",
   "2026-05-28"
  ],
  "expectError": "must be in GBP"
 },
 {
  "name": "an unknown frequency is refused",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "daily",
   "2026-05-28"
  ],
  "expectError": "unknown pay frequency"
 },
 {
  "name": "a trailing newline is not part of an ISO date",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "2026-05-28\n"
  ],
  "expectError": "payDate must be an ISO date"
 },
 {
  "name": "Arabic-Indic digits are not an ISO date",
  "args": [
   {
    "minor": 300000,
    "currency": "GBP"
   },
   "plan-1",
   "monthly",
   "٢٠٢٦-٠٥-٢٨"
  ],
  "expectError": "payDate must be an ISO date"
 }
]