Initial commit: event-driven UK payslip ingest service
Extracted from /home/wizard/code monorepo into its own repo so Woodpecker CI can watch it. Identical content to /home/wizard/code commit e426028. See README.md for overview, env vars, and Paperless workflow config. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
57484619c1
27 changed files with 2878 additions and 0 deletions
52
tests/test_schema.py
Normal file
52
tests/test_schema.py
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from payslip_ingest.schema import ExtractedPayslip, validate_totals
|
||||
|
||||
|
||||
def _sample_payload() -> dict[str, object]:
|
||||
return {
|
||||
"pay_date": "2026-03-28",
|
||||
"pay_period_start": "2026-03-01",
|
||||
"pay_period_end": "2026-03-31",
|
||||
"employer": "Acme Ltd",
|
||||
"currency": "GBP",
|
||||
"gross_pay": "5000.00",
|
||||
"income_tax": "800.00",
|
||||
"national_insurance": "350.00",
|
||||
"pension_employee": "250.00",
|
||||
"pension_employer": "150.00",
|
||||
"student_loan": "100.00",
|
||||
"other_deductions": {
|
||||
"cycle_to_work": "50.00"
|
||||
},
|
||||
"net_pay": "3450.00",
|
||||
}
|
||||
|
||||
|
||||
def test_schema_accepts_realistic_payload() -> None:
|
||||
model = ExtractedPayslip.model_validate(_sample_payload())
|
||||
assert model.employer == "Acme Ltd"
|
||||
assert model.gross_pay == Decimal("5000.00")
|
||||
assert model.other_deductions == {"cycle_to_work": Decimal("50.00")}
|
||||
|
||||
|
||||
def test_schema_rejects_extra_fields() -> None:
|
||||
payload = _sample_payload()
|
||||
payload["bonus_field"] = "not allowed"
|
||||
with pytest.raises(ValidationError):
|
||||
ExtractedPayslip.model_validate(payload)
|
||||
|
||||
|
||||
def test_validate_totals_true_for_matched_numbers() -> None:
|
||||
model = ExtractedPayslip.model_validate(_sample_payload())
|
||||
assert validate_totals(model) is True
|
||||
|
||||
|
||||
def test_validate_totals_false_for_mismatch() -> None:
|
||||
payload = _sample_payload()
|
||||
payload["net_pay"] = "4000.00"
|
||||
model = ExtractedPayslip.model_validate(payload)
|
||||
assert validate_totals(model) is False
|
||||
Loading…
Add table
Add a link
Reference in a new issue