Custom C# Coding - Assistance Needed

The following code is a generic template that I was handed to customize in order to pull bank information. I would like help understanding a few things:

  1. Has anyone messed with this code before or have a better way of pulling the necessary data for the bank.

  2. The customization I need to make is limiting the amount of information that is passed along. I believe this is accomplished by commenting out the unnecessary pieces from lines 352-417.

  3. I need to understand why all of the references seem to be broken on the project.



  1. Does this program need much in the means of direction? Does it need to know where to pull data from or are the place holder variables good enough in this case?

Thanks in advance for the help.

Generic Code:

//FixUpSvcConversion: Strings Extraction Completed at: 9/9/2012 9:24 PM
/* Pre-processed by converter */
    File        : ei/payment-GENERIC.p
    Purpose     : Electronic Bank info in GENERIC format. 
    Syntax      :
    Description : This file replaces ap/app20-GENERIC.w
    Author(s)   : Tatyana Kozmina
    Created     : 06-09-2008
    Notes       :
Revision History:
06/09/08 TatyanaK SCR 40680 - Soft format for electronic payments was implemented.     
03/18/11 DanielM SCR 82225 - Replaced all back slashes with fordward slashes on the target output file   
06/09/11 BillR SCR 85360 -  Added field formatting for the check and doc check amt based on currency  
08/22/11 BillR SCR 85360 - New CSF fields added in payment-def.i for scr 86345 so added logic to handle date fields when they are null to set to today's date                    
03/26/12 galinad SCR 94352 - Variable lineLen (record size) is  init  to 1024 characters now (instead of 512).
using System;
using System.IO;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Transactions;
using Epicor.Data;
using Erp;
using Erp.Tables;
using Ice;
using Ice.Lib;
//using Strings = Erp.Internal.EI.Resources.Strings;
using Epicor.Hosting;
using Erp.Services.Lib.Resources;
using BankBatching = Erp.Internal.Lib.BankBatching;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.EntityFrameworkCore;
using System.Data.Entity;

namespace Erp.Internal.EI
    public partial class Payment_Generic : Ice.Libraries.ContextLibraryBase<ErpContext>, IProcessPayments, Erp.Internal.EI.IOrderedColumnExpressions, IBankBatching
        /// ATTENTION!!!
        /// Storing Batch ID Generated by EI
        /// When the application creates AP payment batches, it generates a batch identifier - depending on the EI and
        /// payment method settings. The following functions used in the AP EI source files help you to set up accurate
        /// storing of the generated AP payment batch reference.
        /// However you can customize them as necessary.
        /// <summary>
        /// "GetPaymentBankBatchID" forms Batch ID.
        /// You must pass an ipRecord which holds the batch reference as a parameter value. To store the reference
        /// successfully, the function needs to return a non-empty string value from this object.
        /// <param name="ipRecord">Object holding Batch Id</param>/// 
        /// </summary> 
        public string GetPaymentBankBatchID(object ipRecord)
            string result = string.Empty;
            return result;
        /// <summary>
        /// "PayMethodGrouping" returns a value which specifies whether the EI program stores the batch reference:
        /// 1 - the EI program stores the batch reference
        /// 0 - the EI program does not store the batch reference.
        /// If you remove the code comment symbols in the commented part of the code, the batch reference will be stored
        /// according to the payment method settings.
        /// <param name="ipPMUID">Payment method UID</param>
        /// </summary>
        public bool PayMethodGrouping(int ipPMUID)
            bool result = false;
            // if (LibBankBatching != null)
            //   result = LibBankBatching.PayMethodGrouping(ipPMUID); 
            return result;
        /// <summary>
        /// "SavePaymentBankBatchID" saves the batch reference in an AP payment.
        /// <param name="ipHeadNum">Payment system number</param>
        /// <param name="ipBankBatchID">Non-empty Bank Batch Id</param>
        /// <param name="ipBatchDate">Bank Batch date</param>
        /// </summary>
        public void SavePaymentBankBatchID(int ipHeadNum, string ipBankBatchID, DateTime? ipBatchDate)
            if (LibBankBatching != null && !String.IsNullOrEmpty(ipBankBatchID) && ipHeadNum != 0)
                LibBankBatching.SavePaymentBankBatchID(ipHeadNum, ipBankBatchID, BankBatching.SourceType.EICheckHed, Session.UserID, ipBatchDate, string.Empty);
        /// ATTENTION!!!
        int lineLen = 1024;
        bool ExpDecimalPoint = true;

        #region Implicit buffers
        Erp.Tables.Company Company;
        Erp.Tables.BankAcct BankAcct;
        Erp.Tables.Currency Currency;


        private Lazy<Erp.Internal.EI.SFCommon> _EISFCommon;
        private Erp.Internal.EI.SFCommon EISFCommon
            get { return _EISFCommon.Value; }

        private Lazy<FileName> libGetFileName;
        private FileName LibGetFileName { get { return libGetFileName.Value; } }
        private Lazy<BankBatching> libBankBatching;
        private BankBatching LibBankBatching
            get { return this.libBankBatching.Value; }

        public class OutFileLine
            public string Line_out { get; set; }
            public int HeadNum { get; set; }
        public OutFileLine ttOutFileLine;
        public List<OutFileLine> ttOutFileLineRows;

        protected override void Initialize()
            this._EISFCommon = new Lazy<SFCommon>(() => new SFCommon(this.Db));
            libGetFileName = new Lazy<FileName>(() => new FileName(Db));
            libBankBatching = new Lazy<BankBatching>(() => new BankBatching(Db));

        public Payment_Generic(ErpContext ctx)
            : base(ctx)

        public void CreateFile(List<Payment_Def.TmpElec> TmpElecRows, int EFTHeadUID, string OutputFile)
            Erp.Internal.EI.Payment_Def.TmpElec tmpElec = (from ttTmpElec_Row in TmpElecRows select ttTmpElec_Row).FirstOrDefault();
            bool storeBankBatchID = PayMethodGrouping(tmpElec != null ? tmpElec.SEPMUID : -1);
            this.buildInfo(TmpElecRows, this);
            OutputFile = LibGetFileName.Get(OutputFile, FileName.ServerFileType.Custom, false);

            using (var fileWriter = new writeFileLib(OutputFile, true))
                foreach (var _OutFileLine in (from OutFileLine_Row in ttOutFileLineRows
                                              select OutFileLine_Row))
                    fileWriter.FileWriteLine(EISFCommon.SpecialCaps( _OutFileLine.Line_out.Substring(0, Math.Min(lineLen, _OutFileLine.Line_out.Length - 1))));
                    if (storeBankBatchID)
                        SavePaymentBankBatchID(_OutFileLine.HeadNum, GetPaymentBankBatchID(string.Empty), tmpElec.ProcessDate);


        ///  Parameters:  none
        /* structure generic format:
            1 line of payment method information
            n transaction records
            1 line of payment method information
        private void buildInfo(List<Payment_Def.TmpElec> TmpElecRows, IOrderedColumnExpressions orderedExpressionProvider)
            string strDelim = string.Empty;
            bool lFirst = false;
            string strValue = string.Empty;

            if (EISFCommon.ttOutFileLineRows == null)
                EISFCommon.ttOutFileLineRows = new List<SFCommon.OutFileLine>();
            else EISFCommon.ttOutFileLineRows.Clear();

            var TmpElec = (from TmpElecHead_Row in TmpElecRows select TmpElecHead_Row).FirstOrDefault();
            if (TmpElec == null)
                throw new BLException(GlobalStrings.InterErrorTmpElecHasNoRecords);

            Company = this.FindFirstCompany(Session.CompanyID);
            if (Company == null)
                throw new BLException(GlobalStrings.CompanyNotFound);

            BankAcct = this.FindFirstBankAcct(Session.CompanyID, TmpElec.FromBankAcctID);
            if (BankAcct == null)
                throw new BLException(GlobalStrings.AValidFromBankAcctIsRequired);

            ExpDecimalPoint = BankAcct.ExportDecimalPoint;

            /* This code adds information from the specified payment method into a document.
               The document will have the structure like this:

                1 line of payment method information
                n transaction records
                1 line of payment method information

            SCR 40680 - uncomment the string below if you want insert payment method information  */
            create OutFileLine.
            {ei/SoftFormat.i &TableName         = PayMethodProp
                             &EFTHeadUID        = EFTHeadUID
                             &LineOut           = OutFileLine.Line-out
                             &LineLen           = lineLen
                             &UseCommaSeparator = yes}

            EISFCommon.ttOutFileLineRows = new List<SFCommon.OutFileLine>();


            ttOutFileLineRows = new List<OutFileLine>();

            foreach (var row in TmpElecRows)

                lFirst = true;
                ttOutFileLine = new OutFileLine();
                ttOutFileLine.HeadNum = row.HeadNum;
                if (row.CheckDate == null) row.CheckDate = CompanyTime.Today();
                if (row.EFTDebitMemoDueDate == null) row.EFTDebitMemoDueDate = CompanyTime.Today();
                if (row.SEPAInvoiceDate == null) row.SEPAInvoiceDate = CompanyTime.Today();

                Currency = this.FindFirstCurrency(Session.CompanyID, row.CurrencyCode);

                List<Func<string>> orderedColExpressions = orderedExpressionProvider.GetOrderedColExpressions(row);

                foreach (var colExpression in orderedColExpressions)
                    if (lFirst)
                        strDelim = string.Empty;
                    else strDelim = ",";

                    strValue = colExpression();

                    ttOutFileLine.Line_out = ttOutFileLine.Line_out + strDelim + strValue;
                    lFirst = false;

            /* This code adds information from the specified payment method into a document.
               The document will have the structure like this:

                1 line of payment method information
                n transaction records
                1 line of payment method information

            SCR 40680 - uncomment the string below if you want insert payment method information  */
            create OutFileLine.
            {ei/SoftFormat.i &TableName         = PayMethodProp
                             &EFTHeadUID        = EFTHeadUID
                             &LineOut           = OutFileLine.Line-out
                             &LineLen           = lineLen
                             &UseCommaSeparator = yes}


        /// <summary>
        /// </summary>
        private string formatCurrency<T>(T column)
            string vCurrencyFormat = string.Empty;
            int vNumDecimals = 0;
            int vneedDec = 0;
            string vLastChar = string.Empty;
            int iloop = 0;

            string fieldType = (column == null) ? "" : column.GetType().Name;
            string strValue = (column == null) ? "" : column.ToString();

            vCurrencyFormat = ">>>,>>>,>>>,>>9.99";
            if (Currency != null)
                vNumDecimals = vCurrencyFormat.Length - (vCurrencyFormat.LastIndexOf(".") + 1);
                vneedDec = Currency.DecimalsGeneral;
                if (vNumDecimals > vneedDec)
                    vCurrencyFormat = vCurrencyFormat.Substring(0, vCurrencyFormat.Length - (vNumDecimals - vneedDec));
                else if (vNumDecimals < vneedDec)
                    vLastChar = vCurrencyFormat.Substring(vCurrencyFormat.Length - 1, 1);
                    for (iloop = 1; iloop <= vneedDec - vNumDecimals; iloop++)
                        vCurrencyFormat = vCurrencyFormat + vLastChar;

                strValue = Compatibility.Convert.ToString(strValue, vCurrencyFormat);
                strValue = formatDecimalSpecial(strValue);
                int decNumber = BitConverter.GetBytes(decimal.GetBits(Convert.ToDecimal(strValue, System.Globalization.CultureInfo.InvariantCulture))[3])[2];
                if (strValue.IndexOf(".") == -1)
                    strValue = strValue + ".";

                for (int i = 0; i <= (vneedDec - decNumber) - 1; i++)
                    strValue = strValue + "0";
                strValue = Compatibility.Convert.ToString(strValue, vCurrencyFormat);
                strValue = formatDecimalSpecial(strValue);
            }/* avail currency*/

            return strValue;

        /// <summary>
        /// </summary>
        private string formatDecimalSpecial<T>(T column)
            string strValue = (column == null) ? "" : column.ToString();

            Decimal dec;
            Decimal.TryParse(strValue, out dec);
            strValue = dec.ToString("G15");
            strValue = strValue.Replace(",", ".");
            if (!ExpDecimalPoint)
                strValue = strValue.Replace(".", "");

            return strValue;

        /// <summary>
        /// This method controls the order of the columns to be returned.
        /// We are using a List of Func rather than a 
        /// simple list of string so we get compile type type checking.
        /// </summary>
        /// <param name="tempRow"></param>
        /// <returns></returns>
        public List<Func<string>> GetOrderedColExpressions(TempRowBase tempRow)
            List<Func<string>> orderedColExpressionList = new List<Func<string>>();
            Payment_Def.TmpElec ttRow = (Payment_Def.TmpElec)tempRow;
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.HeadNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.CheckNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.CheckDate));
            orderedColExpressionList.Add(() => formatCurrency(ttRow.CheckAmt));
            orderedColExpressionList.Add(() => formatCurrency(ttRow.DocCheckAmt));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.CurrencyCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankAcctID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankRoutingNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankCheckDigit));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankCompID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankName));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankServClassCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankEntryClassCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankIBANCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.FromBankIdentifier));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorName));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorAddress1));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorAddress2));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorAddress3));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorCity));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorState));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorPostalCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorCountry));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorCountryNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorCountryISOCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorTaxPayerID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorAccountRef));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankName));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankNameOnAccount));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankAddress1));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankAddress2));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankAddress3));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankCity));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankState));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankPostalCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankCountry));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankCountryNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankAcctNumber));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankBranchCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankIBANCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.VendorBankSwiftNum));
            //orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.GroupCurrCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.GroupCurrencyID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.GroupID));
            //orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.ProcessDate));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.InvoiceList));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.PayerRef));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SECreditTransNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEBankRef));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEPMUID));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEPayCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.BankType));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.NoBankingReference));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.EFTDebitMemoHandlingCode));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.EFTDebitMemoDueDate));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.EFTProductionNumber));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEPAInvoiceNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEPAInvoiceDate));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.PayLegalNumber));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEGrpNum));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEPayType));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.SEReference));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.NOTelePayPmtType));
            orderedColExpressionList.Add(() => EISFCommon.GetFormattedString(ttRow.NOPmtDirection));

            return orderedColExpressionList;


Dylan this is a generic EI template that comes available with Epicor.
It is consumed via the Electronic Interface Module in Epicor however

To get to this point you need to understand like a hundred other things in Epicor so I’m wondering why you were handed just a projcet to do something with without guidance :scream:

What is the project “pulling data from the bank” is not enough there is NACH, Positive Pay, LockBox, WireTransfer, BIA, Bank Rec, and about 15 other formats that most banks support to “pull data”

So what kind of data are you trying to pull? Most of these are also Bank Specific…

I need to understand why all of the references seem to be broken on the project.

The references aren’t broken, you need to set your Reference Path

Wait @dgreenEA are you Epicor SaaS MT (MultiTenant) as your profile says? Cause if that’s the case… none of the above will work.


I was asked to get the Company, HeadNum, CheckAmt, VendorNum, VendorName, InvoiceList, and SEPAInvoiceDate listed within that program. Apparently, its for our credit card company and they need that information for our expenses.

Also our finance team uses the Electronic Interface Module for our ACH payments.

Could you give me a run down on how to set reference paths? Im not entirely sure where to begin with that.

We are on a Public Gov Cloud system. I believe that means we are SaaS MT but I could have the designation wrong.

Thanks for the help!

Hey Dylan,

MT was an older product where multiple companies shared a single database. Government Cloud is far more strict and they would never allow that configuration.

Mark W.


Gotcha, Ill update my profile to get that fixed. Sorry for the confusion.

As for the configuration, what are my alternative options for getting this information then? Would it be efficient to make use of the rest API and pull it that way?

Maybe take a minute and explain what you’re trying to accomplish. Are you trying to import a credit card statement? Do a bank reconciliation?


I’m trying to pull the following information on invoices: Company Name, Invoice Number, Invoice Amount, VendorID, Vendor Name, Items on the Invoice, and Invoice date. We want that list to compile on payment. Once the list of these items is compiled we want to send it over to our company that holds our Virtual cards to make an electronic payment to a vendor Electronic payment form.

Kinda sounds like you just need a BAQ or Dashboard


System.Data.Entity is a framework reference. Right click the References -> Add Reference -> System Assemblies.

The others you’ll either have to add those references or add a reference to the folder containing the assemblies… welcome to DLLHELL

1 Like