summaryrefslogtreecommitdiff
path: root/sql/modules/Voucher.sql
blob: 5c236ed5f6bf5adf69dbf5664500444911adcb9f (plain)
  1. CREATE OR REPLACE FUNCTION voucher_get_batch (in_batch_id integer)
  2. RETURNS batch AS
  3. $$
  4. DECLARE
  5. batch_out batch%ROWTYPE;
  6. BEGIN
  7. SELECT * INTO batch_out FROM batch b WHERE b.id = in_batch_id;
  8. RETURN batch_out;
  9. END;
  10. $$ language plpgsql;
  11. CREATE OR REPLACE FUNCTION batch_update (in_batch text, in_login varchar, in_entered date,
  12. in_batch_number text, in_description text, in_id integer)
  13. RETURNS integer AS
  14. $$
  15. BEGIN
  16. UPDATE batch
  17. SET batch_number = in_batch_number,
  18. description = in_description,
  19. entered = in_entered
  20. WHERE id = in_id;
  21. IF FOUND THEN
  22. RETURN in_id;
  23. END IF;
  24. INSERT INTO batch (batch, employee_id, batch_number, description,
  25. entered)
  26. VALUES (in_batch, (SELECT id FROM employees WHERE login = in_login),
  27. in_batch_number, description);
  28. RETURN currval('id');
  29. END;
  30. $$ LANGUAGE PLPGSQL;
  31. CREATE TYPE voucher_list AS (
  32. id int,
  33. reference text,
  34. description text,
  35. batch_id int,
  36. transaction_id integer,
  37. amount numeric,
  38. transaction_date date,
  39. batch_class text
  40. );
  41. CREATE OR REPLACE FUNCTION voucher_list (in_batch_id integer)
  42. RETURNS SETOF voucher_list AS
  43. $$
  44. declare voucher_item record;
  45. BEGIN
  46. FOR voucher_item IN
  47. SELECT v.id, a.invnumber, e.name,
  48. v.batch_id, v.trans_id,
  49. a.amount, a.transdate, 'Payable'
  50. FROM voucher v
  51. JOIN ap a ON (v.trans_id = a.id)
  52. JOIN entity e ON (a.entity_id = e.id)
  53. WHERE v.batch_id = in_batch_id
  54. AND v.batch_class = (select id from batch_class
  55. WHERE class = 'ap')
  56. UNION
  57. SELECT v.id, a.invnumber, e.name,
  58. v.batch_id, v.trans_id,
  59. a.amount, a.transdate, 'Receivable'
  60. FROM voucher v
  61. JOIN ar a ON (v.trans_id = a.id)
  62. JOIN entity e ON (a.entity_id = e.id)
  63. WHERE v.batch_id = in_batch_id
  64. AND v.batch_class = (select id from batch_class
  65. WHERE class = 'ar')
  66. UNION ALL
  67. -- TODO: Add the class labels to the class table.
  68. SELECT v.id, a.source,
  69. cr.meta_number || '--' || co.legal_name ,
  70. v.batch_id, v.trans_id,
  71. CASE WHEN bc.class LIKE 'payment%' THEN a.amount * -1
  72. ELSE a.amount END, a.transdate,
  73. CASE WHEN bc.class = 'payment' THEN 'Payment'
  74. WHEN bc.class = 'payment_reversal'
  75. THEN 'Payment Reversal'
  76. END
  77. FROM voucher v
  78. JOIN acc_trans a ON (v.id = a.voucher_id)
  79. JOIN batch_class bc ON (bc.id = v.batch_class)
  80. JOIN chart c ON (a.chart_id = c.id)
  81. JOIN ap ON (ap.id = a.trans_id)
  82. JOIN entity_credit_account cr
  83. ON (ap.entity_credit_account = cr.id)
  84. JOIN company co ON (cr.entity_id = co.entity_id)
  85. WHERE v.batch_id = in_batch_id
  86. AND a.voucher_id = v.id
  87. AND (bc.class like 'payment%' AND c.link = 'AP')
  88. UNION ALL
  89. SELECT v.id, a.source, a.memo,
  90. v.batch_id, v.trans_id,
  91. CASE WHEN bc.class LIKE 'receipt%' THEN a.amount * -1
  92. ELSE a.amount END, a.transdate,
  93. CASE WHEN bc.class = 'receipt' THEN 'Receipt'
  94. WHEN bc.class = 'receipt_reversal'
  95. THEN 'Receipt Reversal'
  96. END
  97. FROM voucher v
  98. JOIN acc_trans a ON (v.trans_id = a.trans_id)
  99. JOIN batch_class bc ON (bc.id = v.batch_class)
  100. JOIN chart c ON (a.chart_id = c.id)
  101. JOIN ar ON (ar.id = a.trans_id)
  102. JOIN entity_credit_account cr
  103. ON (ar.entity_credit_account = cr.id)
  104. JOIN company co ON (cr.entity_id = co.entity_id)
  105. WHERE v.batch_id = in_batch_id
  106. AND a.voucher_id = v.id
  107. AND (bc.class like 'receipt%' AND c.link = 'AR')
  108. UNION ALL
  109. SELECT v.id, g.reference, g.description,
  110. v.batch_id, v.trans_id,
  111. sum(a.amount), g.transdate, 'gl'
  112. FROM voucher v
  113. JOIN gl g ON (g.id = v.trans_id)
  114. JOIN acc_trans a ON (v.trans_id = a.trans_id)
  115. WHERE a.amount > 0
  116. AND v.batch_id = in_batch_id
  117. AND v.batch_class IN (select id from batch_class
  118. where class = 'gl')
  119. GROUP BY v.id, g.reference, g.description, v.batch_id,
  120. v.trans_id, g.transdate
  121. ORDER BY 7, 1
  122. LOOP
  123. RETURN NEXT voucher_item;
  124. END LOOP;
  125. END;
  126. $$ language plpgsql;
  127. CREATE TYPE batch_list_item AS (
  128. id integer,
  129. batch_class text,
  130. control_code text,
  131. description text,
  132. created_by text,
  133. created_on date,
  134. transaction_total numeric,
  135. payment_total numeric
  136. );
  137. CREATE OR REPLACE FUNCTION
  138. batch_search(in_class_id int, in_description text, in_created_by_eid int,
  139. in_amount_gt numeric,
  140. in_amount_lt numeric, in_approved bool)
  141. RETURNS SETOF batch_list_item AS
  142. $$
  143. DECLARE out_value batch_list_item;
  144. BEGIN
  145. FOR out_value IN
  146. SELECT b.id, c.class, b.control_code, b.description, u.username,
  147. b.created_on,
  148. sum(
  149. CASE WHEN vc.id = 5 AND al.amount < 0 -- GL
  150. THEN al.amount
  151. WHEN vc.id = 1
  152. THEN ap.amount
  153. WHEN vc.id = 2
  154. THEN ap.amount
  155. ELSE 0
  156. END) AS transaction_total,
  157. sum(
  158. CASE WHEN alc.link = 'AR' AND vc.id IN (6, 7)
  159. THEN al.amount
  160. WHEN alc.link = 'AP' AND vc.id IN (3, 4)
  161. THEN al.amount * -1
  162. ELSE 0
  163. END
  164. ) AS payment_total
  165. FROM batch b
  166. JOIN batch_class c ON (b.batch_class_id = c.id)
  167. LEFT JOIN users u ON (u.entity_id = b.created_by)
  168. JOIN voucher v ON (v.batch_id = b.id)
  169. JOIN batch_class vc ON (v.batch_class = vc.id)
  170. LEFT JOIN ar ON (vc.id = 2 AND v.trans_id = ar.id)
  171. LEFT JOIN ap ON (vc.id = 1 AND v.trans_id = ap.id)
  172. LEFT JOIN acc_trans al ON
  173. ((vc.id = 5 AND v.trans_id = al.trans_id) OR
  174. (vc.id IN (3, 4, 6, 7)
  175. AND al.voucher_id = v.id))
  176. LEFT JOIN chart alc ON (al.chart_id = alc.id)
  177. WHERE (c.id = in_class_id OR in_class_id IS NULL) AND
  178. (b.description LIKE
  179. '%' || in_description || '%' OR
  180. in_description IS NULL) AND
  181. (in_created_by_eid = b.created_by OR
  182. in_created_by_eid IS NULL) AND
  183. ((in_approved = false OR in_approved IS NULL AND
  184. approved_on IS NULL) OR
  185. (in_approved = true AND approved_on IS NOT NULL)
  186. )
  187. GROUP BY b.id, c.class, b.description, u.username, b.created_on,
  188. b.control_code
  189. HAVING
  190. (in_amount_gt IS NULL OR
  191. sum(coalesce(ar.amount - ar.paid, ap.amount - ap.paid,
  192. al.amount))
  193. >= in_amount_gt)
  194. AND
  195. (in_amount_lt IS NULL OR
  196. sum(coalesce(ar.amount - ar.paid, ap.amount - ap.paid,
  197. al.amount))
  198. <= in_amount_lt)
  199. LOOP
  200. RETURN NEXT out_value;
  201. END LOOP;
  202. END;
  203. $$ LANGUAGE PLPGSQL;
  204. CREATE OR REPLACE FUNCTION batch_get_class_id (in_type text) returns int AS
  205. $$
  206. SELECT id FROM batch_class WHERE class = $1;
  207. $$ language sql;
  208. CREATE OR REPLACE FUNCTION
  209. batch_search_mini
  210. (in_class_id int, in_description text, in_created_by_eid int, in_approved bool)
  211. RETURNS SETOF batch_list_item AS
  212. $$
  213. DECLARE out_value batch_list_item;
  214. BEGIN
  215. FOR out_value IN
  216. SELECT b.id, c.class, b.control_code, b.description, u.username,
  217. b.created_on, NULL
  218. FROM batch b
  219. JOIN batch_class c ON (b.batch_class_id = c.id)
  220. LEFT JOIN users u ON (u.entity_id = b.created_by)
  221. JOIN voucher v ON (v.batch_id = b.id)
  222. WHERE (c.id = in_class_id OR in_class_id IS NULL) AND
  223. (b.description LIKE
  224. '%' || in_description || '%' OR
  225. in_description IS NULL) AND
  226. (in_created_by_eid = b.created_by OR
  227. in_created_by_eid IS NULL) AND
  228. ((in_approved = false OR in_approved IS NULL AND
  229. approved_on IS NULL) OR
  230. (in_approved = true AND approved_on IS NOT NULL)
  231. )
  232. GROUP BY b.id, c.class, b.description, u.username, b.created_on,
  233. b.control_code
  234. LOOP
  235. RETURN NEXT out_value;
  236. END LOOP;
  237. END;
  238. $$ LANGUAGE PLPGSQL;
  239. CREATE OR REPLACE FUNCTION batch_post(in_batch_id INTEGER)
  240. returns date AS
  241. $$
  242. BEGIN
  243. UPDATE ar SET approved = true
  244. WHERE id IN (select trans_id FROM voucher
  245. WHERE batch_id = in_batch_id
  246. AND batch_class = 2);
  247. UPDATE ap SET approved = true
  248. WHERE id IN (select trans_id FROM voucher
  249. WHERE batch_id = in_batch_id
  250. AND batch_class = 1);
  251. UPDATE gl SET approved = true
  252. WHERE id IN (select trans_id FROM voucher
  253. WHERE batch_id = in_batch_id
  254. AND batch_class = 5);
  255. UPDATE acc_trans SET approved = true
  256. WHERE voucher_id IN (select id FROM voucher
  257. WHERE batch_id = in_batch_id
  258. AND batch_class IN (3, 4, 7, 8));
  259. UPDATE batch
  260. SET approved_on = now(),
  261. approved_by = (select entity_id FROM users
  262. WHERE username = SESSION_USER)
  263. WHERE id = in_batch_id;
  264. RETURN now()::date;
  265. END;
  266. $$ LANGUAGE PLPGSQL;
  267. CREATE OR REPLACE FUNCTION batch_list_classes() RETURNS SETOF batch_class AS
  268. $$
  269. DECLARE out_val record;
  270. BEGIN
  271. FOR out_val IN select * from batch_class
  272. LOOP
  273. return next out_val;
  274. END LOOP;
  275. END;
  276. $$ language plpgsql;
  277. CREATE OR REPLACE FUNCTION batch_get_users() RETURNS SETOF users AS
  278. $$
  279. DECLARE out_record users%ROWTYPE;
  280. BEGIN
  281. FOR out_record IN
  282. SELECT * from users WHERE entity_id IN (select created_by from batch)
  283. LOOP
  284. RETURN NEXT out_record;
  285. END LOOP;
  286. END;
  287. $$ LANGUAGE PLPGSQL;
  288. CREATE OR REPLACE FUNCTION batch_create(
  289. in_batch_number text, in_description text, in_batch_class text) RETURNS int AS
  290. $$
  291. BEGIN
  292. INSERT INTO
  293. batch (batch_class_id, description, control_code, created_by)
  294. VALUES ((SELECT id FROM batch_class WHERE class = in_batch_class),
  295. in_description, in_batch_number,
  296. (select entity_id FROM users WHERE username = session_user));
  297. return currval('batch_id_seq');
  298. END;
  299. $$ LANGUAGE PLPGSQL;
  300. CREATE OR REPLACE FUNCTION batch_delete(in_batch_id int) RETURNS int AS
  301. $$
  302. DECLARE
  303. t_transaction_ids int[];
  304. BEGIN
  305. -- Adjust AR/AP tables for payment and payment reversal vouchers
  306. -- voucher_id is only set in acc_trans on payment/receipt vouchers and
  307. -- their reversals. -CT
  308. update ar set paid = amount +
  309. (select sum(amount) from acc_trans
  310. join chart ON (acc_trans.chart_id = chart.id)
  311. where link = 'AR' AND trans_id = ar.id
  312. AND (voucher_id IS NULL OR voucher_id NOT IN
  313. (select id from voucher
  314. WHERE batch_id = in_batch_id)))
  315. where id in (select trans_id from acc_trans where voucher_id IN
  316. (select id from voucher where batch_id = in_batch_id));
  317. update ap set paid = amount - (select sum(amount) from acc_trans
  318. join chart ON (acc_trans.chart_id = chart.id)
  319. where link = 'AP' AND trans_id = ap.id
  320. AND (voucher_id IS NULL OR voucher_id NOT IN
  321. (select id from voucher
  322. WHERE batch_id = in_batch_id)))
  323. where id in (select trans_id from acc_trans where voucher_id IN
  324. (select id from voucher where batch_id = in_batch_id));
  325. DELETE FROM acc_trans WHERE voucher_id IN
  326. (select id FROM voucher where batch_id = in_batch_id);
  327. -- The rest of this function involves the deletion of actual
  328. -- transactions, vouchers, and batches, and jobs which are in progress.
  329. -- -CT
  330. SELECT as_array(trans_id) INTO t_transaction_ids
  331. FROM voucher WHERE batch_id = in_batch_id AND batch_class IN (1, 2, 5);
  332. DELETE FROM acc_trans WHERE trans_id = ANY(t_transaction_ids);
  333. DELETE FROM ap WHERE id = ANY(t_transaction_ids);
  334. DELETE FROM gl WHERE id = ANY(t_transaction_ids);
  335. DELETE FROM voucher WHERE batch_id = in_batch_id;
  336. DELETE FROM payments_queue WHERE batch_id = in_batch_id;
  337. DELETE FROM pending_job WHERE batch_id = in_batch_id;
  338. DELETE FROM batch WHERE id = in_batch_id;
  339. DELETE FROM transactions WHERE id = ANY(t_transaction_ids);
  340. RETURN 1;
  341. END;
  342. $$ language plpgsql SECURITY DEFINER;
  343. REVOKE ALL ON FUNCTION batch_delete(int) FROM PUBLIC;
  344. CREATE OR REPLACE FUNCTION voucher__delete(in_voucher_id int)
  345. RETURNS int AS
  346. $$
  347. DECLARE
  348. voucher_row RECORD;
  349. BEGIN
  350. SELECT * INTO voucher_row FROM voucher WHERE id = in_voucher_id;
  351. IF voucher_row.batch_class IN (1, 2, 5) THEN
  352. DELETE from acc_trans WHERE trans_id = voucher_row.trans_id;
  353. DELETE FROM ar WHERE id = voucher_row.trans_id;
  354. DELETE FROM ap WHERE id = voucher_row.trans_id;
  355. DELETE FROM gl WHERE id = voucher_row.trans_id;
  356. DELETE FROM voucher WHERE id = voucher_row.id;
  357. DELETE FROM transactions WHERE id = voucher_row.trans_id;
  358. ELSE
  359. update ar set paid = amount +
  360. (select sum(amount) from acc_trans
  361. join chart ON (acc_trans.chart_id = chart.id)
  362. where link = 'AR' AND trans_id = ar.id
  363. AND (voucher_id IS NULL
  364. OR voucher_id <> voucher_row.id))
  365. where id in (select trans_id from acc_trans
  366. where voucher_id = voucher_row.id);
  367. update ap set paid = amount - (select sum(amount) from acc_trans
  368. join chart ON (acc_trans.chart_id = chart.id)
  369. where link = 'AP' AND trans_id = ap.id
  370. AND (voucher_id IS NULL
  371. OR voucher_id <> voucher_row.id))
  372. where id in (select trans_id from acc_trans
  373. where voucher_id = voucher_row.id);
  374. DELETE FROM acc_trans where voucher_id = voucher_row.id;
  375. END IF;
  376. RETURN 1;
  377. END;
  378. $$ LANGUAGE PLPGSQL SECURITY DEFINER;
  379. REVOKE ALL ON FUNCTION voucher__delete(int) FROM public;