BLVCKFX
3/11/2020 - 7:43 PM

Import bank group with progress bar

Custom batch to import bank group with progress bar. #SADA =>A_BankGroupImport

A_BankGroupImport.PNG

class A_BankGroupImport extends RunBaseBatch
{
    CommaTextIO                                 importFile;
    Counter                                     progressCounter;
    Counter                                     icounter;
    boolean                                     processOK;

    DialogRunbase                               dialog;
    DialogField                                 dialogFilename;

    Filename                                    filename;

    #define.CurrentVersion(1)
    #localmacro.CurrentList
        filename
    #endmacro
    #isoCountryRegionCodes
    #file
    #macrolib.AviFiles
}


/// <summary>
///    Returns false.
/// </summary>
/// <returns>
///    Always returns false.
/// </returns>
/// <remarks>
///    This method must be in this class because it is called from the <c>dialogRunbase</c> class.
/// </remarks>
public boolean canGoBatch()
{
    return false;
}


/// <summary>
///    Determines whether the class is shown in the list of the <c>Journal</c> types.
/// </summary>
/// <returns>
///    true if the class is shown in the list of <c>Journal</c> types; otherwise, false.
/// </returns>
/// <remarks>
///    A class that can be used in a batch journal is a class where the same parameters can be used
///    repeatedly. The dialog can be shown and the parameters can be changed but parameters of some
///    classes might build on data that is only valid for a short time. Not all classes can be run two
///    times with the same parameters. If the <c>canGoBatch</c> method returns false, this method will not
///    have any effect.
/// </remarks>
protected boolean canGoBatchJournal()
{
    return true;
}


/// <summary>
///    Returns a class that contains the methods that are described by the <c>RunBaseDialogable</c>
///    interface.
/// </summary>
/// <returns>
///    A class that contains the methods that are described by the <c>RunBaseDialogable</c> interface.
/// </returns>
/// <remarks>
///    A dialog can be either built by using the <c>Dialog</c> class or by using a class that is created
///    in the Application Object Tree (AOT).
/// </remarks>
public Object dialog()
{
    dialog = new DialogRunbase("@RNS260", this);

    dialogFilename = dialog.addFieldValue(extendedTypeStr(FilenameOpen), filename, "@SYS16423");

    dialog.allowUpdateOnSelectCtrl(true);

    this.dialogSelectCtrl();

    return dialog;
}


/// <summary>
///    When using the <c>dialog</c> class for dialog, this method is called whenever a control is selected.
/// </summary>
/// <remarks>
///    To enable this callback, the <c>allowUpdateOnSelectCtrl</c> method must have been set to true.
/// </remarks>
public void dialogSelectCtrl()
{
    super();
}


public Filename fileName(Filename _filename = filename)
{
    ;
    filename = _filename;
    return filename;
}


public boolean getFromDialog()
{
    filename                          = dialogFilename.value();

    return super();
}


protected void openFile(str _fileOpen = #io_read)
{
    ;

    importFile = new CommaTextIO(filename, _fileOpen, 1252);

    if (! importFile)
    {
        throw error(strFmt("@SYS18678", filename));
    }
}


public container pack()
{
    return [#CurrentVersion,#CurrentList];
}


/// <summary>
/// Update the progress.
/// </summary>
/// <param name="_incCount">
/// Indicates if the count of imported records should be updated.
/// </param>
protected void progressUpdate(boolean _incCount = 1)
{
    this.progressUpdateInt(_incCount ? 1 : 0);
}


/// <summary>
/// Update the progress.
/// </summary>
/// <param name="_incCount">
/// The number of records imported.
/// </param>
protected void progressUpdateInt(int _incCount = 1)
{
    progressCounter += _incCount;
    progress.setCount(progressCounter);
    progress.setText(strFmt("@SYS52615",progressCounter));
}


protected void readFile()
{
    BankGroup                       bankGroup;
    LogisticsPostalAddress          postalAddress;
    LogisticsAddressZipCode         zipCode;

    container                       readCon;
    int                             totalRecords = 0; //Counter for total records
    int                             counter = 0; //Counter for number of records processed
    str 5                           abi, cab;
    LogisticsAddressCity            city;
    LogisticsAddressZipCodeId       zipCodeId;
    LogisticsAddressStreet          street;
    LogisticsAddressCountyId        county;
    Description50                   branchName;
    Name                            bankName;

    #characters

    setprefix("@RNS260");

    info("@SYS4128" + ' ' + filename);
    this.openFile();

    importFile.inRecordDelimiter(#delimiterEnter);
    importFile.inFieldDelimiter(#semicolon);

    readcon = importFile.read();
    while ((importFile.status() == IO_Status::Ok))
    {
        this.progressUpdateInt();
        readcon = importFile.read();
        totalRecords++;
        abi             = conpeek(readcon, 1);
        cab             = conpeek(readcon, 2);
        bankName        = conpeek(readcon, 3);
        branchName      = conpeek(readcon, 4);
        street          = conpeek(readcon, 5);
        city            = conpeek(readcon, 6);
        zipCodeId       = conpeek(readcon, 7);
        county          = conpeek(readcon, 8);

        if (strLen(strFmt("%1%2",abi,cab)) != 10)
            continue;

        if (BankGroup::exist(strFmt("%1%2",abi,cab)))
        {
            bankGroup = BankGroup::find(strFmt("%1%2",abi,cab),true);
            if (!bankGroup.validateDelete())
                continue;

            bankGroup.delete();
        }

        bankGroup.clear();
        bankGroup.initValue();
        bankGroup.BankGroupId       = strFmt("%1%2",abi,cab);
        bankGroup.RegistrationNum   = bankGroup.BankGroupId;
        bankGroup.Name              = bankName;
        bankGroup.BranchName        = branchName;
        bankGroup.CompanyPaymId     = abi;
        bankGroup.CurrencyCode      = CompanyInfo::standardCurrency();
        bankGroup.Location          = LogisticsLocation::create(bankName).RecId;

        postalAddress.initValue();
        postalAddress.City              = city;
        postalAddress.Street            = street;
        postalAddress.CountryRegionId   = CompanyInfo::find().postalAddress().CountryRegionId;
        postalAddress.County            = county;
        postalAddress.ZipCode           = zipCodeId;
        postalAddress.Location          = bankGroup.Location;

        zipCode = LogisticsAddressZipCode::findBestMatch(postalAddress, false);
        if (zipCode)
        {
            postalAddress.State             = zipCode.State;
            postalAddress.County            = zipCode.County;
            postalAddress.CountryRegionId   = zipCode.CountryRegionId;
        }
        else
        {
            // No exact match - try to fill in empty fields based on not exact matches.
            zipCode = LogisticsAddressZipCode::findBestMatch(postalAddress);
            if (!postalAddress.City             && zipCode)
            {
                postalAddress.City              = zipCode.City;
            }
            if (!postalAddress.State            && zipCode)
            {
                postalAddress.State             = zipCode.State;
            }
            if (!postalAddress.County           && zipCode)
            {
                postalAddress.County            = zipCode.County;
            }
            if (!postalAddress.CountryRegionId  && zipCode)
            {
                postalAddress.CountryRegionId   = zipCode.CountryRegionId;
            }
        }

        postalAddress.Address = LogisticsPostalAddress::formatAddress(postalAddress.Street, postalAddress.zipCode, postalAddress.city, postalAddress.countryRegionId, postalAddress.state, postalAddress.county);
        if (!postalAddress.validateWrite())
            continue;

        postalAddress.insert();

        if (!bankGroup.validateWrite())
            continue;

        bankGroup.insert();
        counter++;
    }

    info(strfmt("@SYS105159",totalRecords,totalRecords - counter));
    processOK = true;
}


public void run()
{
    #OCCRetryCount
    if (! this.validate())
        throw error("");

    try
    {
        startLengthyOperation();
        if (! progress)
        {
            progress = RunbaseProgress::construct(1, null);
        }

        progress.setCaption("@RNS260");
        progress.setTotal(icounter);
        progress.setAnimation(#AviFilemove);

        progress.updateInterval(1);
        ttsbegin;
        progressCounter = 0;
        this.readFile();
        if (processOK)
        {
            ttscommit;
        }
        else
        {
            ttsabort;
        }

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


/// <summary>
///    Determines whether the batch task is run on the server or on a client.
/// </summary>
/// <returns>
///    Always returns false.
/// </returns>
/// <remarks>
///    Your classes that extend this class must override the <c>runsImpersonated</c> method and return
///    <c>false</c>, if you want those tasks to run on a client.
/// </remarks>
public boolean runsImpersonated()
{
    return true;
}


public boolean unpack(container _packedClass)
{
    Integer     version = conPeek(_packedClass,1);

    switch (version)
    {
        case #CurrentVersion:
            [version,#CurrentList] = _packedClass;
            break;
        default :
            return false;
    }

    return true;
}


public boolean validate(Object _calledFrom = null)
{
    boolean ret = true;
    ;
    if (! filename)
    {
        ret = checkFailed("@SYS18624");
    }
    if (! WinAPI::fileExists(filename))
    {
        ret = checkFailed(strFmt("@SYS26666", filename));
    }
    return ret;
}


/// <summary>
/// Creates an instance of the <c>AddressZipCodeImport</c> class.
/// </summary>
/// <param name="_addressZipCodeImportCountryRegion">
/// The member of the <c>LogisticsAddrZipCodeImportCountryRegion</c> class.
/// </param>
/// <returns>
/// A new instance of an <c>AddressZipCodeImport</c> class.
/// </returns>
/// <exception cref="M:Exception::Error">
/// The call of the class is incorrect.
/// </exception>
public static A_BankGroupImport construct()
{
    A_BankGroupImport bankGroupImport;
    bankGroupImport = new A_BankGroupImport();
    return bankGroupImport;
}


client server public static ClassDescription description()
{
    return ("@RNS260");

}


public static void main(Args args)
{
    A_BankGroupImport  bankGroupImport;
    ;
    bankGroupImport = A_BankGroupImport::construct();

    if (bankGroupImport.prompt())
    {
        bankGroupImport.run();
    }
}