File: arap.sql

package info (click to toggle)
ledgersmb 1.6.33%2Bds-2.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 33,000 kB
  • sloc: perl: 52,612; sql: 43,562; xml: 36,194; javascript: 2,428; sh: 1,099; makefile: 361; pascal: 25
file content (309 lines) | stat: -rw-r--r-- 13,805 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309

set client_min_messages = 'warning';


BEGIN;

DROP TYPE IF EXISTS purchase_info CASCADE;

CREATE TYPE purchase_info AS (
    id int,
    invoice bool,
    invnumber text,
    ordnumber text,
    ponumber text,
    transdate date,
    entity_name text,
    meta_number text,
    entity_id int,
    amount numeric,
    amount_paid numeric,
    tax numeric,
    currency char(3),
    due_date date,
    notes text,
    shipping_point text,
    ship_via text,
    business_units text[]
);

DROP FUNCTION IF EXISTS ar_ap__transaction_search
(in_account_id int, in_name_part text, in_meta_number text, in_invnumber text,
 in_ordnumber text, in_ponumber text, in_source text, in_description text,
 in_notes text, in_shipvia text, in_from_date date, in_to_date date,
 in_on_hold bool, in_inc_open bool, in_inc_closed bool, in_as_of date,
 in_entity_class int);

CREATE OR REPLACE FUNCTION ar_ap__transaction_search
(in_account_id int, in_name_part text, in_meta_number text, in_invnumber text,
 in_ordnumber text, in_ponumber text, in_source text, in_description text,
 in_notes text, in_shipvia text, in_from_date date, in_to_date date,
 in_on_hold bool, in_inc_open bool, in_inc_closed bool, in_as_of date,
 in_entity_class int, in_approved bool)
RETURNS SETOF purchase_info AS
$$
   SELECT gl.id, gl.invoice,
          gl.invnumber, gl.ordnumber, gl.ponumber, gl.transdate,
          e.name, eca.meta_number::text, e.id, gl.amount,
          gl.amount - sum(CASE WHEN l.description IN ('AR', 'AP')
                               THEN ac.amount ELSE 0
                           END),
          gl.amount - gl.netamount, gl.curr, gl.duedate,
          gl.notes, gl.shippingpoint, gl.shipvia,
          compound_array(bua.business_units || bui.business_units)
     FROM (select id, invoice, invnumber, ordnumber, ponumber, transdate, duedate,
                  description, notes, shipvia, shippingpoint, amount,
                  netamount, curr, entity_credit_account, on_hold,
                  approved
             FROM ar WHERE in_entity_class = 2
            UNION
           select id, invoice, invnumber, ordnumber, ponumber, transdate, duedate,
                  description, notes, shipvia, shippingpoint, amount,
                  netamount, curr, entity_credit_account, on_hold,
                  approved
             FROM ap WHERE in_entity_class = 1) gl
     JOIN entity_credit_account eca ON gl.entity_credit_account = eca.id
     JOIN entity e ON e.id = eca.entity_id
     JOIN acc_trans ac ON gl.id = ac.trans_id
     JOIN account act ON act.id = ac.chart_id
LEFT JOIN account_link l ON l.account_id = act.id
                          AND l.description IN ('AR', 'AP')
LEFT JOIN invoice inv ON gl.id = inv.trans_id
LEFT JOIN (SELECT compound_array(ARRAY[ARRAY[buc.label, bu.control_code]])
                  as business_units, entry_id
             FROM business_unit_class buc
             JOIN business_unit bu ON bu.class_id = buc.id
             JOIN business_unit_ac buac ON buac.bu_id = bu.id
         GROUP BY buac.entry_id) bua
                                 ON bua.entry_id = ac.entry_id
LEFT JOIN (SELECT compound_array(ARRAY[ARRAY[buc.label, bu.control_code]])
                  as business_units, entry_id
             FROM business_unit_class buc
             JOIN business_unit bu ON bu.class_id = buc.id
             JOIN business_unit_inv buinv ON buinv.bu_id = bu.id
         GROUP BY buinv.entry_id) bui
                                 ON bui.entry_id = inv.id
    WHERE (in_account_id IS NULL OR ac.chart_id = in_account_id)
          AND (in_name_part IS NULL
                OR to_tsvector(get_default_lang()::regconfig, e.name)
                   @@ plainto_tsquery(get_default_lang()::regconfig, in_name_part))
          AND (in_meta_number IS NULL
                OR eca.meta_number LIKE in_meta_number || '%')
          AND (in_invnumber IS NULL or gl.invnumber LIKE in_invnumber || '%')
          AND (in_ordnumber IS NULL or gl.ordnumber LIKE in_ordnumber || '%')
          AND (in_ponumber IS NULL or gl.ponumber LIKE in_ponumber || '%')
          AND (in_description IS NULL
                or to_tsvector(get_default_lang()::regconfig, gl.description)
                  @@ plainto_tsquery(get_default_lang()::regconfig, in_description))
          AND (in_notes IS NULL OR
                to_tsvector(get_default_lang()::regconfig, gl.notes)
                 @@ plainto_tsquery(get_default_lang()::regconfig, in_notes))
          AND (in_from_date IS NULL OR in_from_date <= gl.transdate)
          AND (in_to_date IS NULL OR in_to_date >= gl.transdate)
          AND (in_on_hold IS NULL OR in_on_hold = gl.on_hold)
          AND (in_as_of IS NULL OR in_as_of >= ac.transdate)
          AND (in_approved is null
               OR (gl.approved = in_approved AND ac.approved = in_approved))
 GROUP BY gl.id, gl.invnumber, gl.ordnumber, gl.ponumber, gl.transdate,
          gl.duedate, e.name, eca.meta_number, gl.amount,
          gl.netamount, gl.curr, gl.duedate,
          gl.notes, gl.shippingpoint, gl.shipvia, e.id, gl.invoice
   HAVING in_source = ANY(array_agg(ac.source)) or in_source IS NULL;
$$ LANGUAGE SQL;

DROP FUNCTION IF EXISTS ar_ap__transaction_search_summary
(in_account_id int, in_name_part text, in_meta_number text, in_invnumber text,
 in_ordnumber text, in_ponumber text, in_source text, in_description text,
 in_notes text, in_shipvia text, in_from_date date, in_to_date date,
 in_on_hold bool, in_inc_open bool, in_inc_closed bool, in_as_of date,
 in_entity_class int);
CREATE OR REPLACE FUNCTION ar_ap__transaction_search_summary
(in_account_id int, in_name_part text, in_meta_number text, in_invnumber text,
 in_ordnumber text, in_ponumber text, in_source text, in_description text,
 in_notes text, in_shipvia text, in_from_date date, in_to_date date,
 in_on_hold bool, in_inc_open bool, in_inc_closed bool, in_as_of date,
 in_entity_class int, in_approved bool)
RETURNS SETOF purchase_info AS
$$
       SELECT null::int, null::bool, null::text, null::text, null::text,
              null::date, entity_name, meta_number, entity_id, sum(amount),
              sum(amount_paid), sum(tax), currency, null::date,
              null::text, null::text, null::text, null::text[]
         FROM ar_ap__transaction_search
              (in_account_id, in_name_part, in_meta_number, in_invnumber,
              in_ordnumber, in_ponumber, in_source, in_description,
              in_notes, in_shipvia, in_from_date, in_to_date,
              in_on_hold, in_inc_open, in_inc_closed, in_as_of,
              in_entity_class, in_approved)
     GROUP BY entity_name, meta_number, entity_id, currency;
$$ language sql;

--tshvr4 first attempt to mimic AA.pm,sub post_transaction in PLPGSQL function begin
--this is still trial and error
--see also sql/modules/Invoice.sql
--sql/modules/Journal.sql , example of SELECT .. into .. FROM expand(array_lines);
CREATE OR REPLACE FUNCTION AP_simple_post
(
 in_entity_credit_account int,in_ap_liablility_chartid int,in_invnumber text,in_transdate date,in_duedate date,in_curr char(3),in_description text,in_ordnumber text,in_notes text,in_intnotes text,in_ponumber text,in_memo text[],in_netamount numeric[],in_chartid numeric[],in_taxrate numeric[],in_taxchartid numeric[]
)
RETURNS INT AS
$$
DECLARE invnumber text;
DECLARE ap_id   int;
DECLARE entry_id   int;
DECLARE chartid int;
DECLARE tax_chartid int;
DECLARE invoice bool;
DECLARE separate_duties bool;
DECLARE approved bool;
DECLARE taxincluded bool;
DECLARE curr char(3);
DECLARE curr_default char(3);
DECLARE transdate date;
DECLARE duedate date;
DECLARE crdate date;
DECLARE memo text;
DECLARE netamount numeric;
DECLARE netamount_total numeric;
DECLARE taxrate numeric;
DECLARE taxamount numeric;
DECLARE taxamount_total numeric;
DECLARE amount_total numeric;
DECLARE person_id int;
DECLARE dp int;
DECLARE fx_transaction bool;
DECLARE cleared bool;
DECLARE taxform_id int;
DECLARE reportable bool;
DECLARE atf_count int;
DECLARE ect_count int;
BEGIN
 netamount_total=0.0;
 taxamount_total=0.0;
 invoice=false;
 approved=true;
 taxincluded=false;
 fx_transaction=false;
 cleared=false;

 select value::int       INTO dp FROM setting_get('decimal_places');
 select person__get_my_entity_id into person_id from person__get_my_entity_id();
 SELECT value::bool INTO separate_duties FROM defaults WHERE setting_key='separate_duties';
 IF separate_duties = true THEN
  --RAISE EXCEPTION 'separate_duties not yet treated';
  approved=false;
 END IF;
 select eca.taxform_id::int into taxform_id from entity_credit_account eca where eca.id=in_entity_credit_account;
 IF taxform_id <> 0 THEN
  --FOREIGN KEY (taxform_id) REFERENCES country_tax_form(id)
  RAISE EXCEPTION 'taxform not yet treated';
 END IF;

 transdate=coalesce(in_transdate,'today');
 duedate=coalesce(in_duedate,'today');
 crdate=now();

 --IF in_invnumber IS NULL OR (length(trim(in_invnumber))=0) THEN --NULL as only designator for "no value supplied"
 IF in_invnumber IS NULL THEN
  select setting_increment::text INTO invnumber FROM setting_increment('vinumber');
 ELSE
  invnumber=in_invnumber;
 END IF;

 select defaults_get_defaultcurrency into curr_default from defaults_get_defaultcurrency();
 IF in_curr IS NULL THEN
  curr=curr_default;
 ELSE
  curr=in_curr;
 END IF;
 IF curr <> curr_default THEN
  RAISE EXCEPTION 'curr <> curr_default not yet treated';
 END IF;

 FOR out_count IN array_lower(in_memo, 1) .. array_upper(in_memo, 1)
 LOOP
   netamount=in_netamount[out_count];
   netamount_total=netamount_total+netamount;
   taxrate=in_taxrate[out_count];
   IF taxrate IS NOT NULL THEN
    taxamount=netamount*taxrate;
   ELSE
    taxamount=0.0;
   END IF;
   taxamount_total=taxamount_total+taxamount;
 END LOOP;

 amount_total=netamount_total+taxamount_total;

 amount_total=round(amount_total,dp);
 netamount_total=round(netamount_total,dp);

 INSERT INTO ap (entity_credit_account,invnumber,transdate,invoice,approved,taxincluded,curr,duedate,crdate,netamount,amount,person_id,description,ordnumber,notes,intnotes,ponumber) VALUES(in_entity_credit_account,invnumber,transdate,invoice,approved,taxincluded,curr,duedate,crdate,netamount_total,amount_total,person_id,in_description,in_ordnumber,in_notes,in_intnotes,in_ponumber);

 SELECT currval('id') INTO ap_id;--NOT "id"!

 INSERT INTO acc_trans(trans_id,transdate,chart_id,amount,approved) values(ap_id,transdate,in_ap_liablility_chartid,amount_total,approved);

 FOR out_count IN array_lower(in_memo, 1) .. array_upper(in_memo, 1)
 LOOP
  memo=in_memo[out_count];
  chartid=in_chartid[out_count];
  tax_chartid=in_taxchartid[out_count];
  netamount=in_netamount[out_count];
  taxrate=in_taxrate[out_count];
  taxamount=0.0;
  IF taxrate IS NOT NULL THEN
   IF tax_chartid IS NOT NULL THEN
     select count(*) into ect_count from eca_tax ect where ect.eca_id=in_entity_credit_account and ect.chart_id=tax_chartid;
     IF ect_count = 0 THEN
      RAISE EXCEPTION 'tax_chartid NOT IN  eca_tax';
     END IF;
     taxamount=netamount*taxrate;
     taxamount=round(taxamount,dp);
     INSERT INTO acc_trans (trans_id,chart_id,amount,transdate,fx_transaction,memo) VALUES(ap_id,tax_chartid,taxamount*-1.0,transdate,fx_transaction,memo);
   ELSE --tax_chartid null
    RAISE EXCEPTION 'taxrate NOT NULL but tax_chartid NULL';
   END IF;--tax_chartid
  ELSE --taxrate null
   IF tax_chartid IS NOT NULL THEN
    RAISE EXCEPTION 'taxrate NULL but tax_chartid NOT NULL';
   END IF;
   --taxamount=0.0;
  END IF;--taxrate

  netamount=round(netamount,dp);
  INSERT INTO acc_trans (trans_id,chart_id,amount,transdate,memo,fx_transaction,cleared) VALUES(ap_id,chartid,netamount*-1.0,transdate,memo,fx_transaction,cleared);
  SELECT currval('acc_trans_entry_id_seq') INTO entry_id;

  IF taxform_id <> 0 THEN
   select count(*) into atf_count from ac_tax_form atf where atf.entry_id=entry_id;
   IF atf_count > 0 THEN
    update ac_tax_form atf set atf.reportable=reportable where atf.entry_id=entry_id;
   ELSE
    insert into ac_tax_form(entry_id,reportable) values(entry_id,reportable);
   END IF;
  END IF;--taxform_id

 END LOOP;

 PERFORM trans_id FROM acc_trans WHERE trans_id = ap_id GROUP BY trans_id HAVING sum(amount) <> 0;
 IF FOUND THEN
   RAISE EXCEPTION 'Out of balance';
 END IF;

 return ap_id;
END;
$$ LANGUAGE PLPGSQL;
--To Test:
--select * from AP_simple_post(4,66,null,null,null,'DL','descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,95],ARRAY[0.06,0.21],ARRAY[74,70]);
--select * from AP_simple_post(4,66,null,null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,95],ARRAY[0.06,0.21],ARRAY[74,70]);
--select * from AP_simple_post(4,66,'',null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,95],ARRAY[0.06,0.21],ARRAY[74,70]);
--select * from AP_simple_post(4,66,'test chartid not in ecatax',null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,71],ARRAY[0.06,0.21],ARRAY[74,74]);
--select * from AP_simple_post(4,66,'test chartid in ecatax ',null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,71],ARRAY[0.06,0.06],ARRAY[70,70]);
--select * from AP_simple_post(4,66,null,null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,95],ARRAY[null,0.21],ARRAY[74,70]);
--select * from AP_simple_post(4,66,null,null,null,null,'descr','ordnr','notes','intnotes','ponr',ARRAY['a','b'],ARRAY[100.556,205.308],ARRAY[71,95],ARRAY[0.06,0.21],ARRAY[null,70]);
--tshvr4 first attempt to mimic AA.pm,sub post_transaction in PLPGSQL function end

update defaults set value = 'yes' where setting_key = 'module_load_ok';

COMMIT;