@voyantjs/plugin-smartbill 0.38.1 → 0.40.0
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/README.md +23 -2
- package/dist/artifacts.d.ts +20 -61
- package/dist/artifacts.d.ts.map +1 -1
- package/dist/artifacts.js +85 -11
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/mapping.d.ts +17 -3
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +87 -5
- package/dist/plugin.d.ts +14 -3
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +114 -10
- package/dist/runtime.d.ts +2 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +9 -2
- package/dist/settlement.d.ts +4 -1
- package/dist/settlement.d.ts.map +1 -1
- package/dist/settlement.js +7 -6
- package/dist/validation.d.ts +7 -2
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +20 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -27,8 +27,11 @@ const smartbillSync = smartbillPlugin({
|
|
|
27
27
|
username: env.SMARTBILL_USERNAME,
|
|
28
28
|
apiToken: env.SMARTBILL_API_TOKEN,
|
|
29
29
|
companyVatCode: "RO12345678",
|
|
30
|
-
seriesName: "A",
|
|
31
|
-
|
|
30
|
+
seriesName: (event) => (event.channel === "online" ? "WEB" : "A"),
|
|
31
|
+
mentions: async (event) => `Booking ${event.bookingCode ?? event.id}`,
|
|
32
|
+
observations: "Generated by Voyant",
|
|
33
|
+
art311SpecialRegimeText: "Custom Art. 311 disclosure",
|
|
34
|
+
// optional: language, art311SpecialRegime, events, mapEvent, logger, onError
|
|
32
35
|
artifacts: {
|
|
33
36
|
db: appDb,
|
|
34
37
|
documentStorage,
|
|
@@ -58,6 +61,24 @@ upload path defaults to `invoices/<invoiceId>/smartbill/...`; pass
|
|
|
58
61
|
`smartbill_pdf` attachments are reused so repeat event delivery does not upload
|
|
59
62
|
the same PDF again.
|
|
60
63
|
|
|
64
|
+
`seriesName`, `mentions`, and `observations` may be static strings or
|
|
65
|
+
event-specific callbacks. The packaged plugin awaits these callbacks in its
|
|
66
|
+
default mapper, so each invoice event can choose a SmartBill series or
|
|
67
|
+
compliance text based on document type, sales channel, or booking metadata.
|
|
68
|
+
|
|
69
|
+
When `artifacts.db` is configured, duplicate `invoice.issued` and
|
|
70
|
+
`invoice.proforma.issued` deliveries are idempotent by default: the plugin
|
|
71
|
+
checks for an existing non-error SmartBill external reference before creating a
|
|
72
|
+
new SmartBill document. Disable this with
|
|
73
|
+
`idempotency: { skipExistingExternalRef: false }` only when the caller owns
|
|
74
|
+
deduplication elsewhere. Create failures are recorded as SmartBill external refs
|
|
75
|
+
with `status: "error"` and `syncError`; `onError(event, error)` can be supplied
|
|
76
|
+
for application-specific reporting.
|
|
77
|
+
|
|
78
|
+
Use `retrySmartbillInvoiceArtifact({ runtime, client, externalRef, documentType
|
|
79
|
+
})` to re-download and re-attach a SmartBill PDF from an existing external ref
|
|
80
|
+
without issuing a new document.
|
|
81
|
+
|
|
61
82
|
## Exports
|
|
62
83
|
|
|
63
84
|
| Entry | Description |
|
package/dist/artifacts.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { financeService, type InvoiceExternalRef } from "@voyantjs/finance";
|
|
1
2
|
import type { StorageProvider } from "@voyantjs/storage";
|
|
2
3
|
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
3
4
|
import type { SmartbillClientApi } from "./client.js";
|
|
@@ -30,72 +31,30 @@ export interface PersistSmartbillInvoiceArtifactInput {
|
|
|
30
31
|
body: SmartbillInvoiceBody;
|
|
31
32
|
result: SmartbillInvoiceResponse;
|
|
32
33
|
}
|
|
33
|
-
export
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
export type SmartbillExternalRef = Pick<InvoiceExternalRef, "id" | "invoiceId" | "externalId" | "externalNumber" | "externalUrl" | "metadata">;
|
|
35
|
+
export interface RetrySmartbillInvoiceArtifactInput {
|
|
36
|
+
runtime: SmartbillArtifactPersistenceRuntime;
|
|
37
|
+
client: SmartbillClientApi;
|
|
38
|
+
externalRef: SmartbillExternalRef;
|
|
39
|
+
documentType: SmartbillDocumentType;
|
|
40
|
+
}
|
|
41
|
+
type InvoiceAttachmentRecord = Awaited<ReturnType<typeof financeService.createInvoiceAttachment>>;
|
|
42
|
+
type InvoiceRenditionRecord = Awaited<ReturnType<typeof financeService.createInvoiceRendition>>;
|
|
43
|
+
export type SmartbillArtifactPersistenceResult = {
|
|
39
44
|
status: "skipped";
|
|
40
|
-
reason: "missing_invoice";
|
|
41
|
-
attachment?: undefined;
|
|
42
|
-
rendition?: undefined;
|
|
43
|
-
} | {
|
|
44
|
-
status: "registered_ref";
|
|
45
|
-
reason?: undefined;
|
|
46
|
-
attachment?: undefined;
|
|
47
|
-
rendition?: undefined;
|
|
45
|
+
reason: "missing_db" | "missing_invoice" | "missing_document_storage" | "missing_smartbill_reference";
|
|
48
46
|
} | {
|
|
49
47
|
status: "registered_ref";
|
|
50
|
-
reason
|
|
51
|
-
attachment?: undefined;
|
|
52
|
-
rendition?: undefined;
|
|
48
|
+
reason?: "missing_number";
|
|
53
49
|
} | {
|
|
54
50
|
status: "already_exists";
|
|
55
|
-
attachment:
|
|
56
|
-
id: string;
|
|
57
|
-
invoiceId: string;
|
|
58
|
-
kind: string;
|
|
59
|
-
name: string;
|
|
60
|
-
mimeType: string | null;
|
|
61
|
-
fileSize: number | null;
|
|
62
|
-
storageKey: string | null;
|
|
63
|
-
checksum: string | null;
|
|
64
|
-
metadata: unknown;
|
|
65
|
-
createdAt: Date;
|
|
66
|
-
};
|
|
67
|
-
reason?: undefined;
|
|
68
|
-
rendition?: undefined;
|
|
51
|
+
attachment: InvoiceAttachmentRecord;
|
|
69
52
|
} | {
|
|
70
53
|
status: "persisted";
|
|
71
|
-
rendition:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
format: "json" | "pdf" | "html" | "xml";
|
|
78
|
-
errorMessage: string | null;
|
|
79
|
-
templateId: string | null;
|
|
80
|
-
language: string | null;
|
|
81
|
-
invoiceId: string;
|
|
82
|
-
storageKey: string | null;
|
|
83
|
-
fileSize: number | null;
|
|
84
|
-
checksum: string | null;
|
|
85
|
-
generatedAt: Date | null;
|
|
86
|
-
} | null;
|
|
87
|
-
attachment: {
|
|
88
|
-
metadata: unknown;
|
|
89
|
-
name: string;
|
|
90
|
-
id: string;
|
|
91
|
-
createdAt: Date;
|
|
92
|
-
kind: string;
|
|
93
|
-
invoiceId: string;
|
|
94
|
-
storageKey: string | null;
|
|
95
|
-
fileSize: number | null;
|
|
96
|
-
checksum: string | null;
|
|
97
|
-
mimeType: string | null;
|
|
98
|
-
} | null;
|
|
99
|
-
reason?: undefined;
|
|
100
|
-
}>;
|
|
54
|
+
rendition: InvoiceRenditionRecord;
|
|
55
|
+
attachment: InvoiceAttachmentRecord;
|
|
56
|
+
};
|
|
57
|
+
export declare function persistSmartbillInvoiceArtifact({ runtime, client, event, documentType, body, result, }: PersistSmartbillInvoiceArtifactInput): Promise<SmartbillArtifactPersistenceResult>;
|
|
58
|
+
export declare function retrySmartbillInvoiceArtifact({ runtime, client, externalRef, documentType, }: RetrySmartbillInvoiceArtifactInput): Promise<SmartbillArtifactPersistenceResult>;
|
|
59
|
+
export {};
|
|
101
60
|
//# sourceMappingURL=artifacts.d.ts.map
|
package/dist/artifacts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpG,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,UAAU,CAAA;AAE1D,MAAM,WAAW,+BAA+B;IAC9C,KAAK,EAAE,kBAAkB,CAAA;IACzB,YAAY,EAAE,qBAAqB,CAAA;IACnC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,MAAM,EAAE,wBAAwB,CAAA;CACjC;AAED,MAAM,MAAM,mBAAmB,GAC3B,kBAAkB,GAClB,CAAC,CACC,OAAO,EAAE,+BAA+B,KACrC,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,CAAA;AAExE,MAAM,MAAM,gCAAgC,GACxC,eAAe,GACf,IAAI,GACJ,CAAC,CACC,OAAO,EAAE,+BAA+B,KACrC,eAAe,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAA;AAElE,MAAM,MAAM,iCAAiC,GACzC,MAAM,GACN,CAAC,CAAC,OAAO,EAAE,+BAA+B,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;AAE5E,MAAM,WAAW,mCAAmC;IAClD,EAAE,CAAC,EAAE,mBAAmB,CAAA;IACxB,eAAe,CAAC,EAAE,gCAAgC,CAAA;IAClD,wBAAwB,CAAC,EAAE,iCAAiC,CAAA;CAC7D;AAED,MAAM,WAAW,mCAAmC;IAClD,EAAE,CAAC,EAAE,mBAAmB,CAAA;IACxB,eAAe,CAAC,EAAE,gCAAgC,CAAA;IAClD,wBAAwB,CAAC,EAAE,iCAAiC,CAAA;CAC7D;AAED,MAAM,WAAW,oCAAoC;IACnD,OAAO,EAAE,mCAAmC,CAAA;IAC5C,MAAM,EAAE,kBAAkB,CAAA;IAC1B,KAAK,EAAE,kBAAkB,CAAA;IACzB,YAAY,EAAE,qBAAqB,CAAA;IACnC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,MAAM,EAAE,wBAAwB,CAAA;CACjC;AAED,MAAM,MAAM,oBAAoB,GAAG,IAAI,CACrC,kBAAkB,EAClB,IAAI,GAAG,WAAW,GAAG,YAAY,GAAG,gBAAgB,GAAG,aAAa,GAAG,UAAU,CAClF,CAAA;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,EAAE,mCAAmC,CAAA;IAC5C,MAAM,EAAE,kBAAkB,CAAA;IAC1B,WAAW,EAAE,oBAAoB,CAAA;IACjC,YAAY,EAAE,qBAAqB,CAAA;CACpC;AAED,KAAK,uBAAuB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,uBAAuB,CAAC,CAAC,CAAA;AACjG,KAAK,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,sBAAsB,CAAC,CAAC,CAAA;AAE/F,MAAM,MAAM,kCAAkC,GAC1C;IACE,MAAM,EAAE,SAAS,CAAA;IACjB,MAAM,EACF,YAAY,GACZ,iBAAiB,GACjB,0BAA0B,GAC1B,6BAA6B,CAAA;CAClC,GACD;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,UAAU,EAAE,uBAAuB,CAAA;CAAE,GACjE;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,sBAAsB,CAAC;IAAC,UAAU,EAAE,uBAAuB,CAAA;CAAE,CAAA;AAmDnG,wBAAsB,+BAA+B,CAAC,EACpD,OAAO,EACP,MAAM,EACN,KAAK,EACL,YAAY,EACZ,IAAI,EACJ,MAAM,GACP,EAAE,oCAAoC,GAAG,OAAO,CAAC,kCAAkC,CAAC,CA6CpF;AAED,wBAAsB,6BAA6B,CAAC,EAClD,OAAO,EACP,MAAM,EACN,WAAW,EACX,YAAY,GACb,EAAE,kCAAkC,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAqDlF"}
|
package/dist/artifacts.js
CHANGED
|
@@ -23,6 +23,15 @@ async function sha256(bytes) {
|
|
|
23
23
|
function smartbillAttachmentName(documentType, seriesName, number) {
|
|
24
24
|
return `SmartBill ${documentType} ${seriesName}-${number}.pdf`;
|
|
25
25
|
}
|
|
26
|
+
function coerceMetadata(value) {
|
|
27
|
+
return value && typeof value === "object" && !Array.isArray(value)
|
|
28
|
+
? value
|
|
29
|
+
: null;
|
|
30
|
+
}
|
|
31
|
+
function metadataString(metadata, key) {
|
|
32
|
+
const value = metadata?.[key];
|
|
33
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
34
|
+
}
|
|
26
35
|
export async function persistSmartbillInvoiceArtifact({ runtime, client, event, documentType, body, result, }) {
|
|
27
36
|
if (!runtime.db)
|
|
28
37
|
return { status: "skipped", reason: "missing_db" };
|
|
@@ -55,17 +64,82 @@ export async function persistSmartbillInvoiceArtifact({ runtime, client, event,
|
|
|
55
64
|
return { status: "registered_ref" };
|
|
56
65
|
if (!number)
|
|
57
66
|
return { status: "registered_ref", reason: "missing_number" };
|
|
58
|
-
const
|
|
67
|
+
const keyPrefix = await resolveMaybe(runtime.documentStorageKeyPrefix, context);
|
|
68
|
+
return persistSmartbillPdfArtifact({
|
|
69
|
+
db,
|
|
70
|
+
storage,
|
|
71
|
+
client,
|
|
72
|
+
invoiceId: event.id,
|
|
73
|
+
documentType,
|
|
74
|
+
companyVatCode: body.companyVatCode,
|
|
75
|
+
seriesName,
|
|
76
|
+
number,
|
|
77
|
+
language: body.language ?? null,
|
|
78
|
+
keyPrefix,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export async function retrySmartbillInvoiceArtifact({ runtime, client, externalRef, documentType, }) {
|
|
82
|
+
if (!runtime.db)
|
|
83
|
+
return { status: "skipped", reason: "missing_db" };
|
|
84
|
+
const metadata = coerceMetadata(externalRef.metadata);
|
|
85
|
+
const companyVatCode = metadataString(metadata, "companyVatCode") ?? metadataString(metadata, "vatCode");
|
|
86
|
+
const seriesName = metadataString(metadata, "series") ?? metadataString(metadata, "seriesName");
|
|
87
|
+
const number = metadataString(metadata, "number") ??
|
|
88
|
+
externalRef.externalNumber ??
|
|
89
|
+
externalRef.externalId ??
|
|
90
|
+
null;
|
|
91
|
+
if (!companyVatCode || !seriesName || !number) {
|
|
92
|
+
return { status: "skipped", reason: "missing_smartbill_reference" };
|
|
93
|
+
}
|
|
94
|
+
const context = {
|
|
95
|
+
event: { id: externalRef.invoiceId },
|
|
96
|
+
documentType,
|
|
97
|
+
body: {
|
|
98
|
+
companyVatCode,
|
|
99
|
+
client: { name: "Client" },
|
|
100
|
+
seriesName,
|
|
101
|
+
currency: "RON",
|
|
102
|
+
language: metadataString(metadata, "language") ?? undefined,
|
|
103
|
+
products: [],
|
|
104
|
+
},
|
|
105
|
+
result: {
|
|
106
|
+
number,
|
|
107
|
+
series: seriesName,
|
|
108
|
+
url: externalRef.externalUrl ?? undefined,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const db = await resolveMaybe(runtime.db, context);
|
|
112
|
+
if (!db)
|
|
113
|
+
return { status: "skipped", reason: "missing_db" };
|
|
114
|
+
const storage = await resolveMaybe(runtime.documentStorage, context);
|
|
115
|
+
if (!storage)
|
|
116
|
+
return { status: "skipped", reason: "missing_document_storage" };
|
|
117
|
+
const keyPrefix = await resolveMaybe(runtime.documentStorageKeyPrefix, context);
|
|
118
|
+
return persistSmartbillPdfArtifact({
|
|
119
|
+
db,
|
|
120
|
+
storage,
|
|
121
|
+
client,
|
|
122
|
+
invoiceId: externalRef.invoiceId,
|
|
123
|
+
documentType,
|
|
124
|
+
companyVatCode,
|
|
125
|
+
seriesName,
|
|
126
|
+
number,
|
|
127
|
+
language: metadataString(metadata, "language"),
|
|
128
|
+
keyPrefix,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function persistSmartbillPdfArtifact({ db, storage, client, invoiceId, documentType, companyVatCode, seriesName, number, language, keyPrefix, }) {
|
|
132
|
+
const existingAttachments = await financeService.listInvoiceAttachments(db, invoiceId);
|
|
59
133
|
const existingSmartbillAttachment = existingAttachments.find((attachment) => attachment.kind === SMARTBILL_ATTACHMENT_KIND);
|
|
60
134
|
if (existingSmartbillAttachment) {
|
|
61
135
|
return { status: "already_exists", attachment: existingSmartbillAttachment };
|
|
62
136
|
}
|
|
63
137
|
const pdf = documentType === "proforma"
|
|
64
|
-
? await client.viewEstimatePdf(
|
|
65
|
-
: await client.viewInvoicePdf(
|
|
66
|
-
const defaultPrefix = `invoices/${
|
|
67
|
-
const
|
|
68
|
-
const key = `${
|
|
138
|
+
? await client.viewEstimatePdf(companyVatCode, seriesName, number)
|
|
139
|
+
: await client.viewInvoicePdf(companyVatCode, seriesName, number);
|
|
140
|
+
const defaultPrefix = `invoices/${invoiceId}/smartbill`;
|
|
141
|
+
const resolvedKeyPrefix = keyPrefix ?? defaultPrefix;
|
|
142
|
+
const key = `${resolvedKeyPrefix.replace(/\/$/, "")}/${documentType}-${sanitizeKeyPart(seriesName)}-${sanitizeKeyPart(number)}.pdf`;
|
|
69
143
|
const contentType = pdf.contentType || "application/pdf";
|
|
70
144
|
const checksum = await sha256(pdf.bytes);
|
|
71
145
|
const uploaded = await storage.upload(pdf.bytes, {
|
|
@@ -74,7 +148,7 @@ export async function persistSmartbillInvoiceArtifact({ runtime, client, event,
|
|
|
74
148
|
metadata: {
|
|
75
149
|
provider: "smartbill",
|
|
76
150
|
documentType,
|
|
77
|
-
invoiceId
|
|
151
|
+
invoiceId,
|
|
78
152
|
seriesName,
|
|
79
153
|
number,
|
|
80
154
|
},
|
|
@@ -82,23 +156,23 @@ export async function persistSmartbillInvoiceArtifact({ runtime, client, event,
|
|
|
82
156
|
const commonMetadata = {
|
|
83
157
|
provider: "smartbill",
|
|
84
158
|
documentType,
|
|
85
|
-
companyVatCode
|
|
159
|
+
companyVatCode,
|
|
86
160
|
seriesName,
|
|
87
161
|
number,
|
|
88
162
|
storageProvider: storage.name,
|
|
89
163
|
...(uploaded.url ? { url: uploaded.url } : {}),
|
|
90
164
|
};
|
|
91
|
-
const rendition = await financeService.createInvoiceRendition(db,
|
|
165
|
+
const rendition = await financeService.createInvoiceRendition(db, invoiceId, {
|
|
92
166
|
format: "pdf",
|
|
93
167
|
status: "ready",
|
|
94
168
|
storageKey: uploaded.key,
|
|
95
169
|
fileSize: pdf.bytes.byteLength,
|
|
96
170
|
checksum,
|
|
97
|
-
language:
|
|
171
|
+
language: language ?? null,
|
|
98
172
|
generatedAt: new Date().toISOString(),
|
|
99
173
|
metadata: commonMetadata,
|
|
100
174
|
});
|
|
101
|
-
const attachment = await financeService.createInvoiceAttachment(db,
|
|
175
|
+
const attachment = await financeService.createInvoiceAttachment(db, invoiceId, {
|
|
102
176
|
kind: SMARTBILL_ATTACHMENT_KIND,
|
|
103
177
|
name: smartbillAttachmentName(documentType, seriesName, number),
|
|
104
178
|
mimeType: contentType,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
export type { SmartbillArtifactPersistenceOptions, SmartbillArtifactStorageContext, SmartbillDbResolver, SmartbillDocumentStorageResolver, SmartbillDocumentType, SmartbillStorageKeyPrefixResolver, } from "./artifacts.js";
|
|
1
|
+
export type { RetrySmartbillInvoiceArtifactInput, SmartbillArtifactPersistenceOptions, SmartbillArtifactPersistenceResult, SmartbillArtifactPersistenceRuntime, SmartbillArtifactStorageContext, SmartbillDbResolver, SmartbillDocumentStorageResolver, SmartbillDocumentType, SmartbillExternalRef, SmartbillStorageKeyPrefixResolver, } from "./artifacts.js";
|
|
2
|
+
export { retrySmartbillInvoiceArtifact } from "./artifacts.js";
|
|
2
3
|
export type { SmartbillClientApi, SmartbillClientOptions } from "./client.js";
|
|
3
4
|
export { createSmartbillClient } from "./client.js";
|
|
4
|
-
export type { SmartbillMappingOptions } from "./mapping.js";
|
|
5
|
-
export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill } from "./mapping.js";
|
|
5
|
+
export type { SmartbillEventValue, SmartbillMappingOptions, SmartbillMaybePromise, } from "./mapping.js";
|
|
6
|
+
export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill, mapVoyantInvoiceToSmartbillAsync, } from "./mapping.js";
|
|
6
7
|
export type { SmartbillMockDocument, SmartbillMockDocumentKind, SmartbillMockDocumentStatus, SmartbillMockListenOptions, SmartbillMockRequest, SmartbillMockResponse, SmartbillMockSeries, SmartbillMockServer, SmartbillMockServerHandle, SmartbillMockServerOptions, SmartbillMockTax, } from "./mock.js";
|
|
7
8
|
export { createSmartbillMockServer } from "./mock.js";
|
|
8
|
-
export type { SmartbillLogger, SmartbillMapFn, SmartbillPluginOptions, SmartbillSyncEventNames, } from "./plugin.js";
|
|
9
|
+
export type { SmartbillErrorHandler, SmartbillIdempotencyOptions, SmartbillLogger, SmartbillMapFn, SmartbillPluginOptions, SmartbillSyncEventNames, } from "./plugin.js";
|
|
9
10
|
export { smartbillPlugin } from "./plugin.js";
|
|
10
11
|
export type { ResolvedSmartbillSyncEventNames, SmartbillSyncRuntime } from "./runtime.js";
|
|
11
12
|
export { createSmartbillSyncRuntime } from "./runtime.js";
|
|
12
|
-
export type { SmartbillInvoiceSettlementPoller, SmartbillInvoiceSettlementPollerOptions, SmartbillSettlementExternalRef, SmartbillSettlementInvoice, SmartbillSettlementPollerContext, SmartbillSettlementPollerResult, } from "./settlement.js";
|
|
13
|
+
export type { SmartbillInvoiceSettlementPoller, SmartbillInvoiceSettlementPollerOptions, SmartbillSettlementExternalRef, SmartbillSettlementInvoice, SmartbillSettlementPollerContext, SmartbillSettlementPollerResult, SmartbillSettlementSeriesContext, } from "./settlement.js";
|
|
13
14
|
export { createSmartbillInvoiceSettlementPoller } from "./settlement.js";
|
|
14
15
|
export type { SmartbillClient, SmartbillEnvelope, SmartbillEstimateInvoicesResponse, SmartbillFetch, SmartbillInvoiceBody, SmartbillInvoiceResponse, SmartbillPaymentEntry, SmartbillPdfResponse, SmartbillProduct, SmartbillSeriesResponse, SmartbillStatusResponse, SmartbillTaxesResponse, VoyantInvoiceEvent, } from "./types.js";
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mCAAmC,EACnC,+BAA+B,EAC/B,mBAAmB,EACnB,gCAAgC,EAChC,qBAAqB,EACrB,iCAAiC,GAClC,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kCAAkC,EAClC,mCAAmC,EACnC,kCAAkC,EAClC,mCAAmC,EACnC,+BAA+B,EAC/B,mBAAmB,EACnB,gCAAgC,EAChC,qBAAqB,EACrB,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAA;AAC9D,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,SAAS,EACT,YAAY,EACZ,2BAA2B,EAC3B,gCAAgC,GACjC,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,EAC1B,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAA;AACrD,YAAY,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,YAAY,EAAE,+BAA+B,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,YAAY,EACV,gCAAgC,EAChC,uCAAuC,EACvC,8BAA8B,EAC9B,0BAA0B,EAC1B,gCAAgC,EAChC,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,sCAAsC,EAAE,MAAM,iBAAiB,CAAA;AACxE,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,iCAAiC,EACjC,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export { retrySmartbillInvoiceArtifact } from "./artifacts.js";
|
|
1
2
|
export { createSmartbillClient } from "./client.js";
|
|
2
|
-
export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill } from "./mapping.js";
|
|
3
|
+
export { mapClient, mapLineItems, mapVoyantInvoiceToSmartbill, mapVoyantInvoiceToSmartbillAsync, } from "./mapping.js";
|
|
3
4
|
export { createSmartbillMockServer } from "./mock.js";
|
|
4
5
|
export { smartbillPlugin } from "./plugin.js";
|
|
5
6
|
export { createSmartbillSyncRuntime } from "./runtime.js";
|
package/dist/mapping.d.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import type { SmartbillClient, SmartbillInvoiceBody, SmartbillProduct, VoyantInvoiceEvent } from "./types.js";
|
|
2
|
+
export type SmartbillMaybePromise<T> = T | Promise<T>;
|
|
3
|
+
export type SmartbillEventValue<T> = T | ((event: VoyantInvoiceEvent) => SmartbillMaybePromise<T>);
|
|
2
4
|
/**
|
|
3
5
|
* Options for the default invoice mapper.
|
|
4
6
|
*/
|
|
5
7
|
export interface SmartbillMappingOptions {
|
|
6
8
|
/** Romanian company VAT code (e.g. `"RO12345678"`). */
|
|
7
9
|
companyVatCode: string;
|
|
8
|
-
/** SmartBill invoice series name (e.g. `"A"`). */
|
|
9
|
-
seriesName: string
|
|
10
|
+
/** SmartBill invoice series name (e.g. `"A"`), or an event-specific resolver. */
|
|
11
|
+
seriesName: SmartbillEventValue<string>;
|
|
10
12
|
/** Invoice language. Defaults to `"RO"`. */
|
|
11
13
|
language?: string;
|
|
12
14
|
/** Whether VAT is included in line item prices. Defaults to `true`. */
|
|
13
15
|
isTaxIncluded?: boolean;
|
|
14
16
|
/** Whether to use Art. 311 special regime (margin scheme for travel). */
|
|
15
17
|
art311SpecialRegime?: boolean;
|
|
18
|
+
/** Text appended to mentions when Art. 311 special regime is enabled. */
|
|
19
|
+
art311SpecialRegimeText?: string;
|
|
20
|
+
/** SmartBill mentions override, or an event-specific resolver. Defaults to event.mentions. */
|
|
21
|
+
mentions?: SmartbillEventValue<string | null | undefined>;
|
|
22
|
+
/** SmartBill observations override, or an event-specific resolver. Defaults to event.observations. */
|
|
23
|
+
observations?: SmartbillEventValue<string | null | undefined>;
|
|
16
24
|
}
|
|
17
25
|
/**
|
|
18
26
|
* Extract the SmartBill client block from a Voyant invoice event.
|
|
@@ -24,9 +32,15 @@ export declare function mapClient(event: VoyantInvoiceEvent): SmartbillClient;
|
|
|
24
32
|
* Expects `event.lineItems` to be an array of objects with at minimum
|
|
25
33
|
* `description`/`name`, `quantity`, `unitPrice`, `currency`.
|
|
26
34
|
*/
|
|
27
|
-
export declare function mapLineItems(event: VoyantInvoiceEvent, options: SmartbillMappingOptions): SmartbillProduct[];
|
|
35
|
+
export declare function mapLineItems(event: VoyantInvoiceEvent, options: Pick<SmartbillMappingOptions, "isTaxIncluded">): SmartbillProduct[];
|
|
28
36
|
/**
|
|
29
37
|
* Map a full Voyant invoice event to a SmartBill invoice body.
|
|
30
38
|
*/
|
|
31
39
|
export declare function mapVoyantInvoiceToSmartbill(event: VoyantInvoiceEvent, options: SmartbillMappingOptions): SmartbillInvoiceBody;
|
|
40
|
+
/**
|
|
41
|
+
* Async variant of the default mapper. Use this when mapping options include
|
|
42
|
+
* promise-returning callbacks such as `seriesName`, `mentions`, or
|
|
43
|
+
* `observations`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mapVoyantInvoiceToSmartbillAsync(event: VoyantInvoiceEvent, options: SmartbillMappingOptions): Promise<SmartbillInvoiceBody>;
|
|
32
46
|
//# sourceMappingURL=mapping.d.ts.map
|
package/dist/mapping.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAA;IACtB,
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;AAErD,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,kBAAkB,KAAK,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAA;AAKlG;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,cAAc,EAAE,MAAM,CAAA;IACtB,iFAAiF;IACjF,UAAU,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAA;IACvC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,yEAAyE;IACzE,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,mBAAmB,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACzD,sGAAsG;IACtG,YAAY,CAAC,EAAE,mBAAmB,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CAC9D;AAeD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,GAAG,eAAe,CAapE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,eAAe,CAAC,GACtD,gBAAgB,EAAE,CAiBpB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,uBAAuB,GAC/B,oBAAoB,CAEtB;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CACpD,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAE/B"}
|
package/dist/mapping.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const DEFAULT_ART311_SPECIAL_REGIME_TEXT = "Regimul special de taxare - agentie de turism (Art. 311 Cod Fiscal)";
|
|
1
2
|
/**
|
|
2
3
|
* Extract the SmartBill client block from a Voyant invoice event.
|
|
3
4
|
* Falls back to empty strings for missing fields.
|
|
@@ -43,6 +44,17 @@ export function mapLineItems(event, options) {
|
|
|
43
44
|
* Map a full Voyant invoice event to a SmartBill invoice body.
|
|
44
45
|
*/
|
|
45
46
|
export function mapVoyantInvoiceToSmartbill(event, options) {
|
|
47
|
+
return buildSmartbillInvoiceBody(event, resolveMappingOptionsSync(event, options));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Async variant of the default mapper. Use this when mapping options include
|
|
51
|
+
* promise-returning callbacks such as `seriesName`, `mentions`, or
|
|
52
|
+
* `observations`.
|
|
53
|
+
*/
|
|
54
|
+
export async function mapVoyantInvoiceToSmartbillAsync(event, options) {
|
|
55
|
+
return buildSmartbillInvoiceBody(event, await resolveMappingOptions(event, options));
|
|
56
|
+
}
|
|
57
|
+
function buildSmartbillInvoiceBody(event, options) {
|
|
46
58
|
const body = {
|
|
47
59
|
companyVatCode: options.companyVatCode,
|
|
48
60
|
client: mapClient(event),
|
|
@@ -59,14 +71,20 @@ export function mapVoyantInvoiceToSmartbill(event, options) {
|
|
|
59
71
|
body.issueDate = event.issueDate;
|
|
60
72
|
if (typeof event.deliveryDate === "string")
|
|
61
73
|
body.deliveryDate = event.deliveryDate;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
const mentions = options.hasMentionsOverride
|
|
75
|
+
? options.mentions
|
|
76
|
+
: asStringOrUndefined(event.mentions);
|
|
77
|
+
if (mentions)
|
|
78
|
+
body.mentions = mentions;
|
|
79
|
+
const observations = options.hasObservationsOverride
|
|
80
|
+
? options.observations
|
|
81
|
+
: asStringOrUndefined(event.observations);
|
|
82
|
+
if (observations)
|
|
83
|
+
body.observations = observations;
|
|
66
84
|
if (options.art311SpecialRegime) {
|
|
67
85
|
body.mentions = [
|
|
68
86
|
body.mentions,
|
|
69
|
-
|
|
87
|
+
options.art311SpecialRegimeText ?? DEFAULT_ART311_SPECIAL_REGIME_TEXT,
|
|
70
88
|
]
|
|
71
89
|
.filter(Boolean)
|
|
72
90
|
.join("\n");
|
|
@@ -74,6 +92,70 @@ export function mapVoyantInvoiceToSmartbill(event, options) {
|
|
|
74
92
|
return body;
|
|
75
93
|
}
|
|
76
94
|
// --- helpers ---
|
|
95
|
+
function resolveMappingOptionsSync(event, options) {
|
|
96
|
+
return {
|
|
97
|
+
companyVatCode: options.companyVatCode,
|
|
98
|
+
seriesName: resolveRequiredEventValueSync(event, options.seriesName, "seriesName"),
|
|
99
|
+
language: options.language,
|
|
100
|
+
isTaxIncluded: options.isTaxIncluded,
|
|
101
|
+
art311SpecialRegime: options.art311SpecialRegime,
|
|
102
|
+
art311SpecialRegimeText: options.art311SpecialRegimeText,
|
|
103
|
+
mentions: normalizeOptionalText(resolveEventValueSync(event, options.mentions, "mentions")),
|
|
104
|
+
observations: normalizeOptionalText(resolveEventValueSync(event, options.observations, "observations")),
|
|
105
|
+
hasMentionsOverride: options.mentions !== undefined,
|
|
106
|
+
hasObservationsOverride: options.observations !== undefined,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
async function resolveMappingOptions(event, options) {
|
|
110
|
+
return {
|
|
111
|
+
companyVatCode: options.companyVatCode,
|
|
112
|
+
seriesName: await resolveRequiredEventValue(event, options.seriesName, "seriesName"),
|
|
113
|
+
language: options.language,
|
|
114
|
+
isTaxIncluded: options.isTaxIncluded,
|
|
115
|
+
art311SpecialRegime: options.art311SpecialRegime,
|
|
116
|
+
art311SpecialRegimeText: options.art311SpecialRegimeText,
|
|
117
|
+
mentions: normalizeOptionalText(await resolveEventValue(event, options.mentions)),
|
|
118
|
+
observations: normalizeOptionalText(await resolveEventValue(event, options.observations)),
|
|
119
|
+
hasMentionsOverride: options.mentions !== undefined,
|
|
120
|
+
hasObservationsOverride: options.observations !== undefined,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function resolveEventValueSync(event, value, field) {
|
|
124
|
+
const resolved = typeof value === "function"
|
|
125
|
+
? value(event)
|
|
126
|
+
: value;
|
|
127
|
+
if (isPromiseLike(resolved)) {
|
|
128
|
+
throw new Error(`SmartBill mapping option "${field}" returned a Promise; use mapVoyantInvoiceToSmartbillAsync`);
|
|
129
|
+
}
|
|
130
|
+
return resolved;
|
|
131
|
+
}
|
|
132
|
+
function resolveRequiredEventValueSync(event, value, field) {
|
|
133
|
+
const resolved = resolveEventValueSync(event, value, field);
|
|
134
|
+
if (resolved === undefined || resolved === null) {
|
|
135
|
+
throw new Error(`SmartBill mapping option "${field}" is required`);
|
|
136
|
+
}
|
|
137
|
+
return resolved;
|
|
138
|
+
}
|
|
139
|
+
async function resolveEventValue(event, value) {
|
|
140
|
+
return typeof value === "function"
|
|
141
|
+
? await value(event)
|
|
142
|
+
: value;
|
|
143
|
+
}
|
|
144
|
+
async function resolveRequiredEventValue(event, value, field) {
|
|
145
|
+
const resolved = await resolveEventValue(event, value);
|
|
146
|
+
if (resolved === undefined || resolved === null) {
|
|
147
|
+
throw new Error(`SmartBill mapping option "${field}" is required`);
|
|
148
|
+
}
|
|
149
|
+
return resolved;
|
|
150
|
+
}
|
|
151
|
+
function isPromiseLike(value) {
|
|
152
|
+
return (value != null &&
|
|
153
|
+
typeof value === "object" &&
|
|
154
|
+
typeof value.then === "function");
|
|
155
|
+
}
|
|
156
|
+
function normalizeOptionalText(value) {
|
|
157
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
158
|
+
}
|
|
77
159
|
function asString(value, fallback) {
|
|
78
160
|
if (typeof value === "string" && value.length > 0)
|
|
79
161
|
return value;
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Plugin } from "@voyantjs/core";
|
|
2
2
|
import { type SmartbillArtifactPersistenceOptions } from "./artifacts.js";
|
|
3
3
|
import type { SmartbillClientOptions } from "./client.js";
|
|
4
|
-
import type {
|
|
5
|
-
import type { VoyantInvoiceEvent } from "./types.js";
|
|
4
|
+
import type { SmartbillMappingOptions } from "./mapping.js";
|
|
5
|
+
import type { SmartbillInvoiceBody, VoyantInvoiceEvent } from "./types.js";
|
|
6
6
|
export interface SmartbillSyncEventNames {
|
|
7
7
|
issued?: string;
|
|
8
8
|
proformaIssued?: string;
|
|
@@ -13,11 +13,22 @@ export interface SmartbillLogger {
|
|
|
13
13
|
error: (message: string, meta?: unknown) => void;
|
|
14
14
|
info?: (message: string, meta?: unknown) => void;
|
|
15
15
|
}
|
|
16
|
-
export type SmartbillMapFn = (event: VoyantInvoiceEvent) =>
|
|
16
|
+
export type SmartbillMapFn = (event: VoyantInvoiceEvent) => SmartbillInvoiceBody | Promise<SmartbillInvoiceBody>;
|
|
17
|
+
export interface SmartbillIdempotencyOptions {
|
|
18
|
+
/**
|
|
19
|
+
* When artifact DB access is configured, skip SmartBill create calls for
|
|
20
|
+
* duplicate invoice events that already have a non-error SmartBill ref.
|
|
21
|
+
* Defaults to true.
|
|
22
|
+
*/
|
|
23
|
+
skipExistingExternalRef?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type SmartbillErrorHandler = (event: VoyantInvoiceEvent, error: unknown) => void | Promise<void>;
|
|
17
26
|
export interface SmartbillPluginOptions extends SmartbillClientOptions, SmartbillMappingOptions {
|
|
18
27
|
events?: SmartbillSyncEventNames;
|
|
19
28
|
mapEvent?: SmartbillMapFn;
|
|
20
29
|
logger?: SmartbillLogger;
|
|
30
|
+
idempotency?: SmartbillIdempotencyOptions;
|
|
31
|
+
onError?: SmartbillErrorHandler;
|
|
21
32
|
/**
|
|
22
33
|
* Optional finance artifact persistence. When `db` is supplied, the plugin
|
|
23
34
|
* registers the SmartBill external ref after creation. When
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,gBAAgB,CAAA;AAIxD,OAAO,EAGL,KAAK,mCAAmC,EAIzC,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAA;AAE3D,OAAO,KAAK,EAAE,oBAAoB,EAA4B,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAGpG,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAChD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACjD;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,kBAAkB,KACtB,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAEzD,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EAAE,kBAAkB,EACzB,KAAK,EAAE,OAAO,KACX,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAEzB,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB,EAAE,uBAAuB;IAC7F,MAAM,CAAC,EAAE,uBAAuB,CAAA;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,WAAW,CAAC,EAAE,2BAA2B,CAAA;IACzC,OAAO,CAAC,EAAE,qBAAqB,CAAA;IAC/B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,mCAAmC,CAAA;IAC/C,sCAAsC;IACtC,EAAE,CAAC,EAAE,mCAAmC,CAAC,IAAI,CAAC,CAAA;IAC9C,mDAAmD;IACnD,eAAe,CAAC,EAAE,mCAAmC,CAAC,iBAAiB,CAAC,CAAA;IACxE,4DAA4D;IAC5D,wBAAwB,CAAC,EAAE,mCAAmC,CAAC,0BAA0B,CAAC,CAAA;CAC3F;AAYD,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CA6QvE"}
|
package/dist/plugin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { financeService } from "@voyantjs/finance";
|
|
1
2
|
import { ZodError } from "zod";
|
|
2
|
-
import { persistSmartbillInvoiceArtifact, } from "./artifacts.js";
|
|
3
|
+
import { persistSmartbillInvoiceArtifact, retrySmartbillInvoiceArtifact, } from "./artifacts.js";
|
|
3
4
|
import { createSmartbillSyncRuntime } from "./runtime.js";
|
|
4
5
|
import { smartbillPluginOptionsSchema } from "./validation.js";
|
|
5
6
|
function coerceEvent(data) {
|
|
@@ -15,7 +16,55 @@ function coerceEvent(data) {
|
|
|
15
16
|
}
|
|
16
17
|
export function smartbillPlugin(options) {
|
|
17
18
|
const validatedOptions = parseSmartbillPluginOptions(options);
|
|
18
|
-
const { client, logger, mapEvent, eventNames, artifacts } = createSmartbillSyncRuntime(validatedOptions);
|
|
19
|
+
const { client, logger, mapEvent, eventNames, artifacts, idempotency, onError } = createSmartbillSyncRuntime(validatedOptions);
|
|
20
|
+
async function resolveMaybe(value, context) {
|
|
21
|
+
return typeof value === "function"
|
|
22
|
+
? await value(context)
|
|
23
|
+
: value;
|
|
24
|
+
}
|
|
25
|
+
async function resolveArtifactDb(event, documentType, body, result) {
|
|
26
|
+
if (!artifacts.db)
|
|
27
|
+
return null;
|
|
28
|
+
const context = {
|
|
29
|
+
event,
|
|
30
|
+
documentType,
|
|
31
|
+
body: body ?? {
|
|
32
|
+
companyVatCode: validatedOptions.companyVatCode,
|
|
33
|
+
client: { name: "Client" },
|
|
34
|
+
seriesName: "unknown",
|
|
35
|
+
currency: "RON",
|
|
36
|
+
products: [],
|
|
37
|
+
},
|
|
38
|
+
result: result ?? {},
|
|
39
|
+
};
|
|
40
|
+
return (await resolveMaybe(artifacts.db, context)) ?? null;
|
|
41
|
+
}
|
|
42
|
+
async function findExistingSmartbillRef(event, documentType, body) {
|
|
43
|
+
if (idempotency.skipExistingExternalRef === false)
|
|
44
|
+
return null;
|
|
45
|
+
const db = await resolveArtifactDb(event, documentType, body);
|
|
46
|
+
if (!db)
|
|
47
|
+
return null;
|
|
48
|
+
const refs = await financeService.listInvoiceExternalRefs(db, event.id);
|
|
49
|
+
return refs.find((ref) => isUsableSmartbillRef(ref)) ?? null;
|
|
50
|
+
}
|
|
51
|
+
async function handleExistingSmartbillRef(event, documentType, externalRef) {
|
|
52
|
+
logger.info?.(`[smartbill] ${documentType} already has SmartBill ref for ${event.id}; skipping create`, externalRef);
|
|
53
|
+
try {
|
|
54
|
+
const persisted = await retrySmartbillInvoiceArtifact({
|
|
55
|
+
runtime: artifacts,
|
|
56
|
+
client,
|
|
57
|
+
externalRef,
|
|
58
|
+
documentType,
|
|
59
|
+
});
|
|
60
|
+
if (persisted.status === "persisted") {
|
|
61
|
+
logger.info?.(`[smartbill] ${documentType} PDF re-attached for ${event.id}`, persisted);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger.error(`[smartbill] artifact re-attach failed for ${event.id}`, err);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
19
68
|
async function persistArtifact(event, documentType, body, result) {
|
|
20
69
|
try {
|
|
21
70
|
const persisted = await persistSmartbillInvoiceArtifact({
|
|
@@ -34,6 +83,44 @@ export function smartbillPlugin(options) {
|
|
|
34
83
|
logger.error(`[smartbill] artifact persistence failed for ${event.id}`, err);
|
|
35
84
|
}
|
|
36
85
|
}
|
|
86
|
+
async function recordSyncError(event, documentType, err) {
|
|
87
|
+
try {
|
|
88
|
+
await onError?.(event, err);
|
|
89
|
+
}
|
|
90
|
+
catch (handlerError) {
|
|
91
|
+
logger.error(`[smartbill] onError handler failed for ${event.id}`, handlerError);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const db = await resolveArtifactDb(event, documentType);
|
|
95
|
+
if (!db)
|
|
96
|
+
return;
|
|
97
|
+
const refs = await financeService.listInvoiceExternalRefs(db, event.id);
|
|
98
|
+
if (refs.some((ref) => isUsableSmartbillRef(ref)))
|
|
99
|
+
return;
|
|
100
|
+
await financeService.registerInvoiceExternalRef(db, event.id, {
|
|
101
|
+
provider: "smartbill",
|
|
102
|
+
externalId: null,
|
|
103
|
+
externalNumber: null,
|
|
104
|
+
externalUrl: null,
|
|
105
|
+
status: "error",
|
|
106
|
+
syncedAt: new Date().toISOString(),
|
|
107
|
+
syncError: errorMessage(err),
|
|
108
|
+
metadata: { documentType },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (recordError) {
|
|
112
|
+
logger.error(`[smartbill] error external-ref recording failed for ${event.id}`, recordError);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function resolveConfiguredSeriesName(event) {
|
|
116
|
+
const value = validatedOptions.seriesName;
|
|
117
|
+
return typeof value === "function" ? await value(event) : value;
|
|
118
|
+
}
|
|
119
|
+
async function resolveExternalSeriesName(event) {
|
|
120
|
+
return typeof event.externalSeriesName === "string"
|
|
121
|
+
? event.externalSeriesName
|
|
122
|
+
: await resolveConfiguredSeriesName(event);
|
|
123
|
+
}
|
|
37
124
|
const subscribers = [
|
|
38
125
|
{
|
|
39
126
|
event: eventNames.issued,
|
|
@@ -42,13 +129,19 @@ export function smartbillPlugin(options) {
|
|
|
42
129
|
if (!event)
|
|
43
130
|
return;
|
|
44
131
|
try {
|
|
45
|
-
const body = mapEvent(event);
|
|
132
|
+
const body = await mapEvent(event);
|
|
133
|
+
const existingRef = await findExistingSmartbillRef(event, "invoice", body);
|
|
134
|
+
if (existingRef) {
|
|
135
|
+
await handleExistingSmartbillRef(event, "invoice", existingRef);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
46
138
|
const result = await client.createInvoice(body);
|
|
47
139
|
logger.info?.(`[smartbill] invoice created: ${result.series}-${result.number} for ${event.id}`, result);
|
|
48
140
|
await persistArtifact(event, "invoice", body, result);
|
|
49
141
|
}
|
|
50
142
|
catch (err) {
|
|
51
143
|
logger.error(`[smartbill] createInvoice on "${eventNames.issued}" failed for ${event.id}`, err);
|
|
144
|
+
await recordSyncError(event, "invoice", err);
|
|
52
145
|
}
|
|
53
146
|
},
|
|
54
147
|
},
|
|
@@ -61,13 +154,19 @@ export function smartbillPlugin(options) {
|
|
|
61
154
|
try {
|
|
62
155
|
// Same shape as createInvoice — SmartBill's `/proforma`
|
|
63
156
|
// endpoint accepts the same body as `/invoice`.
|
|
64
|
-
const body = mapEvent(event);
|
|
157
|
+
const body = await mapEvent(event);
|
|
158
|
+
const existingRef = await findExistingSmartbillRef(event, "proforma", body);
|
|
159
|
+
if (existingRef) {
|
|
160
|
+
await handleExistingSmartbillRef(event, "proforma", existingRef);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
65
163
|
const result = await client.createProforma(body);
|
|
66
164
|
logger.info?.(`[smartbill] proforma created: ${result.series}-${result.number} for ${event.id}`, result);
|
|
67
165
|
await persistArtifact(event, "proforma", body, result);
|
|
68
166
|
}
|
|
69
167
|
catch (err) {
|
|
70
168
|
logger.error(`[smartbill] createProforma on "${eventNames.proformaIssued}" failed for ${event.id}`, err);
|
|
169
|
+
await recordSyncError(event, "proforma", err);
|
|
71
170
|
}
|
|
72
171
|
},
|
|
73
172
|
},
|
|
@@ -78,9 +177,7 @@ export function smartbillPlugin(options) {
|
|
|
78
177
|
if (!event)
|
|
79
178
|
return;
|
|
80
179
|
try {
|
|
81
|
-
const seriesName =
|
|
82
|
-
? event.externalSeriesName
|
|
83
|
-
: validatedOptions.seriesName;
|
|
180
|
+
const seriesName = await resolveExternalSeriesName(event);
|
|
84
181
|
const number = typeof event.externalNumber === "string"
|
|
85
182
|
? event.externalNumber
|
|
86
183
|
: typeof event.invoiceNumber === "string"
|
|
@@ -105,9 +202,7 @@ export function smartbillPlugin(options) {
|
|
|
105
202
|
if (!event)
|
|
106
203
|
return;
|
|
107
204
|
try {
|
|
108
|
-
const seriesName =
|
|
109
|
-
? event.externalSeriesName
|
|
110
|
-
: validatedOptions.seriesName;
|
|
205
|
+
const seriesName = await resolveExternalSeriesName(event);
|
|
111
206
|
const number = typeof event.externalNumber === "string"
|
|
112
207
|
? event.externalNumber
|
|
113
208
|
: typeof event.invoiceNumber === "string"
|
|
@@ -137,6 +232,15 @@ export function smartbillPlugin(options) {
|
|
|
137
232
|
subscribers,
|
|
138
233
|
};
|
|
139
234
|
}
|
|
235
|
+
function errorMessage(error) {
|
|
236
|
+
return error instanceof Error ? error.message : String(error);
|
|
237
|
+
}
|
|
238
|
+
function isUsableSmartbillRef(ref) {
|
|
239
|
+
return (ref.provider === "smartbill" &&
|
|
240
|
+
ref.status !== "error" &&
|
|
241
|
+
!ref.syncError &&
|
|
242
|
+
Boolean(ref.externalNumber || ref.externalId));
|
|
243
|
+
}
|
|
140
244
|
function parseSmartbillPluginOptions(options) {
|
|
141
245
|
try {
|
|
142
246
|
return smartbillPluginOptionsSchema.parse(options);
|
package/dist/runtime.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface SmartbillSyncRuntime {
|
|
|
13
13
|
mapEvent: SmartbillMapFn;
|
|
14
14
|
eventNames: ResolvedSmartbillSyncEventNames;
|
|
15
15
|
artifacts: SmartbillArtifactPersistenceOptions;
|
|
16
|
+
idempotency: NonNullable<SmartbillPluginOptions["idempotency"]>;
|
|
17
|
+
onError: SmartbillPluginOptions["onError"];
|
|
16
18
|
}
|
|
17
19
|
export declare function createSmartbillSyncRuntime(options: SmartbillPluginOptions): SmartbillSyncRuntime;
|
|
18
20
|
//# sourceMappingURL=runtime.d.ts.map
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +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,MAAM,aAAa,CAAA;AAEnD,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,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;
|
|
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,MAAM,aAAa,CAAA;AAEnD,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,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;CAC3C;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,sBAAsB,GAAG,oBAAoB,CAuChG"}
|
package/dist/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSmartbillClient } from "./client.js";
|
|
2
|
-
import {
|
|
2
|
+
import { mapVoyantInvoiceToSmartbillAsync } from "./mapping.js";
|
|
3
3
|
export function createSmartbillSyncRuntime(options) {
|
|
4
4
|
const client = createSmartbillClient(options);
|
|
5
5
|
const logger = options.logger ?? console;
|
|
@@ -9,9 +9,12 @@ export function createSmartbillSyncRuntime(options) {
|
|
|
9
9
|
language: options.language,
|
|
10
10
|
isTaxIncluded: options.isTaxIncluded,
|
|
11
11
|
art311SpecialRegime: options.art311SpecialRegime,
|
|
12
|
+
art311SpecialRegimeText: options.art311SpecialRegimeText,
|
|
13
|
+
mentions: options.mentions,
|
|
14
|
+
observations: options.observations,
|
|
12
15
|
};
|
|
13
16
|
const mapEvent = options.mapEvent ??
|
|
14
|
-
((event) =>
|
|
17
|
+
((event) => mapVoyantInvoiceToSmartbillAsync(event, mappingOptions));
|
|
15
18
|
const eventNames = {
|
|
16
19
|
issued: options.events?.issued ?? "invoice.issued",
|
|
17
20
|
proformaIssued: options.events?.proformaIssued ?? "invoice.proforma.issued",
|
|
@@ -28,5 +31,9 @@ export function createSmartbillSyncRuntime(options) {
|
|
|
28
31
|
documentStorage: options.artifacts?.documentStorage ?? options.documentStorage,
|
|
29
32
|
documentStorageKeyPrefix: options.artifacts?.documentStorageKeyPrefix ?? options.documentStorageKeyPrefix,
|
|
30
33
|
},
|
|
34
|
+
idempotency: {
|
|
35
|
+
skipExistingExternalRef: options.idempotency?.skipExistingExternalRef ?? true,
|
|
36
|
+
},
|
|
37
|
+
onError: options.onError,
|
|
31
38
|
};
|
|
32
39
|
}
|
package/dist/settlement.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SmartbillClientOptions } from "./client.js";
|
|
2
2
|
export interface SmartbillInvoiceSettlementPollerOptions extends SmartbillClientOptions {
|
|
3
3
|
companyVatCode?: string;
|
|
4
|
-
seriesName?: string;
|
|
4
|
+
seriesName?: string | ((context: SmartbillSettlementSeriesContext) => string | null | undefined | Promise<string | null | undefined>);
|
|
5
5
|
}
|
|
6
6
|
export interface SmartbillSettlementInvoice {
|
|
7
7
|
invoiceNumber: string;
|
|
@@ -15,6 +15,9 @@ export interface SmartbillSettlementPollerContext {
|
|
|
15
15
|
invoice: SmartbillSettlementInvoice;
|
|
16
16
|
externalRef: SmartbillSettlementExternalRef;
|
|
17
17
|
}
|
|
18
|
+
export interface SmartbillSettlementSeriesContext extends SmartbillSettlementPollerContext {
|
|
19
|
+
metadata: Record<string, unknown> | null;
|
|
20
|
+
}
|
|
18
21
|
export interface SmartbillSettlementPollerResult {
|
|
19
22
|
externalId?: string | null;
|
|
20
23
|
externalNumber?: string | null;
|
package/dist/settlement.d.ts.map
CHANGED
|
@@ -1 +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,EAAE,MAAM,CAAA;
|
|
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"}
|
package/dist/settlement.js
CHANGED
|
@@ -13,11 +13,11 @@ function resolveCompanyVatCode(metadata, options) {
|
|
|
13
13
|
options.companyVatCode ??
|
|
14
14
|
null);
|
|
15
15
|
}
|
|
16
|
-
function resolveSeriesName(metadata, options) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
options.seriesName
|
|
20
|
-
|
|
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
21
|
}
|
|
22
22
|
function resolveInvoiceNumber(metadata, externalNumber, externalId, invoiceNumber) {
|
|
23
23
|
return (coerceString(metadata?.number) ??
|
|
@@ -32,9 +32,10 @@ function toCents(value) {
|
|
|
32
32
|
export function createSmartbillInvoiceSettlementPoller(options) {
|
|
33
33
|
const client = createSmartbillClient(options);
|
|
34
34
|
return async ({ invoice, externalRef }) => {
|
|
35
|
+
const context = { invoice, externalRef };
|
|
35
36
|
const metadata = coerceMetadata(externalRef.metadata);
|
|
36
37
|
const companyVatCode = resolveCompanyVatCode(metadata, options);
|
|
37
|
-
const seriesName = resolveSeriesName(metadata, options);
|
|
38
|
+
const seriesName = await resolveSeriesName(metadata, options, context);
|
|
38
39
|
const number = resolveInvoiceNumber(metadata, externalRef.externalNumber, externalRef.externalId, invoice.invoiceNumber);
|
|
39
40
|
if (!companyVatCode) {
|
|
40
41
|
return { syncError: "SmartBill settlement polling requires companyVatCode" };
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { SmartbillArtifactPersistenceOptions, SmartbillDbResolver, SmartbillDocumentStorageResolver, SmartbillStorageKeyPrefixResolver } from "./artifacts.js";
|
|
3
|
-
import type { SmartbillLogger, SmartbillMapFn, SmartbillSyncEventNames } from "./plugin.js";
|
|
3
|
+
import type { SmartbillErrorHandler, SmartbillIdempotencyOptions, SmartbillLogger, SmartbillMapFn, SmartbillSyncEventNames } from "./plugin.js";
|
|
4
4
|
import type { SmartbillFetch } from "./types.js";
|
|
5
5
|
export declare const smartbillPluginOptionsSchema: z.ZodObject<{
|
|
6
6
|
username: z.ZodString;
|
|
7
7
|
apiToken: z.ZodString;
|
|
8
8
|
companyVatCode: z.ZodString;
|
|
9
|
-
seriesName: z.
|
|
9
|
+
seriesName: z.ZodCustom<import("./mapping.js").SmartbillEventValue<string>, import("./mapping.js").SmartbillEventValue<string>>;
|
|
10
10
|
apiUrl: z.ZodOptional<z.ZodString>;
|
|
11
11
|
fetch: z.ZodOptional<z.ZodCustom<SmartbillFetch | undefined, SmartbillFetch | undefined>>;
|
|
12
12
|
language: z.ZodOptional<z.ZodString>;
|
|
13
13
|
isTaxIncluded: z.ZodOptional<z.ZodBoolean>;
|
|
14
14
|
art311SpecialRegime: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
art311SpecialRegimeText: z.ZodOptional<z.ZodString>;
|
|
16
|
+
mentions: z.ZodOptional<z.ZodCustom<import("./mapping.js").SmartbillEventValue<string | null | undefined>, import("./mapping.js").SmartbillEventValue<string | null | undefined>>>;
|
|
17
|
+
observations: z.ZodOptional<z.ZodCustom<import("./mapping.js").SmartbillEventValue<string | null | undefined>, import("./mapping.js").SmartbillEventValue<string | null | undefined>>>;
|
|
15
18
|
events: z.ZodOptional<z.ZodCustom<SmartbillSyncEventNames | undefined, SmartbillSyncEventNames | undefined>>;
|
|
16
19
|
mapEvent: z.ZodOptional<z.ZodCustom<SmartbillMapFn | undefined, SmartbillMapFn | undefined>>;
|
|
17
20
|
logger: z.ZodOptional<z.ZodCustom<SmartbillLogger | undefined, SmartbillLogger | undefined>>;
|
|
21
|
+
idempotency: z.ZodOptional<z.ZodCustom<SmartbillIdempotencyOptions | undefined, SmartbillIdempotencyOptions | undefined>>;
|
|
22
|
+
onError: z.ZodOptional<z.ZodCustom<SmartbillErrorHandler | undefined, SmartbillErrorHandler | undefined>>;
|
|
18
23
|
artifacts: z.ZodOptional<z.ZodCustom<SmartbillArtifactPersistenceOptions | undefined, SmartbillArtifactPersistenceOptions | undefined>>;
|
|
19
24
|
db: z.ZodOptional<z.ZodCustom<SmartbillDbResolver | undefined, SmartbillDbResolver | undefined>>;
|
|
20
25
|
documentStorage: z.ZodOptional<z.ZodCustom<SmartbillDocumentStorageResolver | undefined, SmartbillDocumentStorageResolver | undefined>>;
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EACV,mCAAmC,EACnC,mBAAmB,EACnB,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EACV,mCAAmC,EACnC,mBAAmB,EACnB,gCAAgC,EAChC,iCAAiC,EAClC,MAAM,gBAAgB,CAAA;AAEvB,OAAO,KAAK,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,eAAe,EACf,cAAc,EAEd,uBAAuB,EACxB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAyGhD,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;iBAsBK,CAAA"}
|
package/dist/validation.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
const optionalString = z.string().trim().min(1).optional();
|
|
3
3
|
const optionalUrl = z.string().trim().url().optional();
|
|
4
|
+
const requiredEventString = z.custom((value) => (typeof value === "string" && value.trim().length > 0) || typeof value === "function", "Expected a non-empty string or event resolver function");
|
|
5
|
+
const optionalEventText = z.custom((value) => value === undefined ||
|
|
6
|
+
(typeof value === "string" && value.trim().length > 0) ||
|
|
7
|
+
typeof value === "function", "Expected a non-empty string or event resolver function");
|
|
4
8
|
const optionalFetch = z.custom((value) => value === undefined || typeof value === "function", "Expected a fetch implementation function");
|
|
5
9
|
const optionalLogger = z.custom((value) => value === undefined ||
|
|
6
10
|
(typeof value === "object" &&
|
|
@@ -9,6 +13,7 @@ const optionalLogger = z.custom((value) => value === undefined ||
|
|
|
9
13
|
((value.info ?? undefined) === undefined ||
|
|
10
14
|
typeof value.info === "function")), "Expected a logger with an error function");
|
|
11
15
|
const optionalMapEvent = z.custom((value) => value === undefined || typeof value === "function", "Expected a mapEvent function");
|
|
16
|
+
const optionalOnError = z.custom((value) => value === undefined || typeof value === "function", "Expected an onError function");
|
|
12
17
|
const optionalDb = z.custom((value) => value === undefined ||
|
|
13
18
|
typeof value === "function" ||
|
|
14
19
|
(typeof value === "object" && value !== null), "Expected a database handle or resolver function");
|
|
@@ -43,19 +48,33 @@ const optionalEvents = z.custom((value) => {
|
|
|
43
48
|
const events = value;
|
|
44
49
|
return [events.issued, events.proformaIssued, events.voided, events.syncRequested].every((entry) => entry === undefined || (typeof entry === "string" && entry.trim().length > 0));
|
|
45
50
|
}, "Expected event names to be non-empty strings");
|
|
51
|
+
const optionalIdempotency = z.custom((value) => {
|
|
52
|
+
if (value === undefined)
|
|
53
|
+
return true;
|
|
54
|
+
if (typeof value !== "object" || value === null)
|
|
55
|
+
return false;
|
|
56
|
+
const options = value;
|
|
57
|
+
return (options.skipExistingExternalRef === undefined ||
|
|
58
|
+
typeof options.skipExistingExternalRef === "boolean");
|
|
59
|
+
}, "Expected valid SmartBill idempotency options");
|
|
46
60
|
export const smartbillPluginOptionsSchema = z.object({
|
|
47
61
|
username: z.string().trim().min(1),
|
|
48
62
|
apiToken: z.string().trim().min(1),
|
|
49
63
|
companyVatCode: z.string().trim().min(1),
|
|
50
|
-
seriesName:
|
|
64
|
+
seriesName: requiredEventString,
|
|
51
65
|
apiUrl: optionalUrl,
|
|
52
66
|
fetch: optionalFetch.optional(),
|
|
53
67
|
language: optionalString,
|
|
54
68
|
isTaxIncluded: z.boolean().optional(),
|
|
55
69
|
art311SpecialRegime: z.boolean().optional(),
|
|
70
|
+
art311SpecialRegimeText: optionalString,
|
|
71
|
+
mentions: optionalEventText.optional(),
|
|
72
|
+
observations: optionalEventText.optional(),
|
|
56
73
|
events: optionalEvents.optional(),
|
|
57
74
|
mapEvent: optionalMapEvent.optional(),
|
|
58
75
|
logger: optionalLogger.optional(),
|
|
76
|
+
idempotency: optionalIdempotency.optional(),
|
|
77
|
+
onError: optionalOnError.optional(),
|
|
59
78
|
artifacts: optionalArtifacts.optional(),
|
|
60
79
|
db: optionalDb.optional(),
|
|
61
80
|
documentStorage: optionalDocumentStorage.optional(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/plugin-smartbill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"drizzle-orm": "^0.45.2",
|
|
40
40
|
"zod": "^4.3.6",
|
|
41
|
-
"@voyantjs/core": "0.
|
|
42
|
-
"@voyantjs/finance": "0.
|
|
43
|
-
"@voyantjs/storage": "0.
|
|
41
|
+
"@voyantjs/core": "0.40.0",
|
|
42
|
+
"@voyantjs/finance": "0.40.0",
|
|
43
|
+
"@voyantjs/storage": "0.40.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"typescript": "^6.0.2",
|