diff --git a/app/auth/update-account/_lib/server/update-account.ts b/app/auth/update-account/_lib/server/update-account.ts
index 9de3586..a7a424a 100644
--- a/app/auth/update-account/_lib/server/update-account.ts
+++ b/app/auth/update-account/_lib/server/update-account.ts
@@ -4,22 +4,13 @@ import { redirect } from 'next/navigation';
import { updateCustomer } from '@lib/data/customer';
+import { AccountSubmitData, createAuthApi } from '@kit/auth/api';
import { enhanceAction } from '@kit/next/actions';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import pathsConfig from '~/config/paths.config';
-export interface AccountSubmitData {
- firstName: string;
- lastName: string;
- personalCode: string;
- email: string;
- phone?: string;
- city?: string;
- weight: number | null;
- height: number | null;
- userConsent: boolean;
-}
+import { UpdateAccountSchema } from '../schemas/update-account.schema';
export const onUpdateAccount = enhanceAction(
async (params: AccountSubmitData) => {
diff --git a/app/home/[account]/billing/error.tsx b/app/home/[account]/billing/error.tsx
deleted file mode 100644
index 974e826..0000000
--- a/app/home/[account]/billing/error.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-'use client';
-
-import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
-
-import { useCaptureException } from '@kit/monitoring/hooks';
-import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
-import { AppBreadcrumbs } from '@kit/ui/app-breadcrumbs';
-import { Button } from '@kit/ui/button';
-import { PageBody, PageHeader } from '@kit/ui/page';
-import { Trans } from '@kit/ui/trans';
-
-export default function BillingErrorPage({
- error,
- reset,
-}: {
- error: Error & { digest?: string };
- reset: () => void;
-}) {
- useCaptureException(error);
-
- return (
- <>
- } />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/packages/features/auth/src/server/api.ts b/packages/features/auth/src/server/api.ts
index 30ae995..6f8ead2 100644
--- a/packages/features/auth/src/server/api.ts
+++ b/packages/features/auth/src/server/api.ts
@@ -2,7 +2,17 @@ import { SupabaseClient } from '@supabase/supabase-js';
import { Database } from '@kit/supabase/database';
-import { AccountSubmitData } from './actions/update-account-actions';
+export interface AccountSubmitData {
+ firstName: string;
+ lastName: string;
+ personalCode: string;
+ email: string;
+ phone?: string;
+ city?: string;
+ weight: number | null;
+ height: number | null;
+ userConsent: boolean;
+}
/**
* Class representing an API for interacting with user accounts.
diff --git a/supabase/migrations/20250812143800_log_company_params.sql b/supabase/migrations/20250812143800_log_company_params.sql
new file mode 100644
index 0000000..4641799
--- /dev/null
+++ b/supabase/migrations/20250812143800_log_company_params.sql
@@ -0,0 +1,189 @@
+CREATE OR REPLACE FUNCTION medreport.insert_company_params_on_new_company()
+RETURNS trigger
+LANGUAGE plpgsql
+AS $function$
+BEGIN
+ IF (TG_OP = 'INSERT' AND NEW.slug IS NOT NULL) THEN
+ INSERT INTO medreport.company_params (
+ account_id,
+ slug,
+ benefit_occurance,
+ benefit_amount
+ ) VALUES (
+ NEW.id,
+ NEW.slug,
+ NULL,
+ NULL
+ );
+ END IF;
+
+ RETURN NEW;
+END;
+$function$
+;
+
+grant execute on function medreport.insert_company_params_on_new_company() to authenticated,
+service_role;
+
+CREATE OR REPLACE FUNCTION log_company_params_changes()
+RETURNS trigger AS $$
+BEGIN
+ -- For INSERT operation
+ IF (TG_OP = 'INSERT') THEN
+ INSERT INTO audit.log_entries (
+ schema_name,
+ table_name,
+ record_key,
+ operation,
+ row_data,
+ changed_data,
+ changed_by,
+ changed_by_role,
+ changed_at
+ )
+ VALUES (
+ 'medreport', -- Schema name
+ 'company_params', -- Table name
+ NEW.id, -- The ID of the inserted row
+ 'INSERT', -- Operation type
+ NULL, -- No old data for INSERT
+ row_to_json(NEW), -- New data (after the INSERT)
+ auth.uid(), -- The user performing the insert
+ SESSION_USER, -- The role performing the insert
+ CURRENT_TIMESTAMP -- Timestamp of the insert
+ );
+ -- For UPDATE operation
+ ELSIF (TG_OP = 'UPDATE') THEN
+ INSERT INTO audit.log_entries (
+ schema_name,
+ table_name,
+ record_key,
+ operation,
+ row_data,
+ changed_data,
+ changed_by,
+ changed_by_role,
+ changed_at
+ )
+ VALUES (
+ 'medreport', -- Schema name
+ 'company_params', -- Table name
+ OLD.id, -- The ID of the updated row
+ 'UPDATE', -- Operation type
+ row_to_json(OLD), -- Old data (before the update)
+ row_to_json(NEW), -- New data (after the update)
+ auth.uid(), -- The user performing the update
+ SESSION_USER, -- The role performing the update
+ CURRENT_TIMESTAMP -- Timestamp of the update
+ );
+ -- For DELETE operation
+ ELSIF (TG_OP = 'DELETE') THEN
+ INSERT INTO audit.log_entries (
+ schema_name,
+ table_name,
+ record_key,
+ operation,
+ row_data,
+ changed_data,
+ changed_by,
+ changed_by_role,
+ changed_at
+ )
+ VALUES (
+ 'medreport', -- Schema name
+ 'company_params', -- Table name
+ OLD.id, -- The ID of the deleted row
+ 'DELETE', -- Operation type
+ row_to_json(OLD), -- Old data (before the delete)
+ NULL, -- No new data for DELETE
+ auth.uid(), -- The user performing the delete
+ SESSION_USER, -- The role performing the delete
+ CURRENT_TIMESTAMP -- Timestamp of the delete
+ );
+ END IF;
+
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER company_params_audit_trigger
+AFTER INSERT OR UPDATE OR DELETE ON medreport.company_params
+FOR EACH ROW
+EXECUTE FUNCTION log_company_params_changes();
+
+create or replace function medreport.create_team_account (
+ account_name text,
+ new_personal_code text
+) returns medreport.accounts
+ security definer
+ set search_path = ''
+as $$
+declare
+ existing_account medreport.accounts;
+ current_user uuid := (select auth.uid())::uuid;
+ new_account medreport.accounts;
+begin
+ if not medreport.is_set('enable_team_accounts') then
+ raise exception 'Team accounts are not enabled';
+ end if;
+
+ -- Try to find existing account
+ select *
+ into existing_account
+ from medreport.accounts
+ where personal_code = new_personal_code
+ limit 1;
+
+ -- If not found, fail
+ if not found then
+ raise exception 'No account found with personal_code = %', new_personal_code;
+ end if;
+
+ insert into medreport.accounts(
+ name,
+ is_personal_account,
+ primary_owner_user_id)
+ values (
+ account_name,
+ false,
+ existing_account.id)
+ returning
+ * into new_account;
+
+ -- Insert membership
+ insert into medreport.accounts_memberships (
+ user_id,
+ account_id,
+ account_role,
+ created_by,
+ updated_by,
+ created_at,
+ updated_at,
+ has_seen_confirmation
+ )
+ values (
+ existing_account.id,
+ new_account.id,
+ 'owner',
+ null,
+ null,
+ now(),
+ now(),
+ false
+ )
+ on conflict do nothing;
+
+ return new_account;
+end;
+$$ language plpgsql;
+
+grant execute on function medreport.create_team_account (text, text) to authenticated, service_role;
+
+ALTER TABLE "medreport"."accounts"
+DROP CONSTRAINT "accounts_primary_owner_user_id_fkey";
+
+ALTER TABLE "medreport"."accounts"
+ADD CONSTRAINT "accounts_primary_owner_user_id_fkey"
+FOREIGN KEY (primary_owner_user_id)
+REFERENCES auth.users(id)
+ON DELETE CASCADE;