. , , . , JSON, , , , json_agg() 'ed.
CREATE OR REPLACE FUNCTION get_measures_by_inventory_as_json(invid UUID, del TIMESTAMP WITH TIME ZONE DEFAULT now())
RETURNS TABLE(inventory_id UUID, measure_json JSON)
AS $$
SELECT m.inventory_id, json_build_object(
'id', m.id,
'quantity', m.quantity,
'read', TRUNC(EXTRACT(EPOCH FROM m.read_date)),
'created', TRUNC(EXTRACT(EPOCH FROM m.created)),
'updated', TRUNC(EXTRACT(EPOCH FROM m.updated)),
'deleted', TRUNC(EXTRACT(EPOCH FROM m.deleted))
)
FROM measure m
WHERE m.inventory_id = invid
AND (m.deleted >= del);
$$
LANGUAGE sql;
CREATE OR REPLACE FUNCTION get_inventories_by_location_as_json(locid UUID, del TIMESTAMP WITH TIME ZONE DEFAULT now())
RETURNS TABLE(location_id UUID, inventory_json JSON)
AS $$
SELECT i.location_id, json_build_object(
'id', i.id,
'product_id', p.id,
'name', p.name,
'mass_quantity', p.mass_quantity,
'mass_unit', um.code,
'count_unit', uc.code,
'thumb', p.product_picture_uri,
'sort_order', i.sort_order,
'par_level', i.par_level,
'created', TRUNC(EXTRACT(EPOCH FROM i.created)),
'updated', TRUNC(EXTRACT(EPOCH FROM i.updated)),
'deleted', TRUNC(EXTRACT(EPOCH FROM i.deleted)),
'measures', COALESCE((SELECT json_agg(measure_json) FROM get_measures_by_inventory_as_json(i.id)), '[]')::json
)
FROM inventory i
INNER JOIN product p ON i.product_id = p.id
LEFT JOIN unit um ON p.mass_unit_id = um.id
LEFT JOIN unit uc ON p.count_unit_id = uc.id
WHERE i.location_id = locid
AND i.deleted >= del
AND p.deleted >= del;
$$
LANGUAGE sql;
CREATE OR REPLACE FUNCTION get_inventories_recursive_as_json(locid UUID[], del TIMESTAMP WITH TIME ZONE DEFAULT now())
RETURNS JSON
AS $$
SELECT json_agg(loc) FROM (
SELECT l.id, array_agg(c.id), json_build_object(
'id', l.id,
'name', l.name,
'type', t.code,
'locations', get_inventories_recursive_as_json(array_agg(c.id)),
'inventories', COALESCE((SELECT json_agg(inventory_json) FROM get_inventories_by_location_as_json(l.id)),'[]')::json
) AS loc
FROM location l
LEFT OUTER JOIN location c ON l.id = c.parent_id
INNER JOIN location_type t ON l.location_type_id = t.id
WHERE l.id = ANY(locid)
AND l.deleted >= del
GROUP BY l.id, l.name, t.code
) AS out;
$$
LANGUAGE sql;
CTE, , , , , .
WITH RECURSIVE locations AS (
WITH inventories AS (
WITH measures AS (
SELECT m.inventory_id, json_agg(json_build_object(
'id', m.id,
'quantity', m.quantity,
'read', TRUNC(EXTRACT(EPOCH FROM m.read_date)),
'created', TRUNC(EXTRACT(EPOCH FROM m.created)),
'updated', TRUNC(EXTRACT(EPOCH FROM m.updated)),
'deleted', TRUNC(EXTRACT(EPOCH FROM m.deleted))
)) as measures
FROM measure m
GROUP BY m.inventory_id
)
SELECT i.location_id, json_agg(json_build_object(
'id', i.id,
'product_id', p.id,
'name', p.name,
'mass_quantity', p.mass_quantity,
'mass_unit', um.code,
'count_unit', uc.code,
'thumb', p.product_picture_uri,
'sort_order', i.sort_order,
'par_level', i.par_level,
'created', TRUNC(EXTRACT(EPOCH FROM i.created)),
'updated', TRUNC(EXTRACT(EPOCH FROM i.updated)),
'deleted', TRUNC(EXTRACT(EPOCH FROM i.deleted)),
'measures', COALESCE(m.measures, '[]')
)) AS inventories
FROM inventory i
INNER JOIN product p ON i.product_id = p.id
LEFT JOIN unit um ON p.mass_unit_id = um.id
LEFT JOIN unit uc ON p.count_unit_id = uc.id
LEFT JOIN measures m ON i.id = m.inventory_id
GROUP BY i.location_id
)
SELECT null as id, null as name, null as type, null as inventories
FROM location l
INNER JOIN location_type t ON l.location_type_id = t.id
LEFT OUTER JOIN inventories i ON l.id = i.location_id
GROUP BY l.parent_id
)
SELECT * FROM locations