3 CREATE OR REPLACE FUNCTION acq.copy_fund_tags(
11 FOR fund_tag_rec IN SELECT * FROM acq.fund_tag_map WHERE fund=old_fund_id LOOP
13 INSERT INTO acq.fund_tag_map(fund, tag) VALUES(new_fund_id, fund_tag_rec.tag);
15 WHEN unique_violation THEN
16 -- RAISE NOTICE 'Fund tag already propagated', old_fund.id;
24 CREATE OR REPLACE FUNCTION acq.rollover_funds_by_org_tree(
28 encumb_only BOOL DEFAULT FALSE,
29 include_desc BOOL DEFAULT TRUE
34 new_year INT := old_year + 1;
37 xfer_amount NUMERIC := 0;
41 roll_distrib_forms BOOL;
47 IF old_year IS NULL THEN
48 RAISE EXCEPTION 'Input year argument is NULL';
49 ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
50 RAISE EXCEPTION 'Input year is out of range';
53 IF user_id IS NULL THEN
54 RAISE EXCEPTION 'Input user id argument is NULL';
57 IF org_unit_id IS NULL THEN
58 RAISE EXCEPTION 'Org unit id argument is NULL';
61 -- Validate the org unit
66 WHERE id = org_unit_id;
68 IF org_found IS NULL THEN
69 RAISE EXCEPTION 'Org unit id % is invalid', org_unit_id;
70 ELSIF encumb_only THEN
71 SELECT INTO perm_ous value::BOOL FROM
72 actor.org_unit_ancestor_setting(
73 'acq.fund.allow_rollover_without_money', org_unit_id
75 IF NOT FOUND OR NOT perm_ous THEN
76 RAISE EXCEPTION 'Encumbrance-only rollover not permitted at org %', org_unit_id;
81 -- Loop over the propagable funds to identify the details
82 -- from the old fund plus the id of the new one, if it exists.
92 newf.id AS new_fund_id
95 LEFT JOIN acq.fund AS newf
96 ON ( oldf.code = newf.code )
100 AND newf.year = new_year
101 AND ( ( include_desc AND oldf.org IN ( SELECT id FROM actor.org_unit_descendants( org_unit_id ) ) )
102 OR (NOT include_desc AND oldf.org = org_unit_id ) )
104 --RAISE NOTICE 'Processing fund %', roll_fund.old_fund;
106 IF roll_fund.new_fund_id IS NULL THEN
108 -- The old fund hasn't been propagated yet. Propagate it now.
110 INSERT INTO acq.fund (
118 balance_warning_percent,
124 roll_fund.currency_type,
128 roll_fund.balance_warning_percent,
129 roll_fund.balance_stop_percent
131 RETURNING id INTO new_fund;
133 PERFORM acq.copy_fund_tags(roll_fund.id,new_fund);
136 new_fund = roll_fund.new_fund_id;
139 -- Determine the amount to transfer
143 FROM acq.fund_spent_balance
144 WHERE fund = roll_fund.old_fund;
146 IF xfer_amount <> 0 THEN
147 IF NOT encumb_only AND roll_fund.rollover THEN
149 -- Transfer balance from old fund to new
151 --RAISE NOTICE 'Transferring % from fund % to %', xfer_amount, roll_fund.old_fund, new_fund;
153 PERFORM acq.transfer_fund(
163 -- Transfer balance from old fund to the void
165 -- RAISE NOTICE 'Transferring % from fund % to the void', xfer_amount, roll_fund.old_fund;
167 PERFORM acq.transfer_fund(
173 'Rollover into the void'
178 IF roll_fund.rollover THEN
180 -- Move any lineitems from the old fund to the new one
181 -- where the associated debit is an encumbrance.
183 -- Any other tables tying expenditure details to funds should
184 -- receive similar treatment. At this writing there are none.
186 UPDATE acq.lineitem_detail
189 fund = roll_fund.old_fund -- this condition may be redundant
195 fund = roll_fund.old_fund
199 -- Move encumbrance debits from the old fund to the new fund
201 UPDATE acq.fund_debit
204 fund = roll_fund.old_fund
208 -- Rollover distribution formulae funds
209 SELECT INTO roll_distrib_forms value::BOOL FROM
210 actor.org_unit_ancestor_setting(
211 'acq.fund.rollover_distrib_forms', org_unit_id
214 IF roll_distrib_forms THEN
215 UPDATE acq.distribution_formula_entry
216 SET fund = roll_fund.new_fund_id
217 WHERE fund = roll_fund.old_fund;
221 -- Mark old fund as inactive, now that we've closed it
225 WHERE id = roll_fund.old_fund;
230 CREATE OR REPLACE FUNCTION acq.propagate_funds_by_org_tree(
234 include_desc BOOL DEFAULT TRUE
246 IF old_year IS NULL THEN
247 RAISE EXCEPTION 'Input year argument is NULL';
248 ELSIF old_year NOT BETWEEN 2008 and 2200 THEN
249 RAISE EXCEPTION 'Input year is out of range';
252 IF user_id IS NULL THEN
253 RAISE EXCEPTION 'Input user id argument is NULL';
256 IF org_unit_id IS NULL THEN
257 RAISE EXCEPTION 'Org unit id argument is NULL';
259 SELECT TRUE INTO org_found
261 WHERE id = org_unit_id;
263 IF org_found IS NULL THEN
264 RAISE EXCEPTION 'Org unit id is invalid';
268 -- Loop over the applicable funds
270 FOR old_fund in SELECT * FROM acq.fund
274 AND ( ( include_desc AND org IN ( SELECT id FROM actor.org_unit_descendants( org_unit_id ) ) )
275 OR (NOT include_desc AND org = org_unit_id ) )
279 INSERT INTO acq.fund (
287 balance_warning_percent,
293 old_fund.currency_type,
297 old_fund.balance_warning_percent,
298 old_fund.balance_stop_percent
300 RETURNING id INTO new_id;
302 WHEN unique_violation THEN
303 --RAISE NOTICE 'Fund % already propagated', old_fund.id;
307 PERFORM acq.copy_fund_tags(old_fund.id,new_id);
309 --RAISE NOTICE 'Propagating fund % to fund %',
310 -- old_fund.code, new_id;