Merge branch 'develop' into MED-49
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
"./personal-account-settings": "./src/components/personal-account-settings/index.ts",
|
||||
"./components": "./src/components/index.ts",
|
||||
"./hooks/*": "./src/hooks/*.ts",
|
||||
"./services/*": "./src/server/services/*.ts",
|
||||
"./api": "./src/server/api.ts",
|
||||
"./types/*": "./src/types/*.ts"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
|
||||
import type { AccountBalanceEntry } from '../../types/account-balance-entry';
|
||||
|
||||
export type AccountBalanceSummary = {
|
||||
totalBalance: number;
|
||||
expiringSoon: number;
|
||||
recentEntries: AccountBalanceEntry[];
|
||||
};
|
||||
|
||||
export class AccountBalanceService {
|
||||
private supabase: ReturnType<typeof getSupabaseServerClient>;
|
||||
|
||||
constructor() {
|
||||
this.supabase = getSupabaseServerClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current balance for a specific account
|
||||
*/
|
||||
async getAccountBalance(accountId: string): Promise<number> {
|
||||
const { data, error } = await this.supabase
|
||||
.schema('medreport')
|
||||
.rpc('get_account_balance', {
|
||||
p_account_id: accountId,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error('Error getting account balance:', error);
|
||||
throw new Error('Failed to get account balance');
|
||||
}
|
||||
|
||||
return data || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get balance entries for an account with pagination
|
||||
*/
|
||||
async getAccountBalanceEntries(
|
||||
accountId: string,
|
||||
options: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
entryType?: string;
|
||||
includeInactive?: boolean;
|
||||
} = {}
|
||||
): Promise<{
|
||||
entries: AccountBalanceEntry[];
|
||||
total: number;
|
||||
}> {
|
||||
const { limit = 50, offset = 0, entryType, includeInactive = false } = options;
|
||||
|
||||
let query = this.supabase
|
||||
.schema('medreport')
|
||||
.from('account_balance_entries')
|
||||
.select('*', { count: 'exact' })
|
||||
.eq('account_id', accountId)
|
||||
.order('created_at', { ascending: false })
|
||||
.range(offset, offset + limit - 1);
|
||||
|
||||
if (!includeInactive) {
|
||||
query = query.eq('is_active', true);
|
||||
}
|
||||
|
||||
if (entryType) {
|
||||
query = query.eq('entry_type', entryType);
|
||||
}
|
||||
|
||||
const { data, error, count } = await query;
|
||||
|
||||
if (error) {
|
||||
console.error('Error getting account balance entries:', error);
|
||||
throw new Error('Failed to get account balance entries');
|
||||
}
|
||||
|
||||
return {
|
||||
entries: data || [],
|
||||
total: count || 0,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get balance summary for dashboard display
|
||||
*/
|
||||
async getBalanceSummary(accountId: string): Promise<AccountBalanceSummary> {
|
||||
const [balance, entries] = await Promise.all([
|
||||
this.getAccountBalance(accountId),
|
||||
this.getAccountBalanceEntries(accountId, { limit: 5 }),
|
||||
]);
|
||||
|
||||
// Calculate expiring balance (next 30 days)
|
||||
const thirtyDaysFromNow = new Date();
|
||||
thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);
|
||||
|
||||
const { data: expiringData, error: expiringError } = await this.supabase
|
||||
.schema('medreport')
|
||||
.from('account_balance_entries')
|
||||
.select('amount')
|
||||
.eq('account_id', accountId)
|
||||
.eq('is_active', true)
|
||||
.not('expires_at', 'is', null)
|
||||
.lte('expires_at', thirtyDaysFromNow.toISOString());
|
||||
|
||||
if (expiringError) {
|
||||
console.error('Error getting expiring balance:', expiringError);
|
||||
}
|
||||
|
||||
const expiringSoon = expiringData?.reduce((sum, entry) => sum + (entry.amount || 0), 0) || 0;
|
||||
|
||||
return {
|
||||
totalBalance: balance,
|
||||
expiringSoon,
|
||||
recentEntries: entries.entries,
|
||||
};
|
||||
}
|
||||
|
||||
async processPeriodicBenefitDistributions(): Promise<void> {
|
||||
console.info('Processing periodic benefit distributions...');
|
||||
const { error } = await this.supabase.schema('medreport').rpc('process_periodic_benefit_distributions');
|
||||
if (error) {
|
||||
console.error('Error processing periodic benefit distributions:', error);
|
||||
throw new Error('Failed to process periodic benefit distributions');
|
||||
}
|
||||
console.info('Periodic benefit distributions processed successfully');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import type { Database } from '@kit/supabase/database';
|
||||
|
||||
export type AccountBalanceEntry = Database['medreport']['Tables']['account_balance_entries']['Row'];
|
||||
@@ -1,23 +1,25 @@
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
export type ApplicationRole =
|
||||
Database['medreport']['Tables']['accounts']['Row']['application_role'];
|
||||
export type ApplicationRole = Account['application_role'];
|
||||
export enum ApplicationRoleEnum {
|
||||
User = 'user',
|
||||
Doctor = 'doctor',
|
||||
SuperAdmin = 'super_admin',
|
||||
}
|
||||
|
||||
export type AccountWithParams =
|
||||
Database['medreport']['Tables']['accounts']['Row'] & {
|
||||
accountParams:
|
||||
| (Pick<
|
||||
Database['medreport']['Tables']['account_params']['Row'],
|
||||
'weight' | 'height'
|
||||
> & {
|
||||
isSmoker:
|
||||
| Database['medreport']['Tables']['account_params']['Row']['is_smoker']
|
||||
| null;
|
||||
})
|
||||
| null;
|
||||
};
|
||||
export type AccountParams =
|
||||
Database['medreport']['Tables']['account_params']['Row'];
|
||||
|
||||
export type Account = Database['medreport']['Tables']['accounts']['Row'];
|
||||
export type AccountWithParams = Account & {
|
||||
accountParams:
|
||||
| (Pick<AccountParams, 'weight' | 'height'> & {
|
||||
isSmoker: AccountParams['is_smoker'] | null;
|
||||
})
|
||||
| null;
|
||||
};
|
||||
|
||||
export type CompanyParams =
|
||||
Database['medreport']['Tables']['company_params']['Row'];
|
||||
|
||||
export type BmiThresholds = Database['medreport']['Tables']['bmi_thresholds']['Row'];
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"devDependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@kit/next": "workspace:*",
|
||||
"@kit/accounts": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
|
||||
@@ -11,7 +11,7 @@ import { EllipsisVertical } from 'lucide-react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
import type { Account } from '@kit/accounts/types/accounts';
|
||||
import { Button } from '@kit/ui/button';
|
||||
import { Checkbox } from '@kit/ui/checkbox';
|
||||
import {
|
||||
@@ -44,8 +44,6 @@ import { AdminDeleteUserDialog } from './admin-delete-user-dialog';
|
||||
import { AdminImpersonateUserDialog } from './admin-impersonate-user-dialog';
|
||||
import { AdminResetPasswordDialog } from './admin-reset-password-dialog';
|
||||
|
||||
type Account = Database['medreport']['Tables']['accounts']['Row'];
|
||||
|
||||
const FiltersSchema = z.object({
|
||||
type: z.enum(['all', 'team', 'personal']),
|
||||
query: z.string().optional(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
import { ApplicationRole } from '@kit/accounts/types/accounts';
|
||||
|
||||
const ConfirmationSchema = z.object({
|
||||
confirmation: z.custom<string>((value) => value === 'CONFIRM'),
|
||||
@@ -19,9 +19,7 @@ export const DeleteAccountSchema = ConfirmationSchema.extend({
|
||||
accountId: z.string().uuid(),
|
||||
});
|
||||
|
||||
type ApplicationRoleType =
|
||||
Database['medreport']['Tables']['accounts']['Row']['application_role'];
|
||||
export const UpdateAccountRoleSchema = z.object({
|
||||
accountId: z.string().uuid(),
|
||||
role: z.string() as z.ZodType<ApplicationRoleType>,
|
||||
role: z.string() as z.ZodType<ApplicationRole>,
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'server-only';
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
import type { ApplicationRole } from '@kit/accounts/types/accounts';
|
||||
|
||||
export function createAdminAccountsService(client: SupabaseClient<Database>) {
|
||||
return new AdminAccountsService(client);
|
||||
@@ -25,7 +26,7 @@ class AdminAccountsService {
|
||||
|
||||
async updateRole(
|
||||
accountId: string,
|
||||
role: Database['medreport']['Tables']['accounts']['Row']['application_role'],
|
||||
role: ApplicationRole,
|
||||
) {
|
||||
const { error } = await this.adminClient
|
||||
.schema('medreport')
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@kit/user-analyses": "workspace:*",
|
||||
"@makerkit/data-loader-supabase-core": "^0.0.10",
|
||||
"@makerkit/data-loader-supabase-nextjs": "^1.2.5",
|
||||
"@supabase/supabase-js": "2.49.4",
|
||||
|
||||
@@ -5,6 +5,7 @@ import { isBefore } from 'date-fns';
|
||||
import { renderDoctorSummaryReceivedEmail } from '@kit/email-templates';
|
||||
import { getFullName } from '@kit/shared/utils';
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
import { createUserAnalysesApi } from '@kit/user-analyses/api';
|
||||
|
||||
import { sendEmailFromTemplate } from '../../../../../../../lib/services/mailer.service';
|
||||
import { AnalysisResultDetails } from '../schema/doctor-analysis-detail-view.schema';
|
||||
@@ -641,7 +642,14 @@ export async function submitFeedback(
|
||||
}
|
||||
|
||||
if (status === 'COMPLETED') {
|
||||
const [{ data: recipient }, { data: analysisOrder }] = await Promise.all([
|
||||
const { data: analysisOrder } = await supabase
|
||||
.schema('medreport')
|
||||
.from('analysis_orders')
|
||||
.select('medusa_order_id, id')
|
||||
.eq('id', analysisOrderId)
|
||||
.limit(1)
|
||||
.throwOnError();
|
||||
const [{ data: recipient }] = await Promise.all([
|
||||
supabase
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
@@ -649,19 +657,10 @@ export async function submitFeedback(
|
||||
.eq('is_personal_account', true)
|
||||
.eq('primary_owner_user_id', userId)
|
||||
.throwOnError(),
|
||||
supabase
|
||||
.schema('medreport')
|
||||
.from('analysis_orders')
|
||||
.select('medusa_order_id, id')
|
||||
.eq('id', analysisOrderId)
|
||||
.limit(1)
|
||||
.throwOnError(),
|
||||
supabase
|
||||
.schema('medreport')
|
||||
.from('analysis_orders')
|
||||
.update({ status: 'COMPLETED' })
|
||||
.eq('id', analysisOrderId)
|
||||
.throwOnError(),
|
||||
createUserAnalysesApi(supabase).updateAnalysisOrderStatus({
|
||||
orderId: analysisOrderId,
|
||||
orderStatus: 'COMPLETED',
|
||||
}),
|
||||
]);
|
||||
|
||||
if (!recipient?.[0]?.email) {
|
||||
|
||||
@@ -258,6 +258,37 @@ export async function setShippingMethod({
|
||||
.catch(medusaError);
|
||||
}
|
||||
|
||||
export async function initiateMultiPaymentSession(
|
||||
cart: HttpTypes.StoreCart,
|
||||
benefitsAmount: number,
|
||||
) {
|
||||
const headers = {
|
||||
...(await getAuthHeaders()),
|
||||
};
|
||||
|
||||
return sdk.client.fetch<unknown>(`/store/multi-payment`, {
|
||||
method: 'POST',
|
||||
body: { cartId: cart.id, benefitsAmount },
|
||||
headers,
|
||||
})
|
||||
.then(async (response) => {
|
||||
console.info('Payment session initiated:', response);
|
||||
const cartCacheTag = await getCacheTag('carts');
|
||||
revalidateTag(cartCacheTag);
|
||||
return response as {
|
||||
montonioPaymentSessionId: string | null;
|
||||
companyBenefitsPaymentSessionId: string | null;
|
||||
totalByBenefits: number;
|
||||
totalByMontonio: number;
|
||||
isFullyPaidByBenefits: boolean;
|
||||
};
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('Error initiating payment session:', e, JSON.stringify(Object.keys(e)));
|
||||
return medusaError(e);
|
||||
});
|
||||
}
|
||||
|
||||
export async function initiatePaymentSession(
|
||||
cart: HttpTypes.StoreCart,
|
||||
data: HttpTypes.StoreInitializePaymentSession,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { HttpTypes } from '@medusajs/types';
|
||||
|
||||
import { getAuthHeaders, getCacheOptions } from './cookies';
|
||||
|
||||
export const retrieveOrder = async (id: string) => {
|
||||
export const retrieveOrder = async (id: string, allowCache = true) => {
|
||||
const headers = {
|
||||
...(await getAuthHeaders()),
|
||||
};
|
||||
@@ -24,7 +24,7 @@ export const retrieveOrder = async (id: string) => {
|
||||
},
|
||||
headers,
|
||||
next,
|
||||
cache: 'force-cache',
|
||||
...(allowCache ? { cache: 'force-cache' } : {}),
|
||||
})
|
||||
.then(({ order }) => order)
|
||||
.catch((err) => medusaError(err));
|
||||
@@ -61,11 +61,6 @@ export const listOrders = async (
|
||||
};
|
||||
|
||||
export const createTransferRequest = async (
|
||||
state: {
|
||||
success: boolean;
|
||||
error: string | null;
|
||||
order: HttpTypes.StoreOrder | null;
|
||||
},
|
||||
formData: FormData,
|
||||
): Promise<{
|
||||
success: boolean;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import Image from 'next/image';
|
||||
|
||||
import { useDismissNotification } from '@kit/notifications/hooks';
|
||||
import { Heading } from '@kit/ui/heading';
|
||||
import { If } from '@kit/ui/if';
|
||||
import { Separator } from '@kit/ui/separator';
|
||||
@@ -12,7 +11,7 @@ import { SignOutInvitationButton } from './sign-out-invitation-button';
|
||||
|
||||
export function AcceptInvitationContainer(props: {
|
||||
inviteToken: string;
|
||||
email: string;
|
||||
fullName: string;
|
||||
|
||||
invitation: {
|
||||
id: string;
|
||||
@@ -76,7 +75,7 @@ export function AcceptInvitationContainer(props: {
|
||||
/>
|
||||
|
||||
<InvitationSubmitButton
|
||||
email={props.email}
|
||||
fullName={props.fullName}
|
||||
accountName={props.invitation.account.name}
|
||||
/>
|
||||
</form>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Trans } from '@kit/ui/trans';
|
||||
|
||||
export function InvitationSubmitButton(props: {
|
||||
accountName: string;
|
||||
email: string;
|
||||
fullName: string;
|
||||
}) {
|
||||
const { pending } = useFormStatus();
|
||||
|
||||
@@ -17,7 +17,7 @@ export function InvitationSubmitButton(props: {
|
||||
i18nKey={pending ? 'teams:joiningTeam' : 'teams:continueAs'}
|
||||
values={{
|
||||
accountName: props.accountName,
|
||||
email: props.email,
|
||||
fullName: props.fullName,
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
@@ -20,6 +20,7 @@ import { If } from '@kit/ui/if';
|
||||
import { Input } from '@kit/ui/input';
|
||||
import { ProfileAvatar } from '@kit/ui/profile-avatar';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
import { formatCurrency } from '@kit/shared/utils';
|
||||
|
||||
import { RemoveMemberDialog } from './remove-member-dialog';
|
||||
import { RoleBadge } from './role-badge';
|
||||
@@ -42,6 +43,10 @@ type AccountMembersTableProps = {
|
||||
userRoleHierarchy: number;
|
||||
isPrimaryOwner: boolean;
|
||||
canManageRoles: boolean;
|
||||
membersBenefitsUsage: {
|
||||
personal_account_id: string;
|
||||
benefit_amount: number;
|
||||
}[];
|
||||
};
|
||||
|
||||
export function AccountMembersTable({
|
||||
@@ -51,6 +56,7 @@ export function AccountMembersTable({
|
||||
isPrimaryOwner,
|
||||
userRoleHierarchy,
|
||||
canManageRoles,
|
||||
membersBenefitsUsage,
|
||||
}: AccountMembersTableProps) {
|
||||
const [search, setSearch] = useState('');
|
||||
const { t } = useTranslation('teams');
|
||||
@@ -73,6 +79,7 @@ export function AccountMembersTable({
|
||||
currentUserId,
|
||||
currentAccountId,
|
||||
currentRoleHierarchy: userRoleHierarchy,
|
||||
membersBenefitsUsage,
|
||||
});
|
||||
|
||||
const filteredMembers = members
|
||||
@@ -122,9 +129,13 @@ function useGetColumns(
|
||||
currentUserId: string;
|
||||
currentAccountId: string;
|
||||
currentRoleHierarchy: number;
|
||||
membersBenefitsUsage: {
|
||||
personal_account_id: string;
|
||||
benefit_amount: number;
|
||||
}[];
|
||||
},
|
||||
): ColumnDef<Members[0]>[] {
|
||||
const { t } = useTranslation('teams');
|
||||
const { t, i18n: { language } } = useTranslation('teams');
|
||||
|
||||
return useMemo(
|
||||
() => [
|
||||
@@ -168,6 +179,23 @@ function useGetColumns(
|
||||
return row.original.personal_code ?? '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
header: t('distributedBenefitsAmount'),
|
||||
cell: ({ row }) => {
|
||||
const benefitAmount = params.membersBenefitsUsage.find(
|
||||
(usage) => usage.personal_account_id === row.original.id
|
||||
)?.benefit_amount;
|
||||
if (typeof benefitAmount !== 'number') {
|
||||
return '-';
|
||||
}
|
||||
|
||||
return formatCurrency({
|
||||
currencyCode: 'EUR',
|
||||
locale: language,
|
||||
value: benefitAmount,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
header: t('roleLabel'),
|
||||
cell: ({ row }) => {
|
||||
@@ -175,7 +203,7 @@ function useGetColumns(
|
||||
const isPrimaryOwner = primary_owner_user_id === user_id;
|
||||
|
||||
return (
|
||||
<span className={'flex items-center space-x-1'}>
|
||||
<span className={'flex items-center space-x-1 flex-wrap space-y-1 sm:space-y-0 sm:flex-nowrap'}>
|
||||
<RoleBadge role={role} />
|
||||
|
||||
<If condition={isPrimaryOwner}>
|
||||
|
||||
@@ -13,6 +13,8 @@ import { TeamAccountDangerZone } from './team-account-danger-zone';
|
||||
import { UpdateTeamAccountImage } from './update-team-account-image-container';
|
||||
import { UpdateTeamAccountNameForm } from './update-team-account-name-form';
|
||||
|
||||
const SHOW_TEAM_LOGO = false as boolean;
|
||||
|
||||
export function TeamAccountSettingsContainer(props: {
|
||||
account: {
|
||||
name: string;
|
||||
@@ -32,21 +34,23 @@ export function TeamAccountSettingsContainer(props: {
|
||||
}) {
|
||||
return (
|
||||
<div className={'flex w-full flex-col space-y-4'}>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<Trans i18nKey={'teams:settings.teamLogo'} />
|
||||
</CardTitle>
|
||||
{SHOW_TEAM_LOGO && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<Trans i18nKey={'teams:settings.teamLogo'} />
|
||||
</CardTitle>
|
||||
|
||||
<CardDescription>
|
||||
<Trans i18nKey={'teams:settings.teamLogoDescription'} />
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardDescription>
|
||||
<Trans i18nKey={'teams:settings.teamLogoDescription'} />
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<UpdateTeamAccountImage account={props.account} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<CardContent>
|
||||
<UpdateTeamAccountImage account={props.account} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { RenewInvitationSchema } from '../../schema/renew-invitation.schema';
|
||||
import { UpdateInvitationSchema } from '../../schema/update-invitation.schema';
|
||||
import { createAccountInvitationsService } from '../services/account-invitations.service';
|
||||
import { createAccountPerSeatBillingService } from '../services/account-per-seat-billing.service';
|
||||
import { AccountBalanceService } from '@kit/accounts/services/account-balance.service';
|
||||
|
||||
/**
|
||||
* @name createInvitationsAction
|
||||
@@ -148,6 +149,7 @@ export const updateInvitationAction = enhanceAction(
|
||||
export const acceptInvitationAction = enhanceAction(
|
||||
async (data: FormData, user) => {
|
||||
const client = getSupabaseServerClient();
|
||||
const accountBalanceService = new AccountBalanceService();
|
||||
|
||||
const { inviteToken, nextPath } = AcceptInvitationSchema.parse(
|
||||
Object.fromEntries(data),
|
||||
@@ -171,6 +173,9 @@ export const acceptInvitationAction = enhanceAction(
|
||||
throw new Error('Failed to accept invitation');
|
||||
}
|
||||
|
||||
// Make sure new account gets company benefits added to balance
|
||||
await accountBalanceService.processPeriodicBenefitDistributions();
|
||||
|
||||
// Increase the seats for the account
|
||||
await perSeatBillingService.increaseSeats(accountId);
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { getLogger } from '@kit/shared/logger';
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
type Account = Database['medreport']['Tables']['accounts']['Row'];
|
||||
import type { Account } from '@kit/accounts/types/accounts';
|
||||
|
||||
export function createAccountWebhooksService() {
|
||||
return new AccountWebhooksService();
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { UuringuVastus } from '@kit/shared/types/medipost-analysis';
|
||||
import { toArray } from '@kit/shared/utils';
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
import type { AnalysisOrder } from '../types/analysis-orders';
|
||||
import type { AnalysisOrder, AnalysisOrderStatus } from '../types/analysis-orders';
|
||||
import type {
|
||||
AnalysisResultDetailsElement,
|
||||
AnalysisResultDetailsMapped,
|
||||
@@ -450,6 +450,32 @@ class UserAnalysesApi {
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async updateAnalysisOrderStatus({
|
||||
orderId,
|
||||
medusaOrderId,
|
||||
orderStatus,
|
||||
}: {
|
||||
orderId?: number;
|
||||
medusaOrderId?: string;
|
||||
orderStatus: AnalysisOrderStatus;
|
||||
}) {
|
||||
const orderIdParam = orderId;
|
||||
const medusaOrderIdParam = medusaOrderId;
|
||||
|
||||
console.info(`Updating order id=${orderId} medusaOrderId=${medusaOrderId} status=${orderStatus}`);
|
||||
if (!orderIdParam && !medusaOrderIdParam) {
|
||||
throw new Error('Either orderId or medusaOrderId must be provided');
|
||||
}
|
||||
await this.client
|
||||
.schema('medreport')
|
||||
.rpc('update_analysis_order_status', {
|
||||
order_id: orderIdParam ?? -1,
|
||||
status_param: orderStatus,
|
||||
medusa_order_id_param: medusaOrderIdParam ?? '',
|
||||
})
|
||||
.throwOnError();
|
||||
}
|
||||
}
|
||||
|
||||
export function createUserAnalysesApi(client: SupabaseClient<Database>) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Tables } from '@kit/supabase/database';
|
||||
|
||||
export type AnalysisOrder = Tables<{ schema: 'medreport' }, 'analysis_orders'>;
|
||||
export type AnalysisOrderStatus = AnalysisOrder['status'];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CreditCard, LayoutDashboard, Settings, Users } from 'lucide-react';
|
||||
import { Euro, LayoutDashboard, Settings, Users } from 'lucide-react';
|
||||
|
||||
import { NavigationConfigSchema } from '@kit/ui/navigation-schema';
|
||||
|
||||
@@ -11,28 +11,28 @@ const getRoutes = (account: string) => [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.dashboard',
|
||||
label: 'common:routes.companyDashboard',
|
||||
path: pathsConfig.app.accountHome.replace('[account]', account),
|
||||
Icon: <LayoutDashboard className={iconClasses} />,
|
||||
end: true,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.settings',
|
||||
path: createPath(pathsConfig.app.accountSettings, account),
|
||||
Icon: <Settings className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.members',
|
||||
label: 'common:routes.companyMembers',
|
||||
path: createPath(pathsConfig.app.accountMembers, account),
|
||||
Icon: <Users className={iconClasses} />,
|
||||
},
|
||||
featureFlagsConfig.enableTeamAccountBilling
|
||||
? {
|
||||
label: 'common:routes.billing',
|
||||
path: createPath(pathsConfig.app.accountBilling, account),
|
||||
Icon: <CreditCard className={iconClasses} />,
|
||||
}
|
||||
label: 'common:routes.billing',
|
||||
path: createPath(pathsConfig.app.accountBilling, account),
|
||||
Icon: <Euro className={iconClasses} />,
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
label: 'common:routes.companySettings',
|
||||
path: createPath(pathsConfig.app.accountSettings, account),
|
||||
Icon: <Settings className={iconClasses} />,
|
||||
},
|
||||
].filter(Boolean),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -11,10 +11,10 @@ import { getSupabaseClientKeys } from '../get-supabase-client-keys';
|
||||
* @name getSupabaseServerClient
|
||||
* @description Creates a Supabase client for use in the Server.
|
||||
*/
|
||||
export function getSupabaseServerClient<GenericSchema = Database>() {
|
||||
export function getSupabaseServerClient() {
|
||||
const keys = getSupabaseClientKeys();
|
||||
|
||||
return createServerClient<GenericSchema>(keys.url, keys.anonKey, {
|
||||
return createServerClient<Database>(keys.url, keys.anonKey, {
|
||||
auth: {
|
||||
flowType: 'pkce',
|
||||
autoRefreshToken: true,
|
||||
|
||||
@@ -348,6 +348,8 @@ export type Database = {
|
||||
expires_at: string | null
|
||||
id: string
|
||||
is_active: boolean
|
||||
is_analysis_order: boolean
|
||||
is_analysis_package_order: boolean
|
||||
reference_id: string | null
|
||||
source_company_id: string | null
|
||||
}
|
||||
@@ -361,6 +363,8 @@ export type Database = {
|
||||
expires_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
is_analysis_order?: boolean
|
||||
is_analysis_package_order?: boolean
|
||||
reference_id?: string | null
|
||||
source_company_id?: string | null
|
||||
}
|
||||
@@ -374,6 +378,8 @@ export type Database = {
|
||||
expires_at?: string | null
|
||||
id?: string
|
||||
is_active?: boolean
|
||||
is_analysis_order?: boolean
|
||||
is_analysis_package_order?: boolean
|
||||
reference_id?: string | null
|
||||
source_company_id?: string | null
|
||||
}
|
||||
@@ -2310,6 +2316,15 @@ export type Database = {
|
||||
user_id: string
|
||||
}[]
|
||||
}
|
||||
get_benefits_usages_for_company_members: {
|
||||
Args: {
|
||||
p_account_id: string
|
||||
}
|
||||
Returns: {
|
||||
personal_account_id: string
|
||||
benefit_amount: number
|
||||
}
|
||||
}
|
||||
get_config: {
|
||||
Args: Record<PropertyKey, never>
|
||||
Returns: Json
|
||||
|
||||
Reference in New Issue
Block a user