Automatic TA1 acknowledgment to X12 messages

The Interchange or TA1 Acknowledgment is a means of replying to an interchange or transmission that has been sent. The TA1 acknowledgment verifies the  envelopes only.

Transaction set-specific verification is accomplished through use of the Functional Acknowledgment Transaction Set, 997. See A.1.5.2, Functional Acknowledgment, 997, for more details.

In this example we create “Interchange Acknowledgment, TA1”. Creating “Functional Acknowledgment Transaction Set, 997” is subject for different example.

The TA1 is a single segment and is unique in the sense that this single segment is transmitted without the GS/GE envelope structures. A TA1 can be included in an interchange with other functional groups and transactions.

For complete description refer to A.1.5.1 in “Electronic Data Interchange Transaction Set Implementation Guide” for “HealthCare Eligibility Benefit Inquiry and Response” (Includes October 2002 Addenda Changes) the “270/271 Combined May 2000 004010X092 and October 2002” 004010X092A1

require 'x12node'
require 'x12TA1'

function main(Message)

   local In = x12.parse{
      vmd = 'x12.vmd', data = Message }

   local Out = x12.message{
      vmd = 'TA1.vmd',name = 'TA1' }

   Ack = x12TA1.TA1Ack_004010X091(In, Out)

   return Ack    
end

Example is using three shared files: x12node, subs, and x12TA1, presented below.

When dealing with conformance to Standard, many values forced to appear *hard-coded*. However, lists of *valid* values are subject to any specific interface implementation. Lists can be expanded with additional values as needed.

Shared file ‘x12node’:

-- node functions for use with X12

function node.N(n)
   return type(tonumber(n:nodeValue())) == "number" 
end

function node.S(n)
   return tostring(n)
end

function node.E(n)
   return ((#(string.gsub( n:nodeValue(),' ', ''))) == 0)
end

function node.L(n,l)
   for i, v in ipairs(l) do
      if  string.gsub( n:nodeValue(), ' ', '') == v then
         return true
      end
   end
end

Shared file ‘x12TA1’:

Functions in this file bound by recommendations and  “hardcoded” values based on document “Electronic Data Interchange Transaction Set Implementation Guide” for “HealthCare Eligibility Benefit Inquiry and Response” (Includes October 2002 Addenda Changes) the “270/271 Combined May 2000 004010X092 and October 2002” 004010X092A1

 

x12TA1 = {}

local function toX12(S)
   S = string.gsub (S, "|", "*")
   S = string.gsub (S, "r", "~")
   return string.gsub(S..'~',"*~","~")
end

local function TA105_004010X091(n)

    -- supported Standard List
    SSL =
        {'U'}
    -- supported Controls Version List
    SCV =
        {'00401'}
    -- valid Interchange ID Qualifier For Sender List
    VIIQFS =
        {'01','14','20','27','28','29','30','33','ZZ'}
    -- valid Interchange Sender ID List
    VISI =
        {'345529167','Sender'}
    -- valid Interchange ID Qualifier For Receiver List
    VIIQFR =
        {'01','14','20','27','28','29','30','33','ZZ'}
    -- valid Interchange Receiver ID List
    VIRI =
        {'445483154','ReceiverID','4000136'}
    -- valid Authorization Information Qualifier Value List
    VAIQV =
        {'00','03'}
    -- valid Security Information Qualifier Value List
    VSIQV =
        {'00','01'}

    I07L = 15
    I01L = 10
    I03L = 10
    I11L = 5

   if n.ISA[13]:nodeValue() ~= n.IEA[2]:nodeValue() then
      return '001'
   end

   if n.ISA[13]:E() then
      return "018"
    end

    if n.IEA[2]:E() then
      return "018"
    end

   if not n.ISA[13]:N() then
      return "018"
    end

    if not n.IEA[2]:N() then
      return "018"
    end

     if not n.ISA[11]:L(SSL) then
      return "002"
    end

     if n.ISA[11]:E() then
      return "016"
    end

    if #(n.ISA[11]:nodeValue()) > 1 then
      return "016"
    end

    if not n.ISA[12]:L(SCV) then
      return "003"
    end

    if not n.ISA[5]:L(VIIQFS) then
      return "005"
    end     

    if not n.ISA[7]:L(VIIQFR) then
      return "007"
    end

   if #(n.ISA[8]:nodeValue()) > I07L
            or n.ISA[8]:E() then
      return "008"
    end

    if not n.ISA[8]:L(VIRI) then
       return "009"
    end

    if not n.ISA[1]:L(VAIQV) then
      return "010"
    end                                           

    if n.ISA[1]:nodeValue() == '00' and
            not n.ISA[2]:E()
            then
       return '011'
    end        

    if n.ISA[1]:nodeValue() == '03' and
            n.ISA[2]:E()
            then
       return '011'
    end

    if n.ISA[1]:nodeValue() == '03' and
            #(n.ISA[2]:nodeValue()) > I01L
            then
       return '011'
    end

    if not n.ISA[3]:L(VSIQV) then
      return "012"
    end

    if n.ISA[3]:nodeValue() == '00' and
            not n.ISA[4]:E()
            then
       return '013'
    end

    if n.ISA[3]:nodeValue() == '03' and
            n.ISA[4]:E()
            then
       return '013'
    end

    if n.ISA[3]:nodeValue() == '03' and
            #(n.ISA[4]:nodeValue()) > I03L
            then
       return '013'
    end

    if n.ISA[9]:nodeValue() ~=
       os.date("%y%m%d",os.time{
            year = "20"..string.sub(
               n.ISA[9]:nodeValue(),1,2
            ),
            month = string.sub(
               n.ISA[9]:nodeValue(),3,4
            ),
            day = string.sub(
               n.ISA[9]:nodeValue(),5,6
            ),
            hour = string.sub(
               n.ISA[10]:nodeValue(),1,2
            ),
            minute = string.sub(
               n.ISA[10]:nodeValue(),3,4
            )}
      ) then
       return "014"
    end

    if n.ISA[10]:nodeValue() ~=
       os.date("%H%M",os.time{
            year = "20"..string.sub(
               n.ISA[9]:nodeValue(),1,2
            ),
            month = string.sub(
               n.ISA[9]:nodeValue(),3,4
            ),
            day = string.sub(
               n.ISA[9]:nodeValue(),5,6
            ),
            hour = string.sub(
               n.ISA[10]:nodeValue(),1,2
            ),
            minute = string.sub(
               n.ISA[10]:nodeValue(),3,4
            )}
      ) then
       return "015"
     end     

    if #(n.ISA[12]:nodeValue()) ~= I11L then
       return '017'
    end              

    return '000'   
end

function x12TA1.TA1Ack_004010X091(In, Out)
   InIE = In.IE

   Out.ISA = InIE.ISA
   Out.IEA = InIE.IEA

   Out.ISA[14] = '0'

   Out.ISA[16] = ':'

   Out.TA1[1] = InIE.IEA[2]

   Out.TA1[2] = InIE.ISA[9]

   Out.TA1[3] = InIE.ISA[10]

   Out.TA1[5] = TA105_004010X091(InIE)

   if Out.TA1[5]:nodeValue()  == '000' then
      Out.TA1[4] = 'A'
   else
      Out.TA1[4] = 'R'
   end     

   return (toX12(Out:S()))

end

Two generic vmd files added to “other” files: X12.vmd and TA1.vmd (attached below). Both are generic and dealing only with those parts of X12 message structure which are relevant in scope of automatic generation of TA1 Acknowledgment. There is no practical need to expand (AKA complicate) these vmd files to deal with other particulars of X12 messages. This example shows TA1 for 270/271 “HealthCare Eligibility Benefit Inquiry and Response” scenario, but in similar way it can be reworked to service acknowledgments to other transactions.

x12.vmdTA1.vmd