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:
1 parent
45ca0ea745
commit
d38f4303ff
9 files changed
+272
-42
No files matched your search
@@ -1131,12 +1131,12 @@ export const en: Dictionary = {
|
||||
adminApiCoreSync: {
|
||||
heading: "ApiCore sync",
|
||||
intro:
|
||||
"Fetches harvests, batches and products from ApiCore in one run — in that order, because each step builds on the previous one. Harvests and products are created as drafts: harvests unpublished, products inactive and without a price, because ApiCore does not hold sales prices. Each bottling run becomes its own vintage. Entries already released or edited in the admin are never overwritten; internal ApiCore notes are not copied.",
|
||||
"Fetches harvests, batches and products from ApiCore in one run — in that order, because each step builds on the previous one. Harvests and products are created as drafts: harvests unpublished, products inactive and without a price, because ApiCore does not hold sales prices. Each bottling run becomes its own vintage. Beekeeping facts (dates, lot number, best-before date, filled quantity) always come from ApiCore; texts, prices, images, visibility and shop stock stay as maintained here. Internal ApiCore notes are not copied.",
|
||||
button: "Sync everything",
|
||||
resultHarvests: (created, updated, skipped, failed) =>
|
||||
`Harvests: ${created} created, ${updated} updated, ${skipped} skipped${failed > 0 ? `, ${failed} failed` : ""}.`,
|
||||
resultBatches: (created, skipped, failed) =>
|
||||
`Batches: ${created} created, ${skipped} skipped${failed > 0 ? `, ${failed} failed (see server log)` : ""}.`,
|
||||
resultBatches: (created, updated, skipped, failed) =>
|
||||
`Batches: ${created} created, ${updated} updated, ${skipped} unchanged${failed > 0 ? `, ${failed} failed (see server log)` : ""}.`,
|
||||
resultProducts: (created, skipped, failed) =>
|
||||
`Products: ${created} new vintage${created === 1 ? "" : "s"}, ${skipped} skipped${failed > 0 ? `, ${failed} failed (see server log)` : ""}.`,
|
||||
pending: (count) =>
|
||||
@@ -1144,7 +1144,9 @@ export const en: Dictionary = {
|
||||
discontinued: (count) =>
|
||||
`${count} bottling run${count === 1 ? "" : "s"} belong to an article ApiCore no longer carries, so no new vintage was created. Existing ones stay on sale.`,
|
||||
protectedDrafts: (count) =>
|
||||
`${count} harvest draft${count === 1 ? " was" : "s were"} already edited in the admin and therefore not overwritten.`,
|
||||
`${count} harvest draft${count === 1 ? " was" : "s were"} already edited in the admin: type, location and text stay, only date and year come from ApiCore.`,
|
||||
stockConflicts: (count) =>
|
||||
`For ${count} batch${count === 1 ? "" : "es"} the shop stock exceeds the quantity filled according to ApiCore. Please check the stock under batches — it was not changed automatically.`,
|
||||
lastRun: (when) => `Last complete run: ${when}`,
|
||||
neverRun: "No complete run yet.",
|
||||
error: "Sync with ApiCore failed.",
|
||||
|
||||
Reference in new issue
Block a user