diff --git a/backend/src/main/resources/db/changelog/changes/099-seed-testdata.sql b/backend/src/main/resources/db/changelog/changes/099-seed-testdata.sql new file mode 100644 index 0000000..efdf175 --- /dev/null +++ b/backend/src/main/resources/db/changelog/changes/099-seed-testdata.sql @@ -0,0 +1,567 @@ +-- ============================================================================ +-- Effigenix ERP – Seed-Testdaten: "Effigenix Fleischerei & Feinkost" +-- ============================================================================ +-- Manuell einspielen: psql -d effigenix -f 099-seed-testdata.sql +-- NICHT im Liquibase-Changelog eingetragen! +-- +-- Voraussetzung: Rollen, Permissions und Admin-User existieren bereits +-- (via 002-seed-roles-and-permissions, 004-seed-admin-user, etc.) +-- ============================================================================ + +BEGIN; + +-- ============================================================================ +-- 1. USERS (6 Mitarbeiter) +-- ============================================================================ +-- Passwort für alle: "test1234" (bcrypt) +-- $2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa + +INSERT INTO users (id, username, email, password_hash, branch_id, status, created_at) +VALUES + ('10000000-0000-0000-0000-000000000001', 'mweber', 'markus.weber@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP), + ('10000000-0000-0000-0000-000000000002', 'sfischer', 'sabine.fischer@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP), + ('10000000-0000-0000-0000-000000000003', 'tmueller', 'thomas.mueller@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP), + ('10000000-0000-0000-0000-000000000004', 'kschneider','katrin.schneider@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP), + ('10000000-0000-0000-0000-000000000005', 'pbraun', 'peter.braun@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP), + ('10000000-0000-0000-0000-000000000006', 'lkrause', 'lisa.krause@effigenix.de', '$2a$12$LJ3m4ys3uz2YPMRvKbmrZOZHAMSKL4FBy.XLR3WnCKsMbVDfGKJVa', NULL, 'ACTIVE', CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +-- Rollenzuweisungen +-- mweber = Produktionsleiter +-- sfischer = Einkaufsleiterin +-- tmueller = Lagerarbeiter +-- kschneider = Qualitätsmanagerin +-- pbraun = Verkaufsleiter +-- lkrause = Verkauf +INSERT INTO user_roles (user_id, role_id) VALUES + ('10000000-0000-0000-0000-000000000001', 'c0a80121-0000-0000-0000-000000000002'), -- mweber → PRODUCTION_MANAGER + ('10000000-0000-0000-0000-000000000002', 'c0a80121-0000-0000-0000-000000000006'), -- sfischer → PROCUREMENT_MANAGER + ('10000000-0000-0000-0000-000000000003', 'c0a80121-0000-0000-0000-000000000007'), -- tmueller → WAREHOUSE_WORKER + ('10000000-0000-0000-0000-000000000004', 'c0a80121-0000-0000-0000-000000000004'), -- kschneider → QUALITY_MANAGER + ('10000000-0000-0000-0000-000000000005', 'c0a80121-0000-0000-0000-000000000008'), -- pbraun → SALES_MANAGER + ('10000000-0000-0000-0000-000000000006', 'c0a80121-0000-0000-0000-000000000009') -- lkrause → SALES_STAFF +ON CONFLICT (user_id, role_id) DO NOTHING; + + +-- ============================================================================ +-- 2. PRODUCT CATEGORIES +-- ============================================================================ + +INSERT INTO product_categories (id, name, description) VALUES + ('20000000-0000-0000-0000-000000000001', 'Frischfleisch', 'Frisches Schweine-, Rind- und Geflügelfleisch'), + ('20000000-0000-0000-0000-000000000002', 'Wurstwaren', 'Brüh-, Koch- und Rohwurst, Schinken'), + ('20000000-0000-0000-0000-000000000003', 'Gewürze & Zusätze', 'Gewürzmischungen, Pökelsalz, Naturdärme'), + ('20000000-0000-0000-0000-000000000004', 'Verpackung', 'Folien, Schalen, Etiketten'), + ('20000000-0000-0000-0000-000000000005', 'Feinkost', 'Salate, Aufstriche, marinierte Produkte'), + ('20000000-0000-0000-0000-000000000006', 'Convenience', 'Fertiggerichte, Grillspezialitäten') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 3. SUPPLIERS (5 Lieferanten) +-- ============================================================================ + +INSERT INTO suppliers (id, name, phone, email, contact_person, + street, house_number, postal_code, city, country, + payment_due_days, payment_description, + quality_score, delivery_score, price_score, + status, created_at, updated_at) VALUES + ('30000000-0000-0000-0000-000000000001', + 'Bayerische Fleischwerke GmbH', '+49 89 12345678', 'einkauf@bay-fleisch.de', 'Hans Gruber', + 'Schlachthofstr.', '12', '80339', 'München', 'DE', + 30, 'Netto 30 Tage', 5, 4, 3, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('30000000-0000-0000-0000-000000000002', + 'Gewürzkontor Franken', '+49 911 9876543', 'bestellung@gewuerzkontor.de', 'Maria Lehmann', + 'Industrieweg', '7', '90411', 'Nürnberg', 'DE', + 14, 'Netto 14 Tage, 2% Skonto bei 7 Tagen', 5, 5, 4, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('30000000-0000-0000-0000-000000000003', + 'PackPro Verpackungen AG', '+49 711 5551234', 'vertrieb@packpro.de', 'Stefan Maier', + 'Am Containerhafen', '3', '70327', 'Stuttgart', 'DE', + 45, 'Netto 45 Tage', 4, 3, 5, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('30000000-0000-0000-0000-000000000004', + 'Naturdarm Schmidt OHG', '+49 40 8887766', 'info@naturdarm-schmidt.de', 'Klaus Schmidt', + 'Elbchaussee', '201', '22605', 'Hamburg', 'DE', + 21, 'Netto 21 Tage', 5, 4, 4, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('30000000-0000-0000-0000-000000000005', + 'Alpenrind Tirol KG', '+43 512 334455', 'verkauf@alpenrind.at', 'Franz Hofer', + 'Brennerstr.', '88', '6020', 'Innsbruck', 'AT', + 30, 'Netto 30 Tage', 4, 4, 3, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +-- Zertifikate +INSERT INTO quality_certificates (supplier_id, certificate_type, issuer, valid_from, valid_until) VALUES + ('30000000-0000-0000-0000-000000000001', 'IFS Food', 'TÜV Süd', '2025-03-01', '2026-02-28'), + ('30000000-0000-0000-0000-000000000001', 'Bio-Zertifikat', 'DE-ÖKO-006', '2025-01-01', '2025-12-31'), + ('30000000-0000-0000-0000-000000000002', 'IFS Food', 'DQS GmbH', '2025-06-01', '2026-05-31'), + ('30000000-0000-0000-0000-000000000004', 'EU-Zulassung', 'LAVES Niedersachsen', '2024-01-01', NULL), + ('30000000-0000-0000-0000-000000000005', 'AMA-Gütesiegel', 'AMA Marketing', '2025-01-01', '2026-12-31'), + ('30000000-0000-0000-0000-000000000005', 'Bio Austria', 'Austria Bio Garantie', '2025-04-01', '2026-03-31') +ON CONFLICT (supplier_id, certificate_type, valid_from) DO NOTHING; + + +-- ============================================================================ +-- 4. ARTICLES (18 Artikel) +-- ============================================================================ + +-- Frischfleisch +INSERT INTO articles (id, name, article_number, category_id, status, created_at, updated_at) VALUES + ('40000000-0000-0000-0000-000000000001', 'Schweineschulter ohne Knochen', 'FF-001', '20000000-0000-0000-0000-000000000001', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000002', 'Schweinebauch frisch', 'FF-002', '20000000-0000-0000-0000-000000000001', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000003', 'Rindfleisch Oberschale', 'FF-003', '20000000-0000-0000-0000-000000000001', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000004', 'Schweineleber frisch', 'FF-004', '20000000-0000-0000-0000-000000000001', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000005', 'Speck durchwachsen', 'FF-005', '20000000-0000-0000-0000-000000000001', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +-- Wurstwaren (Endprodukte) + ('40000000-0000-0000-0000-000000000006', 'Hausmacher Bratwurst', 'WW-001', '20000000-0000-0000-0000-000000000002', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000007', 'Kräuter-Leberwurst fein', 'WW-002', '20000000-0000-0000-0000-000000000002', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000008', 'Schinkenspeck geräuchert', 'WW-003', '20000000-0000-0000-0000-000000000002', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +-- Gewürze & Zusätze + ('40000000-0000-0000-0000-000000000009', 'Bratwurstgewürz Classic', 'GZ-001', '20000000-0000-0000-0000-000000000003', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000010', 'Pökelsalz NPS 0,5%', 'GZ-002', '20000000-0000-0000-0000-000000000003', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000011', 'Kräutermischung Leberwurst', 'GZ-003', '20000000-0000-0000-0000-000000000003', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000012', 'Schweinedarm Kaliber 28/30', 'GZ-004', '20000000-0000-0000-0000-000000000003', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000013', 'Räucherchips Buche', 'GZ-005', '20000000-0000-0000-0000-000000000003', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +-- Verpackung + ('40000000-0000-0000-0000-000000000014', 'Vakuumbeutel 20x30cm', 'VP-001', '20000000-0000-0000-0000-000000000004', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000015', 'Metzgerpapier Rolle 50cm', 'VP-002', '20000000-0000-0000-0000-000000000004', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +-- Feinkost + ('40000000-0000-0000-0000-000000000016', 'Fleischsalat hausgemacht', 'FK-001', '20000000-0000-0000-0000-000000000005', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + +-- Convenience + ('40000000-0000-0000-0000-000000000017', 'Currywurst mit Soße', 'CV-001', '20000000-0000-0000-0000-000000000006', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('40000000-0000-0000-0000-000000000018', 'Grillpaket Klassik', 'CV-002', '20000000-0000-0000-0000-000000000006', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +-- Sales Units (Unit-Enum: KG, HUNDRED_GRAM, PIECE_FIXED, PIECE_VARIABLE) +-- (PriceModel-Enum: KG/HUNDRED_GRAM/PIECE_VARIABLE → WEIGHT_BASED, PIECE_FIXED → FIXED) +INSERT INTO sales_units (id, article_id, unit, price_model, price_amount, price_currency) VALUES + -- Frischfleisch: pro kg + ('50000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000001', 'KG', 'WEIGHT_BASED', 6.50, 'EUR'), + ('50000000-0000-0000-0000-000000000002', '40000000-0000-0000-0000-000000000002', 'KG', 'WEIGHT_BASED', 5.80, 'EUR'), + ('50000000-0000-0000-0000-000000000003', '40000000-0000-0000-0000-000000000003', 'KG', 'WEIGHT_BASED', 14.90, 'EUR'), + ('50000000-0000-0000-0000-000000000004', '40000000-0000-0000-0000-000000000004', 'KG', 'WEIGHT_BASED', 4.20, 'EUR'), + ('50000000-0000-0000-0000-000000000005', '40000000-0000-0000-0000-000000000005', 'KG', 'WEIGHT_BASED', 7.90, 'EUR'), + -- Wurstwaren + ('50000000-0000-0000-0000-000000000006', '40000000-0000-0000-0000-000000000006', 'KG', 'WEIGHT_BASED', 12.90, 'EUR'), + ('50000000-0000-0000-0000-000000000007', '40000000-0000-0000-0000-000000000006', 'PIECE_FIXED', 'FIXED', 2.50, 'EUR'), + ('50000000-0000-0000-0000-000000000008', '40000000-0000-0000-0000-000000000007', 'KG', 'WEIGHT_BASED', 11.50, 'EUR'), + ('50000000-0000-0000-0000-000000000009', '40000000-0000-0000-0000-000000000008', 'KG', 'WEIGHT_BASED', 18.90, 'EUR'), + -- Gewürze + ('50000000-0000-0000-0000-000000000010', '40000000-0000-0000-0000-000000000009', 'HUNDRED_GRAM', 'WEIGHT_BASED', 2.20, 'EUR'), + ('50000000-0000-0000-0000-000000000011', '40000000-0000-0000-0000-000000000010', 'KG', 'WEIGHT_BASED', 1.80, 'EUR'), + ('50000000-0000-0000-0000-000000000012', '40000000-0000-0000-0000-000000000011', 'HUNDRED_GRAM', 'WEIGHT_BASED', 2.80, 'EUR'), + ('50000000-0000-0000-0000-000000000013', '40000000-0000-0000-0000-000000000012', 'PIECE_FIXED', 'FIXED', 0.35, 'EUR'), + ('50000000-0000-0000-0000-000000000014', '40000000-0000-0000-0000-000000000013', 'KG', 'WEIGHT_BASED', 8.50, 'EUR'), + -- Verpackung + ('50000000-0000-0000-0000-000000000015', '40000000-0000-0000-0000-000000000014', 'PIECE_FIXED', 'FIXED', 0.12, 'EUR'), + ('50000000-0000-0000-0000-000000000016', '40000000-0000-0000-0000-000000000015', 'PIECE_FIXED', 'FIXED', 18.50, 'EUR'), + -- Feinkost & Convenience + ('50000000-0000-0000-0000-000000000017', '40000000-0000-0000-0000-000000000016', 'KG', 'WEIGHT_BASED', 9.90, 'EUR'), + ('50000000-0000-0000-0000-000000000018', '40000000-0000-0000-0000-000000000017', 'PIECE_FIXED', 'FIXED', 3.90, 'EUR'), + ('50000000-0000-0000-0000-000000000019', '40000000-0000-0000-0000-000000000018', 'PIECE_FIXED', 'FIXED', 24.90, 'EUR') +ON CONFLICT (id) DO NOTHING; + +-- Lieferantenzuordnungen +INSERT INTO article_suppliers (article_id, supplier_id) VALUES + -- Bay. Fleischwerke liefert Frischfleisch + ('40000000-0000-0000-0000-000000000001', '30000000-0000-0000-0000-000000000001'), + ('40000000-0000-0000-0000-000000000002', '30000000-0000-0000-0000-000000000001'), + ('40000000-0000-0000-0000-000000000004', '30000000-0000-0000-0000-000000000001'), + ('40000000-0000-0000-0000-000000000005', '30000000-0000-0000-0000-000000000001'), + -- Alpenrind liefert Rindfleisch + Schweineschulter + ('40000000-0000-0000-0000-000000000003', '30000000-0000-0000-0000-000000000005'), + ('40000000-0000-0000-0000-000000000001', '30000000-0000-0000-0000-000000000005'), + -- Gewürzkontor liefert Gewürze + ('40000000-0000-0000-0000-000000000009', '30000000-0000-0000-0000-000000000002'), + ('40000000-0000-0000-0000-000000000010', '30000000-0000-0000-0000-000000000002'), + ('40000000-0000-0000-0000-000000000011', '30000000-0000-0000-0000-000000000002'), + ('40000000-0000-0000-0000-000000000013', '30000000-0000-0000-0000-000000000002'), + -- Naturdarm Schmidt liefert Därme + ('40000000-0000-0000-0000-000000000012', '30000000-0000-0000-0000-000000000004'), + -- PackPro liefert Verpackung + ('40000000-0000-0000-0000-000000000014', '30000000-0000-0000-0000-000000000003'), + ('40000000-0000-0000-0000-000000000015', '30000000-0000-0000-0000-000000000003') +ON CONFLICT (article_id, supplier_id) DO NOTHING; + + +-- ============================================================================ +-- 5. CUSTOMERS (5 Kunden) +-- ============================================================================ + +INSERT INTO customers (id, name, type, phone, email, contact_person, + billing_street, billing_house_number, billing_postal_code, billing_city, billing_country, + payment_due_days, payment_description, status, created_at, updated_at) VALUES + ('60000000-0000-0000-0000-000000000001', + 'REWE Markt Obermenzing', 'B2B', '+49 89 44556677', 'filiale.obermenzing@rewe.de', 'Andrea Huber', + 'Verdistr.', '55', '81247', 'München', 'DE', + 30, 'Netto 30 Tage', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('60000000-0000-0000-0000-000000000002', + 'Gasthof zum goldenen Hirsch', 'B2B', '+49 89 33221100', 'kueche@goldener-hirsch.de', 'Ludwig Meier', + 'Hauptstr.', '12', '82041', 'Oberhaching', 'DE', + 14, 'Netto 14 Tage', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('60000000-0000-0000-0000-000000000003', + 'Kantinenbetrieb Siemens Campus', 'B2B', '+49 89 72233445', 'einkauf@siemens-kantine.de', 'Petra Zimmermann', + 'Werner-von-Siemens-Str.', '1', '80333', 'München', 'DE', + 45, 'Netto 45 Tage, Sammelrechnung monatlich', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('60000000-0000-0000-0000-000000000004', + 'Metzgerei Weber Stammkunde', 'B2C', '+49 171 9988776', 'familie.weber@gmx.de', NULL, + 'Rosenweg', '8', '82049', 'Pullach', 'DE', + NULL, NULL, 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('60000000-0000-0000-0000-000000000005', + 'Feinkost Dallmayr', 'B2B', '+49 89 21350', 'einkauf@dallmayr.de', 'Maximilian Sedlmayr', + 'Dienerstr.', '14-15', '80331', 'München', 'DE', + 60, 'Netto 60 Tage, Qualitätsprüfung bei Anlieferung', 'ACTIVE', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +-- Lieferadressen +INSERT INTO delivery_addresses (customer_id, label, street, house_number, postal_code, city, country, contact_person, delivery_notes) VALUES + ('60000000-0000-0000-0000-000000000001', 'Warenannahme', 'Verdistr.', '55', '81247', 'München', 'DE', 'Hr. Kohl (Warenannahme)', 'Anlieferung Mo-Sa 6:00-10:00, Rampe 3'), + ('60000000-0000-0000-0000-000000000002', 'Küche Hintereingang', 'Hauptstr.', '12a', '82041', 'Oberhaching', 'DE', 'Küchenchef Ludwig Meier', 'Kühltransport erforderlich, Hintereingang benutzen'), + ('60000000-0000-0000-0000-000000000003', 'Kantine Bau 1', 'Werner-von-Siemens-Str.', '1', '80333', 'München', 'DE', 'Fr. Zimmermann', 'Zufahrt über Tor West, Ausweispflicht'), + ('60000000-0000-0000-0000-000000000003', 'Kantine Bau 7', 'Otto-Hahn-Ring', '6', '81739', 'München', 'DE', 'Hr. Berger', 'Neuperlach Campus, Rampe B'), + ('60000000-0000-0000-0000-000000000005', 'Delikatessenhaus', 'Dienerstr.', '14-15', '80331', 'München', 'DE', 'Fr. Sedlmayr', 'Anlieferung nur 5:00-7:00, Kühlkette dokumentieren'); + +-- Kundenpräferenzen (Enum: BIO, REGIONAL, TIERWOHL, HALAL, KOSHER, GLUTENFREI, LAKTOSEFREI) +INSERT INTO customer_preferences (customer_id, preference) VALUES + ('60000000-0000-0000-0000-000000000001', 'BIO'), + ('60000000-0000-0000-0000-000000000001', 'REGIONAL'), + ('60000000-0000-0000-0000-000000000002', 'REGIONAL'), + ('60000000-0000-0000-0000-000000000003', 'HALAL'), + ('60000000-0000-0000-0000-000000000005', 'BIO'), + ('60000000-0000-0000-0000-000000000005', 'TIERWOHL') +ON CONFLICT (customer_id, preference) DO NOTHING; + +-- Rahmenvertrag REWE +INSERT INTO frame_contracts (id, customer_id, valid_from, valid_until, delivery_rhythm) VALUES + ('70000000-0000-0000-0000-000000000001', '60000000-0000-0000-0000-000000000001', '2026-01-01', '2026-12-31', 'BIWEEKLY') +ON CONFLICT (id) DO NOTHING; + +INSERT INTO contract_line_items (frame_contract_id, article_id, agreed_price_amount, agreed_price_currency, agreed_quantity, unit) VALUES + ('70000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000006', 11.50, 'EUR', 20.0000, 'KG'), + ('70000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000007', 10.20, 'EUR', 10.0000, 'KG'), + ('70000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000008', 17.50, 'EUR', 5.0000, 'KG') +ON CONFLICT (frame_contract_id, article_id) DO NOTHING; + + +-- ============================================================================ +-- 6. STORAGE LOCATIONS (5 Lagerorte) +-- ============================================================================ + +INSERT INTO storage_locations (id, name, storage_type, min_temperature, max_temperature, active) VALUES + ('80000000-0000-0000-0000-000000000001', 'Kühlraum 1 (Fleisch)', 'COLD_ROOM', 0.0, 4.0, true), + ('80000000-0000-0000-0000-000000000002', 'Tiefkühler', 'FREEZER', -22.0, -18.0, true), + ('80000000-0000-0000-0000-000000000003', 'Trockenlager', 'DRY_STORAGE', 15.0, 25.0, true), + ('80000000-0000-0000-0000-000000000004', 'Verkaufstheke', 'DISPLAY_COUNTER', 0.0, 7.0, true), + ('80000000-0000-0000-0000-000000000005', 'Produktionsraum', 'PRODUCTION_AREA', 8.0, 12.0, true) +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 7. STOCKS (Bestandseinträge) +-- ============================================================================ + +INSERT INTO stocks (id, article_id, storage_location_id, minimum_level_amount, minimum_level_unit, minimum_shelf_life_days) VALUES + -- Frischfleisch im Kühlraum + ('90000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000001', '80000000-0000-0000-0000-000000000001', 50.000, 'KILOGRAM', 3), + ('90000000-0000-0000-0000-000000000002', '40000000-0000-0000-0000-000000000002', '80000000-0000-0000-0000-000000000001', 30.000, 'KILOGRAM', 3), + ('90000000-0000-0000-0000-000000000003', '40000000-0000-0000-0000-000000000003', '80000000-0000-0000-0000-000000000001', 20.000, 'KILOGRAM', 3), + ('90000000-0000-0000-0000-000000000004', '40000000-0000-0000-0000-000000000004', '80000000-0000-0000-0000-000000000001', 10.000, 'KILOGRAM', 2), + ('90000000-0000-0000-0000-000000000005', '40000000-0000-0000-0000-000000000005', '80000000-0000-0000-0000-000000000001', 15.000, 'KILOGRAM', 5), + -- Gewürze im Trockenlager + ('90000000-0000-0000-0000-000000000006', '40000000-0000-0000-0000-000000000009', '80000000-0000-0000-0000-000000000003', 5.000, 'KILOGRAM', 30), + ('90000000-0000-0000-0000-000000000007', '40000000-0000-0000-0000-000000000010', '80000000-0000-0000-0000-000000000003', 25.000, 'KILOGRAM', 60), + ('90000000-0000-0000-0000-000000000008', '40000000-0000-0000-0000-000000000011', '80000000-0000-0000-0000-000000000003', 2.000, 'KILOGRAM', 30), + -- Wurstwaren in der Theke + ('90000000-0000-0000-0000-000000000009', '40000000-0000-0000-0000-000000000006', '80000000-0000-0000-0000-000000000004', 5.000, 'KILOGRAM', 2), + ('90000000-0000-0000-0000-000000000010', '40000000-0000-0000-0000-000000000007', '80000000-0000-0000-0000-000000000004', 3.000, 'KILOGRAM', 3), + ('90000000-0000-0000-0000-000000000011', '40000000-0000-0000-0000-000000000008', '80000000-0000-0000-0000-000000000004', 2.000, 'KILOGRAM', 7) +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 8. STOCK BATCHES (Chargen im Bestand) +-- ============================================================================ + +INSERT INTO stock_batches (id, stock_id, batch_id, batch_type, quantity_amount, quantity_unit, expiry_date, status, received_at) VALUES + -- Schweineschulter – 2 Chargen + ('A0000000-0000-0000-0000-000000000001', '90000000-0000-0000-0000-000000000001', 'BF-2026-0215-001', 'PURCHASED', 35.000000, 'KILOGRAM', '2026-02-28', 'AVAILABLE', '2026-02-15 06:00:00+01'), + ('A0000000-0000-0000-0000-000000000002', '90000000-0000-0000-0000-000000000001', 'BF-2026-0220-001', 'PURCHASED', 40.000000, 'KILOGRAM', '2026-03-05', 'AVAILABLE', '2026-02-20 06:30:00+01'), + -- Schweinebauch + ('A0000000-0000-0000-0000-000000000003', '90000000-0000-0000-0000-000000000002', 'BF-2026-0218-001', 'PURCHASED', 25.000000, 'KILOGRAM', '2026-03-01', 'AVAILABLE', '2026-02-18 07:00:00+01'), + -- Rindfleisch + ('A0000000-0000-0000-0000-000000000004', '90000000-0000-0000-0000-000000000003', 'AR-2026-0219-001', 'PURCHASED', 22.000000, 'KILOGRAM', '2026-03-02', 'AVAILABLE', '2026-02-19 08:00:00+01'), + -- Schweineleber + ('A0000000-0000-0000-0000-000000000005', '90000000-0000-0000-0000-000000000004', 'BF-2026-0222-001', 'PURCHASED', 12.000000, 'KILOGRAM', '2026-02-26', 'EXPIRING_SOON', '2026-02-22 06:00:00+01'), + -- Speck + ('A0000000-0000-0000-0000-000000000006', '90000000-0000-0000-0000-000000000005', 'BF-2026-0218-002', 'PURCHASED', 18.000000, 'KILOGRAM', '2026-03-04', 'AVAILABLE', '2026-02-18 06:30:00+01'), + -- Bratwurstgewürz + ('A0000000-0000-0000-0000-000000000007', '90000000-0000-0000-0000-000000000006', 'GK-2026-0101-001', 'PURCHASED', 8.000000, 'KILOGRAM', '2026-12-31', 'AVAILABLE', '2026-01-15 10:00:00+01'), + -- Pökelsalz + ('A0000000-0000-0000-0000-000000000008', '90000000-0000-0000-0000-000000000007', 'GK-2026-0110-001', 'PURCHASED', 50.000000, 'KILOGRAM', '2027-06-30', 'AVAILABLE', '2026-01-20 10:00:00+01'), + -- Kräutermischung Leberwurst + ('A0000000-0000-0000-0000-000000000009', '90000000-0000-0000-0000-000000000008', 'GK-2026-0115-001', 'PURCHASED', 3.500000, 'KILOGRAM', '2026-09-30', 'AVAILABLE', '2026-01-25 09:00:00+01'), + -- Bratwurst in Theke (produziert) + ('A0000000-0000-0000-0000-000000000010', '90000000-0000-0000-0000-000000000009', 'BW-260223-01', 'PRODUCED', 8.500000, 'KILOGRAM', '2026-02-28', 'AVAILABLE', '2026-02-23 14:00:00+01'), + -- Leberwurst in Theke (produziert) + ('A0000000-0000-0000-0000-000000000011', '90000000-0000-0000-0000-000000000010', 'LW-260222-01', 'PRODUCED', 4.200000, 'KILOGRAM', '2026-03-01', 'AVAILABLE', '2026-02-22 15:00:00+01'), + -- Schinkenspeck in Theke (produziert) + ('A0000000-0000-0000-0000-000000000012', '90000000-0000-0000-0000-000000000011', 'SS-260215-01', 'PRODUCED', 3.800000, 'KILOGRAM', '2026-03-15', 'AVAILABLE', '2026-02-15 16:00:00+01') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 9. RECIPES (3 Rezepte) +-- ============================================================================ + +INSERT INTO recipes (id, name, version, type, description, yield_percentage, shelf_life_days, + output_quantity, output_uom, status, article_id, created_at, updated_at) VALUES + ('B0000000-0000-0000-0000-000000000001', + 'Hausmacher Bratwurst', 1, 'FINISHED_PRODUCT', + 'Traditionelle Bratwurst nach Hausrezept. Schweineschulter und Bauch im Verhältnis 70:30, fein gewolft, mit hauseigener Gewürzmischung.', + 92, 5, 10.000000, 'KILOGRAM', 'ACTIVE', + '40000000-0000-0000-0000-000000000006', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('B0000000-0000-0000-0000-000000000002', + 'Kräuter-Leberwurst fein', 1, 'FINISHED_PRODUCT', + 'Feine Leberwurst mit frischen Kräutern. Schweineleber, Schweinebauch und Zwiebeln, fein passiert.', + 88, 7, 8.000000, 'KILOGRAM', 'ACTIVE', + '40000000-0000-0000-0000-000000000007', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + + ('B0000000-0000-0000-0000-000000000003', + 'Schinkenspeck geräuchert', 1, 'FINISHED_PRODUCT', + 'Durchwachsener Speck, trocken gepökelt und über Buchenholz geräuchert. Reifezeit 14 Tage.', + 85, 28, 5.000000, 'KILOGRAM', 'ACTIVE', + '40000000-0000-0000-0000-000000000008', + CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) +ON CONFLICT (id) DO NOTHING; + +-- Rezept-Zutaten: Hausmacher Bratwurst +INSERT INTO recipe_ingredients (id, recipe_id, position, article_id, quantity, uom, substitutable) VALUES + ('B1000000-0000-0000-0000-000000000001', 'B0000000-0000-0000-0000-000000000001', 1, '40000000-0000-0000-0000-000000000001', 7.000000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000002', 'B0000000-0000-0000-0000-000000000001', 2, '40000000-0000-0000-0000-000000000002', 3.000000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000003', 'B0000000-0000-0000-0000-000000000001', 3, '40000000-0000-0000-0000-000000000009', 0.200000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000004', 'B0000000-0000-0000-0000-000000000001', 4, '40000000-0000-0000-0000-000000000010', 0.180000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000005', 'B0000000-0000-0000-0000-000000000001', 5, '40000000-0000-0000-0000-000000000012', 20.000000, 'PIECE', false) +ON CONFLICT (id) DO NOTHING; + +-- Rezept-Zutaten: Kräuter-Leberwurst +INSERT INTO recipe_ingredients (id, recipe_id, position, article_id, quantity, uom, substitutable) VALUES + ('B1000000-0000-0000-0000-000000000006', 'B0000000-0000-0000-0000-000000000002', 1, '40000000-0000-0000-0000-000000000004', 3.000000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000007', 'B0000000-0000-0000-0000-000000000002', 2, '40000000-0000-0000-0000-000000000002', 4.500000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000008', 'B0000000-0000-0000-0000-000000000002', 3, '40000000-0000-0000-0000-000000000011', 0.150000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000009', 'B0000000-0000-0000-0000-000000000002', 4, '40000000-0000-0000-0000-000000000010', 0.120000, 'KILOGRAM', false) +ON CONFLICT (id) DO NOTHING; + +-- Rezept-Zutaten: Schinkenspeck +INSERT INTO recipe_ingredients (id, recipe_id, position, article_id, quantity, uom, substitutable) VALUES + ('B1000000-0000-0000-0000-000000000010', 'B0000000-0000-0000-0000-000000000003', 1, '40000000-0000-0000-0000-000000000005', 5.500000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000011', 'B0000000-0000-0000-0000-000000000003', 2, '40000000-0000-0000-0000-000000000010', 0.280000, 'KILOGRAM', false), + ('B1000000-0000-0000-0000-000000000012', 'B0000000-0000-0000-0000-000000000003', 3, '40000000-0000-0000-0000-000000000013', 0.500000, 'KILOGRAM', true) +ON CONFLICT (id) DO NOTHING; + +-- Produktionsschritte: Hausmacher Bratwurst +INSERT INTO recipe_production_steps (id, recipe_id, step_number, description, duration_minutes, temperature_celsius) VALUES + ('B2000000-0000-0000-0000-000000000001', 'B0000000-0000-0000-0000-000000000001', 1, 'Fleisch auf 2°C vorkühlen und in Würfel schneiden', 30, 2), + ('B2000000-0000-0000-0000-000000000002', 'B0000000-0000-0000-0000-000000000001', 2, 'Durch 3mm-Scheibe wolfen', 20, NULL), + ('B2000000-0000-0000-0000-000000000003', 'B0000000-0000-0000-0000-000000000001', 3, 'Gewürze und Pökelsalz einmischen, kuttern bis Brätbindung', 15, NULL), + ('B2000000-0000-0000-0000-000000000004', 'B0000000-0000-0000-0000-000000000001', 4, 'In Schweinedärme abfüllen, portionieren à 100g', 45, NULL), + ('B2000000-0000-0000-0000-000000000005', 'B0000000-0000-0000-0000-000000000001', 5, 'Qualitätskontrolle: Gewicht, Bindung, Aussehen', 10, NULL) +ON CONFLICT (id) DO NOTHING; + +-- Produktionsschritte: Kräuter-Leberwurst +INSERT INTO recipe_production_steps (id, recipe_id, step_number, description, duration_minutes, temperature_celsius) VALUES + ('B2000000-0000-0000-0000-000000000006', 'B0000000-0000-0000-0000-000000000002', 1, 'Schweinebauch kochen bis weich', 90, 85), + ('B2000000-0000-0000-0000-000000000007', 'B0000000-0000-0000-0000-000000000002', 2, 'Leber blanchieren und entstäuben', 10, 70), + ('B2000000-0000-0000-0000-000000000008', 'B0000000-0000-0000-0000-000000000002', 3, 'Alles durch feinste Scheibe wolfen, Kräuter zugeben', 20, NULL), + ('B2000000-0000-0000-0000-000000000009', 'B0000000-0000-0000-0000-000000000002', 4, 'In Dosen/Gläser abfüllen', 30, NULL), + ('B2000000-0000-0000-0000-000000000010', 'B0000000-0000-0000-0000-000000000002', 5, 'Pasteurisieren bei 80°C Kerntemperatur', 120, 80) +ON CONFLICT (id) DO NOTHING; + +-- Produktionsschritte: Schinkenspeck +INSERT INTO recipe_production_steps (id, recipe_id, step_number, description, duration_minutes, temperature_celsius) VALUES + ('B2000000-0000-0000-0000-000000000011', 'B0000000-0000-0000-0000-000000000003', 1, 'Speck zuschneiden und Schwarte einritzen', 20, NULL), + ('B2000000-0000-0000-0000-000000000012', 'B0000000-0000-0000-0000-000000000003', 2, 'Trockenpökelung mit NPS einreiben', 15, 4), + ('B2000000-0000-0000-0000-000000000013', 'B0000000-0000-0000-0000-000000000003', 3, 'Pökelzeit im Kühlraum (14 Tage, tgl. wenden)', 20160, 4), + ('B2000000-0000-0000-0000-000000000014', 'B0000000-0000-0000-0000-000000000003', 4, 'Wässern und trocken tupfen', 60, NULL), + ('B2000000-0000-0000-0000-000000000015', 'B0000000-0000-0000-0000-000000000003', 5, 'Kalträuchern über Buchenholz (3 Durchgänge)', 480, 25) +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 10. BATCHES (2 Produktionschargen) +-- ============================================================================ + +INSERT INTO batch_number_sequences (production_date, last_sequence) VALUES + ('2026-02-23', 1), + ('2026-02-22', 1) +ON CONFLICT (production_date) DO NOTHING; + +INSERT INTO batches (id, batch_number, recipe_id, status, + planned_quantity_amount, planned_quantity_unit, + production_date, best_before_date, + actual_quantity_amount, actual_quantity_unit, + waste_amount, waste_unit, remarks, + completed_at, + created_at, updated_at, version) VALUES + -- Bratwurst-Charge: abgeschlossen + ('C0000000-0000-0000-0000-000000000001', + 'BW-260223-01', 'B0000000-0000-0000-0000-000000000001', 'COMPLETED', + 10.000000, 'KILOGRAM', + '2026-02-23', '2026-02-28', + 9.200000, 'KILOGRAM', + 0.800000, 'KILOGRAM', 'Leichte Abweichung bei Darmfüllung, Qualität einwandfrei', + '2026-02-23 14:00:00+01', + '2026-02-23 06:00:00+01', '2026-02-23 14:00:00+01', 3), + + -- Leberwurst-Charge: in Produktion + ('C0000000-0000-0000-0000-000000000002', + 'LW-260222-01', 'B0000000-0000-0000-0000-000000000002', 'IN_PRODUCTION', + 8.000000, 'KILOGRAM', + '2026-02-22', '2026-03-01', + NULL, NULL, + NULL, NULL, NULL, + NULL, + '2026-02-22 06:00:00+01', '2026-02-22 10:00:00+01', 1) +ON CONFLICT (id) DO NOTHING; + +-- Batch Consumptions (Verbrauch der Bratwurst-Charge) +INSERT INTO batch_consumptions (id, batch_id, input_batch_id, article_id, quantity_used_amount, quantity_used_unit, consumed_at) VALUES + ('C1000000-0000-0000-0000-000000000001', 'C0000000-0000-0000-0000-000000000001', 'BF-2026-0215-001', '40000000-0000-0000-0000-000000000001', 7.000000, 'KILOGRAM', '2026-02-23 07:00:00+01'), + ('C1000000-0000-0000-0000-000000000002', 'C0000000-0000-0000-0000-000000000001', 'BF-2026-0218-001', '40000000-0000-0000-0000-000000000002', 3.000000, 'KILOGRAM', '2026-02-23 07:00:00+01') +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 11. PRODUCTION ORDERS (3 Aufträge) +-- ============================================================================ + +INSERT INTO production_orders (id, recipe_id, status, planned_quantity_amount, planned_quantity_unit, + planned_date, priority, notes, batch_id, + created_at, updated_at, version) VALUES + -- Bratwurst-Auftrag: abgeschlossen (mit Batch verknüpft) + ('D0000000-0000-0000-0000-000000000001', + 'B0000000-0000-0000-0000-000000000001', 'COMPLETED', + 10.000000, 'KILOGRAM', + '2026-02-23', 'NORMAL', 'Reguläre Wochenproduktion Bratwurst', + 'C0000000-0000-0000-0000-000000000001', + '2026-02-21 09:00:00+01', '2026-02-23 14:00:00+01', 4), + + -- Leberwurst-Auftrag: in Produktion + ('D0000000-0000-0000-0000-000000000002', + 'B0000000-0000-0000-0000-000000000002', 'IN_PROGRESS', + 8.000000, 'KILOGRAM', + '2026-02-22', 'HIGH', 'Eilauftrag – Bestand in Theke niedrig', + 'C0000000-0000-0000-0000-000000000002', + '2026-02-21 14:00:00+01', '2026-02-22 10:00:00+01', 2), + + -- Schinkenspeck-Auftrag: freigegeben (noch kein Batch) + ('D0000000-0000-0000-0000-000000000003', + 'B0000000-0000-0000-0000-000000000003', 'RELEASED', + 5.000000, 'KILOGRAM', + '2026-02-26', 'NORMAL', 'Nachschub für Dallmayr-Bestellung', + NULL, + '2026-02-24 08:00:00+01', '2026-02-25 09:00:00+01', 1) +ON CONFLICT (id) DO NOTHING; + + +-- ============================================================================ +-- 12. STOCK MOVEMENTS (Bestandsbewegungen) +-- ============================================================================ + +INSERT INTO stock_movements (id, stock_id, article_id, stock_batch_id, batch_id, batch_type, + movement_type, direction, quantity_amount, quantity_unit, + reason, reference_document_id, + performed_by, performed_at) VALUES + -- Wareneingänge Frischfleisch + ('E0000000-0000-0000-0000-000000000001', + '90000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000001', + 'A0000000-0000-0000-0000-000000000001', 'BF-2026-0215-001', 'PURCHASED', + 'GOODS_RECEIPT', 'IN', 35.000000, 'KILOGRAM', + 'Wareneingang Bay. Fleischwerke, Lieferschein LS-2026-0455', 'LS-2026-0455', + '10000000-0000-0000-0000-000000000003', '2026-02-15 06:15:00+01'), + + ('E0000000-0000-0000-0000-000000000002', + '90000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000001', + 'A0000000-0000-0000-0000-000000000002', 'BF-2026-0220-001', 'PURCHASED', + 'GOODS_RECEIPT', 'IN', 40.000000, 'KILOGRAM', + 'Wareneingang Bay. Fleischwerke, Lieferschein LS-2026-0512', 'LS-2026-0512', + '10000000-0000-0000-0000-000000000003', '2026-02-20 06:45:00+01'), + + ('E0000000-0000-0000-0000-000000000003', + '90000000-0000-0000-0000-000000000002', '40000000-0000-0000-0000-000000000002', + 'A0000000-0000-0000-0000-000000000003', 'BF-2026-0218-001', 'PURCHASED', + 'GOODS_RECEIPT', 'IN', 25.000000, 'KILOGRAM', + 'Wareneingang Bay. Fleischwerke', 'LS-2026-0489', + '10000000-0000-0000-0000-000000000003', '2026-02-18 07:15:00+01'), + + ('E0000000-0000-0000-0000-000000000004', + '90000000-0000-0000-0000-000000000003', '40000000-0000-0000-0000-000000000003', + 'A0000000-0000-0000-0000-000000000004', 'AR-2026-0219-001', 'PURCHASED', + 'GOODS_RECEIPT', 'IN', 22.000000, 'KILOGRAM', + 'Wareneingang Alpenrind Tirol', 'LS-AT-2026-0088', + '10000000-0000-0000-0000-000000000003', '2026-02-19 08:30:00+01'), + + -- Produktionsverbrauch Bratwurst (Schweineschulter) + ('E0000000-0000-0000-0000-000000000005', + '90000000-0000-0000-0000-000000000001', '40000000-0000-0000-0000-000000000001', + 'A0000000-0000-0000-0000-000000000001', 'BF-2026-0215-001', 'PURCHASED', + 'PRODUCTION_CONSUMPTION', 'OUT', 7.000000, 'KILOGRAM', + 'Verbrauch für Charge BW-260223-01', 'BW-260223-01', + '10000000-0000-0000-0000-000000000001', '2026-02-23 07:00:00+01'), + + -- Produktionsverbrauch Bratwurst (Schweinebauch) + ('E0000000-0000-0000-0000-000000000006', + '90000000-0000-0000-0000-000000000002', '40000000-0000-0000-0000-000000000002', + 'A0000000-0000-0000-0000-000000000003', 'BF-2026-0218-001', 'PURCHASED', + 'PRODUCTION_CONSUMPTION', 'OUT', 3.000000, 'KILOGRAM', + 'Verbrauch für Charge BW-260223-01', 'BW-260223-01', + '10000000-0000-0000-0000-000000000001', '2026-02-23 07:00:00+01'), + + -- Produktionsoutput Bratwurst + ('E0000000-0000-0000-0000-000000000007', + '90000000-0000-0000-0000-000000000009', '40000000-0000-0000-0000-000000000006', + 'A0000000-0000-0000-0000-000000000010', 'BW-260223-01', 'PRODUCED', + 'PRODUCTION_OUTPUT', 'IN', 9.200000, 'KILOGRAM', + 'Produktion Hausmacher Bratwurst, Charge BW-260223-01', 'BW-260223-01', + '10000000-0000-0000-0000-000000000001', '2026-02-23 14:00:00+01'), + + -- Verkauf Bratwurst aus Theke + ('E0000000-0000-0000-0000-000000000008', + '90000000-0000-0000-0000-000000000009', '40000000-0000-0000-0000-000000000006', + 'A0000000-0000-0000-0000-000000000010', 'BW-260223-01', 'PRODUCED', + 'SALE', 'OUT', 0.700000, 'KILOGRAM', + 'Thekenverkauf', NULL, + '10000000-0000-0000-0000-000000000006', '2026-02-23 16:30:00+01'), + + -- Wareneingang Gewürze + ('E0000000-0000-0000-0000-000000000009', + '90000000-0000-0000-0000-000000000006', '40000000-0000-0000-0000-000000000009', + 'A0000000-0000-0000-0000-000000000007', 'GK-2026-0101-001', 'PURCHASED', + 'GOODS_RECEIPT', 'IN', 8.000000, 'KILOGRAM', + 'Wareneingang Gewürzkontor', 'LS-GK-2026-0012', + '10000000-0000-0000-0000-000000000003', '2026-01-15 10:30:00+01'), + + -- Schwund/Abschreibung Leber (kurzes MHD) + ('E0000000-0000-0000-0000-000000000010', + '90000000-0000-0000-0000-000000000004', '40000000-0000-0000-0000-000000000004', + 'A0000000-0000-0000-0000-000000000005', 'BF-2026-0222-001', 'PURCHASED', + 'WASTE', 'OUT', 0.500000, 'KILOGRAM', + 'Randstücke nicht verwertbar, MHD-kritisch', NULL, + '10000000-0000-0000-0000-000000000004', '2026-02-24 08:00:00+01') +ON CONFLICT (id) DO NOTHING; + + +COMMIT; diff --git a/frontend/apps/cli/src/components/inventory/StockMovementDetailScreen.tsx b/frontend/apps/cli/src/components/inventory/StockMovementDetailScreen.tsx index 2d0c5db..480b59a 100644 --- a/frontend/apps/cli/src/components/inventory/StockMovementDetailScreen.tsx +++ b/frontend/apps/cli/src/components/inventory/StockMovementDetailScreen.tsx @@ -1,11 +1,12 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { Box, Text, useInput } from 'ink'; import { useNavigation } from '../../state/navigation-context.js'; import { useStockMovements } from '../../hooks/useStockMovements.js'; import { LoadingSpinner } from '../shared/LoadingSpinner.js'; import { ErrorDisplay } from '../shared/ErrorDisplay.js'; -import { MOVEMENT_TYPE_LABELS, MOVEMENT_DIRECTION_LABELS } from '@effigenix/api-client'; -import type { MovementType, MovementDirection } from '@effigenix/api-client'; +import { MOVEMENT_TYPE_LABELS, MOVEMENT_DIRECTION_LABELS, STORAGE_TYPE_LABELS } from '@effigenix/api-client'; +import type { MovementType, MovementDirection, StorageType } from '@effigenix/api-client'; +import { client } from '../../utils/api-client.js'; const DIRECTION_COLORS: Record = { IN: 'green', @@ -16,12 +17,51 @@ export function StockMovementDetailScreen() { const { params, back } = useNavigation(); const { movement, loading, error, fetchMovement, clearError } = useStockMovements(); + const [storageLabel, setStorageLabel] = useState(null); + const [articleLabel, setArticleLabel] = useState(null); + const [userLabel, setUserLabel] = useState(null); + const movementId = params.movementId ?? ''; useEffect(() => { if (movementId) void fetchMovement(movementId); }, [fetchMovement, movementId]); + // Resolve Storage Location via Stock → StorageLocation + useEffect(() => { + if (!movement?.stockId) return; + void (async () => { + try { + const stock = await client.stocks.getById(movement.stockId); + const loc = await client.storageLocations.getById(stock.storageLocationId); + const typeLabel = STORAGE_TYPE_LABELS[loc.storageType as StorageType] ?? loc.storageType; + setStorageLabel(`${loc.name} (${typeLabel})`); + } catch { setStorageLabel(null); } + })(); + }, [movement?.stockId]); + + // Resolve Article name + number + useEffect(() => { + if (!movement?.articleId) return; + void (async () => { + try { + const article = await client.articles.getById(movement.articleId); + setArticleLabel(`${article.name} (${article.articleNumber})`); + } catch { setArticleLabel(null); } + })(); + }, [movement?.articleId]); + + // Resolve User + useEffect(() => { + if (!movement?.performedBy) return; + void (async () => { + try { + const user = await client.users.getById(movement.performedBy); + setUserLabel(user.username); + } catch { setUserLabel(null); } + })(); + }, [movement?.performedBy]); + useInput((_input, key) => { if (key.backspace || key.escape) back(); }); @@ -58,9 +98,8 @@ export function StockMovementDetailScreen() { Typ: {typeLabel} Richtung: {dirLabel} Menge: {movement.quantityAmount} {movement.quantityUnit} - Stock-ID: {movement.stockId} - Artikel-ID: {movement.articleId} - Chargen-Batch: {movement.stockBatchId} + Lagerort: {storageLabel ?? '...'} {movement.stockId} + Artikel: {articleLabel ?? '...'} {movement.articleId} Chargen-Nr.: {movement.batchId} Chargen-Typ: {movement.batchType} {movement.reason && ( @@ -69,7 +108,7 @@ export function StockMovementDetailScreen() { {movement.referenceDocumentId && ( Referenz-Dok.: {movement.referenceDocumentId} )} - Durchgeführt von: {movement.performedBy} + Durchgeführt von: {userLabel ?? '...'} {movement.performedBy} Zeitpunkt: {dateStr} diff --git a/makefile b/makefile index e2a3300..33e9114 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ -.PHONY: frontend-dev backend/run generate/openapi bugsink +.PHONY: frontend-dev backend/run generate/openapi bugsink seed-testdata frontend/run: cd frontend/apps/cli && node --env-file=../../../.env --import tsx src/index.tsx @@ -10,6 +10,9 @@ backend/run: generate/openapi: ./scripts/generate-openapi.sh +seed-testdata: + PGPASSWORD=effigenix nix shell nixpkgs#postgresql --command psql -f backend/src/main/resources/db/changelog/changes/099-seed-testdata.sql -h localhost -p 5432 -U effigenix -d effigenix + bugsink: @. ./.env 2>/dev/null || true; \ docker start bugsink 2>/dev/null || \