@go-labs-sg/bb 2.18.0 → 2.19.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/commands.js CHANGED
@@ -35,16 +35,35 @@ const getAllNotifications = async () => {
35
35
  } while (cursor);
36
36
  return notifications;
37
37
  };
38
- const createApprovalEmailDeliveryReport = ({ sentCount, skippedCount, message, }) => ({
39
- sent: sentCount > 0,
40
- count: sentCount,
41
- sentCount,
42
- skippedCount,
43
- message,
44
- });
38
+ const createApprovalEmailDeliveryReport = (delivery) => {
39
+ if (!delivery) {
40
+ return {
41
+ queued: false,
42
+ sent: false,
43
+ count: 0,
44
+ queuedCount: 0,
45
+ sentCount: 0,
46
+ skippedCount: 0,
47
+ error: "No approval email delivery was queued",
48
+ };
49
+ }
50
+ const { queuedCount, sentCount, skippedCount, message, operationIds } = delivery;
51
+ return {
52
+ queued: queuedCount > 0,
53
+ sent: false,
54
+ count: queuedCount,
55
+ queuedCount,
56
+ sentCount,
57
+ skippedCount,
58
+ operationIds,
59
+ message,
60
+ };
61
+ };
45
62
  const createApprovalEmailDeliveryFailure = (error) => ({
63
+ queued: false,
46
64
  sent: false,
47
65
  count: 0,
66
+ queuedCount: 0,
48
67
  sentCount: 0,
49
68
  skippedCount: 0,
50
69
  error,
@@ -533,16 +552,11 @@ export async function approveBill(billId) {
533
552
  }
534
553
  let email;
535
554
  try {
536
- await api.email.sendReplyBillApprovalEmail.mutate({
537
- id: result.updatedApproval.id,
538
- });
539
- email = { sent: true };
555
+ const delivery = result.emailDelivery;
556
+ email = createApprovalEmailDeliveryReport(delivery);
540
557
  }
541
558
  catch (error) {
542
- email = {
543
- sent: false,
544
- error: error instanceof Error ? error.message : String(error),
545
- };
559
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
546
560
  }
547
561
  out({
548
562
  ...result,
@@ -629,7 +643,7 @@ export async function createBillApproval(billId) {
629
643
  }
630
644
  else {
631
645
  try {
632
- const delivery = await api.email.sendBillApprovalRequestEmail.mutate(approvalIds);
646
+ const delivery = result.emailDelivery;
633
647
  email = createApprovalEmailDeliveryReport(delivery);
634
648
  }
635
649
  catch (error) {
@@ -1078,7 +1092,7 @@ export async function createBudgetApproval(budgetId, preflight) {
1078
1092
  }
1079
1093
  else {
1080
1094
  try {
1081
- const delivery = await api.email.sendApprovalRequestEmail.mutate(approvalIds);
1095
+ const delivery = result.emailDelivery;
1082
1096
  email = createApprovalEmailDeliveryReport(delivery);
1083
1097
  }
1084
1098
  catch (error) {
@@ -1488,7 +1502,7 @@ export async function createSupplierFromPayload(raw) {
1488
1502
  }
1489
1503
  else {
1490
1504
  try {
1491
- const delivery = await api.email.sendSupplierApprovalRequestEmail.mutate(approvalIds);
1505
+ const delivery = approval.emailDelivery;
1492
1506
  emailResult = createApprovalEmailDeliveryReport(delivery);
1493
1507
  }
1494
1508
  catch (error) {
@@ -1534,7 +1548,7 @@ export async function updateSupplierFromPayload(raw) {
1534
1548
  }
1535
1549
  else {
1536
1550
  try {
1537
- const delivery = await api.email.sendSupplierApprovalRequestEmail.mutate(approvalIds);
1551
+ const delivery = approval.emailDelivery;
1538
1552
  approvalResult = {
1539
1553
  requested: true,
1540
1554
  approvalCount: approvalIds.length,
@@ -1614,16 +1628,11 @@ export async function approveBudget(budgetId) {
1614
1628
  });
1615
1629
  let email;
1616
1630
  try {
1617
- await api.email.sendReplyApprovalEmail.mutate({
1618
- id: result.updatedApproval.id,
1619
- });
1620
- email = { sent: true };
1631
+ const delivery = result.emailDelivery;
1632
+ email = createApprovalEmailDeliveryReport(delivery);
1621
1633
  }
1622
1634
  catch (error) {
1623
- email = {
1624
- sent: false,
1625
- error: error instanceof Error ? error.message : String(error),
1626
- };
1635
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
1627
1636
  }
1628
1637
  out({
1629
1638
  ...result,
@@ -1653,16 +1662,11 @@ export async function rejectBudget(budgetId, reason) {
1653
1662
  });
1654
1663
  let email;
1655
1664
  try {
1656
- await api.email.sendReplyApprovalEmail.mutate({
1657
- id: result.updatedApproval.id,
1658
- });
1659
- email = { sent: true };
1665
+ const delivery = result.emailDelivery;
1666
+ email = createApprovalEmailDeliveryReport(delivery);
1660
1667
  }
1661
1668
  catch (error) {
1662
- email = {
1663
- sent: false,
1664
- error: error instanceof Error ? error.message : String(error),
1665
- };
1669
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
1666
1670
  }
1667
1671
  out({
1668
1672
  ...result,
@@ -1751,16 +1755,11 @@ export async function approveSupplier(supplierId) {
1751
1755
  });
1752
1756
  let email;
1753
1757
  try {
1754
- await api.email.sendReplySupplierApprovalEmail.mutate({
1755
- id: result.updatedApproval.id,
1756
- });
1757
- email = { sent: true };
1758
+ const delivery = result.emailDelivery;
1759
+ email = createApprovalEmailDeliveryReport(delivery);
1758
1760
  }
1759
1761
  catch (error) {
1760
- email = {
1761
- sent: false,
1762
- error: error instanceof Error ? error.message : String(error),
1763
- };
1762
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
1764
1763
  }
1765
1764
  out({
1766
1765
  ...result,
@@ -1789,16 +1788,11 @@ export async function rejectSupplier(supplierId, reason) {
1789
1788
  });
1790
1789
  let email;
1791
1790
  try {
1792
- await api.email.sendReplySupplierApprovalEmail.mutate({
1793
- id: result.updatedApproval.id,
1794
- });
1795
- email = { sent: true };
1791
+ const delivery = result.emailDelivery;
1792
+ email = createApprovalEmailDeliveryReport(delivery);
1796
1793
  }
1797
1794
  catch (error) {
1798
- email = {
1799
- sent: false,
1800
- error: error instanceof Error ? error.message : String(error),
1801
- };
1795
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
1802
1796
  }
1803
1797
  out({
1804
1798
  ...result,
@@ -1831,16 +1825,11 @@ export async function rejectBill(billId, reason) {
1831
1825
  }
1832
1826
  let email;
1833
1827
  try {
1834
- await api.email.sendReplyBillApprovalEmail.mutate({
1835
- id: result.updatedApproval.id,
1836
- });
1837
- email = { sent: true };
1828
+ const delivery = result.emailDelivery;
1829
+ email = createApprovalEmailDeliveryReport(delivery);
1838
1830
  }
1839
1831
  catch (error) {
1840
- email = {
1841
- sent: false,
1842
- error: error instanceof Error ? error.message : String(error),
1843
- };
1832
+ email = createApprovalEmailDeliveryFailure(error instanceof Error ? error.message : String(error));
1844
1833
  }
1845
1834
  out({
1846
1835
  ...result,
package/dist/index.js CHANGED
@@ -176,7 +176,7 @@ Budgets
176
176
  create-budget --payload '<json>' (budget.createBudget; when sourceBudgetId contains unavailable items, set unavailableItemReviewAcknowledged=true after explicit review)
177
177
  update-budget --payload '<json>' (budget.updateBudget; must include id)
178
178
  delete-budget <budgetId>
179
- create-budget-approval <budgetId> (also sends approval request emails)
179
+ create-budget-approval <budgetId> (also queues approval request emails)
180
180
  create-estimate <budgetId> (creates QuickBooks estimate; supports preflight updates)
181
181
  send-estimate-to-contact-person --payload '<json>' Send using the web contact-person workflow; payload includes recipient fields plus HTML content/signature.
182
182
  add-budget-items --budgetId --items '[{"itemId":"…","quantity":1,"markup":30},…]'
@@ -203,7 +203,7 @@ Bills
203
203
  list-claims same flags as list-bills; only reimbursable claims (ignores --isClaimable)
204
204
  isClaimable differentiates the shared bill/claim records: false = bill, true = claim.
205
205
  Non-legacy supplier bills from 1 Jul 2026 00:00 SGT require approved quotation coverage linked to every selected line item, independent of the bill supplier, including already-paid bills.
206
- create-bill-approval <billId> (also sends approval request emails)
206
+ create-bill-approval <billId> (also queues approval request emails)
207
207
  create-bill --payload '<json>' (bill.create; payload.isClaimable false = bill, true = claim)
208
208
  validate-bill-selection --payload '<json>' Check project and supplier validity separately, then verify approved quotation links for each budgetItemId; alreadyPaid never bypasses quotation checks.
209
209
  stage-bill-attachment <projectId> <filePath...> [--file <path>] [--files <csv>] Upload files before create-bill; returns attachment JSON for attachments/paymentProofAttachments
@@ -251,7 +251,7 @@ Customer invoices
251
251
  void-customer-invoice <batchId> Void the invoice batch in QuickBooks.
252
252
  approve-customer-invoice <batchId> Admin approval; rejects voided invoices, notifies the creator, and closes the estimate at cumulative 100% coverage.
253
253
  reject-customer-invoice <batchId> --reason <text> Admin rejection; voids QBO invoices and notifies the creator.
254
- send-customer-invoice-to-contact-person --payload '<json>' Same composer workflow as web; requires invoiceId, to, cc, replyTo, subject, HTML content, and HTML signature.
254
+ send-customer-invoice-to-contact-person --payload '<json>' Queues same composer workflow as web; requires invoiceId, to, cc, replyTo, subject, HTML content, and HTML signature.
255
255
  download-customer-invoice-pdf <invoiceId> [--output <path>]
256
256
  sync-customer-invoice <invoiceId> Refresh local status and balance from QuickBooks; paid invoices become PAID, reversals restore delivery/approval, and QBO voids can reopen an estimate.
257
257
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/bb",
3
- "version": "2.18.0",
3
+ "version": "2.19.0",
4
4
  "description": "Budget Builder CLI for AI agents — manage budgets, bills, claims, quotations, and customer invoices with explicit workflow previews for sensitive changes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",