feat(sms): implement SMS messaging and metered billing
CI / Frontend (push) Successful in 9m50s
CI / Go - apps/auth-service (push) Failing after 4s
CI / Go - apps/backend (push) Successful in 10m18s
CI / Docker publish - auth-service (push) Has been skipped
CI / Docker publish - backend (push) Has been skipped

Implement a complete SMS messaging system including:
- Integration with SMS Manager.cz API for sending messages.
- Metered billing via Stripe using monthly aggregate invoice items.
- Backend services for managing SMS settings, usage logging, and monthly reporting.
- Database migrations for tenant settings, usage logs, and monthly reports.
- Frontend dashboard components for SMS configuration, usage tracking, and history.
- Support for customer phone numbers in the booking flow.

Includes new migrations, backend services, and frontend UI components.
This commit is contained in:
Tomas Dvorak
2026-05-10 11:40:53 +02:00
parent 164a37e997
commit 7d3e3448cf
28 changed files with 3633 additions and 3190 deletions
+47
View File
@@ -0,0 +1,47 @@
-- +goose Up
CREATE TABLE IF NOT EXISTS tenant_sms_settings (
tenant_id uuid PRIMARY KEY REFERENCES tenants(id) ON DELETE CASCADE,
enabled boolean NOT NULL DEFAULT false,
sender_name text NOT NULL DEFAULT '',
monthly_limit integer,
stripe_subscription_item_id text,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sms_usage_logs (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
recipient_phone text NOT NULL,
message_body text NOT NULL,
external_message_id text,
external_request_id text,
status text NOT NULL DEFAULT 'pending',
cost_cents integer NOT NULL DEFAULT 150,
sent_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS sms_monthly_reports (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
year_month text NOT NULL,
message_count integer NOT NULL DEFAULT 0,
total_cost_cents integer NOT NULL DEFAULT 0,
stripe_invoice_id text,
invoice_sent_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (tenant_id, year_month)
);
CREATE INDEX IF NOT EXISTS idx_sms_usage_tenant_month ON sms_usage_logs (tenant_id, date_trunc('month', created_at));
CREATE INDEX IF NOT EXISTS idx_sms_usage_tenant_created ON sms_usage_logs (tenant_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_sms_reports_tenant ON sms_monthly_reports (tenant_id, year_month DESC);
-- +goose Down
DROP INDEX IF EXISTS idx_sms_reports_tenant;
DROP INDEX IF EXISTS idx_sms_usage_tenant_created;
DROP INDEX IF EXISTS idx_sms_usage_tenant_month;
DROP TABLE IF EXISTS sms_monthly_reports;
DROP TABLE IF EXISTS sms_usage_logs;
DROP TABLE IF EXISTS tenant_sms_settings;
@@ -0,0 +1,5 @@
-- +goose Up
ALTER TABLE bookings ADD COLUMN IF NOT EXISTS customer_phone text;
-- +goose Down
ALTER TABLE bookings DROP COLUMN IF EXISTS customer_phone;