import * as gracely from "gracely" import * as isoly from "isoly" import * as selectively from "selectively" import * as authly from "authly" import * as model from "@payfunc/model-card" import { Merchant } from "../Merchant" import { Operation } from "../Merchant/Operation" import { Fee } from "./Fee" import { Processor } from "./Processor" import { V1 } from "./V1" export interface Transaction { authorization: authly.Identifier reference: string type: Merchant.Operation card: "debit" | "credit" scheme: model.Card.Scheme area?: isoly.CountryCode.Alpha2 created: isoly.Date amount?: number currency: isoly.Currency gross: number fee: number | V1.Fee | Fee net: number grossCurrency?: isoly.Currency reserve?: { amount: number; payout?: isoly.Date } merchant?: authly.Identifier | string processor?: Processor nnss?: string arn?: string payout?: isoly.Date | { currency: isoly.Currency; rate?: number; net?: number } transferDate?: isoly.Date clearingDate?: isoly.Date } export namespace Transaction { export function is(value: any | Transaction): value is Transaction { return ( typeof value == "object" && authly.Identifier.is(value.authorization) && typeof value.reference == "string" && Merchant.Operation.is(value.type) && (value.card == "debit" || value.card == "credit") && model.Card.Scheme.is(value.scheme) && (value.area == undefined || isoly.CountryCode.Alpha2.is(value.area)) && isoly.Date.is(value.created) && (value.amount == undefined || typeof value.amount == "number") && isoly.Currency.is(value.currency) && typeof value.gross == "number" && (typeof value.fee == "number" || (typeof value.fee == "object" && (V1.Fee.is(value.fee) || Fee.is(value.fee)))) && typeof value.net == "number" && (value.grossCurrency == undefined || isoly.Currency.is(value.grossCurrency)) && (value.reserve == undefined || (typeof value.reserve == "object" && typeof value.reserve.amount == "number" && (value.reserve.payout == undefined || isoly.Date.is(value.reserve.payout)))) && (value.merchant == undefined || typeof value.merchant == "string") && (value.processor == undefined || Processor.is(value.processor)) && (value.nnss == undefined || typeof value.nnss == "string") && (value.arn == undefined || typeof value.arn == "string") && (value.payout == undefined || isoly.Date.is(value.payout) || (value.payout && typeof value.payout == "object" && isoly.Currency.is(value.payout.currency) && (value.payout.rate == undefined || typeof value.payout.rate == "number") && (value.payout.net == undefined || typeof value.payout.net == "number"))) && (value.transferDate == undefined || isoly.Date.is(value.transferDate)) && (value.clearingDate == undefined || isoly.Date.is(value.clearingDate)) ) } export function flaw(value: Transaction | any): gracely.Flaw { return { type: "Transaction", flaws: typeof value != "object" ? undefined : ([ authly.Identifier.is(value.authorization) || { property: "authorization", type: "authly.Identifier" }, typeof value.reference == "string" || { property: "reference", type: "string" }, Merchant.Operation.is(value.type) || { property: "type", type: "Merchant.Operation" }, ["debit", "credit"].includes(value.card) || { property: "card", type: '"debit" | "credit"' }, model.Card.Scheme.is(value.scheme) || { property: "scheme", type: "model.Card.Scheme" }, value.area == undefined || isoly.CountryCode.Alpha2.is(value.area) || { property: "area", type: "isoly.CountryCode.Alpha2" }, isoly.Date.is(value.created) || { property: "created", type: "isoly.Date" }, value.amount == undefined || typeof value.amount == "number" || { property: "amount", type: "undefined | number" }, isoly.Currency.is(value.currency) || { property: "currency", type: "isoly.Currency" }, typeof value.gross == "number" || { property: "gross", type: "number" }, typeof value.fee == "number" || (typeof value.fee == "object" && ((typeof value.fee.scheme == "number" && typeof value.fee.total == "number") || (typeof value.fee.interchange == "number" && (value.fee.network == undefined || typeof value.fee.network == "number") && typeof value.fee.intergiro == "number" && typeof value.fee.total == "number"))) || { property: "fee", type: "number | { scheme: number; total: number } | { interchange: number; network?: number; intergiro: number; total: number }", }, typeof value.net == "number" || { property: "net", type: "number" }, value.grossCurrency == undefined || isoly.Currency.is(value.grossCurrency) || { property: "grossCurrency", type: "undefined | isoly.Currency", }, value.reserve == undefined || (typeof value.reserve == "object" && typeof value.reserve.amount == "number" && (value.reserve.payout == undefined || isoly.Date.is(value.reserve.payout))) || { property: "reserve", type: "{amount: number, payout?: isoly.Date}", }, value.merchant == undefined || typeof value.merchant == "string" || { property: "merchant", type: "authly.Identifier | string", condition: `Should be merchant id, but may be processor specific reference if unable to match with the correct merchant.`, }, value.processor == undefined || Processor.is(value.processor) || { property: "processor", type: `"omnipay" | "silverflow" | "baboba" | "clearhaus" | undefined`, }, value.nnss == undefined || typeof value.nnss == "string" || { property: "nnss", type: `string | undefined`, }, value.arn == undefined || typeof value.arn == "string" || { property: "arn", type: "string | undefined" }, value.payout == undefined || isoly.Date.is(value.payout) || (value.payout && typeof value.payout == "object" && isoly.Currency.is(value.payout.currency) && (value.payout.rate == undefined || typeof value.payout.rate == "number") && (value.payout.net == undefined || typeof value.payout.net == "number")) || { property: "payout", type: "undefined | isoly.Date | { currency: isoly.Currency; date: isoly.Date; rate?: number; net?: number }", }, value.transferDate == undefined || isoly.Date.is(value.transferDate) || { property: "transferDate", type: "undefined | isoly.Date" }, value.clearingDate == undefined || isoly.Date.is(value.clearingDate) || { property: "clearingDate", type: "undefined | isoly.Date" }, ].filter(gracely.Flaw.is) as gracely.Flaw[]), } } export function toCustomer(value: Transaction, costPlus?: true): Transaction export function toCustomer(value: Transaction[], costPlus?: true): Transaction[] export function toCustomer(value: Transaction | Transaction[], costPlus?: true): Transaction | Transaction[] { let result: Transaction | Transaction[] if (Array.isArray(value)) result = value.map(t => toCustomer(t)) else { result = costPlus ? value : { ...value, fee: typeof value.fee == "object" ? value.fee.total : value.fee } delete result.merchant delete result.processor delete result.nnss delete result.arn } return result } export const template = new selectively.Type.Object({ authorization: new selectively.Type.String(), reference: new selectively.Type.String(), type: new selectively.Type.Union(Operation.types.map(s => new selectively.Type.String(s))), card: new selectively.Type.Union(["debit", "credit"].map(c => new selectively.Type.String(c))), scheme: new selectively.Type.Union(model.Card.Scheme.types.map(s => new selectively.Type.String(s))), area: new selectively.Type.Union(isoly.CountryCode.Alpha2.types.map(a => new selectively.Type.String(a))), created: new selectively.Type.String(), amount: new selectively.Type.Number(), currency: new selectively.Type.Union(isoly.Currency.types.map(c => new selectively.Type.String(c))), gross: new selectively.Type.Number(), grossCurrency: new selectively.Type.Union(isoly.Currency.types.map(c => new selectively.Type.String(c))), fee: new selectively.Type.Union([ new selectively.Type.Number(), new selectively.Type.Object({ scheme: new selectively.Type.Number(), total: new selectively.Type.Number() }), ]), net: new selectively.Type.Number(), reserve: new selectively.Type.Object({ amount: new selectively.Type.Number(), payout: new selectively.Type.String(), }), merchant: new selectively.Type.String(), processor: new selectively.Type.Union(Processor.types.map(c => new selectively.Type.String(c))), nnss: new selectively.Type.String(), arn: new selectively.Type.String(), payout: new selectively.Type.Object({ net: new selectively.Type.Number(), currency: new selectively.Type.Union(isoly.Currency.types.map(c => new selectively.Type.String(c))), date: new selectively.Type.String(), rate: new selectively.Type.Number(), }), transferDate: new selectively.Type.String(), clearingDate: new selectively.Type.String(), }) }