diff --git a/app/home/[account]/members/_lib/server/members-page.loader.ts b/app/home/[account]/members/_lib/server/members-page.loader.ts
index 8df60c8..0f0c50e 100644
--- a/app/home/[account]/members/_lib/server/members-page.loader.ts
+++ b/app/home/[account]/members/_lib/server/members-page.loader.ts
@@ -63,7 +63,20 @@ async function loadAccountMembers(
throw error;
}
- return data ?? [];
+ const members = data ?? [];
+
+ return members
+ .sort((prev, next) => {
+ if (prev.primary_owner_user_id === prev.user_id) {
+ return -1;
+ }
+
+ if (prev.role_hierarchy_level < next.role_hierarchy_level) {
+ return -1;
+ }
+
+ return 1;
+ });
}
export async function loadAccountMembersBenefitsUsage(
@@ -73,6 +86,7 @@ export async function loadAccountMembersBenefitsUsage(
{
personal_account_id: string;
benefit_amount: number;
+ benefit_unused_amount: number;
}[]
> {
const { data, error } = await client
@@ -86,7 +100,11 @@ export async function loadAccountMembersBenefitsUsage(
return [];
}
- return data ?? [];
+ return (data ?? []) as unknown as {
+ personal_account_id: string;
+ benefit_amount: number;
+ benefit_unused_amount: number;
+ }[];
}
/**
diff --git a/packages/features/team-accounts/src/components/members/account-members-table.tsx b/packages/features/team-accounts/src/components/members/account-members-table.tsx
index d1fbcac..d345ff7 100644
--- a/packages/features/team-accounts/src/components/members/account-members-table.tsx
+++ b/packages/features/team-accounts/src/components/members/account-members-table.tsx
@@ -46,6 +46,7 @@ type AccountMembersTableProps = {
membersBenefitsUsage: {
personal_account_id: string;
benefit_amount: number;
+ benefit_unused_amount: number;
}[];
};
@@ -82,33 +83,23 @@ export function AccountMembersTable({
membersBenefitsUsage,
});
- const filteredMembers = members
- .filter((member) => {
- const searchString = search.toLowerCase();
+ const searchString = search.toLowerCase();
+ const filteredMembers = searchString.length > 0
+ ? members
+ .filter((member) => {
+ const displayName = (
+ member.name ??
+ member.email.split('@')[0] ??
+ ''
+ ).toLowerCase();
- const displayName = (
- member.name ??
- member.email.split('@')[0] ??
- ''
- ).toLowerCase();
-
- return (
- displayName.includes(searchString) ||
- member.role.toLowerCase().includes(searchString) ||
- (member.personal_code || '').includes(searchString)
- );
- })
- .sort((prev, next) => {
- if (prev.primary_owner_user_id === prev.user_id) {
- return -1;
- }
-
- if (prev.role_hierarchy_level < next.role_hierarchy_level) {
- return -1;
- }
-
- return 1;
- });
+ return (
+ displayName.includes(searchString) ||
+ member.role.toLowerCase().includes(searchString) ||
+ (member.personal_code || '').includes(searchString)
+ );
+ })
+ : members;
return (
@@ -132,6 +123,7 @@ function useGetColumns(
membersBenefitsUsage: {
personal_account_id: string;
benefit_amount: number;
+ benefit_unused_amount: number;
}[];
},
): ColumnDef[] {
@@ -185,11 +177,11 @@ function useGetColumns(
{
header: t('distributedBenefitsAmount'),
cell: ({ row }) => {
- const benefitAmount = params.membersBenefitsUsage.find(
+ let benefitAmount = params.membersBenefitsUsage.find(
(usage) => usage.personal_account_id === row.original.id,
)?.benefit_amount;
if (typeof benefitAmount !== 'number') {
- return '-';
+ benefitAmount = 0;
}
return formatCurrency({
@@ -199,6 +191,23 @@ function useGetColumns(
});
},
},
+ {
+ header: t('distributedBenefitsUnusedAmount'),
+ cell: ({ row }) => {
+ let benefitUnusedAmount = params.membersBenefitsUsage.find(
+ (usage) => usage.personal_account_id === row.original.id,
+ )?.benefit_unused_amount;
+ if (typeof benefitUnusedAmount !== 'number') {
+ benefitUnusedAmount = 0;
+ }
+
+ return formatCurrency({
+ currencyCode: 'EUR',
+ locale: language,
+ value: benefitUnusedAmount,
+ });
+ },
+ },
{
header: t('roleLabel'),
cell: ({ row }) => {
@@ -246,7 +255,7 @@ function useGetColumns(
),
},
],
- [t, params, permissions],
+ [t, params, permissions, language],
);
}
diff --git a/packages/supabase/src/database.types.ts b/packages/supabase/src/database.types.ts
index 6f03c0b..454e7fb 100644
--- a/packages/supabase/src/database.types.ts
+++ b/packages/supabase/src/database.types.ts
@@ -2323,6 +2323,7 @@ export type Database = {
Returns: {
personal_account_id: string
benefit_amount: number
+ benefit_unused_amount: number
}
}
get_config: {
diff --git a/public/locales/en/teams.json b/public/locales/en/teams.json
index 8af264f..d248e54 100644
--- a/public/locales/en/teams.json
+++ b/public/locales/en/teams.json
@@ -196,5 +196,6 @@
"specialCharactersError": "This name cannot contain special characters. Please choose a different one.",
"personalCode": "Personal Code",
"teamOwnerPersonalCodeLabel": "Owner's Personal Code",
- "distributedBenefitsAmount": "Assigned benefits"
+ "distributedBenefitsAmount": "Assigned benefits",
+ "distributedBenefitsUnusedAmount": "Unused benefits"
}
diff --git a/public/locales/et/teams.json b/public/locales/et/teams.json
index 884923d..48b0281 100644
--- a/public/locales/et/teams.json
+++ b/public/locales/et/teams.json
@@ -196,5 +196,6 @@
"specialCharactersError": "Nimi ei tohi sisaldada erimärke. Palun vali mõni teine.",
"personalCode": "Isikukood",
"teamOwnerPersonalCodeLabel": "Omaniku isikukood",
- "distributedBenefitsAmount": "Väljastatud toetus"
+ "distributedBenefitsAmount": "Väljastatud toetus",
+ "distributedBenefitsUnusedAmount": "Jääk"
}
diff --git a/public/locales/ru/teams.json b/public/locales/ru/teams.json
index 74111f1..c814f7c 100644
--- a/public/locales/ru/teams.json
+++ b/public/locales/ru/teams.json
@@ -196,5 +196,6 @@
"specialCharactersError": "Это имя не может содержать специальные символы. Пожалуйста, выберите другое.",
"personalCode": "Идентификационный код",
"teamOwnerPersonalCodeLabel": "Идентификационный код владельца",
- "distributedBenefitsAmount": "Распределенные выплаты"
+ "distributedBenefitsAmount": "Распределенные выплаты",
+ "distributedBenefitsUnusedAmount": "Неиспользованные выплаты"
}
diff --git a/supabase/migrations/20251001011316_update_benefits_usage_calculation.sql b/supabase/migrations/20251001011316_update_benefits_usage_calculation.sql
new file mode 100644
index 0000000..2e375d5
--- /dev/null
+++ b/supabase/migrations/20251001011316_update_benefits_usage_calculation.sql
@@ -0,0 +1,30 @@
+DROP FUNCTION IF EXISTS medreport.get_benefits_usages_for_company_members(uuid);
+
+CREATE OR REPLACE FUNCTION medreport.get_benefits_usages_for_company_members(p_account_id uuid)
+returns table (
+ personal_account_id uuid,
+ benefit_amount numeric,
+ benefit_unused_amount numeric
+)
+language plpgsql
+as $$
+begin
+ return query
+ with benefit_recipient_accounts as (
+ -- Find all personal accounts that have received benefits from this company
+ select distinct account_id
+ from medreport.account_balance_entries
+ where source_company_id = p_account_id
+ and entry_type = 'benefit'
+ )
+ select
+ bra.account_id as personal_account_id,
+ coalesce(sum(case when abe.entry_type = 'benefit' and abe.source_company_id = p_account_id then abe.amount else 0 end), 0) as benefit_amount,
+ coalesce(sum(case when abe.entry_type = 'benefit' and abe.source_company_id = p_account_id then abe.amount when abe.entry_type = 'purchase' then abe.amount else 0 end), 0) as benefit_unused_amount
+ from benefit_recipient_accounts bra
+ left join medreport.account_balance_entries abe on abe.account_id = bra.account_id
+ group by bra.account_id;
+end;
+$$;
+
+grant execute on function medreport.get_benefits_usages_for_company_members(uuid) to authenticated, service_role;
diff --git a/supabase/migrations/20251001014022_account_members_full_names.sql b/supabase/migrations/20251001014022_account_members_full_names.sql
new file mode 100644
index 0000000..1f50a5d
--- /dev/null
+++ b/supabase/migrations/20251001014022_account_members_full_names.sql
@@ -0,0 +1,48 @@
+DROP FUNCTION IF EXISTS medreport.get_account_members(text);
+
+CREATE OR REPLACE FUNCTION medreport.get_account_members(account_slug text)
+ RETURNS TABLE(
+ id uuid,
+ user_id uuid,
+ account_id uuid,
+ role character varying,
+ role_hierarchy_level integer,
+ primary_owner_user_id uuid,
+ name text,
+ email character varying,
+ personal_code text,
+ picture_url character varying,
+ created_at timestamp with time zone,
+ updated_at timestamp with time zone
+)
+ LANGUAGE plpgsql
+ SET search_path TO ''
+AS $function$begin
+ return QUERY
+ select
+ acc.id,
+ am.user_id,
+ am.account_id,
+ am.account_role,
+ r.hierarchy_level,
+ a.primary_owner_user_id,
+ TRIM(CONCAT(acc.name, ' ', acc.last_name)) as name,
+ acc.email,
+ acc.personal_code,
+ acc.picture_url,
+ am.created_at,
+ am.updated_at
+ from
+ medreport.accounts_memberships am
+ join medreport.accounts a on a.id = am.account_id
+ join medreport.accounts acc on acc.id = am.user_id
+ join medreport.roles r on r.name = am.account_role
+ where
+ a.slug = account_slug;
+
+end;$function$
+;
+
+grant
+ execute on function medreport.get_account_members (text) to authenticated,
+ service_role;