Skip to content
Merged
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
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@unit-finance/unit-node-sdk",
"version": "1.4.5",
"version": "1.4.6",
"description": "",
"main": "dist/unit.js",
"types": "dist/unit.d.ts",
Expand Down
73 changes: 61 additions & 12 deletions resources/stopPayments.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
import { Meta, UnitConfig, UnitResponse } from "../types/common"
import { BaseCheckPaymentListParams, CreateStopPaymentRequest, StopPayment, StopPaymentStatus } from "../types/checkPayment"
import { BaseCheckPaymentListParams } from "../types/checkPayment"
import { AchStopPayment, CreateAchStopPaymentRequest, CreateStopPaymentRequest, PatchAchStopPaymentRequest, StopPayment, StopPaymentResource, StopPaymentStatus } from "../types/stopPayments"
import { BaseResource } from "./baseResource"

export class StopPayments extends BaseResource {
constructor(token: string, basePath: string, config?: UnitConfig) {
super(token, basePath + "/stop-payments", config)
}

public async create(request: CreateStopPaymentRequest): Promise<UnitResponse<StopPayment>> {
return this.httpPost<UnitResponse<StopPayment>>("", { data: request} )
public async create(request: CreateStopPaymentRequest): Promise<UnitResponse<StopPayment>>
public async create(request: CreateAchStopPaymentRequest): Promise<UnitResponse<AchStopPayment>>
public async create(request: CreateStopPaymentRequest | CreateAchStopPaymentRequest): Promise<UnitResponse<StopPaymentResource>> {
return this.httpPost<UnitResponse<StopPaymentResource>>("", { data: request} )
}

public async get(id: string): Promise<UnitResponse<StopPayment>> {
return this.httpGet<UnitResponse<StopPayment>>(`/${id}`)
public async get(id: string): Promise<UnitResponse<StopPaymentResource>> {
return this.httpGet<UnitResponse<StopPaymentResource>>(`/${id}`)
}

public async disable(id: string): Promise<UnitResponse<StopPayment>> {
return this.httpPost<UnitResponse<StopPayment>>(`/${id}/disable`)
public async update(id: string, request: PatchAchStopPaymentRequest): Promise<UnitResponse<AchStopPayment>> {
return this.httpPatch<UnitResponse<AchStopPayment>>(`/${id}`, { data: request })
}

public async list(params?: StopPaymentListParams): Promise<UnitResponse<StopPayment[]> & Meta> {

public async disable(id: string): Promise<UnitResponse<StopPaymentResource>> {
return this.httpPost<UnitResponse<StopPaymentResource>>(`/${id}/disable`)
}

public async list(params?: StopPaymentListParams): Promise<UnitResponse<StopPaymentResource[]> & Meta> {
const parameters: any = {
"page[limit]": (params?.limit ? params.limit : 100),
"page[offset]": (params?.offset ? params.offset : 0),
Expand All @@ -29,17 +36,24 @@ export class StopPayments extends BaseResource {
...(params?.until && { "filter[until]": params.until }),
...(params?.fromAmount && { "filter[fromAmount]": params.fromAmount }),
...(params?.toAmount && { "filter[toAmount]": params.toAmount }),
...(params?.noAmount !== undefined && { "filter[noAmount]": params.noAmount }),
...(params?.fromMinAmount && { "filter[fromMinAmount]": params.fromMinAmount }),
...(params?.toMinAmount && { "filter[toMinAmount]": params.toMinAmount }),
...(params?.noMinAmount !== undefined && { "filter[noMinAmount]": params.noMinAmount }),
...(params?.originatorName && { "filter[originatorName]": params.originatorName }),
...(params?.noOriginatorName !== undefined && { "filter[noOriginatorName]": params.noOriginatorName }),
...(params?.checkNumber && { "filter[checkNumber]": params.checkNumber }),
...(params?.tags && { "tags": params.tags }),
...(params?.type && { "filter[type]": params.type }),
...(params?.tags && { "filter[tags]": this.customStringify(params.tags, ":") }),
...(params?.sort && { "sort": params.sort })
}

if (params?.status)
params.status.forEach((s, idx) => {
parameters[`filter[status][${idx}]`] = s
})
return this.httpGet<UnitResponse<StopPayment[]> & Meta>("", { params: parameters })

return this.httpGet<UnitResponse<StopPaymentResource[]> & Meta>("", { params: parameters })
}
}

Expand All @@ -48,4 +62,39 @@ export interface StopPaymentListParams extends BaseCheckPaymentListParams {
* Optional. Filter by status (Active or Disabled). Usage example: filter[status][0]=Active
*/
status?: StopPaymentStatus[]

/**
* Optional. If set to true, returns only Stop Payments with no amount. If set to false only returns Stop Payments with amount.
*/
noAmount?: boolean

/**
* Optional. Filters ACH Stop Payments that have minAmount higher than the specified amount (in cents).
*/
fromMinAmount?: number

/**
* Optional. Filters ACH Stop Payments that have minAmount lower than the specified amount (in cents).
*/
toMinAmount?: number

/**
* Optional. If set to true, returns only ACH Stop Payments with no minAmount. If set to false only returns Stop Payments with minAmount.
*/
noMinAmount?: boolean

/**
* Optional. Filters the results by a single originator name.
*/
originatorName?: string

/**
* Optional. If set to true, returns only Stop Payments with no originatorName. If set to false only returns Stop Payments with originatorName.
*/
noOriginatorName?: boolean

/**
* Optional. Either checkStopPayment or achStopPayment.
*/
type?: "checkStopPayment" | "achStopPayment"
}
2 changes: 1 addition & 1 deletion tests/cashDeposits.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ dotenv.config()
const unit = new Unit(process.env.UNIT_TOKEN || "test", process.env.UNIT_API_URL || "test")

describe("Get Stores Locations", () => {
test("Get Cash Deposits Stores by coordinates",async () => {
test.skip("Get Cash Deposits Stores by coordinates",async () => {
const res = await unit.cashDeposits.list({serviceType: "Barcode", coordinates: {longitude: -73.93041, latitude: 42.79894}})

res.data.forEach(element => {
Expand Down
71 changes: 63 additions & 8 deletions tests/stopPayments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,77 @@ describe("E2E Test", () => {
expect(response.data.type).toBe("stopPayment")
})

test("Create and Update ACH Stop Payment", async () => {
const accountId = (await createIndividualAccount(unit)).data.id
const relationships = {account: createRelationship("depositAccount", accountId)}

// The Unit API accepts the expiration attribute as a date-only string
// (e.g. "2027-01-18") but returns it as a full ISO datetime at midnight
// UTC (e.g. "2027-01-18T00:00:00.000Z"). We compute both forms so we can
// send the date-only value on the request and assert against the ISO
// datetime on the response.
const futureExpiration = (daysFromNow: number) => {
const d = new Date(Date.now() + daysFromNow * 24 * 60 * 60 * 1000)
d.setUTCHours(0, 0, 0, 0)
const iso = d.toISOString()
return { request: iso.slice(0, 10), response: iso }
}
const initialExpiration = futureExpiration(365)
const updatedExpiration = futureExpiration(180)

const response = await unit.stopPayments.create({
type: "achStopPayment",
attributes: {
minAmount: 5001,
originatorName: ["Pied Piper", "Pied Piper Inc."],
direction: "Debit",
description: "Stop subscription payments greater than $50 to the gym.",
isMultiUse: true,
expiration: initialExpiration.request,
tags: {"test": "test"}
},
relationships
})

expect(response.data.type).toBe("achStopPayment")
expect(response.data.attributes.minAmount).toBe(5001)
expect(response.data.attributes.direction).toBe("Debit")
expect(response.data.attributes.description).toBe("Stop subscription payments greater than $50 to the gym.")

const updated = await unit.stopPayments.update(response.data.id, {
type: "achStopPayment",
attributes: {
tags: {"newTag": "New tag value"},
expiration: updatedExpiration.request
}
})

expect(updated.data.type).toBe("achStopPayment")
expect(updated.data.id).toBe(response.data.id)
expect(updated.data.attributes.expiration).toBe(updatedExpiration.response)
})

test("Get Stop Payments List", async () => {
const stopPayments = (await unit.stopPayments.list()).data

stopPayments.forEach(async sp => {
expect(sp.type).toBe("stopPayment")

for (const sp of stopPayments) {
const res = (await unit.stopPayments.get(sp.id)).data

expect(res.type).toBe("stopPayment")
expect(res.id).toBe(sp.id)
expect(res.type).toBe(sp.type)
expect(res.attributes.createdAt).toBe(sp.attributes.createdAt)
expect(res.attributes.updatedAt).toBe(sp.attributes.updatedAt)
expect(res.attributes.amount).toBe(sp.attributes.amount)
expect(res.attributes.checkNumber).toBe(sp.attributes.checkNumber)
expect(res.attributes.status).toBe(sp.attributes.status)

})
if (sp.type === "stopPayment" && res.type === "stopPayment") {
expect(res.attributes.updatedAt).toBe(sp.attributes.updatedAt)
expect(res.attributes.amount).toBe(sp.attributes.amount)
expect(res.attributes.checkNumber).toBe(sp.attributes.checkNumber)
}

if (sp.type === "achStopPayment" && res.type === "achStopPayment") {
expect(res.attributes.direction).toBe(sp.attributes.direction)
expect(res.attributes.description).toBe(sp.attributes.description)
}
}
})
})
43 changes: 5 additions & 38 deletions types/checkPayment.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Tags, RelationshipsArray, Relationship, BaseListParams, Sort, BaseCreateRequestAttributes, CheckPaymentCounterparty } from "./common"
import { Tags, Relationship, BaseListParams, Sort, BaseCreateRequestAttributes, CheckPaymentCounterparty } from "./common"
import { BasePaymentRelationships } from "./payments"

export type StopPaymentStatus = "Active" | "Disabled"
export { StopPayment, StopPaymentStatus, CreateStopPaymentRequest } from "./stopPayments"

export type CheckPaymentStatus = "New" | "Rejected" | "Pending" | "Canceled" | "PendingCancellation" | "InProduction" | "InDelivery" | "Delivered" |
"ReturnedToSender" | "PendingReview" | "Processed" | "MarkedForReturn" | "Returned"

Expand All @@ -24,12 +25,7 @@ interface BaseCheckPaymentAttributes {
amount: number

/**
* The status of the stop payment, one of Active or Disabled.
*/
status: StopPaymentStatus

/**
* The checkNumber of the check payments that the stop payment operation will be applied to.
* The checkNumber of the check payment.
*/
checkNumber: string

Expand All @@ -39,22 +35,6 @@ interface BaseCheckPaymentAttributes {
tags?: Tags
}

export interface StopPayment {
id: string

type: "stopPayment"

attributes: BaseCheckPaymentAttributes

relationships: {
/**
* The list of CheckPayments that were stopped by this stopPayment.
*/
stoppedPayments?: RelationshipsArray

} & Omit<BasePaymentRelationships, "transaction">
}

type PendingReviewReasons = "SoftLimit"

type CheckPaymentReturnReason =
Expand Down Expand Up @@ -179,24 +159,11 @@ export interface CheckPayment {
memo?: string


} & Omit<BaseCheckPaymentAttributes, "status">
} & BaseCheckPaymentAttributes

relationships: BasePaymentRelationships
}

export interface CreateStopPaymentRequest {
type: "stopPayment"
attributes: {
amount?: number
checkNumber: string
tags: Tags
idempotencyKey?: string
}
relationships: {
account: Relationship
}
}

export interface ApproveCheckPaymentRequest {
id: string

Expand Down
1 change: 1 addition & 0 deletions types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from "./institution"
export * from "./orgToken"
export * from "./payments"
export * from "./checkPayment"
export * from "./stopPayments"
export * from "./repayments"
export * from "./recurringPayment"
export * from "./returns"
Expand Down
Loading
Loading