@arcforgelabs/flow 2026.10.32 → 2026.10.33

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.
Files changed (42) hide show
  1. package/README.md +3 -1
  2. package/npm-shrinkwrap.json +2 -2
  3. package/package.json +2 -1
  4. package/server/api/invoicing.js +56 -24
  5. package/server/app.js +4 -0
  6. package/server/core/invoicing-rules.js +50 -4
  7. package/server/core/job-board.js +15 -4
  8. package/server/core/ledger.js +242 -6
  9. package/server/core/pipeline.js +29 -21
  10. package/server/core/read-before-act.js +96 -0
  11. package/server/core/reconcile.js +350 -0
  12. package/server/core/sending.js +44 -6
  13. package/server/db/migrations/0017_sync_basis.sql +1 -0
  14. package/server/db/migrations/meta/0017_snapshot.json +3867 -0
  15. package/server/db/migrations/meta/_journal.json +7 -0
  16. package/server/db/schema.js +3 -0
  17. package/server/index.js +5 -0
  18. package/server/integrations/port.js +3 -0
  19. package/server/integrations/seazona/act.js +48 -0
  20. package/server/integrations/seazona/feed.js +70 -50
  21. package/server/integrations/seazona/governor.js +28 -2
  22. package/server/integrations/seazona/index.js +60 -3
  23. package/server/integrations/seazona/lanes.js +81 -8
  24. package/server/integrations/seazona/ledger.js +14 -9
  25. package/server/integrations/seazona/migrations/0005_record_reread.sql +1 -0
  26. package/server/integrations/seazona/migrations/0006_sweep_findings.sql +11 -0
  27. package/server/integrations/seazona/migrations/meta/0005_snapshot.json +1329 -0
  28. package/server/integrations/seazona/migrations/meta/0006_snapshot.json +1403 -0
  29. package/server/integrations/seazona/migrations/meta/_journal.json +14 -0
  30. package/server/integrations/seazona/reconcile.js +40 -0
  31. package/server/integrations/seazona/scheduler.js +32 -4
  32. package/server/integrations/seazona/schema.js +21 -0
  33. package/server/integrations/seazona/settings.js +12 -0
  34. package/server/integrations/seazona/store.js +24 -2
  35. package/server/integrations/seazona/sweep.js +574 -0
  36. package/server/integrations/seazona/tables.js +1 -0
  37. package/server/integrations/xero/index.js +4 -0
  38. package/server/integrations/xero/webhooks.js +35 -0
  39. package/server/ui/flow.css +9 -0
  40. package/server/ui/invoicing.js +101 -17
  41. package/server/ui/job-board.js +2 -1
  42. package/server/ui/jobs.js +19 -1
@@ -2,8 +2,8 @@
2
2
  // issue #3). The adapter does not import the ledger: the core reads the
3
3
  // billing feed and passes these shapes to it.
4
4
  //
5
- // item.ledgerJob -> observeJob(db, organisationId, { ...item.ledgerJob, contactId })
6
- // withdrawn.ledgerHold -> setHold(db, organisationId, <obligation id>, { ...ledgerHold, actor })
5
+ // item.ledgerJob -> observeJob(db, organisationId, { ...item.ledgerJob, contactId })
6
+ // withdrawn.ledgerWithdrawn -> observeWithdrawn(db, organisationId, withdrawn.ledgerWithdrawn)
7
7
  //
8
8
  // One Seazona order is one billable job. The contact is Flow's, so the core
9
9
  // resolves it (from item.client) and adds contactId; the ledger keeps a job
@@ -56,15 +56,20 @@ export function toLedgerJob(item) {
56
56
  };
57
57
  }
58
58
 
59
- // An order deleted in Seazona sends its obligation, if there is one, to
60
- // review: a person decides what happens to any invoice already made. An order
61
- // that only stopped being billable needs nothing from the ledger.
62
- export function toLedgerHold(entry) {
63
- if (entry.reason !== 'deleted_in_seazona') return null;
59
+ // observeWithdrawn's input for an order that is no longer billable. An
60
+ // order deleted in Seazona sends its obligation, if there is one, to review:
61
+ // a person decides what happens to any invoice already made. An order whose
62
+ // status moved back (for example from Shipped to In Production) loses an
63
+ // unsent ready mark, and goes to review when its invoice was made.
64
+ export function toLedgerWithdrawn(entry) {
65
+ const deleted = entry.reason === 'deleted_in_seazona';
64
66
  return {
65
67
  sourceSystem: SEAZONA_SOURCE_SYSTEM,
66
68
  sourceJobRef: entry.sourceId,
67
- holdState: 'review',
68
- reason: 'the order was deleted in Seazona',
69
+ sourceStatus: entry.status ?? null,
70
+ deleted,
71
+ reason: deleted ? 'the order was deleted in Seazona' : null,
72
+ observedAt: entry.syncedAt ?? null,
73
+ actor: `system:${SEAZONA_SOURCE_SYSTEM}`,
69
74
  };
70
75
  }
@@ -0,0 +1 @@
1
+ ALTER TABLE "seazona_record_read_failures" ADD COLUMN IF NOT EXISTS "detail_id" text;
@@ -0,0 +1,11 @@
1
+ CREATE TABLE IF NOT EXISTS "seazona_sweep_findings" (
2
+ "resource" text NOT NULL,
3
+ "record_key" text NOT NULL,
4
+ "kind" text NOT NULL,
5
+ "first_found_at" timestamp with time zone NOT NULL,
6
+ "last_found_at" timestamp with time zone NOT NULL,
7
+ "detail" jsonb,
8
+ CONSTRAINT "seazona_sweep_findings_resource_record_key_kind_pk" PRIMARY KEY("resource","record_key","kind")
9
+ );
10
+ --> statement-breakpoint
11
+ CREATE INDEX IF NOT EXISTS "seazona_sweep_findings_found" ON "seazona_sweep_findings" USING btree ("last_found_at");