- Shipped
- August 27, 2026 at 4:08 AM UTC
- Author
- Kamo
- Commit
- d20b75d
A priced task catalogue whose entries carry labourMinutes — the number that both prices a line and sizes a visit. ServiceLineItem.taskCode, landed in SW3, joins to ServiceTask.code BY VALUE and not by FK: the book is versioned, so a sold line must keep meaning what it meant when it was sold even after the entry is repriced or retired. ServiceTaskCategory mirrors ProductCategory rather than reusing it — ProductCategory is joined to Offering through ProductCategoryMapping, so sharing it would put "Drain clearing" and "Kitchen taps" in one tree. The effective window is lifted from hr/timecard/MemberPayRate. ServiceTask holds its book directly rather than reaching it through the optional category: t.category.book is an implicit join, which Hibernate renders as an inner join, so every uncategorised task would silently vanish from "the tasks in this book". columnDefinition is pinned on every FK and every element-collection join column. Verified by exporting the DDL from the mapping: no join column carries a DEFAULT, so an unset FK stays null instead of inventing a random parent id. Every repository read is org-scoped inside the query, never checked afterwards.