Appearance
7. The return-due reminder job
What we're adding
A checkout that is CHECKED_OUT and:
- within 3 days of its
due_date→ statusDUE_SOON - past its
due_date→ statusOVERDUE
Zero Java. The platform's generic engine-entity.status-date-sweep job runs daily and applies config rows we seed.
1. Ship the shared config entity
So a fresh environment that predates the shared table still gets it. spk-assembly/metadata/entities/entity_status_date_sweep_config.json (real file) — ships only the additive columns (day_offset, seeded_by); the installer is idempotent-additive, so an existing table just gains anything missing.
2. Seed the config rows
spk-assembly/metadata/seed-data/office-equipment-sweep-configs.json (real file):
json
{
"entity": "entity_status_date_sweep_config",
"keyFields": ["entity_name", "date_field", "set_status_to", "day_offset"],
"source": "office-equipment",
"rows": [
{
"entity_name": "oeq_checkout",
"status_field": "status",
"when_status_in": "CHECKED_OUT",
"date_field": "due_date",
"compare_op": "lte",
"day_offset": 3,
"set_status_to": "DUE_SOON",
"active": true,
"seeded_by": "office-equipment"
},
{
"entity_name": "oeq_checkout",
"status_field": "status",
"when_status_in": "CHECKED_OUT,DUE_SOON",
"date_field": "due_date",
"compare_op": "lt",
"day_offset": 0,
"set_status_to": "OVERDUE",
"active": true,
"seeded_by": "office-equipment"
}
]
}- Row 1:
day_offset: 3+compare_op: lte→ "fires whendue_dateis within 3 days" — the "N days before" reminder. - Row 2:
day_offset: 0+compare_op: lt→ "fires oncedue_datehas passed".when_status_inincludesDUE_SOONso a warned checkout still escalates to overdue. - Neither sets
set_field, so they writestatus_field(status) itself. keyFieldsincludesday_offsetso the two rows for the same date column are distinct on re-install.
Status value vs. boolean flag
This module flips a status enum because that reads well on the checkout grid. A boolean flag works too: since 2026-09-10 the generic job coerces set_status_to: "true" / "false" to a real boolean (and numeric strings to numbers) before the write, so a config targeting a boolean/integer/numericset_field is fully supported. An earlier draft of this tutorial hit a SQL type error doing exactly that — that platform bug is fixed.
3. The job registers itself
The platform ships an AFTER_CREATE rule on entity_status_date_sweep_config that calls ensureEntityStatusDateSweepJobRegistered. So the first row you seed auto-registers the job for your tenant — you ship no register rule for this job (unlike the aggregation/cadence/compliance jobs).
Verify
bash
erp schema validate spk-assembly/metadata/seed-data/office-equipment-sweep-configs.json --schema plugin-seed-dataOK. After publish, the job is enabled:
bash
$ erp api get "/api/v1/jobs/engine-entity.status-date-sweep"
{ "jobCode": "engine-entity.status-date-sweep", "status": "ENABLED",
"cronExpression": "0 5 0 * * *", "concurrencyPolicy": "PER_TENANT" }This exact sequence was run against the tutorial module:
bash
# a CHECKED_OUT checkout whose due_date is in the past
$ erp api post "/api/v1/entities/oeq_checkout/records" \
--body '{"checkout_number":"CO-100","equipment_id":1,"employee_id":1,"checkout_date":"2026-08-01","due_date":"2026-09-04","status":"CHECKED_OUT"}'
{ "id": 2, "checkout_number": "CO-100", "status": "CHECKED_OUT" }
$ erp api post "/api/v1/jobs/engine-entity.status-date-sweep/execute" --body "{}"
{ "executionId": 534 }
$ erp api get "/api/v1/jobs/engine-entity.status-date-sweep/executions?size=1"
... "resultJson": "{\"swept\": 4, \"failed\": 0, \"rowsScanned\": 102, \"configsScanned\": 30}" ...
$ erp api get "/api/v1/entities/oeq_checkout/records/2"
{ "checkout_number": "CO-100", "status": "OVERDUE" }CHECKED_OUT → OVERDUE. "failed": 0. Verified end to end.
Common mistakes
set_fielda boolean/numeric column with an unparseableset_status_to(e.g."yes"into a boolean) → that row countsfailed. Use"true"/"false".when_status_incasing not matching the enum → nothing sweeps.- Forgot
day_offset→ the "3 days before" rule fires only on the exact day.