Skip to content

Commit

Permalink
added new segments, added example for stp 820
Browse files Browse the repository at this point in the history
  • Loading branch information
mfdeveloper508 committed Apr 26, 2023
1 parent ac90a34 commit 2c25290
Show file tree
Hide file tree
Showing 16 changed files with 1,191 additions and 23 deletions.
50 changes: 50 additions & 0 deletions examples/example_stp_820/example.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2020 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package main

import (
"fmt"
"log"
"os"
"path"
"strings"

"github.com/moov-io/x12/pkg/file"
. "github.com/moov-io/x12/rules/rule_stp_820"
)

func main() {

reader, err := os.Open(path.Join("examples", "example_stp_820", "sample.txt"))
if err != nil {
log.Fatal(err)
}
defer reader.Close()

copyRule := InterchangeRule

eRule := copyRule.Group.GS.Elements["08"]
eRule.AcceptValues = []string{"004010STP820", "004010"}
copyRule.Group.GS.Elements["08"] = eRule

segmentTerminator := "\\"

newChange := file.NewFile(&InterchangeRule, segmentTerminator)

if err = newChange.Parse(file.NewScanner(reader, segmentTerminator)); err != nil {
log.Fatal(err.Error())
return
}

if err = newChange.Validate(); err != nil {
log.Fatal(err.Error())
return
}

fmt.Println(" REGENERATED FILE ")
fmt.Println(strings.ReplaceAll(newChange.String(), segmentTerminator, segmentTerminator+"\n"))

newChange.Print(os.Stdout)
}
15 changes: 15 additions & 0 deletions examples/example_stp_820/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ISA*00* *00* *30*227777777 *14*577777777 *120530*1144*U*00401*000000001*0*P*~\
GS*RA*227777777*577777777*20120530*1144*1*X*004010\
ST*820*0001\
BPR*C*7989.73*C*ACH*CTX*****1657777777**01*148529553*DA*92283334*20120531\
TRN*1*12053011440000192\
N1*PR*YOUR COMPANY*91*227777777\
N1*PE*WALMART\
ENT*1\
RMR*IV*7321239**953.19\
REF*PO*24305\
RMR*IV*7321511**7036.54\
REF*PO*24333\
SE*11*0001\
GE*1*1\
IEA*1*000000001\
146 changes: 146 additions & 0 deletions pkg/segments/ent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2020 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package segments

import (
"errors"
"fmt"
"github.com/moov-io/x12/pkg/rules"
"github.com/moov-io/x12/pkg/util"
)

func NewENT(rule *rules.ElementSetRule) SegmentInterface {

newSegment := ENT{}

if rule == nil {
newRule := make(rules.ElementSetRule)
newSegment.SetRule(&newRule)
} else {
newSegment.SetRule(rule)
}

return &newSegment
}

type ENT struct {
Field01 string `index:"01" json:"01" xml:"01"`
Field02 string `index:"02" json:"02" xml:"02"`
Field03 string `index:"03" json:"03,omitempty" xml:"03,omitempty"`
Field04 string `index:"04" json:"04,omitempty" xml:"04,omitempty"`

Element
}

func (r ENT) defaultMask(index int) string {
mask := rules.MASK_REQUIRED
if index >= 3 {
mask = rules.MASK_OPTIONAL
}
return mask
}

func (r ENT) fieldCount() int {
return 4
}

func (r ENT) Name() string {
return "ENT"
}

func (r *ENT) SetFieldByIndex(index string, data any) error {
return util.SetFieldByIndex(r, index, data)
}

func (r ENT) GetFieldByIndex(index string) any {
return util.GetFieldByIndex(r, index)
}

func (r *ENT) Validate(rule *rules.ElementSetRule) error {

if rule == nil {
rule = r.GetRule()
}

for i := 1; i <= r.fieldCount(); i++ {

idx := fmt.Sprintf("%02d", i)
if err := util.ValidateField(r.GetFieldByIndex(idx), rule.Get(idx), r.defaultMask(i)); err != nil {
return fmt.Errorf("ent's element (%s) has invalid value, %s", idx, err.Error())
}
}

return nil
}

func (r *ENT) Parse(data string, args ...string) (int, error) {

var line string
var err error
var size int

length := util.GetRecordSize(data, args...)
codeLen := len(r.Name())
read := codeLen + 1

if length < int64(read) {
return 0, errors.New("ent segment has not enough input data")
} else {
line = data[:length]
}

if r.Name() != data[:codeLen] {
return 0, errors.New("ent segment contains invalid code")
}

for i := 1; i <= r.fieldCount(); i++ {

var value string
idx := fmt.Sprintf("%02d", i)

if value, size, err = util.ReadField(line, read, r.GetRule().Get(idx), r.defaultMask(i), args...); err != nil {
return 0, fmt.Errorf("unable to parse ent's element (%s), %s", idx, err.Error())
} else {
read += size
r.SetFieldByIndex(idx, value)
}
}

return read, nil
}

func (r ENT) String(args ...string) string {
var buf string

for i := r.fieldCount(); i > 0; i-- {

idx := fmt.Sprintf("%02d", i)
value := r.GetFieldByIndex(idx)

if buf == "" {
mask := r.GetRule().GetMask(idx, r.defaultMask(i))
if mask == rules.MASK_NOTUSED {
continue
}
if mask == rules.MASK_OPTIONAL && (value == nil || fmt.Sprintf("%v", value) == "") {
continue
}
}

if buf == "" {
buf = fmt.Sprintf("%v%s", value, util.GetSegmentTerminator(args...))
} else {
buf = fmt.Sprintf("%v%s", value, util.DataElementSeparator) + buf
}
}

if buf == "" {
buf = fmt.Sprintf("%s%s", r.Name(), util.GetSegmentTerminator(args...))
} else {
buf = fmt.Sprintf("%s%s", r.Name(), util.DataElementSeparator) + buf
}

return buf
}
90 changes: 90 additions & 0 deletions pkg/segments/ent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2020 The Moov Authors
// Use of this source code is governed by an Apache License
// license that can be found in the LICENSE file.

package segments

import (
"testing"

"github.com/moov-io/x12/pkg/rules"
"github.com/stretchr/testify/require"
)

func TestForENT(t *testing.T) {

t.Run("parsing of ent segment", func(t *testing.T) {

seg := NewENT(nil)

in := "ENT*85*2*INDIAN HEALTH HOSPITAL*~"
read, err := seg.Parse(in)
require.NoError(t, err)
require.Equal(t, len(in), read)

in = "ENT*85*2*INDIAN HEALTH HOSPITAL**~"
read, err = seg.Parse(in)
require.NoError(t, err)
require.Equal(t, len(in)-1, read)

in = "ENT*85*2*INDIAN HEALTH HOSPITAL~"
read, err = seg.Parse(in)
require.NoError(t, err)
require.Equal(t, len(in), read)

in = "ENT"
read, err = seg.Parse(in)
require.Error(t, err)
require.Equal(t, "ent segment has not enough input data", err.Error())
require.Equal(t, 0, read)

in = "NMN~"
read, err = seg.Parse(in)
require.Error(t, err)
require.Equal(t, "ent segment contains invalid code", err.Error())
require.Equal(t, 0, read)
})

t.Run("encoding of ent segment", func(t *testing.T) {

seg := NewENT(nil)

require.Equal(t, "ENT**~", seg.String())

in := "ENT*85*2~"
read, err := seg.Parse(in)
require.NoError(t, err)
require.Equal(t, len(in), read)
require.Equal(t, in, seg.String())

require.NoError(t, seg.Validate(nil))
})

t.Run("parsing and encoding of ent segment with specified rule", func(t *testing.T) {

rule := rules.ElementSetRule{
"01": {AcceptValues: []string{"85"}},
"03": {Mask: rules.MASK_OPTIONAL},
"04": {Mask: rules.MASK_NOTUSED},
}

seg := NewENT(&rule)

in := "ENT*85*2*INDIAN HEALTH HOSPITAL*~"
read, err := seg.Parse(in)
require.NoError(t, err)
require.Equal(t, len(in), read)
require.Equal(t, "ENT*85*2*INDIAN HEALTH HOSPITAL~", seg.String())

seg.SetFieldByIndex("01", "86")
err = seg.Validate(nil)
require.Error(t, err)
require.Equal(t, "ent's element (01) has invalid value, the element contains unexpected value", err.Error())

in = "ENT*86*2*INDIAN HEALTH HOSPITAL~"
read, err = seg.Parse(in)
require.Error(t, err)
require.Equal(t, "unable to parse ent's element (01), the element contains unexpected value", err.Error())
require.Equal(t, 0, read)
})
}
Loading

0 comments on commit 2c25290

Please sign in to comment.