@voyantjs/finance 0.28.1 → 0.29.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/dist/service.js CHANGED
@@ -99,6 +99,38 @@ async function paginate(rowsQuery, countQuery, limit, offset) {
99
99
  const [data, countResult] = await Promise.all([rowsQuery, countQuery]);
100
100
  return { data, total: countResult[0]?.total ?? 0, limit, offset };
101
101
  }
102
+ function mapRawPayment(row) {
103
+ // Person display name: "First Last", trimmed. Falls back to null when both
104
+ // halves are missing so the UI can swap to organization or hide the field.
105
+ const personName = row.person_first_name || row.person_last_name
106
+ ? `${row.person_first_name ?? ""} ${row.person_last_name ?? ""}`.trim() || null
107
+ : null;
108
+ return {
109
+ kind: row.kind,
110
+ id: row.id,
111
+ invoiceId: row.invoice_id,
112
+ invoiceNumber: row.invoice_number,
113
+ bookingId: row.booking_id,
114
+ bookingNumber: row.booking_number,
115
+ supplierId: row.supplier_id,
116
+ supplierName: row.supplier_name,
117
+ personId: row.person_id,
118
+ personName,
119
+ organizationId: row.organization_id,
120
+ organizationName: row.organization_name,
121
+ amountCents: row.amount_cents,
122
+ currency: row.currency,
123
+ baseCurrency: row.base_currency,
124
+ baseAmountCents: row.base_amount_cents,
125
+ paymentMethod: row.payment_method,
126
+ status: row.status,
127
+ referenceNumber: row.reference_number,
128
+ paymentDate: row.payment_date,
129
+ notes: row.notes,
130
+ createdAt: row.created_at instanceof Date ? row.created_at : new Date(row.created_at),
131
+ updatedAt: row.updated_at instanceof Date ? row.updated_at : new Date(row.updated_at),
132
+ };
133
+ }
102
134
  export const financeService = {
103
135
  vouchers: vouchersService,
104
136
  getFinanceAggregates,
@@ -1162,7 +1194,32 @@ export const financeService = {
1162
1194
  if (query.status) {
1163
1195
  conditions.push(eq(supplierPayments.status, query.status));
1164
1196
  }
1197
+ if (query.paymentMethod) {
1198
+ conditions.push(eq(supplierPayments.paymentMethod, query.paymentMethod));
1199
+ }
1200
+ if (query.currency) {
1201
+ conditions.push(eq(supplierPayments.currency, query.currency));
1202
+ }
1203
+ if (query.paymentDateFrom) {
1204
+ conditions.push(gte(supplierPayments.paymentDate, query.paymentDateFrom));
1205
+ }
1206
+ if (query.paymentDateTo) {
1207
+ conditions.push(lte(supplierPayments.paymentDate, query.paymentDateTo));
1208
+ }
1165
1209
  const where = conditions.length > 0 ? and(...conditions) : undefined;
1210
+ const sortColumn = (() => {
1211
+ switch (query.sortBy) {
1212
+ case "amountCents":
1213
+ return supplierPayments.amountCents;
1214
+ case "status":
1215
+ return supplierPayments.status;
1216
+ case "paymentDate":
1217
+ return supplierPayments.paymentDate;
1218
+ default:
1219
+ return supplierPayments.createdAt;
1220
+ }
1221
+ })();
1222
+ const sortFn = query.sortDir === "asc" ? asc : desc;
1166
1223
  const [rows, countResult] = await Promise.all([
1167
1224
  db
1168
1225
  .select()
@@ -1170,7 +1227,7 @@ export const financeService = {
1170
1227
  .where(where)
1171
1228
  .limit(query.limit)
1172
1229
  .offset(query.offset)
1173
- .orderBy(desc(supplierPayments.createdAt)),
1230
+ .orderBy(sortFn(sortColumn), desc(supplierPayments.createdAt)),
1174
1231
  db.select({ count: sql `count(*)::int` }).from(supplierPayments).where(where),
1175
1232
  ]);
1176
1233
  return {
@@ -1203,11 +1260,47 @@ export const financeService = {
1203
1260
  if (query.bookingId) {
1204
1261
  conditions.push(eq(invoices.bookingId, query.bookingId));
1205
1262
  }
1263
+ if (query.personId) {
1264
+ conditions.push(eq(invoices.personId, query.personId));
1265
+ }
1266
+ if (query.organizationId) {
1267
+ conditions.push(eq(invoices.organizationId, query.organizationId));
1268
+ }
1269
+ if (query.currency) {
1270
+ conditions.push(eq(invoices.currency, query.currency));
1271
+ }
1272
+ if (query.dueDateFrom) {
1273
+ conditions.push(gte(invoices.dueDate, query.dueDateFrom));
1274
+ }
1275
+ if (query.dueDateTo) {
1276
+ conditions.push(lte(invoices.dueDate, query.dueDateTo));
1277
+ }
1206
1278
  if (query.search) {
1207
1279
  const term = `%${query.search}%`;
1208
1280
  conditions.push(or(ilike(invoices.invoiceNumber, term), ilike(invoices.notes, term)));
1209
1281
  }
1210
1282
  const where = conditions.length > 0 ? and(...conditions) : undefined;
1283
+ const sortColumn = (() => {
1284
+ switch (query.sortBy) {
1285
+ case "invoiceNumber":
1286
+ return invoices.invoiceNumber;
1287
+ case "status":
1288
+ return invoices.status;
1289
+ case "totalCents":
1290
+ return invoices.totalCents;
1291
+ case "paidCents":
1292
+ return invoices.paidCents;
1293
+ case "balanceDueCents":
1294
+ return invoices.balanceDueCents;
1295
+ case "issueDate":
1296
+ return invoices.issueDate;
1297
+ case "dueDate":
1298
+ return invoices.dueDate;
1299
+ default:
1300
+ return invoices.createdAt;
1301
+ }
1302
+ })();
1303
+ const sortFn = query.sortDir === "asc" ? asc : desc;
1211
1304
  const [rows, countResult] = await Promise.all([
1212
1305
  db
1213
1306
  .select()
@@ -1215,7 +1308,7 @@ export const financeService = {
1215
1308
  .where(where)
1216
1309
  .limit(query.limit)
1217
1310
  .offset(query.offset)
1218
- .orderBy(desc(invoices.createdAt)),
1311
+ .orderBy(sortFn(sortColumn), desc(invoices.createdAt)),
1219
1312
  db.select({ count: sql `count(*)::int` }).from(invoices).where(where),
1220
1313
  ]);
1221
1314
  return {
@@ -1403,6 +1496,232 @@ export const financeService = {
1403
1496
  .where(eq(payments.invoiceId, invoiceId))
1404
1497
  .orderBy(desc(payments.paymentDate));
1405
1498
  },
1499
+ async listAllPayments(db, query) {
1500
+ // The unified view UNIONs `payments` (customer-side, FK to invoices) and
1501
+ // `supplier_payments` (FK to bookings + suppliers). Filters that only make
1502
+ // sense for one side (invoiceId / supplierId) implicitly exclude the
1503
+ // other; the explicit `kind` filter takes precedence.
1504
+ const includeCustomer = (!query.kind || query.kind === "customer") && !query.supplierId;
1505
+ const includeSupplier = (!query.kind || query.kind === "supplier") && !query.invoiceId;
1506
+ if (!includeCustomer && !includeSupplier) {
1507
+ return { data: [], total: 0, limit: query.limit, offset: query.offset };
1508
+ }
1509
+ const customerConditions = [sql `true`];
1510
+ if (query.status)
1511
+ customerConditions.push(sql `p.status = ${query.status}`);
1512
+ if (query.paymentMethod)
1513
+ customerConditions.push(sql `p.payment_method = ${query.paymentMethod}`);
1514
+ if (query.currency)
1515
+ customerConditions.push(sql `p.currency = ${query.currency}`);
1516
+ if (query.invoiceId)
1517
+ customerConditions.push(sql `p.invoice_id = ${query.invoiceId}`);
1518
+ if (query.bookingId)
1519
+ customerConditions.push(sql `i.booking_id = ${query.bookingId}`);
1520
+ if (query.paymentDateFrom)
1521
+ customerConditions.push(sql `p.payment_date >= ${query.paymentDateFrom}`);
1522
+ if (query.paymentDateTo)
1523
+ customerConditions.push(sql `p.payment_date <= ${query.paymentDateTo}`);
1524
+ if (query.search)
1525
+ customerConditions.push(sql `p.reference_number ILIKE ${`%${query.search}%`}`);
1526
+ const customerWhere = sql.join(customerConditions, sql ` AND `);
1527
+ const supplierConditions = [sql `true`];
1528
+ if (query.status)
1529
+ supplierConditions.push(sql `sp.status = ${query.status}`);
1530
+ if (query.paymentMethod)
1531
+ supplierConditions.push(sql `sp.payment_method = ${query.paymentMethod}`);
1532
+ if (query.currency)
1533
+ supplierConditions.push(sql `sp.currency = ${query.currency}`);
1534
+ if (query.bookingId)
1535
+ supplierConditions.push(sql `sp.booking_id = ${query.bookingId}`);
1536
+ if (query.supplierId)
1537
+ supplierConditions.push(sql `sp.supplier_id = ${query.supplierId}`);
1538
+ if (query.paymentDateFrom)
1539
+ supplierConditions.push(sql `sp.payment_date >= ${query.paymentDateFrom}`);
1540
+ if (query.paymentDateTo)
1541
+ supplierConditions.push(sql `sp.payment_date <= ${query.paymentDateTo}`);
1542
+ if (query.search)
1543
+ supplierConditions.push(sql `sp.reference_number ILIKE ${`%${query.search}%`}`);
1544
+ const supplierWhere = sql.join(supplierConditions, sql ` AND `);
1545
+ const customerSelect = sql `
1546
+ SELECT
1547
+ 'customer'::text AS kind,
1548
+ p.id AS id,
1549
+ p.invoice_id AS invoice_id,
1550
+ i.invoice_number AS invoice_number,
1551
+ NULL::text AS booking_id,
1552
+ NULL::text AS booking_number,
1553
+ NULL::text AS supplier_id,
1554
+ NULL::text AS supplier_name,
1555
+ i.person_id AS person_id,
1556
+ pe.first_name AS person_first_name,
1557
+ pe.last_name AS person_last_name,
1558
+ i.organization_id AS organization_id,
1559
+ o.name AS organization_name,
1560
+ p.amount_cents AS amount_cents,
1561
+ p.currency AS currency,
1562
+ p.base_currency AS base_currency,
1563
+ p.base_amount_cents AS base_amount_cents,
1564
+ p.payment_method::text AS payment_method,
1565
+ p.status::text AS status,
1566
+ p.reference_number AS reference_number,
1567
+ p.payment_date AS payment_date,
1568
+ p.notes AS notes,
1569
+ p.created_at AS created_at,
1570
+ p.updated_at AS updated_at
1571
+ FROM payments p
1572
+ LEFT JOIN invoices i ON i.id = p.invoice_id
1573
+ LEFT JOIN people pe ON pe.id = i.person_id
1574
+ LEFT JOIN organizations o ON o.id = i.organization_id
1575
+ WHERE ${customerWhere}
1576
+ `;
1577
+ const supplierSelect = sql `
1578
+ SELECT
1579
+ 'supplier'::text AS kind,
1580
+ sp.id AS id,
1581
+ NULL::text AS invoice_id,
1582
+ NULL::text AS invoice_number,
1583
+ sp.booking_id AS booking_id,
1584
+ b.booking_number AS booking_number,
1585
+ sp.supplier_id AS supplier_id,
1586
+ s.name AS supplier_name,
1587
+ NULL::text AS person_id,
1588
+ NULL::text AS person_first_name,
1589
+ NULL::text AS person_last_name,
1590
+ NULL::text AS organization_id,
1591
+ NULL::text AS organization_name,
1592
+ sp.amount_cents AS amount_cents,
1593
+ sp.currency AS currency,
1594
+ sp.base_currency AS base_currency,
1595
+ sp.base_amount_cents AS base_amount_cents,
1596
+ sp.payment_method::text AS payment_method,
1597
+ sp.status::text AS status,
1598
+ sp.reference_number AS reference_number,
1599
+ sp.payment_date AS payment_date,
1600
+ sp.notes AS notes,
1601
+ sp.created_at AS created_at,
1602
+ sp.updated_at AS updated_at
1603
+ FROM supplier_payments sp
1604
+ LEFT JOIN bookings b ON b.id = sp.booking_id
1605
+ LEFT JOIN suppliers s ON s.id = sp.supplier_id
1606
+ WHERE ${supplierWhere}
1607
+ `;
1608
+ const unionParts = [];
1609
+ if (includeCustomer)
1610
+ unionParts.push(customerSelect);
1611
+ if (includeSupplier)
1612
+ unionParts.push(supplierSelect);
1613
+ const unioned = sql.join(unionParts, sql ` UNION ALL `);
1614
+ const sortColumn = (() => {
1615
+ switch (query.sortBy) {
1616
+ case "amountCents":
1617
+ return sql.raw("amount_cents");
1618
+ case "status":
1619
+ return sql.raw("status");
1620
+ case "paymentDate":
1621
+ return sql.raw("payment_date");
1622
+ default:
1623
+ return sql.raw("created_at");
1624
+ }
1625
+ })();
1626
+ const sortDirSql = query.sortDir === "asc" ? sql.raw("ASC") : sql.raw("DESC");
1627
+ const dataResult = await db.execute(sql `
1628
+ SELECT * FROM (${unioned}) all_payments
1629
+ ORDER BY ${sortColumn} ${sortDirSql}, created_at DESC
1630
+ LIMIT ${query.limit}
1631
+ OFFSET ${query.offset}
1632
+ `);
1633
+ const countResult = await db.execute(sql `
1634
+ SELECT COUNT(*)::int AS count FROM (${unioned}) all_payments
1635
+ `);
1636
+ const rows = dataResult;
1637
+ const total = countResult[0]?.count ?? 0;
1638
+ const data = rows.map(mapRawPayment);
1639
+ return {
1640
+ data,
1641
+ total,
1642
+ limit: query.limit,
1643
+ offset: query.offset,
1644
+ };
1645
+ },
1646
+ /**
1647
+ * Resolve a unified payment by id. Dispatches by typeid prefix:
1648
+ * `pay_*` lives in `payments` (customer side), `spay_*` in `supplier_payments`.
1649
+ * Returns the same enriched row shape as `listAllPayments` so callers can
1650
+ * share a single record schema.
1651
+ */
1652
+ async getPaymentById(db, id) {
1653
+ if (id.startsWith("spay_")) {
1654
+ const result = await db.execute(sql `
1655
+ SELECT
1656
+ 'supplier'::text AS kind,
1657
+ sp.id AS id,
1658
+ NULL::text AS invoice_id,
1659
+ NULL::text AS invoice_number,
1660
+ sp.booking_id AS booking_id,
1661
+ b.booking_number AS booking_number,
1662
+ sp.supplier_id AS supplier_id,
1663
+ s.name AS supplier_name,
1664
+ NULL::text AS person_id,
1665
+ NULL::text AS person_first_name,
1666
+ NULL::text AS person_last_name,
1667
+ NULL::text AS organization_id,
1668
+ NULL::text AS organization_name,
1669
+ sp.amount_cents AS amount_cents,
1670
+ sp.currency AS currency,
1671
+ sp.base_currency AS base_currency,
1672
+ sp.base_amount_cents AS base_amount_cents,
1673
+ sp.payment_method::text AS payment_method,
1674
+ sp.status::text AS status,
1675
+ sp.reference_number AS reference_number,
1676
+ sp.payment_date AS payment_date,
1677
+ sp.notes AS notes,
1678
+ sp.created_at AS created_at,
1679
+ sp.updated_at AS updated_at
1680
+ FROM supplier_payments sp
1681
+ LEFT JOIN bookings b ON b.id = sp.booking_id
1682
+ LEFT JOIN suppliers s ON s.id = sp.supplier_id
1683
+ WHERE sp.id = ${id}
1684
+ LIMIT 1
1685
+ `);
1686
+ const row = result[0];
1687
+ return row ? mapRawPayment(row) : null;
1688
+ }
1689
+ const result = await db.execute(sql `
1690
+ SELECT
1691
+ 'customer'::text AS kind,
1692
+ p.id AS id,
1693
+ p.invoice_id AS invoice_id,
1694
+ i.invoice_number AS invoice_number,
1695
+ NULL::text AS booking_id,
1696
+ NULL::text AS booking_number,
1697
+ NULL::text AS supplier_id,
1698
+ NULL::text AS supplier_name,
1699
+ i.person_id AS person_id,
1700
+ pe.first_name AS person_first_name,
1701
+ pe.last_name AS person_last_name,
1702
+ i.organization_id AS organization_id,
1703
+ o.name AS organization_name,
1704
+ p.amount_cents AS amount_cents,
1705
+ p.currency AS currency,
1706
+ p.base_currency AS base_currency,
1707
+ p.base_amount_cents AS base_amount_cents,
1708
+ p.payment_method::text AS payment_method,
1709
+ p.status::text AS status,
1710
+ p.reference_number AS reference_number,
1711
+ p.payment_date AS payment_date,
1712
+ p.notes AS notes,
1713
+ p.created_at AS created_at,
1714
+ p.updated_at AS updated_at
1715
+ FROM payments p
1716
+ LEFT JOIN invoices i ON i.id = p.invoice_id
1717
+ LEFT JOIN people pe ON pe.id = i.person_id
1718
+ LEFT JOIN organizations o ON o.id = i.organization_id
1719
+ WHERE p.id = ${id}
1720
+ LIMIT 1
1721
+ `);
1722
+ const row = result[0];
1723
+ return row ? mapRawPayment(row) : null;
1724
+ },
1406
1725
  async createPayment(db, invoiceId, data) {
1407
1726
  const [invoice] = await db.select().from(invoices).where(eq(invoices.id, invoiceId)).limit(1);
1408
1727
  if (!invoice) {
@@ -157,6 +157,20 @@ export declare const updateInvoiceSchema: z.ZodObject<{
157
157
  dueDate: z.ZodOptional<z.ZodString>;
158
158
  notes: z.ZodOptional<z.ZodNullable<z.ZodOptional<z.ZodString>>>;
159
159
  }, z.core.$strip>;
160
+ export declare const invoiceListSortFieldSchema: z.ZodEnum<{
161
+ createdAt: "createdAt";
162
+ status: "status";
163
+ issueDate: "issueDate";
164
+ invoiceNumber: "invoiceNumber";
165
+ totalCents: "totalCents";
166
+ paidCents: "paidCents";
167
+ balanceDueCents: "balanceDueCents";
168
+ dueDate: "dueDate";
169
+ }>;
170
+ export declare const invoiceListSortDirSchema: z.ZodEnum<{
171
+ asc: "asc";
172
+ desc: "desc";
173
+ }>;
160
174
  export declare const invoiceListQuerySchema: z.ZodObject<{
161
175
  status: z.ZodOptional<z.ZodEnum<{
162
176
  void: "void";
@@ -167,7 +181,26 @@ export declare const invoiceListQuerySchema: z.ZodObject<{
167
181
  overdue: "overdue";
168
182
  }>>;
169
183
  bookingId: z.ZodOptional<z.ZodString>;
184
+ personId: z.ZodOptional<z.ZodString>;
185
+ organizationId: z.ZodOptional<z.ZodString>;
186
+ currency: z.ZodOptional<z.ZodString>;
187
+ dueDateFrom: z.ZodOptional<z.ZodString>;
188
+ dueDateTo: z.ZodOptional<z.ZodString>;
170
189
  search: z.ZodOptional<z.ZodString>;
190
+ sortBy: z.ZodDefault<z.ZodEnum<{
191
+ createdAt: "createdAt";
192
+ status: "status";
193
+ issueDate: "issueDate";
194
+ invoiceNumber: "invoiceNumber";
195
+ totalCents: "totalCents";
196
+ paidCents: "paidCents";
197
+ balanceDueCents: "balanceDueCents";
198
+ dueDate: "dueDate";
199
+ }>>;
200
+ sortDir: z.ZodDefault<z.ZodEnum<{
201
+ asc: "asc";
202
+ desc: "desc";
203
+ }>>;
171
204
  limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
172
205
  offset: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
173
206
  }, z.core.$strip>;
@@ -1 +1 @@
1
- {"version":3,"file":"validation-billing.d.ts","sourceRoot":"","sources":["../src/validation-billing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA0BvB,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;iBAAyC,CAAA;AAepF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAkC,CAAA;AAChF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA4C,CAAA;AA4B1F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAoB,CAAA;AACpD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8B,CAAA;AAC9D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;iBAMjC,CAAA;AACF,eAAO,MAAM,wBAAwB;;;;;;;;;;iBAYnC,CAAA;AAYF,eAAO,MAAM,2BAA2B;;;;;;;;iBAAqB,CAAA;AAC7D,eAAO,MAAM,2BAA2B;;;;;;;;iBAA+B,CAAA;AAcvE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBAAuB,CAAA;AAC1D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;iBAAiC,CAAA;AAUpE,eAAO,MAAM,8BAA8B;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;iBAAyC,CAAA;AAEpF,eAAO,MAAM,uBAAuB;;iBAElC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;iBAA+D,CAAA;AACpG,eAAO,MAAM,sBAAsB;;iBAA4C,CAAA;AAC/E,eAAO,MAAM,wBAAwB;;;iBAGnC,CAAA;AAgBF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;iBAAgC,CAAA;AAC5E,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;iBAA0C,CAAA;AACtF,eAAO,MAAM,kCAAkC;;;;;;;;;iBAG7C,CAAA;AACF,eAAO,MAAM,gCAAgC;;iBAA4C,CAAA;AAmBzF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;iBAA4B,CAAA;AACpE,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;iBAAsC,CAAA;AAC9E,eAAO,MAAM,8BAA8B;;;;;;;iBAKzC,CAAA;AAgBF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAA;AAsBhF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;iBAAsB,CAAA;AACxD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;iBAAgC,CAAA;AAClE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;iBAInC,CAAA;AAeF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAAqB,CAAA;AACtD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAA+B,CAAA;AAChE,eAAO,MAAM,uBAAuB;;;;;iBAGlC,CAAA;AAWF,eAAO,MAAM,4BAA4B;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;iBAAuC,CAAA;AAChF,eAAO,MAAM,+BAA+B;;;;;;iBAI1C,CAAA;AAaF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;iBAA0B,CAAA;AAChE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;iBAAoC,CAAA;AAC1E,eAAO,MAAM,4BAA4B;;;;;;;;;iBAIvC,CAAA;AAYF,eAAO,MAAM,8BAA8B;;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;;iBAAyC,CAAA;AAEpF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;iBAO3C,CAAA;AAEF,eAAO,MAAM,2CAA2C;;;;;;;;;;;;;;iBActD,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM9C,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;iBAInC,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;;;;;;iBAE7C,CAAA;AAEF,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmB/C,CAAA;AAEF,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAA;AAC7F,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAA;AACjG,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAA;AACzF,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAA"}
1
+ {"version":3,"file":"validation-billing.d.ts","sourceRoot":"","sources":["../src/validation-billing.ts"],"names":[],"mappings":"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"}
@@ -55,10 +55,28 @@ const invoiceCoreSchema = z.object({
55
55
  });
56
56
  export const insertInvoiceSchema = invoiceCoreSchema;
57
57
  export const updateInvoiceSchema = invoiceCoreSchema.partial();
58
+ export const invoiceListSortFieldSchema = z.enum([
59
+ "invoiceNumber",
60
+ "status",
61
+ "totalCents",
62
+ "paidCents",
63
+ "balanceDueCents",
64
+ "issueDate",
65
+ "dueDate",
66
+ "createdAt",
67
+ ]);
68
+ export const invoiceListSortDirSchema = z.enum(["asc", "desc"]);
58
69
  export const invoiceListQuerySchema = z.object({
59
70
  status: invoiceStatusSchema.optional(),
60
71
  bookingId: z.string().optional(),
72
+ personId: z.string().optional(),
73
+ organizationId: z.string().optional(),
74
+ currency: z.string().optional(),
75
+ dueDateFrom: z.string().optional(),
76
+ dueDateTo: z.string().optional(),
61
77
  search: z.string().optional(),
78
+ sortBy: invoiceListSortFieldSchema.default("createdAt"),
79
+ sortDir: invoiceListSortDirSchema.default("desc"),
62
80
  limit: z.coerce.number().int().min(1).max(100).default(50),
63
81
  offset: z.coerce.number().int().min(0).default(0),
64
82
  });