@voyant-travel/plugin-smartbill 0.119.2
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/LICENSE +201 -0
- package/README.md +324 -0
- package/dist/artifacts.d.ts +80 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +295 -0
- package/dist/client/errors.d.ts +28 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +32 -0
- package/dist/client/fetch.d.ts +4 -0
- package/dist/client/fetch.d.ts.map +1 -0
- package/dist/client/fetch.js +32 -0
- package/dist/client/rate-limit.d.ts +8 -0
- package/dist/client/rate-limit.d.ts.map +1 -0
- package/dist/client/rate-limit.js +54 -0
- package/dist/client/resilience.d.ts +36 -0
- package/dist/client/resilience.d.ts.map +1 -0
- package/dist/client/resilience.js +23 -0
- package/dist/client.d.ts +67 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +234 -0
- package/dist/hono.d.ts +199 -0
- package/dist/hono.d.ts.map +1 -0
- package/dist/hono.js +77 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/invoice-ui-data.d.ts +46 -0
- package/dist/invoice-ui-data.d.ts.map +1 -0
- package/dist/invoice-ui-data.js +62 -0
- package/dist/invoice-ui.d.ts +438 -0
- package/dist/invoice-ui.d.ts.map +1 -0
- package/dist/invoice-ui.js +97 -0
- package/dist/mapping.d.ts +50 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +219 -0
- package/dist/mock/node.d.ts +4 -0
- package/dist/mock/node.d.ts.map +1 -0
- package/dist/mock/node.js +14 -0
- package/dist/mock/pdf.d.ts +7 -0
- package/dist/mock/pdf.d.ts.map +1 -0
- package/dist/mock/pdf.js +44 -0
- package/dist/mock/types.d.ts +94 -0
- package/dist/mock/types.d.ts.map +1 -0
- package/dist/mock/types.js +1 -0
- package/dist/mock.d.ts +4 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +431 -0
- package/dist/plugin.d.ts +55 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +192 -0
- package/dist/runtime.d.ts +25 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +42 -0
- package/dist/settlement.d.ts +33 -0
- package/dist/settlement.d.ts.map +1 -0
- package/dist/settlement.js +65 -0
- package/dist/sync/events.d.ts +5 -0
- package/dist/sync/events.d.ts.map +1 -0
- package/dist/sync/events.js +96 -0
- package/dist/sync/helpers.d.ts +66 -0
- package/dist/sync/helpers.d.ts.map +1 -0
- package/dist/sync/helpers.js +353 -0
- package/dist/sync/invoice.d.ts +3 -0
- package/dist/sync/invoice.d.ts.map +1 -0
- package/dist/sync/invoice.js +25 -0
- package/dist/sync/types.d.ts +71 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +1 -0
- package/dist/sync.d.ts +4 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +2 -0
- package/dist/types.d.ts +189 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/validation.d.ts +39 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +120 -0
- package/dist/workflow-candidates.d.ts +36 -0
- package/dist/workflow-candidates.d.ts.map +1 -0
- package/dist/workflow-candidates.js +182 -0
- package/dist/workflow-remote-discovery.d.ts +6 -0
- package/dist/workflow-remote-discovery.d.ts.map +1 -0
- package/dist/workflow-remote-discovery.js +83 -0
- package/dist/workflows/refs.d.ts +13 -0
- package/dist/workflows/refs.d.ts.map +1 -0
- package/dist/workflows/refs.js +51 -0
- package/dist/workflows/spaced-client.d.ts +5 -0
- package/dist/workflows/spaced-client.d.ts.map +1 -0
- package/dist/workflows/spaced-client.js +44 -0
- package/dist/workflows/types.d.ts +142 -0
- package/dist/workflows/types.d.ts.map +1 -0
- package/dist/workflows/types.js +1 -0
- package/dist/workflows.d.ts +5 -0
- package/dist/workflows.d.ts.map +1 -0
- package/dist/workflows.js +229 -0
- package/package.json +129 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SmartbillArtifactPersistenceOptions } from "./artifacts.js";
|
|
2
|
+
import { createSmartbillClient, type SmartbillClientApi } from "./client.js";
|
|
3
|
+
import type { SmartbillLogger, SmartbillMapFn, SmartbillPluginOptions } from "./plugin.js";
|
|
4
|
+
export interface ResolvedSmartbillSyncEventNames {
|
|
5
|
+
issued: string;
|
|
6
|
+
proformaIssued: string;
|
|
7
|
+
proformaConverted: string;
|
|
8
|
+
voided: string;
|
|
9
|
+
syncRequested: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SmartbillSyncRuntime {
|
|
12
|
+
client: ReturnType<typeof createSmartbillClient>;
|
|
13
|
+
logger: SmartbillLogger;
|
|
14
|
+
mapEvent: SmartbillMapFn;
|
|
15
|
+
eventNames: ResolvedSmartbillSyncEventNames;
|
|
16
|
+
artifacts: SmartbillArtifactPersistenceOptions;
|
|
17
|
+
idempotency: NonNullable<SmartbillPluginOptions["idempotency"]>;
|
|
18
|
+
onError: SmartbillPluginOptions["onError"];
|
|
19
|
+
writeBackInvoiceNumber: SmartbillPluginOptions["writeBackInvoiceNumber"];
|
|
20
|
+
}
|
|
21
|
+
export interface SmartbillSyncRuntimeOverrides {
|
|
22
|
+
client?: SmartbillClientApi;
|
|
23
|
+
}
|
|
24
|
+
export declare function createSmartbillSyncRuntime(options: SmartbillPluginOptions, overrides?: SmartbillSyncRuntimeOverrides): SmartbillSyncRuntime;
|
|
25
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,gBAAgB,CAAA;AACzE,OAAO,EAAE,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE5E,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAG1F,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;IAChD,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAA;IACxB,UAAU,EAAE,+BAA+B,CAAA;IAC3C,SAAS,EAAE,mCAAmC,CAAA;IAC9C,WAAW,EAAE,WAAW,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC,CAAA;IAC/D,OAAO,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAA;IAC1C,sBAAsB,EAAE,sBAAsB,CAAC,wBAAwB,CAAC,CAAA;CACzE;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC5B;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,sBAAsB,EAC/B,SAAS,GAAE,6BAAkC,GAC5C,oBAAoB,CA0CtB"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createSmartbillClient } from "./client.js";
|
|
2
|
+
import { mapVoyantInvoiceToSmartbillAsync } from "./mapping.js";
|
|
3
|
+
export function createSmartbillSyncRuntime(options, overrides = {}) {
|
|
4
|
+
const client = overrides.client ?? createSmartbillClient(options);
|
|
5
|
+
const logger = options.logger ?? console;
|
|
6
|
+
const mappingOptions = {
|
|
7
|
+
companyVatCode: options.companyVatCode,
|
|
8
|
+
seriesName: options.seriesName,
|
|
9
|
+
language: options.language,
|
|
10
|
+
isTaxIncluded: options.isTaxIncluded,
|
|
11
|
+
measuringUnitName: options.measuringUnitName,
|
|
12
|
+
art311SpecialRegime: options.art311SpecialRegime,
|
|
13
|
+
art311SpecialRegimeText: options.art311SpecialRegimeText,
|
|
14
|
+
mentions: options.mentions,
|
|
15
|
+
observations: options.observations,
|
|
16
|
+
};
|
|
17
|
+
const mapEvent = options.mapEvent ??
|
|
18
|
+
((event) => mapVoyantInvoiceToSmartbillAsync(event, mappingOptions));
|
|
19
|
+
const eventNames = {
|
|
20
|
+
issued: options.events?.issued ?? "invoice.issued",
|
|
21
|
+
proformaIssued: options.events?.proformaIssued ?? "invoice.proforma.issued",
|
|
22
|
+
proformaConverted: options.events?.proformaConverted ?? "invoice.proforma.converted",
|
|
23
|
+
voided: options.events?.voided ?? "invoice.voided",
|
|
24
|
+
syncRequested: options.events?.syncRequested ?? "invoice.external.sync.requested",
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
client,
|
|
28
|
+
logger,
|
|
29
|
+
mapEvent,
|
|
30
|
+
eventNames,
|
|
31
|
+
artifacts: {
|
|
32
|
+
db: options.artifacts?.db ?? options.db,
|
|
33
|
+
documentStorage: options.artifacts?.documentStorage ?? options.documentStorage,
|
|
34
|
+
documentStorageKeyPrefix: options.artifacts?.documentStorageKeyPrefix ?? options.documentStorageKeyPrefix,
|
|
35
|
+
},
|
|
36
|
+
idempotency: {
|
|
37
|
+
skipExistingExternalRef: options.idempotency?.skipExistingExternalRef ?? true,
|
|
38
|
+
},
|
|
39
|
+
onError: options.onError,
|
|
40
|
+
writeBackInvoiceNumber: options.writeBackInvoiceNumber,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { SmartbillClientOptions } from "./client.js";
|
|
2
|
+
export interface SmartbillInvoiceSettlementPollerOptions extends SmartbillClientOptions {
|
|
3
|
+
companyVatCode?: string;
|
|
4
|
+
seriesName?: string | ((context: SmartbillSettlementSeriesContext) => string | null | undefined | Promise<string | null | undefined>);
|
|
5
|
+
}
|
|
6
|
+
export interface SmartbillSettlementInvoice {
|
|
7
|
+
invoiceNumber: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SmartbillSettlementExternalRef {
|
|
10
|
+
externalId: string | null;
|
|
11
|
+
externalNumber: string | null;
|
|
12
|
+
metadata?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface SmartbillSettlementPollerContext {
|
|
15
|
+
invoice: SmartbillSettlementInvoice;
|
|
16
|
+
externalRef: SmartbillSettlementExternalRef;
|
|
17
|
+
}
|
|
18
|
+
export interface SmartbillSettlementSeriesContext extends SmartbillSettlementPollerContext {
|
|
19
|
+
metadata: Record<string, unknown> | null;
|
|
20
|
+
}
|
|
21
|
+
export interface SmartbillSettlementPollerResult {
|
|
22
|
+
externalId?: string | null;
|
|
23
|
+
externalNumber?: string | null;
|
|
24
|
+
status?: string | null;
|
|
25
|
+
paidAmountCents?: number | null;
|
|
26
|
+
unpaidAmountCents?: number | null;
|
|
27
|
+
settledAt?: string | null;
|
|
28
|
+
syncError?: string | null;
|
|
29
|
+
metadata?: Record<string, unknown> | null;
|
|
30
|
+
}
|
|
31
|
+
export type SmartbillInvoiceSettlementPoller = (context: SmartbillSettlementPollerContext) => Promise<SmartbillSettlementPollerResult>;
|
|
32
|
+
export declare function createSmartbillInvoiceSettlementPoller(options: SmartbillInvoiceSettlementPollerOptions): SmartbillInvoiceSettlementPoller;
|
|
33
|
+
//# sourceMappingURL=settlement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlement.d.ts","sourceRoot":"","sources":["../src/settlement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGzD,MAAM,WAAW,uCAAwC,SAAQ,sBAAsB;IACrF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EACP,MAAM,GACN,CAAC,CACC,OAAO,EAAE,gCAAgC,KACtC,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAA;CACzE;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,0BAA0B,CAAA;IACnC,WAAW,EAAE,8BAA8B,CAAA;CAC5C;AAED,MAAM,WAAW,gCAAiC,SAAQ,gCAAgC;IACxF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC1C;AAED,MAAM,MAAM,gCAAgC,GAAG,CAC7C,OAAO,EAAE,gCAAgC,KACtC,OAAO,CAAC,+BAA+B,CAAC,CAAA;AAyD7C,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,uCAAuC,GAC/C,gCAAgC,CA4ClC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createSmartbillClient } from "./client.js";
|
|
2
|
+
function coerceString(value) {
|
|
3
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
4
|
+
}
|
|
5
|
+
function coerceMetadata(value) {
|
|
6
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
7
|
+
? value
|
|
8
|
+
: null;
|
|
9
|
+
}
|
|
10
|
+
function resolveCompanyVatCode(metadata, options) {
|
|
11
|
+
return (coerceString(metadata?.companyVatCode) ??
|
|
12
|
+
coerceString(metadata?.vatCode) ??
|
|
13
|
+
options.companyVatCode ??
|
|
14
|
+
null);
|
|
15
|
+
}
|
|
16
|
+
async function resolveSeriesName(metadata, options, context) {
|
|
17
|
+
const optionSeriesName = typeof options.seriesName === "function"
|
|
18
|
+
? await options.seriesName({ ...context, metadata })
|
|
19
|
+
: options.seriesName;
|
|
20
|
+
return (coerceString(metadata?.seriesName) ?? coerceString(metadata?.series) ?? optionSeriesName ?? null);
|
|
21
|
+
}
|
|
22
|
+
function resolveInvoiceNumber(metadata, externalNumber, externalId, invoiceNumber) {
|
|
23
|
+
return (coerceString(metadata?.number) ??
|
|
24
|
+
coerceString(metadata?.invoiceNumber) ??
|
|
25
|
+
externalNumber ??
|
|
26
|
+
externalId ??
|
|
27
|
+
invoiceNumber);
|
|
28
|
+
}
|
|
29
|
+
function toCents(value) {
|
|
30
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.round(value * 100) : null;
|
|
31
|
+
}
|
|
32
|
+
export function createSmartbillInvoiceSettlementPoller(options) {
|
|
33
|
+
const client = createSmartbillClient(options);
|
|
34
|
+
return async ({ invoice, externalRef }) => {
|
|
35
|
+
const context = { invoice, externalRef };
|
|
36
|
+
const metadata = coerceMetadata(externalRef.metadata);
|
|
37
|
+
const companyVatCode = resolveCompanyVatCode(metadata, options);
|
|
38
|
+
const seriesName = await resolveSeriesName(metadata, options, context);
|
|
39
|
+
const number = resolveInvoiceNumber(metadata, externalRef.externalNumber, externalRef.externalId, invoice.invoiceNumber);
|
|
40
|
+
if (!companyVatCode) {
|
|
41
|
+
return { syncError: "SmartBill settlement polling requires companyVatCode" };
|
|
42
|
+
}
|
|
43
|
+
if (!seriesName) {
|
|
44
|
+
return { syncError: "SmartBill settlement polling requires seriesName" };
|
|
45
|
+
}
|
|
46
|
+
const status = await client.getPaymentStatus(companyVatCode, seriesName, number);
|
|
47
|
+
const paid = status.paid === true;
|
|
48
|
+
return {
|
|
49
|
+
externalId: externalRef.externalId ?? null,
|
|
50
|
+
externalNumber: number,
|
|
51
|
+
status: paid ? "paid" : "unpaid",
|
|
52
|
+
paidAmountCents: toCents(status.paidAmount),
|
|
53
|
+
unpaidAmountCents: toCents(status.unpaidAmount),
|
|
54
|
+
settledAt: paid && typeof status.paidAmount === "number" && status.paidAmount > 0
|
|
55
|
+
? new Date().toISOString()
|
|
56
|
+
: null,
|
|
57
|
+
syncError: status.errorText ? status.errorText : null,
|
|
58
|
+
metadata: {
|
|
59
|
+
...(metadata ?? {}),
|
|
60
|
+
companyVatCode,
|
|
61
|
+
seriesName,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SyncSmartbillInvoiceEventInput, SyncSmartbillInvoiceEventResult, SyncSmartbillInvoiceVoidEventInput, SyncSmartbillInvoiceVoidEventResult, SyncSmartbillProformaConversionInput, SyncSmartbillProformaConversionResult } from "./types.js";
|
|
2
|
+
export declare function syncSmartbillInvoiceEvent({ event, documentType, runtime, pluginOptions, operationLabel, }: SyncSmartbillInvoiceEventInput): Promise<SyncSmartbillInvoiceEventResult>;
|
|
3
|
+
export declare function syncSmartbillProformaConversion({ event, runtime, pluginOptions, }: SyncSmartbillProformaConversionInput): Promise<SyncSmartbillProformaConversionResult>;
|
|
4
|
+
export declare function syncSmartbillInvoiceVoidEvent({ event, runtime, pluginOptions, }: SyncSmartbillInvoiceVoidEventInput): Promise<SyncSmartbillInvoiceVoidEventResult>;
|
|
5
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/sync/events.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,8BAA8B,EAC9B,+BAA+B,EAC/B,kCAAkC,EAClC,mCAAmC,EACnC,oCAAoC,EACpC,qCAAqC,EACtC,MAAM,YAAY,CAAA;AAEnB,wBAAsB,yBAAyB,CAAC,EAC9C,KAAK,EACL,YAAY,EACZ,OAAO,EACP,aAAa,EACb,cAAiF,GAClF,EAAE,8BAA8B,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAyB3E;AAED,wBAAsB,+BAA+B,CAAC,EACpD,KAAK,EACL,OAAO,EACP,aAAa,GACd,EAAE,oCAAoC,GAAG,OAAO,CAAC,qCAAqC,CAAC,CAoDvF;AAED,wBAAsB,6BAA6B,CAAC,EAClD,KAAK,EACL,OAAO,EACP,aAAa,GACd,EAAE,kCAAkC,GAAG,OAAO,CAAC,mCAAmC,CAAC,CA8CnF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { applyExternalAllocationIfRequired, findExistingSmartbillRef, findProformaSmartbillRef, findSmartbillRefForCancellation, handleExistingSmartbillRef, persistArtifact, recordSmartbillCancellation, recordSyncError, resolveArtifactDb, resolveSmartbillCancellationTarget, writeBackInvoiceNumberIfRequired, } from "./helpers.js";
|
|
2
|
+
export async function syncSmartbillInvoiceEvent({ event, documentType, runtime, pluginOptions, operationLabel = documentType === "proforma" ? "createProforma" : "createInvoice", }) {
|
|
3
|
+
try {
|
|
4
|
+
const body = await runtime.mapEvent(event);
|
|
5
|
+
const existingRef = await findExistingSmartbillRef(event, documentType, body, runtime);
|
|
6
|
+
if (existingRef) {
|
|
7
|
+
return handleExistingSmartbillRef(event, documentType, body, existingRef, runtime);
|
|
8
|
+
}
|
|
9
|
+
const result = documentType === "proforma"
|
|
10
|
+
? await runtime.client.createProforma(body)
|
|
11
|
+
: await runtime.client.createInvoice(body);
|
|
12
|
+
runtime.logger.info?.(`[smartbill] ${documentType} created: ${result.series}-${result.number} for ${event.id}`, result);
|
|
13
|
+
const artifact = await persistArtifact(event, documentType, body, result, runtime);
|
|
14
|
+
await writeBackInvoiceNumberIfRequired(event, documentType, body, result, runtime);
|
|
15
|
+
await applyExternalAllocationIfRequired(event, documentType, body, result, runtime);
|
|
16
|
+
return { status: "created", invoiceId: event.id, documentType, result, artifact };
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
runtime.logger.error(`[smartbill] ${operationLabel} failed for ${event.id}`, err);
|
|
20
|
+
await recordSyncError(event, documentType, err, runtime, pluginOptions);
|
|
21
|
+
throw err;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function syncSmartbillProformaConversion({ event, runtime, pluginOptions, }) {
|
|
25
|
+
const proformaId = typeof event.proformaId === "string" ? event.proformaId : null;
|
|
26
|
+
const body = await runtime.mapEvent(event);
|
|
27
|
+
const existingRef = await findExistingSmartbillRef(event, "invoice", body, runtime);
|
|
28
|
+
if (existingRef) {
|
|
29
|
+
return handleExistingSmartbillRef(event, "invoice", body, existingRef, runtime);
|
|
30
|
+
}
|
|
31
|
+
if (!proformaId) {
|
|
32
|
+
return fallbackToSmartbillInvoiceCreate(event, runtime, pluginOptions, "missing proforma id");
|
|
33
|
+
}
|
|
34
|
+
const db = await resolveArtifactDb(event, "invoice", body, undefined, runtime, pluginOptions);
|
|
35
|
+
if (!db) {
|
|
36
|
+
return fallbackToSmartbillInvoiceCreate(event, runtime, pluginOptions, "missing artifact database");
|
|
37
|
+
}
|
|
38
|
+
const proformaRef = await findProformaSmartbillRef(db, proformaId);
|
|
39
|
+
if (!proformaRef) {
|
|
40
|
+
return fallbackToSmartbillInvoiceCreate(event, runtime, pluginOptions, `missing SmartBill proforma reference for ${proformaId}`);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const result = await runtime.client.convertEstimateToInvoice(body.companyVatCode, proformaRef.seriesName, proformaRef.number, body);
|
|
44
|
+
runtime.logger.info?.(`[smartbill] proforma converted: ${proformaRef.seriesName}-${proformaRef.number} -> ${result.series}-${result.number} for ${event.id}`, result);
|
|
45
|
+
const artifact = await persistArtifact(event, "invoice", body, result, runtime);
|
|
46
|
+
await writeBackInvoiceNumberIfRequired(event, "invoice", body, result, runtime);
|
|
47
|
+
await applyExternalAllocationIfRequired(event, "invoice", body, result, runtime);
|
|
48
|
+
return { status: "created", invoiceId: event.id, documentType: "invoice", result, artifact };
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
runtime.logger.error(`[smartbill] convertEstimateToInvoice failed for ${event.id}`, err);
|
|
52
|
+
await recordSyncError(event, "invoice", err, runtime, pluginOptions);
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function syncSmartbillInvoiceVoidEvent({ event, runtime, pluginOptions, }) {
|
|
57
|
+
const documentType = "invoice";
|
|
58
|
+
const db = await resolveArtifactDb(event, documentType, undefined, undefined, runtime, pluginOptions);
|
|
59
|
+
const externalRef = db ? await findSmartbillRefForCancellation(db, event.id) : null;
|
|
60
|
+
if (externalRef?.status === "cancelled") {
|
|
61
|
+
runtime.logger.info?.(`[smartbill] invoice already cancelled for ${event.id}`, externalRef);
|
|
62
|
+
return { status: "already_cancelled", invoiceId: event.id, externalRef };
|
|
63
|
+
}
|
|
64
|
+
const target = await resolveSmartbillCancellationTarget(event, externalRef, pluginOptions);
|
|
65
|
+
if (!target) {
|
|
66
|
+
runtime.logger.error(`[smartbill] cannot cancel invoice ${event.id}: missing external number`);
|
|
67
|
+
return { status: "missing_number", invoiceId: event.id };
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const result = await runtime.client.cancelInvoice(pluginOptions.companyVatCode, target.seriesName, target.number);
|
|
71
|
+
runtime.logger.info?.(`[smartbill] invoice cancelled: ${target.seriesName}-${target.number} for ${event.id}`, result);
|
|
72
|
+
await recordSmartbillCancellation(event, target, result, externalRef, runtime, pluginOptions);
|
|
73
|
+
return {
|
|
74
|
+
status: "cancelled",
|
|
75
|
+
invoiceId: event.id,
|
|
76
|
+
seriesName: target.seriesName,
|
|
77
|
+
number: target.number,
|
|
78
|
+
externalRef,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
runtime.logger.error(`[smartbill] cancelInvoice failed for ${event.id}`, err);
|
|
83
|
+
await recordSyncError(event, documentType, err, runtime, pluginOptions);
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function fallbackToSmartbillInvoiceCreate(event, runtime, pluginOptions, reason) {
|
|
88
|
+
runtime.logger.info?.(`[smartbill] cannot convert proforma for ${event.id}: ${reason}; falling back to createInvoice`);
|
|
89
|
+
return syncSmartbillInvoiceEvent({
|
|
90
|
+
event,
|
|
91
|
+
documentType: "invoice",
|
|
92
|
+
runtime,
|
|
93
|
+
pluginOptions,
|
|
94
|
+
operationLabel: `createInvoice fallback after proforma conversion (${reason})`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Invoice } from "@voyant-travel/finance";
|
|
2
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
3
|
+
import { type SmartbillDocumentType, type SmartbillExternalRef } from "../artifacts.js";
|
|
4
|
+
import type { SmartbillClientApi } from "../client.js";
|
|
5
|
+
import type { SmartbillMapFn, SmartbillPluginOptions } from "../plugin.js";
|
|
6
|
+
import type { SmartbillSyncRuntime } from "../runtime.js";
|
|
7
|
+
import type { SmartbillInvoiceBody, SmartbillInvoiceResponse, VoyantInvoiceEvent } from "../types.js";
|
|
8
|
+
import type { SyncSmartbillInvoiceEventResult } from "./types.js";
|
|
9
|
+
export declare function findProformaSmartbillRef(db: PostgresJsDatabase, proformaId: string): Promise<{
|
|
10
|
+
ref: {
|
|
11
|
+
id: string;
|
|
12
|
+
invoiceId: string;
|
|
13
|
+
provider: string;
|
|
14
|
+
externalId: string | null;
|
|
15
|
+
externalNumber: string | null;
|
|
16
|
+
externalUrl: string | null;
|
|
17
|
+
status: string | null;
|
|
18
|
+
metadata: unknown;
|
|
19
|
+
syncedAt: Date | null;
|
|
20
|
+
syncError: string | null;
|
|
21
|
+
createdAt: Date;
|
|
22
|
+
updatedAt: Date;
|
|
23
|
+
};
|
|
24
|
+
seriesName: string;
|
|
25
|
+
number: string;
|
|
26
|
+
} | null>;
|
|
27
|
+
export declare function findExistingSmartbillRef(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: SmartbillInvoiceBody, runtime: SmartbillSyncRuntime): Promise<SmartbillExternalRef | null>;
|
|
28
|
+
export declare function findSmartbillRefForCancellation(db: PostgresJsDatabase, invoiceId: string): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
invoiceId: string;
|
|
31
|
+
provider: string;
|
|
32
|
+
externalId: string | null;
|
|
33
|
+
externalNumber: string | null;
|
|
34
|
+
externalUrl: string | null;
|
|
35
|
+
status: string | null;
|
|
36
|
+
metadata: unknown;
|
|
37
|
+
syncedAt: Date | null;
|
|
38
|
+
syncError: string | null;
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
updatedAt: Date;
|
|
41
|
+
} | null>;
|
|
42
|
+
export declare function resolveSmartbillCancellationTarget(event: VoyantInvoiceEvent, externalRef: Awaited<ReturnType<typeof findSmartbillRefForCancellation>>, pluginOptions: Pick<SmartbillPluginOptions, "seriesName">): Promise<{
|
|
43
|
+
seriesName: string;
|
|
44
|
+
number: string;
|
|
45
|
+
} | null>;
|
|
46
|
+
export declare function recordSmartbillCancellation(event: VoyantInvoiceEvent, target: {
|
|
47
|
+
seriesName: string;
|
|
48
|
+
number: string;
|
|
49
|
+
}, result: Awaited<ReturnType<SmartbillClientApi["cancelInvoice"]>>, externalRef: Awaited<ReturnType<typeof findSmartbillRefForCancellation>>, runtime: SmartbillSyncRuntime, pluginOptions: Pick<SmartbillPluginOptions, "companyVatCode" | "seriesName">): Promise<void>;
|
|
50
|
+
export declare function handleExistingSmartbillRef(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: SmartbillInvoiceBody, externalRef: SmartbillExternalRef, runtime: SmartbillSyncRuntime): Promise<SyncSmartbillInvoiceEventResult>;
|
|
51
|
+
export declare function persistArtifact(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: Awaited<ReturnType<SmartbillMapFn>>, result: Awaited<ReturnType<SmartbillClientApi["createInvoice"]>>, runtime: SmartbillSyncRuntime): Promise<import("../artifacts.js").SmartbillArtifactPersistenceResult | null>;
|
|
52
|
+
export declare function applyExternalAllocationIfRequired(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: SmartbillInvoiceBody, result: SmartbillInvoiceResponse, runtime: SmartbillSyncRuntime): Promise<void>;
|
|
53
|
+
export declare function writeBackInvoiceNumberIfRequired(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: SmartbillInvoiceBody, result: SmartbillInvoiceResponse, runtime: SmartbillSyncRuntime): Promise<void>;
|
|
54
|
+
export declare function recordSyncError(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, err: unknown, runtime: SmartbillSyncRuntime, pluginOptions: Pick<SmartbillPluginOptions, "companyVatCode" | "seriesName">): Promise<void>;
|
|
55
|
+
export declare function resolveArtifactDb(event: VoyantInvoiceEvent, documentType: SmartbillDocumentType, body: SmartbillInvoiceBody | undefined, result: SmartbillInvoiceResponse | undefined, runtime: SmartbillSyncRuntime, pluginOptions?: Pick<SmartbillPluginOptions, "companyVatCode" | "seriesName">): Promise<PostgresJsDatabase<Record<string, never>> | null>;
|
|
56
|
+
export declare function withDefaultArtifactDb(pluginOptions: SmartbillPluginOptions, db: PostgresJsDatabase): SmartbillPluginOptions;
|
|
57
|
+
export declare function documentTypeForInvoice(invoice: Invoice): SmartbillDocumentType | null;
|
|
58
|
+
export declare function isMatchingSmartbillRef(ref: {
|
|
59
|
+
provider: string;
|
|
60
|
+
status?: string | null;
|
|
61
|
+
syncError?: string | null;
|
|
62
|
+
externalNumber?: string | null;
|
|
63
|
+
externalId?: string | null;
|
|
64
|
+
metadata?: unknown;
|
|
65
|
+
}, documentType: SmartbillDocumentType): boolean;
|
|
66
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/sync/helpers.ts"],"names":[],"mappings":"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"}
|