payment

package
v0.0.0-...-8ad0638 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2019 License: MIT Imports: 4 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const (
	ErrAbortedOperation code = iota + 1

	ErrInvalidArgFilterCmpNotExists
	ErrInvalidArgFilterCmpNotSupported
	ErrInvalidArgFilterLeafNoValSet
	ErrInvalidArgFilterLogicalOpNotExists
	ErrInvalidArgFilterNodeEmpty
	ErrInvalidArgFilterValue

	ErrInvalidArgVersionMismatch

	ErrInvalidPaymentID
	ErrInvalidPaymentOrgID
	ErrInvalidPaymentType
	ErrInvalidPaymentAttrPaymentID

	ErrNotFound

	ErrUnexpectedOSError
	ErrUnexpectedStoreError
	ErrUnexpectedSysError
)

The list of error codes that the payment service can return.

Variables

This section is empty.

Functions

func ErrMDArg

func ErrMDArg(name string, val interface{}) errors.MD

ErrMDArg creates a new metadata from an function argument which is related with the error to create.

func ErrMDFact

func ErrMDFact(name string, val interface{}) errors.MD

ErrMDFact creates a new metdata for a value which represent an important fact which provide context to the error for the user/developer/ops when reading the verbose version of the error.

name should be short but meaninful to understand the value.

func ErrMDField

func ErrMDField(name string, val interface{}) errors.MD

ErrMDField creates a new metadata from a struct field whose name and value are relevant for the error to create.

func ErrMDFnCall

func ErrMDFnCall(fname string, args ...interface{}) errors.MD

ErrMDFnCall creates a new metadata to inform the function which has been called and with which arguments. This metadata is intended to be used for internal function calls, so the user isn't aware of those and when they return an error code which isn't enough concrete to let inform the user what specifically happened.

func ErrMDVar

func ErrMDVar(name string, val interface{}) errors.MD

ErrMDVar creates a new metdata from a variable whose name and value are relevant for the error to create. When the variable is not exposed, the name should be meaningful to the user/developer/ops when reading the verbose version of the error.

Types

type Attrs

type Attrs struct {
	Amount               float64 `json:"amount"`
	Currency             string  `json:"currency"`
	Reference            string  `json:"reference"`
	EndToEndReference    string  `json:"end_to_end_reference"`
	NumericReference     string  `json:"numeric_reference"`
	PaymentID            string  `json:"payment_id"`
	PaymentPurpose       string  `json:"payment_purpose"`
	PaymentScheme        string  `json:"payment_scheme"`
	PaymentType          string  `json:"payment_type"`
	ProcessingDate       string  `json:"processing_date"`
	SchemePaymentSubType string  `json:"scheme_payment_sub_type"`
	SchemePaymentType    string  `json:"scheme_payment_type"`
	BeneficiaryParty     Party   `json:"beneficiary_party"`
	DebtorParty          Party   `json:"debtor_party"`
	SponsorParty         Party   `json:"sponsor_party"`
	ChargesInformation   struct {
		BearerCode    string `json:"bearer_code"`
		SenderCharges []struct {
			Amount   float64 `json:"amount"`
			Currency string  `json:"currency"`
		} `json:"sender_charges"`
		ReceiverChargesAmount   float64 `json:"receiver_charges_amount"`
		ReceiverChargesCurrency string  `json:"receiver_charges_currency"`
	} `json:"charges_information"`
	Fx struct {
		ContractReference string `json:"contract_reference"`
		ExchangeRate      string `json:"exchange_rate"`
		OriginalAmount    string `json:"original_amount"`
		OriginalCurrency  string `json:"original_currency"`
	} `json:"fx"`
}

Attrs contains the information of the attributes attached to a payment.

func (Attrs) Validate

func (a Attrs) Validate() error

Validate validates that the attributes contains alls the required values and their values respect the requirements of the business domain.

type Chunk

type Chunk struct {
	Limit  uint32
	Offset uint64
}

Chunk is the type to indicate how many items of a collection to get and from which offset.

type Filter

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

Filter is an abstraction of a specified filter over a set of different values.

It represents a binary tree where when it's a leaf node, it contains the comparison operator and value to apply, meanwhile when it isn't a left, it contains the 2 children nodes (which are Filter) and the logical operator applied between the both of them.

You can see it as any boolean logical operation used in conditionals in the majority of programming languages.

The zero value is a noop filter.

Example
package main

import (
	"fmt"
	"log"

	"github.com/gofrs/uuid"
	"github.com/ifraixedes/go-payments-api-example/payment"
)

func main() {
	var f payment.Filter
	{
		var fleft payment.Filter
		{
			var fage10, err = payment.NewFilterByAmount(payment.FilterCmpGreaterOrEqualThan, 10)
			fatalIfErr(err)

			fidne, err := payment.NewFilterByID(
				payment.FilterCmpNotEqual, uuid.FromStringOrNil("86b16b89-61c1-4f2f-963b-b542e3597d69"),
			)
			fatalIfErr(err)

			fal8_5, err := payment.NewFilterByAmount(payment.FilterCmpLessThan, 8.5)
			fatalIfErr(err)

			faid, err := payment.NewFilter(payment.FilterLogicalAnd, fage10, fidne)
			fatalIfErr(err)

			fleft, err = payment.NewFilter(payment.FilterLogicalOr, faid, fal8_5)
			fatalIfErr(err)
		}

		fright, err := payment.NewFilterByType(payment.FilterCmpEqual, "Payment")
		fatalIfErr(err)

		f, err = payment.NewFilter(payment.FilterLogicalAnd, fleft, fright)
		fatalIfErr(err)
	}

	// Given a filter this is a processor for printing out the string filter
	// expected by the example test
	var (
		cf                     = &f
		stk              stack = []payment.Filter{}
		closeParentheses       = false
		filterSQL        string
	)

	for { // Iteratively in-order traversal of the filter (which is a binary tree)
		if cf == nil {
			var pn, ok = stk.Pop()
			if !ok {
				break
			}

			if pn.NodeType() == payment.FilterNodeTypeLeaf {
				var lstr = toLeaf(pn.Leaf())
				if closeParentheses {
					filterSQL = fmt.Sprintf("%s%s)", filterSQL, lstr)
					closeParentheses = false
				} else {
					filterSQL = fmt.Sprintf("%s%s", filterSQL, lstr)
				}
			}

			if pn.NodeType() == payment.FilterNodeTypeNonLeaf {
				if len(stk) > 0 {
					filterSQL = fmt.Sprintf("(%s", filterSQL)
					closeParentheses = true
				}

				var op, _, right = pn.Nodes()
				filterSQL = fmt.Sprintf("%s %s ", filterSQL, toLogicalOp(op))
				cf = &right
			}

			continue
		}

		if cf.NodeType() == payment.FilterNodeTypeNonLeaf {
			_, left, _ := cf.Nodes()
			stk.Push(*cf)
			cf = &left
		} else {
			stk.Push(*cf)
			cf = nil
		}
	}

	fmt.Println(filterSQL)
}

type stack []payment.Filter

func (s *stack) Push(f payment.Filter) {
	var ts = append(*s, f)
	*s = ts
}

func (s *stack) Pop() (payment.Filter, bool) {
	if ts := *s; len(ts) > 0 {
		var f = ts[len(ts)-1]
		ts = ts[:len(ts)-1]

		*s = ts
		return f, true
	}

	return payment.Filter{}, false
}

func toCmpOp(op payment.FilterCmp) string {
	switch op {
	case payment.FilterCmpEqual:
		return "="
	case payment.FilterCmpGreaterOrEqualThan:
		return ">="
	case payment.FilterCmpGreaterThan:
		return ">"
	case payment.FilterCmpLessOrEqualThan:
		return "<="
	case payment.FilterCmpLessThan:
		return "<"
	case payment.FilterCmpMatch:
		return "LIKE"
	case payment.FilterCmpNotEqual:
		return "!="
	}

	fatalIfErr(fmt.Errorf("Unrecognized comparison operator: %d", op))
	return ""
}

func toLogicalOp(op payment.FilterLogical) string {
	switch op {
	case payment.FilterLogicalAnd:
		return "AND"
	case payment.FilterLogicalOr:
		return "OR"
	}

	fatalIfErr(fmt.Errorf("Unrecognized logical operator: %d", op))
	return ""
}

func toLeafName(f payment.FilterLeaf) string {
	switch f.(type) {
	case payment.FilterLeafAmount:
		return "amount"
	case payment.FilterLeafType:
		return "type"
	case payment.FilterLeafID:
		return "id"
	}

	fatalIfErr(fmt.Errorf("Unrecognized leaf type: %T", f))
	return ""
}

func toLeafValue(f payment.FilterLeaf) string {
	switch f.(type) {
	case payment.FilterLeafAmount:
		_, val := f.Filter()
		return fmt.Sprintf("%.2f", val)
	case payment.FilterLeafType:
		_, val := f.Filter()
		return fmt.Sprintf("'%s'", val)
	case payment.FilterLeafID:
		_, val := f.Filter()
		id := val.(uuid.UUID)
		return fmt.Sprintf("'%s'", id.String())
	}

	fatalIfErr(fmt.Errorf("Unrecognized leaf type: %T", f))
	return ""
}

func toLeaf(f payment.FilterLeaf) string {
	var op, _ = f.Filter()
	return fmt.Sprintf("%s %s %s", toLeafName(f), toCmpOp(op), toLeafValue(f))
}

func fatalIfErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}
Output:
((amount >= 10.00 AND id != '86b16b89-61c1-4f2f-963b-b542e3597d69') OR amount < 8.50) AND type = 'Payment'

func NewFilter

func NewFilter(op FilterLogical, left Filter, right Filter) (Filter, error)

NewFilter creates a filter of NodeTypeNonLeaf composed by 2 other Filters.

func NewFilterByAmount

func NewFilterByAmount(cmp FilterCmp, val float64) (Filter, error)

NewFilterByAmount creates a new Filter leaf node of a FilterByAmount with the specified cmp and val.

The following error codes can be returned (declared in errs sub package):

* InvalidArgFilterCmpNotExists

* InvalidArgFilterCmpNotSupported - when cmd is FilterCmpMatch

func NewFilterByID

func NewFilterByID(cmp FilterCmp, val uuid.UUID) (Filter, error)

NewFilterByID creates a new Filer leaf node of a FilterLeafID with the specified cmp and val.

The following error codes can be returned (declared in errs sub package):

* InvalidArgFilterCmpNotExists

* InvalidArgFilterCmpNotSupported - when cmp isn't FilterCmpEqual nor FilterCmpNotEqual

func NewFilterByType

func NewFilterByType(cmp FilterCmp, val string) (Filter, error)

NewFilterByType creates a new Filter leaf node of a FilterByType with cmp and val.

The following error codes can be returned (declared in errs sub package):

* InvalidArgFilterCmpNotExists

* InvalidArgFilterCmpNotSupported - when cmp isn't FilterCmpEqual nor FilterCmpNotEqual

* InvalidArgFilterValue - currently only "Payment" is valid value type

func NewFilterFromLeaf

func NewFilterFromLeaf(l FilterLeaf) (Filter, error)

NewFilterFromLeaf creates a Filter of NodeTypeLeaf. It returns an error if f.IsSet returns false.

The following error codes may be returned:

* InvalidArgFilterLeafNoValSet

func (Filter) Leaf

func (f Filter) Leaf() FilterLeaf

Leaf returns the FilterLeaf value. The value is nil when it's node type is not NodeTypeLeaf.

func (Filter) NodeType

func (f Filter) NodeType() FilterNodeType

NodeType returns the type of this node. Zero value returns FilterNodeTypeEmpty.

func (Filter) Nodes

func (f Filter) Nodes() (FilterLogical, Filter, Filter)

Nodes returns the operator applied over the 2 children nodes and those nodes left and right.

FilterLogical is an invalid value and the 2 filter will be of node type NodeTypeEmpty, when f is not an NodeTypeNonLeaf.

type FilterCmp

type FilterCmp uint8

FilterCmp specifies the comparison operation to perform.

const (
	FilterCmpEqual FilterCmp
	FilterCmpNotEqual
	FilterCmpGreaterThan
	FilterCmpGreaterOrEqualThan
	FilterCmpLessThan
	FilterCmpLessOrEqualThan
	FilterCmpMatch
)

The list of valid FilterCmp values.

type FilterLeaf

type FilterLeaf interface {
	Filter() (op FilterCmp, val interface{})
	IsSet() bool
}

FilterLeaf is the interface which any type which can be a leaf node of a Filter must satisifies

type FilterLeafAmount

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

FilterLeafAmount allows to filter payment by its amount filed.

func (FilterLeafAmount) Filter

func (f FilterLeafAmount) Filter() (FilterCmp, interface{})

Filter returns the operation and string value which has been set.

func (FilterLeafAmount) IsSet

func (f FilterLeafAmount) IsSet() bool

IsSet returns true when the filter is set, otherwise none.

type FilterLeafID

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

FilterLeafID is the FilterLeaf for filtering payments by ID.

func (FilterLeafID) Filter

func (f FilterLeafID) Filter() (FilterCmp, interface{})

Filter returns the operation and ID value which has been set.

func (FilterLeafID) IsSet

func (f FilterLeafID) IsSet() bool

IsSet returns true when the filter is set, otherwise none.

type FilterLeafType

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

FilterLeafType is the FilterLeaf for filtering payments by type.

func (FilterLeafType) Filter

func (f FilterLeafType) Filter() (FilterCmp, interface{})

Filter returns the operation and string value which has been set.

func (FilterLeafType) IsSet

func (f FilterLeafType) IsSet() bool

IsSet returns true when the filter is set, otherwise none.

type FilterLogical

type FilterLogical uint8

FilterLogical specifies the logical operation to perform when more than one comparison operation is involved.

const (
	FilterLogicalAnd FilterLogical
	FilterLogicalOr
)

The list of valid FilterLogical values.

type FilterNodeType

type FilterNodeType uint8

FilterNodeType represents the type that a filter node can have.

const (
	FilterNodeTypeEmpty FilterNodeType = iota
	FilterNodeTypeLeaf
	FilterNodeTypeNonLeaf
)

The list of valid FilterNodeType values.

type Party

type Party struct {
	AccountName       string `json:"account_name"`
	AccountNumber     string `json:"account_number"`
	AccountNumberCode string `json:"account_number_code"`
	AccountType       int    `json:"account_type"`
	Address           string `json:"address"`
	BankID            string `json:"bank_id"`
	BankIDCode        string `json:"bank_id_code"`
	Name              string `json:"name"`
}

Party contains the information of each single party involved in a payment.

func (Party) Validate

func (p Party) Validate() error

Validate valides that the party contains all the required values and their values respect the requirments of the business domain.

type Pymt

type Pymt struct {
	PymtUpsert
	ID      uuid.UUID `json:"id"`
	Version uint32    `json:"version"`
}

Pymt contains all the information which a single payment has.

type PymtUpsert

type PymtUpsert struct {
	Type       string    `json:"type"`
	OrgID      uuid.UUID `json:"organisation_id"`
	Attributes Attrs     `json:"attributes"`
}

PymtUpsert contains the information required to create or update a payment.

func (PymtUpsert) Validate

func (p PymtUpsert) Validate() error

Validate validates that the input payment contains all the required values and their values respect the requirments of the business domain.

type Selection

type Selection struct {
	Version    bool
	Type       bool
	OrgID      bool
	Attributes bool
}

Selection specifies the fields of a single payment to be retrieved. The payment's fields which aren't present are always retrieved. Each file is a boolean, when it's true, the value is retrieved otherwise it won't be.

func SelectAll

func SelectAll() Selection

SelectAll returns the value which indicates to retrieve all the fields of a payment.

type Service

type Service interface {
	// Create creates a new payment returning its ID.
	//
	// This method can return any of the errors returned by p.Validate.
	Create(ctx context.Context, p PymtUpsert) (uuid.UUID, error)

	// Delete deletes the payment which has associated the passed ID.
	//
	// The following error codes can be returned:
	//
	// * ErrInvalidPaymentID
	//
	// * ErrNotFound
	Delete(context.Context, uuid.UUID) error

	// Find retrieve list of payments which fulfill f, sorted by o and chunked by
	// c. Each payment only contains the fields indicated by s.
	// If there is not payments which fulfill f or the chunk specified by p is out
	// of range, an empty list and nil error are returned.
	Find(ctx context.Context, f Filter, s Selection, o Sort, c Chunk) ([]Pymt, error)

	// Get retrieves the payment which has associated the passed ID. The payment
	// only contains the fields indicated by s.
	//
	// The following error codes can be returned:
	//
	// * ErrInvalidPaymentID
	//
	// * ErrNotFound
	Get(ctx context.Context, id uuid.UUID, s Selection) (Pymt, error)

	// Update updates the payment with the associated ID, if its version matches
	// with version. The payment version is incremented if the update succeeds.
	//
	// The following error codes can be returned:
	//
	// * ErrInvalidArgVersionMismatch - When the version doesn't match with the
	// current payment version for avoiding to override the payment concurrently.
	//
	// * ErrNotFound
	Update(ctx context.Context, id uuid.UUID, version uint32, p PymtUpsert) error
}

Service is the interface which any specific implementation of a payment service must satisfy. All the implementation must also return the error codes documented in this interface (general ones and on each method).

All the methods can return, a part of their specific ones which are documented on them, the following error codes:

  • ErrOperationAborted - This could happen due to a ctx deadline; ctx.Err must be checked to find out that the error is returned because of ctx.

* ErrUnexpectedOSError

* ErrUnexpectedStoreError

* ErrUnexpectedSysError

type Sort

type Sort struct {
	Type       SortDir
	ID         SortDir
	Version    SortDir
	OrgID      SortDir
	Attributes SortAttributes
}

Sort specifies the allowed fields for sorting a list of payments.

The payment's fields which aren't present aren't allowed to be used for sorting.

type SortAttributes

type SortAttributes struct {
	Amount SortDir
}

SortAttributes is the type of the Attributes field of the Sort type.

type SortDir

type SortDir uint8

SortDir is the type which represents the direction when sorting values.

const (
	SortUnspecified SortDir = iota
	SortAscending
	SortDescending
)

The list of valid SortDir values

func (SortDir) Valid

func (s SortDir) Valid() bool

Valid returns true if s is a valid SortDir value, otherwise false

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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