feat: T6 wave 2 – medicine book, document rights, label particulars, herd events
Backend Image / build-and-push (push) Successful in 6m34s
Frontend Image / build-and-push (push) Successful in 10m17s

- Veterinary medicine catalogue, lots and append-only movement ledger
  (rest always computed; corrections as counter-bookings; inactive
  medicines take no new stock; unit must match on lot moves).
- Documents of medicine lots, authority notices and restrictions need the
  domain right on top of documents:* (403 before any lookup).
- Label particulars: pure checkLabel with six mandatory gaps and four
  warnings, AFM font metrics, Berlin-day dates, geometric reading order
  for split addresses, new master-data fields with row-locked updates.
- Herd events ColonyCreated, ColonyMoved, ApiaryChanged and
  TskReferenceDayReached (ids only, never forwarded to webhooks); CSV
  import emits ColonyCreated with audit.
- ARCHITECTURE.md §12 Compliance (T6), Annahmen 59–70.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-15 13:43:44 +02:00
1 parent 8a31c42578
commit c18860c75c
73 files changed
+7121 -309

No files matched your search

+21 -1
View File
@@ -103,7 +103,11 @@ describe('Shop sync (e2e)', () => {
},
});
const product = await prisma.product.create({
data: { name: `Sommertracht 500 g ${suffix}`, sku: `SKU-${suffix}` },
data: {
name: `Sommertracht 500 g ${suffix}`,
sku: `SKU-${suffix}`,
legalName: `Rechtsname-${suffix}`,
},
});
productId = product.id;
const bottling = await prisma.bottlingBatch.create({
@@ -163,6 +167,22 @@ describe('Shop sync (e2e)', () => {
expect(raw).not.toContain('"userId"');
});
it('carries no label master data in the product payload', async () => {
const response = await request(app.getHttpServer())
.get('/api/v1/shop-sync')
.set('Authorization', `Bearer ${syncToken}`)
.expect(200);
const body = response.body as ShopSyncFeedBody;
const product = body.products.find((p) => p.id === productId);
expect(product).toBeDefined();
expect(product).not.toHaveProperty('legalName');
const raw = JSON.stringify(response.body);
expect(raw).not.toContain('legalName');
expect(raw).not.toContain('foodBusiness');
expect(raw).not.toContain(`Rechtsname-${suffix}`);
});
it('grants the sync account nothing beyond the feed', async () => {
await request(app.getHttpServer())
.get('/api/v1/harvests')