feat(stock): keep shop stock in sync with ApiCore, write sales back
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 3m40s
Docker Image bauen und veroeffentlichen / build-and-push (push) Successful in 3m40s
ApiCore now owns the remaining stock per batch; the shop sells from it and reports every paid sale and every return back. - Outbox apicore_stock_events, written in the same transaction as the status change: paid -> SALE, cancelled-after-payment / refunded return -> RETURN onto the batches of the sale, reopened paid order -> SALE. Whether a return is due is decided by the open sales in the outbox, so unpaid orders never book and nothing is booked twice. - Delivery right after the response (next/server after()) plus CronJob wabenhain-apicore-stock every 10 minutes with 1/5/15/60 min backoff; ApiCore deduplicates by event id. Rejected bookings stop and show up on the dashboard. - Reconcile: shop stock = ApiCore remaining - unconfirmed bookings - reservations of unpaid orders, in a serializable transaction like the checkout. Triggered after bookings, by the signed ApiCore webhook stock.changed (ids only, numbers are fetched) and by the sync button. - Manufactured goods (candles, propolis products, ...): one shop product per ApiCore article via Product.apicoreProductId, drafts created by the sync, existing products linkable in the product form; new category SONSTIGES. Stock field is read-only for linked products. - OrderItem.apicoreAllocations keeps which lots were sold (recalls). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
641afa1ae4
commit
93b589ff04
39 files changed
+1400
-37
No files matched your search
@@ -248,3 +248,55 @@ spec:
|
||||
# Derselbe Wert wie beim App-Container: der Lauf laedt
|
||||
# denselben Prisma-Client samt Treiber.
|
||||
memory: 512Mi
|
||||
---
|
||||
# Bestandsabgleich mit ApiCore (scripts/apicore-stock-sync.ts): sendet
|
||||
# liegengebliebene Verkaeufe/Rueckbuchungen an ApiCore und gleicht alle
|
||||
# verknuepften Produkte gegen den ApiCore-Restbestand ab. Sicherheitsnetz
|
||||
# unter dem Sofort-Versand und dem Webhook "stock.changed" — scheitert der
|
||||
# Lauf (ApiCore nicht erreichbar, Buchung abgelehnt), ist der Job rot.
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: wabenhain-apicore-stock
|
||||
namespace: wabenhain
|
||||
spec:
|
||||
schedule: "*/10 * * * *"
|
||||
concurrencyPolicy: Forbid
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 5
|
||||
startingDeadlineSeconds: 300
|
||||
jobTemplate:
|
||||
spec:
|
||||
backoffLimit: 1
|
||||
# Ein Lauf darf den naechsten nicht blockieren.
|
||||
activeDeadlineSeconds: 540
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
securityContext:
|
||||
runAsUser: 1001
|
||||
runAsGroup: 1001
|
||||
containers:
|
||||
- name: apicore-stock
|
||||
# DASSELBE Image und derselbe Tag wie in 05-app-deployment.yaml.
|
||||
image: git.encry.de/nick.rosenloecher/wabenhain:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
# Braucht DATABASE_URL, DATABASE_PROVIDER, APICORE_API_URL und
|
||||
# APICORE_API_KEY — dieselben Quellen wie die App.
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: wabenhain-config
|
||||
- secretRef:
|
||||
name: wabenhain-secrets
|
||||
command: ["/bin/sh", "-c"]
|
||||
args:
|
||||
- |
|
||||
set -eu
|
||||
node scripts/prisma-provider.mjs
|
||||
exec tsx scripts/apicore-stock-sync.ts
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
Reference in new issue
Block a user