All checks were successful
Deploy to K8s / deploy (push) Successful in 7s
Add internal/web/api package with Go structs for every /api/X route:
AdultsResponse, JuniorsResponse, PaymentsResponse, VersionResponse.
All fields carry explicit json: tags matching the Python view-model keys.
Key design choices:
- member_data / month_labels / raw_payments are nested objects (not
the pre-serialised JSON strings used in Jinja templates)
- Expected{Value int; Unknown bool} with custom MarshalJSON emits int
or the string "?" for junior single-attendance months
- RawTransaction covers the full 11-column payments sheet row
schemagen_test.go reflects all four response types via
github.com/invopop/jsonschema and golden-compares against committed
schemas in tests/fixtures/api-schema/. The JSONSchema() method on
Expected lives in the test file so the prod binary has no jsonschema
dependency.
Closes M5.1 in docs/plans/2026-05-03-2349-go-backend-rewrite-progress.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
92 lines
1.8 KiB
JSON
92 lines
1.8 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$ref": "#/$defs/PaymentsResponse",
|
|
"$defs": {
|
|
"PaymentsResponse": {
|
|
"properties": {
|
|
"grouped_payments": {
|
|
"additionalProperties": {
|
|
"items": {
|
|
"$ref": "#/$defs/RawTransaction"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"type": "object"
|
|
},
|
|
"sorted_people": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"attendance_url": {
|
|
"type": "string"
|
|
},
|
|
"payments_url": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"additionalProperties": false,
|
|
"type": "object",
|
|
"required": [
|
|
"grouped_payments",
|
|
"sorted_people",
|
|
"attendance_url",
|
|
"payments_url"
|
|
]
|
|
},
|
|
"RawTransaction": {
|
|
"properties": {
|
|
"date": {
|
|
"type": "string"
|
|
},
|
|
"amount": {
|
|
"type": "number"
|
|
},
|
|
"manual_fix": {
|
|
"type": "string"
|
|
},
|
|
"person": {
|
|
"type": "string"
|
|
},
|
|
"purpose": {
|
|
"type": "string"
|
|
},
|
|
"inferred_amount": {
|
|
"type": "number"
|
|
},
|
|
"sender": {
|
|
"type": "string"
|
|
},
|
|
"vs": {
|
|
"type": "string"
|
|
},
|
|
"message": {
|
|
"type": "string"
|
|
},
|
|
"bank_id": {
|
|
"type": "string"
|
|
},
|
|
"sync_id": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"additionalProperties": false,
|
|
"type": "object",
|
|
"required": [
|
|
"date",
|
|
"amount",
|
|
"manual_fix",
|
|
"person",
|
|
"purpose",
|
|
"inferred_amount",
|
|
"sender",
|
|
"vs",
|
|
"message",
|
|
"bank_id",
|
|
"sync_id"
|
|
]
|
|
}
|
|
}
|
|
}
|