feat(MED-97): update cart flow for using benefits
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,125 @@
|
||||
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> {
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import type { Database } from '@kit/supabase/database';
|
||||
|
||||
export type AccountBalanceEntry = Database['medreport']['Tables']['account_balance_entries']['Row'];
|
||||
@@ -253,6 +253,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,
|
||||
|
||||
@@ -337,6 +337,51 @@ export type Database = {
|
||||
}
|
||||
medreport: {
|
||||
Tables: {
|
||||
account_balance_entries: {
|
||||
Row: {
|
||||
id: string
|
||||
account_id: string
|
||||
amount: number
|
||||
entry_type: string
|
||||
description: string
|
||||
source_company_id: string
|
||||
reference_id: string
|
||||
created_at: string
|
||||
created_by: string
|
||||
expires_at: string
|
||||
is_active: boolean
|
||||
is_analysis_order: boolean
|
||||
is_analysis_package_order: boolean
|
||||
}
|
||||
Insert: {
|
||||
account_id: string
|
||||
amount: number
|
||||
entry_type: string
|
||||
description: string
|
||||
source_company_id: string
|
||||
reference_id: string
|
||||
created_at: string
|
||||
created_by: string
|
||||
expires_at: string
|
||||
is_active: boolean
|
||||
is_analysis_order?: boolean
|
||||
is_analysis_package_order?: boolean
|
||||
}
|
||||
Update: {
|
||||
account_id?: string
|
||||
amount?: number
|
||||
entry_type?: string
|
||||
description?: string
|
||||
source_company_id?: string
|
||||
reference_id?: string
|
||||
created_at?: string
|
||||
created_by?: string
|
||||
expires_at?: string
|
||||
is_active?: boolean
|
||||
is_analysis_order?: boolean
|
||||
is_analysis_package_order?: boolean
|
||||
}
|
||||
}
|
||||
account_params: {
|
||||
Row: {
|
||||
account_id: string
|
||||
@@ -2148,6 +2193,10 @@ export type Database = {
|
||||
Args: { medusa_order_id: string }
|
||||
Returns: boolean
|
||||
}
|
||||
process_periodic_benefit_distributions: {
|
||||
Args: {}
|
||||
Returns: void
|
||||
}
|
||||
revoke_nonce: {
|
||||
Args: { p_id: string; p_reason?: string }
|
||||
Returns: boolean
|
||||
|
||||
Reference in New Issue
Block a user