Parameters
bdTotalAmountInvoice | input-output | decimal | |
biRowId | input-output | integer | |
oiReturnStatus | output | integer | Return status of the method. |
Internal usage
QadFinancials
program code (program3/bcinvoiceapmatching.p)
/* =================================================================================================== */
/* Method : ApiEDICInvoiceAPMatchingImportNoLC */
/* =================================================================================================== */
/* When allocting the InvoicedQty to the PVOD_DET's we apply the following rules: */
/* a) In case there is just one open tqPendingVoucherByRcvr found using the filter-criteria: */
/* we will allocate all if it is allowed or when line is asked to set to finished */
/* b) In case there are multiple open tqPendingVoucherByRcvr found using the filter-criteria: */
/* system will divide the invoiced qty among these tqPendingVoucherByRcvr until all is allocated, */
/* using follwoing 2 rules: */
/* - when it is not the last pvod_det : it will max allocate the outstanding balance */
/* - when it is the last pvod_det: it will always allocate all remaining if it is allowed or */
/* if the line is asked to set to finished */
/* =================================================================================================== */
/* Note: */
/* - In all the cases: the IsPvodFinished is set to true when explictly asked for by the caller or */
/* when the allocated quantity is exactly the outstanding balance of the pvod_det */
/* - You can overallocate: the line will get a negative balance and will be kept open (not-finished) */
/* - you can specify a negative quantity: this will create a credit note and will use any pvod_det */
/* that is overallocated */
/* =================================================================================================== */
/* Database: */
/* - only PVOD_DETs are used where pvod_det.pvod_last_voucher = '' and pvo_mstr.pvo_last_voucher = '' */
/* - the remaining balance for a PVOD_DET is calculated by pvod_trans_qty - pvod_vouchered_qty */
/* =================================================================================================== */
assign oiReturnStatus = -98
viLocalReturn = 0.
MAIN_BLOCK:
do on error undo, leave:
/* ==================================================================================== *
* Matching of Non-logistical charges *
* ==================================================================================== */
for each tEDIAPMatching where
tEDIAPMatching.tc_ParentRowid = tEDICInvoice.tc_Rowid:
if tEDIAPMatching.tcPurchaseOrderNumber = '':U then assign tEDIAPMatching.tcPurchaseOrderNumber = ?.
if tEDIAPMatching.tcReceiverNumber = '':U then assign tEDIAPMatching.tcReceiverNumber = ?.
if tEDIAPMatching.tiPurchaseOrderLineNumber = 0 then assign tEDIAPMatching.tiPurchaseOrderLineNumber = ?.
/* ================================================================================================= */
/* We allow to pass the Usage Date as a second field in tcReceiverNumber */
/* delimter = '|' and format = YYYYMMDD */
/* example: <tcReceiverNumber>RB00000001|20141130</ReceiverNumber> */
/* We have to do it this way as we can not make changes in the interface by adding a parameter */
/* for the next release this will be done the proper way */
/* ================================================================================================= */
assign vtUsageDate = ?.
if num-entries (tEDIAPMatching.tcReceiverNumber,"|") = 2
then do :
assign vcUsageDate = entry (2,tEDIAPMatching.tcReceiverNumber,'|')
tEDIAPMatching.tcReceiverNumber = entry (1,tEDIAPMatching.tcReceiverNumber,'|').
/* format should be YYYYMMDD */
if length (vcUsageDate,"CHARACTER") = 8
then assign vtUsageDate = date (int (substring (vcUsageDate,5,2,"CHARACTER")),
int (substring (vcUsageDate,7,2,"CHARACTER")),
int (substring (vcUsageDate,1,4,"CHARACTER")))
no-error.
end. /* if num-entries (tEDIAPMatching.tcReceiverNumber,"|") = 2 */
assign vcReceiver = if tEDIAPMatching.tcReceiverNumber <> ?
then tEDIAPMatching.tcReceiverNumber
else tEDICInvoice.tcReceiverNumber
vcPurchaseOrderNumber = if tEDIAPMatching.tcPurchaseOrderNumber <> ?
then tEDIAPMatching.tcPurchaseOrderNumber
else tEDICInvoice.tcPurchaseOrderNumber.
/* Is all data defined */
if tEDICInvoice.tcDomainCode = ? or
vcPurchaseOrderNumber = ? or
vcReceiver = ? or
tEDIAPMatching.tiPurchaseOrderLineNumber = ?
then do:
assign vcMessage = #T-7'There are missing parameters for retrieving of pending vouchers to be matched.':255(71009)T-7#
vcContext = "tEDICInvoice.tcDomainCode=&1|tEDICInvoice.tcPurchaseOrderNumber=&2|tEDIAPMatching.tcPurchaseOrderNumber=&3":U
+ "tEDICInvoice.tcReceiverNumber=&4|tEDIAPMatching.tcReceiverNumber=&5|tEDIAPMatching.tiPurchaseOrderLineNumber= &6":U
vcContext = substitute(vcContext, tEDICInvoice.tcDomainCode,tEDICInvoice.tcPurchaseOrderNumber,tEDIAPMatching.tcPurchaseOrderNumber,tEDICInvoice.tcReceiverNumber,tEDIAPMatching.tcReceiverNumber,tEDIAPMatching.tiPurchaseOrderLineNumber)
vcMessage = substitute("&1 (&2)":U, vcMessage, vcContext)
vcContext = replace(vcContext, "|":U, chr(2)).
<M-8 run SetMessage
(input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input tEDICInvoice.tc_Rowid (icRowid),
input 'QadFin-8552':U (icFcMsgNumber),
input '':U (icFcExplanation),
input '':U (icFcIdentification),
input vcContext (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BCInvoiceAPMatching>
delete tCInvoiceRef.
assign viLocalReturn = -1.
leave MAIN_BLOCK.
end.
/* Get pending vouchers ready for matchng */
<Q-77 run PendingVoucherByRcvr (all) (Read) (NoCache)
(input vcReceiver, (Receiver)
input tEDICInvoice.tcDomainCode, (Domain)
input ?, (ReceiptType)
output dataset tqPendingVoucherByRcvr) in BMfgPendingVoucher>
assign vdQtyToMatch = tEDIAPMatching.tdMatchQty.
/* ===================================================================================================== */
/* Let's count how many pvo's we got so we can test when we are dealing with the last one */
/* - If the qty to match > 0 (invoice) and there is at least one receipt, we only consider receipts. If */
/* there is no receipt, we also consider returns */
/* - If the qty to match < 0 (credit note) and there is at least one return, we only consider returns. If*/
/* there is no return, we also consider receipts */
/* ===================================================================================================== */
assign viTotalNumberOfPvodDetAll = 0
viTotalNumberOfPvodDetSignOK = 0.
for each tqPendingVoucherByRcvr where
tqPendingVoucherByRcvr.tcpvo_domain = tEDICInvoice.tcDomainCode and
tqPendingVoucherByRcvr.tcpvo_order = vcPurchaseOrderNumber and
tqPendingVoucherByRcvr.tcpvo_internal_ref = vcReceiver and
tqPendingVoucherByRcvr.tcpvo_last_voucher = "":U and
tqPendingVoucherByRcvr.tcpvod_last_voucher = "":U and
tqPendingVoucherByRcvr.tipvo_line = tEDIAPMatching.tiPurchaseOrderLineNumber:
/* If usage date is specified, it has to be an exact match */
if vtUsageDate <> ? and vtUsageDate <> tqPendingVoucherByRcvr.ttpvod_eff_date
then next.
/* Balance must be + for invoices, and must be - for credit notes */
if (tEDIAPMatching.tdMatchQty > 0 and tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty > 0) or
(tEDIAPMatching.tdMatchQty < 0 and tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty < 0)
then assign viTotalNumberOfPvodDetSignOK = viTotalNumberOfPvodDetSignOK + 1.
/* Increase pvod_det counter */
assign viTotalNumberOfPvodDetAll = viTotalNumberOfPvodDetAll + 1.
end. /* for each tqPendingVoucherByRcvr */
/* ===================================================================================================== */
/* Get pending vouchers and allocate the invoiced quantity */
/* ===================================================================================================== */
assign vdQtyToMatch = tEDIAPMatching.tdMatchQty
viCounterPvodDet = 0
viTotalNumberOfPvodDet = (if viTotalNumberOfPvodDetSignOK >= 1
then viTotalNumberOfPvodDetSignOK
else viTotalNumberOfPvodDetAll).
for each tqPendingVoucherByRcvr where
tqPendingVoucherByRcvr.tcpvo_domain = tEDICInvoice.tcDomainCode and
tqPendingVoucherByRcvr.tcpvo_order = vcPurchaseOrderNumber and
tqPendingVoucherByRcvr.tcpvo_internal_ref = vcReceiver and
tqPendingVoucherByRcvr.tcpvo_last_voucher = "":U and
tqPendingVoucherByRcvr.tcpvod_last_voucher = "":U and
tqPendingVoucherByRcvr.tipvo_line = tEDIAPMatching.tiPurchaseOrderLineNumber:
/* ======================================================================================= */
/* If usage date is specified, it has to be an exact match */
/* ======================================================================================= */
if vtUsageDate <> ? and vtUsageDate <> tqPendingVoucherByRcvr.ttpvod_eff_date
then next.
/* ======================================================================================= */
/* Balance must be + for invoices, and must be - for credit notes */
/* ======================================================================================= */
if viTotalNumberOfPvodDetSignOK >= 1 and
((tEDIAPMatching.tdMatchQty > 0 and tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty <= 0) or
(tEDIAPMatching.tdMatchQty < 0 and tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty >= 0))
then next.
/* ======================================================================================= */
/* keep track how many VPO's were treated so we can test when we are treating the last one */
/* ======================================================================================= */
assign viCounterPvodDet = viCounterPvodDet + 1.
create tAPMatchingLnRef.
assign tAPMatchingLnRef.tcDomainCode = tqPendingVoucherByRcvr.tcpvo_domain
tAPMatchingLnRef.tiPvoId = tqPendingVoucherByRcvr.tipvo_id
tAPMatchingLnRef.tiPvodLineId = tqPendingVoucherByRcvr.tipvod_id_line
tAPMatchingLnRef.tlIsRecalculateTaxes = true
tAPMatchingLnRef.tdMatchUnitPrice = tEDIAPMatching.tdMatchUnitPrice
tAPMatchingLnRef.tdMatchQty = if viCounterPvodDet = viTotalNumberOfPvodDet and
(tEDIAPMatching.tlIsPvodFinished <> false or
(tEDIAPMatching.tlIsPvodFinished = false and vlAllowOverAllocationPVO = True))
then vdQtyToMatch
else if vdQtyToMatch >= 0
then min(vdQtyToMatch, tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty)
else max(vdQtyToMatch, tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty)
tAPMatchingLnRef.tlIsPvodFinished = (tEDIAPMatching.tlIsPvodFinished <> false or
tAPMatchingLnRef.tdMatchQty = tqPendingVoucherByRcvr.tdpvod_trans_qty - tqPendingVoucherByRcvr.tdpvod_vouchered_qty)
vdQtyToMatch = vdQtyToMatch - tAPMatchingLnRef.tdMatchQty
tAPMatchingLnRef.tc_ParentRowid = tCInvoiceRef.tc_Rowid
tAPMatchingLnRef.tc_Rowid = string(biRowid)
biRowid = biRowid - 1.
/* ====================================================================== */
/* Calculate the totals for this invoice */
/* This is needed to see if the invoice has a negative or positive amount */
/* The Invoice Type will be defaulted based on this. */
/* ====================================================================== */
assign bdTotalAmountInvoice = bdTotalAmountInvoice + (tAPMatchingLnRef.tdMatchQty * tAPMatchingLnRef.tdMatchUnitPrice).
/* ================================= */
/* if all is allocated, we can leave */
/* ================================= */
if vdQtyToMatch = 0
then leave.
end. /* for each tqPendingVoucherByRcvr where */
/* ===================================================== */
/* If not all quantity was allocated, we raise an error */
/* ===================================================== */
if vdQtyToMatch <> 0
then do:
assign vcMessage = #T-13'Cannot match requested quantity as there is not enough pending quantity on unmatched receipts.':255(71105)T-13#
vcContext = "Domain=&1|PurchaseOrderNumber=&2|ReceiverNumber=&3|PurchaseOrderLineNumber=&4|tdMatchQty=&5|viTotalNumberOfPvodDet=&6|vdQtyToMatch=&7|vtUsageDate=&8":U
vcContext = substitute(vcContext, tEDICInvoice.tcDomainCode, vcPurchaseOrderNumber, vcReceiver, tEDIAPMatching.tiPurchaseOrderLineNumber, tEDIAPMatching.tdMatchQty,viTotalNumberOfPvodDet,vdQtyToMatch,vtUsageDate)
vcMessage = substitute("&1 (&2)":U, vcMessage, vcContext)
vcContext = replace(vcContext, "|":U, chr(2)).
<M-12 run SetMessage
(input vcMessage (icMessage),
input '':U (icArguments),
input '':U (icFieldName),
input '':U (icFieldValue),
input 'E':U (icType),
input 3 (iiSeverity),
input tEDICInvoice.tc_Rowid (icRowid),
input 'QadFin-8554':U (icFcMsgNumber),
input '':U (icFcExplanation),
input '':U (icFcIdentification),
input vcContext (icFcContext),
output viFcReturnSuper (oiReturnStatus)) in BCInvoiceAPMatching>
delete tCInvoiceRef.
assign viLocalReturn = -1.
leave MAIN_BLOCK.
end. /* if vdQtyToMatch <> 0 */
end. /* for each tEDIAPMatching where */
end. /* MAIN_BLOCK */
/* =================================================================================================== */
/* Return */
/* =================================================================================================== */
assign oiReturnStatus = viLocalReturn.