import axios from 'axios'; import { sleep } from '@/lib/helper'; import { BaseApiService } from '@/services/api/base'; import { BaseApiResponse, GroupedApprovals } from '@/types/api/api-general'; import { CreateExpensePayload, CreateExpenseRealizationPayload, Expense, UpdateExpensePayload, } from '@/types/api/expense'; import { httpClient } from '@/services/http/client'; export class ExpenseApiService extends BaseApiService< Expense, FormData, FormData > { constructor(basePath: string) { super(basePath); } async create( payload: FormData ): Promise | undefined> { try { const createExpenseRequestRes = await httpClient< BaseApiResponse >(this.basePath, { method: 'POST', body: payload, }); return createExpenseRequestRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async createRealization( id: number, payload: FormData ): Promise | undefined> { try { const createExpenseRealizationRes = await httpClient< BaseApiResponse >(`${this.basePath}/${id}/realizations`, { method: 'POST', body: payload, }); return createExpenseRealizationRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async update( id: number, payload: FormData, deletedDocumentIds?: number[] ): Promise | undefined> { try { for (const deletedDocumentId of deletedDocumentIds ?? []) { await this.deleteExpenseRequestDocument(id, deletedDocumentId); } const updateExpenseRequestRes = await httpClient< BaseApiResponse >(`${this.basePath}/${id}`, { method: 'PATCH', body: payload, }); return updateExpenseRequestRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async updateRealization( id: number, payload: FormData ): Promise | undefined> { try { const updateExpenseRealizationRes = await httpClient< BaseApiResponse >(`${this.basePath}/${id}/realizations`, { method: 'PATCH', body: payload, }); return updateExpenseRealizationRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async uploadRequestDocuments( id: number, files: File[] ): Promise | undefined> { try { const updateExpenseRequestDocumentsFormData = new FormData(); // files (multiple "documents" keys) files.forEach((file) => { updateExpenseRequestDocumentsFormData.append('documents', file); }); const updateExpenseRealizationRes = await httpClient< BaseApiResponse >(`${this.basePath}/${id}`, { method: 'PATCH', body: updateExpenseRequestDocumentsFormData, }); return updateExpenseRealizationRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async uploadRealizationDocuments( id: number, files: File[] ): Promise | undefined> { try { const updateExpenseRealizationDocumentsFormData = new FormData(); // files (multiple "documents" keys) files.forEach((file) => { updateExpenseRealizationDocumentsFormData.append('documents', file); }); const updateExpenseRealizationRes = await httpClient< BaseApiResponse >(`${this.basePath}/${id}/realizations`, { method: 'PATCH', body: updateExpenseRealizationDocumentsFormData, }); return updateExpenseRealizationRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async approveManager( id: number, notes?: string ): Promise | undefined> { try { const approveRes = await httpClient>( `${this.basePath}/approvals/manager`, { method: 'POST', body: { action: 'APPROVED', approvable_ids: [id], notes: notes, }, } ); return approveRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async bulkApproveManager( ids: number[], notes?: string ): Promise | undefined> { try { const bulkApproveRes = await httpClient>( `${this.basePath}/approvals/manager`, { method: 'POST', body: { action: 'APPROVED', approvable_ids: ids, notes: notes, }, } ); return bulkApproveRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async approveFinance( id: number, notes?: string ): Promise | undefined> { try { const approveRes = await httpClient>( `${this.basePath}/approvals/finance`, { method: 'POST', body: { action: 'APPROVED', approvable_ids: [id], notes: notes, }, } ); return approveRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async bulkApproveFinance( ids: number[], notes?: string ): Promise | undefined> { try { const bulkApproveRes = await httpClient>( `${this.basePath}/approvals/finance`, { method: 'POST', body: { action: 'APPROVED', approvable_ids: ids, notes: notes, }, } ); return bulkApproveRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async rejectManager( id: number, notes?: string ): Promise | undefined> { try { const rejectRes = await httpClient>( `${this.basePath}/approvals/manager`, { method: 'POST', body: { action: 'REJECTED', approvable_ids: [id], notes: notes, }, } ); return rejectRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async bulkRejectManager( ids: number[], notes?: string ): Promise | undefined> { try { const bulkRejectRes = await httpClient>( `${this.basePath}/approvals/manager`, { method: 'POST', body: { action: 'REJECTED', approvable_ids: ids, notes: notes, }, } ); return bulkRejectRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async rejectFinance( id: number, notes?: string ): Promise | undefined> { try { const rejectRes = await httpClient>( `${this.basePath}/approvals/finance`, { method: 'POST', body: { action: 'REJECTED', approvable_ids: [id], notes: notes, }, } ); return rejectRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async bulkRejectFinance( ids: number[], notes?: string ): Promise | undefined> { try { const bulkRejectRes = await httpClient>( `${this.basePath}/approvals/finance`, { method: 'POST', body: { action: 'REJECTED', approvable_ids: ids, notes: notes, }, } ); return bulkRejectRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async complete(id: number): Promise | undefined> { try { const completeRes = await httpClient>( `${this.basePath}/${id}/complete`, { method: 'POST', } ); return completeRes; } catch (error) { if (axios.isAxiosError>(error)) { return error.response?.data; } return undefined; } } async deleteExpenseRequestDocument( expenseId: number, documentId: number ): Promise { try { const deleteExpenseRequestDocument = await httpClient( `${this.basePath}/${expenseId}/documents/${documentId}`, { method: 'DELETE', } ); return deleteExpenseRequestDocument; } catch (error) { if (axios.isAxiosError(error)) { return error.response?.data; } return undefined; } } async deleteExpenseRealizationDocument( expenseId: number, documentId: number ): Promise { try { const deleteExpenseRealizationDocument = await httpClient( `${this.basePath}/${expenseId}/realization-documents/${documentId}`, { method: 'DELETE', } ); return deleteExpenseRealizationDocument; } catch (error) { if (axios.isAxiosError(error)) { return error.response?.data; } return undefined; } } async getApprovalHistory( expenseId: number, group: boolean = true, page: number = 1, limit: number = 10 ) { try { const approvalHistoryRes = await httpClient( '/approvals', { query: { module_name: 'EXPENSES', module_id: expenseId, group_step_number: group ? 'true' : 'false', page, limit, }, } ); return approvalHistoryRes; } catch (error) { if (axios.isAxiosError(error)) { return error.response?.data; } return undefined; } } convertExpenseRequestPayloadToFormData = (payload: CreateExpensePayload) => { const formData = new FormData(); formData.append('category', payload.category); formData.append('transaction_date', payload.transaction_date); formData.append('supplier_id', String(payload.supplier_id)); // files (multiple "documents" keys) payload.documents.forEach((file) => { formData.append('documents', file); }); formData.append( 'cost_per_kandangs', JSON.stringify(payload.cost_per_kandangs) ); return formData; }; convertExpenseRequestUpdatePayloadToFormData = ( payload: UpdateExpensePayload ) => { const formData = new FormData(); formData.append('category', payload.category); formData.append('transaction_date', payload.transaction_date); formData.append('supplier_id', String(payload.supplier_id)); // files (multiple "documents" keys) payload.documents.forEach((file) => { formData.append('documents', file); }); formData.append( 'cost_per_kandang', JSON.stringify(payload.cost_per_kandang) ); return formData; }; convertExpenseRealizationPayloadToFormData = ( payload: CreateExpenseRealizationPayload ) => { const formData = new FormData(); formData.append('realization_date', payload.realization_date); // files (multiple "documents" keys) payload.documents.forEach((file) => { formData.append('documents', file); }); formData.append('realizations', JSON.stringify(payload.realizations)); return formData; }; } export const ExpenseApi = new ExpenseApiService('/expenses');