@fabriktor/fx 0.0.130 → 0.0.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -86,11 +86,23 @@ export type CreateEntityPaymentOptions = {
86
86
  };
87
87
  export type CreatePaymentOptions = PaymentInsertOptions & MultiCreateCheckpoint;
88
88
  export type ReplacePaymentOptions = PaymentReplaceOptions;
89
- export type SearchPaymentsOptions = OwnerSearchOptions & {
89
+ export type PaymentSearchFilters = {
90
90
  type?: Payment["type"] | Payment["type"][];
91
91
  kind?: Payment["kind"];
92
+ psp_actionable_status?: Payment["psp_actionable_status"][];
93
+ currency?: string;
92
94
  };
95
+ export type SearchPaymentsOptions = SearchOptions & EntityPaymentScope & PaymentSearchFilters;
93
96
  export type SearchPaymentsPage = SearchPage<Payment>;
97
+ export declare const PaymentDirection: {
98
+ readonly Outgoing: "outgoing";
99
+ readonly Incoming: "incoming";
100
+ };
101
+ export type PaymentDirection = (typeof PaymentDirection)[keyof typeof PaymentDirection];
102
+ export type SearchPaymentHistoryOptions = OwnerSearchOptions & PaymentSearchFilters & {
103
+ direction: PaymentDirection;
104
+ };
105
+ export declare function isIncomingPayment(payment: Payment, viewerID: string): boolean;
94
106
  export type CreatePmtAccountOptions = PmtAccountInsertOptions;
95
107
  export type ContinuePmtAccountOnboardingOptions = PmtAccountOnboardingOptions;
96
108
  export type ContinuePmtAccountOnboardingResult = string;
@@ -182,6 +194,7 @@ export interface PaymentsFXOperator {
182
194
  createPayment(opts: CreatePaymentOptions): Promise<Payment>;
183
195
  replacePayment(opts: ReplacePaymentOptions): Promise<Payment>;
184
196
  searchPayments(opts: SearchPaymentsOptions): Promise<SearchPaymentsPage>;
197
+ searchPaymentHistory(opts: SearchPaymentHistoryOptions): Promise<SearchPaymentsPage>;
185
198
  createPmtAccount(opts: CreatePmtAccountOptions): Promise<PmtAccount>;
186
199
  continuePmtAccountOnboarding(opts: ContinuePmtAccountOnboardingOptions): Promise<ContinuePmtAccountOnboardingResult>;
187
200
  replacePmtAccount(opts: ReplacePmtAccountOptions): Promise<PmtAccount>;
@@ -228,6 +241,7 @@ export declare class PaymentsFX implements PaymentsFXOperator {
228
241
  createPayment(opts: CreatePaymentOptions): Promise<Payment>;
229
242
  replacePayment(opts: ReplacePaymentOptions): Promise<Payment>;
230
243
  searchPayments(opts: SearchPaymentsOptions): Promise<SearchPaymentsPage>;
244
+ searchPaymentHistory(opts: SearchPaymentHistoryOptions): Promise<SearchPaymentsPage>;
231
245
  createPmtAccount(opts: CreatePmtAccountOptions): Promise<PmtAccount>;
232
246
  continuePmtAccountOnboarding(opts: ContinuePmtAccountOnboardingOptions): Promise<ContinuePmtAccountOnboardingResult>;
233
247
  replacePmtAccount(opts: ReplacePmtAccountOptions): Promise<PmtAccount>;
@@ -26,7 +26,7 @@ const msgPayableSourceMissing = "Payable entity source is unavailable.";
26
26
  const msgPayableBalanceChanged = "Payment balance changed or a payment is still pending. Refresh before paying.";
27
27
  const msgPaymentMethodRequired = "A payment method is required.";
28
28
  const msgPayableUnavailable = "This entity is not available for payment.";
29
- const msgPaymentScopeMissing = "Payment history requires a payer or recipient scope and an entity type.";
29
+ const msgPaymentScopeMissing = "Payment history requires a payer or recipient scope.";
30
30
  const msgPaymentHistoryIncomplete = "Payment history response is incomplete.";
31
31
  const msgPaymentEntityInvalid = "Payment resolution requires a valid entity, currency, and amount.";
32
32
  const msgPaymentEntityConflict = "Payment resolution received conflicting entity amounts.";
@@ -63,6 +63,14 @@ const msgPublicAmountExceedsBalance = "Public payment amount cannot exceed the s
63
63
  export const PaymentsEvents = {
64
64
  Changed: createEvent(),
65
65
  };
66
+ export const PaymentDirection = {
67
+ Outgoing: "outgoing",
68
+ Incoming: "incoming",
69
+ };
70
+ export function isIncomingPayment(payment, viewerID) {
71
+ return (payment.recipient_id === viewerID &&
72
+ (payment.is_external || payment.payer_id !== viewerID));
73
+ }
66
74
  export const PmtAccountAccessStatus = {
67
75
  Missing: "missing",
68
76
  OnboardingRequired: "onboarding_required",
@@ -390,12 +398,57 @@ export class PaymentsFX {
390
398
  return payment;
391
399
  }
392
400
  async searchPayments(opts) {
393
- return await runOwnerSearch({
401
+ const owner_id = resolvedID(opts.owner_id);
402
+ const recipient_id = resolvedID(opts.recipient_id);
403
+ if (!owner_id && !recipient_id)
404
+ throw errValidation({ msg: msgPaymentScopeMissing });
405
+ return await runSearch({
394
406
  ...opts,
395
- query: queryParams({ type: opts.type, kind: opts.kind }),
407
+ query: queryParams({
408
+ owner_id,
409
+ recipient_id,
410
+ type: opts.type,
411
+ kind: opts.kind,
412
+ psp_actionable_status: opts.psp_actionable_status,
413
+ currency: opts.currency?.trim().toUpperCase() || undefined,
414
+ }),
396
415
  search: (searchOpts) => this.payments.searchManyPayments(searchOpts),
397
416
  });
398
417
  }
418
+ async searchPaymentHistory(opts) {
419
+ const { owner_id, direction, ...searchOpts } = opts;
420
+ const viewer = resolvedID(owner_id);
421
+ if (!viewer)
422
+ throw errValidation({ msg: msgPaymentScopeMissing });
423
+ const incoming = direction === PaymentDirection.Incoming;
424
+ let page = opts.page;
425
+ while (true) {
426
+ opts.signal?.throwIfAborted();
427
+ const out = await this.searchPayments({
428
+ ...searchOpts,
429
+ ...(incoming ? { recipient_id: viewer } : { owner_id: viewer }),
430
+ page,
431
+ });
432
+ // Public bill payments belong to their recipient. Ownership alone does
433
+ // not make them outgoing; scan source pages without changing their order.
434
+ const results = out.results.filter((payment) => isIncomingPayment(payment, viewer) === incoming);
435
+ if (results.length || out.done) {
436
+ return {
437
+ ...out,
438
+ results,
439
+ total_count: undefined,
440
+ last_page: undefined,
441
+ };
442
+ }
443
+ if (out.next_page <= out.page) {
444
+ throw errResolveFailed({
445
+ resource: resourcePayment,
446
+ msg: msgPaymentHistoryIncomplete,
447
+ });
448
+ }
449
+ page = out.next_page;
450
+ }
451
+ }
399
452
  async createPmtAccount(opts) {
400
453
  const out = await this.payments.insertOnePmtAccount(opts);
401
454
  const id = requiredOperationID(out, msgCreatedPmtAccountIDMissing);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabriktor/fx",
3
- "version": "0.0.130",
3
+ "version": "0.0.131",
4
4
  "description": "![Fabriktor Logo](./img/fabriktor-character.gif)",
5
5
  "type": "module",
6
6
  "exports": {