Issue #23571:fix value posted to inventory
[xtuple] / foundation-database / public / functions / postcreditmemo.sql
1
2 CREATE OR REPLACE FUNCTION postCreditMemo(INTEGER, INTEGER) RETURNS INTEGER AS $$
3 -- Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple. 
4 -- See www.xtuple.com/CPAL for the full text of the software license.
5 DECLARE
6   pCmheadid ALIAS FOR $1;
7   pItemlocSeries ALIAS FOR $2;
8   _return INTEGER;
9
10 BEGIN
11
12   SELECT postCreditMemo(pCmheadid, fetchJournalNumber('AR-CM'), pItemlocSeries) INTO _return;
13
14   RETURN _return;
15
16 END;
17 $$ LANGUAGE 'plpgsql';
18
19
20 CREATE OR REPLACE FUNCTION postCreditMemo(INTEGER, INTEGER, INTEGER) RETURNS INTEGER AS $$
21 -- Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple. 
22 -- See www.xtuple.com/CPAL for the full text of the software license.
23 DECLARE
24   pCmheadid ALIAS FOR $1;
25   pJournalNumber ALIAS FOR $2;
26   pItemlocSeries ALIAS FOR $3;
27   _r RECORD;
28   _p RECORD;
29   _aropenid INTEGER;
30   _cohistid INTEGER;
31   _sequence INTEGER;
32   _itemlocSeries INTEGER;
33   _invhistid INTEGER;
34   _test INTEGER;
35   _totalAmount NUMERIC   := 0;
36   _commissionDue NUMERIC := 0;
37   _toApply NUMERIC;
38   _toClose BOOLEAN;
39   _glDate       DATE;
40   _taxBaseValue NUMERIC := 0;
41
42 BEGIN
43
44 --  Cache some parameters
45   SELECT cmhead.*,
46          findARAccount(cmhead_cust_id) AS ar_accnt_id,
47          ( SELECT COALESCE(SUM(taxhist_tax), 0)
48            FROM cmheadtax
49            WHERE ( (taxhist_parent_id = cmhead_id)
50              AND   (taxhist_taxtype_id = getAdjustmentTaxtypeId()) ) ) AS adjtax
51          INTO _p
52   FROM cmhead
53   WHERE (cmhead_id=pCmheadid);
54
55   IF (_p.cmhead_posted) THEN
56     RETURN -10;
57   END IF;
58
59   IF (_p.cmhead_hold) THEN
60     RETURN -11;
61   END IF;
62
63   _glDate := COALESCE(_p.cmhead_gldistdate, _p.cmhead_docdate);
64
65   _itemlocSeries = pItemlocSeries;
66
67   SELECT fetchGLSequence() INTO _sequence;
68
69 --  Start by handling taxes
70   FOR _r IN SELECT tax_sales_accnt_id, 
71               round(sum(taxdetail_tax),2) AS tax,
72               currToBase(_p.cmhead_curr_id, round(sum(taxdetail_tax),2), _p.cmhead_docdate) AS taxbasevalue
73             FROM tax 
74              JOIN calculateTaxDetailSummary('CM', pCmheadid, 'T') ON (taxdetail_tax_id=tax_id)
75             GROUP BY tax_id, tax_sales_accnt_id LOOP
76
77     PERFORM insertIntoGLSeries( _sequence, 'A/R', 'CM', _p.cmhead_number,
78                                 _r.tax_sales_accnt_id, 
79                                 _r.taxbasevalue,
80                                 _glDate, _p.cmhead_billtoname );
81
82     _totalAmount := _totalAmount + _r.tax * -1;
83   END LOOP;
84
85 -- Update item tax records with posting data
86   UPDATE cmitemtax SET 
87     taxhist_docdate=_p.cmhead_docdate,
88     taxhist_distdate=_glDate,
89     taxhist_curr_id=_p.cmhead_curr_id,
90     taxhist_curr_rate=curr_rate,
91     taxhist_journalnumber=pJournalNumber
92   FROM cmhead
93    JOIN cmitem ON (cmhead_id=cmitem_cmhead_id),
94    curr_rate
95   WHERE ((cmhead_id=pCmheadId)
96     AND (taxhist_parent_id=cmitem_id)
97     AND (_p.cmhead_curr_id=curr_id)
98     AND (_p.cmhead_docdate BETWEEN curr_effective 
99                            AND curr_expires) );
100
101 -- Update Header taxes (Freight and Adjustments) with posting data
102   UPDATE cmheadtax SET 
103     taxhist_docdate=_p.cmhead_docdate,
104     taxhist_distdate=_glDate,
105     taxhist_curr_id=_p.cmhead_curr_id,
106     taxhist_curr_rate=curr_rate,
107     taxhist_journalnumber=pJournalNumber
108   FROM curr_rate
109   WHERE ((taxhist_parent_id=pCmheadId)
110     AND (_p.cmhead_curr_id=curr_id)
111     AND (_p.cmhead_docdate BETWEEN curr_effective 
112                            AND curr_expires) );
113
114 -- Process line items
115 -- Always use std cost
116   FOR _r IN SELECT *, stdCost(item_id) AS std_cost
117             FROM creditmemoitem
118             WHERE ( (cmitem_cmhead_id=pCmheadid)
119               AND   (cmitem_qtycredit <> 0 ) ) LOOP
120
121 --  Calcuate the Commission to be debited
122     _commissionDue := (_commissionDue + (_r.extprice * _p.cmhead_commission));
123
124     IF (_r.extprice <> 0) THEN
125 --  Debit the Sales Account for the current cmitem
126       SELECT insertIntoGLSeries( _sequence, 'A/R', 'CM', _p.cmhead_number,
127                                  CASE WHEN _p.cmhead_rahead_id IS NULL THEN
128                                    getPrjAccntId(_p.cmhead_prj_id, salesaccnt_credit_accnt_id)
129                                  ELSE
130                                    getPrjAccntId(_p.cmhead_prj_id, salesaccnt_returns_accnt_id)
131                                  END,
132                                round(currToBase(_p.cmhead_curr_id,
133                                                 _r.extprice * -1,
134                                                 _p.cmhead_docdate), 2),
135                                  _glDate, _p.cmhead_billtoname) INTO _test
136       FROM salesaccnt
137       WHERE (salesaccnt_id=findSalesAccnt(_r.cmitem_itemsite_id, 'IS', _p.cmhead_cust_id,
138                                           _p.cmhead_saletype_id, _p.cmhead_shipzone_id));
139       IF (NOT FOUND) THEN
140         PERFORM deleteGLSeries(_sequence);
141         RETURN -12;
142       END IF;
143     END IF;
144
145 --  Record Sales History for this C/M Item
146     SELECT nextval('cohist_cohist_id_seq') INTO _cohistid;
147     INSERT INTO cohist
148     ( cohist_id, cohist_cust_id, cohist_itemsite_id, cohist_shipto_id,
149       cohist_shipdate, cohist_shipvia,
150       cohist_ordernumber, cohist_ponumber, cohist_orderdate,
151       cohist_doctype, cohist_invcnumber, cohist_invcdate,
152       cohist_qtyshipped, cohist_unitprice, cohist_unitcost,
153       cohist_salesrep_id, cohist_commission, cohist_commissionpaid,
154       cohist_billtoname, cohist_billtoaddress1,
155       cohist_billtoaddress2, cohist_billtoaddress3,
156       cohist_billtocity, cohist_billtostate, cohist_billtozip,
157       cohist_shiptoname, cohist_shiptoaddress1,
158       cohist_shiptoaddress2, cohist_shiptoaddress3,
159       cohist_shiptocity, cohist_shiptostate, cohist_shiptozip,
160       cohist_curr_id, cohist_taxtype_id, cohist_taxzone_id,
161       cohist_shipzone_id, cohist_saletype_id )
162     VALUES
163     ( _cohistid, _p.cmhead_cust_id, _r.cmitem_itemsite_id, _p.cmhead_shipto_id,
164       _p.cmhead_docdate, '',
165       _p.cmhead_number, _p.cmhead_custponumber, _p.cmhead_docdate,
166       'C', _p.cmhead_invcnumber, _p.cmhead_docdate,
167       (_r.qty * -1), _r.unitprice, _r.std_cost,
168       _p.cmhead_salesrep_id, (_p.cmhead_commission * _r.extprice * -1), FALSE,
169       _p.cmhead_billtoname, _p.cmhead_billtoaddress1,
170       _p.cmhead_billtoaddress2, _p.cmhead_billtoaddress3,
171       _p.cmhead_billtocity, _p.cmhead_billtostate, _p.cmhead_billtozip,
172       _p.cmhead_shipto_name, _p.cmhead_shipto_address1,
173       _p.cmhead_shipto_address2, _p.cmhead_shipto_address3,
174       _p.cmhead_shipto_city, _p.cmhead_shipto_state, _p.cmhead_shipto_zipcode,
175       _p.cmhead_curr_id, _r.cmitem_taxtype_id, _p.cmhead_taxzone_id,
176       _p.cmhead_shipzone_id, _p.cmhead_saletype_id );
177     INSERT INTO cohisttax
178     ( taxhist_parent_id, taxhist_taxtype_id, taxhist_tax_id,
179       taxhist_basis, taxhist_basis_tax_id, taxhist_sequence,
180       taxhist_percent, taxhist_amount, taxhist_tax,
181       taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
182       taxhist_journalnumber )
183     SELECT _cohistid, taxhist_taxtype_id, taxhist_tax_id,
184            taxhist_basis, taxhist_basis_tax_id, taxhist_sequence,
185            taxhist_percent, taxhist_amount, taxhist_tax,
186            taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
187            taxhist_journalnumber 
188     FROM cmitemtax
189     WHERE (taxhist_parent_id=_r.cmitem_id);
190
191     _totalAmount := _totalAmount + round(_r.extprice, 2);
192
193   END LOOP;
194
195 --  Credit the Misc. Account for Miscellaneous Charges
196   IF (_p.cmhead_misc <> 0) THEN
197     SELECT insertIntoGLSeries( _sequence, 'A/R', 'CM', _p.cmhead_number,
198                                getPrjAccntId(_p.cmhead_prj_id, accnt_id), round(currToBase(_p.cmhead_curr_id,
199                                                           _p.cmhead_misc * -1,
200                                                           _p.cmhead_docdate), 2),
201                                _glDate, _p.cmhead_billtoname) INTO _test
202     FROM accnt
203     WHERE (accnt_id=_p.cmhead_misc_accnt_id);
204
205 --  If the Misc. Charges Account was not found then punt
206     IF (NOT FOUND) THEN
207       PERFORM deleteGLSeries(_sequence);
208       RETURN -14;
209     END IF;
210
211 --  Record the Sales History for any Misc. Charge
212     INSERT INTO cohist
213     ( cohist_cust_id, cohist_itemsite_id, cohist_shipto_id,
214       cohist_misc_type, cohist_misc_descrip, cohist_misc_id,
215       cohist_shipdate, cohist_shipvia,
216       cohist_ordernumber, cohist_ponumber, cohist_orderdate,
217       cohist_doctype, cohist_invcnumber, cohist_invcdate,
218       cohist_qtyshipped, cohist_unitprice, cohist_unitcost,
219       cohist_salesrep_id, cohist_commission, cohist_commissionpaid,
220       cohist_billtoname, cohist_billtoaddress1,
221       cohist_billtoaddress2, cohist_billtoaddress3,
222       cohist_billtocity, cohist_billtostate, cohist_billtozip,
223       cohist_shiptoname, cohist_shiptoaddress1,
224       cohist_shiptoaddress2, cohist_shiptoaddress3,
225       cohist_shiptocity, cohist_shiptostate, cohist_shiptozip,
226       cohist_curr_id,
227       cohist_shipzone_id, cohist_saletype_id )
228     VALUES
229     ( _p.cmhead_cust_id, -1, _p.cmhead_shipto_id,
230       'M', _p.cmhead_misc_descrip, _p.cmhead_misc_accnt_id,
231       _p.cmhead_docdate, '',
232       _p.cmhead_number, _p.cmhead_custponumber, _p.cmhead_docdate,
233       'C', _p.cmhead_invcnumber, _p.cmhead_docdate,
234       1, (_p.cmhead_misc * -1), (_p.cmhead_misc * -1),
235       _p.cmhead_salesrep_id, 0, FALSE,
236       _p.cmhead_billtoname, _p.cmhead_billtoaddress1,
237       _p.cmhead_billtoaddress2, _p.cmhead_billtoaddress3,
238       _p.cmhead_billtocity, _p.cmhead_billtostate, _p.cmhead_billtozip,
239       _p.cmhead_shipto_name, _p.cmhead_shipto_address1,
240       _p.cmhead_shipto_address2, _p.cmhead_shipto_address3,
241       _p.cmhead_shipto_city, _p.cmhead_shipto_state, _p.cmhead_shipto_zipcode,
242       _p.cmhead_curr_id,
243       _p.cmhead_shipzone_id, _p.cmhead_saletype_id );
244
245 --  Cache the Misc. Amount distributed
246     _totalAmount := _totalAmount + _p.cmhead_misc;
247   END IF;
248
249   -- Credit Tax Adjustments
250   IF (_p.adjtax <> 0) THEN
251   --  Record the Sales History for Tax Adjustment
252     SELECT nextval('cohist_cohist_id_seq') INTO _cohistid;
253     INSERT INTO cohist
254     ( cohist_id, cohist_cust_id, cohist_itemsite_id, cohist_shipto_id,
255       cohist_misc_type, cohist_misc_descrip,
256       cohist_shipdate, cohist_shipvia,
257       cohist_ordernumber, cohist_ponumber, cohist_orderdate,
258       cohist_doctype, cohist_invcnumber, cohist_invcdate,
259       cohist_qtyshipped, cohist_unitprice, cohist_unitcost,
260       cohist_salesrep_id, cohist_commission, cohist_commissionpaid,
261       cohist_billtoname, cohist_billtoaddress1,
262       cohist_billtoaddress2, cohist_billtoaddress3,
263       cohist_billtocity, cohist_billtostate, cohist_billtozip,
264       cohist_shiptoname, cohist_shiptoaddress1,
265       cohist_shiptoaddress2, cohist_shiptoaddress3,
266       cohist_shiptocity, cohist_shiptostate, cohist_shiptozip,
267       cohist_curr_id, cohist_taxtype_id, cohist_taxzone_id,
268       cohist_shipzone_id, cohist_saletype_id )
269     VALUES
270     ( _cohistid, _p.cmhead_cust_id, -1, _p.cmhead_shipto_id,
271       'T', 'Misc Tax Adjustment',
272       _p.cmhead_docdate, '',
273       _p.cmhead_number, _p.cmhead_custponumber, _p.cmhead_docdate,
274       'C', _p.cmhead_invcnumber, _p.cmhead_docdate,
275       0, 0, 0,
276       _p.cmhead_salesrep_id, 0, FALSE,
277       _p.cmhead_billtoname, _p.cmhead_billtoaddress1,
278       _p.cmhead_billtoaddress2, _p.cmhead_billtoaddress3,
279       _p.cmhead_billtocity, _p.cmhead_billtostate, _p.cmhead_billtozip,
280       _p.cmhead_shipto_name, _p.cmhead_shipto_address1,
281       _p.cmhead_shipto_address2, _p.cmhead_shipto_address3,
282       _p.cmhead_shipto_city, _p.cmhead_shipto_state, _p.cmhead_shipto_zipcode,
283       _p.cmhead_curr_id, getAdjustmentTaxtypeId(), _p.cmhead_taxzone_id,
284       _p.cmhead_shipzone_id, _p.cmhead_saletype_id );
285     INSERT INTO cohisttax
286     ( taxhist_parent_id, taxhist_taxtype_id, taxhist_tax_id,
287       taxhist_basis, taxhist_basis_tax_id, taxhist_sequence,
288       taxhist_percent, taxhist_amount, taxhist_tax,
289       taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
290       taxhist_journalnumber  )
291     SELECT _cohistid, taxhist_taxtype_id, taxhist_tax_id,
292            (taxhist_basis * -1), taxhist_basis_tax_id, taxhist_sequence,
293            taxhist_percent, taxhist_amount, taxhist_tax,
294            taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
295            taxhist_journalnumber 
296     FROM cmheadtax
297     WHERE ( (taxhist_parent_id=_p.cmhead_id)
298       AND   (taxhist_taxtype_id=getAdjustmentTaxtypeId()) );
299
300   END IF;
301
302 --  Debit the Freight Account
303   IF (_p.cmhead_freight <> 0) THEN
304     SELECT insertIntoGLSeries( _sequence, 'A/R', 'CM', _p.cmhead_number,
305                                getPrjAccntId(_p.cmhead_prj_id, accnt_id),
306                                round(currToBase(_p.cmhead_curr_id,
307                                                 _p.cmhead_freight * -1,
308                                                 _p.cmhead_docdate), 2),
309                                _glDate, _p.cmhead_billtoname) INTO _test
310     FROM accnt
311     WHERE (accnt_id=findFreightAccount(_p.cmhead_cust_id));
312
313 --  If the Freight Charges Account was not found then punt
314     IF (NOT FOUND) THEN
315       PERFORM deleteGLSeries(_sequence);
316       RETURN -16;
317     END IF;
318
319 --  Cache the Amount Distributed to Freight
320     _totalAmount := _totalAmount + _p.cmhead_freight;
321
322 --  Record the Sales History for any Freight
323     SELECT nextval('cohist_cohist_id_seq') INTO _cohistid;
324     INSERT INTO cohist
325     ( cohist_id, cohist_cust_id, cohist_itemsite_id, cohist_shipto_id,
326       cohist_misc_type, cohist_misc_descrip,
327       cohist_shipdate, cohist_shipvia,
328       cohist_ordernumber, cohist_ponumber, cohist_orderdate,
329       cohist_doctype, cohist_invcnumber, cohist_invcdate,
330       cohist_qtyshipped, cohist_unitprice, cohist_unitcost,
331       cohist_salesrep_id, cohist_commission, cohist_commissionpaid,
332       cohist_billtoname, cohist_billtoaddress1,
333       cohist_billtoaddress2, cohist_billtoaddress3,
334       cohist_billtocity, cohist_billtostate, cohist_billtozip,
335       cohist_shiptoname, cohist_shiptoaddress1,
336       cohist_shiptoaddress2, cohist_shiptoaddress3,
337       cohist_shiptocity, cohist_shiptostate, cohist_shiptozip,
338       cohist_curr_id, cohist_taxtype_id, cohist_taxzone_id,
339       cohist_shipzone_id, cohist_saletype_id )
340     VALUES
341     ( _cohistid, _p.cmhead_cust_id, -1, _p.cmhead_shipto_id,
342       'F', 'Freight Charge',
343       _p.cmhead_docdate, '',
344       _p.cmhead_number, _p.cmhead_custponumber, _p.cmhead_docdate,
345       'C', _p.cmhead_invcnumber, _p.cmhead_docdate,
346       1, (_p.cmhead_freight * -1), (_p.cmhead_freight * -1),
347       _p.cmhead_salesrep_id, 0, FALSE,
348       _p.cmhead_billtoname, _p.cmhead_billtoaddress1,
349       _p.cmhead_billtoaddress2, _p.cmhead_billtoaddress3,
350       _p.cmhead_billtocity, _p.cmhead_billtostate, _p.cmhead_billtozip,
351       _p.cmhead_shipto_name, _p.cmhead_shipto_address1,
352       _p.cmhead_shipto_address2, _p.cmhead_shipto_address3,
353       _p.cmhead_shipto_city, _p.cmhead_shipto_state, _p.cmhead_shipto_zipcode,
354       _p.cmhead_curr_id, getFreightTaxtypeId(), _p.cmhead_taxzone_id,
355       _p.cmhead_shipzone_id, _p.cmhead_saletype_id );
356     INSERT INTO cohisttax
357     ( taxhist_parent_id, taxhist_taxtype_id, taxhist_tax_id,
358       taxhist_basis, taxhist_basis_tax_id, taxhist_sequence,
359       taxhist_percent, taxhist_amount, taxhist_tax,
360       taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
361       taxhist_journalnumber  )
362     SELECT _cohistid, taxhist_taxtype_id, taxhist_tax_id,
363            (taxhist_basis * -1), taxhist_basis_tax_id, taxhist_sequence,
364            taxhist_percent, taxhist_amount, taxhist_tax,
365            taxhist_docdate, taxhist_distdate, taxhist_curr_id, taxhist_curr_rate,
366            taxhist_journalnumber 
367     FROM cmheadtax
368     WHERE ( (taxhist_parent_id=_p.cmhead_id)
369       AND   (taxhist_taxtype_id=getFreightTaxtypeId()) );
370
371   END IF;
372
373   _totalAmount := _totalAmount;
374
375 --  Credit the A/R for the total Amount
376   IF (_totalAmount <> 0) THEN
377     IF (_p.ar_accnt_id != -1) THEN
378       PERFORM insertIntoGLSeries( _sequence, 'A/R', 'CM', _p.cmhead_number,
379                                   _p.ar_accnt_id,
380                                   round(currToBase(_p.cmhead_curr_id,
381                                                    _totalAmount,
382                                                    _p.cmhead_docdate), 2),
383                                   _glDate, _p.cmhead_billtoname);
384     ELSE
385       PERFORM deleteGLSeries(_sequence);
386       RETURN -18;
387     END IF;
388   END IF;
389
390 --  Commit the GLSeries;
391   PERFORM postGLSeries(_sequence, pJournalNumber);
392
393 --  Create the Invoice aropen item
394   SELECT NEXTVAL('aropen_aropen_id_seq') INTO _aropenid;
395   INSERT INTO aropen
396   ( aropen_id, aropen_username, aropen_journalnumber,
397     aropen_open, aropen_posted,
398     aropen_cust_id, aropen_ponumber,
399     aropen_docnumber,
400     aropen_applyto, aropen_doctype,
401     aropen_docdate, aropen_duedate, aropen_distdate, aropen_terms_id,
402     aropen_amount, aropen_paid,
403     aropen_salesrep_id, aropen_commission_due, aropen_commission_paid,
404     aropen_ordernumber, aropen_notes,
405     aropen_rsncode_id, aropen_curr_id )
406   SELECT _aropenid, getEffectiveXtUser(), pJournalNumber,
407          TRUE, FALSE,
408          cmhead_cust_id, cmhead_custponumber,
409          cmhead_number,
410          CASE WHEN (cmhead_invcnumber='-1') THEN 'OPEN'
411               ELSE (cmhead_invcnumber::TEXT)
412          END,
413          'C',
414          cmhead_docdate, cmhead_docdate, _glDate, -1,
415          _totalAmount, 0,
416          cmhead_salesrep_id, (_commissionDue * -1), FALSE,
417          cmhead_number::TEXT, cmhead_comments,
418          cmhead_rsncode_id, cmhead_curr_id
419   FROM cmhead
420   WHERE (cmhead_id=pCmheadid);
421
422 -- Handle the Inventory and G/L Transactions for any returned Inventory where cmitem_updateinv is true
423   FOR _r IN SELECT cmitem_itemsite_id AS itemsite_id, cmitem_id,
424                    (cmitem_qtyreturned * cmitem_qty_invuomratio) AS qty,
425                    cmhead_number, cmhead_cust_id AS cust_id, item_number,
426                    cmhead_saletype_id AS saletype_id, cmhead_shipzone_id AS shipzone_id,
427                    stdCost(item_id) AS std_cost, cmhead_prj_id,
428                    itemsite_costmethod
429             FROM cmhead, cmitem, itemsite, item
430             WHERE ( (cmitem_cmhead_id=cmhead_id)
431              AND (cmitem_itemsite_id=itemsite_id)
432              AND (itemsite_item_id=item_id)
433              AND (cmitem_qtyreturned <> 0)
434              AND (cmitem_updateinv)
435              AND (cmhead_id=pCmheadid) ) LOOP
436
437 --  Return credited stock to inventory
438     IF (_itemlocSeries = 0) THEN
439       _itemlocSeries := NEXTVAL('itemloc_series_seq');
440     END IF;
441     IF (_r.itemsite_costmethod != 'J') THEN
442       SELECT postInvTrans(itemsite_id, 'RS', _r.qty,
443                          'S/O', 'CM', _r.cmhead_number, '',
444                          ('Credit Return ' || _r.item_number),
445                          costcat_asset_accnt_id,
446                          getPrjAccntId(_r.cmhead_prj_id, resolveCOSAccount(itemsite_id, _r.cust_id, _r.saletype_id, _r.shipzone_id)), 
447                          _itemlocSeries, _glDate, (_r.std_cost * _r.qty)) INTO _invhistid
448         FROM itemsite, costcat
449        WHERE ((itemsite_costcat_id=costcat_id)
450           AND (itemsite_id=_r.itemsite_id));
451     ELSE
452       RAISE DEBUG 'postCreditMemo(%, %, %) tried to postInvTrans a %-costed item',
453                   pCmheadid, pJournalNumber, pItemlocSeries,
454                   _r.itemsite_costmethod;
455     END IF;
456
457   END LOOP;
458
459 --  Update coitem to reflect the returned qty where cmitem_updateinv is true
460   FOR _r IN SELECT cmitem_qtyreturned, cmitem_itemsite_id, cohead_id
461             FROM cmitem, cmhead, invchead, cohead
462             WHERE ( (cmitem_cmhead_id=cmhead_id)
463              AND (cmhead_invcnumber=invchead_invcnumber)
464              AND (invchead_ordernumber=cohead_number)
465              AND (cmitem_qtyreturned <> 0)
466              AND (cmitem_updateinv)
467              AND (cmhead_id=pCmheadid) ) LOOP
468     UPDATE coitem
469     SET coitem_qtyreturned = (coitem_qtyreturned + _r.cmitem_qtyreturned)
470     WHERE coitem_id IN ( SELECT coitem_id
471                          FROM coitem
472                          WHERE ( (coitem_cohead_id=_r.cohead_id)
473                           AND (coitem_itemsite_id = _r.cmitem_itemsite_id) )
474                          LIMIT 1 );
475   END LOOP;
476
477 --  Mark the cmhead as posted
478   UPDATE cmhead
479   SET cmhead_posted=TRUE, cmhead_gldistdate=_glDate
480   WHERE (cmhead_id=pCmheadid);
481
482 --  Find the apply-to document and make the application
483   SELECT cmhead_number, cmhead_curr_id, cmhead_docdate,
484          aropen_id, aropen_cust_id, aropen_docnumber,
485          currToCurr(aropen_curr_id, cmhead_curr_id, aropen_amount - aropen_paid,
486                     cmhead_docdate) AS balance INTO _p
487   FROM aropen, cmhead
488   WHERE ( (aropen_doctype='I')
489    AND (aropen_docnumber=cmhead_invcnumber)
490    AND (cmhead_id=pCmheadid) );
491   IF (FOUND) THEN
492
493     IF round(_totalAmount, 2) <= round(_p.balance, 2) THEN
494       _toApply = _totalAmount;
495     ELSE
496       _toApply = _p.balance;
497     END IF;
498
499     UPDATE aropen
500     SET aropen_paid = round(aropen_paid + currToCurr(_p.cmhead_curr_id,
501                                                      aropen_curr_id, _toApply,
502                                                      _p.cmhead_docdate), 2)
503     WHERE (aropen_id=_p.aropen_id);
504
505 --  Alter the new A/R Open Item to reflect the application
506     UPDATE aropen
507     SET aropen_paid = round(currToCurr(_p.cmhead_curr_id, aropen_curr_id,
508                                        _toApply, _p.cmhead_docdate), 2)
509     WHERE (aropen_id=_aropenid);
510
511 --  Record the application
512     INSERT INTO arapply
513     ( arapply_cust_id,
514       arapply_source_aropen_id, arapply_source_doctype, arapply_source_docnumber,
515       arapply_target_aropen_id, arapply_target_doctype, arapply_target_docnumber,
516       arapply_fundstype, arapply_refnumber,
517       arapply_applied, arapply_closed,
518       arapply_postdate, arapply_distdate, arapply_journalnumber, arapply_curr_id )
519     VALUES
520     ( _p.aropen_cust_id,
521       _aropenid, 'C', _p.cmhead_number,
522       _p.aropen_id, 'I', _p.aropen_docnumber,
523       '', '',
524       round(_toApply, 2), _toClose,
525       CURRENT_DATE, _p.cmhead_docdate, 0, _p.cmhead_curr_id );
526
527   END IF;
528     
529   RETURN _itemlocSeries;
530
531 END;
532 $$ LANGUAGE 'plpgsql';
533