project QadFinancials > class BCInvoiceAPMatching > method ApiEDICInvoiceAPMatchingImportNoLC


Parameters


bdTotalAmountInvoiceinput-outputdecimal
biRowIdinput-outputinteger
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BCInvoiceAPMatching.ApiEDICInvoiceAPMatchingImport


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.