werkator/jvm build succeeded after 09:39
Each habit limit gets an inner level (yellow) and an outer level (red); existing limits become the inner ones. Plan in werkjournal.werkbaum #habit-limit-levels, scenarios WJ-067 to WJ-072. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #7 Co-authored-by: claude-code <claude-code@javagil.de>
16 lines
4.5 KiB
Markdown
16 lines
4.5 KiB
Markdown
# Tracking JSON import
|
|
|
|
Reports offers an Import JSON dialog beside Export JSON. It reads a schema version 1 file as written by the export and adds its records to the signed-in account. Nothing is changed and nothing is deleted: a record the account already holds is counted as already present, so the same file twice adds nothing. Removing single records stays a manual step in the normal screens. The upload goes through a Vaadin session resource, not a public endpoint, and the whole file is applied in one owner transaction, so a rejected file leaves no partial state.
|
|
|
|
Identity is the record, not its stored key. Customers, projects and habits match by name, case- and whitespace-insensitively as the catalog's own uniqueness does; a project matches within its customer. Work entries match by day, customer, project, hours and description, which also means two identical bookings of one day collapse into one. Habit days, day-off markers and weekly limit changes match by their own natural key. Stored keys are unique across all accounts: an imported key is reused when it is still free and replaced by a fresh one otherwise, which is what happens to every record of a file exported from another account.
|
|
|
|
Both shapes of file are therefore accepted. An export points at its records by key, with `customerId`, `projectId` and `habitId` and the `customers`, `projects` and `habits` sections those keys refer to. A file written by hand instead names them inline, as `customer`, `project` and `habit`, and needs no sections and no `id` on any record at all; a name the account does not hold yet is created and counted in that record's own section. Exactly one of the two forms per reference: both the key and the name is refused rather than silently preferring one, and neither is a missing reference. A key may also point at a record the file omits, as long as the account holds it, so a trimmed export still works.
|
|
|
|
Refused with the position in the file and nothing applied: an unreadable file, a schema version other than 1, a field the schema does not define at any level, an invalid value (hours outside one to twelve, a negative count, a description beyond two thousand characters, a blank name, a malformed date or key, an effective date that is not a Monday, limits out of the order outer minimum ≤ minimum ≤ maximum ≤ outer maximum; outer limits a file lacks are unset), a reference given twice or not at all, a key naming a record neither the file nor the account carries, work or a habit count dated after today, and a day whose hours would exceed the twelve the editor allows. Day-off markers may lie ahead, as they may when set by hand. Archived customers and projects and inactive habits are added in that state, and an existing record keeps its own name and state.
|
|
|
|
Existence checks deliberately avoid jOOQ's `fetchExists`, which renders `exists (subquery)`. H2 2.4.240 answers a repeated subquery of identical text and parameters with its first result for the rest of an uncommitted transaction: the second of two identical work entries in one file looked absent and was written twice. Reproduced with plain JDBC against H2 alone, without jOOQ, and confined to one open transaction — the answer is correct again after a commit, so no other service is affected, since each of those writes at most one record per table after its check. A plain row lookup is not cached that way and is used throughout the import.
|
|
|
|
Validation covers a complete file from another account including minted keys and an untouched source, the same file twice, an account reading back its own export, a changed record of the same name and key landing beside the original, an existing habit count and a removed day-off marker surviving, the daily hour limit rolling back a whole file, future dates, unknown schema versions and fields, invalid values with their position, missing references including a crossed customer and project pair, omitted sections, two records of one name in one file, repeated bookings and blank descriptions, a hand-written file of names without a single key, names the account lacks being created once however often they recur, one project name under two customers, and a reference given twice or not at all: nineteen service cases. WJ-066 imports a file from another journal through the actual dialog in Chromium and Firefox, checks the added and already-present counts per section, that her own records are unchanged, and that a second import of the same file adds nothing.
|
|
|
|
Verified locally on 2026-10-09 for 0.1.117-SNAPSHOT, and again on 2026-10-12 for 0.1.118-SNAPSHOT after names were accepted inline.
|