-- ===================================== -- BAKERY INVENTORY DEMO DATA -- Comprehensive demo dataset for inventory system -- Includes: Demo user/tenant, ingredients, stock with lots, movements -- ===================================== -- Demo Configuration Variables -- These can be modified to create data for different demo scenarios DO $$ DECLARE -- Demo User & Tenant Configuration demo_tenant_id UUID := 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID; demo_user_email VARCHAR := 'demo@panaderiasanpablo.com'; demo_user_name VARCHAR := 'Demo User - Panadería San Pablo'; demo_bakery_name VARCHAR := 'Panadería San Pablo - Demo'; -- Ingredient IDs (will be generated) harina_trigo_id UUID; harina_integral_id UUID; levadura_fresca_id UUID; levadura_seca_id UUID; mantequilla_id UUID; aceite_oliva_id UUID; huevos_id UUID; leche_id UUID; azucar_blanca_id UUID; azucar_morena_id UUID; sal_id UUID; chocolate_id UUID; vainilla_id UUID; canela_id UUID; nueces_id UUID; pasas_id UUID; -- Finished Product IDs croissant_id UUID; pan_integral_id UUID; napolitana_id UUID; palmera_id UUID; pan_tostado_id UUID; magdalena_id UUID; empanada_id UUID; cafe_con_leche_id UUID; BEGIN -- =========================================== -- 1. SETUP DEMO TENANT AND USER -- =========================================== RAISE NOTICE 'Setting up demo data for tenant: % (%)', demo_bakery_name, demo_tenant_id; -- Clean existing demo data for this tenant DELETE FROM stock_movements WHERE tenant_id = demo_tenant_id; DELETE FROM stock WHERE tenant_id = demo_tenant_id; DELETE FROM ingredients WHERE tenant_id = demo_tenant_id; -- =========================================== -- 2. RAW INGREDIENTS - COMPREHENSIVE BAKERY STOCK -- =========================================== -- Generate ingredient IDs harina_trigo_id := gen_random_uuid(); harina_integral_id := gen_random_uuid(); levadura_fresca_id := gen_random_uuid(); levadura_seca_id := gen_random_uuid(); mantequilla_id := gen_random_uuid(); aceite_oliva_id := gen_random_uuid(); huevos_id := gen_random_uuid(); leche_id := gen_random_uuid(); azucar_blanca_id := gen_random_uuid(); azucar_morena_id := gen_random_uuid(); sal_id := gen_random_uuid(); chocolate_id := gen_random_uuid(); vainilla_id := gen_random_uuid(); canela_id := gen_random_uuid(); nueces_id := gen_random_uuid(); pasas_id := gen_random_uuid(); -- Insert raw ingredients INSERT INTO ingredients ( id, tenant_id, name, product_type, ingredient_category, product_category, unit_of_measure, low_stock_threshold, reorder_point, reorder_quantity, is_active, is_perishable, shelf_life_days, average_cost, brand, storage_instructions, created_at, updated_at ) VALUES -- FLOURS (harina_trigo_id, demo_tenant_id, 'Harina de Trigo 000', 'INGREDIENT', 'FLOUR', NULL, 'KILOGRAMS', 25.0, 50.0, 200.0, true, false, 365, 2.50, 'Molinos del Valle', 'Almacenar en lugar seco', NOW(), NOW()), (harina_integral_id, demo_tenant_id, 'Harina Integral', 'INGREDIENT', 'FLOUR', NULL, 'KILOGRAMS', 15.0, 30.0, 100.0, true, false, 180, 3.20, 'Bio Natural', 'Almacenar en lugar seco', NOW(), NOW()), -- YEASTS (levadura_fresca_id, demo_tenant_id, 'Levadura Fresca', 'INGREDIENT', 'YEAST', NULL, 'KILOGRAMS', 1.0, 2.5, 10.0, true, true, 7, 8.50, 'Levapan', 'Refrigerar entre 2-8°C', NOW(), NOW()), (levadura_seca_id, demo_tenant_id, 'Levadura Seca Activa', 'INGREDIENT', 'YEAST', NULL, 'KILOGRAMS', 0.5, 1.0, 5.0, true, false, 730, 12.00, 'Fleischmann', 'Lugar seco, temperatura ambiente', NOW(), NOW()), -- FATS (mantequilla_id, demo_tenant_id, 'Mantequilla', 'INGREDIENT', 'FATS', NULL, 'KILOGRAMS', 3.0, 8.0, 25.0, true, true, 30, 6.80, 'La Serenísima', 'Refrigerar', NOW(), NOW()), (aceite_oliva_id, demo_tenant_id, 'Aceite de Oliva Extra Virgen', 'INGREDIENT', 'FATS', NULL, 'LITROS', 2.0, 5.0, 20.0, true, false, 730, 15.50, 'Cocinero', 'Lugar fresco y oscuro', NOW(), NOW()), -- DAIRY & EGGS (huevos_id, demo_tenant_id, 'Huevos Frescos', 'INGREDIENT', 'EGGS', NULL, 'UNITS', 36, 60, 180, true, true, 21, 0.25, 'Granja San José', 'Refrigerar', NOW(), NOW()), (leche_id, demo_tenant_id, 'Leche Entera', 'INGREDIENT', 'DAIRY', NULL, 'LITROS', 5.0, 12.0, 50.0, true, true, 5, 1.80, 'La Serenísima', 'Refrigerar', NOW(), NOW()), -- SUGARS (azucar_blanca_id, demo_tenant_id, 'Azúcar Blanca', 'INGREDIENT', 'SUGAR', NULL, 'KILOGRAMS', 8.0, 20.0, 100.0, true, false, 730, 1.20, 'Ledesma', 'Lugar seco', NOW(), NOW()), (azucar_morena_id, demo_tenant_id, 'Azúcar Morena', 'INGREDIENT', 'SUGAR', NULL, 'KILOGRAMS', 3.0, 8.0, 25.0, true, false, 365, 2.80, 'Orgánica', 'Lugar seco', NOW(), NOW()), -- SALT & FLAVORINGS (sal_id, demo_tenant_id, 'Sal Fina', 'INGREDIENT', 'SALT', NULL, 'KILOGRAMS', 2.0, 5.0, 20.0, true, false, 1095, 0.80, 'Celusal', 'Lugar seco', NOW(), NOW()), (chocolate_id, demo_tenant_id, 'Chocolate Semiamargo', 'INGREDIENT', 'ADDITIVES', NULL, 'KILOGRAMS', 1.0, 3.0, 15.0, true, false, 365, 8.50, 'Águila', 'Lugar fresco', NOW(), NOW()), (vainilla_id, demo_tenant_id, 'Extracto de Vainilla', 'INGREDIENT', 'SPICES', NULL, 'MILLILITERS', 100, 250, 1000, true, false, 1095, 0.15, 'McCormick', 'Lugar fresco', NOW(), NOW()), (canela_id, demo_tenant_id, 'Canela en Polvo', 'INGREDIENT', 'SPICES', NULL, 'GRAMS', 50, 150, 500, true, false, 730, 0.08, 'Alicante', 'Lugar seco', NOW(), NOW()), -- NUTS & FRUITS (nueces_id, demo_tenant_id, 'Nueces Peladas', 'INGREDIENT', 'ADDITIVES', NULL, 'KILOGRAMS', 0.5, 1.5, 8.0, true, false, 180, 12.00, 'Los Nogales', 'Lugar fresco y seco', NOW(), NOW()), (pasas_id, demo_tenant_id, 'Pasas de Uva', 'INGREDIENT', 'ADDITIVES', NULL, 'KILOGRAMS', 1.0, 2.0, 10.0, true, false, 365, 4.50, 'Mendoza Premium', 'Lugar seco', NOW(), NOW()); -- =========================================== -- 3. FINISHED PRODUCTS -- =========================================== -- Generate finished product IDs croissant_id := gen_random_uuid(); pan_integral_id := gen_random_uuid(); napolitana_id := gen_random_uuid(); palmera_id := gen_random_uuid(); pan_tostado_id := gen_random_uuid(); magdalena_id := gen_random_uuid(); empanada_id := gen_random_uuid(); cafe_con_leche_id := gen_random_uuid(); INSERT INTO ingredients ( id, tenant_id, name, product_type, ingredient_category, product_category, unit_of_measure, low_stock_threshold, reorder_point, reorder_quantity, is_active, is_perishable, shelf_life_days, average_cost, created_at, updated_at ) VALUES -- BAKERY PRODUCTS (croissant_id, demo_tenant_id, 'Croissant Clásico', 'FINISHED_PRODUCT', NULL, 'CROISSANTS', 'PIECES', 12, 30, 80, true, true, 1, 1.20, NOW(), NOW()), (pan_integral_id, demo_tenant_id, 'Pan Integral', 'FINISHED_PRODUCT', NULL, 'BREAD', 'PIECES', 8, 20, 50, true, true, 3, 2.50, NOW(), NOW()), (napolitana_id, demo_tenant_id, 'Napolitana de Chocolate', 'FINISHED_PRODUCT', NULL, 'PASTRIES', 'PIECES', 10, 25, 60, true, true, 2, 1.80, NOW(), NOW()), (palmera_id, demo_tenant_id, 'Palmera de Hojaldre', 'FINISHED_PRODUCT', NULL, 'PASTRIES', 'PIECES', 8, 20, 40, true, true, 2, 2.20, NOW(), NOW()), (pan_tostado_id, demo_tenant_id, 'Pan Tostado', 'FINISHED_PRODUCT', NULL, 'BREAD', 'PIECES', 15, 35, 80, true, true, 5, 1.50, NOW(), NOW()), (magdalena_id, demo_tenant_id, 'Magdalena de Vainilla', 'FINISHED_PRODUCT', NULL, 'PASTRIES', 'PIECES', 6, 18, 50, true, true, 3, 1.00, NOW(), NOW()), (empanada_id, demo_tenant_id, 'Empanada de Carne', 'FINISHED_PRODUCT', NULL, 'OTHER_PRODUCTS', 'PIECES', 5, 15, 40, true, true, 1, 3.50, NOW(), NOW()), (cafe_con_leche_id, demo_tenant_id, 'Café con Leche', 'FINISHED_PRODUCT', NULL, 'BEVERAGES', 'UNITS', 8, 20, 50, true, true, 1, 2.80, NOW(), NOW()); -- =========================================== -- 4. STOCK LOTS - DIVERSE SCENARIOS -- =========================================== RAISE NOTICE 'Creating stock lots with diverse scenarios...'; -- RAW INGREDIENTS STOCK -- HARINA DE TRIGO - Good stock with multiple lots INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, harina_trigo_id, 'raw_ingredient', 120.0, 15.0, 105.0, 'HARINA-TRI-20241201-001', NOW() - INTERVAL '5 days', NOW() + INTERVAL '360 days', 2.50, 300.0, 'Almacén Principal - Estante A1', true, false, 'good', NOW(), NOW()), (gen_random_uuid(), demo_tenant_id, harina_trigo_id, 'raw_ingredient', 80.0, 5.0, 75.0, 'HARINA-TRI-20241125-002', NOW() - INTERVAL '12 days', NOW() + INTERVAL '353 days', 2.50, 200.0, 'Almacén Principal - Estante A2', true, false, 'good', NOW(), NOW()); -- HARINA INTEGRAL - Normal stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, harina_integral_id, 'raw_ingredient', 45.0, 8.0, 37.0, 'HARINA-INT-20241128-001', NOW() - INTERVAL '9 days', NOW() + INTERVAL '171 days', 3.20, 144.0, 'Almacén Principal - Estante A3', true, false, 'good', NOW(), NOW()); -- LEVADURA FRESCA - CRITICAL LOW (below threshold, expires soon) INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, levadura_fresca_id, 'raw_ingredient', 0.8, 0.3, 0.5, 'LEVAD-FRE-20241204-001', NOW() - INTERVAL '2 days', NOW() + INTERVAL '5 days', 8.50, 6.8, 'Cámara Fría - Nivel 2', true, false, 'good', NOW(), NOW()); -- LEVADURA SECA - Good stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, levadura_seca_id, 'raw_ingredient', 2.5, 0.0, 2.5, 'LEVAD-SEC-20241115-001', NOW() - INTERVAL '22 days', NOW() + INTERVAL '708 days', 12.00, 30.0, 'Almacén Principal - Estante B1', true, false, 'good', NOW(), NOW()); -- MANTEQUILLA - Low stock, expires soon INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, mantequilla_id, 'raw_ingredient', 2.5, 0.5, 2.0, 'MANT-20241203-001', NOW() - INTERVAL '3 days', NOW() + INTERVAL '27 days', 6.80, 17.0, 'Cámara Fría - Nivel 1', true, false, 'good', NOW(), NOW()); -- ACEITE DE OLIVA - Good stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, aceite_oliva_id, 'raw_ingredient', 12.0, 2.0, 10.0, 'ACEITE-20241120-001', NOW() - INTERVAL '17 days', NOW() + INTERVAL '713 days', 15.50, 186.0, 'Almacén Principal - Estante C1', true, false, 'good', NOW(), NOW()); -- HUEVOS - Multiple lots, one EXPIRED INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES -- Fresh eggs (gen_random_uuid(), demo_tenant_id, huevos_id, 'raw_ingredient', 60, 6, 54, 'HUEVOS-20241205-001', NOW() - INTERVAL '1 day', NOW() + INTERVAL '20 days', 0.25, 15.0, 'Cámara Fría - Cajón 1', true, false, 'good', NOW(), NOW()), -- EXPIRED eggs - should trigger alert (gen_random_uuid(), demo_tenant_id, huevos_id, 'raw_ingredient', 18, 0, 18, 'HUEVOS-20241115-002', NOW() - INTERVAL '22 days', NOW() - INTERVAL '1 day', 0.25, 4.5, 'Cámara Fría - Cajón 2', true, true, 'expired', NOW(), NOW()); -- LECHE - Expires TODAY (critical) INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, leche_id, 'raw_ingredient', 8.0, 1.0, 7.0, 'LECHE-20241202-001', NOW() - INTERVAL '4 days', NOW() + INTERVAL '12 hours', 1.80, 14.4, 'Cámara Fría - Nivel 3', true, false, 'expires_today', NOW(), NOW()); -- AZUCAR BLANCA - Overstock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, azucar_blanca_id, 'raw_ingredient', 150.0, 10.0, 140.0, 'AZUC-BLA-20241110-001', NOW() - INTERVAL '27 days', NOW() + INTERVAL '703 days', 1.20, 180.0, 'Almacén Principal - Estante D1', true, false, 'good', NOW(), NOW()); -- OTHER INGREDIENTS - Various scenarios INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES -- Azúcar morena - Good (gen_random_uuid(), demo_tenant_id, azucar_morena_id, 'raw_ingredient', 15.0, 2.0, 13.0, 'AZUC-MOR-20241125-001', NOW() - INTERVAL '12 days', NOW() + INTERVAL '353 days', 2.80, 42.0, 'Almacén Principal - Estante D2', true, false, 'good', NOW(), NOW()), -- Sal - Overstock (gen_random_uuid(), demo_tenant_id, sal_id, 'raw_ingredient', 25.0, 1.0, 24.0, 'SAL-20240915-001', NOW() - INTERVAL '82 days', NOW() + INTERVAL '1013 days', 0.80, 20.0, 'Almacén Principal - Estante E1', true, false, 'good', NOW(), NOW()), -- Chocolate - Normal (gen_random_uuid(), demo_tenant_id, chocolate_id, 'raw_ingredient', 4.5, 0.5, 4.0, 'CHOC-20241201-001', NOW() - INTERVAL '5 days', NOW() + INTERVAL '360 days', 8.50, 38.25, 'Almacén Principal - Estante F1', true, false, 'good', NOW(), NOW()); -- =========================================== -- 5. FINISHED PRODUCTS STOCK - REALISTIC BAKERY SCENARIOS -- =========================================== -- CROISSANTS - Central bakery model with different stages INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, original_expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES -- Par-baked croissants (frozen, good stock) (gen_random_uuid(), demo_tenant_id, croissant_id, 'par_baked', 75, 0, 75, 'CROIS-PAR-20241205-001', NOW() - INTERVAL '1 day', NOW() + INTERVAL '4 days', NOW() + INTERVAL '4 days', 0.85, 63.75, 'Congelador - Sección A', true, false, 'good', NOW(), NOW()), -- Par-baked croissants (older batch, some reserved) (gen_random_uuid(), demo_tenant_id, croissant_id, 'par_baked', 40, 15, 25, 'CROIS-PAR-20241203-002', NOW() - INTERVAL '3 days', NOW() + INTERVAL '2 days', NOW() + INTERVAL '2 days', 0.85, 34.0, 'Congelador - Sección B', true, false, 'good', NOW(), NOW()), -- Fresh croissants (baked this morning) (gen_random_uuid(), demo_tenant_id, croissant_id, 'fully_baked', 35, 5, 30, 'CROIS-FRESH-20241206-001', NOW() - INTERVAL '4 hours', NOW() + INTERVAL '20 hours', 1.20, 42.0, 'Vitrina Principal - Nivel 1', true, false, 'good', NOW(), NOW()), -- Croissants from yesterday (expires soon, low stock) (gen_random_uuid(), demo_tenant_id, croissant_id, 'fully_baked', 8, 0, 8, 'CROIS-FRESH-20241205-002', NOW() - INTERVAL '28 hours', NOW() + INTERVAL '8 hours', 1.20, 9.6, 'Vitrina Principal - Nivel 2', true, false, 'expires_today', NOW(), NOW()); -- PAN INTEGRAL - Different batches INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES -- Fresh bread (gen_random_uuid(), demo_tenant_id, pan_integral_id, 'fully_baked', 25, 3, 22, 'PAN-INT-20241206-001', NOW() - INTERVAL '6 hours', NOW() + INTERVAL '66 hours', 2.50, 62.5, 'Estantería Pan - Nivel 1', true, false, 'good', NOW(), NOW()), -- Day-old bread (gen_random_uuid(), demo_tenant_id, pan_integral_id, 'fully_baked', 12, 1, 11, 'PAN-INT-20241205-002', NOW() - INTERVAL '30 hours', NOW() + INTERVAL '42 hours', 2.50, 30.0, 'Estantería Pan - Nivel 2', true, false, 'good', NOW(), NOW()); -- NAPOLITANAS - OUT OF STOCK (sold out scenario) INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, napolitana_id, 'fully_baked', 0, 0, 0, 'NAPO-20241206-001', NOW() - INTERVAL '6 hours', NOW() + INTERVAL '42 hours', 1.80, 0.0, 'Vitrina Pasteles - Nivel 1', false, false, 'sold_out', NOW(), NOW()); -- PALMERAS - Good stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, palmera_id, 'fully_baked', 28, 4, 24, 'PALM-20241206-001', NOW() - INTERVAL '3 hours', NOW() + INTERVAL '45 hours', 2.20, 61.6, 'Vitrina Pasteles - Nivel 2', true, false, 'good', NOW(), NOW()); -- PAN TOSTADO - Multiple batches INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES -- Fresh batch (gen_random_uuid(), demo_tenant_id, pan_tostado_id, 'fully_baked', 42, 6, 36, 'PAN-TOS-20241206-001', NOW() - INTERVAL '2 hours', NOW() + INTERVAL '118 hours', 1.50, 63.0, 'Estantería Pan Tostado - A', true, false, 'good', NOW(), NOW()), -- Older batch (gen_random_uuid(), demo_tenant_id, pan_tostado_id, 'fully_baked', 18, 2, 16, 'PAN-TOS-20241204-002', NOW() - INTERVAL '26 hours', NOW() + INTERVAL '94 hours', 1.50, 27.0, 'Estantería Pan Tostado - B', true, false, 'good', NOW(), NOW()); -- MAGDALENAS - Low stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, magdalena_id, 'fully_baked', 5, 1, 4, 'MAGD-20241206-001', NOW() - INTERVAL '5 hours', NOW() + INTERVAL '67 hours', 1.00, 5.0, 'Vitrina Pasteles - Nivel 3', true, false, 'good', NOW(), NOW()); -- EMPANADAS - Fresh, good stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, empanada_id, 'fully_baked', 20, 3, 17, 'EMP-20241206-001', NOW() - INTERVAL '1 hour', NOW() + INTERVAL '23 hours', 3.50, 70.0, 'Vitrina Empanadas', true, false, 'good', NOW(), NOW()); -- CAFÉ CON LECHE - Low stock INSERT INTO stock ( id, tenant_id, ingredient_id, production_stage, current_quantity, reserved_quantity, available_quantity, batch_number, received_date, expiration_date, unit_cost, total_cost, storage_location, is_available, is_expired, quality_status, created_at, updated_at ) VALUES (gen_random_uuid(), demo_tenant_id, cafe_con_leche_id, 'fully_baked', 9, 1, 8, 'CAFE-20241206-001', NOW() - INTERVAL '2 hours', NOW() + INTERVAL '22 hours', 2.80, 25.2, 'Máquina de Café', true, false, 'good', NOW(), NOW()); RAISE NOTICE 'Stock lots created successfully with diverse scenarios'; END $$; -- =========================================== -- 6. STOCK MOVEMENTS - REALISTIC TRANSACTION HISTORY -- =========================================== DO $$ DECLARE demo_tenant_id UUID := 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID; movement_record RECORD; BEGIN RAISE NOTICE 'Creating realistic stock movement history...'; -- PURCHASES - Raw materials received INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) SELECT gen_random_uuid(), demo_tenant_id, s.ingredient_id, s.id, 'PURCHASE', s.current_quantity + s.reserved_quantity, s.unit_cost, s.total_cost, 0.0, s.current_quantity + s.reserved_quantity, 'PO-' || TO_CHAR(s.received_date, 'YYYY-MM-DD-') || LPAD((ROW_NUMBER() OVER (ORDER BY s.received_date))::text, 3, '0'), CASE WHEN s.production_stage = 'raw_ingredient' THEN 'Recepción de materia prima - ' || i.name ELSE 'Producción interna - ' || i.name END, s.received_date, s.received_date, NULL FROM stock s JOIN ingredients i ON s.ingredient_id = i.id WHERE s.tenant_id = demo_tenant_id AND s.production_stage = 'raw_ingredient'; -- PRODUCTION USE - Raw materials consumed INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) VALUES -- Flour used for daily production (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Harina de Trigo 000' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Harina de Trigo 000' AND tenant_id = demo_tenant_id) LIMIT 1), 'PRODUCTION_USE', -35.0, 2.50, -87.5, 155.0, 120.0, 'PROD-20241206-001', 'Consumo para producción diaria de pan y pasteles', NOW() - INTERVAL '6 hours', NOW() - INTERVAL '6 hours', NULL), -- Yeast used (contributing to low stock) (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Levadura Fresca' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Levadura Fresca' AND tenant_id = demo_tenant_id) LIMIT 1), 'PRODUCTION_USE', -2.2, 8.50, -18.7, 3.0, 0.8, 'PROD-20241206-002', 'Consumo para fermentación - stock crítico', NOW() - INTERVAL '4 hours', NOW() - INTERVAL '4 hours', NULL), -- Butter used (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Mantequilla' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Mantequilla' AND tenant_id = demo_tenant_id) LIMIT 1), 'PRODUCTION_USE', -1.5, 6.80, -10.2, 4.0, 2.5, 'PROD-20241206-003', 'Consumo para croissants y pasteles', NOW() - INTERVAL '5 hours', NOW() - INTERVAL '5 hours', NULL); -- TRANSFORMATIONS - Par-baked to fully baked INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) VALUES -- Morning croissant batch (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id) AND production_stage = 'fully_baked' AND batch_number LIKE 'CROIS-FRESH-20241206%'), 'PRODUCTION_USE', 35.0, 1.20, 42.0, 0.0, 35.0, 'TRANS-20241206-001', 'Horneado final de croissants congelados - lote mañana', NOW() - INTERVAL '4 hours', NOW() - INTERVAL '4 hours', NULL); -- SALES - Products sold to customers INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) VALUES -- Napolitanas sold out completely (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Napolitana de Chocolate' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Napolitana de Chocolate' AND tenant_id = demo_tenant_id)), 'SALE', -30.0, 1.80, -54.0, 30.0, 0.0, 'SALE-20241206-001', 'Venta completa - napolitanas muy populares hoy', NOW() - INTERVAL '2 hours', NOW() - INTERVAL '2 hours', NULL), -- Croissant sales (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id) AND production_stage = 'fully_baked' AND batch_number LIKE 'CROIS-FRESH-20241206%'), 'SALE', -5.0, 1.20, -6.0, 40.0, 35.0, 'SALE-20241206-002', 'Ventas matutinas de croissants frescos', NOW() - INTERVAL '3 hours', NOW() - INTERVAL '3 hours', NULL), -- Palmera sales (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Palmera de Hojaldre' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Palmera de Hojaldre' AND tenant_id = demo_tenant_id)), 'SALE', -4.0, 2.20, -8.8, 32.0, 28.0, 'SALE-20241206-003', 'Ventas de palmeras - desayuno', NOW() - INTERVAL '2 hours', NOW() - INTERVAL '2 hours', NULL); -- WASTE - Expired or damaged products INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) VALUES -- Expired eggs marked as waste (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Huevos Frescos' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Huevos Frescos' AND tenant_id = demo_tenant_id) AND is_expired = true), 'WASTE', -18.0, 0.25, -4.5, 18.0, 0.0, 'WASTE-20241206-001', 'Huevos vencidos - descarte por caducidad', NOW() - INTERVAL '1 hour', NOW() - INTERVAL '1 hour', NULL); -- RESERVATIONS - Products reserved for specific orders INSERT INTO stock_movements ( id, tenant_id, ingredient_id, stock_id, movement_type, quantity, unit_cost, total_cost, quantity_before, quantity_after, reference_number, notes, movement_date, created_at, created_by ) VALUES -- Croissants reserved for afternoon baking (gen_random_uuid(), demo_tenant_id, (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id), (SELECT id FROM stock WHERE ingredient_id = (SELECT id FROM ingredients WHERE name = 'Croissant Clásico' AND tenant_id = demo_tenant_id) AND production_stage = 'par_baked' AND batch_number LIKE 'CROIS-PAR-20241203%'), 'RESERVATION', -15.0, 0.85, -12.75, 40.0, 25.0, 'RESER-20241206-001', 'Reserva para horneado de la tarde - pedido especial', NOW() - INTERVAL '30 minutes', NOW() - INTERVAL '30 minutes', NULL); RAISE NOTICE 'Stock movements history created successfully'; END $$; -- =========================================== -- 7. SUMMARY REPORTS -- =========================================== \echo '' \echo '=========================================' \echo 'DEMO INVENTORY DATA SUMMARY' \echo '=========================================' SELECT 'INGREDIENTS OVERVIEW' as report_section; SELECT product_type, COALESCE(ingredient_category::text, product_category::text, 'N/A') as category, COUNT(*) as total_items, COUNT(CASE WHEN is_active THEN 1 END) as active_items FROM ingredients WHERE tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID GROUP BY product_type, COALESCE(ingredient_category::text, product_category::text, 'N/A') ORDER BY product_type, category; \echo '' SELECT 'STOCK SUMMARY BY STAGE' as report_section; SELECT production_stage, COUNT(*) as total_lots, SUM(current_quantity) as total_quantity, SUM(available_quantity) as available_quantity, SUM(reserved_quantity) as reserved_quantity, ROUND(SUM(total_cost), 2) as total_value FROM stock WHERE tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID GROUP BY production_stage ORDER BY production_stage; \echo '' SELECT 'CRITICAL STOCK ALERTS' as report_section; SELECT i.name, s.production_stage, s.current_quantity, s.available_quantity, i.low_stock_threshold, s.batch_number, s.expiration_date, CASE WHEN s.available_quantity = 0 THEN 'OUT_OF_STOCK' WHEN s.is_expired THEN 'EXPIRED' WHEN s.expiration_date <= NOW() + INTERVAL '24 hours' THEN 'EXPIRES_SOON' WHEN s.available_quantity <= i.low_stock_threshold THEN 'LOW_STOCK' ELSE 'OK' END as alert_status, s.storage_location FROM stock s JOIN ingredients i ON s.ingredient_id = i.id WHERE s.tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID AND ( s.available_quantity = 0 OR s.is_expired OR s.expiration_date <= NOW() + INTERVAL '48 hours' OR s.available_quantity <= i.low_stock_threshold ) ORDER BY CASE WHEN s.available_quantity = 0 THEN 1 WHEN s.is_expired THEN 2 WHEN s.expiration_date <= NOW() + INTERVAL '24 hours' THEN 3 WHEN s.available_quantity <= i.low_stock_threshold THEN 4 ELSE 5 END, s.expiration_date ASC; \echo '' SELECT 'MOVEMENT ACTIVITY (Last 24 hours)' as report_section; SELECT i.name, sm.movement_type, ABS(sm.quantity) as quantity, sm.reference_number, sm.notes, sm.movement_date FROM stock_movements sm JOIN ingredients i ON sm.ingredient_id = i.id WHERE sm.tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID AND sm.movement_date >= NOW() - INTERVAL '24 hours' ORDER BY sm.movement_date DESC LIMIT 15; \echo '' \echo '=========================================' \echo 'DEMO DATA CREATION COMPLETED SUCCESSFULLY' \echo 'Tenant ID: c464fb3e-7af2-46e6-9e43-85318f34199a' \echo 'Total Ingredients: ' || (SELECT COUNT(*) FROM ingredients WHERE tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID)::text \echo 'Total Stock Lots: ' || (SELECT COUNT(*) FROM stock WHERE tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID)::text \echo 'Total Movements: ' || (SELECT COUNT(*) FROM stock_movements WHERE tenant_id = 'c464fb3e-7af2-46e6-9e43-85318f34199a'::UUID)::text \echo '========================================='