Wednesday 30 August 2023

LN Taxation - Sessions

 tcmcs0137m000 - Tax Codes

tcmcs0536m000 - Tax Codes by country

tctax0122m000 - Goods and service Categories

tctax0623m000 - Goods and service Categories mapping

tctax0135m000 - Tax Handling

tfgld0571m000 - Posting Data for Single Tax Codes

tctax1100m000 - Tax Exception by Country

tctax0101m000 - Tax Parameters by Country

tctax4105m000 - Tax Number Definitions by Registration Type

tctax2115m000 - Jurisdictions by Country 

tctax2520m000 - Registrations

tctax4102m000 - Registrations by Business Partner

tctax8100m000 - Test Tax Scenario

Monday 26 July 2021

Cross Join of Two Columns in Excel



Sub cross_join()


    Dim i, j, tot_sor_rows, tot_ref_rows As Integer

    Dim res_pos As Integer

    Dim sh1 As Worksheet

    

    Set sh1 = ThisWorkbook.Sheets("Sheet1")

    tot_sor_rows = sh1.Range("A1", sh1.Range("A1").End(xlDown)).Rows.Count

    tot_ref_rows = sh1.Range("B1", sh1.Range("B1").End(xlDown)).Rows.Count

    res_pos = 2

    

    For i = 2 To tot_sor_rows

        For j = 2 To tot_ref_rows

            sh1.Range("C" + CStr(res_pos)).Value = (CStr(sh1.Range("A" + CStr(i)).Value) + "-" + CStr(sh1.Range("B" + CStr(j)).Value))

            res_pos = res_pos + 1

        Next j

    Next i


End Sub

Sunday 20 September 2020

Why do ERP Implementation Projects of Small & Medium Sized Businesses FAIL?

 Let’s note some curtail facts first:

  • ERP has become a hygiene for smooth operations of any company.
  • ERP users are either Generation X or Millennials. They are accustomed to using user friendly & easy to use software. Thus, it is important to equip them with a good ERP irrespective of you company size and number of licenses you will consume.
  • License cost of most of top tier ERP vendors remains same irrespective of the customer’s business size. Small/Medium sized businesses might not have such deep pockets. Could be because they are still in start-up stage and are struggling to reach the breakeven point or their operations size is still small.
  • Efforts of ERP implementation is more inclined to ‘complexity of business’ than number of licenses the customer buys. Thus, it requires relatively similar efforts to implement ERP in a small/medium sized business. 
  • ERP is a complex B2B product and requires enormous efforts from BD teams to understand customer requirement and prepare proposal. It requires multiple meetings with different levels of the client’s company. Is this effort worth it?

Some bookish knowledge:

The below matrix explains sales strategy, efforts and its outcome while targetting your prospect:  


It is very much evident that, “’It is not worth it’ in targeting very small or small/medium sized company for products that require high touch. 


'Not worth' it Projects:

ERP is a high touch product. Profitable companies do not put efforts when its 'not worth it'! But then Top Tier ERP Vendors do not want to lose the business coming from license sale to the SME segment. However, they are clearly not interested in wasting their efforts in pitching and implementing the ERP at such SMEs themselves.

Even big profitable service companies don’t find it worthful in taking up such projects.

This is when the need for developing Small-scale Channel Partners came! These top tier ERP vendors started developing channel partners who can take up these low-profit & high-risk projects. The margins at which these small-scale channel partners operated did not gave them the bandwidth of hiring good quality ERP consultants! And that’s where the problem began!!

Small-scale Channel Partners started winning projects without even knowing the complexity of efforts involved in the project. And when it came to execution, they went dry… falling short of liquidity, knowledge and burning their workforce at the same time.


SMEs' ERP implementation went for a toss:

In desperation of meeting the breakeven point (which included paying salaries to their employees); theese small-scale channel partners strategized the idea of earning profit through 'economies of scale' and started targeting more SMEs. The idea was to share the same resource pool across multiple implementation projects.

While this strategy gave them the liquidity for initial few months; they were unable to handle the stress of so many projects running in parallel. Little did they know, that ERP implementation projects dont work with strategy of 'economies of scale'.

This resulted into either one or all the projects under them going for a toss.

This lead to SMEs failing to reap the benefits of the ERP even they selected a 'TOP TIER' ERP!


These is my personal analysis and will be happy to hear your thoughts and suggestions on this.

Friday 26 July 2019

Email from ERP LN using eMessage Connector

#define                                EMAIL_ID_SEP  chr$(124)
                #include               <bic_cmf>
                #include               <bic_text>

                table      tttaad121
                table      tttaad200
                table      tttadv111
                table      tttadv330

                domain tsmdm.page      hold.provider                                                                         
function extern                domain tcbool ppmmm.dll0800.send.mail(
                                                                domain ttcmf.prov          i.service,
                                                                domain tcmcs.st80           i.from.addr,
                                                                domain tcmcs.s999m      i.to.addr,
                                                                domain tcmcs.s999m      i.cc.addr,
                                                                domain tcmcs.s999m      i.subject,
                                                                domain tcmcs.s999m      i.email.body,
                                                                domain tcbool                   i.email.body.is.file,
                                                                domain tcmcs.s999m      i.att.path,
                                                                domain tcmcs.s999m      i.attachment,
                                                                domain tcbool                   i.interactive,
                                                ref          domain tcmcs.s999m      o.err.msg,             
                                                        ...)                 
{
                DllUsage
                Expl:      This function can be used to send email.
                Pre:        NA
                Post:      NA
                Input:
                                i.service               -> Service to be used to send the email.
                                                                   eg. "OUTLOOK", "SMTP".
                                i.to.addr               -> Email ID of the TO recipient.
                                                                   If email is to be sent to multiple
                                                                   persons send  the IDs  "|" seperated.
                                i.cc.addr               -> Email ID of the CC recipient.
                                                                   If email is to be sent to multiple
                                                                   persons send  the IDs  "|" seperated.
                                i.subject               -> Subject for the email.
                                i.email.body       -> Contains actual text   OR the file path which
                                                                   contains text to be sent as mail body. File
                                                                   must   be present on the server.
                                i.email.body.is.file
                                                                -> Boolean variable, if
                                                                   true    = varibale i.email.body.is.file      must
                                                                                contain the file path for the text to be
                                                                                sent as  the body for the mail.
                                                                   false = varibale i.email.body.is.file must
                                                                                contain actual text to be sent as the
                                                                                mail body.
                                i.attachment      -> Path of the file which is to      be sent as
                                                                   attachment. If there    are multiple attachments
                                                                   to be sent then sent    the file path pipe
                                                                   seperated.
                                i.interactive        -> If true = a message box opens.
                                                                   false = user      has no interaction.


                Output:
                                o.err.msg            -> Error message if any.
                Returns:
                                true                       -> If successfull.
                                false                      -> If failed.
                EndDllUsage

                                boolean                               flag
                                long                       fp, ret
                                long                       comp
                                long                       stat
                                long                       i.att.format                                   
                                long                       message.ID
                                long                       attachment.ID
                                long                       hold.curr.company
                                string                     sourcefile(1024)
                string          sept(1)                                       
                long            add.att.name                                   
                domain tcmcs.st80           l.frm.addr

                hold.provider = i.service
                if isspace(i.to.addr) and isspace(i.cc.addr) then
                                |* True is returned because there is no need of                sending                any
                       |* message. Not an error.
                                return(true)
                endif

                comp = get.compnr()
        i.att.format = 0
        if get.argc() > 11 then
                i.att.format = get.long.arg(12)
        endif
                                                                               
        sept = ""
        if get.argc() > 12 then
                sept = trim$(get.string.arg(13))
        endif

        add.att.name = 0
        if get.argc() > 13 then
                add.att.name = get.long.arg(14)
        endif

                |* Set the body                for the  email
                if i.email.body.is.file       then
                                sourcefile = i.email.body
                else
                                sourcefile = creat.tmp.file$(bse.tmp.dir$())
                                fp = seq.open(sourcefile, "w")
                                seq.puts(i.email.body, fp)
                                seq.close(fp)
                endif

                flag = compnr.check(0)

                |* Create the message connector            object
                message.ID = cmf.create()
                ret = cmf.setClass(message.ID, "CMF.NOTE.EMAIL")
                ret = cmf.setSubject(message.ID, i.subject)

                |* Set FROM recipient
                if not isspace(i.from.addr) then
                                create.recipient(message.ID, i.from.addr, ttcmf.role.from)
                endif

                |* Set TO recipient
                divide.and.add.recipient.to.xml(message.ID, i.to.addr, ttcmf.role.to)

                |* Set CC recipient
                divide.and.add.recipient.to.xml(message.ID, i.cc.addr, ttcmf.role.cc)

                |* Set email message boby
                attachment.ID =               cmf.createAttachment(message.ID)
                ret = cmf.setAttachmentBody(attachment.ID, ttyeno.yes)

                |* If ttyeno.no  & text/plain,rtf or images/gif then attachment is sent
                |* If ttyeno.yes & text/plain then text   is sent   in body; if images/gif
                |* or text/rtf gives error
                ret = cmf.setAttachmentMIME(attachment.ID, "text/plain")
                ret = cmf.setAttachmentFileName(attachment.ID,sourcefile)

                |* Linking the attachment.         
                link.attachments(message.ID,i.att.path,i.attachment,i.att.format,sept,add.att.name)
                ret = cmf.setPriority(message.ID, ttcmf.prio.high)
                ret = cmf.setSensitivity(message.ID,ttcmf.sens.secret)
                ret = cmf.setNotification(message.ID,ttcmf.noti.nondelivery)


                if message.ID <> 0 then
                                stat = cmf.startService(i.service,2)
                                if stat     <> 0 then
                                                o.err.msg = form.text$("tcwflk0012")
                                                |* Message could not be             sent (Infor ERP  LN eMessage
                                                |* Connector service did not start)
                                                cleanup.and.revert(       comp,
                                                                                                sourcefile,
                                                                                                (not i.email.body.is.file))
                                                return(false)
                                endif
                                if i.interactive = true       then
                                                cmf.setdisplay(message.ID, ttyeno.yes)
                                endif
                                stat = cmf.send(message.ID,i.service)
                                if stat     <> 0 then
                                                o.err.msg = form.text$("tcwflk0013")
                                                |* Message could not be             sent (Infor ERP  LN eMessage
                                                |* Connector service refused message)
                                                cmf.stopService(i.service,2)
                                                cleanup.and.revert(       comp,
                                                                                                sourcefile,
                                                                                                (not i.email.body.is.file))
                                                return(false)
                                endif
                                stat = cmf.stopService(i.service,2)
                endif
                cleanup.and.revert(comp, sourcefile, (not i.email.body.is.file))
                return(true)
}
function domain               tcbool divide.and.add.recipient.to.xml(long   i.message.ID,
                                                                                                 domain                tcmcs.s999m i.addr,
                                                                                                 domain                ttcmf.role  i.role)
{
                boolean               recipient.set
                long       process.var.addr
                domain tcmcs.st80           hold.addr


                recipient.set =   false
                while(not isspace(i.addr))
                                process.var.addr = pos(i.addr, EMAIL_ID_SEP)

                                if process.var.addr > 0   then
                                                hold.addr = i.addr(1; process.var.addr - 1)
                                                i.addr = i.addr(process.var.addr + 1)
                                else
                                                hold.addr = i.addr
                                                i.addr = ""
                                endif

                                if not isspace(hold.addr) then
                                                create.recipient(i.message.ID, hold.addr, i.role)
                                                recipient.set =   true
                                endif
                endwhile

                return(recipient.set)
}

function create.recipient(   long                     i.message.ID,
                                domain      tcmcs.st80           i.recipient.address,
                                domain      ttcmf.role            i.role)
{
                long       recipient.ID
                long       ret

                if isspace(i.recipient.address)     then
                                return
                endif

                recipient.ID = cmf.createRecipient(i.message.ID, i.role)
                ret = cmf.setRecipientName(recipient.ID, i.recipient.address)
                ret = cmf.setRecipientAddress(recipient.ID, i.recipient.address)
                ret = cmf.setRecipientType(recipient.ID, "SMTP")                       
                if i.role = ttcmf.role.to then
                                ret = cmf.setRecipientResponsibility(recipient.ID, "TRUE")
                endif
}

function domain               tcbool link.attachments(long   i.message.ID,
                                                                                domain tcmcs.s999m i.att.path,
                                                                                domain tcmcs.s999m i.att,   
                                        long i.att.format,
                                        string sept(1),
                                        long   add.att.name)
                                                                     
{
                boolean               att.set
                long       att.ID
                long       ret
                long       process.var
                domain tcmcs.s999m      hold.att
        long    slash.pos                                                     

                att.set   = false
                while(not isspace(i.att.path))
                                process.var = pos(i.att.path, EMAIL_ID_SEP)

                                if process.var > 0 then
                                                hold.att = i.att.path(1; process.var - 1)
                                                i.att.path = i.att.path(process.var + 1)
                                else
                                                hold.att = i.att.path &    i.att
                                                i.att.path = ""
                                endif

                                if not isspace(hold.att) then
                                                att.ID = cmf.createAttachment(i.message.ID)
                                                ret = cmf.setAttachmentBody(att.ID, ttyeno.no)
                        on case i.att.format
                        case 0:
                                ret = cmf.setAttachmentMIME(att.ID, "application/pdf")
                                break
                        case 1:
                                ret = cmf.setAttachmentMIME(att.ID, "application/x-msexcel")
                                break
                        endcase
                        if add.att.name = 1 and not isspace(sept) and isspace(i.att) then
                                slash.pos = rpos(hold.att,sept)
                                i.att = hold.att(slash.pos + 1)
                                ret = cmf.setAttachmentFileName(att.ID,            hold.att, i.att)
                                i.att = ""
                        else
                                ret = cmf.setAttachmentFileName(att.ID,            hold.att, i.att)
                        endif
                                                att.set   = true
                                endif
                endwhile

                return(att.set)
}

function cleanup.and.revert(long   i.comp,
                                                    domain tcmcs.s999m i.tmp.file,
                                                    domain tcbool      i.del.file)
{
                compnr.check(i.comp)
                if i.del.file then
                                seq.unlink(i.tmp.file)
                endif
}

Monday 23 July 2018

LN DLL to convert Text (i.e. field with domain tctxtn) to String

function extern domain tcmcs.s512 gp.cus.dll0200.convert.text.field.to.value(
domain tcmcs.st20m i.text.variable)
{
string l.text.buffer(200, 10) mb
string l.return.value(512) mb
long l.number.of.text.lines
long i

l.return.value = ""
l.number.of.text.lines = text.to.buf(i.text.variable,
     language$,
             10, l.text.buffer)
if l.number.of.text.lines > 0 then
for i = 1 to l.number.of.text.lines
l.return.value = l.return.value & " " & trim$(l.text.buffer(1,i))
endfor
endif
return(l.return.value)
}

Thursday 29 March 2018

AFS to Process Billing Request (Compose, Print & Post)

#pragma used dll ottstpapihand
#pragma used dll ottdllbw

function extern domain  tcbool cicust.dll0001.compose.print.post.invoices( domain tcncmp i.financial.company,
domain cisli.brid i.billing.request,
domain cisli.devc i.device,
domain tcdate i.date,
ref domain tcmcs.s132m o.error.msg mb )
{
DllUsage
Expl : This function is used to completely process a given billing
  request. This does composing, printing and posting.
Pre : Financial Company should be the Current Company
Post : NA
Input : i.financial.company
  i.billing.request
  i.device -> Device to display the report.
  i.print.euro ->
Indicator whether EMU amount have to be printed
also in Euro or not.
Output : o.error.msg -> Error message when returning false
Returns : True -> When Billing Request is processed successfully
  False  -> Error in processing Billing Request
EndDllUsage

string error(200)
     
error = ""
o.error.msg = ""
        stpapi.put.field( "cisli2200m000", "f.billing.req.f", str$(i.billing.request))
        stpapi.put.field( "cisli2200m000", "f.billing.req.t", str$(i.billing.request))
        stpapi.put.field( "cisli2200m000", "f.composing", str$(etol(tcyesno.yes)))
        stpapi.put.field( "cisli2200m000", "f.br.compose", str$(etol(tcyesno.yes)))
        stpapi.put.field( "cisli2200m000", "f.invoice.date", str$(i.date))
        stpapi.put.field( "cisli2200m000", "f.br.print", str$(etol(tcyesno.yes)))
        stpapi.put.field( "cisli2200m000", "f.print.option", str$(etol(cisli.prno.original)))
        stpapi.put.field( "cisli2200m000", "f.print.in.euro", str$(etol(tcyesno.no)))
        stpapi.put.field( "cisli2200m000", "f.print.trans.dt", str$(i.date))
        stpapi.put.field( "cisli2200m000", "f.br.post", str$(etol(tcyesno.yes)))
        stpapi.put.field( "cisli2200m000", "f.post.trans.dt", str$(i.date))
        stpapi.put.field( "cisli2200m000", "f.br.set.device", i.device)
        stpapi.put.field( "cisli2200m000", "f.print.device", i.device)
        stpapi.put.field( "cisli2200m000", "f.post.device", i.device)
        stpapi.put.field( "cisli2200m000", "f.excp.device", i.device)

stpapi.form.command( "cisli2200m000", 5, "exec.cont.process", error )
        stpapi.end.session( "cisli2200m000" )

if not isspace(error) then
o.error.msg = error
return(false)
endif
return(true)
}

Wednesday 14 February 2018

Issue: Opening Balance of Ledger became 0 for Periods

When you have closed the previous year provisionally and then you run session: tfgld3203m000 (Rebuild Opening Balance/History from Transactions) for current year with checkbox "Opening Balance" selected. System will set the Opening Balance for all the periods of current year as zero.

To avoid this, you must run the "Rebuild Opening Balance/History from Transactions" session without selecting "Opening Balance" checkbox for current year.