Documentation
¶
Index ¶
- Constants
- func ErrMDArg(name string, val interface{}) errors.MD
- func ErrMDFact(name string, val interface{}) errors.MD
- func ErrMDField(name string, val interface{}) errors.MD
- func ErrMDFnCall(fname string, args ...interface{}) errors.MD
- func ErrMDVar(name string, val interface{}) errors.MD
- type Attrs
- type Chunk
- type Filter
- func NewFilter(op FilterLogical, left Filter, right Filter) (Filter, error)
- func NewFilterByAmount(cmp FilterCmp, val float64) (Filter, error)
- func NewFilterByID(cmp FilterCmp, val uuid.UUID) (Filter, error)
- func NewFilterByType(cmp FilterCmp, val string) (Filter, error)
- func NewFilterFromLeaf(l FilterLeaf) (Filter, error)
- type FilterCmp
- type FilterLeaf
- type FilterLeafAmount
- type FilterLeafID
- type FilterLeafType
- type FilterLogical
- type FilterNodeType
- type Party
- type Pymt
- type PymtUpsert
- type Selection
- type Service
- type Sort
- type SortAttributes
- type SortDir
Examples ¶
Constants ¶
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 ¶
ErrMDArg creates a new metadata from an function argument which is related with the error to create.
func ErrMDFact ¶
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 ¶
ErrMDField creates a new metadata from a struct field whose name and value are relevant for the error to create.
func ErrMDFnCall ¶
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.
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.
type Chunk ¶
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 ¶
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 ¶
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 ¶
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.
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 ¶
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.
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.
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.
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 ¶
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.
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.