@classytic/revenue 2.0.1 → 2.1.3
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.
- package/CHANGELOG.md +66 -0
- package/README.md +33 -10
- package/dist/bank-feed-BlQeq2rK.mjs +133 -0
- package/dist/bank-feed.enums-BadqNJTC.d.mts +118 -0
- package/dist/bank-feed.enums-kYTLTTbe.mjs +165 -0
- package/dist/bridges/index.d.mts +1 -1
- package/dist/core/state-machines.d.mts +25 -2
- package/dist/core/state-machines.mjs +43 -3
- package/dist/engine-types-Jctrbasz.d.mts +1160 -0
- package/dist/enums/index.d.mts +4 -3
- package/dist/enums/index.mjs +4 -3
- package/dist/{errors-DHa8JVQ-.mjs → errors-LYYg9wcs.mjs} +23 -1
- package/dist/{escrow.schema-D5X32LwX.d.mts → escrow.schema-YuBgjL-I.d.mts} +27 -27
- package/dist/{event-constants-CEMitnIV.mjs → event-constants-Dn1TKahe.mjs} +6 -0
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +3 -3
- package/dist/index.d.mts +32 -13
- package/dist/index.mjs +142 -19
- package/dist/providers/index.d.mts +2 -2
- package/dist/providers/index.mjs +2 -2
- package/dist/registry-h8sasoLh.d.mts +145 -0
- package/dist/repositories/create-repositories.d.mts +1 -1
- package/dist/repositories/create-repositories.mjs +1 -1
- package/dist/{revenue-bridges-sdlrR85c.d.mts → revenue-bridges-BtkWFsJu.d.mts} +107 -1
- package/dist/{revenue-event-catalog-LqxPnsU_.mjs → revenue-event-catalog-BvjNVnPd.mjs} +77 -3
- package/dist/{revenue-event-catalog-BX3g7RUi.d.mts → revenue-event-catalog-JpJcyK1E.d.mts} +198 -2
- package/dist/settlement.repository-BAdc9qGl.mjs +1444 -0
- package/dist/shared/index.d.mts +1 -1
- package/dist/shared/index.mjs +2 -2
- package/dist/{subscription.enums-tfoAgsTv.mjs → subscription.enums-95othr0i.mjs} +1 -40
- package/dist/{transaction.enums-u4MshXcL.d.mts → subscription.enums-k24kLpF7.d.mts} +1 -36
- package/dist/validators/index.d.mts +158 -2
- package/dist/validators/index.mjs +95 -2
- package/package.json +7 -7
- package/dist/engine-types-CcjIb4Fy.d.mts +0 -611
- package/dist/registry-DhFMsSn5.mjs +0 -150
- package/dist/registry-SvIGPAx_.d.mts +0 -143
- package/dist/settlement.repository-DHIPx5S4.mjs +0 -771
- /package/dist/{audit-B39B0Sdq.mjs → audit-Ba2XB2C4.mjs} +0 -0
- /package/dist/{audit-DZ0eTr9g.d.mts → audit-DRKuLBFO.d.mts} +0 -0
- /package/dist/{context-DRqSeTPM.d.mts → context-pjP1QeE3.d.mts} +0 -0
- /package/dist/{escrow.schema-BBv9oVEW.mjs → escrow.schema-C-b41z_G.mjs} +0 -0
- /package/dist/{monetization.enums-BtiU3t8o.mjs → monetization.enums-B9HBOecd.mjs} +0 -0
- /package/dist/{monetization.enums-D2xbxXJM.d.mts → monetization.enums-DzAI4sT7.d.mts} +0 -0
- /package/dist/{splits-BAfY-a9P.mjs → splits-CNfQj92L.mjs} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
1
|
+
import { _ as TRANSACTION_STATUS, a as TRANSACTION_KIND, b as isTransactionFlow, c as isBankFeedSource, d as isTransactionKind, f as statusesForKind, g as TRANSACTION_FLOW_VALUES, h as TRANSACTION_FLOW, i as BANK_FEED_STATUS_VALUES, l as isBankFeedStatus, m as LIBRARY_CATEGORY_VALUES, n as BANK_FEED_SOURCE_VALUES, o as TRANSACTION_KIND_VALUES, p as LIBRARY_CATEGORIES, r as BANK_FEED_STATUS, s as initialStatusFor, t as BANK_FEED_SOURCE, u as isStatusValidForKind, v as TRANSACTION_STATUS_VALUES, x as isTransactionStatus, y as isLibraryCategory } from "./bank-feed.enums-kYTLTTbe.mjs";
|
|
2
|
+
import { n as SubscriptionRepository, r as TransactionRepository, t as SettlementRepository } from "./settlement.repository-BAdc9qGl.mjs";
|
|
3
|
+
import { n as createEvent, t as REVENUE_EVENTS } from "./event-constants-Dn1TKahe.mjs";
|
|
4
|
+
import { A as isReleaseReason, C as HOLD_REASON_VALUES, D as RELEASE_REASON_VALUES, E as RELEASE_REASON, O as isHoldReason, S as HOLD_REASON, T as HOLD_STATUS_VALUES, _ as SETTLEMENT_STATUS_VALUES, a as isPlanKey, b as isSettlementStatus, c as PAYOUT_METHOD_VALUES, d as SPLIT_TYPE, f as SPLIT_TYPE_VALUES, g as SETTLEMENT_STATUS, h as isSplitType, i as SUBSCRIPTION_STATUS_VALUES, k as isHoldStatus, l as SPLIT_STATUS, m as isSplitStatus, n as PLAN_KEY_VALUES, o as isSubscriptionStatus, p as isPayoutMethod, r as SUBSCRIPTION_STATUS, s as PAYOUT_METHOD, t as PLAN_KEYS, u as SPLIT_STATUS_VALUES, v as SETTLEMENT_TYPE, w as HOLD_STATUS, x as isSettlementType, y as SETTLEMENT_TYPE_VALUES } from "./subscription.enums-95othr0i.mjs";
|
|
5
|
+
import { a as InvalidStateTransitionError, c as ProviderCapabilityError, d as RevenueError, f as SettlementNotFoundError, g as WrongTransactionKindError, h as ValidationError, i as ConfigurationError, l as ProviderNotFoundError, m as TransactionNotFoundError, n as BankFeedImportError, o as PaymentIntentCreationError, p as SubscriptionNotFoundError, r as BankFeedProviderNotFoundError, s as PaymentVerificationError, t as AlreadyVerifiedError, u as RefundNotSupportedError } from "./errors-LYYg9wcs.mjs";
|
|
6
|
+
import { BANK_FEED_STATE_MACHINE, HOLD_STATE_MACHINE, MANUAL_STATE_MACHINE, PAYMENT_FLOW_STATE_MACHINE, SETTLEMENT_STATE_MACHINE, SPLIT_STATE_MACHINE, SUBSCRIPTION_STATE_MACHINE, StateMachine, TRANSACTION_STATE_MACHINE, smFor } from "./core/state-machines.mjs";
|
|
7
|
+
import { a as reverseTax, c as reverseCommission, i as getTaxType, n as calculateSplits, o as validateTaxCalculation, r as calculateTax, s as calculateCommission, t as calculateOrganizationPayout } from "./splits-CNfQj92L.mjs";
|
|
7
8
|
import { createRevenueRepositories } from "./repositories/create-repositories.mjs";
|
|
8
|
-
import { a as
|
|
9
|
-
import {
|
|
10
|
-
import { a as PAYMENT_GATEWAY_TYPE_VALUES, c as isPaymentGatewayType, i as PAYMENT_GATEWAY_TYPE, l as isPaymentStatus, n as MONETIZATION_TYPE_VALUES, o as PAYMENT_STATUS, r as isMonetizationType, s as PAYMENT_STATUS_VALUES, t as MONETIZATION_TYPES } from "./monetization.enums-
|
|
11
|
-
import { _ as transactionListFilterSchema, a as paymentVerifySchema, c as settlementCreateSchema, d as subscriptionBaseSchema, f as subscriptionCreateSchema, g as transactionCreateSchema, h as transactionBaseSchema, i as paymentIntentSchema, l as settlementListFilterSchema, m as subscriptionUpdateSchema, n as escrowReleaseSchema, o as refundSchema, p as subscriptionListFilterSchema, r as splitRuleSchema, s as settlementBaseSchema, t as escrowHoldSchema, u as settlementUpdateSchema, v as transactionUpdateSchema } from "./escrow.schema-
|
|
12
|
-
import { C as sumMoney, E as toSmallestUnit, S as subtractMoney, T as toMajor, _ as isZeroMoney, a as CurrencyMismatchError, b as multiplyMoney, c as addMoney, d as fromMajor, f as fromSmallestUnit, g as isPositiveMoney, h as isNegativeMoney, i as CURRENCIES, l as compareMoney, m as isMoney, n as getAuditTrail, o as MINOR_UNIT_FACTOR, p as isCurrencyCode, r as getLastStateChange, s as absMoney, t as appendAuditEvent, u as equalsMoney, v as minorUnitFactor, w as toCurrencyCode, x as negateMoney, y as money } from "./audit-
|
|
9
|
+
import { a as createProviderRegistry, i as ProviderRegistry, n as BankFeedProviderRegistry, o as PaymentProvider, r as createBankFeedProviderRegistry, t as BankFeedProvider } from "./bank-feed-BlQeq2rK.mjs";
|
|
10
|
+
import { M as revenueEventDefinitions, N as InProcessRevenueBus } from "./revenue-event-catalog-BvjNVnPd.mjs";
|
|
11
|
+
import { a as PAYMENT_GATEWAY_TYPE_VALUES, c as isPaymentGatewayType, i as PAYMENT_GATEWAY_TYPE, l as isPaymentStatus, n as MONETIZATION_TYPE_VALUES, o as PAYMENT_STATUS, r as isMonetizationType, s as PAYMENT_STATUS_VALUES, t as MONETIZATION_TYPES } from "./monetization.enums-B9HBOecd.mjs";
|
|
12
|
+
import { _ as transactionListFilterSchema, a as paymentVerifySchema, c as settlementCreateSchema, d as subscriptionBaseSchema, f as subscriptionCreateSchema, g as transactionCreateSchema, h as transactionBaseSchema, i as paymentIntentSchema, l as settlementListFilterSchema, m as subscriptionUpdateSchema, n as escrowReleaseSchema, o as refundSchema, p as subscriptionListFilterSchema, r as splitRuleSchema, s as settlementBaseSchema, t as escrowHoldSchema, u as settlementUpdateSchema, v as transactionUpdateSchema } from "./escrow.schema-C-b41z_G.mjs";
|
|
13
|
+
import { C as sumMoney, E as toSmallestUnit, S as subtractMoney, T as toMajor, _ as isZeroMoney, a as CurrencyMismatchError, b as multiplyMoney, c as addMoney, d as fromMajor, f as fromSmallestUnit, g as isPositiveMoney, h as isNegativeMoney, i as CURRENCIES, l as compareMoney, m as isMoney, n as getAuditTrail, o as MINOR_UNIT_FACTOR, p as isCurrencyCode, r as getLastStateChange, s as absMoney, t as appendAuditEvent, u as equalsMoney, v as minorUnitFactor, w as toCurrencyCode, x as negateMoney, y as money } from "./audit-Ba2XB2C4.mjs";
|
|
13
14
|
import { PluginManager } from "./plugins/plugin.interface.mjs";
|
|
14
|
-
import { customIdPlugin, multiTenantPlugin, prefixedId, softDeletePlugin } from "@classytic/mongokit";
|
|
15
|
-
import { resolveTenantConfig } from "@classytic/
|
|
15
|
+
import { batchOperationsPlugin, customIdPlugin, methodRegistryPlugin, multiTenantPlugin, prefixedId, softDeletePlugin } from "@classytic/mongokit";
|
|
16
|
+
import { resolveTenantConfig } from "@classytic/repo-core/tenant";
|
|
16
17
|
import mongoose, { Schema } from "mongoose";
|
|
17
18
|
import { InvalidOutboxEventError, OutboxOwnershipError } from "@classytic/primitives/outbox";
|
|
18
19
|
import { err, isErr, isOk, ok } from "@classytic/primitives/result";
|
|
19
20
|
|
|
20
21
|
//#region src/models/transaction.schema.ts
|
|
22
|
+
const NO_BANK_FEED_INDEXES = {
|
|
23
|
+
idempotentImport: false,
|
|
24
|
+
byAccount: false,
|
|
25
|
+
matchCandidates: false
|
|
26
|
+
};
|
|
21
27
|
function buildTransactionSchema(config) {
|
|
22
28
|
const fields = {
|
|
23
29
|
publicId: { type: String },
|
|
@@ -25,6 +31,13 @@ function buildTransactionSchema(config) {
|
|
|
25
31
|
type: String,
|
|
26
32
|
default: null
|
|
27
33
|
},
|
|
34
|
+
kind: {
|
|
35
|
+
type: String,
|
|
36
|
+
enum: TRANSACTION_KIND_VALUES,
|
|
37
|
+
default: TRANSACTION_KIND.PAYMENT_FLOW,
|
|
38
|
+
required: true,
|
|
39
|
+
index: true
|
|
40
|
+
},
|
|
28
41
|
type: {
|
|
29
42
|
type: String,
|
|
30
43
|
required: true
|
|
@@ -56,6 +69,9 @@ function buildTransactionSchema(config) {
|
|
|
56
69
|
default: 0
|
|
57
70
|
},
|
|
58
71
|
taxDetails: { type: Schema.Types.Mixed },
|
|
72
|
+
fxRate: { type: Number },
|
|
73
|
+
originalAmount: { type: Number },
|
|
74
|
+
originalCurrency: { type: String },
|
|
59
75
|
method: {
|
|
60
76
|
type: String,
|
|
61
77
|
required: true
|
|
@@ -64,11 +80,27 @@ function buildTransactionSchema(config) {
|
|
|
64
80
|
type: String,
|
|
65
81
|
default: "pending"
|
|
66
82
|
},
|
|
83
|
+
approvals: {
|
|
84
|
+
type: Schema.Types.Mixed,
|
|
85
|
+
default: null
|
|
86
|
+
},
|
|
67
87
|
gateway: { type: Schema.Types.Mixed },
|
|
68
88
|
paymentDetails: { type: Schema.Types.Mixed },
|
|
69
89
|
commission: { type: Schema.Types.Mixed },
|
|
70
90
|
splits: [{ type: Schema.Types.Mixed }],
|
|
71
91
|
hold: { type: Schema.Types.Mixed },
|
|
92
|
+
externalId: { type: String },
|
|
93
|
+
postedDate: { type: Date },
|
|
94
|
+
valueDate: { type: Date },
|
|
95
|
+
description: { type: String },
|
|
96
|
+
counterparty: { type: Schema.Types.Mixed },
|
|
97
|
+
reference: { type: String },
|
|
98
|
+
balanceAfter: { type: Number },
|
|
99
|
+
vendorCategory: { type: String },
|
|
100
|
+
bankAccountId: { type: String },
|
|
101
|
+
source: { type: String },
|
|
102
|
+
journalEntryRef: { type: Schema.Types.Mixed },
|
|
103
|
+
matching: { type: Schema.Types.Mixed },
|
|
72
104
|
sourceId: { type: String },
|
|
73
105
|
sourceModel: { type: String },
|
|
74
106
|
relatedTransactionId: {
|
|
@@ -103,6 +135,32 @@ function buildTransactionSchema(config) {
|
|
|
103
135
|
sourceId: 1,
|
|
104
136
|
sourceModel: 1
|
|
105
137
|
});
|
|
138
|
+
schema.index({
|
|
139
|
+
kind: 1,
|
|
140
|
+
status: 1,
|
|
141
|
+
createdAt: -1
|
|
142
|
+
});
|
|
143
|
+
schema.index({ relatedTransactionId: 1 }, { sparse: true });
|
|
144
|
+
const bfi = config.bankFeedIndexes ?? NO_BANK_FEED_INDEXES;
|
|
145
|
+
if (bfi.byAccount) schema.index({
|
|
146
|
+
bankAccountId: 1,
|
|
147
|
+
postedDate: -1
|
|
148
|
+
}, {
|
|
149
|
+
partialFilterExpression: { bankAccountId: { $type: "string" } },
|
|
150
|
+
name: "bank_feed_by_account"
|
|
151
|
+
});
|
|
152
|
+
if (bfi.matchCandidates) {
|
|
153
|
+
schema.index({
|
|
154
|
+
kind: 1,
|
|
155
|
+
amount: 1,
|
|
156
|
+
postedDate: -1
|
|
157
|
+
}, { name: "match_candidates_by_amount_date" });
|
|
158
|
+
schema.index({
|
|
159
|
+
kind: 1,
|
|
160
|
+
amount: 1,
|
|
161
|
+
createdAt: -1
|
|
162
|
+
}, { name: "match_candidates_by_amount_createdat" });
|
|
163
|
+
}
|
|
106
164
|
if (config.extraIndexes) for (const idx of config.extraIndexes) schema.index(idx.fields, idx.options);
|
|
107
165
|
return schema;
|
|
108
166
|
}
|
|
@@ -151,6 +209,10 @@ function buildSubscriptionSchema(config) {
|
|
|
151
209
|
canceledAt: { type: Date },
|
|
152
210
|
cancelAt: { type: Date },
|
|
153
211
|
cancellationReason: { type: String },
|
|
212
|
+
approvals: {
|
|
213
|
+
type: Schema.Types.Mixed,
|
|
214
|
+
default: null
|
|
215
|
+
},
|
|
154
216
|
renewalTransactionId: {
|
|
155
217
|
type: Schema.Types.ObjectId,
|
|
156
218
|
ref: txnRef
|
|
@@ -207,6 +269,10 @@ function buildSettlementSchema(config) {
|
|
|
207
269
|
type: String,
|
|
208
270
|
default: "pending"
|
|
209
271
|
},
|
|
272
|
+
approvals: {
|
|
273
|
+
type: Schema.Types.Mixed,
|
|
274
|
+
default: null
|
|
275
|
+
},
|
|
210
276
|
payoutMethod: {
|
|
211
277
|
type: String,
|
|
212
278
|
required: true
|
|
@@ -282,7 +348,7 @@ function buildSettlementSchema(config) {
|
|
|
282
348
|
* The field storage type follows `scope.fieldType` (`'objectId'` →
|
|
283
349
|
* `Schema.Types.ObjectId` + `ref`, `'string'` → `String`). No hardcoding
|
|
284
350
|
* here — callers must pass a `ResolvedTenantConfig` from
|
|
285
|
-
* `@classytic/
|
|
351
|
+
* `@classytic/repo-core/tenant` via `resolveTenantConfig(...)`.
|
|
286
352
|
*/
|
|
287
353
|
function injectTenantField(schema, scope) {
|
|
288
354
|
schema.add({ [scope.tenantField]: {
|
|
@@ -325,7 +391,7 @@ var RevenueModelCollisionError = class extends Error {
|
|
|
325
391
|
}
|
|
326
392
|
};
|
|
327
393
|
function createRevenueModels(options) {
|
|
328
|
-
const { connection, scope, schemaOptions = {}, modules = {}, collectionPrefix, forceRecreate } = options;
|
|
394
|
+
const { connection, scope, schemaOptions = {}, modules = {}, collectionPrefix, forceRecreate, bankFeedIndexes } = options;
|
|
329
395
|
const prefix = collectionPrefix ?? "";
|
|
330
396
|
if (forceRecreate) {
|
|
331
397
|
for (const name of REVENUE_MODEL_NAMES) if (connection.models[name]) connection.deleteModel(name);
|
|
@@ -333,7 +399,8 @@ function createRevenueModels(options) {
|
|
|
333
399
|
const txnSchema = buildTransactionSchema({
|
|
334
400
|
scoped: scope.enabled,
|
|
335
401
|
extraFields: schemaOptions.transaction?.extraFields,
|
|
336
|
-
extraIndexes: schemaOptions.transaction?.extraIndexes
|
|
402
|
+
extraIndexes: schemaOptions.transaction?.extraIndexes,
|
|
403
|
+
...bankFeedIndexes ? { bankFeedIndexes } : {}
|
|
337
404
|
});
|
|
338
405
|
injectTenantField(txnSchema, scope);
|
|
339
406
|
txnSchema.index({ "gateway.sessionId": 1 }, { sparse: true });
|
|
@@ -349,6 +416,23 @@ function createRevenueModels(options) {
|
|
|
349
416
|
publicId: { $type: "string" }
|
|
350
417
|
}
|
|
351
418
|
});
|
|
419
|
+
if (bankFeedIndexes?.idempotentImport) if (scope.enabled && scope.strategy === "field") txnSchema.index({
|
|
420
|
+
[scope.tenantField]: 1,
|
|
421
|
+
bankAccountId: 1,
|
|
422
|
+
externalId: 1
|
|
423
|
+
}, {
|
|
424
|
+
unique: true,
|
|
425
|
+
partialFilterExpression: { externalId: { $type: "string" } },
|
|
426
|
+
name: "bank_feed_idempotent_import"
|
|
427
|
+
});
|
|
428
|
+
else txnSchema.index({
|
|
429
|
+
bankAccountId: 1,
|
|
430
|
+
externalId: 1
|
|
431
|
+
}, {
|
|
432
|
+
unique: true,
|
|
433
|
+
partialFilterExpression: { externalId: { $type: "string" } },
|
|
434
|
+
name: "bank_feed_idempotent_import"
|
|
435
|
+
});
|
|
352
436
|
const models = { Transaction: connection.model("Transaction", txnSchema, prefix + DEFAULT_COLLECTIONS.Transaction) };
|
|
353
437
|
if (modules.subscription !== false) {
|
|
354
438
|
const subSchema = buildSubscriptionSchema({
|
|
@@ -388,10 +472,23 @@ function createRevenueModels(options) {
|
|
|
388
472
|
* See PACKAGE_RULES §13–§14.
|
|
389
473
|
*/
|
|
390
474
|
async function createRevenue(config) {
|
|
475
|
+
const bankFeedRaw = config.modules?.bankFeed;
|
|
476
|
+
const bankFeedEnabled = bankFeedRaw === false ? false : typeof bankFeedRaw === "object" && bankFeedRaw !== null ? bankFeedRaw.enabled !== false : true;
|
|
477
|
+
const userIndexCfg = typeof bankFeedRaw === "object" && bankFeedRaw !== null ? bankFeedRaw.indexes : void 0;
|
|
478
|
+
const bankFeedIndexes = bankFeedEnabled ? {
|
|
479
|
+
idempotentImport: userIndexCfg?.idempotentImport ?? true,
|
|
480
|
+
byAccount: userIndexCfg?.byAccount ?? true,
|
|
481
|
+
matchCandidates: userIndexCfg?.matchCandidates ?? false
|
|
482
|
+
} : {
|
|
483
|
+
idempotentImport: false,
|
|
484
|
+
byAccount: false,
|
|
485
|
+
matchCandidates: false
|
|
486
|
+
};
|
|
391
487
|
const modules = {
|
|
392
488
|
subscription: config.modules?.subscription !== false,
|
|
393
489
|
escrow: config.modules?.escrow ?? false,
|
|
394
|
-
settlement: config.modules?.settlement ?? false
|
|
490
|
+
settlement: config.modules?.settlement ?? false,
|
|
491
|
+
bankFeed: bankFeedEnabled
|
|
395
492
|
};
|
|
396
493
|
const scope = resolveTenantConfig(config.scope);
|
|
397
494
|
const events = config.eventTransport ?? new InProcessRevenueBus({ logger: config.logger });
|
|
@@ -400,6 +497,7 @@ async function createRevenue(config) {
|
|
|
400
497
|
scope,
|
|
401
498
|
schemaOptions: config.schemaOptions,
|
|
402
499
|
modules,
|
|
500
|
+
bankFeedIndexes,
|
|
403
501
|
...config.collectionPrefix !== void 0 ? { collectionPrefix: config.collectionPrefix } : {},
|
|
404
502
|
...config.forceRecreate !== void 0 ? { forceRecreate: config.forceRecreate } : {}
|
|
405
503
|
});
|
|
@@ -424,16 +522,18 @@ async function createRevenue(config) {
|
|
|
424
522
|
return plugins;
|
|
425
523
|
};
|
|
426
524
|
const repositories = createRevenueRepositories(models, {
|
|
427
|
-
transaction: buildPlugins("txn"),
|
|
525
|
+
transaction: buildPlugins("txn", modules.bankFeed ? [methodRegistryPlugin(), batchOperationsPlugin()] : []),
|
|
428
526
|
subscription: buildPlugins("sub"),
|
|
429
527
|
settlement: buildPlugins("stl")
|
|
430
528
|
}, config.repositoryPlugins);
|
|
431
529
|
const providers = createProviderRegistry(config.providers ?? {}, config.defaultCurrency);
|
|
530
|
+
const bankFeedProviders = createBankFeedProviderRegistry(config.bankFeedProviders ?? {});
|
|
432
531
|
const commission = typeof config.modules?.commission === "object" ? config.modules.commission : config.commission;
|
|
433
532
|
repositories.transaction.inject({
|
|
434
533
|
events,
|
|
435
534
|
outbox: config.outbox,
|
|
436
535
|
providers,
|
|
536
|
+
bankFeedProviders,
|
|
437
537
|
bridges: config.bridges ?? {},
|
|
438
538
|
commission,
|
|
439
539
|
defaultCurrency: config.defaultCurrency,
|
|
@@ -460,6 +560,7 @@ async function createRevenue(config) {
|
|
|
460
560
|
models,
|
|
461
561
|
repositories,
|
|
462
562
|
providers,
|
|
563
|
+
bankFeedProviders,
|
|
463
564
|
events,
|
|
464
565
|
async syncIndexes() {
|
|
465
566
|
await Promise.all(Object.values(models).filter(Boolean).map((m) => m.createIndexes()));
|
|
@@ -471,4 +572,26 @@ async function createRevenue(config) {
|
|
|
471
572
|
}
|
|
472
573
|
|
|
473
574
|
//#endregion
|
|
474
|
-
|
|
575
|
+
//#region src/events/outbox-store.ts
|
|
576
|
+
var MemoryOutboxStore = class {
|
|
577
|
+
events = [];
|
|
578
|
+
async save(event, _options) {
|
|
579
|
+
this.events.push({ event });
|
|
580
|
+
}
|
|
581
|
+
async getPending(limit) {
|
|
582
|
+
return this.events.filter((e) => !e.acknowledgedAt).slice(0, limit).map((e) => e.event);
|
|
583
|
+
}
|
|
584
|
+
async acknowledge(eventId, _options) {
|
|
585
|
+
const entry = this.events.find((e) => e.event.meta.id === eventId);
|
|
586
|
+
if (entry) entry.acknowledgedAt = /* @__PURE__ */ new Date();
|
|
587
|
+
}
|
|
588
|
+
async purge(olderThanMs) {
|
|
589
|
+
const cutoff = Date.now() - olderThanMs;
|
|
590
|
+
const before = this.events.length;
|
|
591
|
+
this.events = this.events.filter((e) => !e.acknowledgedAt || e.acknowledgedAt.getTime() >= cutoff);
|
|
592
|
+
return before - this.events.length;
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
//#endregion
|
|
597
|
+
export { AlreadyVerifiedError, BANK_FEED_SOURCE, BANK_FEED_SOURCE_VALUES, BANK_FEED_STATE_MACHINE, BANK_FEED_STATUS, BANK_FEED_STATUS_VALUES, BankFeedImportError, BankFeedProvider, BankFeedProviderNotFoundError, BankFeedProviderRegistry, CURRENCIES, ConfigurationError, CurrencyMismatchError, HOLD_REASON, HOLD_REASON_VALUES, HOLD_STATE_MACHINE, HOLD_STATUS, HOLD_STATUS_VALUES, InProcessRevenueBus, InvalidOutboxEventError, InvalidStateTransitionError, LIBRARY_CATEGORIES, LIBRARY_CATEGORY_VALUES, MANUAL_STATE_MACHINE, MINOR_UNIT_FACTOR, MONETIZATION_TYPES, MONETIZATION_TYPE_VALUES, MemoryOutboxStore, OutboxOwnershipError, PAYMENT_FLOW_STATE_MACHINE, PAYMENT_GATEWAY_TYPE, PAYMENT_GATEWAY_TYPE_VALUES, PAYMENT_STATUS, PAYMENT_STATUS_VALUES, PAYOUT_METHOD, PAYOUT_METHOD_VALUES, PLAN_KEYS, PLAN_KEY_VALUES, PaymentIntentCreationError, PaymentProvider, PaymentVerificationError, PluginManager, ProviderCapabilityError, ProviderNotFoundError, ProviderRegistry, RELEASE_REASON, RELEASE_REASON_VALUES, REVENUE_EVENTS, RefundNotSupportedError, RevenueError, SETTLEMENT_STATE_MACHINE, SETTLEMENT_STATUS, SETTLEMENT_STATUS_VALUES, SETTLEMENT_TYPE, SETTLEMENT_TYPE_VALUES, SPLIT_STATE_MACHINE, SPLIT_STATUS, SPLIT_STATUS_VALUES, SPLIT_TYPE, SPLIT_TYPE_VALUES, SUBSCRIPTION_STATE_MACHINE, SUBSCRIPTION_STATUS, SUBSCRIPTION_STATUS_VALUES, SettlementNotFoundError, SettlementRepository, StateMachine, SubscriptionNotFoundError, SubscriptionRepository, TRANSACTION_FLOW, TRANSACTION_FLOW_VALUES, TRANSACTION_KIND, TRANSACTION_KIND_VALUES, TRANSACTION_STATE_MACHINE, TRANSACTION_STATUS, TRANSACTION_STATUS_VALUES, TransactionNotFoundError, TransactionRepository, ValidationError, WrongTransactionKindError, absMoney, addMoney, appendAuditEvent, calculateCommission, calculateOrganizationPayout, calculateSplits, calculateTax, compareMoney, createBankFeedProviderRegistry, createEvent, createProviderRegistry, createRevenue, equalsMoney, err, escrowHoldSchema, escrowReleaseSchema, fromMajor, fromSmallestUnit, getAuditTrail, getLastStateChange, getTaxType, initialStatusFor, isBankFeedSource, isBankFeedStatus, isCurrencyCode, isErr, isHoldReason, isHoldStatus, isLibraryCategory, isMonetizationType, isMoney, isNegativeMoney, isOk, isPaymentGatewayType, isPaymentStatus, isPayoutMethod, isPlanKey, isPositiveMoney, isReleaseReason, isSettlementStatus, isSettlementType, isSplitStatus, isSplitType, isStatusValidForKind, isSubscriptionStatus, isTransactionFlow, isTransactionKind, isTransactionStatus, isZeroMoney, minorUnitFactor, money, multiplyMoney, negateMoney, ok, paymentIntentSchema, paymentVerifySchema, refundSchema, revenueEventDefinitions, reverseCommission, reverseTax, settlementBaseSchema, settlementCreateSchema, settlementListFilterSchema, settlementUpdateSchema, smFor, splitRuleSchema, statusesForKind, subscriptionBaseSchema, subscriptionCreateSchema, subscriptionListFilterSchema, subscriptionUpdateSchema, subtractMoney, sumMoney, toCurrencyCode, toMajor, toSmallestUnit, transactionBaseSchema, transactionCreateSchema, transactionListFilterSchema, transactionUpdateSchema, validateTaxCalculation };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export {
|
|
1
|
+
import { a as BankFeedProviderRegistry, c as ParseUploadParams, d as PaymentProvider, i as BankFeedProviderCapabilities, l as ParseUploadResult, n as createProviderRegistry, o as FetchTransactionsParams, r as BankFeedProvider, s as FetchTransactionsResult, t as ProviderRegistry, u as createBankFeedProviderRegistry } from "../registry-h8sasoLh.mjs";
|
|
2
|
+
export { BankFeedProvider, type BankFeedProviderCapabilities, BankFeedProviderRegistry, type FetchTransactionsParams, type FetchTransactionsResult, type ParseUploadParams, type ParseUploadResult, PaymentProvider, ProviderRegistry, createBankFeedProviderRegistry, createProviderRegistry };
|
package/dist/providers/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as createProviderRegistry, i as ProviderRegistry, n as BankFeedProviderRegistry, o as PaymentProvider, r as createBankFeedProviderRegistry, t as BankFeedProvider } from "../bank-feed-BlQeq2rK.mjs";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { BankFeedProvider, BankFeedProviderRegistry, PaymentProvider, ProviderRegistry, createBankFeedProviderRegistry, createProviderRegistry };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { a as BankFeedSourceValue } from "./bank-feed.enums-BadqNJTC.mjs";
|
|
2
|
+
import { CreateIntentParams, PaymentIntent, PaymentResult, ProviderCapabilities, RefundResult, WebhookEvent } from "@classytic/primitives/payment-gateway";
|
|
3
|
+
import { BankStatement, BankTransaction } from "@classytic/primitives/bank-transaction";
|
|
4
|
+
|
|
5
|
+
//#region src/providers/base.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Abstract `PaymentProvider` — the contract revenue's repositories
|
|
8
|
+
* consume. Provider implementations may extend this for the default
|
|
9
|
+
* config plumbing, or just satisfy the structural shape.
|
|
10
|
+
*/
|
|
11
|
+
declare abstract class PaymentProvider {
|
|
12
|
+
readonly config: Record<string, unknown>;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
private _defaultCurrency;
|
|
15
|
+
constructor(config?: Record<string, unknown>);
|
|
16
|
+
get defaultCurrency(): string;
|
|
17
|
+
setDefaultCurrency(currency: string): void;
|
|
18
|
+
abstract createIntent(params: CreateIntentParams): Promise<PaymentIntent>;
|
|
19
|
+
abstract verifyPayment(intentId: string): Promise<PaymentResult>;
|
|
20
|
+
abstract getStatus(intentId: string): Promise<PaymentResult>;
|
|
21
|
+
abstract refund(paymentId: string, amount?: number | null, options?: {
|
|
22
|
+
reason?: string;
|
|
23
|
+
}): Promise<RefundResult>;
|
|
24
|
+
abstract handleWebhook(payload: unknown, headers?: Record<string, string>): Promise<WebhookEvent>;
|
|
25
|
+
/**
|
|
26
|
+
* Default: accept all signatures (manual / dev provider). Real
|
|
27
|
+
* gateways MUST override with HMAC / timing-safe verification.
|
|
28
|
+
*/
|
|
29
|
+
verifyWebhookSignature(_payload: unknown, _signature: string): boolean;
|
|
30
|
+
getCapabilities(): ProviderCapabilities;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/providers/bank-feed.d.ts
|
|
34
|
+
interface BankFeedProviderCapabilities {
|
|
35
|
+
/** Supports continuous sync (Plaid, QBO CDC, Xero CDC). */
|
|
36
|
+
supportsSync: boolean;
|
|
37
|
+
/** Supports file upload parsing (OFX, CAMT.053, MT940, CSV, IIF). */
|
|
38
|
+
supportsUpload: boolean;
|
|
39
|
+
/** Provider may report retracted entries (Plaid `removed[]`, OFX correction). */
|
|
40
|
+
supportsRemovals: boolean;
|
|
41
|
+
/** Cursor-resumable — `fetchTransactions` returns a `nextCursor`. */
|
|
42
|
+
cursorBased: boolean;
|
|
43
|
+
/** Multi-account in a single sync call. */
|
|
44
|
+
multiAccount: boolean;
|
|
45
|
+
}
|
|
46
|
+
interface FetchTransactionsParams {
|
|
47
|
+
/** Resumption token from a previous call (Plaid cursor, QBO `LastUpdatedTime`, …). */
|
|
48
|
+
cursor?: string | undefined;
|
|
49
|
+
/** Account scope. May be undefined for providers that fetch all accounts. */
|
|
50
|
+
bankAccountId?: string | undefined;
|
|
51
|
+
/** Optional date floor — supplements cursor-based drains. */
|
|
52
|
+
from?: Date | undefined;
|
|
53
|
+
/** Optional date ceiling. */
|
|
54
|
+
to?: Date | undefined;
|
|
55
|
+
/** Provider-specific knobs. */
|
|
56
|
+
options?: Record<string, unknown> | undefined;
|
|
57
|
+
}
|
|
58
|
+
interface FetchTransactionsResult {
|
|
59
|
+
/** Newly added or updated rows. */
|
|
60
|
+
transactions: BankTransaction[];
|
|
61
|
+
/** Vendor-stable IDs of rows the upstream feed has retracted. */
|
|
62
|
+
removed?: Array<{
|
|
63
|
+
externalId: string;
|
|
64
|
+
bankAccountId?: string;
|
|
65
|
+
}>;
|
|
66
|
+
/** Resumption cursor for the next call. */
|
|
67
|
+
nextCursor?: string;
|
|
68
|
+
/** True when more pages are available — driver may stop calling when false. */
|
|
69
|
+
hasMore?: boolean;
|
|
70
|
+
/** Provider raw response for audit. Optional. */
|
|
71
|
+
raw?: unknown;
|
|
72
|
+
}
|
|
73
|
+
interface ParseUploadParams {
|
|
74
|
+
/** Raw upload bytes / string. */
|
|
75
|
+
buffer: Buffer | string | Uint8Array;
|
|
76
|
+
/** Format hint — providers MAY auto-detect when absent. */
|
|
77
|
+
format?: BankFeedSourceValue;
|
|
78
|
+
/** Account scope to stamp on every parsed row (when the file omits it). */
|
|
79
|
+
bankAccountId?: string;
|
|
80
|
+
/** Format-specific quirks (e.g. `'chase' | 'boa' | 'lenient'`). */
|
|
81
|
+
options?: Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
interface ParseUploadResult {
|
|
84
|
+
/** Statement-level metadata (account, period, balances). */
|
|
85
|
+
statements: BankStatement[];
|
|
86
|
+
/** Flat list of all rows across all statements — convenience for `import()`. */
|
|
87
|
+
transactions: BankTransaction[];
|
|
88
|
+
/** Per-row parse errors that didn't abort the file. */
|
|
89
|
+
warnings: Array<{
|
|
90
|
+
line?: number;
|
|
91
|
+
reason: string;
|
|
92
|
+
}>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Bank-feed provider — implement one method or both depending on the
|
|
96
|
+
* upstream's capabilities. Mirrors the optional-method pattern that
|
|
97
|
+
* works well across PaymentProvider's gateway plurality.
|
|
98
|
+
*/
|
|
99
|
+
declare abstract class BankFeedProvider {
|
|
100
|
+
readonly config: Record<string, unknown>;
|
|
101
|
+
readonly name: string;
|
|
102
|
+
constructor(name: string, config?: Record<string, unknown>);
|
|
103
|
+
/**
|
|
104
|
+
* Fetch a batch of transactions. Cursor-based providers (Plaid)
|
|
105
|
+
* return `nextCursor` for the next call; date-range providers
|
|
106
|
+
* (older QBO Reports API) ignore cursor and use `from` / `to`.
|
|
107
|
+
* Throws if the provider does not support sync.
|
|
108
|
+
*/
|
|
109
|
+
fetchTransactions?(_params: FetchTransactionsParams): Promise<FetchTransactionsResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Parse a file upload (OFX / CAMT.053 / MT940 / CSV / IIF). The
|
|
112
|
+
* canonical implementation delegates to `@classytic/fin-io`. Throws
|
|
113
|
+
* if the provider does not support uploads.
|
|
114
|
+
*/
|
|
115
|
+
parseUpload?(_params: ParseUploadParams): Promise<ParseUploadResult>;
|
|
116
|
+
/**
|
|
117
|
+
* Async drain — yields one batch per call until the upstream is
|
|
118
|
+
* caught up. Default implementation pulls `fetchTransactions` in a
|
|
119
|
+
* loop; providers can override for more efficient pagination
|
|
120
|
+
* (e.g. SSE / long-poll) or to interleave `removed[]` correctly.
|
|
121
|
+
*/
|
|
122
|
+
drain(params?: FetchTransactionsParams): AsyncGenerator<FetchTransactionsResult>;
|
|
123
|
+
abstract getCapabilities(): BankFeedProviderCapabilities;
|
|
124
|
+
}
|
|
125
|
+
declare class BankFeedProviderRegistry {
|
|
126
|
+
private providers;
|
|
127
|
+
register(name: string, provider: BankFeedProvider): void;
|
|
128
|
+
get(name: string): BankFeedProvider;
|
|
129
|
+
has(name: string): boolean;
|
|
130
|
+
list(): string[];
|
|
131
|
+
}
|
|
132
|
+
declare function createBankFeedProviderRegistry(providers?: Record<string, BankFeedProvider>): BankFeedProviderRegistry;
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/providers/registry.d.ts
|
|
135
|
+
declare class ProviderRegistry {
|
|
136
|
+
private providers;
|
|
137
|
+
register(name: string, provider: PaymentProvider): void;
|
|
138
|
+
get(name: string): PaymentProvider;
|
|
139
|
+
has(name: string): boolean;
|
|
140
|
+
list(): string[];
|
|
141
|
+
setDefaultCurrency(currency: string): void;
|
|
142
|
+
}
|
|
143
|
+
declare function createProviderRegistry(providers?: Record<string, PaymentProvider>, defaultCurrency?: string): ProviderRegistry;
|
|
144
|
+
//#endregion
|
|
145
|
+
export { BankFeedProviderRegistry as a, ParseUploadParams as c, PaymentProvider as d, BankFeedProviderCapabilities as i, ParseUploadResult as l, createProviderRegistry as n, FetchTransactionsParams as o, BankFeedProvider as r, FetchTransactionsResult as s, ProviderRegistry as t, createBankFeedProviderRegistry as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as SubscriptionRepository, l as TransactionRepository, s as SettlementRepository, u as RevenueModels } from "../engine-types-Jctrbasz.mjs";
|
|
2
2
|
import { PluginType } from "@classytic/mongokit";
|
|
3
3
|
|
|
4
4
|
//#region src/repositories/create-repositories.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as SubscriptionRepository, r as TransactionRepository, t as SettlementRepository } from "../settlement.repository-
|
|
1
|
+
import { n as SubscriptionRepository, r as TransactionRepository, t as SettlementRepository } from "../settlement.repository-BAdc9qGl.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/repositories/create-repositories.ts
|
|
4
4
|
function createRevenueRepositories(models, builtInPlugins, hostPlugins = {}) {
|
|
@@ -1,10 +1,116 @@
|
|
|
1
|
-
import { t as RevenueContext } from "./context-
|
|
1
|
+
import { t as RevenueContext } from "./context-pjP1QeE3.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/bridges/ledger.bridge.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* LedgerBridge — host-implemented contract for posting revenue events
|
|
6
|
+
* into a general-ledger / accounting system.
|
|
7
|
+
*
|
|
8
|
+
* Revenue does NOT import any ledger package directly (PACKAGE_RULES §23).
|
|
9
|
+
* The host wires this bridge once at engine creation time; revenue's repo
|
|
10
|
+
* verbs call the relevant hook after each state transition. Every method
|
|
11
|
+
* is optional — features degrade gracefully when omitted.
|
|
12
|
+
*
|
|
13
|
+
* Two phases of hooks:
|
|
14
|
+
*
|
|
15
|
+
* 1. **Payment-flow hooks** (`onPaymentVerified`, `onRefundProcessed`,
|
|
16
|
+
* `onSettlementCompleted`) — the original Stripe-style integration.
|
|
17
|
+
* Fired when a gateway transaction reaches a terminal accounting
|
|
18
|
+
* moment.
|
|
19
|
+
*
|
|
20
|
+
* 2. **Bank-feed hooks** (`onTransactionImported`, `onTransactionMatched`,
|
|
21
|
+
* `onTransactionJournalized`, `onTransactionRejected`,
|
|
22
|
+
* `onTransactionUnmatched`, `onTransactionRemovedByFeed`) — added
|
|
23
|
+
* in 3.0. Fired during the bank-feed lifecycle so the host can post
|
|
24
|
+
* JEs at match time, recall them on un-match, and chain
|
|
25
|
+
* `journalize()` after a successful JE post.
|
|
26
|
+
*
|
|
27
|
+
* The canonical wiring for `onTransactionMatched` is:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* const ledgerBridge: LedgerBridge = {
|
|
31
|
+
* async onTransactionMatched(txn, mapping, ctx) {
|
|
32
|
+
* const report = await wireImport({
|
|
33
|
+
* source: [{ txn, mapping }],
|
|
34
|
+
* mapper: bankToJournalEntryMapper(mapping),
|
|
35
|
+
* journalEntries: ledger.repositories.journalEntry,
|
|
36
|
+
* context: { organizationId: ctx.organizationId },
|
|
37
|
+
* }).run();
|
|
38
|
+
* if (report.ok && report.entries[0]) {
|
|
39
|
+
* await revenue.repositories.transaction.journalize(
|
|
40
|
+
* String(txn._id),
|
|
41
|
+
* { journalEntryRef: { type: 'JournalEntry', id: report.entries[0].id } },
|
|
42
|
+
* ctx,
|
|
43
|
+
* );
|
|
44
|
+
* }
|
|
45
|
+
* },
|
|
46
|
+
* };
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
4
49
|
interface LedgerBridge {
|
|
50
|
+
/** Fired when a gateway transaction reaches `verified` status. */
|
|
5
51
|
onPaymentVerified?(transaction: Record<string, unknown>, ctx: RevenueContext): Promise<void>;
|
|
52
|
+
/** Fired after a refund posts (the new outflow row + the updated original). */
|
|
6
53
|
onRefundProcessed?(original: Record<string, unknown>, refund: Record<string, unknown>, ctx: RevenueContext): Promise<void>;
|
|
54
|
+
/** Fired when a settlement record reaches `completed`. */
|
|
7
55
|
onSettlementCompleted?(settlement: Record<string, unknown>, ctx: RevenueContext): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Fired once per row inserted by `import()`. Use this for live preview
|
|
58
|
+
* dashboards or downstream materialized views — most production hosts
|
|
59
|
+
* leave this unimplemented and act on the per-batch `events.publish`
|
|
60
|
+
* stream instead.
|
|
61
|
+
*/
|
|
62
|
+
onTransactionImported?(transaction: Record<string, unknown>, ctx: RevenueContext): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Fired after `match()` succeeds. The host's typical implementation
|
|
65
|
+
* posts a journal entry via the host's ledger package (e.g. arc's
|
|
66
|
+
* `wireImport` over `@classytic/ledger`'s `journalEntry` repository),
|
|
67
|
+
* then calls `revenue.repositories.transaction.journalize(id, …)` so
|
|
68
|
+
* the row transitions `matched → journalized`.
|
|
69
|
+
*/
|
|
70
|
+
onTransactionMatched?(transaction: Record<string, unknown>, mapping: {
|
|
71
|
+
debitAccount?: string;
|
|
72
|
+
creditAccount?: string;
|
|
73
|
+
notes?: string;
|
|
74
|
+
}, ctx: RevenueContext): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Fired after `unmatch()` succeeds. Hosts can void / reverse the
|
|
77
|
+
* journal entry created at match time. Pass the prior
|
|
78
|
+
* `journalEntryRef` so reversal is keyed correctly.
|
|
79
|
+
*/
|
|
80
|
+
onTransactionUnmatched?(transaction: Record<string, unknown>, priorJournalEntryRef: {
|
|
81
|
+
type: string;
|
|
82
|
+
id: string;
|
|
83
|
+
} | undefined, ctx: RevenueContext): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Fired after `journalize()` stamps `journalEntryRef` on the row.
|
|
86
|
+
* Most hosts are passive on this hook (the JE was created in
|
|
87
|
+
* `onTransactionMatched`); useful for audit logs and analytics.
|
|
88
|
+
*/
|
|
89
|
+
onTransactionJournalized?(transaction: Record<string, unknown>, journalEntryRef: {
|
|
90
|
+
type: string;
|
|
91
|
+
id: string;
|
|
92
|
+
}, ctx: RevenueContext): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Fired after `reject()` — operator skip on a duplicate / non-cash
|
|
95
|
+
* import. Hosts typically log for audit.
|
|
96
|
+
*
|
|
97
|
+
* **JE reversal contract.** `reject()` is legal from `'matched'` as
|
|
98
|
+
* well as `'imported'`. If your `onTransactionMatched` posted a JE
|
|
99
|
+
* synchronously (the typical bridge implementation), the JE must be
|
|
100
|
+
* reversed here — revenue itself never calls into ledger and has no
|
|
101
|
+
* way to know one exists. Idempotency is the bridge's responsibility:
|
|
102
|
+
* a reject on a never-journalized row should be a no-op for ledger,
|
|
103
|
+
* a reject after journalize should void the JE keyed off
|
|
104
|
+
* `transaction.matching` or whatever the host stamped at match time.
|
|
105
|
+
*/
|
|
106
|
+
onTransactionRejected?(transaction: Record<string, unknown>, reason: string, ctx: RevenueContext): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Fired when the upstream feed retracts a row (Plaid `removed[]`,
|
|
109
|
+
* OFX correction, QBO CDC delete). The transaction is soft-deleted
|
|
110
|
+
* before this hook runs. If a JE was already posted, the host
|
|
111
|
+
* should reverse it.
|
|
112
|
+
*/
|
|
113
|
+
onTransactionRemovedByFeed?(transaction: Record<string, unknown>, ctx: RevenueContext): Promise<void>;
|
|
8
114
|
}
|
|
9
115
|
//#endregion
|
|
10
116
|
//#region src/bridges/tax.bridge.d.ts
|