@arcforgelabs/flow 2026.10.47 → 2026.10.48-1

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 (39) hide show
  1. package/README.md +1 -0
  2. package/npm-shrinkwrap.json +11 -11
  3. package/package.json +1 -1
  4. package/server/api/invoicing.js +35 -8
  5. package/server/core/contacts.js +160 -0
  6. package/server/core/directory.js +4 -9
  7. package/server/core/invoices.js +84 -31
  8. package/server/core/sending.js +65 -3
  9. package/server/db/doctor.js +1 -1
  10. package/server/db/index.js +19 -0
  11. package/server/db/migrations/0021_flow_schema.sql +68 -0
  12. package/server/db/migrations/0022_contacts.sql +11 -0
  13. package/server/db/migrations/meta/0021_snapshot.json +4377 -0
  14. package/server/db/migrations/meta/0022_snapshot.json +4446 -0
  15. package/server/db/migrations/meta/_journal.json +14 -0
  16. package/server/db/schema.js +15 -0
  17. package/server/integrations/port.js +2 -0
  18. package/server/integrations/schema.js +3 -2
  19. package/server/integrations/seazona/sweep.js +11 -8
  20. package/server/integrations/setup.js +1 -0
  21. package/server/integrations/xero/catalogue.js +82 -14
  22. package/server/integrations/xero/client.js +37 -0
  23. package/server/integrations/xero/create-contact.js +126 -0
  24. package/server/integrations/xero/delete-invoice.js +104 -0
  25. package/server/integrations/xero/drafts.js +19 -8
  26. package/server/integrations/xero/index.js +9 -0
  27. package/server/integrations/xero/migrations/0011_xero_invoice_deleted.sql +11 -0
  28. package/server/integrations/xero/migrations/0012_xero_contact_details.sql +16 -0
  29. package/server/integrations/xero/migrations/meta/_journal.json +14 -0
  30. package/server/integrations/xero/routes.js +21 -0
  31. package/server/integrations/xero/settings.js +3 -0
  32. package/server/ui/app.js +8 -3
  33. package/server/ui/contacts.js +260 -0
  34. package/server/ui/flow.css +40 -0
  35. package/server/ui/invoicing.js +159 -54
  36. package/server/ui/kit.js +28 -8
  37. package/server/ui/mobile.js +6 -3
  38. package/server/ui/nav-pins.js +5 -2
  39. package/server/ui/routes.js +1 -1
@@ -0,0 +1,68 @@
1
+ -- Flow's tables move from "public" to their own schema, "flow" (issue: Replit's
2
+ -- publish compares the workspace's "public" schema with production's and
3
+ -- offers to make production match, deletes included; docs/REPLIT.md, "The
4
+ -- workspace database"). Every connection searches "flow" first
5
+ -- (server/db/index.js, FLOW_SEARCH_PATH), so queries keep their table names.
6
+ -- The adapters' tables move too, when they exist; an adapter turned on later
7
+ -- creates its tables in "flow". It runs again without harm.
8
+ DO $flow_guard$
9
+ DECLARE
10
+ t text;
11
+ BEGIN
12
+ CREATE SCHEMA IF NOT EXISTS flow;
13
+ FOREACH t IN ARRAY ARRAY[
14
+ 'alert_dismissals', 'automations', 'background_jobs', 'billing_obligations', 'contacts',
15
+ 'customer_billing_settings', 'external_links', 'integration_setting_events', 'integration_settings',
16
+ 'invoice_lines', 'invoice_rules', 'invoice_versions', 'invoices', 'invoicing_settings',
17
+ 'job_field_events', 'job_field_settings', 'job_field_values', 'job_fields', 'line_mappings',
18
+ 'link_rejections', 'link_suggestions', 'obligation_events', 'obligation_payments',
19
+ 'obligation_writebacks', 'organisations', 'outbox', 'people', 'pipeline_cursors',
20
+ 'price_item_links', 'price_items', 'prior_links', 'review_items',
21
+ 'seazona_api_governor', 'seazona_api_requests', 'seazona_clients', 'seazona_history_batch_jobs',
22
+ 'seazona_history_batches', 'seazona_history_jobs', 'seazona_history_rows', 'seazona_invoices',
23
+ 'seazona_lane_state', 'seazona_order_read_failures', 'seazona_orders', 'seazona_person_settings',
24
+ 'seazona_record_read_failures', 'seazona_reference', 'seazona_stage_moves', 'seazona_sweep_findings',
25
+ 'xero_call_guard', 'xero_calls', 'xero_connections', 'xero_contacts', 'xero_credit_notes',
26
+ 'xero_daily_checks', 'xero_import_settings', 'xero_invoice_links', 'xero_invoice_pushes',
27
+ 'xero_invoices', 'xero_items', 'xero_mirror_cursors', 'xero_payment_cursors', 'xero_payments',
28
+ 'xero_sync_runs', 'xero_webhook_events'
29
+ ] LOOP
30
+ IF to_regclass(format('public.%I', t)) IS NOT NULL AND to_regclass(format('flow.%I', t)) IS NULL THEN
31
+ EXECUTE format('ALTER TABLE public.%I SET SCHEMA flow', t);
32
+ END IF;
33
+ END LOOP;
34
+ FOREACH t IN ARRAY ARRAY['flow_refuse_change', 'flow_invoice_lines_draft_only', 'flow_invoice_rules'] LOOP
35
+ IF to_regprocedure(format('public.%I()', t)) IS NOT NULL AND to_regprocedure(format('flow.%I()', t)) IS NULL THEN
36
+ EXECUTE format('ALTER FUNCTION public.%I() SET SCHEMA flow', t);
37
+ END IF;
38
+ -- The trigger functions name tables without a schema.
39
+ IF to_regprocedure(format('flow.%I()', t)) IS NOT NULL THEN
40
+ EXECUTE format('ALTER FUNCTION flow.%I() SET search_path = flow, public', t);
41
+ END IF;
42
+ END LOOP;
43
+ -- New sessions, a pooler's included, search "flow" first: a transaction
44
+ -- pooler does not keep a session's SET. Flow's role sets it for itself, and
45
+ -- the database too when Flow owns it; Flow's own connections set it anyway.
46
+ BEGIN
47
+ EXECUTE format('ALTER ROLE %I IN DATABASE %I SET search_path TO flow, public', current_user, current_database());
48
+ EXCEPTION WHEN insufficient_privilege THEN
49
+ RAISE NOTICE 'flow: this role cannot set its own search_path; Flow sets its own';
50
+ END;
51
+ BEGIN
52
+ EXECUTE format('ALTER DATABASE %I SET search_path TO flow, public', current_database());
53
+ EXCEPTION WHEN insufficient_privilege THEN
54
+ RAISE NOTICE 'flow: not the database owner, so its default search_path stays; Flow sets its own';
55
+ END;
56
+ -- A pooler keeps the server sessions it opened before this move, with the
57
+ -- old search_path, and hands them to new clients. Close the idle ones
58
+ -- of this role: the pooler opens new ones, which take the setting above.
59
+ BEGIN
60
+ PERFORM pg_terminate_backend(a.pid) FROM pg_stat_activity a
61
+ WHERE a.datname = current_database() AND a.usename = current_user
62
+ AND a.pid <> pg_backend_pid() AND a.state = 'idle' AND a.backend_type = 'client backend';
63
+ EXCEPTION WHEN others THEN
64
+ RAISE NOTICE 'flow: could not close the idle sessions; a pooler''s open sessions keep the old search_path until they close';
65
+ END;
66
+ -- This session too: the migrations after this one create their tables in "flow".
67
+ PERFORM set_config('search_path', 'flow, public', false);
68
+ END $flow_guard$;
@@ -0,0 +1,11 @@
1
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "first_name" text;--> statement-breakpoint
2
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "last_name" text;--> statement-breakpoint
3
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "phone" text;--> statement-breakpoint
4
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "mobile" text;--> statement-breakpoint
5
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "account_number" text;--> statement-breakpoint
6
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "tax_number" text;--> statement-breakpoint
7
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "tax_rate" text;--> statement-breakpoint
8
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "address" jsonb;--> statement-breakpoint
9
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "practitioners" jsonb DEFAULT '[]'::jsonb NOT NULL;--> statement-breakpoint
10
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "active" boolean DEFAULT true NOT NULL;--> statement-breakpoint
11
+ ALTER TABLE "contacts" ADD COLUMN IF NOT EXISTS "updated_at" timestamp with time zone DEFAULT now() NOT NULL;