pgsql/investigations/ar-creditmemo.sql
[Pman.Xtuple] / pgsql / x-dragon-locbal.sql
1
2 -- loc bal is disabled at present - it's slow, and does not help much..
3
4
5 CREATE SEQUENCE locbal_id_seq
6     START WITH 1
7     INCREMENT BY 1
8     NO MINVALUE
9     NO MAXVALUE
10     CACHE 1;
11 GRANT ALL ON SEQUENCE locbal_id_seq  TO xtrole;
12
13
14 CREATE TABLE locbal (
15     locbal_id INTEGER NOT NULL DEFAULT nextval(('locbal_id_seq'::text)::regclass),
16     locbal_period_id integer,
17     locbal_location_id integer,
18     
19     locbal_itemsite_id integer,
20     
21     locbal_beginning numeric(20,2),
22     locbal_ending numeric(20,2),
23     
24     locbal_credits numeric(20,2),
25     locbal_debits numeric(20,2),
26     
27     CONSTRAINT locbal_itemsite_id_fkey FOREIGN KEY (locbal_itemsite_id)
28         REFERENCES itemsite  (itemsite_id)  MATCH SIMPLE,
29     
30     
31     CONSTRAINT locbal_period_id_fkey FOREIGN KEY (locbal_period_id)
32         REFERENCES period (period_id)  MATCH SIMPLE,
33         
34     CONSTRAINT locbal_location_id_fkey FOREIGN KEY (locbal_location_id)
35         REFERENCES location (location_id),
36     CONSTRAINT locbal_id_pkey PRIMARY KEY (locbal_id)
37 );
38
39 CREATE UNIQUE INDEX locbal_locsite_idx  ON locbal USING btree  (locbal_period_id, locbal_location_id, locbal_itemsite_id );
40
41
42
43 ALTER TABLE public.locbal OWNER TO admin;
44 GRANT ALL ON TABLE locbal  TO xtrole;
45 COMMENT ON TABLE locbal IS 'Location Balance information';
46
47  CREATE SEQUENCE loccurbal_id_seq
48     START WITH 1
49     INCREMENT BY 1
50     NO MINVALUE
51     NO MAXVALUE
52     CACHE 1;
53
54 GRANT ALL ON TABLE loccurbal_id_seq TO xtrole;
55
56 CREATE TABLE loccurbal (
57     loccurbal_id INTEGER NOT NULL DEFAULT nextval(('loccurbal_id_seq'::text)::regclass),
58     loccurbal_location_id integer,
59     loccurbal_itemsite_id integer,
60     loccurbal_ending numeric(20,2),
61     
62     CONSTRAINT loccurbal_itemsite_id_fkey FOREIGN KEY (loccurbal_itemsite_id)
63         REFERENCES itemsite  (itemsite_id)  MATCH SIMPLE,
64     CONSTRAINT loccurbal_location_id_fkey FOREIGN KEY (loccurbal_location_id)
65         REFERENCES location (location_id),
66     CONSTRAINT loccurbal_id_pkey PRIMARY KEY (loccurbal_id)
67 );
68
69 ALTER TABLE public.loccurbal OWNER TO admin;
70
71 GRANT ALL ON TABLE loccurbal TO xtrole;
72
73 COMMENT ON TABLE loccurbal IS 'Location Balance current';
74
75
76 CREATE UNIQUE INDEX loccurbal_locsite_idx  ON loccurbal USING btree  (loccurbal_location_id, loccurbal_itemsite_id );
77
78
79
80
81 -- update balance.
82
83
84 -- TESTING:
85 -- SELECT distinct(invhist_itemsite_id), invdetaillocation_id, NOW() FROM invdetailview GROUP BY invhist_itemsite_id LIMIT 100;
86
87 -- 
88
89 DROP FUNCTION locbal_update_location_itemsite(integer, integer, date );
90 CREATE OR REPLACE FUNCTION locbal_update_location_itemsite(integer, integer, date )
91   RETURNS NUMERIC AS
92 $BODY$
93 -- Copyright (c) 1999-2011 by OpenMFG LLC, d/b/a xTuple. 
94 -- See www.xtuple.com/CPAL for the full text of the software license.
95 DECLARE
96   i_location_id ALIAS FOR $1;
97   i_itemsite_id ALIAS FOR $2;
98   i_date ALIAS FOR $3;
99   
100   v_id INTEGER;
101   v_chk INTEGER;
102   v_ret NUMERIC;
103   v_last NUMERIC;
104 BEGIN
105
106     --RAISE NOTICE 'update locbal(a) % , %, %',i_location_id, i_itemsite_id,  i_date;
107     SELECT
108             period_id
109         INTO
110             v_id
111         FROM
112             period
113         WHERE
114             period_start <= i_date
115             AND
116             period_end >= i_date;
117         
118     IF NOT FOUND THEN
119         RAISE NOTICE 'no period found';
120         RETURN 0;
121     END IF;
122   
123     -- make sure there are some transactions for that item/location
124     SELECT
125             invdetail_id
126         INTO
127             v_chk
128         FROM
129             invdetailview
130         WHERE
131             invhist_itemsite_id = i_itemsite_id
132             AND
133             invdetail_location_id = i_location_id
134             AND
135             invhist_posted
136         LIMIT 1;
137         
138     IF NOT FOUND THEN
139         RAISE NOTICE 'no transactions found';
140         RETURN 0;
141     END IF;
142     
143     
144      --RAISE NOTICE 'locbal_update_location_itemsite_period(  % , %, %) ',i_location_id, i_itemsite_id, v_id;
145    
146     -- this handle current and before..
147     SELECT
148             locbal_update_location_itemsite_period(i_location_id, i_itemsite_id, v_id)
149         INTO
150             v_ret;
151     
152     -- we should update after...
153     
154  
155     -- finally update the total..
156     --RAISE NOTICE 'locbal_update_begin_end   %   ',i_date  ;
157    
158     PERFORM
159            locbal_update_begin_end(locbal_id)
160         FROM
161             locbal
162         LEFT JOIN
163             period
164         ON
165             locbal_period_id = period_id
166         WHERE
167             period_start > i_date
168             AND
169             locbal_itemsite_id = i_itemsite_id
170             AND
171             locbal_location_id = i_location_id
172         ORDER BY
173             period_start ASC;
174     
175     
176      --RAISE NOTICE 'loccurbal_update(  % , % ) ',i_location_id, i_itemsite_id ;
177     ---- updates loccurbal find final locbal_id
178     PERFORM loccurbal_update(i_location_id, i_itemsite_id); 
179     RETURN v_ret;
180   
181   
182 END;
183 $BODY$
184   LANGUAGE plpgsql VOLATILE
185   COST 100;
186 ALTER FUNCTION locbal_update_location_itemsite(integer, integer, date )
187   OWNER TO admin;
188     
189
190
191
192  
193 CREATE OR REPLACE FUNCTION locbal_update_begin_end(integer  )
194   RETURNS NUMERIC AS
195 $BODY$
196 -- Copyright (c) 1999-2011 by OpenMFG LLC, d/b/a xTuple. 
197 -- See www.xtuple.com/CPAL for the full text of the software license.
198 DECLARE
199     i_id ALIAS FOR $1;
200     v_location_id INTEGER;
201     v_itemsite_id INTEGER;
202    
203     v_period_start DATE;
204     v_balance NUMERIC;
205     
206 BEGIN
207
208     --0 get current.
209     SELECT
210             locbal_location_id,
211             locbal_itemsite_id,
212             period_start
213         INTO
214             v_location_id,
215             v_itemsite_id,
216             v_period_start
217         FROM
218             locbal
219         LEFT JOIN
220             period
221         ON
222             locbal_period_id = period_id
223         WHERE
224             locbal_id = i_id ;
225         
226     
227     -- get prev
228     
229     SELECT
230             locbal_ending
231         INTO
232             v_balance
233         FROM
234             locbal
235         LEFT JOIN
236             period
237         ON
238             locbal_period_id = period_id
239         WHERE
240             locbal_id != i_id
241             AND
242             period_start < v_period_start
243             AND
244             locbal_location_id = v_location_id
245             AND 
246             locbal_itemsite_id = v_itemsite_id
247         ORDER BY
248             period_start DESC
249         LIMIT 1;
250     
251     IF NOT FOUND THEN
252         -- RAISE NOTICE 'no more previous periods';
253         v_balance := 0;
254     END IF;
255
256     UPDATE
257         locbal
258         SET
259             locbal_beginning = v_balance,
260             locbal_ending = v_balance + locbal_credits - locbal_debits
261         WHERE
262             locbal_id = i_id;
263     
264     RETURN v_balance;
265 END;
266 $BODY$
267   LANGUAGE plpgsql VOLATILE
268   COST 100;
269 ALTER FUNCTION locbal_update_begin_end(integer  )
270   OWNER TO admin;
271     
272
273
274
275
276  
277 CREATE OR REPLACE FUNCTION loccurbal_update(integer, integer)
278   RETURNS NUMERIC AS
279 $BODY$
280 -- Copyright (c) 1999-2011 by OpenMFG LLC, d/b/a xTuple. 
281 -- See www.xtuple.com/CPAL for the full text of the software license.
282 DECLARE
283     
284     i_location_id ALIAS FOR $1;
285     i_itemsite_id ALIAS FOR $2;
286    
287     v_id INTEGER;
288     v_balance NUMERIC;
289     
290 BEGIN
291
292     --0 get current.
293      
294     -- get last
295     
296     SELECT
297             COALESCE(locbal_ending, 0)
298         INTO
299             v_balance
300         FROM
301             locbal
302         LEFT JOIN
303             period
304         ON
305             locbal_period_id = period_id
306         WHERE
307              
308             locbal_location_id = i_location_id
309             AND 
310             locbal_itemsite_id = i_itemsite_id
311         ORDER BY
312             period_start DESC
313         LIMIT 1;
314     
315     IF NOT FOUND  THEN
316         v_balance := 0;
317     END IF;
318     
319     SELECT
320           loccurbal_id 
321         INTO
322             v_id
323         FROM
324             loccurbal
325         WHERE
326             loccurbal_location_id = i_location_id
327             AND 
328             loccurbal_itemsite_id = i_itemsite_id
329         LIMIT 1;
330     
331     IF NOT FOUND THEN
332         INSERT INTO loccurbal (
333             loccurbal_location_id,
334             loccurbal_itemsite_id,
335             loccurbal_ending 
336         ) VALUES (
337             i_location_id,
338             i_itemsite_id,
339             v_balance
340         );
341         RETURN v_balance;
342     END IF;
343     
344      
345     UPDATE
346         loccurbal
347         SET
348             loccurbal_ending = v_balance 
349         WHERE
350             loccurbal_id = v_id;
351     
352     RETURN v_balance;
353 END;
354 $BODY$
355   LANGUAGE plpgsql VOLATILE
356   COST 100;
357 ALTER FUNCTION loccurbal_update(integer, integer)
358   OWNER TO admin;
359     
360
361  
362
363     
364     
365 CREATE OR REPLACE FUNCTION locbal_update_location_itemsite_period(integer,integer, integer)
366   RETURNS NUMERIC AS
367 $BODY$
368 -- Copyright (c) 1999-2011 by OpenMFG LLC, d/b/a xTuple. 
369 -- See www.xtuple.com/CPAL for the full text of the software license.
370 DECLARE
371   i_location_id ALIAS FOR $1;
372   i_itemsite_id ALIAS FOR $2;
373   i_period_id ALIAS FOR $3;
374   
375  
376   v_id INTEGER;
377   v_prev_period_id INTEGER;
378    
379   v_credit NUMERIC;
380   v_debit NUMERIC;
381   v_balance NUMERIC;
382   
383   v_start DATE;
384   v_end DATE;
385
386 BEGIN
387
388     --RAISE NOTICE 'SELECT locbal_update_location_itemsite_period (% , %, %)',i_location_id, i_itemsite_id,  i_period_id;
389     SELECT
390             period_start,
391             period_end
392         INTO
393             v_start,
394             v_end
395         FROM
396             period
397         WHERE
398             period_id = i_period_id;
399
400     -- check to see if we have a value for the previous period.
401
402
403     SELECT
404             period_id
405         INTO
406             v_prev_period_id
407         FROM
408             period
409         WHERE
410             period_start < v_start
411             AND
412             period_id != i_period_id
413         ORDER BY
414             period_start DESC
415         LIMIT 1;
416         
417     IF NOT FOUND THEN
418         -- RAISE NOTICE 'no more previous periods';
419         v_balance := 0;
420     ELSE
421         -- find out if we have a balance for the previous period..
422         
423         SELECT
424                 locbal_ending
425             INTO
426                 v_balance
427             FROM
428                 locbal
429             WHERE
430                 locbal_location_id = i_location_id
431             AND
432                 locbal_itemsite_id = i_itemsite_id
433             AND
434                 locbal_period_id = v_prev_period_id;
435                 
436             
437         IF NOT FOUND THEN
438         
439             
440         
441             SELECT
442                 locbal_update_location_itemsite_period(i_location_id,i_itemsite_id, v_prev_period_id)
443             INTO
444                 v_balance;
445                 
446         END IF;
447     
448     
449     END IF;
450
451
452
453     SELECT
454             
455             COALESCE(SUM( CASE WHEN invdetail_qty > 0 THEN invdetail_qty ELSE 0 END) , 0) ,
456             COALESCE(SUM( CASE WHEN invdetail_qty < 0 THEN invdetail_qty * -1 ELSE 0 END) , 0) 
457         INTO
458             v_credit,
459             v_debit
460          
461         FROM
462             invdetailview
463         WHERE
464             invhist_transdate >= v_start
465             AND
466             invhist_transdate < v_end + INTERVAL '1 DAY'
467             AND
468             invhist_itemsite_id = i_itemsite_id 
469             AND
470             invdetail_location_id = i_location_id
471             AND
472             invhist_posted;
473             
474             
475     IF NOT FOUND THEN
476         v_credit := 0;
477         v_debit := 0;
478     END IF;
479     
480     -- do we have a current record...
481       
482     SELECT
483             locbal_id
484         INTO
485             v_id
486         FROM
487             locbal
488         WHERE
489             locbal_location_id = i_location_id
490         AND
491             locbal_itemsite_id = i_itemsite_id
492         AND
493             locbal_period_id = i_period_id;
494     
495     IF NOT FOUND THEN
496         --RAISE NOTICE 'adding locbal';
497     
498         INSERT INTO locbal
499         ( 
500             locbal_period_id  ,
501             locbal_location_id  ,
502             
503             locbal_itemsite_id  ,
504             
505             locbal_beginning  ,
506             locbal_ending  ,
507             
508             locbal_credits  ,
509             locbal_debits
510         ) VALUES (
511             i_period_id,
512             i_location_id,
513             i_itemsite_id,
514             
515             v_balance,
516             v_balance + v_credit - v_debit,
517             
518             v_credit,
519             v_debit
520         
521         );
522     ELSE
523         --RAISE NOTICE 'updating locbal';
524         UPDATE locbal
525             SET 
526                 locbal_beginning  = v_balance,
527                 locbal_ending = v_balance + v_credit - v_debit ,
528                 
529                 locbal_credits  = v_credit,
530                 locbal_debits = v_debit
531             WHERE
532                 locbal_id = v_id;
533     END IF;
534     
535             
536     RETURN v_balance + v_credit - v_debit ;
537
538 END;
539 $BODY$
540   LANGUAGE plpgsql VOLATILE
541   COST 100;
542 ALTER FUNCTION locbal_update_location_itemsite_period(integer,integer, integer)
543   OWNER TO admin;
544     
545
546 -- TESTING
547 --
548 --SELECT locbal_update_location_itemsite(a,b,c)
549 --    FROM (
550 --        SELECT distinct(invhist_itemsite_id) b, invdetail_location_id a, MAX(invhist_transdate)::date c
551 --        FROM invdetailview
552 --        
553 --        GROUP BY invhist_itemsite_id, invdetail_location_id  ) d;
554 -- 
555 -- 
556 -- 
557
558   
559
560 CREATE OR REPLACE FUNCTION _invhist_locbaltrigger()
561   RETURNS trigger AS
562 $BODY$
563 DECLARE
564   v_ret NUMERIC;
565
566 BEGIN
567     IF (TG_OP = 'INSERT') THEN
568         SELECT locbal_update_location_itemsite(NEW.invdetail_location_id, invhist_itemsite_id, invhist_transdate::date)
569         INTO v_ret
570             FROM invhist WHERE invhist_id = NEW.invdetail_invhist_id;
571     
572         RETURN NEW;
573     END IF;
574      IF (TG_OP = 'UPDATE') THEN
575         
576         SELECT locbal_update_location_itemsite(NEW.invdetail_location_id, invhist_itemsite_id, invhist_transdate::date)
577         INTO v_ret
578             FROM invhist WHERE invhist_id = NEW.invdetail_invhist_id;
579         
580         SELECT locbal_update_location_itemsite(OLD.invdetail_location_id, invhist_itemsite_id, invhist_transdate::date)
581         INTO v_ret
582             FROM invhist WHERE invhist_id = OLD.invdetail_invhist_id;
583     
584         RETURN NEW;
585     END IF;
586     
587     IF (TG_OP = 'DELETE') THEN
588         SELECT locbal_update_location_itemsite(OLD.invdetail_location_id, invhist_itemsite_id, invhist_transdate::date)
589         INTO v_ret
590             FROM invhist WHERE invhist_id = OLD.invdetail_invhist_id;
591       
592         RETURN OLD;
593     END IF;
594     
595     RETURN NEW;
596     
597  END;
598 $BODY$
599   LANGUAGE plpgsql VOLATILE
600   COST 100;
601 ALTER FUNCTION _invhist_locbaltrigger()
602   OWNER TO admin;      
603 --    
604 --CREATE TRIGGER invhist_locbaltrigger
605 --  AFTER INSERT OR UPDATE OR DELETE
606 --  ON invdetail
607 --  FOR EACH ROW
608 --  EXECUTE PROCEDURE _invhist_locbaltrigger();
609
610 DROP TRIGGER invhist_locbaltrigger ON invdetail;