@voyantjs/finance 0.26.4 → 0.26.6

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/routes.d.ts CHANGED
@@ -30,6 +30,17 @@ export declare const financeRoutes: import("hono/hono-base").HonoBase<Env, {
30
30
  balanceDueCents: number;
31
31
  count: number;
32
32
  }[];
33
+ outstandingTopN: {
34
+ id: string;
35
+ invoiceNumber: string | null;
36
+ bookingId: string | null;
37
+ status: "void" | "draft" | "sent" | "partially_paid" | "paid" | "overdue";
38
+ currency: string;
39
+ totalCents: number;
40
+ balanceDueCents: number;
41
+ issueDate: string | null;
42
+ dueDate: string | null;
43
+ }[];
33
44
  };
34
45
  };
35
46
  outputFormat: "json";
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAiF7C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCAmtCtB,CAAA;AAEJ,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAA;AAChD,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAA"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAiF7C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCAmtCtB,CAAA;AAEJ,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAA;AAChD,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAA"}
@@ -1,6 +1,17 @@
1
1
  import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
2
  import { invoices } from "./schema.js";
3
3
  type InvoiceStatus = (typeof invoices.$inferSelect)["status"];
4
+ export interface FinanceAggregateOutstandingInvoice {
5
+ id: string;
6
+ invoiceNumber: string | null;
7
+ bookingId: string | null;
8
+ status: InvoiceStatus;
9
+ currency: string;
10
+ totalCents: number;
11
+ balanceDueCents: number;
12
+ issueDate: string | null;
13
+ dueDate: string | null;
14
+ }
4
15
  export interface FinanceAggregates {
5
16
  total: number;
6
17
  countsByStatus: Array<{
@@ -38,10 +49,18 @@ export interface FinanceAggregates {
38
49
  balanceDueCents: number;
39
50
  count: number;
40
51
  }>;
52
+ /**
53
+ * Bounded top-N slice of outstanding invoices ordered by `due_date`
54
+ * (oldest first; nulls last) so the dashboard can render the
55
+ * "needs collection" list without a separate paginated request.
56
+ * Default 5, max 20 — caller bounds via `outstandingTopLimit`.
57
+ */
58
+ outstandingTopN: FinanceAggregateOutstandingInvoice[];
41
59
  }
42
60
  export declare function getFinanceAggregates(db: PostgresJsDatabase, options?: {
43
61
  from?: string;
44
62
  to?: string;
63
+ outstandingTopLimit?: number;
45
64
  }): Promise<FinanceAggregates>;
46
65
  export {};
47
66
  //# sourceMappingURL=service-aggregates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-aggregates.d.ts","sourceRoot":"","sources":["../src/service-aggregates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,KAAK,aAAa,GAAG,CAAC,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAA;AAc7D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/D,qFAAqF;IACrF,cAAc,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClF,8DAA8D;IAC9D,oBAAoB,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjE;;;;OAIG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChF;;;;OAIG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC7E;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,kBAAkB,EACtB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAO,GAC3C,OAAO,CAAC,iBAAiB,CAAC,CAkH5B"}
1
+ {"version":3,"file":"service-aggregates.d.ts","sourceRoot":"","sources":["../src/service-aggregates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,KAAK,aAAa,GAAG,CAAC,OAAO,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAA;AAc7D,MAAM,WAAW,kCAAkC;IACjD,EAAE,EAAE,MAAM,CAAA;IACV,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,aAAa,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC/D,qFAAqF;IACrF,cAAc,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClF,8DAA8D;IAC9D,oBAAoB,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjE;;;;OAIG;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChF;;;;OAIG;IACH,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5E;;;;;OAKG;IACH,eAAe,EAAE,kCAAkC,EAAE,CAAA;CACtD;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,kBAAkB,EACtB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAO,GACzE,OAAO,CAAC,iBAAiB,CAAC,CA8J5B"}
@@ -1,4 +1,4 @@
1
- import { and, inArray, ne, sql } from "drizzle-orm";
1
+ import { and, asc, inArray, ne, sql } from "drizzle-orm";
2
2
  import { invoices } from "./schema.js";
3
3
  const ALL_INVOICE_STATUSES = [
4
4
  "draft",
@@ -11,6 +11,7 @@ const ALL_INVOICE_STATUSES = [
11
11
  /** Statuses where balance_due_cents > 0 is meaningful money we're owed. */
12
12
  const OUTSTANDING_STATUSES = ["sent", "partially_paid", "overdue"];
13
13
  export async function getFinanceAggregates(db, options = {}) {
14
+ const outstandingTopLimit = Math.max(0, Math.min(options.outstandingTopLimit ?? 5, 20));
14
15
  const fromDate = options.from ? new Date(options.from) : undefined;
15
16
  const toDate = options.to ? new Date(options.to) : undefined;
16
17
  const rangeConditions = [];
@@ -77,6 +78,26 @@ export async function getFinanceAggregates(db, options = {}) {
77
78
  .where(and(inArray(invoices.status, [...OUTSTANDING_STATUSES]), sql `${invoices.balanceDueCents} > 0`, sql `${invoices.dueDate} < ${todayDateString}`))
78
79
  .groupBy(invoices.currency)
79
80
  .orderBy(invoices.currency);
81
+ const outstandingTopRows = outstandingTopLimit === 0
82
+ ? []
83
+ : await db
84
+ .select({
85
+ id: invoices.id,
86
+ invoiceNumber: invoices.invoiceNumber,
87
+ bookingId: invoices.bookingId,
88
+ status: invoices.status,
89
+ currency: invoices.currency,
90
+ totalCents: invoices.totalCents,
91
+ balanceDueCents: invoices.balanceDueCents,
92
+ issueDate: invoices.issueDate,
93
+ dueDate: invoices.dueDate,
94
+ })
95
+ .from(invoices)
96
+ .where(and(inArray(invoices.status, [...OUTSTANDING_STATUSES]), sql `${invoices.balanceDueCents} > 0`))
97
+ // Nulls-last on dueDate so undated invoices don't pretend to be
98
+ // the most overdue. After that, oldest issued first.
99
+ .orderBy(sql `${invoices.dueDate} IS NULL`, asc(invoices.dueDate), asc(invoices.issueDate), asc(invoices.id))
100
+ .limit(outstandingTopLimit);
80
101
  return {
81
102
  total: totalRow?.count ?? 0,
82
103
  countsByStatus: ALL_INVOICE_STATUSES.map((status) => ({
@@ -102,5 +123,16 @@ export async function getFinanceAggregates(db, options = {}) {
102
123
  balanceDueCents: Number(row.balanceDueCents),
103
124
  count: row.count,
104
125
  })),
126
+ outstandingTopN: outstandingTopRows.map((row) => ({
127
+ id: row.id,
128
+ invoiceNumber: row.invoiceNumber ?? null,
129
+ bookingId: row.bookingId ?? null,
130
+ status: row.status,
131
+ currency: row.currency,
132
+ totalCents: Number(row.totalCents),
133
+ balanceDueCents: Number(row.balanceDueCents),
134
+ issueDate: row.issueDate ?? null,
135
+ dueDate: row.dueDate ?? null,
136
+ })),
105
137
  };
106
138
  }
@@ -173,5 +173,6 @@ export declare const voucherSourceTypeSchema: z.ZodEnum<{
173
173
  export declare const financeAggregatesQuerySchema: z.ZodObject<{
174
174
  from: z.ZodOptional<z.ZodString>;
175
175
  to: z.ZodOptional<z.ZodString>;
176
+ outstandingTopLimit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
176
177
  }, z.core.$strip>;
177
178
  //# sourceMappingURL=validation-shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation-shared.d.ts","sourceRoot":"","sources":["../src/validation-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,mBAAmB;;;;;;;EAO9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;;EAU9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;EAAyD,CAAA;AACzF,eAAO,MAAM,0BAA0B;;;;;;;;;EASrC,CAAA;AACF,eAAO,MAAM,8BAA8B;;;;;;;;EAQzC,CAAA;AACF,eAAO,MAAM,2BAA2B;;;;;;;;;EAStC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;;;;EAO3C,CAAA;AACF,eAAO,MAAM,6BAA6B;;;;;;EAMxC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;;;;;EAQ3C,CAAA;AACF,eAAO,MAAM,0BAA0B;;;;;;EAMrC,CAAA;AACF,eAAO,MAAM,iBAAiB;;;EAAkC,CAAA;AAChE,eAAO,MAAM,sBAAsB;;;;EAAyC,CAAA;AAC5E,eAAO,MAAM,yBAAyB;;;;;;EAMpC,CAAA;AACF,eAAO,MAAM,2BAA2B;;;;;;;EAOtC,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;EAS9B,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;;;EAOhC,CAAA;AACF,eAAO,MAAM,cAAc;;;;EAA+C,CAAA;AAC1E,eAAO,MAAM,6BAA6B;;;;;;;;EAQxC,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;EAAmD,CAAA;AACrF,eAAO,MAAM,sBAAsB;;;;;;EAA4D,CAAA;AAE/F,eAAO,MAAM,gBAAgB;;;iBAG3B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;EAAoD,CAAA;AACpF,eAAO,MAAM,uBAAuB;;;;;;EAMlC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAA"}
1
+ {"version":3,"file":"validation-shared.d.ts","sourceRoot":"","sources":["../src/validation-shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,mBAAmB;;;;;;;EAO9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;;EAU9B,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;EAAyD,CAAA;AACzF,eAAO,MAAM,0BAA0B;;;;;;;;;EASrC,CAAA;AACF,eAAO,MAAM,8BAA8B;;;;;;;;EAQzC,CAAA;AACF,eAAO,MAAM,2BAA2B;;;;;;;;;EAStC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;;;;EAO3C,CAAA;AACF,eAAO,MAAM,6BAA6B;;;;;;EAMxC,CAAA;AACF,eAAO,MAAM,gCAAgC;;;;;;;;EAQ3C,CAAA;AACF,eAAO,MAAM,0BAA0B;;;;;;EAMrC,CAAA;AACF,eAAO,MAAM,iBAAiB;;;EAAkC,CAAA;AAChE,eAAO,MAAM,sBAAsB;;;;EAAyC,CAAA;AAC5E,eAAO,MAAM,yBAAyB;;;;;;EAMpC,CAAA;AACF,eAAO,MAAM,2BAA2B;;;;;;;EAOtC,CAAA;AACF,eAAO,MAAM,mBAAmB;;;;;;;;;EAS9B,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;;;EAOhC,CAAA;AACF,eAAO,MAAM,cAAc;;;;EAA+C,CAAA;AAC1E,eAAO,MAAM,6BAA6B;;;;;;;;EAQxC,CAAA;AACF,eAAO,MAAM,qBAAqB;;;;;EAAmD,CAAA;AACrF,eAAO,MAAM,sBAAsB;;;;;;EAA4D,CAAA;AAE/F,eAAO,MAAM,gBAAgB;;;iBAG3B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;EAAoD,CAAA;AACpF,eAAO,MAAM,uBAAuB;;;;;;EAMlC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;iBAUvC,CAAA"}
@@ -141,4 +141,11 @@ export const voucherSourceTypeSchema = z.enum([
141
141
  export const financeAggregatesQuerySchema = z.object({
142
142
  from: z.string().datetime().optional(),
143
143
  to: z.string().datetime().optional(),
144
+ /**
145
+ * Cap on the top-N outstanding-invoice rows returned alongside the
146
+ * outstanding-by-currency aggregate. The dashboard surfaces 5 rows
147
+ * in its "needs collection" panel; allow up to 20 so adjacent
148
+ * digests can reuse the endpoint.
149
+ */
150
+ outstandingTopLimit: z.coerce.number().int().min(0).max(20).default(5),
144
151
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/finance",
3
- "version": "0.26.4",
3
+ "version": "0.26.6",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -39,12 +39,12 @@
39
39
  "drizzle-orm": "^0.45.2",
40
40
  "hono": "^4.12.10",
41
41
  "zod": "^4.3.6",
42
- "@voyantjs/bookings": "0.26.4",
43
- "@voyantjs/core": "0.26.4",
44
- "@voyantjs/db": "0.26.4",
45
- "@voyantjs/hono": "0.26.4",
46
- "@voyantjs/utils": "0.26.4",
47
- "@voyantjs/storage": "0.26.4"
42
+ "@voyantjs/bookings": "0.26.6",
43
+ "@voyantjs/core": "0.26.6",
44
+ "@voyantjs/db": "0.26.6",
45
+ "@voyantjs/hono": "0.26.6",
46
+ "@voyantjs/utils": "0.26.6",
47
+ "@voyantjs/storage": "0.26.6"
48
48
  },
49
49
  "devDependencies": {
50
50
  "typescript": "^6.0.2",