mirror of
https://github.com/immissmandy/Kitchen.git
synced 2026-07-27 12:25:30 +02:00
feat: KitchenStock light UI, Gemma 31B AI, supermarket store filters & 130+ vegan products
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
-- Migration 00003: Transactional Stock Adjustment RPC (adjust_product_stock with FEFO)
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.adjust_product_stock(
|
||||
p_household_id UUID,
|
||||
p_product_id UUID,
|
||||
p_quantity_change NUMERIC,
|
||||
p_reason public.stock_movement_reason,
|
||||
p_batch_id UUID DEFAULT NULL,
|
||||
p_note TEXT DEFAULT NULL
|
||||
)
|
||||
RETURNS NUMERIC
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public
|
||||
AS $$
|
||||
DECLARE
|
||||
v_user_id UUID;
|
||||
v_total_before NUMERIC := 0.0;
|
||||
v_total_after NUMERIC := 0.0;
|
||||
v_target_batch RECORD;
|
||||
v_remaining_to_deduct NUMERIC;
|
||||
v_deduct_amount NUMERIC;
|
||||
BEGIN
|
||||
v_user_id := auth.uid();
|
||||
|
||||
-- 1. Check permissions
|
||||
IF NOT public.has_household_role(p_household_id, ARRAY['MEMBER', 'ADMIN', 'OWNER']::public.household_role[]) THEN
|
||||
RAISE EXCEPTION 'PERMISSION_DENIED: User is not authorized to modify stock in household %', p_household_id;
|
||||
END IF;
|
||||
|
||||
-- 2. Lock product and calculate current total stock
|
||||
PERFORM 1 FROM public.products WHERE id = p_product_id AND household_id = p_household_id FOR UPDATE;
|
||||
|
||||
SELECT COALESCE(SUM(quantity), 0.0) INTO v_total_before
|
||||
FROM public.inventory_batches
|
||||
WHERE household_id = p_household_id AND product_id = p_product_id;
|
||||
|
||||
-- 3. Check for negative stock
|
||||
IF (v_total_before + p_quantity_change) < 0 THEN
|
||||
RAISE EXCEPTION 'INSUFFICIENT_STOCK: Required quantity reduction exceeds current total stock (%)', v_total_before;
|
||||
END IF;
|
||||
|
||||
-- 4. Apply changes
|
||||
IF p_batch_id IS NOT NULL THEN
|
||||
-- Target specific batch
|
||||
SELECT * INTO v_target_batch
|
||||
FROM public.inventory_batches
|
||||
WHERE id = p_batch_id AND product_id = p_product_id AND household_id = p_household_id
|
||||
FOR UPDATE;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'BATCH_NOT_FOUND: Specified batch % does not exist', p_batch_id;
|
||||
END IF;
|
||||
|
||||
IF (v_target_batch.quantity + p_quantity_change) < 0 THEN
|
||||
RAISE EXCEPTION 'INSUFFICIENT_BATCH_STOCK: Batch quantity cannot be reduced below 0';
|
||||
END IF;
|
||||
|
||||
UPDATE public.inventory_batches
|
||||
SET quantity = quantity + p_quantity_change,
|
||||
updated_at = NOW()
|
||||
WHERE id = p_batch_id;
|
||||
|
||||
ELSE
|
||||
-- No explicit batch provided
|
||||
IF p_quantity_change > 0 THEN
|
||||
-- Increase stock: Add to default batch (batch without expiration_date or newest) or create new batch
|
||||
SELECT id INTO p_batch_id
|
||||
FROM public.inventory_batches
|
||||
WHERE household_id = p_household_id
|
||||
AND product_id = p_product_id
|
||||
AND expiration_date IS NULL
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1;
|
||||
|
||||
IF p_batch_id IS NOT NULL THEN
|
||||
UPDATE public.inventory_batches
|
||||
SET quantity = quantity + p_quantity_change,
|
||||
updated_at = NOW()
|
||||
WHERE id = p_batch_id;
|
||||
ELSE
|
||||
INSERT INTO public.inventory_batches (household_id, product_id, quantity)
|
||||
VALUES (p_household_id, p_product_id, p_quantity_change)
|
||||
RETURNING id INTO p_batch_id;
|
||||
END IF;
|
||||
|
||||
ELSIF p_quantity_change < 0 THEN
|
||||
-- FEFO Deduction (First Expire, First Out)
|
||||
v_remaining_to_deduct := ABS(p_quantity_change);
|
||||
|
||||
FOR v_target_batch IN
|
||||
SELECT id, quantity
|
||||
FROM public.inventory_batches
|
||||
WHERE household_id = p_household_id
|
||||
AND product_id = p_product_id
|
||||
AND quantity > 0
|
||||
ORDER BY
|
||||
expiration_date ASC NULLS LAST,
|
||||
created_at ASC
|
||||
FOR UPDATE
|
||||
LOOP
|
||||
IF v_remaining_to_deduct <= 0 THEN
|
||||
EXIT;
|
||||
END IF;
|
||||
|
||||
v_deduct_amount := LEAST(v_target_batch.quantity, v_remaining_to_deduct);
|
||||
|
||||
UPDATE public.inventory_batches
|
||||
SET quantity = quantity - v_deduct_amount,
|
||||
updated_at = NOW()
|
||||
WHERE id = v_target_batch.id;
|
||||
|
||||
v_remaining_to_deduct := v_remaining_to_deduct - v_deduct_amount;
|
||||
END LOOP;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- 5. Calculate new total stock
|
||||
SELECT COALESCE(SUM(quantity), 0.0) INTO v_total_after
|
||||
FROM public.inventory_batches
|
||||
WHERE household_id = p_household_id AND product_id = p_product_id;
|
||||
|
||||
-- 6. Insert stock_movements record
|
||||
INSERT INTO public.stock_movements (
|
||||
household_id,
|
||||
product_id,
|
||||
batch_id,
|
||||
quantity_before,
|
||||
quantity_change,
|
||||
quantity_after,
|
||||
reason,
|
||||
note,
|
||||
created_by
|
||||
) VALUES (
|
||||
p_household_id,
|
||||
p_product_id,
|
||||
p_batch_id,
|
||||
v_total_before,
|
||||
p_quantity_change,
|
||||
v_total_after,
|
||||
p_reason,
|
||||
p_note,
|
||||
v_user_id
|
||||
);
|
||||
|
||||
RETURN v_total_after;
|
||||
END;
|
||||
$$;
|
||||
Reference in New Issue
Block a user