feat(apicore-sync): field-level ownership between ApiCore and the shop

ApiCore stays the source of truth for beekeeping facts, Wabenhain for
everything sales-related; both remain separate packages talking only over
ApiCore's HTTP API.

- Batches: lot number, fill date, best-before date and filled jar count
  now follow ApiCore on every run (before: created once, corrections never
  arrived). remainingGlasses - the shop's own stock - is never written; if
  it exceeds a corrected fill quantity, the run reports it instead of
  silently adjusting.
- Batches are matched by the new Batch.apicoreBottlingId instead of the lot
  number, so correcting a lot number in ApiCore no longer creates a second
  batch. Existing synced batches are adopted once via their lot number.
- Harvests: date and year always follow ApiCore, also when published or
  edited; type, location and text stay as maintained in the admin.
- Products stay entirely shop-owned after creation (weight drives the
  legally required unit price, so it is never changed automatically).
- Admin panel: batch update count and stock-conflict notice; intro text
  states which system owns which fields.

Migration is additive (nullable unique column).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-09-27 20:14:35 +02:00
1 parent 45ca0ea745
commit d38f4303ff
9 files changed
+272 -42

No files matched your search

@@ -0,0 +1,13 @@
-- Herkunftsschluessel fuer den ApiCore-Chargen-Sync: ID der Abfuellung
-- (BottlingBatch). Bisher wurde eine Charge nur ueber die Losnummer (code)
-- wiedererkannt — wird die Losnummer in ApiCore korrigiert, entstand beim
-- naechsten Lauf eine zweite Charge. Nullable: manuell angelegte Chargen
-- haben keine Herkunft in ApiCore, bestehende Zeilen bleiben gueltig. Schon
-- synchronisierte Chargen erhalten die ID beim naechsten Lauf ueber ihre
-- Losnummer.
-- AlterTable
ALTER TABLE "batches" ADD COLUMN "apicoreBottlingId" TEXT;
-- CreateIndex
CREATE UNIQUE INDEX "batches_apicoreBottlingId_key" ON "batches"("apicoreBottlingId");
+4
View File
@@ -178,6 +178,10 @@ model Batch {
id String @id @default(cuid())
/// z.B. FH-26-01
code String @unique
/// ApiCore-ID der Abfuellung (BottlingBatch), aus der diese Charge stammt.
/// Stabiler Zuordnungsschluessel fuer den Sync: die Losnummer (code) kann in
/// ApiCore korrigiert werden, die ID nicht. Null bei manuell angelegten Chargen.
apicoreBottlingId String? @unique
harvestId String
fillDate DateTime
bestBeforeDate DateTime