@voyantjs/finance 0.80.14 → 0.80.16

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/dist/service.js CHANGED
@@ -30,6 +30,23 @@ export class InvoiceNumberAllocationError extends Error {
30
30
  this.seriesId = details.seriesId;
31
31
  }
32
32
  }
33
+ export class ExternalInvoiceNumberSeriesCollisionError extends Error {
34
+ code = "external_invoice_number_series_code_conflict";
35
+ seriesCode;
36
+ provider;
37
+ scope;
38
+ existingProvider;
39
+ existingScope;
40
+ constructor(details) {
41
+ super(`Invoice number series code "${details.seriesCode}" already belongs to ${details.existingProvider ?? "a local series"} in scope "${details.existingScope}"`);
42
+ this.name = "ExternalInvoiceNumberSeriesCollisionError";
43
+ this.seriesCode = details.seriesCode;
44
+ this.provider = details.provider;
45
+ this.scope = details.scope;
46
+ this.existingProvider = details.existingProvider;
47
+ this.existingScope = details.existingScope;
48
+ }
49
+ }
33
50
  export class InvoiceNumberConflictError extends Error {
34
51
  code = "invoice_number_conflict";
35
52
  invoiceNumber;
@@ -183,6 +200,12 @@ function toTimestamp(value) {
183
200
  function toDateString(value) {
184
201
  return value.toISOString().slice(0, 10);
185
202
  }
203
+ function readStringMetadata(value, key) {
204
+ if (value == null || typeof value !== "object")
205
+ return null;
206
+ const candidate = value[key];
207
+ return typeof candidate === "string" && candidate.trim() ? candidate : null;
208
+ }
186
209
  function startOfUtcDay(value) {
187
210
  return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate()));
188
211
  }
@@ -2402,6 +2425,111 @@ export const financeService = {
2402
2425
  await db.delete(invoices).where(eq(invoices.id, id));
2403
2426
  return { status: "deleted" };
2404
2427
  },
2428
+ async voidInvoice(db, id, input = {}, runtime = {}) {
2429
+ const reason = input.reason?.trim() || null;
2430
+ const voidedAt = new Date();
2431
+ const result = await db.transaction(async (tx) => {
2432
+ const [existing] = await tx.select().from(invoices).where(eq(invoices.id, id)).limit(1);
2433
+ if (!existing) {
2434
+ return { status: "not_found" };
2435
+ }
2436
+ if (existing.status === "void") {
2437
+ return { status: "already_void", invoice: existing };
2438
+ }
2439
+ if (existing.status === "draft") {
2440
+ return { status: "draft", invoice: existing };
2441
+ }
2442
+ const voidableStatuses = new Set([
2443
+ "pending_external_allocation",
2444
+ "issued",
2445
+ "partially_paid",
2446
+ "overdue",
2447
+ ]);
2448
+ if (!voidableStatuses.has(existing.status)) {
2449
+ return { status: "invalid_status", invoice: existing };
2450
+ }
2451
+ const [payment] = await tx
2452
+ .select({ id: payments.id })
2453
+ .from(payments)
2454
+ .where(eq(payments.invoiceId, id))
2455
+ .limit(1);
2456
+ if (payment) {
2457
+ return { status: "has_payments", invoice: existing };
2458
+ }
2459
+ const [creditNote] = await tx
2460
+ .select({ id: creditNotes.id })
2461
+ .from(creditNotes)
2462
+ .where(eq(creditNotes.invoiceId, id))
2463
+ .limit(1);
2464
+ if (creditNote) {
2465
+ return { status: "has_credit_notes", invoice: existing };
2466
+ }
2467
+ const changes = {
2468
+ status: "void",
2469
+ voidedAt,
2470
+ voidReason: reason,
2471
+ balanceDueCents: 0,
2472
+ baseBalanceDueCents: existing.baseBalanceDueCents == null ? null : 0,
2473
+ updatedAt: voidedAt,
2474
+ };
2475
+ const actionLedgerChanges = {
2476
+ status: "void",
2477
+ balanceDueCents: changes.balanceDueCents,
2478
+ baseBalanceDueCents: changes.baseBalanceDueCents,
2479
+ };
2480
+ const [invoice] = await tx
2481
+ .update(invoices)
2482
+ .set(changes)
2483
+ .where(eq(invoices.id, id))
2484
+ .returning();
2485
+ if (!invoice) {
2486
+ return { status: "not_found" };
2487
+ }
2488
+ const actionLedgerContext = runtime.actionLedgerContext;
2489
+ if (actionLedgerContext) {
2490
+ await appendActionLedgerMutation(tx, buildInvoiceUpdateActionLedgerInput(actionLedgerContext, { invoice, changes: actionLedgerChanges }, { authorizationSource: runtime.actionLedgerAuthorizationSource }));
2491
+ }
2492
+ return { status: "voided", invoice };
2493
+ });
2494
+ if (result.status === "voided" && runtime.eventBus) {
2495
+ const [smartbillRef] = await db
2496
+ .select()
2497
+ .from(invoiceExternalRefs)
2498
+ .where(and(eq(invoiceExternalRefs.invoiceId, result.invoice.id), eq(invoiceExternalRefs.provider, "smartbill")))
2499
+ .orderBy(desc(invoiceExternalRefs.createdAt))
2500
+ .limit(1);
2501
+ const [externalRef] = smartbillRef
2502
+ ? [smartbillRef]
2503
+ : await db
2504
+ .select()
2505
+ .from(invoiceExternalRefs)
2506
+ .where(eq(invoiceExternalRefs.invoiceId, result.invoice.id))
2507
+ .orderBy(desc(invoiceExternalRefs.createdAt))
2508
+ .limit(1);
2509
+ const [series] = result.invoice.seriesId
2510
+ ? await db
2511
+ .select({ name: invoiceNumberSeries.name })
2512
+ .from(invoiceNumberSeries)
2513
+ .where(eq(invoiceNumberSeries.id, result.invoice.seriesId))
2514
+ .limit(1)
2515
+ : [];
2516
+ const event = {
2517
+ invoiceId: result.invoice.id,
2518
+ invoiceNumber: result.invoice.invoiceNumber,
2519
+ invoiceType: result.invoice.invoiceType,
2520
+ bookingId: result.invoice.bookingId,
2521
+ totalCents: result.invoice.totalCents,
2522
+ currency: result.invoice.currency,
2523
+ reason,
2524
+ voidedAt: result.invoice.voidedAt?.toISOString() ?? voidedAt.toISOString(),
2525
+ externalProvider: externalRef?.provider ?? null,
2526
+ externalNumber: externalRef?.externalNumber ?? null,
2527
+ externalSeriesName: readStringMetadata(externalRef?.metadata, "seriesName") ?? series?.name ?? null,
2528
+ };
2529
+ await runtime.eventBus.emit("invoice.voided", event);
2530
+ }
2531
+ return result;
2532
+ },
2405
2533
  listInvoiceLineItems(db, invoiceId) {
2406
2534
  return db
2407
2535
  .select()
@@ -3042,6 +3170,96 @@ export const financeService = {
3042
3170
  .limit(1);
3043
3171
  return row ?? null;
3044
3172
  },
3173
+ async ensureExternalInvoiceNumberSeries(db, inputs) {
3174
+ return db.transaction(async (tx) => {
3175
+ const rows = [];
3176
+ for (const input of inputs) {
3177
+ const now = new Date();
3178
+ const code = input.code ?? `${input.provider}-${input.scope}`;
3179
+ const active = input.active ?? true;
3180
+ const isDefault = active === false ? false : (input.isDefault ?? true);
3181
+ const [existingExternal] = await tx
3182
+ .select()
3183
+ .from(invoiceNumberSeries)
3184
+ .where(and(eq(invoiceNumberSeries.scope, input.scope), eq(invoiceNumberSeries.externalProvider, input.provider)))
3185
+ .orderBy(desc(invoiceNumberSeries.isDefault), desc(invoiceNumberSeries.updatedAt), desc(invoiceNumberSeries.createdAt))
3186
+ .limit(1);
3187
+ const [existingByCode] = existingExternal
3188
+ ? [null]
3189
+ : await tx
3190
+ .select()
3191
+ .from(invoiceNumberSeries)
3192
+ .where(eq(invoiceNumberSeries.code, code))
3193
+ .limit(1);
3194
+ if (existingByCode &&
3195
+ (existingByCode.scope !== input.scope ||
3196
+ existingByCode.externalProvider !== input.provider)) {
3197
+ throw new ExternalInvoiceNumberSeriesCollisionError({
3198
+ seriesCode: code,
3199
+ provider: input.provider,
3200
+ scope: input.scope,
3201
+ existingProvider: existingByCode.externalProvider,
3202
+ existingScope: existingByCode.scope,
3203
+ });
3204
+ }
3205
+ const existing = existingExternal ?? existingByCode;
3206
+ const nextCode = existingExternal ? existingExternal.code : code;
3207
+ if (isDefault) {
3208
+ const defaultScopeWhere = existing
3209
+ ? and(eq(invoiceNumberSeries.scope, input.scope), ne(invoiceNumberSeries.id, existing.id))
3210
+ : eq(invoiceNumberSeries.scope, input.scope);
3211
+ await tx
3212
+ .update(invoiceNumberSeries)
3213
+ .set({ isDefault: false, updatedAt: now })
3214
+ .where(defaultScopeWhere);
3215
+ }
3216
+ if (existing) {
3217
+ const [row] = await tx
3218
+ .update(invoiceNumberSeries)
3219
+ .set({
3220
+ code: nextCode,
3221
+ name: input.name,
3222
+ prefix: input.prefix ?? existing.prefix,
3223
+ separator: input.separator ?? existing.separator,
3224
+ padLength: input.padLength ?? existing.padLength,
3225
+ resetStrategy: input.resetStrategy ?? existing.resetStrategy,
3226
+ scope: input.scope,
3227
+ isDefault,
3228
+ externalProvider: input.provider,
3229
+ externalConfigKey: input.externalConfigKey ?? null,
3230
+ active,
3231
+ updatedAt: now,
3232
+ })
3233
+ .where(eq(invoiceNumberSeries.id, existing.id))
3234
+ .returning();
3235
+ if (row)
3236
+ rows.push(row);
3237
+ continue;
3238
+ }
3239
+ const [row] = await tx
3240
+ .insert(invoiceNumberSeries)
3241
+ .values({
3242
+ code,
3243
+ name: input.name,
3244
+ prefix: input.prefix ?? "",
3245
+ separator: input.separator ?? "",
3246
+ padLength: input.padLength ?? 0,
3247
+ currentSequence: 0,
3248
+ resetStrategy: input.resetStrategy ?? "never",
3249
+ resetAt: null,
3250
+ scope: input.scope,
3251
+ isDefault,
3252
+ externalProvider: input.provider,
3253
+ externalConfigKey: input.externalConfigKey ?? null,
3254
+ active,
3255
+ })
3256
+ .returning();
3257
+ if (row)
3258
+ rows.push(row);
3259
+ }
3260
+ return rows;
3261
+ });
3262
+ },
3045
3263
  async createInvoiceNumberSeries(db, data) {
3046
3264
  return db.transaction(async (tx) => {
3047
3265
  const isDefault = data.active === false ? false : data.isDefault;
@@ -159,6 +159,9 @@ export declare const updateInvoiceSchema: z.ZodObject<{
159
159
  dueDate: z.ZodOptional<z.ZodString>;
160
160
  notes: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodString>>>;
161
161
  }, z.core.$strip>;
162
+ export declare const voidInvoiceSchema: z.ZodObject<{
163
+ reason: z.ZodNullable<z.ZodOptional<z.ZodString>>;
164
+ }, z.core.$strip>;
162
165
  export declare const invoiceListSortFieldSchema: z.ZodEnum<{
163
166
  status: "status";
164
167
  createdAt: "createdAt";
@@ -1 +1 @@
1
- {"version":3,"file":"validation-billing.d.ts","sourceRoot":"","sources":["../src/validation-billing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validation-billing.d.ts","sourceRoot":"","sources":["../src/validation-billing.ts"],"names":[],"mappings":"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"}
@@ -56,6 +56,9 @@ const invoiceCoreSchema = z.object({
56
56
  });
57
57
  export const insertInvoiceSchema = invoiceCoreSchema;
58
58
  export const updateInvoiceSchema = invoiceCoreSchema.partial();
59
+ export const voidInvoiceSchema = z.object({
60
+ reason: z.string().trim().max(1000).optional().nullable(),
61
+ });
59
62
  export const invoiceListSortFieldSchema = z.enum([
60
63
  "invoiceNumber",
61
64
  "status",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/finance",
3
- "version": "0.80.14",
3
+ "version": "0.80.16",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -60,14 +60,14 @@
60
60
  "drizzle-orm": "^0.45.2",
61
61
  "hono": "^4.12.10",
62
62
  "zod": "^4.3.6",
63
- "@voyantjs/action-ledger": "0.80.14",
64
- "@voyantjs/bookings": "0.80.14",
65
- "@voyantjs/core": "0.80.14",
66
- "@voyantjs/db": "0.80.14",
67
- "@voyantjs/hono": "0.80.14",
68
- "@voyantjs/products": "0.80.14",
69
- "@voyantjs/storage": "0.80.14",
70
- "@voyantjs/utils": "0.80.14"
63
+ "@voyantjs/action-ledger": "0.80.16",
64
+ "@voyantjs/bookings": "0.80.16",
65
+ "@voyantjs/core": "0.80.16",
66
+ "@voyantjs/db": "0.80.16",
67
+ "@voyantjs/hono": "0.80.16",
68
+ "@voyantjs/products": "0.80.16",
69
+ "@voyantjs/storage": "0.80.16",
70
+ "@voyantjs/utils": "0.80.16"
71
71
  },
72
72
  "devDependencies": {
73
73
  "typescript": "^6.0.2",