feat(MED-97): update cart flow for using benefits

This commit is contained in:
2025-09-26 13:24:09 +03:00
parent 56f84a003c
commit db38e602aa
15 changed files with 419 additions and 81 deletions

View File

@@ -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');
}
}
}

View File

@@ -0,0 +1,3 @@
import type { Database } from '@kit/supabase/database';
export type AccountBalanceEntry = Database['medreport']['Tables']['account_balance_entries']['Row'];