Полагаю, это должно быть сделано:
DO LANGUAGE plpgsql $$
DECLARE
input CONSTANT jsonb := '...';
delivery jsonb;
updated bill_products;
BEGIN
FOR delivery IN SELECT jsonb_array_elements(input) LOOP
UPDATE bill_products
SET delivered = delivered + (delivery->>'delivered')::numeric
WHERE bill_id = (delivery->>'bill_id')::int
AND pro_id = (delivery->>'product_id')::int
RETURNING *
INTO STRICT updated;
INSERT INTO inventory(pro_id, quantity)
VALUES (updated.pro_id, updated.delivered);
END LOOP;
UPDATE bill
SET approved = NOT EXISTS (SELECT 1
FROM bill_products
WHERE bill_products.bill_id = bill.bill_id
AND delivered < quantity)
WHERE bill_id IN (SELECT DISTINCT (d->>'bill_id')::int
FROM jsonb_array_elements(input) d);
END;
$$;
( онлайн-демонстрация )
В качестве альтернативы использование простого SQL вместо цикла может быть еще проще:
WITH updates AS (
UPDATE bill_products
SET delivered = delivered + (delivery->>'delivered')::numeric
FROM jsonb_array_elements(input) delivery
WHERE bill_id = (delivery->>'bill_id')::int
AND pro_id = (delivery->>'product_id')::int
RETURNING pro_id, delivered
) INSERT INTO inventory(pro_id, quantity)
SELECT * FROM updates;
( online demo )
Обратите внимание, что дублирование информации о доставке в таблицах inventory
и bill_products
не является хорошим дизайном базы данных. Возможно, вам следует опустить столбец bill_prodcts.delivered
и вычислять сумму соответствующих записей инвентаря каждый раз, когда вам это нужно.