Changes between Version 3 and Version 4 of DatabaseProgramming


Ignore:
Timestamp:
06/07/26 23:24:04 (3 days ago)
Author:
231020
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseProgramming

    v3 v4  
    33== Функции
    44
    5 Функција 1: Проверка дали корисникот има доволно баланс за BUY
    6 
    7 {{{
    8 CREATE OR REPLACE FUNCTION check_portfolio_balance(
    9     p_portfolio_id BIGINT,
    10     p_price FLOAT8,
    11     p_quantity INT
    12 )
    13 RETURNS BOOLEAN AS $$
    14 DECLARE
    15     v_balance NUMERIC(18,2);
    16     v_total FLOAT8;
    17 BEGIN
    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;
     5Функција 1: Ажурира и враќа моменталната добивка/загуба на CFD позицијата врз основа на најновата цена на акциите.
     6
     7{{{
     8CREATE OR REPLACE FUNCTION calculate_cfd_profit_loss(p_cfd_id BIGINT)
     9RETURNS FLOAT8
     10AS $$
     11DECLARE
     12    v_quantity INT;
     13    v_open_price FLOAT8;
     14    v_current_price FLOAT8;
     15    v_profit_loss FLOAT8;
     16BEGIN
     17    SELECT c.quantity,
     18           c.open_price,
     19           s.current_price
     20    INTO v_quantity,
     21         v_open_price,
     22         v_current_price
     23    FROM CFD_position c
     24    JOIN stock s ON c.stock_id = s.id
     25    WHERE c.id = p_cfd_id;
     26
     27    v_profit_loss :=
     28        (v_current_price - v_open_price) * v_quantity;
     29
     30    UPDATE CFD_position
     31    SET profit_loss = v_profit_loss
     32    WHERE id = p_cfd_id;
     33
     34    RETURN v_profit_loss;
    2935END;
    3036$$ LANGUAGE plpgsql;
     
    5258}}}
    5359
     60Функција 3: Проверка дали корисникот има доволно баланс за BUY
     61
     62{{{
     63CREATE OR REPLACE FUNCTION check_portfolio_balance(
     64    p_portfolio_id BIGINT,
     65    p_price FLOAT8,
     66    p_quantity INT
     67)
     68RETURNS BOOLEAN AS $$
     69DECLARE
     70    v_balance NUMERIC(18,2);
     71    v_total FLOAT8;
     72BEGIN
     73    SELECT balance INTO v_balance
     74    FROM portfolios
     75    WHERE id = p_portfolio_id;
     76
     77    v_total := p_price * p_quantity;
     78
     79    IF v_balance >= v_total THEN
     80        RETURN TRUE;
     81    ELSE
     82        RETURN FALSE;
     83    END IF;
     84END;
     85$$ LANGUAGE plpgsql;
     86}}}
     87
    5488
    5589
     
    5892== Процедури
    5993
    60 Процедура 1: Креирање на trade request од корисник
     94Процедура 1: Одобрување на trade request од admin - креира broker order и settlement
     95
     96
     97{{{
     98CREATE OR REPLACE PROCEDURE approve_trade_request(
     99    p_trade_request_id BIGINT
     100)
     101AS $$
     102DECLARE
     103    v_tr trade_request%ROWTYPE;
     104    v_portfolio portfolios%ROWTYPE;
     105    v_broker_order_id BIGINT;
     106    v_stock_id BIGINT;
     107BEGIN
     108
     109    SELECT * INTO v_tr
     110    FROM trade_request
     111    WHERE id = p_trade_request_id AND status = 'OPEN';
     112
     113    IF NOT FOUND THEN
     114        RAISE EXCEPTION 'Trade request % не постои или не е OPEN', p_trade_request_id;
     115    END IF;
     116
     117    SELECT * INTO v_portfolio
     118    FROM portfolios
     119    WHERE id = v_tr.portfolio_id;
     120
     121
     122    SELECT id INTO v_stock_id
     123    FROM stock
     124    WHERE symbol = v_tr.stock_symbol;
     125
     126
     127    UPDATE trade_request
     128    SET status = 'CLOSED'
     129    WHERE id = p_trade_request_id;
     130
     131
     132    INSERT INTO broker_order (
     133        order_type, limit_price, quantity, status,
     134        executed_price, broker_fee, mse_reference_number,
     135        submitted_at, executed_at, trade_request_id
     136    )
     137    VALUES (
     138        v_tr.type, v_tr.price_per_unit, v_tr.quantity, 'EXECUTED',
     139        v_tr.price_per_unit, (random() * 50)::FLOAT8,
     140        'MSE-' || p_trade_request_id,
     141        v_tr.timestamp, NOW(), p_trade_request_id
     142    )
     143    RETURNING id INTO v_broker_order_id;
     144
     145
     146    INSERT INTO settlement_record (
     147        broker_order_id, user_id, stock_symbol, quantity,
     148        settled_price, total_cost, settlement_status, settled_at
     149    )
     150    VALUES (
     151        v_broker_order_id, v_portfolio.user_id, v_tr.stock_symbol,
     152        v_tr.quantity, v_tr.price_per_unit,
     153        v_tr.price_per_unit * v_tr.quantity,
     154        'SETTLED', NOW()
     155    );
     156
     157
     158    INSERT INTO trade_transaction (
     159        price, quantity, timestamp, type, origin, user_id, stock_id
     160    )
     161    VALUES (
     162        v_tr.price_per_unit, v_tr.quantity, NOW(),
     163        v_tr.type, 'INTERNAL', v_portfolio.user_id, v_stock_id
     164    );
     165
     166    RAISE NOTICE 'Trade request % одобрен — Broker Order % креиран',
     167        p_trade_request_id, v_broker_order_id;
     168END;
     169$$ LANGUAGE plpgsql;
     170}}}
     171
     172
     173
     174Процедура 2: Креирање на trade request од корисник
    61175
    62176{{{
     
    98212
    99213
    100 Процедура 2: Одобрување на trade request од admin - креира broker order и settlement
    101 
    102 
    103 {{{
    104 CREATE OR REPLACE PROCEDURE approve_trade_request(
    105     p_trade_request_id BIGINT
    106 )
    107 AS $$
    108 DECLARE
    109     v_tr trade_request%ROWTYPE;
    110     v_portfolio portfolios%ROWTYPE;
    111     v_broker_order_id BIGINT;
    112     v_stock_id BIGINT;
    113 BEGIN
    114 
    115     SELECT * INTO v_tr
    116     FROM trade_request
    117     WHERE id = p_trade_request_id AND status = 'OPEN';
    118 
    119     IF NOT FOUND THEN
    120         RAISE EXCEPTION 'Trade request % не постои или не е OPEN', p_trade_request_id;
    121     END IF;
    122 
    123     SELECT * INTO v_portfolio
    124     FROM portfolios
    125     WHERE id = v_tr.portfolio_id;
    126 
    127 
    128     SELECT id INTO v_stock_id
    129     FROM stock
    130     WHERE symbol = v_tr.stock_symbol;
    131 
    132 
    133     UPDATE trade_request
    134     SET status = 'CLOSED'
    135     WHERE id = p_trade_request_id;
    136 
    137 
    138     INSERT INTO broker_order (
    139         order_type, limit_price, quantity, status,
    140         executed_price, broker_fee, mse_reference_number,
    141         submitted_at, executed_at, trade_request_id
    142     )
    143     VALUES (
    144         v_tr.type, v_tr.price_per_unit, v_tr.quantity, 'EXECUTED',
    145         v_tr.price_per_unit, (random() * 50)::FLOAT8,
    146         'MSE-' || p_trade_request_id,
    147         v_tr.timestamp, NOW(), p_trade_request_id
    148     )
    149     RETURNING id INTO v_broker_order_id;
    150 
    151 
    152     INSERT INTO settlement_record (
    153         broker_order_id, user_id, stock_symbol, quantity,
    154         settled_price, total_cost, settlement_status, settled_at
    155     )
    156     VALUES (
    157         v_broker_order_id, v_portfolio.user_id, v_tr.stock_symbol,
    158         v_tr.quantity, v_tr.price_per_unit,
    159         v_tr.price_per_unit * v_tr.quantity,
    160         'SETTLED', NOW()
    161     );
    162 
    163 
    164     INSERT INTO trade_transaction (
    165         price, quantity, timestamp, type, origin, user_id, stock_id
    166     )
    167     VALUES (
    168         v_tr.price_per_unit, v_tr.quantity, NOW(),
    169         v_tr.type, 'INTERNAL', v_portfolio.user_id, v_stock_id
    170     );
    171 
    172     RAISE NOTICE 'Trade request % одобрен — Broker Order % креиран',
    173         p_trade_request_id, v_broker_order_id;
    174 END;
    175 $$ LANGUAGE plpgsql;
    176 }}}
    177 
    178 
    179214
    180215== Тригери
    181216
    182 Тригер 1: При SELL - провери дали корисникот има доволно акции во holdings
    183 
    184 
    185 {{{
    186 CREATE OR REPLACE FUNCTION check_holdings_before_sell()
    187 RETURNS TRIGGER AS $$
    188 DECLARE
    189     v_stock_id BIGINT;
    190     v_available_qty INT;
    191 BEGIN
    192     IF NEW.type = 'SELL' THEN
    193         SELECT id INTO v_stock_id
    194         FROM stock WHERE symbol = NEW.stock_symbol;
    195 
    196         SELECT quantity INTO v_available_qty
    197         FROM portfolio_holdings
    198         WHERE portfolio_id = NEW.portfolio_id
    199           AND stock_id = v_stock_id;
    200 
    201         IF NOT FOUND OR v_available_qty < NEW.quantity THEN
    202             RAISE EXCEPTION 'Недоволно акции за продажба. Достапно: %, Побарано: %',
    203                 COALESCE(v_available_qty, 0), NEW.quantity;
    204         END IF;
    205     END IF;
    206 
    207     RETURN NEW;
    208 END;
    209 $$ LANGUAGE plpgsql;
    210 
    211 CREATE TRIGGER trg_check_holdings_before_sell
    212 BEFORE INSERT ON trade_request
    213 FOR EACH ROW
    214 EXECUTE FUNCTION check_holdings_before_sell();
    215 }}}
    216 
    217 
    218 Тригер 2: цената треба автоматски да се менува кога ќе се случи нова трансакција
     217Тригер 1: Цената треба автоматски да се менува кога ќе се случи нова трансакција
    219218
    220219{{{
     
    247246
    248247
     248Тригер 2: При SELL - провери дали корисникот има доволно акции во holdings
     249
     250
     251{{{
     252CREATE OR REPLACE FUNCTION check_holdings_before_sell()
     253RETURNS TRIGGER AS $$
     254DECLARE
     255    v_stock_id BIGINT;
     256    v_available_qty INT;
     257BEGIN
     258    IF NEW.type = 'SELL' THEN
     259        SELECT id INTO v_stock_id
     260        FROM stock WHERE symbol = NEW.stock_symbol;
     261
     262        SELECT quantity INTO v_available_qty
     263        FROM portfolio_holdings
     264        WHERE portfolio_id = NEW.portfolio_id
     265          AND stock_id = v_stock_id;
     266
     267        IF NOT FOUND OR v_available_qty < NEW.quantity THEN
     268            RAISE EXCEPTION 'Недоволно акции за продажба. Достапно: %, Побарано: %',
     269                COALESCE(v_available_qty, 0), NEW.quantity;
     270        END IF;
     271    END IF;
     272
     273    RETURN NEW;
     274END;
     275$$ LANGUAGE plpgsql;
     276
     277CREATE TRIGGER trg_check_holdings_before_sell
     278BEFORE INSERT ON trade_request
     279FOR EACH ROW
     280EXECUTE FUNCTION check_holdings_before_sell();
     281}}}
     282
     283
     284
     285