cadeft

package module
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2024 License: Apache-2.0 Imports: 14 Imported by: 0

README

cadeft

Moov Banner Logo

Community · Blog

GoDoc Build Status Coverage Status Go Report Card Repo Size Apache 2 License Slack Channel GitHub Stars Twitter

Moov's mission is to give developers an easy way to create and integrate bank processing into their own software products. Our open source projects are each focused on solving a single responsibility in financial services and designed around performance, scalability, and ease of use.

Description

cadeft is a parser library designed for parsing and generating Electronic Funds Transfer (EFT) files adhereing to the Payments Canada 005 specification.

Reading EFT files

There are 2 options to read files either cadeft.Reader or cadeft.FileStreamer

cadeft.Reader

Reader will attempt to read all transactions from an EFT file and return a populated cadeft.File struct or a collection of errors encountered during parsing.

file, err := os.Open("./eft_file.txt")
if err != nil {
  return err
}

// Create a new reader passing an io.Reader
reader := cadeft.NewReader(file)

// attempt to read the file
eftFile, err := reader.ReadFile()
if err != nil {
  return err
}

// print out all transers or handle the file
for _, txn := range eftFile.Txns {
  fmt.Printf("%+v", txn)
}
cadeft.FileStreamer

cadeft.FileStreamer will read one transaction from a file at a time or return an error. Consecutive calls to ScanTxn() will read the next transaction or return an error. FileStreamer will keep state of the parser's position and return new transactions every call. This allows the caller to either ignore errors that have surfaced when parsing/validating a transaction and construct their own array of cadeft.Transaction structs. You can also call Validate() on a cadeft.Transaction struct which will validate all fields against the Payments Canada 005 Spec.

file, err := os.Open("./eft_file.txt")
if err != nil {
  return err
}

// instantiate a new FileStreamer
stramer := cadeft.NewFileStreamer(file)

// start reading the file
for {
  // every iteration a new transaction is returned or an error
  txn, err := fileStreamer.ScanTxn()
		if err != nil {
            // an io.EOF is returned when parsing is complete
			if err == io.EOF {
				break
			}

            // handle the parse error as you want
			var parseErr *cadeft.ParseError
			if ok := errors.As(err, &parseErr); ok {
				log.Err(parseErr).Msg("encountered parse error when processing incoming file")
				continue
			} else {
				log.Err(err).Msg("fatal error when streaming transaction from file")
				return err
			}
		}

  // validate that the parsed txn is valid
  err = txn.Validate()
  if err != nil {
    return err
  }
}

NOTE: Because ScanTxn keeps track of the parser's state it is not concurrency-safe if you want to incorporate some level of concurrency make sure the call to ScanTxn() is outside of a go routine like so:

...
fileStreamer := cadeft.NewFileStreamer(file)

wg := sync.WaitGroup{}
batchSize := 10
guard := make(chan struct{}, batchSize)

for {
  txn, err := fileStreamer.ScanTxn()
  if err != nil {
    // handle the error any which way you want
  }

  // read transactions into memory and concurrently handle each txn
  guard <- struct{}{}
  wg.Add(1)
  go func() {
    defer func() {
      wg.Done()
      <-guard
    }()
    // do your thing...
  }
  wg.Wait()
}

Write EFT Files

To write an EFT file construct a cadeft.File struct with the appropriate Header, Footer and []Transactions. You can confirm that your file is valid by calling File.Validate() or Validate() on the Header, Footer and each individual Transaction.

// create the file header
header := cadeft.NewFileHeader("123456789", 1, time.Now(), int64(610), "CAD")

// create a transaction, in this case it's a credit transaction
txn := cadeft.NewTransaction(
  cadeft.CreditRecord, // recod type
  "450", // transaction code
  420, // amount
  Ptr(time.Now()), // date
  "123456789", // institution ID
  "12345", // account number
  "222222222222222", // item trace nnumber
  "payor name", // payor/payee name
  "payor long name", // payor/payee long name
  "987654321", // return institution ID
  "54321", // return account number
  "", // original item trace number (only used for returns)
  cadeft.WithCrossRefNo("0000100000024"), // cross ref number (optional)
)

// create a new cadeft.File instance with header and txn
file := cadeft.NewFile(header, cadeft.Transactions{txn})
if err := file.Validate(); err != nil {
  // file does not adhere to the 005 spec
  return err
}

// serialize the file into payments canada 005 spec
serializedFile, err := file.Create()
if err != nil {
  // error when writing the file
  return err
}

// write the serialized string to a file or print it out
fmt.Printf("%s", serializedFile)

Project status

cadeft is currently being developed for use in multiple production environments. The library was developed in large part by Synctera. Please star the project if you are interested in its progress. Let us know if you encounter any bugs/unclear documentation or have feature suggestions by opening up an issue or pull request. Thanks!

Getting help

channel info
Project Documentation Our project documentation available online.
Twitter @moov You can follow Moov.io's Twitter feed to get updates on our project(s). You can also tweet us questions or just share blogs or stories.
GitHub Issue If you are able to reproduce a problem please open a GitHub Issue under the specific project that caused the error.
moov-io slack Join our slack channel (#cadeft) to have an interactive discussion about the development of the project.

Supported and tested platforms

  • 64-bit Linux (Ubuntu, Debian), macOS, and Windows

Contributing

Yes please! Please review our Contributing guide and Code of Conduct to get started!

This project uses Go Modules and Go v1.20 or newer. See Golang's install instructions for help setting up Go. You can download the source code and we offer tagged and released versions as well. We highly recommend you use a tagged release for production.

Releasing

To make a release of cadeft simply open a pull request with CHANGELOG.md and version.go updated with the next version number and details. You'll also need to push the tag (i.e. git push origin v1.0.0) to origin in order for CI to make the release.

Testing

We maintain a comprehensive suite of unit tests and recommend table-driven testing when a particular function warrants several very similar test cases. After starting the services with Docker Compose run all tests with go test ./.... Current overall coverage can be found on Codecov.

License

Apache License 2.0 - See LICENSE for details.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// parse errors
	ErrInvalidRecordLength = fmt.Errorf("transaction record is not 240 characters")
	// Validation errors
	ErrMissingOriginatorId                   = fmt.Errorf("missing originator ID")
	ErrMissingCreationDate                   = fmt.Errorf("missing creation date")
	ErrInvalidRecordType                     = fmt.Errorf("invalid record type")
	ErrInvalidCurrencyCode                   = fmt.Errorf("invalid currency code")
	ErrInvalidOriginatorIdLength             = fmt.Errorf("invalid originator ID length")
	ErrInvalidOriginatorId                   = fmt.Errorf("invalid originator ID not alpha numeric")
	ErrInvalidFileCreationNum                = fmt.Errorf("invalid file creation number")
	ErrInvalidDestinationDataCenterNo        = fmt.Errorf("invalid destination data center")
	ErrInvalidDirectClearerCommunicationArea = fmt.Errorf("invalid direct clearer communication area")
	ErrScanParseError                        = fmt.Errorf("failed to parse txn")
)

Functions

func Arr

func Arr[T any](v T) []*T

func NewParseError

func NewParseError(err error, msg string) error

func NewValidationError

func NewValidationError(err error) error

func Ptr

func Ptr[T any](v T) *T

Types

type BaseTxn

type BaseTxn struct {
	TxnType               TransactionType `json:"txn_type" validate:"required,numeric,max=3"`
	Amount                int64           `json:"amount" validate:"required,max=9999999999"`
	ItemTraceNo           string          `json:"item_trace_no" validate:"eft_num,max=22"`
	InstitutionID         string          `json:"institution_id" validate:"required,eft_num,max=9"`
	StoredTransactionType TransactionType `json:"stored_txn_type" validate:"eft_num,max=3"`
	OriginatorShortName   string          `json:"short_name" validate:"max=15"`
	OriginatorLongName    string          `json:"long_name" validate:"required,max=30"`
	UserID                string          `json:"user_id" validate:"eft_alpha,max=10"`
	CrossRefNo            string          `json:"cross_ref_no" validate:"eft_alpha,max=19"`
	SundryInfo            string          `json:"sundry_info" validate:"eft_alpha,max=15"`
	SettlementCode        string          `json:"settlement_code" validate:"eft_alpha,max=2"`
	InvalidDataElementID  string          `json:"invalid_data_element_id" validate:"eft_num,max=11"`
	RecordType            RecordType      `json:"type" validate:"rec_type"`
}

BaseTxn represents the common fields of every Transaction record D, C, E, F, I and J

func (BaseTxn) GetAmount

func (b BaseTxn) GetAmount() int64

GetAmount returns the amount being transacted

type BaseTxnOpt

type BaseTxnOpt func(d *BaseTxn)

func WithCrossRefNo

func WithCrossRefNo(s string) BaseTxnOpt

WithCrossRefNo sets the Originator'sCross Reference No. field 15

func WithInvalidDataElementID

func WithInvalidDataElementID(s string) BaseTxnOpt

WithInvalidDataElementID sets the Invalid Data Element No. field 21 mainly used for returns to indicate which fields are incorrect

func WithSettlementCode

func WithSettlementCode(s string) BaseTxnOpt

WithSettlementCode sets the Originator-Direct Clearer Settlement Code, field 20

func WithStoredTransactionType

func WithStoredTransactionType(s string) BaseTxnOpt

WithStoredTransactionType sets the Stored Transaction Type, field 10 mainly used for returns and reversals (J, I, E and F records)

func WithSundryInfo

func WithSundryInfo(s string) BaseTxnOpt

WithSundryInfo sets the Originator's Sundry Information, field 18

func WithUserID

func WithUserID(s string) BaseTxnOpt

WithUserID sets the Originating DirectClearer's User's ID, field 14

type Credit

type Credit struct {
	BaseTxn
	DateFundsAvailable  *time.Time `json:"date_funds_available" validate:"required"`
	PayeeAccountNo      string     `json:"payee_account_no" validate:"required,max=12,numeric"`
	PayeeName           string     `json:"payee_name" validate:"required,max=30"`
	ReturnInstitutionID string     `json:"return_institution_id" validate:"required,max=9,numeric"`
	ReturnAccountNo     string     `json:"return_account_no" validate:"required,max=12,eft_alpha"`
}

Credit represents Logical Record Type C according to the EFT standard 005

func NewCredit

func NewCredit(
	txnType TransactionType,
	amount int64,
	dateFundsAvailable *time.Time,
	institutionID string,
	payeeAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payeeName string,
	originatorLongName string,
	returnInstitutionID string,
	returnAccountNo string,
	opts ...BaseTxnOpt,
) Credit

func (Credit) Build

func (c Credit) Build() (string, error)

Build serializes a Credit into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (Credit) GetAccountNo

func (c Credit) GetAccountNo() string

func (Credit) GetAmount

func (c Credit) GetAmount() int64

func (Credit) GetBaseTxn

func (c Credit) GetBaseTxn() BaseTxn

func (Credit) GetDate

func (c Credit) GetDate() *time.Time

func (Credit) GetName

func (c Credit) GetName() string

func (Credit) GetOriginalAccountNo

func (c Credit) GetOriginalAccountNo() string

func (Credit) GetOriginalInstitutionID

func (c Credit) GetOriginalInstitutionID() string

func (Credit) GetOriginalItemTraceNo

func (c Credit) GetOriginalItemTraceNo() string

func (Credit) GetReturnAccountNo

func (c Credit) GetReturnAccountNo() string

func (Credit) GetReturnInstitutionID

func (c Credit) GetReturnInstitutionID() string

func (Credit) GetType

func (c Credit) GetType() RecordType

func (*Credit) Parse

func (c *Credit) Parse(data string) error

Parse takes in a serialized transaction segment and populates a Credit struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (Credit) Validate

func (c Credit) Validate() error

Validate checks whether the fields of a Credit struct contain the correct fields that are required when writing/reading an EFT file. The validation check can be found on Section D of EFT standard 005.

type CreditReturn

type CreditReturn struct {
	BaseTxn
	DateFundsAvailable    *time.Time `json:"date_funds_available" validate:"required"`
	PayeeAccountNo        string     `json:"payee_account_no" validate:"required,max=12,numeric"`
	PayeeName             string     `json:"payee_name" validate:"required,max=30"`
	OriginalInstitutionID string     `json:"original_institution_id" validate:"required,max=9,numeric"`
	OriginalAccountNo     string     `json:"original_account_no" validate:"required,max=12,eft_alpha"`
	OriginalItemTraceNo   string     `json:"original_item_trace_no" validate:"required,eft_num,max=22"`
}

CreditReturn represents Logical Record Type I according to the EFT standard 005

func NewCreditReturn

func NewCreditReturn(
	txnType TransactionType,
	amount int64,
	dateFundsAvailable *time.Time,
	institutionID string,
	payeeAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payeeName string,
	originatorLongName string,
	originalInstitutionID string,
	originalAccountNo string,
	originalItemTraceNo string,
	opts ...BaseTxnOpt) CreditReturn

func (CreditReturn) Build

func (c CreditReturn) Build() (string, error)

Build serializes a CreditReturn into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (CreditReturn) GetAccountNo

func (c CreditReturn) GetAccountNo() string

func (CreditReturn) GetAmount

func (c CreditReturn) GetAmount() int64

func (CreditReturn) GetBaseTxn

func (c CreditReturn) GetBaseTxn() BaseTxn

func (CreditReturn) GetDate

func (c CreditReturn) GetDate() *time.Time

func (CreditReturn) GetName

func (c CreditReturn) GetName() string

func (CreditReturn) GetOriginalAccountNo

func (c CreditReturn) GetOriginalAccountNo() string

func (CreditReturn) GetOriginalInstitutionID

func (c CreditReturn) GetOriginalInstitutionID() string

func (CreditReturn) GetOriginalItemTraceNo

func (c CreditReturn) GetOriginalItemTraceNo() string

func (CreditReturn) GetReturnAccountNo

func (c CreditReturn) GetReturnAccountNo() string

func (CreditReturn) GetReturnInstitutionID

func (c CreditReturn) GetReturnInstitutionID() string

func (CreditReturn) GetType

func (c CreditReturn) GetType() RecordType

func (*CreditReturn) Parse

func (c *CreditReturn) Parse(data string) error

Parse takes in a serialized transaction segment and populates a CreditReturn struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (CreditReturn) Validate

func (c CreditReturn) Validate() error

Validate checks whether the fields of a CreditReturn struct contain the correct fields that are required when writing/reading an EFT file. The validation check can be found on Section D of EFT standard 005.

type CreditReverse

type CreditReverse struct {
	BaseTxn
	DateFundsAvailable  *time.Time `json:"date_funds_available" validate:"required"`
	PayeeAccountNo      string     `json:"payee_account_no" validate:"required,max=12,numeric"`
	PayeeName           string     `json:"payee_name" validate:"required,max=30"`
	ReturnInstitutionID string     `json:"return_institution_id" validate:"required,max=9,numeric"`
	ReturnAccountNo     string     `json:"return_account_no" validate:"required,max=12,eft_alpha"`
	OriginalItemTraceNo string     `json:"original_item_trace_no" validate:"required,eft_num,max=22"`
}

CreditReverse represents Logical Record Type E according to the EFT standard 005

func NewCreditReverse

func NewCreditReverse(
	txnType TransactionType,
	amount int64,
	dateFundsAvailable *time.Time,
	institutionID string,
	payeeAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payeeName string,
	originatorLongName string,
	returnInstitutionID string,
	returnAccountNo string,
	originalItemTraceNo string,
	opts ...BaseTxnOpt) CreditReverse

func (CreditReverse) Build

func (c CreditReverse) Build() (string, error)

Build serializes a CreditReverse into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (CreditReverse) GetAccountNo

func (c CreditReverse) GetAccountNo() string

func (CreditReverse) GetAmount

func (c CreditReverse) GetAmount() int64

func (CreditReverse) GetBaseTxn

func (c CreditReverse) GetBaseTxn() BaseTxn

func (CreditReverse) GetDate

func (c CreditReverse) GetDate() *time.Time

func (CreditReverse) GetName

func (c CreditReverse) GetName() string

func (CreditReverse) GetOriginalAccountNo

func (c CreditReverse) GetOriginalAccountNo() string

func (CreditReverse) GetOriginalInstitutionID

func (c CreditReverse) GetOriginalInstitutionID() string

func (CreditReverse) GetOriginalItemTraceNo

func (c CreditReverse) GetOriginalItemTraceNo() string

func (CreditReverse) GetReturnAccountNo

func (c CreditReverse) GetReturnAccountNo() string

func (CreditReverse) GetReturnInstitutionID

func (c CreditReverse) GetReturnInstitutionID() string

func (CreditReverse) GetType

func (c CreditReverse) GetType() RecordType

func (*CreditReverse) Parse

func (c *CreditReverse) Parse(data string) error

Parse takes in a serialized transaction segment and populates a CreditReverse struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (CreditReverse) Validate

func (c CreditReverse) Validate() error

type DCSign

type DCSign string

type Debit

type Debit struct {
	BaseTxn
	DueDate             *time.Time `json:"due_date" validate:"required"`
	PayorAccountNo      string     `json:"payor_account_no" validate:"required,max=12,numeric"`
	PayorName           string     `json:"payor_name" validate:"required,max=30"`
	ReturnInstitutionID string     `json:"return_institution_id" validate:"required,max=9,numeric"`
	ReturnAccountNo     string     `json:"return_account_no" validate:"required,max=12,eft_alpha"`
}

Debit represents Logical Record Type D according to the EFT standard 005

func NewDebit

func NewDebit(
	txnType TransactionType,
	amount int64,
	dueDate *time.Time,
	institutionID string,
	payorAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payorName string,
	originatorLongName string,
	returnInstitutionID string,
	returnAccountNo string,
	opts ...BaseTxnOpt,
) Debit

func (Debit) Build

func (d Debit) Build() (string, error)

Build serializes a Debit into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (Debit) GetAccountNo

func (d Debit) GetAccountNo() string

func (Debit) GetAmount

func (d Debit) GetAmount() int64

func (Debit) GetBaseTxn

func (d Debit) GetBaseTxn() BaseTxn

func (Debit) GetDate

func (d Debit) GetDate() *time.Time

func (Debit) GetName

func (d Debit) GetName() string

func (Debit) GetOriginalAccountNo

func (d Debit) GetOriginalAccountNo() string

func (Debit) GetOriginalInstitutionID

func (d Debit) GetOriginalInstitutionID() string

func (Debit) GetOriginalItemTraceNo

func (d Debit) GetOriginalItemTraceNo() string

func (Debit) GetReturnAccountNo

func (d Debit) GetReturnAccountNo() string

func (Debit) GetReturnInstitutionID

func (d Debit) GetReturnInstitutionID() string

func (Debit) GetType

func (d Debit) GetType() RecordType

func (*Debit) Parse

func (d *Debit) Parse(data string) error

Parse takes in a serialized transaction segment and populates a Debit struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (Debit) Validate

func (d Debit) Validate() error

Validate checks whether the fields of a Debit struct contain the correct fields that are required when writing/reading an EFT file. The validation check can be found on Section D of EFT standard 005.

type DebitReturn

type DebitReturn struct {
	BaseTxn
	DueDate               *time.Time `json:"due_date" validate:"required"`
	PayorAccountNo        string     `json:"payor_account_no" validate:"required,max=12,numeric"`
	PayorName             string     `json:"payor_name" validate:"required,max=30"`
	OriginalInstitutionID string     `json:"original_institution_id" validate:"required,max=9,numeric"`
	OriginalAccountNo     string     `json:"original_account_no" validate:"required,max=12,eft_alpha"`
	OriginalItemTraceNo   string     `json:"original_item_trace_no" validate:"required,eft_num,max=22"`
}

DebitReturn represents Logical Record Type J according to the EFT standard 005

func NewDebitReturn

func NewDebitReturn(
	txnType TransactionType,
	amount int64,
	dueDate *time.Time,
	institutionID string,
	payorAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payorName string,
	originatorLongName string,
	originalInstitutionID string,
	originalAccountNo string,
	originalItemTraceNo string,
	opts ...BaseTxnOpt,
) DebitReturn

func (DebitReturn) Build

func (d DebitReturn) Build() (string, error)

Build serializes a DebitReturn into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (DebitReturn) GetAccountNo

func (dr DebitReturn) GetAccountNo() string

func (DebitReturn) GetAmount

func (d DebitReturn) GetAmount() int64

func (DebitReturn) GetBaseTxn

func (dr DebitReturn) GetBaseTxn() BaseTxn

func (DebitReturn) GetDate

func (dr DebitReturn) GetDate() *time.Time

func (DebitReturn) GetName

func (dr DebitReturn) GetName() string

func (DebitReturn) GetOriginalAccountNo

func (dr DebitReturn) GetOriginalAccountNo() string

func (DebitReturn) GetOriginalInstitutionID

func (dr DebitReturn) GetOriginalInstitutionID() string

func (DebitReturn) GetOriginalItemTraceNo

func (dr DebitReturn) GetOriginalItemTraceNo() string

func (DebitReturn) GetReturnAccountNo

func (dr DebitReturn) GetReturnAccountNo() string

func (DebitReturn) GetReturnInstitutionID

func (dr DebitReturn) GetReturnInstitutionID() string

func (DebitReturn) GetType

func (d DebitReturn) GetType() RecordType

func (*DebitReturn) Parse

func (d *DebitReturn) Parse(data string) error

Parse takes in a serialized transaction segment and populates a DebitReturn struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (DebitReturn) Validate

func (d DebitReturn) Validate() error

Validate checks whether the fields of a DebitReturn struct contain the correct fields that are required when writing/reading an EFT file. The validation check can be found on Section D of EFT standard 005.

type DebitReverse

type DebitReverse struct {
	BaseTxn
	DueDate             *time.Time `json:"due_date" validate:"required"`
	PayorAccountNo      string     `json:"payor_account_no" validate:"required,max=12,numeric"`
	PayorName           string     `json:"payor_name" validate:"required,max=30"`
	ReturnInstitutionID string     `json:"return_institution_id" validate:"required,max=9,numeric"`
	ReturnAccountNo     string     `json:"return_account_no" validate:"required,max=12,eft_alpha"`
	OriginalItemTraceNo string     `json:"original_item_trace_no" validate:"required,eft_num,max=22"`
}

DebitReverse represents Logical Record Type F according to the EFT standard 005

func NewDebitReverse

func NewDebitReverse(
	txnType TransactionType,
	amount int64,
	dueDate *time.Time,
	institutionID string,
	payorAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payorName string,
	originatorLongName string,
	returnInstitutionID string,
	returnAccountNo string,
	originalItemTraceNo string,
	opts ...BaseTxnOpt,
) DebitReverse

func (DebitReverse) Build

func (d DebitReverse) Build() (string, error)

Build serializes a DebitReverse into a 240 length string that adheres to the EFT standard 005 standard. Numeric fields are padded with zeros to the left and alphanumeric fields are padded with spaces to the right any missing fields are filled with 0's or blanks

func (DebitReverse) GetAccountNo

func (d DebitReverse) GetAccountNo() string

func (DebitReverse) GetAmount

func (d DebitReverse) GetAmount() int64

func (DebitReverse) GetBaseTxn

func (d DebitReverse) GetBaseTxn() BaseTxn

func (DebitReverse) GetDate

func (c DebitReverse) GetDate() *time.Time

func (DebitReverse) GetName

func (d DebitReverse) GetName() string

func (DebitReverse) GetOriginalAccountNo

func (d DebitReverse) GetOriginalAccountNo() string

func (DebitReverse) GetOriginalInstitutionID

func (d DebitReverse) GetOriginalInstitutionID() string

func (DebitReverse) GetOriginalItemTraceNo

func (d DebitReverse) GetOriginalItemTraceNo() string

func (DebitReverse) GetReturnAccountNo

func (d DebitReverse) GetReturnAccountNo() string

func (DebitReverse) GetReturnInstitutionID

func (d DebitReverse) GetReturnInstitutionID() string

func (DebitReverse) GetType

func (d DebitReverse) GetType() RecordType

func (*DebitReverse) Parse

func (d *DebitReverse) Parse(data string) error

Parse takes in a serialized transaction segment and populates a DebitReverse struct containing the relevant data. The data passed in should be of length 240, the transaction length associated with the EFT file spec.

func (DebitReverse) Validate

func (d DebitReverse) Validate() error

type File

type File struct {
	Header *FileHeader  `json:"file_header,omitempty"`
	Txns   Transactions `json:"transactions,omitempty"`
	Footer *FileFooter  `json:"file_footer,omitempty"`
}

func NewFile

func NewFile(header *FileHeader, txns []Transaction) File

func (*File) Create

func (f *File) Create() (string, error)

Create returns a serialized EFT file as a string or an error. The serialized file will adhere to the EFT 005 payments canada specification but depending on individual fields the file may be rejected. Use the Validate function to catch any validation errors. Make sure to add the appropriate FileHeader and Transactions via NewFile before calling Create.

func (File) GetAllCreditReturns

func (f File) GetAllCreditReturns() []CreditReturn

Returns all credit return transactions or I records

func (File) GetAllCredits

func (f File) GetAllCredits() []Credit

Returns all credit transactions or C records

func (File) GetAllDebitReturns

func (f File) GetAllDebitReturns() []DebitReturn

Returns all debit return transactions or J records

func (File) GetAllDebitTxns

func (f File) GetAllDebitTxns() []Debit

Returns all debit transactions or D records

func (File) Validate

func (f File) Validate() error

Validate runs validation on the entire file starting from the FileHeader then every Taransaction. Any error that is encountered will be appended to a multierror and returned to the caller.

type FileFooter

type FileFooter struct {
	RecordHeader
	TotalValueOfDebit    int64 `json:"total_value_debit"`
	TotalCountOfDebit    int64 `json:"total_count_debit"`
	TotalValueOfCredit   int64 `json:"total_value_credit"`
	TotalCountOfCredit   int64 `json:"total_count_credit"`
	TotalValueOfERecords int64 `json:"total_value_reverse_debit"`
	TotalCountOfERecords int64 `json:"total_count_reverse_debit"`
	TotalValueOfFRecords int64 `json:"total_value_reverse_credit"`
	TotalCountOfFRecords int64 `json:"total_count_reverse_credit"`
}

FileFooter represents either Logical Record Type Z or V in the EFT 005 standard spec. FileFooter fields are populated from the Transaction entries and their counts and values. When building a file unless you really need to add a custom FileFooter allow the library to generate it for you via File.Create()

func NewFileFooter

func NewFileFooter(recordHeader RecordHeader, txns []Transaction) *FileFooter

func (FileFooter) Build

func (ff FileFooter) Build() (string, error)

Build takes the FileFooter struct, constructs a serialized string and returns it for writing

func (FileFooter) GetType

func (ff FileFooter) GetType() RecordType

func (*FileFooter) Parse

func (ff *FileFooter) Parse(line string) error

Parse will take in a serialized footer record of type Z and parse the amounts into a FileFooter struct

type FileHeader

type FileHeader struct {
	RecordHeader
	CreationDate                   *time.Time `json:"creation_date" validate:"required"`
	DestinationDataCenterNo        int64      `json:"destination_data_center" validate:"min=0,max=99999,numeric"`
	DirectClearerCommunicationArea string     `json:"communication_area" validate:"max=20"`
	CurrencyCode                   string     `json:"currency_code" validate:"required,eft_cur,len=3"`
}

FileHeader represents Logical Record Type A in the EFT 005 spec. Every EFT file should have a header entry which contains information about the originator, currency and creation dates. the supported currency should be CAD or USD.

func NewFileHeader

func NewFileHeader(
	originatorId string,
	fileCreationNum int64,
	creationDate *time.Time,
	destinationDataCenterNo int64,
	currencyCode string,
	opts ...HeaderOpts) *FileHeader

func (FileHeader) Validate

func (fh FileHeader) Validate() error

Validate checks whether the fields of a FileHeader struct contain the correct fields that are required when writing/reading an EFT file. The validation check can be found on Section D of EFT standard 005.

type FileStreamer

type FileStreamer struct {
	// contains filtered or unexported fields
}

FileStreamer is used for stream parsing an EFT file. Instead of reading the whole file FileStreamer attempts to read segments of transactions line by line. The caller is responsible for handling/ignoring any errors that are encountered. FileStreamer stores the state of the parser and hence is not safe for concurrency usage. Main usage is via ScanTxn which attempts to parse a segment of the file, return a Transaction or an error and move the file pointer along.

func NewFileStream

func NewFileStream(in io.ReadSeeker) FileStreamer

func (FileStreamer) GetFooter

func (fs FileStreamer) GetFooter() (*FileFooter, error)

GetFooter attempts to seek to the end of the file in search of a Z record. If no footer record is found an error is returned. Once scanning is complete the file pointer is reset to the beginning of the file.

func (FileStreamer) GetHeader

func (fs FileStreamer) GetHeader() (*FileHeader, error)

GetHeader scans the file for a A record and attempts to parse the record and return a FileHeader, an error is returned if parsing fails. the file pointer is then reset to the beginning of the file.

func (*FileStreamer) ScanTxn

func (fs *FileStreamer) ScanTxn() (Transaction, error)

ScanTxn parses transaction records (D, C, I, J, E and F logical records) one at a time. Upon successfully parsing a transaction segment a Transaction struct is returned otherwise a non nil error is returned in both cases the file pointer is moved to the next transaction in the file. When parsing is complete (ether file has ended or a footer record is encountered) an io.EOF error is returned, the caller can use this to terminate parsing of the file. If ScanTxn returns an instance of ScanParseError the error can be ignored by the caller. ScanTxn() will return EOF if a Footer record is encountered or if a line is empty

type HeaderOpts

type HeaderOpts func(*FileHeader)

func WithDirectClearerCommunicationArea

func WithDirectClearerCommunicationArea(comm string) HeaderOpts

This option will add an optional direct clearer communication area field to the header

type ParseError

type ParseError struct {
	Err error
	Msg string
}

func (*ParseError) Error

func (p *ParseError) Error() string

func (*ParseError) UnWrap

func (p *ParseError) UnWrap() error

type Reader

type Reader struct {
	File File
	// contains filtered or unexported fields
}

func NewReader

func NewReader(in io.Reader) *Reader

func (*Reader) ReadFile

func (r *Reader) ReadFile() (File, error)

ReadFile will attempt to read the whole EFT file according to the 005 spec from payments canada. If no errors are encountered a populated File object is returned that contains the Header, Transactions and Footer. Use the FileStreamer object to be able ignore errors and proceed parsing the file.

type RecordHeader

type RecordHeader struct {
	RecordType      RecordType `json:"type" validate:"rec_type"`
	OriginatorID    string     `json:"originator_id" validate:"required,eft_alpha,len=10"`
	FileCreationNum int64      `json:"file_creation_number" validate:"required,max=9999"`
	// contains filtered or unexported fields
}

RecordHeader represnts the common field that begins every Transaction line in an EFT file. The contents of this field are the RecordTpye the row count and originator id. This field is mostly internal and used for writing the file.

type RecordType

type RecordType string
const (
	HeaderRecord         RecordType = "A"
	CreditRecord         RecordType = "C"
	DebitRecord          RecordType = "D"
	CreditReverseRecord  RecordType = "E"
	DebitReverseRecord   RecordType = "F"
	ReturnCreditRecord   RecordType = "I"
	ReturnDebitRecord    RecordType = "J"
	NoticeOfChangeRecord RecordType = "S"
	NoticeOfChangeHeader RecordType = "U"
	NoticeOfChangeFooter RecordType = "V"
	FooterRecord         RecordType = "Z"
)

type Transaction

type Transaction interface {
	Parse(string) error
	Build() (string, error)
	Validate() error
	GetType() RecordType
	GetAmount() int64
	GetBaseTxn() BaseTxn
	GetAccountNo() string
	GetDate() *time.Time
	GetName() string
	GetReturnInstitutionID() string
	GetReturnAccountNo() string
	GetOriginalInstitutionID() string
	GetOriginalAccountNo() string
	GetOriginalItemTraceNo() string
}

func NewTransaction

func NewTransaction(
	recordType RecordType,
	txnType TransactionType,
	amount int64,
	date *time.Time,
	institutionID string,
	payorPayeeAccountNo string,
	itemTraceNo string,
	originatorShortName string,
	payorPayeeName string,
	originatorLongName string,
	originalOrReturnInstitutionID string,
	originalOrReturnAccountNo string,
	originalItemTraceNo string,
	opts ...BaseTxnOpt,
) Transaction

type TransactionType

type TransactionType string

type Transactions

type Transactions []Transaction

func (*Transactions) UnmarshalJSON

func (f *Transactions) UnmarshalJSON(data []byte) error

type ValidationError

type ValidationError struct {
	Err error
}

func (*ValidationError) Error

func (v *ValidationError) Error() string

func (*ValidationError) UnWrap

func (v *ValidationError) UnWrap() error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL