Four fields were still frozen because changing them would have bypassed the
record that makes the change traceable, and a user's login data could not be
corrected at all. Locking a field is the wrong trade: a wrong value stays in
the system forever. The fix is to let the edit write the same history entry the
dedicated endpoint writes.
- A colony's apiary is editable through PATCH and writes the same
ColonyApiaryHistory entry POST /colonies/:id/move writes, so the location
history never skips a stand the colony was recorded on.
- A honey batch's storage container is editable through PATCH and writes the
same HoneyBatchRelocation entry POST /honey-batches/:id/relocate writes.
- A stock item's quantity is editable and books the difference as an ADJUSTMENT
movement, so the stored level stays the sum of its movements.
- A role's key is editable (system roles were already rejected outright by
RolesService.update, which keeps the seed's ADMIN lookup intact).
- A user's e-mail - the login identity - is editable. A typo there previously
locked the account out for good.
- New POST /users/:id/reset-password lets an administrator set someone else's
password: there is no self-service reset flow, so a forgotten password was
the one thing no edit could repair. It revokes every refresh token and clears
the permission cache exactly as a self-service change does, refuses to act on
your own account (that goes through /profile/password, which proves ownership
by asking for the current one), and never writes the password to the log.
Frontend:
- Users had no edit UI at all, although PATCH /users/:id existed. New
EditUserDialog covers name, e-mail, role and an optional new password.
- Colony, honey batch and stock item forms gained the newly editable fields,
each with a note saying the correction is recorded as a move, a relocation
or a stock adjustment.
- The role dialog gained the key field.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
An inspection, treatment, feeding, varroa measurement or swarm control check
filed against the wrong colony could not be repaired: the colony was frozen at
creation time, and with no delete endpoint either, the only remedy was leaving
a wrong record in the colony's history. The same held for a harvest booked
against the wrong apiary or with a colony forgotten, for an extraction linked
to the wrong harvests, and for a honey batch whose number or source extraction
was mistyped.
Backend:
- The five colony-scoped update DTOs now cover the full create DTO, colonyId
included.
- Harvest update accepts apiaryId and colonyIds, extraction update accepts
harvestIds. Both validate the ids first and replace the whole join-row set
inside the existing transaction; the join rows carry no data of their own,
so replacing beats diffing.
- Honey batch update accepts batchNumber, extractionId and status. Status was
previously only ever set to BOTTLED by the bottling module, so SOLD and
CONSUMED were unreachable through the API.
- Colony and storage container codes, and a task's relatedType/relatedId, are
editable.
- apiaryId on a colony and storageContainerId on a honey batch stay out of
PATCH on purpose: both have dedicated endpoints that also write the history
entry (ColonyApiaryHistory, HoneyBatchRelocation) the traceability chain
depends on.
- AllExceptionsFilter now also translates Prisma P2003 to a 400 and P2025 to a
404. Services write straight against the foreign keys with no application
level existence check, so before this a stale or mistyped relation id came
back as a bare 500 and filled the log with fake server errors.
Frontend:
- New shared fields: ColonySelectField (used by all five colony-scoped edit
dialogs), HarvestSelectField (both extraction dialogs) and TaskRelatedField.
- Re-filing a record invalidates the lists of both the colony it left and the
one it joined, otherwise one of the two stays stale.
- The harvest dialog gained an apiary select and a colony checklist that keeps
already-linked colonies visible even when they moved or were dissolved; the
honey batch dialog gained batch number, source extraction and status.
- Extraction and harvest forms refuse to submit an empty relation set instead
of letting the backend reject it.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
None of these numeric business fields had a lower bound, so a
negative honey weight, jar count, feeding amount, mite count, or
stock quantity was silently accepted - each would corrupt whatever
total or statistic it later feeds into. Added @Min(0):
- Harvest: honeySuperCount, grossWeight, netWeight
- HoneyBatch: amount (+ @Max(100) on waterContent, a percentage)
- HoneyMeasurement: waterContent (+ @Max(100))
- Feeding: amount
- Extraction: amount (+ @Max(100) on waterContent)
- StockItem: quantity, minThreshold
- VarroaMeasurement: durationMinutes, miteCount, calculatedValue
Left temperature fields alone (extraction, inspection) - genuinely
can be negative (winter inspections, outdoor storage) and no
confident domain bound exists to apply instead. Update DTOs for these
entities all extend PartialType(PickType(Create...Dto, [...])) from
@nestjs/swagger, which preserves validation decorators, so no
separate change was needed there.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
A batch that doesn't fit in one container (e.g. 125 kg across 5 x 25 kg
buckets) had no way to be represented - HoneyBatch.storageContainerId
is a single nullable FK. Adds HoneyBatchContainerAllocation as an
additive join table (container + amount per batch), independent of the
existing single-container/relocate() flow which still covers the
simple one-container case unchanged.
- GET/PUT/DELETE /honey-batches/:id/containers[/:containerId], reusing
the existing honey-batches:relocate permission.
- Assigning a container is an upsert (@@unique on batch+container), and
the total assigned is validated against the batch's own amount when
known.
- New "Aufteilung auf mehrere Behälter" card on the honey batch detail
page, alongside (not replacing) the existing storage card.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
- SiteSettings gains websiteUrl (e.g. online shop link) alongside the
existing social links, editable in Verwaltung > Automatisierung.
- /herkunft/[lot] now shows the apiary's Standort instead of its internal
Name (so multiple apiaries at one location read as one origin), adds
small icons per social link, and surfaces previously-fetched-but-unused
data (Honigsorte, Abfülldatum, stat cards) to make the page a richer
customer-facing info page.
- Backup schedule (path/cron/retention) is now also configurable via the
GUI (Verwaltung > Backup), stored in a new BackupSettings singleton;
an env var always wins over the GUI value per field, and the scheduler
reloads its cron job live when GUI settings change.
- New Automatisierung rules let an admin define a format (e.g.
"WH-{YYYY}-{SEQ:4}") that auto-generates HoneyBatch.batchNumber and
BottlingBatch.lotNumber on creation, with an atomic per-rule sequence
counter and a manual reset. Manual entry still works when the rule is
inactive.
Neues HoneyBatchRelocation-Modell dokumentiert jede Umlagerung einer
Honigcharge zwischen Lagerbehältern (von/nach, Zeitpunkt, Benutzer,
Notiz). HoneyBatchesService.relocate() aktualisiert
HoneyBatch.storageContainerId transaktional zusammen mit dem
Historieneintrag; wirft NotFoundException bei unbekanntem Zielbehälter.
Neue Endpunkte: POST /honey-batches/:id/relocate,
GET /honey-batches/:id/relocations. honeyBatchInclude liefert jetzt
zusätzlich den aktuell zugeordneten storageContainer mit.
Unit- und E2E-Tests ergänzt (Mehrfachumlagerung, Historienreihenfolge,
404 bei unbekanntem Behälter). Migration auf Dev- und Test-Datenbank
angewendet.
HoneyBatchesModule inkl. Honigmessungen und
Rückverfolgbarkeits-Endpunkt, der eine Charge über die Schleuderung
und Ernte bis zu den Ursprungsvölkern zurückverfolgt.