feat: ApiCore-Sync auf Chargen erweitern
Der bestehende Ernten-Sync (admin/ernten) laedt jetzt zusaetzlich Chargen aus ApiCore. Fachliche Zuordnung recherchiert direkt im ApiCore-Backend-Quellcode (../ApiCore/ApiCore-Backend): Wabenhains "Charge" (model Batch) entspricht ApiCores "BottlingBatch" (Schleuderung -> HoneyBatch -> Abfuellung -> BottlingBatch), NICHT "HoneyBatch" selbst — die Felder passen fast 1:1 (lotNumber/code, date/fillDate, bestBeforeDate/bestBeforeDate, jarCount/glassCount). - lib/apicore-client.ts: fetchApiCoreBottlingBatches() laedt GET /bottling-batches (inkl. verknuepfter HoneyBatch) und GET /extractions (inkl. verknuepfter Ernten) und loest daraus die zugehoerige ApiCore-Ernten-ID pro Charge auf. - admin/actions/apicore-sync.ts: Chargen-Sync laeuft nach dem Ernten-Sync (damit frisch angelegte Ernten schon als harvestId verfuegbar sind), legt Chargen NUR NEU an (nie Update) — anders als Harvest hat Batch kein isPublished-Feld, ein Update wuerde insbesondere remainingGlasses (echter, durch Verkaeufe veraenderter Lagerbestand) stillschweigend zuruecksetzen. Nicht-fatal: schlaegt nur der Chargen-Teil fehl, bleiben bereits synchronisierte Ernten erhalten. - admin/ernten/page.tsx + i18n: zeigt Chargen-Sync-Ergebnis separat an. - .env.example: zwei zusaetzliche ApiCore-Berechtigungen dokumentiert (extractions:read, bottling:read). Verifiziert: tsc --noEmit clean, 118/118 Tests gruen, pnpm build clean. Konnte nicht gegen einen echten ApiCore-Server getestet werden (siehe bereits bestehende Einschraenkung beim Ernten-Sync) — Feldnamen/Shape direkt aus ApiCore-Backends Prisma-Schema und Service-Code entnommen. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
5caa85ce3e
commit
d52753cfef
7 files changed
+231
-17
No files matched your search
@@ -8,7 +8,8 @@ import { getDictionary } from "@/i18n/get-dictionary";
|
||||
|
||||
export default async function AdminHarvestsPage(props: PageProps<"/admin/ernten">) {
|
||||
const t = getDictionary(await getLocale());
|
||||
const { synced, updated, skipped, failed, syncError } = await props.searchParams;
|
||||
const { synced, updated, skipped, failed, syncError, batchSynced, batchSkipped, batchFailed, batchLoadError } =
|
||||
await props.searchParams;
|
||||
const harvests = await prisma.harvest.findMany({
|
||||
orderBy: [{ year: "desc" }, { harvestDate: "desc" }],
|
||||
include: { _count: { select: { batches: true, products: true } } },
|
||||
@@ -29,6 +30,16 @@ export default async function AdminHarvestsPage(props: PageProps<"/admin/ernten"
|
||||
{t.adminHarvestsPage.syncError} ({syncError})
|
||||
</p>
|
||||
) : null}
|
||||
{batchSynced !== undefined ? (
|
||||
<p className="mb-6 text-sm text-forest bg-forest/5 border border-forest/20 px-4 py-3">
|
||||
{t.adminHarvestsPage.batchSyncResult(Number(batchSynced), Number(batchSkipped ?? 0), Number(batchFailed ?? 0))}
|
||||
</p>
|
||||
) : null}
|
||||
{batchLoadError !== undefined ? (
|
||||
<p className="mb-6 text-sm text-red-700 bg-red-50 border border-red-200 px-4 py-3">
|
||||
{t.adminHarvestsPage.batchSyncError} ({batchLoadError})
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="overflow-x-auto bg-background border border-ink/10">
|
||||
<table className="w-full text-sm">
|
||||
|
||||
Reference in new issue
Block a user