Sales Frontend (Sprint 2): - Add services: leads, opportunities, activities, pipeline, dashboard APIs - Add hooks: useSales with React Query integration - Add pages: SalesPage, LeadsPage, LeadDetailPage, OpportunitiesPage, OpportunityDetailPage, ActivitiesPage - Integrate routes in main router Commissions Frontend (Sprint 4): - Add services: schemes, entries, periods, assignments, dashboard APIs - Add hooks: useCommissions with React Query integration - Add pages: CommissionsPage, SchemesPage, EntriesPage, PeriodsPage, MyEarningsPage - Integrate routes in main router Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
148 lines
4.6 KiB
TypeScript
148 lines
4.6 KiB
TypeScript
import api from '../api';
|
|
import { CommissionScheme } from './schemes.api';
|
|
|
|
export type EntryStatus = 'pending' | 'approved' | 'rejected' | 'paid' | 'cancelled';
|
|
|
|
export interface CommissionEntry {
|
|
id: string;
|
|
tenant_id: string;
|
|
user_id: string;
|
|
scheme_id: string;
|
|
assignment_id: string | null;
|
|
reference_type: string;
|
|
reference_id: string;
|
|
base_amount: number;
|
|
rate_applied: number;
|
|
commission_amount: number;
|
|
currency: string;
|
|
status: EntryStatus;
|
|
period_id: string | null;
|
|
paid_at: string | null;
|
|
payment_reference: string | null;
|
|
notes: string | null;
|
|
metadata: Record<string, unknown>;
|
|
created_at: string;
|
|
updated_at: string;
|
|
approved_by: string | null;
|
|
approved_at: string | null;
|
|
scheme?: CommissionScheme;
|
|
user?: {
|
|
id: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
email: string;
|
|
};
|
|
}
|
|
|
|
export interface CalculateCommissionDto {
|
|
user_id: string;
|
|
reference_type: string;
|
|
reference_id: string;
|
|
base_amount: number;
|
|
currency?: string;
|
|
notes?: string;
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
export interface UpdateEntryStatusDto {
|
|
status: EntryStatus;
|
|
notes?: string;
|
|
}
|
|
|
|
export interface CalculationResult {
|
|
rate_applied: number;
|
|
commission_amount: number;
|
|
scheme_id: string;
|
|
assignment_id: string | null;
|
|
}
|
|
|
|
export interface EntryFilters {
|
|
user_id?: string;
|
|
scheme_id?: string;
|
|
period_id?: string;
|
|
status?: EntryStatus;
|
|
reference_type?: string;
|
|
date_from?: string;
|
|
date_to?: string;
|
|
page?: number;
|
|
limit?: number;
|
|
sortBy?: string;
|
|
sortOrder?: 'ASC' | 'DESC';
|
|
}
|
|
|
|
export interface PaginatedEntries {
|
|
data: CommissionEntry[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
totalPages: number;
|
|
}
|
|
|
|
export const entriesApi = {
|
|
list: async (params?: EntryFilters): Promise<PaginatedEntries> => {
|
|
const response = await api.get<PaginatedEntries>('/commissions/entries', { params });
|
|
return response.data;
|
|
},
|
|
|
|
listPending: async (params?: { page?: number; limit?: number }): Promise<PaginatedEntries> => {
|
|
const response = await api.get<PaginatedEntries>('/commissions/entries/pending', { params });
|
|
return response.data;
|
|
},
|
|
|
|
get: async (id: string): Promise<CommissionEntry> => {
|
|
const response = await api.get<CommissionEntry>(`/commissions/entries/${id}`);
|
|
return response.data;
|
|
},
|
|
|
|
getByUser: async (userId: string, params?: { page?: number; limit?: number }): Promise<PaginatedEntries> => {
|
|
const response = await api.get<PaginatedEntries>(`/commissions/entries/user/${userId}`, { params });
|
|
return response.data;
|
|
},
|
|
|
|
getByPeriod: async (periodId: string, params?: { page?: number; limit?: number }): Promise<PaginatedEntries> => {
|
|
const response = await api.get<PaginatedEntries>(`/commissions/entries/period/${periodId}`, { params });
|
|
return response.data;
|
|
},
|
|
|
|
getByReference: async (type: string, refId: string): Promise<CommissionEntry | null> => {
|
|
const response = await api.get<CommissionEntry | { message: string }>(`/commissions/entries/reference/${type}/${refId}`);
|
|
if ('message' in response.data) {
|
|
return null;
|
|
}
|
|
return response.data;
|
|
},
|
|
|
|
calculate: async (data: CalculateCommissionDto): Promise<CommissionEntry> => {
|
|
const response = await api.post<CommissionEntry>('/commissions/entries/calculate', data);
|
|
return response.data;
|
|
},
|
|
|
|
simulate: async (data: CalculateCommissionDto): Promise<CalculationResult> => {
|
|
const response = await api.post<CalculationResult>('/commissions/entries/simulate', data);
|
|
return response.data;
|
|
},
|
|
|
|
updateStatus: async (id: string, data: UpdateEntryStatusDto): Promise<CommissionEntry> => {
|
|
const response = await api.patch<CommissionEntry>(`/commissions/entries/${id}/status`, data);
|
|
return response.data;
|
|
},
|
|
|
|
bulkApprove: async (entryIds: string[]): Promise<{ approved: number; failed: number }> => {
|
|
const response = await api.post<{ approved: number; failed: number }>('/commissions/entries/bulk-approve', { entry_ids: entryIds });
|
|
return response.data;
|
|
},
|
|
|
|
bulkReject: async (entryIds: string[], reason?: string): Promise<{ rejected: number; failed: number }> => {
|
|
const response = await api.post<{ rejected: number; failed: number }>('/commissions/entries/bulk-reject', { entry_ids: entryIds, reason });
|
|
return response.data;
|
|
},
|
|
|
|
cancelByReference: async (type: string, refId: string, reason?: string): Promise<CommissionEntry | null> => {
|
|
const response = await api.post<CommissionEntry | { message: string }>(`/commissions/entries/cancel/${type}/${refId}`, { reason });
|
|
if ('message' in response.data) {
|
|
return null;
|
|
}
|
|
return response.data;
|
|
},
|
|
};
|