Changes between Initial Version and Version 1 of AdvancedReport9


Ignore:
Timestamp:
09/25/26 16:22:27 (5 days ago)
Author:
201178
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedReport9

    v1 v1  
     1= Прогноза за потрошувачка на состојки врз основа на продажби =
     2
     3== Опис ==
     4
     5Извештајот предвидува колку од секоја состојка ќе биде потрошена во следните 30 дена, врз основа на просечната дневна потрошувачка во последните 90 дена. Користи три нивоа на вгнездување: (1) продажби по производ по ден, (2) агрегација по состојка преку рецепт, (3) споредба со моменталната залиха за да се најдат состојки што ќе треба наскоро да се нарачаат.
     6
     7== SQL решение ==
     8
     9{{{
     10CREATE OR REPLACE FUNCTION project.get_ingredient_consumption_forecast()
     11RETURNS TABLE (
     12    ingredient_id INT,
     13    ingredient_name TEXT,
     14    avg_daily_usage NUMERIC,
     15    forecast_30d NUMERIC,
     16    current_stock NUMERIC,
     17    days_until_empty NUMERIC,
     18    action TEXT
     19)
     20LANGUAGE sql
     21AS $$
     22    WITH daily_product_sales AS (
     23        SELECT
     24            oi.product_id,
     25            DATE(o.created_at) AS sale_date,
     26            SUM(oi.quantity) AS qty_sold
     27        FROM project.order_item oi
     28        JOIN project.orders o ON o.order_id = oi.order_id
     29        WHERE o.status = 'ПЛАТЕНА'
     30          AND o.created_at >= NOW() - INTERVAL '90 days'
     31        GROUP BY oi.product_id, DATE(o.created_at)
     32    ),
     33    ingredient_usage AS (
     34        SELECT
     35            ri.ingredient_id AS ing_id,
     36            SUM(dps.qty_sold * ri.quantity_needed)::numeric AS total_used
     37        FROM daily_product_sales dps
     38        JOIN project.recipe r ON r.product_id = dps.product_id
     39        JOIN project.recipe_item ri ON ri.recipe_id = r.recipe_id
     40        GROUP BY ri.ingredient_id
     41    ),
     42    stock AS (
     43        SELECT
     44            ii.ingredient_id AS ing_id,
     45            COALESCE(SUM(ii.quantity_change), 0)::numeric AS current_stock
     46        FROM project.ingredient_inventory ii
     47        GROUP BY ii.ingredient_id
     48    )
     49    SELECT
     50        i.ingredient_id,
     51        i.name::TEXT,
     52        ROUND(iu.total_used / 90.0, 3),
     53        ROUND((iu.total_used / 90.0) * 30, 2),
     54        COALESCE(s.current_stock, 0),
     55        CASE
     56            WHEN (iu.total_used / 90.0) > 0
     57            THEN ROUND(COALESCE(s.current_stock, 0) / (iu.total_used / 90.0), 1)
     58            ELSE NULL
     59        END,
     60        CASE
     61            WHEN COALESCE(s.current_stock, 0) < (iu.total_used / 90.0) * 30
     62                 AND i.min_stock > COALESCE(s.current_stock, 0) THEN 'ИТНО НАРАЧАЈ'
     63            WHEN COALESCE(s.current_stock, 0) < (iu.total_used / 90.0) * 30 THEN 'НАРАЧАЈ'
     64            ELSE 'ОК'
     65        END::TEXT
     66    FROM project.ingredient i
     67    JOIN ingredient_usage iu ON iu.ing_id = i.ingredient_id
     68    LEFT JOIN stock s ON s.ing_id = i.ingredient_id
     69    WHERE i.active = TRUE
     70    ORDER BY 6 ASC NULLS LAST;
     71$$;
     72}}}
     73
     74== Релациона алгебра ==
     75
     76{{{
     77OI(order_id, product_id, quantity, unit_price)
     78O(order_id, status, created_at)
     79R(recipe_id, product_id)
     80RI(recipe_id, ingredient_id, quantity_needed)
     81I(ingredient_id, name, min_stock, active)
     82II(id, ingredient_id, quantity_change)
     83
     84J1 ← OI ⨝ OI.order_id = O.order_id O
     85F1 ← σ status='ПЛАТЕНА' ∧ created_at ≥ NOW() - INTERVAL '90 days' (J1)
     86
     87G1 ← γ product_id, sale_date; SUM(quantity) → qty_sold (F1)
     88
     89J2 ← G1 ⨝ G1.product_id = R.product_id R
     90J3 ← J2 ⨝ R.recipe_id = RI.recipe_id RI
     91G2 ← γ ingredient_id; SUM(qty_sold * quantity_needed) → total_used (J3)
     92
     93G3 ← γ ingredient_id; COALESCE(SUM(quantity_change), 0) → current_stock (II)
     94
     95J4 ← I ⨝ G2 ⨝ G3
     96F2 ← σ active=TRUE (J4)
     97
     98R ← π ingredient_id, ingredient_name, avg_daily_usage, forecast_30d,
     99      current_stock, days_until_empty, action (F2)
     100
     101R_final ← τ days_until_empty ASC (R)
     102}}}