wiki:AdvancedDatabaseDevelopment

Version 5 (modified by 221181, 4 days ago) ( diff )

--

Напреден развој на база

1.Тригери и Функции

1.1 Автоматско пресметување на вкупниот износ на продажба

Автоматски ја ажурира вкупната сума на продажбата секогаш кога се додаваат, менуваат или бришат ставки, со што се обезбедува точна пресметка во базата на податоци.

CREATE OR REPLACE FUNCTION trg_fn_recalculate_sale_total()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
    v_sale_id INT;
BEGIN
    IF TG_OP = 'DELETE' THEN
        v_sale_id := OLD.sale_id;
    ELSE
        v_sale_id := NEW.sale_id;
    END IF;

    UPDATE sale
    SET total_amount = (
        SELECT COALESCE(SUM(quantity * unit_price_at_sale), 0)
        FROM sale_item
        WHERE sale_id = v_sale_id
    )
    WHERE sale_id = v_sale_id;

    RETURN NULL;
END;
$$;

CREATE TRIGGER trg_recalculate_sale_total
AFTER INSERT OR UPDATE OR DELETE ON sale_item
FOR EACH ROW
EXECUTE FUNCTION trg_fn_recalculate_sale_total();

1.2 Спречување на паѓање на залихата во негативна вредност

Спречува која било операција да ја намали количината на залиха под нула, со што се обезбедува дека залихата никогаш нема да биде негативна.

CREATE OR REPLACE FUNCTION trg_fn_prevent_negative_stock()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
    IF NEW.quantity_on_hand < 0 THEN
        RAISE EXCEPTION
            'Stock cannot be negative! Warehouse: %, Product: %, Quantity: %',
            NEW.warehouse_id, NEW.product_id, NEW.quantity_on_hand;
    END IF;
    RETURN NEW;
END;
$$;

CREATE TRIGGER trg_prevent_negative_stock
BEFORE INSERT OR UPDATE ON warehouse_stock
FOR EACH ROW
EXECUTE FUNCTION trg_fn_prevent_negative_stock();

1.3 Корисникот не може сам да го избрише својот акаунт

Ако најавен корисник се обиде да го избрише својот сопствен акаунт, тоа се спречува.

CREATE OR REPLACE FUNCTION trg_func_no_self_delete() RETURNS TRIGGER AS $$ BEGIN
    IF OLD.username = CURRENT_USER THEN
        RAISE EXCEPTION 'You cannot delete your own account.';
    END IF;
    RETURN OLD;
END;
 $$ LANGUAGE plpgsql;

CREATE TRIGGER trg_user_self_delete BEFORE DELETE ON users
FOR EACH ROW EXECUTE FUNCTION trg_func_no_self_delete();

2.Views

2.1 Кој ден од неделата се продава најмногу?

Кои денови се зафатени, а кои мирни за планирање на персоналот.

CREATE OR REPLACE VIEW vw_sales_by_day_of_week AS
SELECT
    EXTRACT(ISODOW FROM s.date_time)::INT AS day_number,
    CASE EXTRACT(ISODOW FROM s.date_time)::INT
        WHEN 1 THEN 'Monday'
        WHEN 2 THEN 'Tuesday'
        WHEN 3 THEN 'Wednesday'
        WHEN 4 THEN 'Thursday'
        WHEN 5 THEN 'Friday'
        WHEN 6 THEN 'Saturday'
        WHEN 7 THEN 'Sunday'
    END AS day_name,
    COUNT(DISTINCT s.sale_id) AS total_sales,
    SUM(s.total_amount)       AS total_revenue,
    ROUND(AVG(s.total_amount), 2) AS avg_sale_value,
    SUM(si.quantity)          AS total_items_sold
FROM sale s
JOIN sale_item si ON s.sale_id = si.sale_id
GROUP BY EXTRACT(ISODOW FROM s.date_time)
ORDER BY day_number;

2.2 Кој продавач продава повеќе?

Прикажува колку продажби направил секој вработен, колку приход донел и неговото место во рангирањето.

CREATE OR REPLACE VIEW vw_employee_sales_ranking AS
SELECT
    u.user_id,
    u.full_name,
    u.role,
    COUNT(DISTINCT s.sale_id) AS total_sales,
    COALESCE(SUM(s.total_amount), 0) AS total_revenue,
    ROUND(COALESCE(AVG(s.total_amount), 0), 2) AS avg_sale_value,
    COUNT(DISTINCT s.customer_id) AS unique_customers,
    RANK() OVER (ORDER BY COALESCE(SUM(s.total_amount), 0) DESC)
        AS revenue_rank
FROM users u
LEFT JOIN sale s ON u.user_id = s.user_id
GROUP BY u.user_id, u.full_name, u.role
HAVING COUNT(s.sale_id) > 0
ORDER BY total_revenue DESC;
Note: See TracWiki for help on using the wiki.