Monday, August 1, 2011

Create Electronic Payment Format - AX 2009

Electronic payments are being used heavily today. It is importnat to understand how these work and how to implement them as they save lots of time and even more paperwork. In addition, AX 2009 provides some out-of-the-box payment templates, but they are not very felxible and very often we need to create our own.

Now the good thing about creating our own is that we can inherit from two base classes. (1) VendOutPaym and (2) VendOutPaymRecord.

VendOutPaym is ussually used to create the header and closing records of a payment file. On the other hand, VendOutPaymRecord is used to create the the lines records of the payment file. So, if we have a payment journal (AP > Journals > Payments> Payment Journal) with 10 lines, we should see only one header line, (in my case) only one Bank line (after header), 10 line records (Payment journal lines) and one closing line with totals, got the idea?

So, we would have to create two classes. One to write the header and closing records and one to write the journal lines, ok?

Here is the first class to write header and closing records. Because in my file the empey spaces needed to be filled with only 0's, I created a method that's called getProcessedStr that takes a string and an integer. The string is the actual value that will be written into the file but needs extra 0's. The int is the total lenght of this record in the text file.




The method is static as it is used in both the header and line creation classes. In addition, there are other custom methods to get the Vendor Name, amouts, etc.

I will create another post this week where i will explain how to setup the electronic payment in AP.

class KUMVendOutPaym_SA extends VendOutPaym
{
    AmountCur                   total_Amount_Transactions;
    Counter                     total_Number_Transactions;
    Counter                     record_Count;
    Amount                      totalLinesAmount;
    str 10                      vendorNumber;
    str 30                      vendorName;
    int                         numOfLines;

    KMN_CurrencySouthAmerica    currencyMX;
    LedgerJournalTrans          gLedgerJournalTrans;

    DialogField                 dialogCurrency;
    DialogField                 dialogSendMail;


    #define.preHeader('$$AAPDSTD0152[PROD[NL$$')
    #define.CustIdNumberLen(12)

    #DEFINE.SysLastValuesCurrentVersion(1)
    #LOCALMACRO.SysLastValuesList
        currencyMX,
    #ENDMACRO

    #DEFINE.CurrentVersion(6)
    #LOCALMACRO.CurrentList
        currencyMX,
        total_Amount_Transactions,
        total_Number_Transactions,
        record_Count,
        rbcClientNumber,
        rbcClientName,
    #ENDMACRO
}


protected void calcLinesTotalAmount(Amount _amount)
{
    ;
    totalLinesAmount = totalLinesAmount + _amount;
}
public void close()
{
    ;
    file.writeExp(this.createFileTrailerRecord());
    setprefix(strfmt("@SYS73667", this.parmFilename()));

    if (printControlReport)
        this.printControlReport();
   

    if (printPaymAdvice)
        this.printPaymAdvice();
}

private int codepage()
{
    #Localcodepage
    ;
    return #cp_1252;
}

/// <summary>
///    Prepares the bank records for output to the export file.
/// </summary>
/// <returns>
///    A container.
/// </returns>
protected container createFileBankRecordDetails()
{
    #define.recType('2')
    #define.currTypeMX('MXN')

    container   bankRecord    = connull();
    str 1       recordType    = #recType;
    str 1       operationType;
    str 2       AccountType;
    str 3       currencyIndicator;
    str 3       keyCurrecny;
    str 4       branchNumber;
    str 18      amountCurrDebit;
    str 20      accountNumber;
    str 20      blank;


    BankAccountTable        bankAccountTable = this.getBankAccountTable();
    ;

    recordType          = strLFix(recordType, 1);
    operationType       = strLFix("1", 1);
    keyCurrecny         = strLFix("001", 3);
    amountCurrDebit     = strLFix(this.getAmountCurrDebit(18), 18);
    AccountType         = strLFix("01", 2);
    branchNumber        = strRfix(CompanyInfo::find().KMN_BranchId, 4);
    accountNumber       = strRfix(KUMVendOutPaym_SA::getProcessedStr(bankAccountTable.AccountNum, 20), 20);
    blank               = strLFix("", 20);

//    destinationDataCenter =   strLFix(bankAccountTable.CompanyPaymId, 5, #space);
//    originatorNumber      =   strLFix(VendPaymModeSpec::find(this.getUniquePaymModeTable().PaymMode).Specification, 10, #space);
//    fileCreationDate      =   strLFix(#zero + substr(date2Julian(systemdateget()), 3, 5), 6, #space);
//    fileCreationNumber    =   strLFix(num2Str0(this.getUniquePaymModeTable().LastSequenceNumber + 1, 4), 4, #space);
//    institutionNumber     =   strLFix(#zero + substr(bankAccountTable.RegistrationNum, strlen(bankAccountTable.RegistrationNum), -3), 4, #space);
//    branchTransitNumber   =   strLFix(substr(bankAccountTable.RegistrationNum, 1, 5), 5, #space);
//    accountNumber         =   strLFix(strReplace(bankAccountTable.AccountNum, '-', ''), 12, #space);
//    originatorShortNumber =   strLFix(substr(CompanyInfo::name(), 1, 15), 15, #space);

    if (currencyMX == KMN_CurrencySouthAmerica::Mexico)
    {
        currencyIndicator = #currTypeMX;
    }

    bankRecord        = conins(bankRecord, 1, recordType            +
                                              operationType         +
                                              keyCurrecny           +
                                              amountCurrDebit       +
                                              AccountType           +
                                              branchNumber          +
                                              accountNumber         +
                                              blank);

    return bankRecord;
}

/// <summary>
///    Prepares the header record for output to the export file.
/// </summary>
/// <returns>
///    A container.
/// </returns>
protected container createFileHeaderRecordDetails()
{
    #define.recType('1')
    #define.currTypeMX('MXN')

    container   headerRecord    =   connull();
    str 1       recordType      = #recType;
    str 1       layoutVersion;
    str 1       volume;
    str 1       fileChars;
    str 2       fileNature;
    str 3       currencyIndicator;
    str 4       seqFileNumber;
    str 6       paymentDate;
    str 12      customerIdNumber;
    str 20      fileDescription;
    str 36      companyName;
    str 40      instructionForPaymt;
    ;

    recordType          = strLFix(recordType, 1);
    customerIdNumber    = strRFix(KUMVendOutPaym_SA::getProcessedStr(CompanyInfo::find().KMN_CIN, 12), 12);
    paymentDate         = strLFix(this.getPaymentDate(), 6);
    seqFileNumber       = strLFix(this.getSequenceNumber(4), 4);
    companyName         = strLFix("Business Name", 36);
    fileDescription     = strLFix(this.getJournalDescName(), 20);
    fileNature          = strLFix("05", 2);
    instructionForPaymt = strLFix("", 40);
    layoutVersion       = strLFix("C", 1);
    volume              = strLFix("0", 1);
    fileChars           = strLFix("0", 1);

    if (currencyMX == KMN_CurrencySouthAmerica::Mexico)
    {
        currencyIndicator = #currTypeMX;
    }

    headerRecord        = conins(headerRecord, 1, recordType            +
                                                  customerIdNumber      +
                                                  paymentDate           +
                                                  seqFileNumber         +
                                                  companyName           +
                                                  fileDescription       +
                                                  fileNature            +
                                                  instructionForPaymt   +
                                                  layoutVersion         +
                                                  volume                +
                                                  fileChars);

    return headerRecord;
}

/// <summary>
///    Prepares a trailer record for output to the export file.
/// </summary>
/// <returns>
///    A container.
/// </returns><remarks />
protected container createFileTrailerRecord()
{
    //  CIBC EFT 80 Byte File Layout
    //  Trailer Record
    container   trailerRecord                   =   connull();

    #define.space(' ')
    #define.recType('4')

    str 1       recordType                      =   #recType;             // Trailer record
    str 3       keyCurrency                     =   "001";
    str 6       numOfCredits                    =   strLFix(this.getNumOfLines(6), 6);
    str 16      totalNumCredits                 =   strRFix(KUMVendOutPaym_SA::getProcessedStr(strrem(num2str(totalLinesAmount, 0, 2, 0, 0), "."),16), 16);
    str 6       numOfDebits                     =   strLFix(this.getNumOfLines(6), 6);
    str 16      totalNumDebits                  =   strLFix(totalNumCredits, 16);
    ;


    //detailCount         =   strLFix(num2Str0(this.parmTotal_Number_Transactions(0), 6), 6, #space);

    trailerRecord       =   conins(trailerRecord, 1, recordType         +
                                                     keyCurrency        +
                                                     NumOfCredits       +
                                                     totalNumCredits    +
                                                     numOfDebits        +
                                                     totalNumDebits);

    return trailerRecord;
}

public classId custVendOutPaymRecordRootClassId()
{
    ;
    return classnum(KUMVendOutPaymRecord_SA);
}

protected Object dialog()
{
    DialogRunbase   dialog = super();
    ;

    dialog.caption(this.interfaceName());
    this.dialogAddFileName(dialog);


    return dialog;
}

protected void dialogAddCurrency(DialogRunbase _dialog)
{
    DialogRunbase   dialog = _dialog;
    ;
    dialog.addGroup("@SYS62786");
    dialogCurrency  = dialog.addFieldValue(typeid(KMN_CurrencySouthAmerica), currencyMX, "@SYS7572");
}
public void generatePaymentLines()
{
    #OCCRetryCount
    LedgerJournalTrans              ledgerJournalTrans;
    KUMVendOutPaymRecord_SA         vendOutPaymRecord_SA;
    boolean                         ok = true;
    ;

    numOfLines = 0;
    totalLinesAmount = 0;

    try
    {
        ttsbegin;

        setprefix("@SYS17561");
        queryRun.reset();
        while (queryRun.next())
        {
            ledgerJournalTrans = queryRun.get(tablenum(LedgerJournalTrans));

            vendOutPaymRecord_SA = CustVendOutPaymRecord::construct(ledgerJournalTrans.PaymMode,
                                                                    ledgerJournalTrans.PaymSpec,
                                                                    this,
                                                                    this.vendPaym(ledgerJournalTrans));
            vendOutPaymRecord_SA.parmFile(file);

            setprefix(strfmt("@SYS66088",
                             ledgerJournalTrans.TransDate,
                             ledgerJournalTrans.Voucher,
                             ledgerJournalTrans.AccountNum));

            numOfLines++;
            this.calcLinesTotalAmount(ledgerJournalTrans.AmountCurDebit);

            if (vendOutPaymRecord_SA.checkValues(ledgerJournalTrans, this.parmProgress()))
            {
                if (!vendOutPaymRecord_SA.parmSkipPaymRecord())
                {
                    vendOutPaymRecord_SA.output();
                   outPaymRecordList.addEnd(vendOutPaymRecord_SA);
 this.updateLedgerJournalTrans(ledgerJournalTrans, vendOutPaymRecord_SA, true);                   this.trackSequenceOnPaymMode(CustVendPaymModeTable::findCommon(ledgerJournalTrans, true));
                }
                else
                {
                    continue;
                }
            }
            else
            {
                ok = false;
            }

        }

        if (!ok)
        {
            throw error("@SYS18447");
        }

        ttscommit;
    }
    catch (Exception::Deadlock)
    {
        retry;
    }

    catch (Exception::UpdateConflict)
    {
        if (appl.ttsLevel() == 0)
        {
            if (xSession::currentRetryCount() >= #RetryNum)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }
}

protected str getAmountCurrDebit(int len)
{
    LedgerJournalTrans  _ledgerJournalTrans;
    Amount              AmtLedgerTrans;
    Amount              totalAmtLedgerTrans;
    str                 strAmtPlaceHolder;
    str                 strAmtRem;
    str                 strTotalAmtSum;
    int                 _strLen;
    ;


    while select _ledgerJournalTrans where _ledgerJournalTrans.JournalNum == this.parmLedgerJournalId()
    {
        AmtLedgerTrans = _ledgerJournalTrans.AmountCurDebit;
        totalAmtLedgerTrans = totalAmtLedgerTrans + AmtLedgerTrans;
    }

    strAmtPlaceHolder = num2str(totalAmtLedgerTrans,4, 2, 0, 0);
    strAmtRem = strRem(strAmtPlaceHolder, ".");
    _strLen = strLen(strAmtRem);

    if(_strLen == 2)
        strAmtRem = strAmtRem + '00';

    strTotalAmtSum = KUMVendOutPaym_SA::getProcessedStr(strAmtRem, len);

    return strTotalAmtSum;
}

/// <summary>
///    Returns the Bank Account Table.
/// </summary>
/// <returns>
///    The Bank Account Table.
/// </returns>
public BankAccountTable getBankAccountTable()
{
    ;

    return BankAccountTable::find(CompanyInfo::find().Bank);
}




/// <summary>
///    Returns the name of the journal
/// </summary>
/// <returns>
///    A string.
/// </returns>
protected str getJournalDescName()
{
    ;
    return LedgerJournalTable::find(this.parmLedgerJournalId()).Name;
}

protected LedgerJournalTrans getLedgerJournalTrans()
{
    LedgerJournalTrans  _ledgerJournalTrans;
    ;

    select * from _ledgerJournalTrans
        where _ledgerJournalTrans.JournalNum == this.parmLedgerJournalId();

    return _ledgerJournalTrans;
}

protected str getNumOfLines(int charsToFill)
{
    str ret;
    ;

    ret = KUMVendOutPaym_SA::getProcessedStr(int2str(numOfLines),charsToFill);
    //ret = ret + int2str(numOfLines);
    return ret;
}

protected str getPaymentDate()
{
    TransDate_MX            paymentDate;
    LedgerJournalTrans      ledgerJournalTrans;
    str                     strPaymDate;
    ;

   
    while select ledgerJournalTrans where ledgerJournalTrans.JournalNum == this.parmLedgerJournalId()
    {
        paymentDate = ledgerJournalTrans.TransDate;
        break;
    }

    if(paymentDate)
        strPaymDate = date2str(paymentDate,
                                123,
                                DateDay::Digits2,
                                DateSeparator::None,
                                DateMonth::Digits2,
                                DateSeparator::None,
                                DateYear::Digits2);


    return strPaymDate;
}

/// <summary>
///    Queries VendPaymModeTable and returns next available sequence number + 0's
/// </summary>
/// <returns>
///    A string.
/// </returns>
protected str getSequenceNumber(int numCharsToFill)
{
    LedgerJournalTrans          _ledgerJournalTrans;
    PaymentSequenceNum          _latSequenceNumber;
    int                         _intSequence;
    int                         _placeHolder;
    str                         _strSequence;
    str                         _zero;
    str                         ret;
    ;

    while select _ledgerJournalTrans where _ledgerJournalTrans.JournalNum == this.parmLedgerJournalId()
    {
        _latSequenceNumber = VendPaymModeTable::find(_ledgerJournalTrans.PaymMode).LastSequenceNumber;
        break;
    }

    if(_latSequenceNumber)
    {
        _intSequence =  _latSequenceNumber;
        //_strSequence = int2str(_intSequence);
        _placeHolder = strlen(int2str(_intSequence));

        if(_placeHolder != 4)
        {
            _zero = this.getZeroString(4, int2str(_intSequence));
            ret = _zero + int2str(_intSequence);
        }
        else
            ret = int2str(_intSequence);
    }
    else
    {
        ret = '0001';
        //KMN_LocalizationSetInfoErrors::routeMessage(KMN_ErrorType::NoSequence, KMN_InfoErrorOutputType::Error);
    }
    return ret;
}

/// <summary>
///    Returns the Royal Bank of Canada (RBC) client number.
/// </summary>
/// <returns>
///    The RBC client number.
/// </returns>
public str getVendorNumber()
{
    ;

    return vendorNumber;
}

public PaymInterfaceName interfaceName()
{
    ;
    return 'EFT Mexico';
}
public void open()
{
    ;
    // Open file for text-output

    file = CustVendOutPaym::newFile(filename, this.codepage());

    if (!file || file.status() != IO_Status::Ok)
    {
        // Error when opening file %1
        throw error(strfmt("@SYS73665", filename));
    }

    this.parmVendName(strLFix(CompanyInfo::find().Name, 30));
    this.getVendorNumber();
    if (!this.validateHeaderValues())
    {
        // Update has been canceled.
        throw(error(strfmt("@SYS18738", this.getUniquePaymModeTable().PaymMode)));
    }
    else
    {
                file.write(this.createFileHeaderRecordDetails());
               file.write(this.createFileBankRecordDetails());
    }
}

public KMN_CurrencySouthAmerica parmCurrency(KMN_CurrencySouthAmerica _currency = currencyMX)
{
    ;
    currencyMX = _currency;

    return currencyMX;
}

public LedgerJournalTrans parmLedgerJournalTrans(LedgerJournalTrans _ledgerJournalTrans = gLedgerJournalTrans)
{
    ;
    gLedgerJournalTrans = _ledgerJournalTrans;
    return gLedgerJournalTrans;
}

public str parmVendName(str _vendname = vendorName)
{
    vendorName = _vendname;
    return vendorName;
}

public boolean validate()
{
    #define.MexicanDollarISO('MXN')
    Currency            currency;
    BankAccountTable    bankAccountTable;
    LedgerJournalId     _ledgerJournalId;
    LedgerJournalTrans  _ledgerJournalTrans ;
    boolean             ok = true;
    boolean             currencyOk = false;
    boolean             noMexicanCurrency = true;

    ;

    bankAccountTable = this.getBankAccountTable();

    _ledgerJournalTrans = this.getLedgerJournalTrans();
    if(!_ledgerJournalTrans)
        ok = checkFailed(strfmt("@KUM308"));
//    else
//    {
//        if(!_ledgerJournalTrans.DocumentDate)
//            ok = checkFailed(strfmt("@KUM309"));
//    }

    if (!bankAccountTable)
    {
        ok = checkFailed(strfmt("@SYS26720", accountId));
    }

    if (ok)
    {
        // If we are only paying mexican currency transactions
        if (currencyMX == KMN_CurrencySouthAmerica::Mexico)
        {
            // Verify that the currency of the bank is the same as the currency code for the mexica peso ISO code (MXN).
            currency.selectForUpdate(false);
            while select CurrencyCode from currency where currency.CurrencyCodeISO == #MexicanDollarISO
            {
                noMexicanCurrency = false;
                if (currency.CurrencyCode == bankAccountTable.CurrencyCode)
                {
                    currencyOk = true;
                    break;
                }
            }

            if (noMexicanCurrency)
            {
                // There is not a currency code with the Mexican ISO currency code of 'MXN'.
                ok = checkFailed("@SYS98121");
            }

            if (!currencyOk)
            {
                // The currency code assigned to bank '%1' must be a Mexican currency.
                ok = checkFailed(strfmt("@SYS98120", this.parmBankAccountID()));
            }
        }

    }

    if (ok)
    {
        if (!filename)
        {
            ok = checkFailed("@SYS18624");
        }

        if (WinAPI::fileExistsClient(filename))
        {
            if(Box::yesNo(strfmt("@SYS60148", filename), DialogButton::Yes) == DialogButton::No)
            {
                ok = false;
            }
        }
    }

    return ok;
}

/// <summary>
///    Validates values that are required by the export format.
/// </summary>
/// <returns>
///    true if validation succeeds; otherwise, false.
/// </returns>
/// <remarks>
///       The following details are validated:
///
///    <list type="bullet">
///       <item>
///          <description>Methods of payment - Vendor: Last file number is not equal or greater than 9999.
///          </description>
///       </item>
///       <item>
///          <description>Company information: Company name is not blank.
///          </description>
///       </item>
///       <item>
///          <description>Bank account: Company ID is not blank.
///          </description>
///       </item>
///    </list>
///       ///   If any of these validations fail, an appropriate error message is provided and the file export does not occur.
///
/// </remarks>
protected boolean validateHeaderValues()
{
    #DEFINE.allzeros('0000000000')
    boolean ok = true;
    ;

    // The next last file number used for this format will exceed 9999.
    if (this.getUniquePaymModeTable().LastSequenceNumber + 1 > 9999)
    {
        // Methods of payment - %1, export format requires that the last file number cannot exceed 9999
        ok = checkFailed(strfmt("@SYS98755", this.getUniquePaymModeTable().PaymMode));
    }

    // Company Name field is blank.
    if (strlen(strltrim(this.parmVendName())) < 1)
    {
        // Methods of payment - %1, export format requires a non-blank Company name
        ok = checkFailed(strfmt("@SYS98756", this.getUniquePaymModeTable().PaymMode));
    }

    // The Comany ID value for the selected bank is not valid.
    if (this.getVendorNumber() == #allZeros)
    {
        // Methods of payment - %1, export format requires a valid Company ID for bank account: %2
        ok = checkFailed(strfmt("@SYS98757", this.getUniquePaymModeTable().PaymMode,
                                         this.getBankAccountTable().AccountID));
    }
    return ok;
}




/// <summary>
///    Returns a record with 0's to the left
/// </summary>
/// <returns>
///    A string
/// </returns>
public static str getProcessedStr(str objectStr, int specLen)
{
    str                         localObjectStr2;
    str                         zero;
    int                         realLen = 0;
    int                         resultLen = 0;
    int                         i;
    int                         x = 0;
    boolean                     ok = true;
    ;

    if(objectStr == "0")
        x = 1;

    realLen = strLen(objectStr);
    if(realLen < specLen)
    {
        resultLen = specLen - realLen;
        ok = false;
    }

    if(ok)
        return objectStr;
    else
    {
        for(i = x; i < resultLen; i++)
            zero = zero + '0';

        localObjectStr2 = zero + objectStr;
        return localObjectStr2;
    }

}


The following is the clas the writes the journal lines:

class KUMVendOutPaymRecord_SA extends VendOutPaymRecord
{
    #define.interfaceName('Mexico EFT Record')
    #define.bankAccountType('Banamex')
    #define.spaces(' ')
    AddressCountryRegionISOCode     isoCode;
    KMN_CurrencySouthAmerica        currencyMX;
    LedgerJournalTrans              ledgerJournalTrans;
    BankAccount                     bankAccount;
    VendName                        vendName;
    container                       rbcBasicPaymentRecord;
    str 218                         basicPaymentRecord;
    boolean                         skipPaymRecord;
    Amount                          paymt;
}

/// <summary>
///    Validates that the <c>custVendPaym.paymDate</c> is not less than or greater than 173 days from the current system date.
/// </summary>
/// <returns>
///    true if validation succeeds; otherwise, false.
/// </returns>
protected boolean checkPaymentDate()
{
    #define.MaxDaysPastOrFuture(173)

    boolean     ok          = true;
    date        testDate    = systemdateget();
    ;

    //  payment date cannot be more than 173 days in the past or the future.
    if (abs(custVendPaym.paymDate() - testDate) > #MaxDaysPastOrFuture)
    {
        // Methods of payment - %1, export format requires all payment due dates to be not more than 173 days in the past or in the future.
        ok =  checkFailed(strfmt("@SYS98754", this.parmCustVendPaym().ledgerJournalTrans().PaymMode));
    }

    return ok;
}
public boolean checkValues(LedgerJournalTrans _ledgerJournalTrans     = null,
                           RunbaseProgress    _progress               = null,
                           BankAccount        _bankAccount            = '')

{
    #define.MexicanPesoISO('MXN')
    LedgerJournalId                 ledgerJournalId;
    boolean                         ok = true;
    VendBankAccount                 vendBankAccount;
    Currency                        currency;
    boolean                         currencyOk = false;
    boolean                         noMexicanCurrency = true;
    ;

    this.parmLedgerJournalTrans(_ledgerJournalTrans);
    changecompany (custVendPaym.ledgerJournalTrans().Company)
    {
        // Only transactions with Debit Amounts can be used from Accounts Payable
        if (custVendPaym.paymAmountInSendersCurrency() <= 0)
        {
            // Payment  must be a debit amount greater than zero.
            ok = checkFailed(strfmt("@SYS98765", custVendPaym.ledgerJournalTrans().AccountNum));
        }

        ledgerJournalId = this.getJournalDescName();
        if(!ledgerJournalId || ledgerJournalId == '0')
            ok = checkFailed(strfmt("@KUM316", custVendPaym.ledgerJournalTrans().JournalNum));

        if (custVendPaym.custVendTable().BankAccountId)
        {
            vendBankAccount = VendBankAccount::find(custVendPaym.ledgerJournalTrans().AccountNum, this.parmCustVendPaym().custVendTable().BankAccountId);
            if (vendBankAccount)
            {
                if (!vendBankAccount.RegistrationNum)
                {
                    // Bank routing number on account '%1' for vendor '%2' is missing.
                    ok = checkFailed(strfmt("@SYS98758", vendBankAccount.AccountID, custVendPaym.ledgerJournalTrans().AccountNum));
                }

                if (!vendBankAccount.AccountNum)
                {
                    // Bank account number on account '%1' for vendor '%2' is missing.
                    ok = checkFailed(strfmt("@SYS82529", vendBankAccount.AccountID, custVendPaym.ledgerJournalTrans().AccountNum));
                }

//                isoCode = AddressCountryRegion::find(vendBankAccount.CountryRegionId).isOcode;
//                if (!(isoCode == #MexicanPesoISO))
//                {
//                    warning(strfmt("@KUM315") );
//                    this.parmSkipPaymRecord(true);
//                }
            }
            else
            {
                // A bank account has not been set up for the vendor %1.
                ok = checkFailed(strfmt("@SYS98116", custVendPaym.ledgerJournalTrans().AccountNum));
            }
        }
        else
        {
            // A bank account has not been set up for the vendor %1.
            ok = checkFailed(strfmt("@SYS98116", custVendPaym.ledgerJournalTrans().AccountNum));
        }


        currencyMX = custVendOutPaym.parmCurrency();
        if (currencyMX == KMN_CurrencySouthAmerica::Mexico)
        {
            // Verify that the currency of the voucher is the same as the currency code for the Mexican Dollar ISO code (MXN).
            currency.selectForUpdate(false);
            while select CurrencyCode from currency where currency.CurrencyCodeISO == #MexicanPesoISO
            {
                currencyOk = false;
                if (currency.CurrencyCode == custVendPaym.ledgerJournalTrans().currencyCode())
                {
                    currencyOk = true;
                    break;
                }
            }


            if (!currencyOk)
            {
                // Payments must be in a currency with the Mexican ISO currency code of 'MXN'.
                warning(strfmt("@KUM314"));
                this.parmSkipPaymRecord(true);
            }
        }

        if (!this.parmCustVendPaym().ledgerJournalTrans().PaymSpec)
        {
            // Payment specification must be specified for method of payment '%1'.
            ok = checkFailed(strfmt("@SYS98763", this.parmCustVendPaym().ledgerJournalTrans().PaymMode, custVendPaym.ledgerJournalTrans().AccountNum));
        }

        ok  = this.checkPaymentDate()   && ok;

    }

    return ok;
}

/// <summary>
///    Record Type
/// </summary>
protected void fillField01()
{
    ;

    this.strInsert('3', 1);
}
/// <summary>///    Operation Type/// </summary>
protected void fillField02()
{
    ;

    this.strInsert('0', 2);
}

/// <summary>
///    Key CUrrency
/// </summary>
protected void fillField03()
{
    ;
    this.strInsert('001', 3);
}

/// <summary>
///    Amount
/// </summary>
protected void fillField04()
{
    LedgerJournalTrans  _ledgerJournalTrans;
    str 18 amount;
    ;
    _ledgerJournalTrans = this.parmLedgerJournalTrans();
    amount = strRFix(KUMVendOutPaym_SA::getProcessedStr(strrem(num2str(_ledgerJournalTrans.AmountCurDebit, 0, 2, 0, 0), "."),18), 18);
    this.strInsert(amount, 6);
}

/// <summary>
///    Account Type
/// </summary>
protected void fillField05()
{
    ;
    this.strInsert('03', 24);
}

/// <summary>
///    Account Number
/// </summary>
protected void fillField06()
{
    BankAccount _bankAccount;
    ;
    _bankAccount = strRFix(KUMVendOutPaym_SA::getProcessedStr(this.parmBankAccount(), 20),20);
    this.strInsert(_bankAccount, 26);
}

/// <summary>
///    Alphanumeric Reference - Ledger Journal Name
/// </summary>
protected void fillField07()
{
    str 40 _ledgerJournalId;
    ;

    _ledgerJournalId = strLFix(this.getJournalDescName(), 40);
    this.strInsert(_ledgerJournalId, 46);
}

/// <summary>
///    Beneficiary - Vend Name
/// </summary>
protected void fillField08()
{
    str 55 _vendName;
    ;

    _vendName = strLFix(this.getVendorName(), 55);
    this.strInsert(_vendName, 86);
}

/// <summary>
///    Instructions - JournalTableName
/// </summary>
protected void fillField09()
{
    str 40 _ledgerJournalId;
    ;

    _ledgerJournalId = strLFix(this.getJournalDescName(), 40);
    this.strInsert(_ledgerJournalId, 141);
}

/// <summary>
///    EFT Description
/// </summary>
protected void fillField10()
{
    ;
    this.strInsert(strrep(#spaces, 24), 181);
}

/// <summary>
///    Bank Code
/// </summary>
protected void fillField11()
{
    ;
    this.strInsert(strrep(#spaces, 4), 205);
}

/// <summary>
///    Numerical Reference
/// </summary>
protected void fillField12()
{
    ;
    this.strInsert(strrep(#spaces, 7), 209);
}

/// <summary>
///    Term
/// </summary>
protected void fillField13()
{
    ;
    this.strInsert('00', 216);
}

/// <summary>
///    Controls the data preparation and organization for each record in the export file.
/// </summary>
protected void fillRecord()
{
    ;

    this.fillField01();
    this.fillField02();
    this.fillField03();
    this.fillField04();
    this.fillField05();
    this.fillField06();
    this.fillField07();
    this.fillField08();
    this.fillField09();
    this.fillField10();
    this.fillField11();
    this.fillField12();
    this.fillField13();

}

protected LedgerJournalId getJournalDescName()
{
    LedgerJournalTrans  _ledgerJournalTrans;
    ;

    _ledgerJournalTrans = this.parmLedgerJournalTrans();
    return LedgerJournalTable::find(_ledgerJournalTrans.JournalNum).Name;
}

protected VendName getVendorName()
{
    LedgerJournalTrans  _ledgerJournalTrans;
    ;

    _ledgerJournalTrans = this.parmLedgerJournalTrans();
    return VendTable::find(_ledgerJournalTrans.AccountNum).NameKana;

}

/// <summary>
///    Initializes the class properties that are required for each record in the file export.
/// </summary>
protected void initRecord()
{
    ;
    this.setVendorBankAccount();
    rbcBasicPaymentRecord   =   connull();
    basicPaymentRecord      =  strrep(#spaces, 218);
}
public PaymInterfaceName interfaceName()
{
    ;
    return #interfaceName; //Comes from class declaration
}

public void output()
{
    ;

    //custVendOutPaym.total(custVendPaym.paymAmountInForeignCurrency());
    this.initRecord();
    this.fillRecord();
    rbcBasicPaymentRecord = conins(rbcBasicPaymentRecord, 1, basicPaymentRecord);
    file.write(rbcBasicPaymentRecord);
}

public BankAccount parmBankAccount(BankAccount _bankAccount = bankAccount)
{
    ;
    bankAccount = _bankAccount;
    return bankAccount;
}

public LedgerJournalTrans parmLedgerJournalTrans(LedgerJournalTrans _ledgerJournalTrans = ledgerJournalTrans)
{
    ;
    ledgerJournalTrans = _ledgerJournalTrans;
    return ledgerJournalTrans;
}

public boolean parmSkipPaymRecord(boolean _skipPaymRecord = skipPaymRecord)
{
    skipPaymRecord = _skipPaymRecord;
    return skipPaymRecord;
}

protected void setVendorBankAccount()
{
    LedgerJournalTrans      _ledgerJournalTrans;
    VendBankAccount         bankAccountTable;
    VendTable               vendTable;
    ;

    _ledgerJournalTrans = this.parmLedgerJournalTrans();
    vendTable = VendTable::find(_ledgerJournalTrans.AccountNum);
    this.parmBankAccount(VendBankAccount::find(vendTable.AccountNum, vendTable.BankAccount, false).AccountNum);
}

/// <summary>
///    Writes the supplied data at the specified position in the payment record.
/// </summary>
/// <param name="_fieldValue">
///    The data to write.
/// </param>
/// <param name="_fieldPosition">
///    The position at which to write.
/// </param>
protected void strInsert(str _fieldValue, int _fieldPosition)
{
    str hello;
    ;

    basicPaymentRecord = strpoke(basicPaymentRecord, _fieldValue, _fieldPosition);
    hello = "";
}

1 comment:

  1. Thanks for sharing. This sort of also applies to the CustPaym-regime, as well.

    ReplyDelete

Thank you for your thoughts. Your comment will appear in my blog shortly after review.

Have a great day!