templates: add multi-category filter (repeatable or CSV) to GET /api/templates/search; add has_keywords filter; add categories listing endpoint with counts; update docs; add tests

This commit is contained in:
HotSwapp
2025-08-15 15:04:40 -05:00
parent 21c6b285d6
commit e3a279dba7
17 changed files with 3727 additions and 2 deletions

View File

@@ -230,6 +230,101 @@ Allowed sort fields (high level):
- `PUT /api/documents/qdros/{file_no}/{id}` - Update QDRO
- `DELETE /api/documents/qdros/{file_no}/{id}` - Delete QDRO
📚 See also: [PENSIONS.md](PENSIONS.md) for detailed pensions API fields, sorting, and examples.
### Pensions
- `GET /api/pensions/schedules` - List pension schedules for a file
- Query params: `file_no` (required), `skip`, `limit`, `sort_by` (id,file_no,version,vests_on,vests_at), `sort_dir`, `include_total`,
filters: `start`, `end`, `version`, numeric ranges: `vests_at_min`, `vests_at_max`, search: `search` (tokenized across `version`, `frequency`).
- Examples:
```bash
curl "http://localhost:6920/api/pensions/schedules?file_no=F-1&sort_by=vests_on&sort_dir=asc&limit=20&include_total=true"
curl "http://localhost:6920/api/pensions/schedules?file_no=F-1&version=02&vests_at_min=10&vests_at_max=50"
```
- `GET /api/pensions/marriages` - List marriage history for a file
- Query params: `file_no` (required), `skip`, `limit`, `sort_by` (id,file_no,version,married_from,married_to,marital_percent,service_from,service_to), `sort_dir`, `include_total`,
filters: `start`, `end`, `version`, numeric ranges: `married_years_min/_max`, `service_years_min/_max`, `marital_percent_min/_max`, search: `search` (tokenized across `version`, `spouse_name`, `notes`).
- Example:
```bash
curl "http://localhost:6920/api/pensions/marriages?file_no=F-1&search=Jane%20Doe&sort_by=married_from&sort_dir=desc"
```
- `GET /api/pensions/death-benefits` - List death benefits for a file
- Query params: `file_no` (required), `skip`, `limit`, `sort_by` (id,file_no,version,lump1,lump2,growth1,growth2,disc1,disc2,created), `sort_dir`, `include_total`,
filters: `start`, `end`, `version`, numeric ranges: `lump1_min/_max`, `lump2_min/_max`, `growth1_min/_max`, `growth2_min/_max`, `disc1_min/_max`, `disc2_min/_max`, search: `search` (tokenized across `version`, `beneficiary_name`, `benefit_type`, `notes`).
- Example:
```bash
curl "http://localhost:6920/api/pensions/death-benefits?file_no=F-1&lump1_min=100&sort_by=lump1&sort_dir=desc"
```
- `GET /api/pensions/separations` - List separation agreements for a file
- Query params: `file_no` (required), `skip`, `limit`, `sort_by` (id,file_no,version,agreement_date), `sort_dir`, `include_total`,
filters: `start`, `end`, `version`, search: `search` (tokenized across `version`, `terms`, `notes`).
- Example:
```bash
curl "http://localhost:6920/api/pensions/separations?file_no=F-1&start=2024-01-01&end=2024-12-31&sort_by=agreement_date"
```
- `GET /api/pensions/{file_no}/detail` - Detail view for a file's pension data with nested, independently paginated lists
- Each nested list accepts its own paging/sorting/filtering query prefixes: `s_*` (schedules), `m_*` (marriages), `d_*` (death benefits), `sep_*` (separations)
- Example:
```bash
curl "http://localhost:6920/api/pensions/F-1/detail?s_sort_by=vests_on&s_limit=10&m_sort_by=married_from&d_sort_by=lump1&sep_sort_by=agreement_date"
```
- `POST /api/pensions/` - Create a main Pension record
- Body (JSON, selected fields):
```json
{
"file_no": "F-1",
"version": "01",
"plan_id": "PID1",
"plan_name": "Plan A",
"vested_per": 50,
"tax_rate": 25
}
```
- Notes: numeric validation enforced (e.g., `vested_per` 0100; `tax_rate` 0100; monetary values non-negative)
- `GET /api/pensions/{pension_id}` - Get a Pension by id
- `PUT /api/pensions/{pension_id}` - Update a Pension (partial fields accepted)
- Example:
```bash
curl -X PUT "http://localhost:6920/api/pensions/123" -H 'Content-Type: application/json' -d '{"plan_name":"Plan B","vested_per":75}'
```
- `DELETE /api/pensions/{pension_id}` - Delete a Pension
### Templates
- `GET /api/templates/search` - Search document templates
- Query params:
- `q` (str, optional): partial match on template name or description
- `category` (str[] or CSV, optional): filter by one or more categories. Repeat the parameter (`?category=A&category=B`) or pass a comma-separated list (`?category=A,B`).
- `keywords` (str[], optional, repeatable): keyword tags assigned to templates
- `keywords_mode` (str, optional): `any` (default) returns templates that match any of the provided keywords; `all` returns only templates that contain all the provided keywords
- `has_keywords` (bool, optional): when `true`, only templates that have one or more keywords are returned; when `false`, only templates with no keywords are returned
- `skip` (int, optional): pagination offset, default 0
- `limit` (int, optional): page size, default 50, max 200
- `sort_by` (str, optional): `name` (default) | `category` | `updated`
- `sort_dir` (str, optional): `asc` (default) | `desc`
- `active_only` (bool, optional): when `true` (default), only active templates are returned
- Examples:
```bash
# Any of the keywords (default)
curl "http://localhost:6920/api/templates/search?keywords=qdro&keywords=divorce"
# Must contain all keywords
curl "http://localhost:6920/api/templates/search?keywords=qdro&keywords=divorce&keywords_mode=all"
# Sorted by name descending with pagination
curl "http://localhost:6920/api/templates/search?sort_by=name&sort_dir=desc&skip=10&limit=10"
# Include inactive templates
curl "http://localhost:6920/api/templates/search?active_only=false"
```
- `GET /api/templates/categories` - List distinct template categories with counts
- Query params:
- `active_only` (bool, optional): when `true` (default), only counts active templates
- Example:
```bash
curl "http://localhost:6920/api/templates/categories?active_only=false"
```
### Support
- `POST /api/support/tickets` - Create support ticket (public; auth optional)
- `GET /api/support/tickets` - List tickets (admin; supports filters, search, pagination, sorting, `include_total`)