Changes between Initial Version and Version 1 of DatabaseProgramming


Ignore:
Timestamp:
05/12/26 10:45:41 (2 weeks ago)
Author:
231020
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v1 v1  
     1= Функции, процедури и тригери
     2
     3== Функции
     4
     5Функција 1: Проверка дали корисникот има доволно баланс за BUY
     6
     7{{{
     8CREATE OR REPLACE FUNCTION check_portfolio_balance(
     9    p_portfolio_id BIGINT,
     10    p_price FLOAT8,
     11    p_quantity INT
     12)
     13RETURNS BOOLEAN AS $$
     14DECLARE
     15    v_balance NUMERIC(18,2);
     16    v_total FLOAT8;
     17BEGIN
     18    SELECT balance INTO v_balance
     19    FROM portfolios
     20    WHERE id = p_portfolio_id;
     21
     22    v_total := p_price * p_quantity;
     23
     24    IF v_balance >= v_total THEN
     25        RETURN TRUE;
     26    ELSE
     27        RETURN FALSE;
     28    END IF;
     29END;
     30$$ LANGUAGE plpgsql;
     31}}}
     32
     33Функција 2: Вредност на портфолио за конкретен корисник
     34
     35{{{
     36CREATE OR REPLACE FUNCTION get_portfolio_value(
     37    p_user_id BIGINT
     38)
     39RETURNS FLOAT8 AS $$
     40DECLARE
     41    v_value FLOAT8;
     42BEGIN
     43    SELECT SUM(ph.quantity * s.current_price) INTO v_value
     44    FROM portfolios p
     45    JOIN portfolio_holdings ph ON p.id = ph.portfolio_id
     46    JOIN stock s ON ph.stock_id = s.id
     47    WHERE p.user_id = p_user_id;
     48
     49    RETURN COALESCE(v_value, 0);
     50END;
     51$$ LANGUAGE plpgsql;
     52}}}
     53
     54
     55== Процедури
     56
     57Процедура 1: Креирање на trade request од корисник
     58
     59{{{
     60CREATE OR REPLACE PROCEDURE create_trade_request(
     61    p_portfolio_id BIGINT,
     62    p_price FLOAT8,
     63    p_quantity INT,
     64    p_stock_symbol VARCHAR(20),
     65    p_type VARCHAR(10)
     66)
     67AS $$
     68DECLARE
     69    v_user_id BIGINT;
     70BEGIN
     71    SELECT user_id INTO v_user_id
     72    FROM portfolios
     73    WHERE id = p_portfolio_id;
     74
     75    IF p_type = 'BUY' THEN
     76        IF NOT check_portfolio_balance(p_portfolio_id, p_price, p_quantity) THEN
     77            RAISE EXCEPTION 'Недоволен баланс за купување. Portfolio ID: %', p_portfolio_id;
     78        END IF;
     79    END IF;
     80
     81    INSERT INTO trade_request (
     82        portfolio_id, price_per_unit, quantity,
     83        status, stock_symbol, timestamp, type
     84    )
     85    VALUES (
     86        p_portfolio_id, p_price, p_quantity,
     87        'OPEN', p_stock_symbol, NOW(), p_type
     88    );
     89
     90    RAISE NOTICE 'Trade request креиран за корисник % — % x % на %',
     91        v_user_id, p_type, p_quantity, p_stock_symbol;
     92END;
     93$$ LANGUAGE plpgsql;
     94}}}
     95
     96
     97Процедура 2: Одобрување на trade request од admin - креира broker order и settlement
     98
     99
     100{{{
     101CREATE OR REPLACE PROCEDURE approve_trade_request(
     102    p_trade_request_id BIGINT
     103)
     104AS $$
     105DECLARE
     106    v_tr trade_request%ROWTYPE;
     107    v_portfolio portfolios%ROWTYPE;
     108    v_broker_order_id BIGINT;
     109    v_stock_id BIGINT;
     110BEGIN
     111
     112    SELECT * INTO v_tr
     113    FROM trade_request
     114    WHERE id = p_trade_request_id AND status = 'OPEN';
     115
     116    IF NOT FOUND THEN
     117        RAISE EXCEPTION 'Trade request % не постои или не е OPEN', p_trade_request_id;
     118    END IF;
     119
     120    SELECT * INTO v_portfolio
     121    FROM portfolios
     122    WHERE id = v_tr.portfolio_id;
     123
     124
     125    SELECT id INTO v_stock_id
     126    FROM stock
     127    WHERE symbol = v_tr.stock_symbol;
     128
     129
     130    UPDATE trade_request
     131    SET status = 'CLOSED'
     132    WHERE id = p_trade_request_id;
     133
     134
     135    INSERT INTO broker_order (
     136        order_type, limit_price, quantity, status,
     137        executed_price, broker_fee, mse_reference_number,
     138        submitted_at, executed_at, trade_request_id
     139    )
     140    VALUES (
     141        v_tr.type, v_tr.price_per_unit, v_tr.quantity, 'EXECUTED',
     142        v_tr.price_per_unit, (random() * 50)::FLOAT8,
     143        'MSE-' || p_trade_request_id,
     144        v_tr.timestamp, NOW(), p_trade_request_id
     145    )
     146    RETURNING id INTO v_broker_order_id;
     147
     148
     149    INSERT INTO settlement_record (
     150        broker_order_id, user_id, stock_symbol, quantity,
     151        settled_price, total_cost, settlement_status, settled_at
     152    )
     153    VALUES (
     154        v_broker_order_id, v_portfolio.user_id, v_tr.stock_symbol,
     155        v_tr.quantity, v_tr.price_per_unit,
     156        v_tr.price_per_unit * v_tr.quantity,
     157        'SETTLED', NOW()
     158    );
     159
     160
     161    INSERT INTO trade_transaction (
     162        price, quantity, timestamp, type, origin, user_id, stock_id
     163    )
     164    VALUES (
     165        v_tr.price_per_unit, v_tr.quantity, NOW(),
     166        v_tr.type, 'INTERNAL', v_portfolio.user_id, v_stock_id
     167    );
     168
     169    RAISE NOTICE 'Trade request % одобрен — Broker Order % креиран',
     170        p_trade_request_id, v_broker_order_id;
     171END;
     172$$ LANGUAGE plpgsql;
     173}}}
     174
     175
     176
     177== Тригери
     178
     179Тригер 1: При SELL - провери дали корисникот има доволно акции во holdings
     180
     181
     182{{{
     183CREATE OR REPLACE FUNCTION check_holdings_before_sell()
     184RETURNS TRIGGER AS $$
     185DECLARE
     186    v_stock_id BIGINT;
     187    v_available_qty INT;
     188BEGIN
     189    IF NEW.type = 'SELL' THEN
     190        SELECT id INTO v_stock_id
     191        FROM stock WHERE symbol = NEW.stock_symbol;
     192
     193        SELECT quantity INTO v_available_qty
     194        FROM portfolio_holdings
     195        WHERE portfolio_id = NEW.portfolio_id
     196          AND stock_id = v_stock_id;
     197
     198        IF NOT FOUND OR v_available_qty < NEW.quantity THEN
     199            RAISE EXCEPTION 'Недоволно акции за продажба. Достапно: %, Побарано: %',
     200                COALESCE(v_available_qty, 0), NEW.quantity;
     201        END IF;
     202    END IF;
     203
     204    RETURN NEW;
     205END;
     206$$ LANGUAGE plpgsql;
     207
     208CREATE TRIGGER trg_check_holdings_before_sell
     209BEFORE INSERT ON trade_request
     210FOR EACH ROW
     211EXECUTE FUNCTION check_holdings_before_sell();
     212}}}