project QadFinancials > class BDInvoice > method CreateDInvoiceMovements

Description

This method will first load all invoices linked to the movements or stages that got passed to the method.
Create the postingline on the control account and add the movement record.
Also update the balance fields and status fields of the invoices.
This method will also balance the LC and CC amounts of the invoice, when the invoice gets balanced in TC.


Parameters


tDIMovementinput-outputtemp-tableMovement records wherefor a dinvoicemovement record must be created
tDInvoiceStageUpdatesinputtemp-table
biBJournalEntryIdinput-outputintegerInstance of Journal Entry
ilClearDatainputlogicalClearData
itPaymentTaxPointDateinputdate
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BBankEntry.AdditionalUpdatesInvDIMovements
method BCDocument.AdditionalUpdatesPosting
method BDDocument.AdditionalUpdatesPosting
method BDInvoice.CreateDInvoicesDeduction
method BDInvoice.UpdateDeductionDetailPosting
method BOpenItemAdjustment.OIAdjCommitSubDInvoice
method BQCrossCyPosting.ApiProcessQCrossCyPostingForDI
method BSelfBill.ApiCreateInvPrepayPaymentSub


program code (program3/bdinvoice.p)

/* ====================================================================== */
/* first clear the instance, otherwise problems when you execute it twice */
/* ====================================================================== */
if ilClearData = true
then do:
    <M-1 run ClearData (output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
    if viFcReturnSuper <> 0 then assign oiReturnStatus = viFcReturnSuper.
    if viFcReturnSuper < 0 then return.
    assign vcListDIPostingLinesForQCrossCy = "":U.
end. /* if ilClearData = true */

/* ====================================================================================================== */
/* Reset vcListCInvoiceIDsForQCrossCy; Comma-separated list of CInvoiceIDs for the CInvoices wherefor a  */
/* tNewCrossCyPostingTable-record is created in method CreateCInvoiceMovement (and the submethods of it). */
/* Based on this list, PreSave-method will update the CInvoiceIsSelected-flag for these CInvoices (that   */
/* are not loaded into the business-instance).                                                            */
/* ====================================================================================================== */
assign vcListDInvoiceIDsForQCrossCy = "":U.

/* ====================================== */
/* check if there is one record available */
/* ====================================== */
find first tDIMovement no-error.
if not available tDIMovement
then do:
    assign vcMessage      = trim(#T-31'You must define the input for the method that creates activity on customer invoices.':255(1794)T-31#)
           oiReturnStatus = -1.
    <M-2 run SetMessage
       (input  vcMessage (icMessage), 
        input  '':U (icArguments), 
        input  '':U (icFieldName), 
        input  '':U (icFieldValue), 
        input  'E':U (icType), 
        input  3 (iiSeverity), 
        input  '':U (icRowid), 
        input  'QADFIN-700':U (icFcMsgNumber), 
        input  '' (icFcExplanation), 
        input  '' (icFcIdentification), 
        input  '' (icFcContext), 
        output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
    return.
end. /* if not available tDIMovement */
assign vcListDInvoiceIds = "":U.

/* ====================================================== */
/* Empty the temp-table used for calling BQCrossCyPosting */
/* Record created in CreateDInvoiceMovementsCrossCyExt    */
/* ====================================================== */
empty temp-table tNewQCrossCyPostingDI.
empty temp-table tMoveSuspendedTax.

/* ============================================ */
/* start and/or open the journal entry instance */
/* ============================================ */
assign viBJournalEntryDIID = biBJournalEntryID.
if viBJournalEntryDIID = 0 or viBJournalEntryDIID = ?
then do:
    <I-42 {bFcStartAndOpenInstance
            &ADD-TO-TRANSACTION = "True"
            &CLASS              = "BJournalEntry"}>
    assign vlBJEIsStartedFromDI = true.
end. /* if viBJournalEntryDIID = 0 or viBJournalEntryDIID = ? */
else do:
    <I-43 {bFcOpenInstance
            &CLASS           = "BJournalEntry"}>
end. /* else do: */

for each tDIMovement :
    /* ====================== */
    /* replace unknown values */
    /* ====================== */
    if tDIMovement.tiDInvoiceId = ? then assign tDIMovement.tiDInvoiceId = 0.
    if tDIMovement.tdAmountDebitTC = ? then assign tDIMovement.tdAmountDebitTC = 0.
    if tDIMovement.tdAmountCreditTC = ? then assign tDIMovement.tdAmountCreditTC = 0.
    if tDIMovement.tcGLAccountDivisionCode = ? then assign tDIMovement.tcGLAccountDivisionCode = "":U.
    
    /* ==================== */
    /* invoice is mandatory */
    /* ==================== */
    if tDIMovement.tiDInvoiceId = 0
    then do:
        assign vcMessage      = trim(#T-32'You must enter the invoice identification.':255(1204)T-32#)
               oiReturnStatus = -1.
        <M-5 run SetMessage
           (input  vcMessage (icMessage), 
            input  '':U (icArguments), 
            input  '':U (icFieldName), 
            input  '':U (icFieldValue), 
            input  'E':U (icType), 
            input  3 (iiSeverity), 
            input  '':U (icRowid), 
            input  'QADFIN-701':U (icFcMsgNumber), 
            input  '' (icFcExplanation), 
            input  '' (icFcIdentification), 
            input  '' (icFcContext), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        leave.
    end. /* if tDIMovement.tiDInvoiceId = 0 */
    
    /* ============================== */
    /* debit or credit must be filled */
    /* ============================== */
    if tDIMovement.tdAmountDebitTC  = 0 and
       tDIMovement.tdAmountCreditTC = 0
    then do:
        assign vcMessage      = trim(#T-33'You must enter either the debit or the credit amount.':255(1205)T-33#)
               oiReturnStatus = -1.
        <M-6 run SetMessage
           (input  vcMessage (icMessage), 
            input  '':U (icArguments), 
            input  '':U (icFieldName), 
            input  '':U (icFieldValue), 
            input  'E':U (icType), 
            input  3 (iiSeverity), 
            input  '':U (icRowid), 
            input  'QADFIN-702':U (icFcMsgNumber), 
            input  '' (icFcExplanation), 
            input  '' (icFcIdentification), 
            input  '' (icFcContext), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        leave.
    end.
    
    /* ========================================================= */
    /* Check if the DInvoice is in another company; if so then   */
    /* start another method that will do the specific processing */
    /* ========================================================= */
    <Q-23 run DInvoicePrim (all) (Read) (NoCache)
       (input ?, (CompanyId)
        input tDIMovement.tiDInvoiceId, (DInvoiceId)
        input ?, (PeriodYear)
        input ?, (JournalId)
        input ?, (JournalCode)
        input ?, (DInvoiceVoucher)
        output dataset tqDInvoicePrim) in BDInvoice >
    find first tqDInvoicePrim where 
               tqDInvoicePrim.tiDInvoice_ID  = tDIMovement.tiDInvoiceId and
               tqDInvoicePrim.tiCompany_ID  <> viCompanyId
               no-lock no-error.
    if available tqDInvoicePrim
    then do :
        find first tDInvoiceStageUpdates where
                   tDInvoiceStageUpdates.tiDInvoice_ID = tDIMovement.tiDInvoiceId
                   no-error.

        <M-25 run CreateDInvoiceMovementsCrossCy
           (input  tDIMovement.tcPostingRowId (icPostingRowId), 
            input  tDIMovement.tdAmountCreditTC (idMovementAmountCreditTC), 
            input  tDIMovement.tdAmountDebitTC (idMovementAmountDebitTC), 
            input  tDIMovement.tiDInvoiceId (iiMovementDInvoiceID), 
            input  tDIMovement.tcGLAccountDivisionCode (icMovemenGLAccountDivisionCode), 
            input  if available tDInvoiceStageUpdates then tDInvoiceStageUpdates.DDocumentInvoiceXref_ID else ? (iiDDocInvoiceXrefID), 
            input  tDIMovement.tdMovementDiscountTC (idMovementDiscountAmountTC), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        if viFcReturnSuper <> 0 then assign oiReturnStatus = viFcReturnSuper.
        if oiReturnStatus < 0 
        then leave. 
        next. /* posting lines are created in this submethod so continue with the next tDIMovement */
    end. /* if available tqDInvoicePrim */

    /* ================================================================== */
    /* put all invoices in a variable, so you can do a dataload only once */
    /* ================================================================== */
    find first tDInvoice where 
               tDInvoice.DInvoice_ID = tDIMovement.tiDInvoiceId
               no-error.
    if not available tDInvoice
    then assign vcListDInvoiceIds = if vcListDInvoiceIds = "":U
                                    then string(tDIMovement.tiDInvoiceId)
                                    else if lookup(string(tDIMovement.tiDInvoiceId), vcListDInvoiceIds,chr(4)) = 0
                                         then vcListDInvoiceIds + chr(4) + string (tDIMovement.tiDInvoiceId)
                                         else vcListDInvoiceIds.
end. /* for each tDIMovement : */
    
if oiReturnStatus < 0 
then do:
    <I-44 {bFcCloseInstance
            &CLASS           = "BJournalEntry"}>
    return.
end. /* if oiReturnStatus < 0 */

/* ================================================================== */
/* Add the missing DInvoice IDs for DInvoiceStagesUpdates to the list */
/* ================================================================== */
for each tDInvoiceStageUpdates where
         tDInvoiceStage.DInvoice_ID <> ? and
         tDInvoiceStage.DInvoice_ID <> 0:

    if not can-find (first tDInvoice where
                           tDInvoice.DInvoice_ID = tDInvoiceStageUpdates.tiDInvoice_ID) and 
       not can-find (first tNewQCrossCyPostingDI where 
                           tNewQCrossCyPostingDI.DInvoice_ID = tDInvoiceStageUpdates.tiDInvoice_ID) /* Make sure no DI's are loaded that belong to other companies */
    then assign vcListDInvoiceIds = if vcListDInvoiceIds = "":U
                                    then string(tDInvoiceStageUpdates.tiDInvoice_ID)
                                    else if lookup(string(tDInvoiceStageUpdates.tiDInvoice_ID), vcListDInvoiceIds,chr(4)) = 0
                                         then vcListDInvoiceIds + chr(4) + string(tDInvoiceStageUpdates.tiDInvoice_ID)
                                         else vcListDInvoiceIds.
end. /* for each tDInvoiceStageUpdates */

/* ================================================================================================ */
/* Load the Invoices that are related to the movement- and stagedrecords we got as input parameters */
/* ================================================================================================ */
if vcListDInvoiceIds <> "":U
then do:
    <M-7 run DataLoad
       (input  '':U (icRowids), 
        input  vcListDInvoiceIds (icPkeys), 
        input  '':U (icObjectIds), 
        input  '' (icFreeform), 
        input  True (ilKeepPrevious), 
        output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
    if viFcReturnSuper <> 0
    then do:
        assign vcMessage      = trim(substitute(#T-34'Data could not be loaded: unable to load the list of customer invoices (&1).':100(1795)T-34#, replace(vcListDInvoiceIds, chr(4), ",":U)))
               oiReturnStatus = -1.
        <M-8 run SetMessage
           (input  vcMessage (icMessage), 
            input  '':U (icArguments), 
            input  '':U (icFieldName), 
            input  '':U (icFieldValue), 
            input  'E':U (icType), 
            input  3 (iiSeverity), 
            input  '':U (icRowid), 
            input  'QADFIN-703':U (icFcMsgNumber), 
            input  '' (icFcExplanation), 
            input  '' (icFcIdentification), 
            input  '' (icFcContext), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        return.
    end. /* if viFcReturnSuper <> 0 */
end. /* if vcListDInvoiceIds <> "":U */

FOREACHDIMOVEMENTBLOCK: do:
for each tDIMovement :
    /* ========================= */
    /* search the debtor invoice */
    /* ========================= */
    find first tDInvoice where
               tDInvoice.DInvoice_ID = tDIMovement.tiDInvoiceId
               no-error.
    if not available tDInvoice
    then next.

    /* Make sure, we are skipiing creation of the movements for Cross-company invoices */
    if can-find (first tNewQCrossCyPostingDI where 
                       tNewQCrossCyPostingDI.DInvoice_ID = tDIMovement.tiDInvoiceId)
    then next.

    if tDInvoice.tcNormalPaymentConditionType = {&PAYMENTCONDITIONPAYMENTTYPE-STAGED}
    then do:
        if not can-find(first tDInvoiceStageUpdates where
                              tDInvoiceStageUpdates.tiDInvoice_ID = tDInvoice.DInvoice_ID)
        then do:
            <M-59 run CreateDInvoiceStageUpdate
               (input  tDInvoice.DInvoice_ID (iiDInvoiceID), 
                input  itPaymentTaxPointDate (itPaymentDate), 
                input  tDIMovement.tdAmountDebitTC - tdimovement.tdAmountCreditTC (idMovementAmountTC), 
                output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
        end. /* if tDIMovement.tiPostingLineId <> 0 and */
    end. /* if tDInvoice.tcNormalPaymentConditionType = {&PAYMENTCONDITIONPAYMENTTYPE-STAGED} */
    
    /* ================================================================================================= */
    /* Get the IntercompanyCode linked to this BusinessRelation. This IntercoCode is used in the Posting */
    /* ================================================================================================= */
    assign vcBusinessRelationCode = tDInvoice.tcBusinessRelationCode
           vcDBusinessRelationInterCoCode = "":U.
    if vcBusinessRelationCode <> "":U
    then do :
        <Q-26 run BusinessRelationByIDCodeIC (all) (Read) (NoCache)
           (input ?, (BusinessRelationID)
            input vcBusinessRelationCode, (BusinessRelationCode)
            input ?, (BusinessRelationIntercoCode)
            input ?, (BusinessRelationIsActive)
            output dataset tqBusinessRelationByIDCodeIC) in BBusinessRelation >    
        find first tqBusinessRelationByIDCodeIC no-error.    
        if available tqBusinessRelationByIDCodeIC
        then assign vcDBusinessRelationInterCoCode = tqBusinessRelationByIDCodeIC.tcBusinessRelationICCode.    
    end. /* if vcBusinessRelationCode <> "":U */

    /* =================== */
    /* get control account */
    /* =================== */
    <Q-61 run GLById (all) (Read) (NoCache)
       (input viCompanyId, (CompanyId)
        input tDInvoice.ControlGL_ID, (GLId)
        output dataset tqGLById) in BGL >
    find first tqGLById where tqGLById.tiGL_ID = tDInvoice.ControlGL_ID no-error.
    if not available tqGLById
    then do:
        assign vcMessage      = trim(#T-60'The specified customer control account is not defined in the system.':150(49402)T-60#)
               oiReturnStatus = -1.
        <M-64 run SetMessage
           (input  vcMessage (icMessage), 
            input  '':U (icArguments), 
            input  '':U (icFieldName), 
            input  '':U (icFieldValue), 
            input  'E':U (icType), 
            input  3 (iiSeverity), 
            input  '':U (icRowid), 
            input  'QadFin-6704':U (icFcMsgNumber), 
            input  '':U (icFcExplanation), 
            input  '':U (icFcIdentification), 
            input  '':U (icFcContext), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        leave FOREACHDIMOVEMENTBLOCK.
    end. /* end of if not available tqGLById */
    
    /* ========================================================================================== */
    /* Check, if this is the last payment of the invoice, in this case complete LC and CC balance */
    /* has to be taken for the movement                                                           */
    /* ========================================================================================== */
    assign vlIsLastPayment = 
       (tDInvoice.DInvoiceBalanceCreditTC = tDIMovement.tdAmountDebitTC  and tDIMovement.tdAmountDebitTC <> 0 or
        tDInvoice.DInvoiceBalanceDebitTC  = tDIMovement.tdAmountCreditTC and tDIMovement.tdAmountCreditTC <> 0).

    /* =============================== */
    /* Calculate the LC and CC amounts */
    /* =============================== */
    if tDInvoice.DInvoiceCurrency_ID = viCompanyLCId or 
       tDInvoice.tcCurrencyCode = vcCompanyLC  
    then assign vdDebitLC  = tDIMovement.tdAmountDebitTC
                vdCreditLC = tDIMovement.tdAmountCreditTC.
    else if vlIsLastPayment /* Last payment of the invoice */
    then assign vdDebitLC = tDInvoice.DInvoiceBalanceCreditLC
                vdCreditLC = tDInvoice.DInvoiceBalanceDebitLC.

    else assign vdDebitLC = <M-54 RoundAmount
                               (input  tDIMovement.tdAmountDebitTC * tDInvoice.DInvoiceExchangeRate * tDInvoice.DInvoiceRateScale (idUnroundedAmount), 
                                input  viCompanyLCId (iiCurrencyID), 
                                input  vcCompanyLC (icCurrencyCode)) in BApplicationProperty>
                vdCreditLC = <M-55 RoundAmount
                                (input  tDIMovement.tdAmountCreditTC * tDInvoice.DInvoiceExchangeRate * tDInvoice.DInvoiceRateScale (idUnroundedAmount), 
                                 input  viCompanyLCId (iiCurrencyID), 
                                 input  vcCompanyLC (icCurrencyCode)) in BApplicationProperty>.

    assign vdDebitCC  = 0
           vdCreditCC = 0.

    if viCompanyCCId <> 0 and viCompanyCCId <> ?
    then do:
        if tDInvoice.tcCurrencyCode = vcCompanyCC
        then assign vdDebitCC  = tDIMovement.tdAmountDebitTC
                    vdCreditCC = tDIMovement.tdAmountCreditTC.
        else if vlDomainIsStatutory = false
        then assign vdDebitCC  = vdDebitLC
                    vdCreditCC = vdCreditLC.
        else if vlIsLastPayment  /* Last payment of the invoice */
        then assign vdDebitCC  = tDInvoice.DInvoiceBalanceCreditCC
                    vdCreditCC = tDInvoice.DInvoiceBalanceDebitCC.
        else assign vdDebitCC  = <M-4 RoundAmount
                                    (input  tDIMovement.tdAmountDebitTC * tDInvoice.DInvoiceCCRate * tDInvoice.DInvoiceCCScale (idUnroundedAmount), 
                                     input  viCompanyCCId (iiCurrencyID), 
                                     input  vcCompanyCC (icCurrencyCode)) in BApplicationProperty>
                    vdCreditCC = <M-12 RoundAmount
                                    (input  tDIMovement.tdAmountCreditTC * tDInvoice.DInvoiceCCRate * tDInvoice.DInvoiceCCScale (idUnroundedAmount), 
                                     input  viCompanyCCId (iiCurrencyID), 
                                     input  vcCompanyCC (icCurrencyCode)) in BApplicationProperty>.
    end. /* if viCompanyCCId <> 0 and viCompanyCCId <> ? */
    
    /* ========================= */
    /* get division profile info */
    /* ========================= */
    if tqGLById.tlGLIsDivisionAccount and tDIMovement.tcGLAccountDivisionCode = "":U
    then do:         
        <Q-63 run GetDivisionFromProfile (all) (Read) (NoCache)
           (input tDInvoice.Company_ID, (CompanyId)
            input tqGLById.tiDivisionProfile_ID, (DivisionProfileId)
            output dataset tqDivisionFromProfile) in BProfile >
        find first tqDivisionFromProfile no-error.
        if not available tqDivisionFromProfile
        then do:             
            assign vcMessage      = trim(#T-57'The sub-account profile of the Customer Control account is not defined.':255(763399828)T-57#)
                   oiReturnStatus = -3.
            <M-65 run SetMessage
               (input  vcMessage (icMessage), 
                input  '':U (icArguments), 
                input  '':U (icFieldName), 
                input  '':U (icFieldValue), 
                input  'E':U (icType), 
                input  3 (iiSeverity), 
                input  '':U (icRowid), 
                input  'QadFin-6705':U (icFcMsgNumber), 
                input  '':U (icFcExplanation), 
                input  '':U (icFcIdentification), 
                input  '':U (icFcContext), 
                output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
            leave FOREACHDIMOVEMENTBLOCK.
        end. /* if not available tqDivisionFromProfile */
    end. /* end of if tqProfileLinkByGL.tlGLIsDivisionAccount and */    
    assign vcParam = if tqGLById.tlGLIsDivisionAccount
                     then if tDIMovement.tcGLAccountDivisionCode = "":U
                          then if tDInvoice.tcDivisionCode = "":U
                               then tqDivisionFromProfile.tcDivisionCode
                               else tDInvoice.tcDivisionCode
                          else tDIMovement.tcGLAccountDivisionCode
                     else "":U.

    /* ============================================= */                            
    /* Create the postingline on the control account */
    /* ============================================= */    
    empty temp-table tDefaultSafsDI.
    <M-18 run AddControlPosting
       (input  tDIMovement.tcPostingRowId (icPostingtcRowid), 
        input  tqGLById.tcGLCode (icGLCode), 
        input  vcParam (icDivisionCode), 
        input  vcDBusinessRelationInterCoCode (icIntercoBusinessRelationCode), 
        input  tDInvoice.tcCurrencyCode (icCurrencyCode), 
        input  tDIMovement.tdAmountDebitTC (idDebitTC), 
        input  vdDebitLC (idDebitLC), 
        input  vdDebitCC (idDebitCC), 
        input  tDIMovement.tdAmountCreditTC (idCreditTC), 
        input  vdCreditLC (idCreditLC), 
        input  vdCreditCC (idCreditCC), 
        input  tDInvoice.DInvoiceDIText (icText), 
        input  tDInvoice.Debtor_ID (iiMasterId), 
        input  tDIMovement.tiDInvoiceId (iiTransactionId), 
        input  if tDInvoice.DInvoiceExchangeRate = 0 then 1 else tDInvoice.DInvoiceExchangeRate (idExchangeRate), 
        input  if tDInvoice.DInvoiceRateScale = 0 then 1 else tDInvoice.DInvoiceRateScale (idExchangeRateScale), 
        input  if tDInvoice.DInvoiceCCRate = 0 then 1 else tDInvoice.DInvoiceCCRate (idPostingLineCCRate), 
        input  if tDInvoice.DInvoiceCCScale = 0 then 1 else tDInvoice.DInvoiceCCScale (idPostingLineCCScale), 
        input  '':U (icAllocationKey), 
        input  tDInvoice.tcCostCentreCode (icCostCentreCode), 
        input  tDInvoice.tcProjectCode (icProjectCode), 
        input  tDefaultSafsDI (tDefaultSafs), 
        output tDIMovement.tiPostingLineId (oiPostingLineId), 
        input  false (ilLinkedCrCyDaemonReqExists), 
        output viFcReturnSuper (oiReturnStatus)) in BJournalEntry>
    if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
    then assign oiReturnStatus = viFcReturnSuper.
    if viFcReturnSuper < 0 then leave FOREACHDIMOVEMENTBLOCK.

    /* ======================= */
    /* Create DInvoiceMovement */
    /* ======================= */    
    if not can-find(first tDInvoiceMovement where
                          tDInvoiceMovement.tc_ParentRowid = tDInvoice.tc_Rowid and
                          tDInvoiceMovement.PostingLine_ID = tDIMovement.tiPostingLineId)
    then do:
        <M-19 run AddDetailLine
           (input  'DInvoiceMovement':U (icTable), 
            input  tDInvoice.tc_Rowid (icParentRowid), 
            output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
        then assign oiReturnStatus = viFcReturnSuper.
        assign tDInvoiceMovement.DInvoice_ID                = tDIMovement.tiDInvoiceId
               tDInvoiceMovement.PostingLine_Id             = tDIMovement.tiPostingLineId
               tDInvoiceMovement.DInvoiceMovementDiscountTC = tDIMovement.tdMovementDiscountTC
               tDInvoiceMovement.DInvoiceMovementType       = {&MOVEMENTTYPE-MOVEMENT}. 
        /* ============================= */       
        /* update the bank records first */
        /* ============================= */
        if tDInvoice.DInvoiceType <> {&INVOICETYPE-DEDUCTION} then
        do:     
            <M-41 run UpdateDInvoiceBankToPayTC
               (input  tDIMovement.tiDInvoiceId (iiDInvoiceId), 
                input  tDInvoice.DInvoiceBalanceDebitTC (idOldBalanceDebitTC), 
                input  tDInvoice.DInvoiceBalanceCreditTC (idOldBalanceCreditTC), 
                input  tDIMovement.tdAmountDebitTC (idMovementAmountDebitTC), 
                input  tDIMovement.tdAmountCreditTC (idMovementAmountCreditTC), 
                output viFcReturnSuper (oiReturnStatus)) in BDInvoice>        
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if viFcReturnSuper < 0
            then Leave FOREACHDIMOVEMENTBLOCK.
        end.
        /* =========================================== */
        /* Create Suspended tax postinglines if needed */
        /* =========================================== */
        if tDInvoice.DInvoiceType <> {&INVOICETYPE-DEDUCTION} then
        do:  
          <M-70 run CreateDInvoiceMovementsSuspTax
               (output vdSuspTaxAmountTC (odSuspTaxAmountTC), 
                input-output tMoveSuspendedTax (tMoveSuspendedTax), 
                input  itPaymentTaxPointDate (itPaymentTaxPointDate), 
                output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
                   
        end.
        /* ======================================================================================== */
        /* Update balance fields; if the originalbalance-Credit was filled then all updates of      */
        /* the balance will be on the credit fields allthough the DInvoice record can have linked   */ 
        /* posting-lines with an amount filled on the debit-side of the posting.                    */
        /* CuccBal  NewBal  Posting (=tDIMov)   BalanceChange                                       */
        /* 100Cr    80Cr    20Db                -20Cr                                               */
        /* 100Cr    110Cr   10Cr                10Cr                                                */
        /* 100Db    70Db    30Cr                -30Db                                               */
        /* 100Db    140Db   40Db                40Db                                                */
        /* ======================================================================================== */
        if tDInvoice.DInvoiceBalanceDebitTC <> ? and tDInvoice.DInvoiceBalanceDebitTC <> 0
        then assign tDInvoice.DInvoiceBalanceDebitTC = tDInvoice.DInvoiceBalanceDebitTC - tDIMovement.tdAmountCreditTC + tDIMovement.tdAmountDebitTC
                    tDInvoice.DInvoiceBalanceDebitLC = tDInvoice.DInvoiceBalanceDebitLC - vdCreditLC + vdDebitLC
                    tDInvoice.DInvoiceBalanceDebitCC = tDInvoice.DInvoiceBalanceDebitCC - vdCreditCC + vdDebitCC.
        else do:
     
            if tDInvoice.DInvoiceBalanceCreditTC <> ? and tDInvoice.DInvoiceBalanceCreditTC <> 0
            then assign tDInvoice.DInvoiceBalanceCreditTC = tDInvoice.DInvoiceBalanceCreditTC + tDIMovement.tdAmountCreditTC - tDIMovement.tdAmountDebitTC
                        tDInvoice.DInvoiceBalanceCreditLC = tDInvoice.DInvoiceBalanceCreditLC + vdCreditLC - vdDebitLC
                        tDInvoice.DInvoiceBalanceCreditCC = tDInvoice.DInvoiceBalanceCreditCC + vdCreditCC - vdDebitCC.
            else /* set the invoice back to the last movement */
                 assign tDInvoice.DInvoiceBalanceDebitTC  = tDIMovement.tdAmountDebitTC
                        tDInvoice.DInvoiceBalanceDebitLC  = vdDebitLC 
                        tDInvoice.DInvoiceBalanceDebitCC  = vdDebitCC
                        tDInvoice.DInvoiceBalanceCreditTC = tDIMovement.tdAmountCreditTC
                        tDInvoice.DInvoiceBalanceCreditLC = vdCreditLC 
                        tDInvoice.DInvoiceBalanceCreditCC = vdCreditCC.
        end.
        assign tDInvoice.DInvoiceBalanceTC = tDInvoice.DInvoiceBalanceDebitTC - tDInvoice.DInvoiceBalanceCreditTC
               tDInvoice.DInvoiceBalanceLC = tDInvoice.DInvoiceBalanceDebitLC - tDInvoice.DInvoiceBalanceCreditLC
               tDInvoice.DInvoiceBalanceCC = tDInvoice.DInvoiceBalanceDebitCC - tDInvoice.DInvoiceBalanceCreditCC
               tDInvoice.DInvoiceIsOpen    = (tDInvoice.DInvoiceBalanceTC <> 0 or tDInvoice.DInvoiceBalanceLC <> 0 or tDInvoice.DInvoiceBalanceCC <> 0)
               tDInvoice.tc_Status         = (if tDInvoice.tc_Status = "":U then "C":U else tDInvoice.tc_Status)
               tDInvoice.DInvoiceIsSelected = false.
                
        if tDInvoice.DinvoiceType = {&INVOICETYPE-DEDUCTION} then
        do:

            if tDInvoice.dinvoicebalancedebittc < 0 then
            do:
                assign
                    tDInvoice.DInvoiceBalanceCreditTC = abs(tDInvoice.DInvoiceBalanceDebitTC)
                    tDInvoice.DInvoiceBalanceCreditlc = abs(tDInvoice.DInvoiceBalanceDebitLC)
                    tDInvoice.DInvoiceBalanceCreditcc = abs(tDInvoice.DInvoiceBalanceDebitCC) 
                    tDInvoice.DInvoiceBalanceDebitTC = 0
                    tDInvoice.DInvoiceBalanceDebitLC = 0
                    tDInvoice.DInvoiceBalanceDebitCC = 0.
            end.
        end.
        
        
    end. /* if not can find */
end. /* for each tDIMovement */

/* ================================================================================================= */
/* Create one postingline to reverse existing delayed tax account and one for the normal tax account */
/* Update the existing tax records of the invoice.                                                   */
/* ================================================================================================= */
if can-find(first tMoveSuspendedTax)
then do:
    <M-69 run MoveSuspendedTax
       (input  viBJournalEntryDIID (iiBJournalEntryID), 
        input  tMoveSuspendedTax (tMoveSuspendedTax), 
        input  true (ilInstanceBJEAlreadyOpened), 
        output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
        if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
        then assign oiReturnStatus = viFcReturnSuper.
        if viFcReturnSuper < 0 then leave FOREACHDIMOVEMENTBLOCK.
end.
end. /* FOREACHDIMOVEMENTBLOCK */

/* ============================ */
/* Update DInvoiceStage Records */
/* ============================ */
for each tDIMovement,
    each tDInvoiceStageUpdates where
         tDInvoiceStageUpdates.tiDInvoice_ID = tDIMovement.tiDInvoiceId:

   find first tDInvoiceStage where
              tDInvoiceStage.DInvoiceStage_ID = tDInvoiceStageUpdates.DInvoiceStage_ID
              no-error.
   
   if available tDInvoiceStage
   then do:
       if tDIMovement.tlIsUndoPayment = no
       then assign tDInvoiceStage.DInvoiceStageAmtAppliedTC = tDInvoiceStage.DInvoiceStageAmtAppliedTC + tDinvoiceStageUpdates.DDocInvoiceXrefStageAlloTC.
       else assign tDInvoiceStage.DInvoiceStageAmtAppliedTC = tDInvoiceStage.DInvoiceStageAmtAppliedTC - tDinvoiceStageUpdates.DDocInvoiceXrefStageAlloTC.
               
       assign 
          tDInvoiceStage.tc_Status = (if tDInvoiceStage.tc_Status = "":U then "C":U else tDInvoiceStage.tc_Status)
          tDInvoiceStage.DinvoiceStageIsSelected = false.             
    end.
end. /* end of update CinvoiceStage records */

/* ========================================================================================================= */
/* Normally we would here close BJournalEntry we will not do it for performance                              */
/* reasons as this way the Commit of the transaction does not have to re-open the instance to commit it.     */
/* And in all other scenario's the instance of the class ill be closed by the de-activiate procedure of the  */
/* appserver that is executed after each call to the appserver                                               */
/* ========================================================================================================= */

if oiReturnStatus < 0 
then do :
    /* ======================= */
    /* Stop external instances */
    /* ======================= */    
    <M-66 run StopExternalInstances
       (output viFcReturnSuper (oiReturnStatus)) in BDInvoice>
    return.
end.

/* ============ */
/* State the ID */
/* ============ */
assign biBJournalEntryID      = viBJournalEntryDIID.

/* ========================================================================== */
/* Create Q-CrossCompany postings that will be picked up later-on by a daemon  */
/* ========================================================================== */
if can-find (first tNewQCrossCyPostingDI)
then do :
    if viBQCrossCyPostingDIID = 0 or viBQCrossCyPostingDIID = ?
    then do:
        <I-50 {bFcStartAndOpenInstance
            &ADD-TO-TRANSACTION = "true"
            &CLASS              = "BQCrossCyPosting"}>
    end. /* if viBQCrossCyPostingID = 0 */
    else do:
        <I-51 {bFcOpenInstance
            &CLASS           = "BQCrossCyPosting"}>
    end. /* if viBQCrossCyPostingID <> 0 */
    <M-52 run ApiCreateQCrossCyPosting (input  tNewQCrossCyPostingDI (tNewQCrossCyPosting), 
                                    output viExternalReturn (oiReturnStatus)) in BQCrossCyPosting>   
    /* ========================================================================================================= */
    /* Normally we would here close BQCrossCyPosting but we will not do it for performance                       */
    /* reasons as this way the Commit of the transaction does not have to re-open the instance to commit it.     */
    /* And in all other scenario's the instance of the class ill be closed by the de-activiate procedure of the  */
    /* appserver that is executed after each call to the appserver                                               */
    /* ========================================================================================================= */
    if viExternalReturn <> 0 
    then assign oiReturnStatus = viExternalReturn.
    if oiReturnStatus < 0 
    then return. 
end. /* if can-find (first tNewQCrossCyPostingDI) */