Skip to content
Open
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
14 changes: 12 additions & 2 deletions batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,11 @@ func (b *Batch) upsertOffsets() error {
debitED := createOffsetEntryDetail(b.offset, b)
debitED.TraceNumber = fmt.Sprintf("%15.15d", lastTraceNumber(b.Entries)+offsetCount)
debitED.Amount = b.Control.TotalCreditEntryDollarAmount
if len(b.offset.Addenda05) > 0 {
debitED.AddendaRecordIndicator = 1
debitED.Addenda05 = make([]*Addenda05, len(b.offset.Addenda05))
copy(debitED.Addenda05, b.offset.Addenda05)
}
switch b.offset.AccountType {
case OffsetChecking:
debitED.TransactionCode = CheckingDebit
Expand All @@ -1247,6 +1252,11 @@ func (b *Batch) upsertOffsets() error {
creditED := createOffsetEntryDetail(b.offset, b)
creditED.TraceNumber = fmt.Sprintf("%15.15d", lastTraceNumber(b.Entries)+offsetCount)
creditED.Amount = b.Control.TotalDebitEntryDollarAmount
if len(b.offset.Addenda05) > 0 {
creditED.AddendaRecordIndicator = 1
creditED.Addenda05 = make([]*Addenda05, len(b.offset.Addenda05))
copy(creditED.Addenda05, b.offset.Addenda05)
}
switch b.offset.AccountType {
case OffsetChecking:
creditED.TransactionCode = CheckingCredit
Expand All @@ -1260,12 +1270,12 @@ func (b *Batch) upsertOffsets() error {
// Add both EntryDetails to our Batch and recalculate some fields
if debitED != nil {
b.AddEntry(debitED)
b.Control.EntryAddendaCount += 1
b.Control.EntryAddendaCount += 1 + debitED.addendaCount()
b.Control.TotalDebitEntryDollarAmount += debitED.Amount
}
if creditED != nil {
b.AddEntry(creditED)
b.Control.EntryAddendaCount += 1
b.Control.EntryAddendaCount += 1 + creditED.addendaCount()
b.Control.TotalCreditEntryDollarAmount += creditED.Amount
}
b.Header.ServiceClassCode = MixedDebitsAndCredits
Expand Down
37 changes: 37 additions & 0 deletions batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,43 @@ func TestBatch__CalculateBalancedOffsetDebit(t *testing.T) {
}
}

func TestBatch_OffsetAddenda05(t *testing.T) {
file, err := ReadFile(filepath.Join("test", "testdata", "ppd-debit.ach"))
require.NoError(t, err)

entries := file.Batches[0].GetEntries()
require.Len(t, entries, 1)

addenda05 := NewAddenda05()
addenda05.PaymentRelatedInformation = "abc123"
addenda05.SequenceNumber = 1
addenda05.EntryDetailSequenceNumber = 2

file.Batches[0].WithOffset(&Offset{
RoutingNumber: "121042882",
AccountNumber: "123456789",
AccountType: OffsetChecking,
Description: "test offset",
Addenda05: []*Addenda05{addenda05},
})

// retabulate
err = file.Batches[0].Create()
require.NoError(t, err)

err = file.Create()
require.NoError(t, err)

// verify offset entry was added
entries = file.Batches[0].GetEntries()
require.Len(t, entries, 2)
require.Empty(t, entries[0].Addenda05)

// Check the Addenda05 on our offset record PaymentRelatedInformation
require.Len(t, entries[1].Addenda05, 1)
require.Equal(t, "abc123", entries[1].Addenda05[0].PaymentRelatedInformation)
}

func TestBatch__CalculateBalancedOffsetDebitAndCredit(t *testing.T) {
off := &Offset{
RoutingNumber: "121042882",
Expand Down
11 changes: 10 additions & 1 deletion batcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,21 @@ type Batcher interface {
SetValidation(*ValidateOpts)
}

// Offset contains the associated information to append an 'Offset Record' on an ACH batch during Create.
// Offset contains the fields required to append a balancing EntryDetail to a Batch during Create.
//
// After tabulating the amounts and counts a batch with an Offset field populated will create
// an EntryDetail record that balances the net debit/credit of the file. This is often used to upload
// balanced files (files whose debit and credit totals match).
//
// The EntryDetail offset record will have an IndividualName of "OFFSET" and any existing EntryDetails
// with an exactly matching IndividualName will be deleted from the file.
type Offset struct {
RoutingNumber string `json:"routingNumber"`
AccountNumber string `json:"accountNumber"`
AccountType OffsetAccountType `json:"accountType"`
Description string `json:"description"`

Addenda05 []*Addenda05 `json:"addenda05"`
}

type OffsetAccountType string
Expand Down
14 changes: 14 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2571,6 +2571,15 @@ components:
- totalDebit
- totalCredit
Offset:
description: |
Offset contains the fields required to append a balancing EntryDetail to a Batch during Create.

After tabulating the amounts and counts a batch with an Offset field populated will create
an EntryDetail record that balances the net debit/credit of the file. This is often used to upload
balanced files (files whose debit and credit totals match).

The EntryDetail offset record will have an IndividualName of "OFFSET" and any existing EntryDetails
with an exactly matching IndividualName will be deleted from the file.
properties:
routingNumber:
type: string
Expand All @@ -2590,6 +2599,11 @@ components:
type: string
description: Memo for Offset EntryDetail record
example: OFFSET
addenda05:
type: array
description: List of Addenda05 records
items:
$ref: '#/components/schemas/Addenda05'
required:
- routingNumber
- accountNumber
Expand Down
2 changes: 1 addition & 1 deletion server/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func TestFiles_CreateWithOffset(t *testing.T) {
require.Equal(t, "088888880123460", entries[1].TraceNumber)

offset := reflect.ValueOf(b).Elem().FieldByName("offset")
expected := `&ach.Offset{RoutingNumber:"987654320", AccountNumber:"123123123", AccountType:"checking", Description:"OFFSET"}`
expected := `&ach.Offset{RoutingNumber:"987654320", AccountNumber:"123123123", AccountType:"checking", Description:"OFFSET", Addenda05:[]*ach.Addenda05(nil)}`
require.Equal(t, expected, fmt.Sprintf("%#v", offset))
}

Expand Down
Loading