Функции, процедури, тригери : functions.txt

File functions.txt, 5.1 KB (added by 231068, 7 days ago)
Line 
1--================================================================================================================
2-- FUNCTIONS
3--================================================================================================================
4
5-- 1. Конверзија на валути
6CREATE OR REPLACE FUNCTION fn_convert_currency(
7 p_from_curr INT,
8 p_to_curr INT,
9 p_amount DECIMAL(20, 2),
10 p_date DATE DEFAULT CURRENT_DATE
11)
12 RETURNS DECIMAL(20, 2) AS
13$$
14DECLARE
15 v_rate DECIMAL(15, 6);
16BEGIN
17 IF p_from_curr = p_to_curr THEN
18 RETURN p_amount;
19 END IF;
20
21 SELECT (er_to.rate / er_from.rate)
22 INTO v_rate
23 FROM Exchange_rate er_from
24 JOIN Exchange_rate er_to
25 ON er_to.currency_id = p_to_curr
26 AND er_to.date_updated = p_date
27 WHERE er_from.currency_id = p_from_curr
28 AND er_from.date_updated = p_date;
29
30 IF v_rate IS NULL THEN
31 RAISE EXCEPTION 'Nema kurs za %', p_date;
32 END IF;
33
34 RETURN ROUND(p_amount * v_rate, 2);
35END;
36$$ LANGUAGE plpgsql;
37
38
39-- 2. Проверка дали сметка е активна
40CREATE OR REPLACE FUNCTION fn_is_account_eligible(p_account_id INT)
41 RETURNS BOOLEAN AS
42$$
43DECLARE
44 v_acc_status VARCHAR(20);
45 v_client_status VARCHAR(20);
46BEGIN
47 SELECT a.status, c.status
48 INTO v_acc_status, v_client_status
49 FROM Account a
50 JOIN Client c ON a.client_id = c.client_id
51 WHERE a.account_id = p_account_id;
52
53 IF NOT FOUND THEN
54 RETURN FALSE;
55 END IF;
56
57 RETURN (v_acc_status = 'ACTIVE' AND v_client_status = 'ACTIVE');
58END;
59$$ LANGUAGE plpgsql;
60
61
62-- 3. Враќа вкупен неплатен долг на клиент (сума на сите PENDING/LATE рати)
63CREATE OR REPLACE FUNCTION fn_get_client_total_debt(p_client_id INT)
64 RETURNS DECIMAL(20, 2) AS
65$$
66DECLARE
67 v_total DECIMAL(20, 2);
68BEGIN
69 SELECT COALESCE(SUM(li.amount), 0)
70 INTO v_total
71 FROM Loan_installment li
72 JOIN Loan l ON li.loan_id = l.loan_id
73 WHERE l.client_id = p_client_id
74 AND li.status IN ('PENDING', 'LATE')
75 AND l.status = 'APPROVED';
76
77 RETURN v_total;
78END;
79$$ LANGUAGE plpgsql;
80
81-- сите кредити на клиент
82SELECT fn_get_client_total_debt(318290);
83
84
85
86-- 4. Враќа преостаната сума за отплата на кредит
87CREATE OR REPLACE FUNCTION fn_get_loan_remaining_amount(p_loan_id INT)
88 RETURNS TABLE
89 (
90 loan_id INT,
91 total_amount DECIMAL(15, 2),
92 paid_amount DECIMAL(15, 2),
93 remaining_amount DECIMAL(15, 2),
94 late_count INT,
95 pending_count INT
96 )
97AS
98$$
99BEGIN
100 RETURN QUERY
101 SELECT l.loan_id,
102 l.amount,
103 COALESCE(SUM(li.amount) FILTER (WHERE li.status = 'PAID'), 0)::DECIMAL(15, 2),
104 COALESCE(SUM(li.amount) FILTER (WHERE li.status != 'PAID'), 0)::DECIMAL(15, 2),
105 COUNT(*) FILTER (WHERE li.status = 'LATE')::INT,
106 COUNT(*) FILTER (WHERE li.status = 'PENDING')::INT
107 FROM Loan l
108 JOIN Loan_installment li ON l.loan_id = li.loan_id
109 WHERE l.loan_id = p_loan_id
110 GROUP BY l.loan_id, l.amount;
111
112 IF NOT FOUND THEN
113 RAISE EXCEPTION 'Кредитот со ID % не постои.', p_loan_id;
114 END IF;
115END;
116$$ LANGUAGE plpgsql;
117
118
119SELECT *
120FROM fn_get_loan_remaining_amount(86961);
121
122
123-- 5. Го пресметува очекуваниот износ на камата за штедна сметка за даден период
124CREATE OR REPLACE FUNCTION fn_calculate_savings_interest(
125 p_account_id INT,
126 p_period_start DATE,
127 p_period_end DATE
128)
129 RETURNS DECIMAL(20, 2) AS
130$$
131DECLARE
132 v_balance DECIMAL(20, 2);
133 v_interest_rate DECIMAL(5, 2);
134 v_interest_period VARCHAR(20);
135 v_capitalization VARCHAR(20);
136 v_days INT;
137 v_result DECIMAL(20, 2);
138BEGIN
139 SELECT a.balance, sa.interest_rate, sa.interest_period, sa.capitalization_type
140 INTO v_balance, v_interest_rate, v_interest_period, v_capitalization
141 FROM Account a
142 JOIN SavingsAccount sa ON a.account_id = sa.account_id
143 WHERE a.account_id = p_account_id;
144
145 IF NOT FOUND THEN
146 RAISE EXCEPTION 'Сметка % не е штедна сметка или не постои.', p_account_id;
147 END IF;
148
149 v_days := (p_period_end - p_period_start);
150
151 IF v_capitalization = 'SIMPLE' THEN
152 -- Проста камата: P * r * t
153 v_result := v_balance * (v_interest_rate / 100.0) * (v_days / 365.0);
154 ELSE
155 -- Сложена камата: P * (1 + r)^t - P
156 v_result := v_balance * (
157 POWER(1 + (v_interest_rate / 100.0), v_days / 365.0) - 1
158 );
159 END IF;
160
161 RETURN ROUND(v_result, 2);
162END;
163$$ LANGUAGE plpgsql;
164
165
166SELECT fn_calculate_savings_interest(1001, '2026-04-01', '2026-04-30');