Tuesday, November 1, 2016

Testing SSRS report RDP class in Job

static void testSSRSDPCLS(Args _args)
{
    VendInvoiceTmp tempTable;
    VendInvoiceDP dataProvider = new VendInvoiceDP();
    VendInvoiceContract contract = new VendInvoiceContract();
    contract.parmFromDate(systemDateGet()-365);
    contract.parmToDate(systemDateGet());


    dataProvider.parmDataContract(contract);
    dataProvider.processReport();
    tempTable = dataProvider.getVendInvoiceTmp();

    while select tempTable
    {
        info(tempTable.AVAVendName);
        info(tempTable.AccountNum);
    }
}

Monday, October 17, 2016

Fetching current legal entity address

static void AVAgetAddressOnPurposeForLegalEntity(Args _args)
{
    LogisticsAddressing  address;

    ;

    address = DirParty::findPostalAddressByRole(CompanyInfo::current(), LogisticsLocationRoleType::Business).Address;

    info(address);

}

Saving PO report as PDF in the shared path

/// <summary>
/// This method generates the PO Confirmation report.
/// </summary>
/// <param name="_purchTable">
/// Gets the PurchTable buffer.
/// </param>
/// <remarks>
/// Generates the PO Confirmation report.
/// </remarks>

//Begin
private void AVAPOConfrimationReportGeneration(PurchTable _purchTable)
{
    SrsReportRunController          ssrsController = new SrsReportRunController();
    PurchPurchaseOrderContract      Contract = new PurchPurchaseOrderContract();
    SRSPrintDestinationSettings     printerSettings;
    VendPurchOrderJour              VendPurchOrderJrn;
    str                             poReportPath;
    ;

    select firstOnly RecId from VendPurchOrderJrn
    order by VendPurchOrderJrn.createdDateTime DESC
    where VendPurchOrderJrn.PurchId == _purchTable.PurchId;

    poReportPath = PurchParameters::find().AvaPurchOrderPath + '\\'  + _purchTable.PurchId +'.pdf';
    ssrsController.parmReportName(ssrsReportStr(PurchPurchaseOrder, Report));
    ssrsController.parmExecutionMode(SysOperationExecutionMode::Synchronous);
    ssrsController.parmShowDialog(false);
    Contract.parmRecordId(VendPurchOrderJrn.RecId);
    ssrsController.parmReportContract().parmRdpContract(Contract);

    //link the printer settings to the controller
    printerSettings = ssrsController.parmReportContract().parmPrintSettings();
    //print to pdf and always overwrite if the file exists
    printerSettings.printMediumType(SRSPrintMediumType::File);
    printerSettings.fileFormat(SRSReportFileFormat::PDF);
    printerSettings.overwriteFile(true);
    printerSettings.fileName(@poReportPath);

    try
    {
    //run & save the report
    ssrsController.runReport();
    }
    catch(Exception::CLRError)
    {
        //Access the last CLR Exception
        info(CLRInterop::getLastException().ToString());
        AifUtil::getClrErrorMessage();
        //See AifUtil::getClrErrorMessage for another alternative
        //how to parse the Exception object
    }
}
//End

Sending PO report to email

/// <summary>
/// this method has logic to send email
/// </summary>
/// <param name="_vendTable">
/// getting vendor table as parameter
/// </param>
/// <param name="_purchTable">
/// getting purchase order table as parameter
/// </param>
/// <param name="_emailAttachments">
/// getting whether the email checkbox is selected or not as parameter
/// </param>
// Begin
public static void sendEmailSysMailer(VendTable _vendTable, PurchTable _purchTable, NoYes _emailAttachments=NoYes::No)
{
    InteropPermission permission = new InteropPermission(InteropKind::ComInterop);
    SysMailer   sysMailer;
    str         filePathName, reportFilePathName;
    VendTable   vendTable=_vendTable;
    DocuRef     docuRef;
    EmailBase   sender;
    Notes       body;
    ;

    if(_purchTable.RecId)
    {
        sender = SysUserInfo::find(curUserId()).Email;

        permission.assert();
        sysMailer = new SysMailer();

        //reportFilePathName = PurchParameters::find().AvaPurchOrderPath + '\\default.pdf';
        reportFilePathName = PurchParameters::find().AvaPurchOrderPath + '\\' + _purchTable.PurchId +'.pdf';
        // AVAEmailPOConfirmationWithAttachments - Hema - 28/Aug/2016 - Begin
        //Requirement change
        //Attach PO report as external attachment to the PO header and then send it to vendor's email
        AvaSendingEmailPOConfirmation::attachPOReport(_purchTable, reportFilePathName);
        //sysMailer.attachments().add(reportFilePathName);
        // AVAEmailPOConfirmationWithAttachments - Hema - 28/Aug/2016 - End

        if(_emailAttachments == NoYes::Yes)
        {
            //info('Sender email id: ' + sender);
            while select docuRef
                where docuRef.RefRecId    == _purchTable.RecId
                   && docuRef.Restriction == DocuRestriction::External
                   && docuRef.RefTableId  == tableNum(PurchTable)
                {
                    filePathName = docuRef.completeFilename();
                    if( !((docuRef.docuType().TypeGroup == DocuTypeGroup::Note) || (docuRef.docuType().TypeGroup == DocuTypeGroup::URL)))
                    {
                        sysMailer.attachments().add(filePathName);
                    }
                }
            //info('Vendor primary email id: ' +vendTable.email());
            body = 'Please see attached '+ _purchTable.PurchId +' from Golden Spread Electric Cooperative.  Feel free to contact us if you have any questions and concerns.';
            //sysMailer.quickSend("bijan.ghofranian@avanade.com",vendTable.email(),'PO Confirmed '+_purchTable.PurchId,'Your PO '+ _purchTable.PurchId + ' was Confirmed');
            sysMailer.quickSend(sender,vendTable.email(),'PO Confirmed '+_purchTable.PurchId,body);
            info(strFmt("@AVA39",vendTable.email())); //Email sent to %1
            sysMailer.attachments().clear();
        }
        CodeAccessPermission::revertAssert();
    }
}
//End

Attaching PO report as PO header attachment


/// <summary>
/// this method has logic to add po report pdf as external attachment against the POil
/// </summary>
/// <param name="_purchTable">
/// getting purchase order table as parameter
/// </param>
/// <param name="_fileName">
/// getting file name to attach as external attachment as parameter
/// </param>
//Begin
static void attachPOReport(PurchTable _purchTable, Notes _fileName)
{
    DocuRef docuRef;
    DocuActionArchive archive;
    ;

    if (_purchTable!=null)
    {
        try
        {
            docuRef.clear();
            docuRef.RefRecId = _purchTable.RecId;
            docuRef.RefTableId = tableNum(PurchTable);
            docuRef.RefCompanyId = curext();
            docuRef.Name = _fileName;
            docuRef.TypeId = 'File';
            docuRef.Restriction = DocuRestriction::External;
            docuRef.insert();
            archive = DocuAction::newDocuRef(docuRef);
            archive.add(docuRef, _fileName);
        }
        catch(Exception::CLRError)
        {
            //Access the last CLR Exception
            info(CLRInterop::getLastException().ToString());
            AifUtil::getClrErrorMessage();
            //See AifUtil::getClrErrorMessage for another alternative
            //how to parse the Exception object
        }

    }
}
//End

Since PO confirmation class is running server-side, docuActionArchive class->add method is changed to server-side. Refer this link in my blog: https://www.blogger.com/blogger.g?blogID=3375586050608221914#editor/target=post;postID=7858382166586064691;onPublishedMenu=editor;onClosedMenu=editor;postNum=1;src=postname

Docuref in batch (server side)

Adding attachment with transaction when running in server-side


DocuActionArchive class

Add method

if (docuRules)
    {
          // Begin
        //fileSize = WinAPI::fileSize(attachFilename);
        if(isRunningOnServer())
        {
            fileSize = WinAPIServer::fileSize(attachFilename);
        }
        else
        {
            fileSize = WinAPI::fileSize(attachFilename);
        }
        // End
         
          isFileSizeOk = Docu::validateFileSize(_docuRef.docuType() ,fileSize);
 
      }


else
        {
              // Begin
            //WinAPI::copyFile(attachFilename, docuFilename);
            if(isRunningOnServer())
            {
                WinAPIServer::copyFile(attachFilename, docuFilename);
            }
            else
            {
                WinAPI::copyFile(attachFilename, docuFilename);
            }
            //End
             
          }

Tuesday, March 29, 2016

Testing AIF service create method through C# code with ledgerdimension and defaultdimension

1. In VS create console application project.
2. copy the below code in Program.cs
3. Run this code and test in Ax tables.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// Add a using statement for the service reference.
using FTI.FTIServiceRef;
using System.Collections;


namespace FTI
{
    class Program
    {
        static void Main(string[] args)
        {              
            // Instantiate an instance of the service client class.
            FreeTextInvoiceServiceClient proxy = new FreeTextInvoiceServiceClient();
       
            // Create an instance of the document class.
             AxdFreeTextInvoice freetextInvoice = new AxdFreeTextInvoice();

            CallContext context = new CallContext();
            context.Language = "en-us";
            context.Company = "gsec";

            // Create instances of the entities that are used in the service and
            // set the needed fields on those entities.
            AxdEntity_CustInvoiceTable custInvoiceTable = new AxdEntity_CustInvoiceTable();
            custInvoiceTable.OrderAccount = "Cus-000001";
            custInvoiceTable.LanguageId = "en-us";
            custInvoiceTable.PurchOrderFormNum = "Test";
            custInvoiceTable.CustomerRef = "Test1";
           
            AxdEntity_CustInvoiceLine custInvoiceLine = new AxdEntity_CustInvoiceLine();
            custInvoiceLine.Description = "Test Description";
            custInvoiceLine.InvoiceTxt = "Test Invoice Txt";
            custInvoiceLine.AmountCur = 120;
            custInvoiceLine.AmountCurSpecified = true;

            //custInvoiceLine.LedgerDimension = 5637152076; //for main account 10100000

            AxdType_DefaultAccount account = new AxdType_DefaultAccount();
            account.MainAccount = "10100000";
            custInvoiceLine.LedgerDimension = account;

            custInvoiceLine.DefaultDimension = new AxdType_DimensionAttributeValueSet();

            AxdType_DimensionAttributeValue dimValue1 = new AxdType_DimensionAttributeValue();
            dimValue1.Name = "BusinessUnit";
            dimValue1.Value = "100";

            AxdType_DimensionAttributeValue dimValue2 = new AxdType_DimensionAttributeValue();
            dimValue2.Name = "Department";
            dimValue2.Value = "1000";

            AxdType_DimensionAttributeValue dimValue3 = new AxdType_DimensionAttributeValue();
            dimValue3.Name = "CostCenter";
            dimValue3.Value = "10000";

            custInvoiceLine.DefaultDimension.Values = new AxdType_DimensionAttributeValue[3] { dimValue1, dimValue2, dimValue3 };
            /*custInvoiceLine.DefaultDimension.Values = new AxdType_DimensionAttributeValue[3];
            custInvoiceLine.DefaultDimension.Values[0] = dimValue1;
            custInvoiceLine.DefaultDimension.Values[1] = dimValue2;
            custInvoiceLine.DefaultDimension.Values[2] = dimValue3;*/

            //account.Values = new AxdType_DimensionAttributeValue[3] { dimValue1, dimValue2, dimValue3 };
           
            //AxdEntity_InventDim inventDim = new AxdEntity_InventDim();
            //inventDim.InventSiteId = "MUS";
            /*inventDim.configId = "HD";
            inventDim.InventColorId = "01";
            inventDim.InventSizeId = "42";*/

            // Add the sub-entity instances to their parent entities as an array
            // of the sub-entity type.
            //salesLine.InventDim = new AxdEntity_InventDim[1] { inventDim };
            custInvoiceTable.CustInvoiceLine = new AxdEntity_CustInvoiceLine[1] { custInvoiceLine };
            freetextInvoice.CustInvoiceTable = new AxdEntity_CustInvoiceTable[1] { custInvoiceTable };

            try
            {
                // Call the create method on the service passing in the document.
                EntityKey[] returnedFTIEntityKey = proxy.create(context, freetextInvoice);              

                // The create method returns an EntityKey which contains the ID of the sales order.
                EntityKey returnedFTI = (EntityKey)returnedFTIEntityKey.GetValue(0);
                Console.WriteLine("The free text invoice created has a ID of " + returnedFTI.KeyData[0].Value);
                Console.ReadLine();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                Console.ReadLine();
            }
        }
    }
}


Monday, February 29, 2016

Creating ledgerdimension for Main Account

Creating ledgerdimension for Main Account

LedgerDimensionDefaultAccount          ledgerDimension;

ledgerDimension = DimensionStorage::getDefaultAccountForMainAccountNum(interfaceParameters.MainAccountNum);
                        custInvoiceLine.LedgerDimension = ledgerDimension;

Creating Default dimension for the given combination

Creating Default dimension for the given combination
int dimCount;
DimensionAttribute                            dimensionAttribute;
str                                                     dimValue;
DimensionAttributeValue                   dimensionAttributeValue;

for (dimCount = 1; dimCount <= conLen(conAttr); dimCount++)
                        {
                            dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,dimCount));

                            if (dimensionAttribute.RecId == 0)
                            {
                                continue;
                            }

                            dimValue = conPeek(conValue,dimCount);

                            if (dimValue != "")
                            {
                                // _createIfNotFound is "true". A dimensionAttributeValue record will be created if not found.
                                dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);

                                // Add the dimensionAttibuteValue to the default dimension
                                valueSetStorage.addItem(dimensionAttributeValue);
                            }
                        }
                        defaultDimension = valueSetStorage.save();
                        custInvoiceLine.DefaultDimension = defaultDimension;

Using SysOperationFramework (Custom CSV import)

Using SysOperationFramework

Create DataContract classs - We can define parameters in this class.

[DataContractAttribute]
class Ava_SysOperationImportFreeTxDataContract
{
    Name            name;
    BirthDate       birthDate;
    FilenameOpen        Filename;

    MonthsOfYear    monthThatWontBeSerialized;
}
//getting birthdate as parameter
//this parameter won't display in the form since no [DataMemberAttribute] is defined for this method
public BirthDate parmBirthDate(BirthDate _birthDate = birthDate)
{
    birthDate = _birthDate;

    return birthDate;
}
//getting file name as parameter
[DataMemberAttribute]
public FilenameOpen parmFilePath(FilenameOpen _Filename = Filename)
{
    Filename = _Filename;

    return Filename;
}

Create Service Class - It’s not a good practice to keep whole business logic in one controller class. Because it will be a big responsibility for a single class to handle.Thatswhy here we have created a Service class which is referenced in Controller class.


class Ava_SysOperationImportFreeTextService extends SysOperationServiceBase
{
}
//Method for reading CSV file and stored into CustInvoiceTable and CustInvoiceLines table
public void Ava_FreeTextInvoiceImportfromCSV()
{
    //public void Ava_FreeTextInvoiceImportfromCSV(Ava_SysOperationImportFreeTxDataContract _contract)
    Dialog      dialog  = new Dialog();
    DialogField
    dialogField;
    AsciiIo importFile;
    str filePath,fileNameOnly;
    filetype type;
    container record, offsetAccount;
    str         Delimiter = ",";
    int totalRecords, dimCount;
    InventDim               InventDim;
    CustInvoiceTable custInvoiceTable, custInvoiceTableSel;
    CustInvoiceLine custInvoiceLine;
    CustTable custTable;
    Map                 customerFTI = new Map(Types::String, Types::String);
    MapEnumerator       mapEnum;
    LineNum             lineNum;
    DimensionAttribute              dimAttr;
    DimensionAttributeSetItem       dimAttrSetItem;
    DimensionEnumeration            dimensionSetId;
    Container                       combinedContainer;
    CustAccount                     custAccount;
    Counter                         counter;
    DimensionAttributeValue         dimAttributeValue;
    LedgerDimensionDefaultAccount          ledgerDimension;
    container               conAttr;
    container               conValue;
    DimensionAttributeValueSetStorage   valueSetStorage = new DimensionAttributeValueSetStorage();
    DimensionDefault                               result;
    DimensionAttribute                            dimensionAttribute;
    DimensionAttributeValue                   dimensionAttributeValue;
    str                     dimValue;
    DimensionDefault    defaultDimension;
    MainAccount MainAccount;
    DimensionAttributeValueCombination dimensionAttributeValueCombination;
    Ava_InterfaceParameters interfaceParameters;
    str60 invoiceId;
    FileIOPermission       readPermission;
    Filename fileName = "Momentum RC Jan 2016.CSV";
    TaxGroupHeading taxGroupHeading;
    TaxGroup taxGroup;
    Notes invalidValues;

    select interfaceParameters;
    readPermission = new FileIOPermission(interfaceParameters.FilePath + "\\" + fileName, 'R'); //#io_read);
    readPermission.assert();
    importFile = new AsciiIo(interfaceParameters.FilePath + "\\" + fileName, 'R');
    if((!importFile) || (importFile.status() != IO_Status::Ok))
    {
        warning("Error in opening import file");
        throw(Exception::Error);
    }
    importFile.inFieldDelimiter(Delimiter);
    if((!importFile) || (importFile.status() != IO_Status::Ok))
    {
        warning("Error in opening log file");
        throw(Exception::Error);
    }
    try
    {

        record = importFile.read();
        while(importFile.status() ==  IO_Status::Ok)
        {
            record = importFile.read();
            if(!record)
                break;
            if(!interfaceParameters.CustAccount || !interfaceParameters.MainAccountNum)
            {
                error("Customer account and Main account should not be empty");
                throw(Exception::Error);
            }
            ttsbegin;
            invoiceId = conPeek(record,1);
            select RecId from custInvoiceTableSel
            where custInvoiceTableSel.AvaExternalInvoiceId==invoiceId;
            if(!custInvoiceTableSel.RecId)
            {
                taxGroup=conPeek(record,5);
                select TaxGroup from taxGroupHeading
                where taxGroupHeading.TaxGroup==taxGroup;
                if(!taxGroupHeading.TaxGroup)
                {
                    invalidValues += "Invalid Sales tax group for invoice id " + invoiceId;
                }
                else
                {
                //error("Invoice has alredy been imported");
                //throw(Exception::Error);

                totalRecords = totalRecords + 1;

                custInvoiceTable.clear();
                custTable = CustTable::find(interfaceParameters.CustAccount);
                if (custTable.RecId != 0)
                {
                    custInvoiceTable.initValue();
                    custInvoiceTable.AvaExternalInvoiceId=conPeek(record,1);
                    custInvoiceTable.InvoiceDate = str2Date(conPeek(record,3),213);//systemDateGet();
                    custInvoiceTable.initFromCustTable(custTable);
                    custInvoiceTable.initFromTaxItemGroup();
                    custInvoiceTable.DlvTerm = custTable.DlvTerm;
                    custInvoiceTable.setIntrastatDestinationData();

                    /*custInvoiceTable.OrderAccount = custTable.AccountNum;
                    custInvoiceTable.modifiedField(fieldNum(CustInvoiceTable, OrderAccount));
                    custInvoiceTable.InvoiceId = customerInvoices.InvoiceId;*/
                    custInvoiceTable.insert();
                    lineNum = 0;
                    customerFTI.insert(custTable.AccountNum, custInvoiceTable.InvoiceAccount);
                    }
                    if (custInvoiceTable.RecId != 0)
                    {
                        custInvoiceLine.clear();
                        custInvoiceLine.initValue();
                        custInvoiceLine.initFromCustInvoiceTable(custInvoiceTable);
                        //get customer account number
                        custAccount = custTable.AccountNum;
                        counter = 1; //Dimension starting point
                        combinedContainer = conNull();
                        dimAttributeValue = null;
                        custInvoiceLine.Description     = conPeek(record,8);
                        custInvoiceLine.TaxGroup        = conPeek(record,5);
                        custInvoiceLine.TaxItemGroup    = "ALL";
                        custInvoiceLine.Quantity        = conPeek(record,6);
                        custInvoiceLine.UnitPrice       = conPeek(record,7);

                        custInvoiceLine.AmountCur       = custInvoiceLine.Quantity * custInvoiceLine.UnitPrice;
                        /*custInvoiceLine.AmountCur = Currency::curAmount(123 * nextLineNum,
                                                    custInvoiceTable.CurrencyCode,
                                                    custInvoiceTable.InvoiceDate);*/
                        custInvoiceLine.ParentRecId     = custInvoiceTable.RecId;
                        ledgerDimension = DimensionStorage::getDefaultAccountForMainAccountNum(interfaceParameters.MainAccountNum);
                        custInvoiceLine.LedgerDimension = ledgerDimension;
                        if(conPeek(record,4)!='')
                        {
                            conAttr += 'GeoCode';
                            conValue += conPeek(record,4);
                            select dimAttr
                            order by Name
                                where dimAttr.Type != DimensionAttributeType::MainAccount
                                && dimAttr.Name=="Geocode"
                            join RecId from dimAttributeValue
                                where dimAttributeValue.DimensionAttribute == dimAttr.RecId;
                            dimAttributeValue = AxdDimensionUtil::validateFinancialDimensionValue(dimAttr, conPeek(record,4));
                        }
                        if(conPeek(record,5)!='')
                        {
                            conAttr += 'Province';
                            conValue += conPeek(record,5);
                            select dimAttr
                            order by Name
                                where dimAttr.Type != DimensionAttributeType::MainAccount
                                && dimAttr.Name=="Province"
                            join RecId from dimAttributeValue
                                where dimAttributeValue.DimensionAttribute == dimAttr.RecId;
                            dimAttributeValue = AxdDimensionUtil::validateFinancialDimensionValue(dimAttr, conPeek(record,5));
                        }

                        if(interfaceParameters.BusinessUnit)
                        {
                            conAttr += 'BusinessUnit';
                            conValue += interfaceParameters.BusinessUnit;
                        }
                        if(interfaceParameters.BusinessUnit)
                        {
                            conAttr += 'Department';
                            conValue += interfaceParameters.Department;
                        }
                        for (dimCount = 1; dimCount <= conLen(conAttr); dimCount++)
                        {
                            dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,dimCount));

                            if (dimensionAttribute.RecId == 0)
                            {
                                continue;
                            }

                            dimValue = conPeek(conValue,dimCount);

                            if (dimValue != "")
                            {
                                // _createIfNotFound is "true". A dimensionAttributeValue record will be created if not found.
                                dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);

                                // Add the dimensionAttibuteValue to the default dimension
                                valueSetStorage.addItem(dimensionAttributeValue);
                            }
                        }
                        defaultDimension = valueSetStorage.save();
                        custInvoiceLine.DefaultDimension = defaultDimension;
                        custInvoiceLine.LedgerDimension = ledgerDimension;
                        //LINE NUM LOGIC.
                        if(!lineNum)
                        {
                            lineNum = CustInvoiceLine::lastLineNum_W(custInvoiceLine.ParentRecId);
                        }
                        lineNum += 1;
                        custInvoiceLine.LineNum = lineNum;
                        custInvoiceLine.insert();

                        if(str2int(conPeek(record,10)) > 0 || str2int(conPeek(record,10)) < 0) //Discount
                        {
                            //get customer account number
                            custAccount = custTable.AccountNum;
                            counter = 1; //Dimension starting point
                            combinedContainer = conNull();
                            dimAttributeValue = null;
                            custInvoiceLine.Description     = "Discount";
                            //custInvoiceLine.LedgerDimension = 40300
                            custInvoiceLine.TaxGroup        = conPeek(record,5);
                            custInvoiceLine.TaxItemGroup    = "ALL";
                            custInvoiceLine.Quantity        = conPeek(record,6);
                            custInvoiceLine.UnitPrice       = conPeek(record,10);

                            custInvoiceLine.AmountCur       = custInvoiceLine.Quantity * custInvoiceLine.UnitPrice;
                            /*custInvoiceLine.AmountCur = Currency::curAmount(123 * nextLineNum,
                                                        custInvoiceTable.CurrencyCode,
                                                        custInvoiceTable.InvoiceDate);*/
                            custInvoiceLine.ParentRecId     = custInvoiceTable.RecId;
                            custInvoiceLine.LedgerDimension = ledgerDimension;
                            custInvoiceLine.DefaultDimension = defaultDimension;

                            //LINE NUM LOGIC.
                            if(!lineNum)
                            {
                                lineNum = CustInvoiceLine::lastLineNum_W(custInvoiceLine.ParentRecId);
                            }
                            lineNum += 1;
                            custInvoiceLine.LineNum = lineNum;
                            custInvoiceLine.insert();
                        }
                        if(str2int(conPeek(record,12)) > 0 || str2int(conPeek(record,12)) < 0) //Card Fee
                        {
                            //get customer account number
                            custAccount = custTable.AccountNum;
                            counter = 1; //Dimension starting point
                            combinedContainer = conNull();
                            dimAttributeValue = null;
                            custInvoiceLine.Description     = "Card Fee";
                            //custInvoiceLine.LedgerDimension = 40300
                            custInvoiceLine.TaxGroup        = conPeek(record,5);
                            custInvoiceLine.TaxItemGroup    = "ALL";
                            custInvoiceLine.Quantity        = conPeek(record,6);
                            custInvoiceLine.UnitPrice       = conPeek(record,12);

                            custInvoiceLine.AmountCur       = custInvoiceLine.Quantity * custInvoiceLine.UnitPrice;
                            /*custInvoiceLine.AmountCur = Currency::curAmount(123 * nextLineNum,
                                                        custInvoiceTable.CurrencyCode,
                                                        custInvoiceTable.InvoiceDate);*/
                            custInvoiceLine.ParentRecId     = custInvoiceTable.RecId;
                            custInvoiceLine.LedgerDimension = ledgerDimension;
                            custInvoiceLine.DefaultDimension = defaultDimension;
                            //LINE NUM LOGIC.
                            if(!lineNum)
                            {
                                lineNum = CustInvoiceLine::lastLineNum_W(custInvoiceLine.ParentRecId);
                            }
                            lineNum += 1;
                            custInvoiceLine.LineNum = lineNum;
                            custInvoiceLine.insert();
                        }
                        if(str2int(conPeek(record,14)) > 0 || str2int(conPeek(record,10)) < 0) //20% Reseller (Branches)
                        {
                            //get customer account number
                            custAccount = custTable.AccountNum;
                            counter = 1; //Dimension starting point
                            combinedContainer = conNull();
                            dimAttributeValue = null;
                            custInvoiceLine.Description     = "20% Reseller (Branches)";
                            //custInvoiceLine.LedgerDimension = 40300
                            custInvoiceLine.TaxGroup        = conPeek(record,5);
                            custInvoiceLine.TaxItemGroup    = "ALL";
                            custInvoiceLine.Quantity        = conPeek(record,6);
                            custInvoiceLine.UnitPrice       = conPeek(record,14);

                            custInvoiceLine.AmountCur       = custInvoiceLine.Quantity * custInvoiceLine.UnitPrice;
                            /*custInvoiceLine.AmountCur = Currency::curAmount(123 * nextLineNum,
                                                        custInvoiceTable.CurrencyCode,
                                                        custInvoiceTable.InvoiceDate);*/
                            custInvoiceLine.ParentRecId     = custInvoiceTable.RecId;
                            custInvoiceLine.LedgerDimension = ledgerDimension;
                            custInvoiceLine.DefaultDimension = defaultDimension;

                            //LINE NUM LOGIC.
                            if(!lineNum)
                            {
                                lineNum = CustInvoiceLine::lastLineNum_W(custInvoiceLine.ParentRecId);
                            }
                            lineNum += 1;
                            custInvoiceLine.LineNum = lineNum;
                            custInvoiceLine.insert();
                        }
                    }
                }
                }
            ttscommit;
        }
            info(invalidValues);
            mapEnum = customerFTI.getEnumerator();
            info(strFmt('Following Free Text Invoices are successfully created.'));
            while (mapEnum.moveNext())
            {
                info(strFmt('Customer Account : %1 , Invoice Account : %2', mapEnum.currentKey(), mapEnum.currentValue()));
            }

            // Optionally call revertAssert() to limit scope of assert.
            CodeAccessPermission::revertAssert();
    }
    catch(Exception::Error)
    {
        Throw(Exception::Error);
    }
    info(strFmt("Total Read Records = %1",totalRecords));
}

Controller Class - As the name implies Controller, this class has great responsibility to initiate the operation. This class holds all the information regarding Execution mode, it should show a progress form or Dialog.

class Ava_SysOperationImportFreeTextController extends SysOperationServiceController
{

}
//setting caption for Task description for parameter dialog 
protected ClassDescription defaultCaption()
{
    // This will be the dialog's caption
    return 'Importing Free Text Invoices';

}
//new method
protected void new()
{
    // This tells the controller what method it should execute as the service. In this case, we'll run SysOperationDemoService.performDemo()
    //super(classStr(AvaSysOperationDemoService), methodStr(AvaSysOperationDemoService, performDemo), SysOperationExecutionMode::Synchronous);
    super(classStr(Ava_SysOperationImportFreeTextService), methodStr(Ava_SysOperationImportFreeTextService, Ava_FreeTextInvoiceImportfromCSV), SysOperationExecutionMode::Synchronous);

}
//validate your parameters
protected boolean validate()
{
    //Ava_SysOperationImportFreeTxDataContract    contract;
    boolean                         ret = true;
    /*
    contract = this.getDataContractObject();
    //info(contract.parmFilePath());
    if (contract.parmBirthDate() > DateTimeUtil::date(DateTimeUtil::addYears(DateTimeUtil::utcNow(), -18)))
    {
        // Failing the validate will not close the dialog, and the user will have another chance of inputting the correct values
        ret = checkFailed('The user is underage!');
    }*/

    return ret;

}
//run method
public void run()
{
    //info('Run method has been called');

    super();

}
//construct method
public static Ava_SysOperationImportFreeTextController construct()
{
    Ava_SysOperationImportFreeTextController      controller;

    controller = new Ava_SysOperationImportFreeTextController();

    controller.parmShowDialog(true); // Actually the default value
    controller.parmShowProgressForm(false);

    return controller;

}
//main method
public static void main(Args _args)
{
    Ava_SysOperationImportFreeTextController controller;

    controller = Ava_SysOperationImportFreeTextController::construct();

    controller.startOperation();

}

you can add action menuitem for this controller class and run the logic.