Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

response: support GL and Loan transaction codes for Returns/NOCs #252

Merged
merged 1 commit into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions examples/gl-debit.ach
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
101 231380104 1210428821906240000A094101Federal Reserve Bank My Bank Name
5225Name on Account 121042882 PPDREG.SALARY 190625 1121042880000001
64723138010412345678 0100000000 Receiver Account Name 0121042880000001
82250000010023138010000100000000000000000000121042882 121042880000001
9000001000001000000010023138010000100000000000000000000
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

11 changes: 11 additions & 0 deletions examples/loan-credit.ach
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
101 231380104 1210428821906240000A094101Federal Reserve Bank My Bank Name
5220Name on Account 121042882 PPDREG.SALARY 190625 1121042880000001
65223138010412345678 0100000000 Receiver Account Name 0121042880000001
82200000010023138010000000000000000100000000121042882 121042880000001
9000001000001000000010023138010000000000000000100000000
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
Expand All @@ -133,14 +131,10 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6Z
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
Expand Down
12 changes: 10 additions & 2 deletions pkg/response/entry_transformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,13 @@ func (t *CorrectionTransformer) MorphEntry(ctx context.Context, fh ach.FileHeade

// Set the TransactionCode from the EntryDetail
switch ed.TransactionCode {
case ach.CheckingCredit, ach.CheckingDebit, ach.SavingsCredit, ach.SavingsDebit:
case ach.CheckingCredit, ach.CheckingDebit, ach.SavingsCredit, ach.SavingsDebit,
ach.GLCredit, ach.GLDebit, ach.LoanCredit:
out.TransactionCode = ed.TransactionCode - 1

case ach.LoanDebit:
out.TransactionCode += 1 // LoanDebit (55) -> LoanReturnNOCDebit (56)

case ach.CheckingPrenoteCredit, ach.CheckingPrenoteDebit, ach.SavingsPrenoteCredit, ach.SavingsPrenoteDebit,
ach.GLPrenoteCredit, ach.GLPrenoteDebit, ach.LoanPrenoteCredit:
out.TransactionCode = ed.TransactionCode - 2
Expand Down Expand Up @@ -127,9 +131,13 @@ func (t *ReturnTransformer) MorphEntry(ctx context.Context, fh ach.FileHeader, b

// Set the TransactionCode from the EntryDetail
switch ed.TransactionCode {
case ach.CheckingCredit, ach.CheckingDebit, ach.SavingsCredit, ach.SavingsDebit:
case ach.CheckingCredit, ach.CheckingDebit, ach.SavingsCredit, ach.SavingsDebit,
ach.GLCredit, ach.GLDebit, ach.LoanCredit:
out.TransactionCode = ed.TransactionCode - 1

case ach.LoanDebit:
out.TransactionCode = ed.TransactionCode + 1 // LoanDebit (55) -> LoanReturnNOCDebit (56)

case ach.CheckingPrenoteCredit, ach.CheckingPrenoteDebit, ach.SavingsPrenoteCredit, ach.SavingsPrenoteDebit,
ach.GLPrenoteCredit, ach.GLPrenoteDebit, ach.LoanPrenoteCredit:
out.TransactionCode = ed.TransactionCode - 2
Expand Down
93 changes: 93 additions & 0 deletions pkg/response/entry_transformer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"path/filepath"
"testing"
"time"

"github.com/moov-io/ach"
"github.com/moov-io/ach-test-harness/pkg/service"
Expand Down Expand Up @@ -34,6 +35,7 @@ func TestMorphEntry__Correction(t *testing.T) {
t.Fatal("exected Addenda98 record")
}
require.NotEqual(t, ed.TraceNumber, out.TraceNumber)
require.Equal(t, ach.CheckingReturnNOCDebit, out.TransactionCode)
require.Equal(t, ed.TraceNumber, out.Addenda98.OriginalTrace)
require.Equal(t, "C01", out.Addenda98.ChangeCode)
require.Equal(t, "45111616", out.Addenda98.CorrectedData)
Expand Down Expand Up @@ -71,13 +73,96 @@ func TestMorphEntry__Return(t *testing.T) {
t.Fatal("exected Addenda99 record")
}
require.NotEqual(t, ed.TraceNumber, out.TraceNumber)
require.Equal(t, ach.CheckingReturnNOCDebit, out.TransactionCode)
require.Equal(t, "12104288", out.RDFIIdentification)
require.Equal(t, "2", out.CheckDigit)
require.Equal(t, ed.TraceNumber, out.Addenda99.OriginalTrace)
require.Equal(t, "R01", out.Addenda99.ReturnCode)
require.Equal(t, "23138010", out.Addenda99.OriginalDFI)
}

func TestMorphEntry_Return_GL(t *testing.T) {
file, err := ach.ReadFile(filepath.Join("..", "..", "examples", "gl-debit.ach"))
require.NoError(t, err)

xform := &ReturnTransformer{}
action := service.Action{
Return: &service.Return{
Code: "R03",
},
}
bh := file.Batches[0].GetHeader()
ed := file.Batches[0].GetEntries()[0]
out, err := xform.MorphEntry(context.Background(), file.Header, bh, ed, &action)
require.NoError(t, err)

if out.Addenda98 != nil {
t.Fatal("unexpected Addenda98")
}
if out.Addenda99 == nil {
t.Fatal("exected Addenda99 record")
}
require.NotEqual(t, ed.TraceNumber, out.TraceNumber)
require.Equal(t, ach.GLReturnNOCDebit, out.TransactionCode)
require.Equal(t, "12104288", out.RDFIIdentification)
require.Equal(t, "2", out.CheckDigit)
require.Equal(t, ed.TraceNumber, out.Addenda99.OriginalTrace)
require.Equal(t, "R03", out.Addenda99.ReturnCode)
require.Equal(t, "23138010", out.Addenda99.OriginalDFI)

// Try the reversal
err = file.Reversal(time.Now())
require.NoError(t, err)

bh = file.Batches[0].GetHeader()
ed = file.Batches[0].GetEntries()[0]

out, err = xform.MorphEntry(context.Background(), file.Header, bh, ed, &action)
require.NoError(t, err)
require.Equal(t, ach.GLReturnNOCCredit, out.TransactionCode)
}

func TestMorphEntry_Return_Loan(t *testing.T) {
file, err := ach.ReadFile(filepath.Join("..", "..", "examples", "loan-credit.ach"))
require.NoError(t, err)

xform := &ReturnTransformer{}
action := service.Action{
Return: &service.Return{
Code: "R03",
},
}
bh := file.Batches[0].GetHeader()
ed := file.Batches[0].GetEntries()[0]
out, err := xform.MorphEntry(context.Background(), file.Header, bh, ed, &action)
require.NoError(t, err)

if out.Addenda98 != nil {
t.Fatal("unexpected Addenda98")
}
if out.Addenda99 == nil {
t.Fatal("exected Addenda99 record")
}
require.NotEqual(t, ed.TraceNumber, out.TraceNumber)
require.Equal(t, ach.LoanReturnNOCCredit, out.TransactionCode)
require.Equal(t, "12104288", out.RDFIIdentification)
require.Equal(t, "2", out.CheckDigit)
require.Equal(t, ed.TraceNumber, out.Addenda99.OriginalTrace)
require.Equal(t, "R03", out.Addenda99.ReturnCode)
require.Equal(t, "23138010", out.Addenda99.OriginalDFI)

// Try the reversal
err = file.Reversal(time.Now())
require.NoError(t, err)

bh = file.Batches[0].GetHeader()
ed = file.Batches[0].GetEntries()[0]

out, err = xform.MorphEntry(context.Background(), file.Header, bh, ed, &action)
require.NoError(t, err)
require.Equal(t, ach.LoanReturnNOCDebit, out.TransactionCode)
}

func TestMorphEntry__Prenote(t *testing.T) {
file, err := ach.ReadFile(filepath.Join("..", "..", "testdata", "prenote.ach"))
require.NoError(t, err)
Expand Down Expand Up @@ -142,4 +227,12 @@ func TestMorphEntry__Prenote(t *testing.T) {
require.Equal(t, "R01", out.Addenda99.ReturnCode, msg)
}
})

t.Run("loan", func(t *testing.T) {
// TODO(adam):
})

t.Run("general-ledger", func(t *testing.T) {
// TODO(adam):
})
}
Loading