project QadFinancials > class BCInvoice > method CreateCInvoiceMovements

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


tMovementinput-outputtemp-tableMovement records wherefor a cinvoicemovement record must be created
tCInvoiceStageUpdatesinputtemp-table
biBJournalEntryIdinput-outputintegerJournal Entry ID
ilClearDatainputlogicalClearData; pass true in case you want BCinvoice to start from scratch
itPaymentTaxPointDateinputdateTax Point Date of Payment
ilIsCallFromBankingEntryOrOIAdjinputlogical
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


QadFinancials
method BBankEntry.AdditionalUpdatesInvCInvoice
method BCDocument.AdditionalUpdatesPosting
method BCInvoice.AdditionalUpdatesAllCreateCA
method BExpenseNote.APIExpNoteRegister
method BOpenItemAdjustment.OIAdjCommitSubCInvoice
method BQCrossCyPosting.ApiProcessQCrossCyPostingForCI


program code (program7/bcinvoice.p)

if ilIsCallFromBankingEntryOrOIAdj = ? 
then assign ilIsCallFromBankingEntryOrOIAdj = false.

/* ======================================================= */
/* Default the payment tax point date when it's left empty */
/* ======================================================= */
if itPaymentTaxPointDate = ? then assign itPaymentTaxPointDate = today.

/* ====================================================================== */
/* first clear the instance, otherwise problems when you execute it twice */
/* ====================================================================== */
if ilClearData
then do:
    <M-1 run ClearData (output oiReturnStatus (oiReturnStatus)) in BCInvoice>
    if oiReturnStatus < 0 then return.    
    
    empty temp-table tCInvoiceIDsForQCrossCompany.
    empty temp-table tPostingLinesForQCrossCompany.    
end. /* if ilClearData */

/* =============================================== */
/* check if there is one movement record available */
/* =============================================== */
find first tMovement no-error.
if not available tMovement
then do:
    assign oiReturnStatus = -1.
    <M-18 run SetMessage
       (input  trim(#T-44'You must define the input for the method that creates activity on supplier invoices.':255(1203)T-44#) (icMessage), 
        input  '':U (icArguments), 
        input  '':U (icFieldName), 
        input  '':U (icFieldValue), 
        input  'E':U (icType), 
        input  3 (iiSeverity), 
        input  '':U (icRowid), 
        input  'QADFIN-679':U (icFcMsgNumber), 
        input  '' (icFcExplanation), 
        input  '' (icFcIdentification), 
        input  '' (icFcContext), 
        output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
    return.
end. /* if not available tMovement */

/* ====================================================== */
/* Empty the temp-table used for calling BQCrossCyPosting */
/* Record created in CreateCInvoiceMovementsCrossCyExt    */
/* ====================================================== */
empty temp-table tNewQCrossCyPostingTable.
empty temp-table tInvoicesToUpdate.
assign vcListCInvoiceIds = "":U.

/* ============================================ */
/* start and/or open the journal entry instance */
/* ============================================ */
assign viBJournalEntryCIID = biBJournalEntryId.
if viBJournalEntryCIId = 0 or viBJournalEntryCIId = ?
then do:
  <I-40 {bFcStartAndOpenInstance
       &ADD-TO-TRANSACTION   = "true"
       &CLASS                = "BJournalEntry"}>
  assign vlBJEIsStartedFromCI = true.
end. /* if viBJournalEntryCIId = 0 or viBJournalEntryCIId = ? */
else do:
  <I-41 {bFcOpenInstance
       &CLASS           = "BJournalEntry"}>
end. /* else do: */

/* ==================================================== */
/* Get the list of ID's to load and do some validations */
/* ==================================================== */
<M-67 run CreateCInvoiceMovementsIDS
   (input-output tMovement (tMovement), 
    input  tCInvoiceStageUpdates (tCInvoiceStageUpdates), 
    output tInvoicesToUpdate (tInvoicesToUpdate), 
    output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
then assign oiReturnStatus = viFcReturnSuper.
            
/* ====================================================== */
/* close the journal entry instance when an error occured */
/* ====================================================== */
if oiReturnStatus < 0
then do:
    <I-42 {bFcCloseInstance
         &CLASS           = "BJournalEntry"}>
    return.                                  
end. /* if oiReturnStatus < 0 */

/* ========================================================= */
/* Add CInvoice_ID's from the stage updates to the load list */
/* ========================================================= */
for each tCInvoiceStageUpdates:
    find first tCInvoice where 
               tCInvoice.CInvoice_ID = tCInvoiceStageUpdates.tiCInvoice_Id 
               no-error.
    if not available tCInvoice and
       not can-find (first tNewQCrossCyPostingTable where 
                           tNewQCrossCyPostingTable.CInvoice_ID = tCInvoiceStageUpdates.tiCInvoice_Id)
    then do:
            /* assign vcListCInvoiceIds = if vcListCInvoiceIds = "":U
                                    then string(tCInvoiceStageUpdates.tiCInvoice_Id)
                                    else if lookup(string(tCInvoiceStageUpdates.tiCInvoice_Id), vcListCInvoiceIds,chr(4)) = 0
                                         then vcListCInvoiceIds + chr(4) + string (tCInvoiceStageUpdates.tiCInvoice_Id)
                                         else vcListCInvoiceIds.*/
        if not can-find(first tInvoicesToUpdate where tInvoicesToUpdate.tiCInvoiceID =  tCInvoiceStageUpdates.tiCInvoice_Id)
        then do:
            create tInvoicesToUpdate.
            assign tInvoicesToUpdate.tiCInvoiceID = tCInvoiceStageUpdates.tiCInvoice_Id.
        end.
    end.
end. /* for each tCInvoiceStageUpdates: */

/* ================================================================================================ */
/* Load the Invoices that are related to the movement- and stagedrecords we got as input parameters */
/* ================================================================================================ */
for each tInvoicesToUpdate:

    if vcListCInvoiceIds = '':U
    then assign vcListCInvoiceIds = string(tInvoicesToUpdate.tiCInvoiceID).
    else assign vcListCInvoiceIds = vcListCInvoiceIds + chr(4) + string(tInvoicesToUpdate.tiCInvoiceID).

    /* if vcListCInvoiceIds > 10000, load the data to prevent vcListPostingIDsToLoad to get out of 32K limit */
    if length(vcListCInvoiceIds , "CHARACTER") > 10000
    then do :
        
        /* If we do a DataLoad here then vlFcDataValidated will be set to false again. */
        /* When this method is called from a sub-method of  BCInvoice:AdditionalUpdates then we only want to create a movement on the linked invoice. */
        /* As all data in this flow has already been validated, we consider it to be okay to save the linked invoice without validating that invoice */
        /* To avoid we get error 'BLF-308: Data to save () has not been validated", we will manually assign vlFcDataValidated to true after the DataLoad if it was already true before the DataLoad */
        assign vlPreviousFcDataValidated = vlFcDataValidated.
        <M-34 run DataLoad
           (input  '':U (icRowids), 
            input  vcListCInvoiceIds (icPkeys), 
            input  '':U (icObjectIds), 
            input  '' (icFreeform), 
            input  yes (ilKeepPrevious), 
            output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
        if vlPreviousFcDataValidated = true
        then assign vlFcDataValidated = true.
        
        /* ====================================================================== */
        /* close the journal entry instance when an error occured during the load */
        /* ====================================================================== */
        if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
        then assign oiReturnStatus = viFcReturnSuper.
        if oiReturnStatus < 0
        then do:
            <I-43 {bFcCloseInstance
                 &CLASS           = "BJournalEntry"}>
            return.
        end. /* if oiReturnStatus < 0 */
        
         assign vcListCInvoiceIds = '':U.
     end. /* if length(vcListCInvoiceIds , "CHARACTER") > 10000 */

end.

if vcListCInvoiceIds <> ''
then do :
    
    /* If we do a DataLoad here then vlFcDataValidated will be set to false again. */
    /* When this method is called from a sub-method of  BCInvoice:AdditionalUpdates then we only want to create a movement on the linked invoice. */
    /* As all data in this flow has already been validated, we consider it to be okay to save the linked invoice without validating that invoice */
    /* To avoid we get error 'BLF-308: Data to save () has not been validated", we will manually assign vlFcDataValidated to true after the DataLoad if it was already true before the DataLoad */
    assign vlPreviousFcDataValidated = vlFcDataValidated.
    <M-84 run DataLoad
       (input  '':U (icRowids), 
        input  vcListCInvoiceIds (icPkeys), 
        input  '':U (icObjectIds), 
        input  '' (icFreeform), 
        input  yes (ilKeepPrevious), 
        output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
    if vlPreviousFcDataValidated = true
    then assign vlFcDataValidated = true.
    
    /* ====================================================================== */
    /* close the journal entry instance when an error occured during the load */
    /* ====================================================================== */
    if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
    then assign oiReturnStatus = viFcReturnSuper.
    if oiReturnStatus < 0
    then do:
        <I-52 {bFcCloseInstance
             &CLASS           = "BJournalEntry"}>
        return.
    end. /* if oiReturnStatus < 0 */
        
    assign vcListCInvoiceIds = '':U.
    
end. /* if vcListCInvoiceIds <> '' */

empty temp-table tCInvoiceVatDelayDelta.

/* =========================================================== */
/* check if the Movement came from Unconfirm Payment selection */
/* Set the vlIsPaySelUnconfirm data item - CA767022            */
/* =========================================================== */      
<I-89 {bFcOpenInstance
        &CLASS           = "Session"}>
<M-2 run GetLogicalValue
   (input  'PaySelUnconfirm':U (icName), 
    output vlIsPaySelUnconfirm (olValue), 
    output viFcReturnSuper (oiReturnStatus)) in Session>
/* set the value back to null in case it will affect furtuer normal payment selection */
if vlIsPaySelUnconfirm <> ?
then do:
    <M-83 run SetLogicalValue
       (input  'PaySelUnconfirm':U (icName), 
        input  ? (ilValue), 
        output viFcReturnSuper (oiReturnStatus)) in Session>
end. /* if vlIsPaySelUnconfirm <> ? */


FOREACHTMOVEMENTBLOCK : DO :
for each tMovement 
    /* first the one with false, after that the one with true */
    by tMovement.tlMovementIsAboutWHT:
    
    /* ================================= */
    /* get the invoice for this movement */
    /* ================================= */
    find first tCInvoice where
               tCInvoice.CInvoice_ID = tMovement.tiCInvoiceId and
               tCInvoice.Company_ID  = viCompanyId no-error.
    if not available tCInvoice
    then next. 
    
    /* ============================================================================== */
    /* Make sure, we are skiping creation of the movements for Cross-company invoices */
    /* ============================================================================== */
    if can-find (first tNewQCrossCyPostingTable where 
                       tNewQCrossCyPostingTable.CInvoice_ID = tMovement.tiCInvoiceId)
    then next.

    /* ========================================================================================== */
    /* 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 = 
       (tCInvoice.CInvoiceBalanceCreditTC = tMovement.tdAmountDebitTC  and tMovement.tdAmountDebitTC <> 0 or
        tCInvoice.CInvoiceBalanceDebitTC  = tMovement.tdAmountCreditTC and tMovement.tdAmountCreditTC <> 0).
        
    /* ========================================================================================== */
    /* Check if this is the reopening of the invoice to full invoice amount (like payment undo)   */
    /* ========================================================================================== */
    assign vlIsFullReopen =
        tMovement.tlIsUndoPayment and
        ((tCInvoice.CInvoiceBalanceCreditTC + tMovement.tdAmountCreditTC = tCInvoice.CInvoiceOriginalCreditTC and tMovement.tdAmountCreditTC <> 0) or
         (tCInvoice.CInvoiceBalanceDebitTC + tMovement.tdAmountDebitTC = tCInvoice.CInvoiceOriginalDebitTC and tMovement.tdAmountDebitTC <> 0)).
    
    /* =============================== */    
    /* Calculate the LC and CC amounts */
    /* =============================== */
    if tMovement.tlMovementIsAboutWHT <> true
    then do :        
        /* ========================= */
        /* Fill in LC and CC Amounts */
        /* ========================= */
        if tCInvoice.CInvoiceCurrency_ID = viCompanyLCId or 
           tCInvoice.tcCurrencyCode      = vcCompanyLC  
        then assign vdDebitLC   = tMovement.tdAmountDebitTC
                    vdCreditLC  = tMovement.tdAmountCreditTC.

        else if vlIsLastPayment /* Last payment of the invoice */
        then assign vdDebitLC  = tCInvoice.CInvoiceBalanceCreditLC
                    vdCreditLC = tCInvoice.CInvoiceBalanceDebitLC.

        else if vlIsFullReopen /* Full reopening of the invoice */
        then assign vdDebitLC  = tCInvoice.CInvoiceOriginalDebitLC - tCInvoice.CInvoiceBalanceDebitLC
                    vdCreditLC = tCInvoice.CInvoiceOriginalCreditLC - tCInvoice.CInvoiceBalanceCreditLC.

        else /* Special exchange rate is to be used - e. g. Expense Notes  */
            if (tMovement.tdAmountCreditLC <> 0 and
                tMovement.tdAmountCreditLC <> ?) or
               (tMovement.tdAmountDebitLC  <> 0 and
                tMovement.tdAmountDebitLC  <> ?)
            then assign vdDebitLC = <M-61 RoundAmount
                                       (input  tMovement.tdAmountDebitLC (idUnroundedAmount), 
                                        input  viCompanyLCId (iiCurrencyID), 
                                        input  ? (icCurrencyCode)) in BApplicationProperty>
                        vdCreditLC = <M-62 RoundAmount
                                        (input  tMovement.tdAmountCreditLC (idUnroundedAmount), 
                                         input  viCompanyLCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BApplicationProperty>.
            else assign vdDebitLC = <M-63 RoundAmount
                                       (input  tMovement.tdAmountDebitTC * tCInvoice.CInvoiceExchangeRate * tCInvoice.CinvoiceRateScale (idUnroundedAmount), 
                                        input  viCompanyLCId (iiCurrencyID), 
                                        input  ? (icCurrencyCode)) in BApplicationProperty>
                        vdCreditLC = <M-64 RoundAmount
                                        (input  tMovement.tdAmountCreditTC * tCInvoice.CInvoiceExchangeRate * tCInvoice.CinvoiceRateScale (idUnroundedAmount), 
                                         input  viCompanyLCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BApplicationProperty>.

        if tCInvoice.CInvoiceCurrency_ID = viCompanyCCId or
           tCInvoice.tcCurrencyCode      = vcCompanyCC 
        then assign vdDebitCC  = tMovement.tdAmountDebitTC
                    vdCreditCC = tMovement.tdAmountCreditTC.
        
        else if vlDomainIsStatutory = false
        then assign vdDebitCC  = vdDebitLC
                    vdCreditCC = vdCreditLC.
        
        else if vlIsLastPayment  /* Last payment of the invoice */
        then assign vdDebitCC  = tCInvoice.CInvoiceBalanceCreditCC
                    vdCreditCC = tCInvoice.CInvoiceBalanceDebitCC.

        else if vlIsFullReopen /* Full reopening of the invoice */
        then assign vdDebitCC  = tCInvoice.CInvoiceOriginalDebitCC - tCInvoice.CInvoiceBalanceDebitCC
                    vdCreditCC = tCInvoice.CInvoiceOriginalCreditCC - tCInvoice.CInvoiceBalanceCreditCC.

        else /* Special exchange rate is to be used - e. g. Expense Notes  */ 
            if (tMovement.tdAmountCreditCC <> 0 and
                tMovement.tdAmountCreditCC <> ?) or
               (tMovement.tdAmountDebitCC  <> 0 and
                tMovement.tdAmountDebitCC  <> ?)
            then assign vdDebitCC = <M-39 RoundAmount
                                       (input  tMovement.tdAmountDebitCC (idUnroundedAmount), 
                                        input  viCompanyCCId (iiCurrencyID), 
                                        input  ? (icCurrencyCode)) in BApplicationProperty>
                        vdCreditCC = <M-91 RoundAmount
                                        (input  tMovement.tdAmountCreditCC (idUnroundedAmount), 
                                         input  viCompanyCCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BApplicationProperty>.
            else assign vdDebitCC  = <M-51 RoundAmount
                                        (input  tMovement.tdAmountDebitTC * tCInvoice.CInvoiceCCRate * tCInvoice.CInvoiceCCScale (idUnroundedAmount), 
                                         input  viCompanyCCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BApplicationProperty>
                        vdCreditCC = <M-49 RoundAmount
                                        (input  tMovement.tdAmountCreditTC * tCInvoice.CInvoiceCCRate * tCInvoice.CInvoiceCCScale (idUnroundedAmount), 
                                         input  viCompanyCCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BApplicationProperty>.
    end. /* if tMovement.tlMovementIsAboutWHT <> true */
    else do:
        /* ================================= */
        /* Fill in LC and CC Amounts for WHT */
        /* ================================= */
        if tCInvoice.CInvoiceCurrency_ID = viCompanyLCId or 
           tCInvoice.tcCurrencyCode      = vcCompanyLC  
        then assign vdDebitLC   = tMovement.tdAmountDebitTC
                    vdCreditLC  = tMovement.tdAmountCreditTC.
        else if (tMovement.tdAmountCreditLC <> 0 and
                 tMovement.tdAmountCreditLC <> ?) or
                (tMovement.tdAmountDebitLC  <> 0 and
                 tMovement.tdAmountDebitLC  <> ?)
             then assign vdDebitLC  = <M-95 RoundAmount
                                         (input  tMovement.tdAmountDebitLC (idUnroundedAmount), 
                                          input  viCompanyLCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>
                         vdCreditLC = <M-22 RoundAmount
                                         (input  tMovement.tdAmountCreditLC (idUnroundedAmount), 
                                          input  viCompanyLCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>.
             else do :
                 if tMovement.tdRateTCLC  = 0 or
                    tMovement.tdScaleTCLC = ? or
                    tMovement.tdRateTCLC  = 0 or
                    tMovement.tdScaleTCLC = ?
                 then do :
                     assign oiReturnStatus = -1
                            vcmessage      = trim(#T-78'Internal error: The input-record for the invoice-movement does not hold a proper rate fot the base-currency.':255(570834916)T-78#).
                     <M-37 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-469759':U (icFcMsgNumber), 
                         input  '':U (icFcExplanation), 
                         input  '':U (icFcIdentification), 
                         input  '':U (icFcContext), 
                         output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
                     Leave FOREACHTMOVEMENTBLOCK.
                 end. /* if tMovement.tdRateTCLC  = 0 or */
                 assign vdDebitLC  = <M-576 RoundAmount
                                        (input  tMovement.tdAmountDebitTC * tMovement.tdRateTCLC * tMovement.tdScaleTCLC (idUnroundedAmount), 
                                         input  viCompanyLCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BCInvoice>  
                        vdCreditLC = <M-545 RoundAmount
                                        (input  tMovement.tdAmountCreditTC * tMovement.tdRateTCLC * tMovement.tdScaleTCLC (idUnroundedAmount), 
                                         input  viCompanyLCId (iiCurrencyID), 
                                         input  ? (icCurrencyCode)) in BCInvoice>. 
             end. /* else do */  
        if tCInvoice.CInvoiceCurrency_ID = viCompanyCCId or 
           tCInvoice.tcCurrencyCode      = vcCompanyCC  
        then assign vdDebitCC   = tMovement.tdAmountDebitTC
                    vdCreditCC  = tMovement.tdAmountCreditTC.
        else if (tMovement.tdAmountCreditCC <> 0 and
                 tMovement.tdAmountCreditCC <> ?) or
                (tMovement.tdAmountDebitCC  <> 0 and
                 tMovement.tdAmountDebitCC  <> ?)
             then assign vdDebitCC  = <M-12 RoundAmount
                                         (input  tMovement.tdAmountDebitCC (idUnroundedAmount), 
                                          input  viCompanyCCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>
                         vdCreditCC = <M-13 RoundAmount
                                         (input  tMovement.tdAmountCreditCC (idUnroundedAmount), 
                                          input  viCompanyCCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>.
             else do :
                 if tMovement.tdRateTCCC  = 0 or
                    tMovement.tdScaleTCCC = ? or
                    tMovement.tdRateTCCC  = 0 or
                    tMovement.tdScaleTCCC = ?
                 then do :
                     assign oiReturnStatus = -1
                            vcmessage      = trim(#T-5'Internal error: The input-record for the invoice-movement does not hold a proper rate fot the statutory-currency.':255(198000521)T-5#).
                     <M-56 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-871039':U (icFcMsgNumber), 
                         input  '':U (icFcExplanation), 
                         input  '':U (icFcIdentification), 
                         input  '':U (icFcContext), 
                         output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
                     Leave FOREACHTMOVEMENTBLOCK.
                 end. /* if tMovement.tdRateTCCC  = 0 or */
                 assign vdDebitCC  = <M-6 RoundAmount
                                         (input  tMovement.tdAmountDebitTC * tMovement.tdRateTCCC * tMovement.tdScaleTCCC (idUnroundedAmount), 
                                          input  viCompanyCCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>  
                        vdCreditCC = <M-54 RoundAmount
                                         (input  tMovement.tdAmountCreditTC * tMovement.tdRateTCCC * tMovement.tdScaleTCCC (idUnroundedAmount), 
                                          input  viCompanyCCId (iiCurrencyID), 
                                          input  ? (icCurrencyCode)) in BCInvoice>. 
            end. /* else do : */
    end. /* else do: */
        
    /* ===================================================================================================== */
    /* If tMovement is marked as WHT then we should not post on the control-account but on the different GLs */ 
    /* specified in CInvoiceWHT. We will call a separate submethod that will create the related postings     */
    /* ===================================================================================================== */
    if tMovement.tlMovementIsAboutWHT = true
    then do :    
        <M-38 run CreateCInvoiceMovementsWHT
           (input  tMovement.tdAmountDebitTC (idDebitTC), 
            input  tMovement.tdAmountCreditTC (idCreditTC), 
            input  vdDebitLC (idDebitLC), 
            input  vdCreditLC (idCreditLC), 
            input  vdDebitCC (idDebitCC), 
            input  vdCreditCC (idCreditCC), 
            output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
        if viFcReturnSuper <> 0 
        then assign oiReturnStatus = viFcReturnSuper.
        if viFcReturnSuper < 0
        then Leave FOREACHTMOVEMENTBLOCK.
    end. /* if tMovement.tlMovementIsAboutWHT = true */
    
    else do :
        /* ============================================================================================================= */
        /* if the current invoice is 'STAGED', we should check if at least one tCinvoiceStageUpdates record is available */
        /* If not, then we have no payment records for the stages yet, which means we should create them.                */
        /* ============================================================================================================= */
        if tCInvoice.tcNormalPaymentConditionType = {&PAYMENTCONDITIONPAYMENTTYPE-STAGED}
        then do:
            find first tCInvoiceStageUpdates where 
                       tCinvoiceStageUpdates.tiCInvoice_ID = tCInvoice.CInvoice_ID
                       no-error. 
            if tMovement.tiPostingLine_ID <> 0 and 
               tMovement.tiPostingLine_ID <> ? and 
               not available (tCinvoiceStageUpdates)
            then do:
                <Q-86 run PostingByPostingLineId (all) (Read) (NoCache)
                   (input tCInvoice.Company_ID, (CompanyId)
                    input tMovement.tiPostingLine_ID, (PostingLineId)
                    output dataset tqPostingByPostingLineId) in BPosting>
                for first tqPostingByPostingLineId:                            
                    <M-35 run CreateCInvoiceStageUpdate
                       (input  tCinvoice.Cinvoice_ID (iiCinvoiceID), 
                        input  tqPostingByPostingLineId.ttPostingDate (itPaymentDate), 
                        input  tMovement.tdAmountDebitTC - tMovement.tdAmountCreditTC (idMovementAmount), 
                        output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
                end. /* for first tqPostingByPostingLineId: */
           end. /* if tMovement.tiPostingLine_ID <> 0 and */
        end. /* if tCInvoice.tcNormalPaymentConditionType = {&PAYMENTCONDITIONPAYMENTTYPE-STAGED} */          
        
        /* ================================================================================================= */
        /* Get the IntercompanyCode linked to this BusinessRelation. This IntercoCode is used in the Posting */
        /* ================================================================================================= */    
        assign vcBusinessRelationCode        = tCInvoice.tcBusinessRelationCode
               vcBusinessRelationInterCoCode = "":U.
        if vcBusinessRelationCode <> "":U
        then do:
            <Q-47 run BusinessRelationByIDCodeIC (all) (Read) (Cache)
               (input ?, (BusinessRelationID)
                input vcBusinessRelationCode, (BusinessRelationCode)
                input ?, (BusinessRelationIntercoCode)
                input ?, (BusinessRelationIsActive)
                output dataset tqBusinessRelationByIDCodeIC) in BBusinessRelation>
            find first tqBusinessRelationByIDCodeIC no-error.
            if available tqBusinessRelationByIDCodeIC
            then assign vcBusinessRelationInterCoCode = tqBusinessRelationByIDCodeIC.tcBusinessRelationICCode.
        end. /* if vcBusinessRelationCode <> "":U */
    
        /* =================== */
        /* get control account */
        /* =================== */
        <Q-30 run GLById (all) (Read) (Cache)
           (input viCompanyId, (CompanyId)
            input tCInvoice.ControlGL_ID, (GLId)
            output dataset tqGLById) in BGL>
        find first tqGLById where tqGLById.tiGL_ID = tCInvoice.ControlGL_ID no-error.
        if not available tqGLById
        then do:
            assign oiReturnStatus = -1
                   vcmessage      = trim(#T-21'The system could not find a supplier control account record.':255(771986882)T-21#).
            <M-9 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-407283':U (icFcMsgNumber), 
                input  '':U (icFcExplanation), 
                input  '':U (icFcIdentification), 
                input  '':U (icFcContext), 
                output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
            leave FOREACHTMOVEMENTBLOCK.
        end. /* end of if not available tqGLById */
        
        /* ========================= */
        /* get division profile info */
        /* ========================= */
        if tqGLById.tlGLIsDivisionAccount and 
           tMovement.tcGLAccountDivisionCode = "":U
        then do:     
            <Q-74 run GetDivisionFromProfile (all) (Read) (NoCache)
              (input tCInvoice.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 oiReturnStatus = -3.
                <M-75 run SetMessage
                   (input  #T-49'The sub-account profile of the Supplier Control account is not defined.':150(894249329)T-49# (icMessage), 
                    input  '':U (icArguments), 
                    input  '':U (icFieldName), 
                    input  '':U (icFieldValue), 
                    input  'E':U (icType), 
                    input  3 (iiSeverity), 
                    input  '':U (icRowid), 
                    input  'QadFin-6771':U (icFcMsgNumber), 
                    input  '':U (icFcExplanation), 
                    input  '':U (icFcIdentification), 
                    input  '':U (icFcContext), 
                    output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
                leave FOREACHTMOVEMENTBLOCK.
            end. /* if not available tqDivisionFromProfile */
        end. /* end of if tqGLById.tlGLIsDivisionAccount and tDIMovement.tcGLAccountDivisionCode = "":U */    
        assign vcDivisionCode= if tqGLById.tlGLIsDivisionAccount
                               then if tMovement.tcGLAccountDivisionCode = "":U
                                    then if tCInvoice.tcDivisionCode = "":U and 
                                            available tqDivisionFromProfile
                                         then tqDivisionFromProfile.tcDivisionCode
                                         else tCInvoice.tcDivisionCode
                                    else tMovement.tcGLAccountDivisionCode
                               else "":U.
        
        /* ==================== */
        /* Get the CreditorType */
        /* ==================== */
        <Q-53 run SupplierForSICACreate (all) (Read) (Cache)
           (input tCInvoice.Company_ID, (CompanyId)
            input tCInvoice.Creditor_ID, (CreditorId)
            input tCInvoice.tcCreditorCode, (CreditorCode)
            output dataset tqSupplierForSICACreate) in BCreditor>
        find tqSupplierForSICACreate where
             tqSupplierForSICACreate.tcCreditorCode = tCInvoice.tcCreditorCode
             no-error.
        if available tqSupplierForSICACreate
        then assign vcCreditorTypeCode = tqSupplierForSICACreate.tcCreditorTypeCode.
        else assign vcCreditorTypeCode = '':U.

        /* ============================================= */
        /* Create the postingline on the control account */
        /* ============================================= */
        empty temp-table tDefaultSafsCI.
        create tDefaultSafsCI.
        assign tDefaultSafsCI.tcSafConceptCode = {&SAFCONCEPT-SUPPLIERTYPE}
               tDefaultSafsCI.tcSafCode        = vcCreditorTypeCode.
        <M-14 run AddControlPosting
           (input  tMovement.tcPostingRowId (icPostingtcRowid), 
            input  tqGLById.tcGLCode (icGLCode), 
            input  vcDivisionCode (icDivisionCode), 
            input  vcBusinessRelationInterCoCode (icIntercoBusinessRelationCode), 
            input  tCInvoice.tcCurrencyCode (icCurrencyCode), 
            input  tMovement.tdAmountDebitTC (idDebitTC), 
            input  vdDebitLC (idDebitLC), 
            input  vdDebitCC (idDebitCC), 
            input  tMovement.tdAmountCreditTC (idCreditTC), 
            input  vdCreditLC (idCreditLC), 
            input  vdCreditCC (idCreditCC), 
            input  (if length(tMovement.tcPostingText,'CHARACTER':U) = 0 then tCInvoice.CInvoiceCIText else tMovement.tcPostingText) (icText), 
            input  tCInvoice.Creditor_ID (iiMasterId), 
            input  tMovement.tiCInvoiceId (iiTransactionId), 
            input  if tCInvoice.CInvoiceExchangeRate = 0 then 1 else tCInvoice.CInvoiceExchangeRate (idExchangeRate), 
            input  if tCInvoice.CinvoiceRateScale = 0 then 1 else tCInvoice.CinvoiceRateScale (idExchangeRateScale), 
            input  if tCInvoice.CInvoiceCCRate = 0 then 1 else tCInvoice.CInvoiceCCRate (idPostingLineCCRate), 
            input  if tCInvoice.CInvoiceCCScale = 0 then 1 else tCInvoice.CInvoiceCCScale (idPostingLineCCScale), 
            input  '':U (icAllocationKey), 
            input  tCInvoice.tcCostCentreCode (icCostCentreCode), 
            input  tCInvoice.tcProjectCode (icProjectCode), 
            input  tDefaultSafsCI (tDefaultSafs), 
            output tMovement.tiPostingLine_ID (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 FOREACHTMOVEMENTBLOCK.
        
        /* ======================= */
        /* Create CInvoiceMovement */
        /* ======================= */
        if not can-find(first tCInvoiceMovement where
                              tCInvoiceMovement.tc_ParentRowid = tCInvoice.tc_Rowid and
                              tCInvoiceMovement.PostingLine_ID = tMovement.tiPostingLine_ID)
        then do:
            <M-25 run AddDetailLine
               (input  'CInvoiceMovement':U (icTable), 
                input  tCInvoice.tc_Rowid (icParentRowid), 
                output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if oiReturnStatus < 0 then Leave FOREACHTMOVEMENTBLOCK.
            assign tCInvoiceMovement.CInvoice_ID                = tMovement.tiCInvoiceId
                   tCInvoiceMovement.PostingLine_Id             = tMovement.tiPostingLine_ID
                   tCInvoiceMovement.CInvoiceMovementDiscountTC = tMovement.tdMovementDiscountTC
                   tCInvoiceMovement.CInvoiceMovementType       = {&MOVEMENTTYPE-MOVEMENT}.
                        
            /* ============================= */
            /* update the bank records first */
            /* ============================= */
            <M-32 run UpdateCInvoiceBankToPayTC
               (input  tMovement.tiCInvoiceId (iiCInvoiceId), 
                input  tCInvoice.CInvoiceBalanceDebitTC (idOldBalanceDebitTC), 
                input  tCInvoice.CInvoiceBalanceCreditTC (idOldBalanceCreditTC), 
                input  tMovement.tdAmountDebitTC (idMovementAmountDebitTC), 
                input  tMovement.tdAmountCreditTC (idMovementAmountCreditTC), 
                input  tMovement.tiBankNumber_ID (iiBankNumber_ID), 
                output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if viFcReturnSuper < 0
            then Leave FOREACHTMOVEMENTBLOCK.
            
            /* ========================================================================================== */
            /* create delayed tax posting lines and undo the tax posting lines for the payments if needed */
            /* ========================================================================================== */
            <M-80 run CreateCInvoiceMovementsDelTax
               (input  ilIsCallFromBankingEntryOrOIAdj (ilIsCallFromBankingEntryOrOIAdj), 
                input-output tCInvoiceVatDelayDelta (tCInvoiceVatDelayDelta), 
                output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
            if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
            then assign oiReturnStatus = viFcReturnSuper.
            if viFcReturnSuper < 0
            then Leave FOREACHTMOVEMENTBLOCK.
    
            /* ====================================================================================== */
            /* Update balance fields; if the originalbalance-Credit was filled then all updates of    */
            /* the balance will be on the credit fields allthough the CInvoice 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 tCInvoice.CInvoiceOriginalDebitTC <> ? and tCInvoice.CInvoiceOriginalDebitTC <> 0
            then assign tCInvoice.CInvoiceBalanceDebitTC = tCInvoice.CInvoiceBalanceDebitTC - tMovement.tdAmountCreditTC + tMovement.tdAmountDebitTC
                        tCInvoice.CInvoiceBalanceDebitLC = tCInvoice.CInvoiceBalanceDebitLC - vdCreditLC + vdDebitLC
                        tCInvoice.CInvoiceBalanceDebitCC = tCInvoice.CInvoiceBalanceDebitCC - vdCreditCC + vdDebitCC.
            else assign tCInvoice.CInvoiceBalanceCreditTC = tCInvoice.CInvoiceBalanceCreditTC - tMovement.tdAmountDebitTC + tMovement.tdAmountCreditTC
                        tCInvoice.CInvoiceBalanceCreditLC = tCInvoice.CInvoiceBalanceCreditLC - vdDebitLC + vdCreditLC
                        tCInvoice.CInvoiceBalanceCreditCC = tCInvoice.CInvoiceBalanceCreditCC - vdDebitCC + vdCreditCC.

            assign tCInvoice.CInvoiceBalanceTC  = tCInvoice.CInvoiceBalanceDebitTC - tCInvoice.CInvoiceBalanceCreditTC
                   tCInvoice.CInvoiceBalanceLC  = tCInvoice.CInvoiceBalanceDebitLC - tCInvoice.CInvoiceBalanceCreditLC
                   tCInvoice.CInvoiceBalanceCC  = tCInvoice.CInvoiceBalanceDebitCC - tCInvoice.CInvoiceBalanceCreditCC
                   tCInvoice.CInvoiceIsOpen     = (tCInvoice.CInvoiceBalanceTC <> 0 or tCInvoice.CInvoiceBalanceLC <> 0 or tCInvoice.CInvoiceBalanceCC <> 0)
                   tCInvoice.tc_Status          = (if tCInvoice.tc_Status = "":U then "C":U else tCInvoice.tc_Status)
                   tCInvoice.CInvoiceIsSelected = if vlIsPaySelUnconfirm = true then true else false.        
        end. /* if not can-find(first tCInvoiceMovement where */
    
    end. /* Not if tMovement.tlMovementIsAboutWHT = true */
    
    /* ========================================================================== */
    /* Update the HoldAmount of the invoice if it was provided in the input table */
    /* ========================================================================== */
    if tMovement.tdCInvoiceHoldAmountTC <> ?
    then assign tCInvoice.CInvoiceHoldAmountTC  = tMovement.tdCInvoiceHoldAmountTC
                tCInvoice.tc_Status             = (if tCInvoice.tc_Status = "":U then "C":U else tCInvoice.tc_Status).
        
end. /* for each tmovement */
END. /* FOREACHTMOVEMENTBLOCK */

/* ================================================================================================= */
/* 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 tCInvoiceVatDelayDelta)
then do:
    <M-16 run UpdateCInvoiceVatDelay
       (input  tCInvoiceVatDelayDelta (tCInvoiceVatDelayDelta), 
        input  ? (iiBJournalEntryID), 
        input  ? (ihBJournalEntryHandle), 
        output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
    if viFcReturnSuper < 0 or (viFcReturnSuper > 0 and oiReturnStatus = 0)
    then assign oiReturnStatus = viFcReturnSuper.
    if viFcReturnSuper < 0 then return.
end. /* if can-find(first tMoveDelTax) */

/* ============================ */
/* Update CInvoiceStage Records */
/* ============================ */
for each tMovement
    break by tMovement.tiCInvoiceId:
    if first-of(tMovement.tiCInvoiceId)
    then do:
        for each tCInvoiceStageUpdates where
                 tCInvoiceStageUpdates.tiCInvoice_ID = tMovement.tiCInvoiceId and
                 (tCInvoiceStageUpdates.tc_Status <> "":U or tMovement.tlIsUndoPayment):
            find first tCInvoiceStage where 
                       tCInvoiceStage.CInvoiceStage_ID = tCinvoiceStageUpdates.CInvoiceStage_ID
                       no-error.
            if available tCinvoiceStage   
            then do:
                if tMovement.tlIsUndoPayment
                then assign tCInvoiceStage.CInvoiceStageAmtAppliedTC = tCInvoiceStage.CInvoiceStageAmtAppliedTC - tCinvoiceStageUpdates.CDocInvoiceXrefStageAlloTC.
                else assign tCInvoiceStage.CInvoiceStageAmtAppliedTC = tCInvoiceStage.CInvoiceStageAmtAppliedTC + tCinvoiceStageUpdates.CDocInvoiceXrefStageAlloTC.
                assign tCinvoiceStage.tc_Status = (if tCInvoiceStage.tc_Status = "":U then "C":U else tCInvoiceStage.tc_Status).
            end.
        end. /* for each tCInvoiceStageUpdates where */
    end. /* if first-of(tMovement.tiCInvoiceId) */
end. /* end of update CinvoiceStage records */

/* ========================================================================================================= */
/* Normally we would here close the communication to BJournalEntry 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 oiReturnStatus < 0 
then do:
    /* Stop external instances */
    <M-76 run StopExternalInstances
       (output viFcReturnSuper (oiReturnStatus)) in BCInvoice>
    return.
end.
/* State the ID */
assign biBJournalEntryId = viBJournalEntryCIID.

/* ========================================================================== */
/* Create Q-CrossCompany postings that will be picked up later-on by a daemon */
/* ========================================================================== */
if can-find (first tNewQCrossCyPostingTable)    
then do :
    if viBQCrossCyPostingID = 0 or viBQCrossCyPostingID = ?
    then do:
        <I-57 {bFcStartAndOpenInstance
             &ADD-TO-TRANSACTION   = "true"
             &CLASS                = "BQCrossCyPosting"}>
    end. /* if viBQCrossCyPostingID = 0 */
    else do:
        <I-58 {bFcOpenInstance
             &CLASS           = "BQCrossCyPosting"}>
    end. /* if viBQCrossCyPostingID <> 0 */
    <M-59 run ApiCreateQCrossCyPosting
       (input  tNewQCrossCyPostingTable (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 tNewQCrossCyPostingTable) */