Files
lti-web-client/src/services/api/expense.ts
T

543 lines
13 KiB
TypeScript

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<BaseApiResponse<Expense> | undefined> {
try {
const createExpenseRequestRes = await httpClient<
BaseApiResponse<Expense>
>(this.basePath, {
method: 'POST',
body: payload,
});
return createExpenseRequestRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async createRealization(
id: number,
payload: FormData
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const createExpenseRealizationRes = await httpClient<
BaseApiResponse<Expense>
>(`${this.basePath}/${id}/realizations`, {
method: 'POST',
body: payload,
});
return createExpenseRealizationRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async update(
id: number,
payload: FormData,
deletedDocumentIds?: number[]
): Promise<BaseApiResponse<Expense> | undefined> {
try {
for (const deletedDocumentId of deletedDocumentIds ?? []) {
await this.deleteExpenseRequestDocument(id, deletedDocumentId);
}
const updateExpenseRequestRes = await httpClient<
BaseApiResponse<Expense>
>(`${this.basePath}/${id}`, {
method: 'PATCH',
body: payload,
});
return updateExpenseRequestRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async updateRealization(
id: number,
payload: FormData
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const updateExpenseRealizationRes = await httpClient<
BaseApiResponse<Expense>
>(`${this.basePath}/${id}/realizations`, {
method: 'PATCH',
body: payload,
});
return updateExpenseRealizationRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async uploadRequestDocuments(
id: number,
files: File[]
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const updateExpenseRequestDocumentsFormData = new FormData();
// files (multiple "documents" keys)
files.forEach((file) => {
updateExpenseRequestDocumentsFormData.append('documents', file);
});
const updateExpenseRealizationRes = await httpClient<
BaseApiResponse<Expense>
>(`${this.basePath}/${id}`, {
method: 'PATCH',
body: updateExpenseRequestDocumentsFormData,
});
return updateExpenseRealizationRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async uploadRealizationDocuments(
id: number,
files: File[]
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const updateExpenseRealizationDocumentsFormData = new FormData();
// files (multiple "documents" keys)
files.forEach((file) => {
updateExpenseRealizationDocumentsFormData.append('documents', file);
});
const updateExpenseRealizationRes = await httpClient<
BaseApiResponse<Expense>
>(`${this.basePath}/${id}/realizations`, {
method: 'PATCH',
body: updateExpenseRealizationDocumentsFormData,
});
return updateExpenseRealizationRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async approveManager(
id: number,
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const approveRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/manager`,
{
method: 'POST',
body: {
action: 'APPROVED',
approvable_ids: [id],
notes: notes,
},
}
);
return approveRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async bulkApproveManager(
ids: number[],
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const bulkApproveRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/manager`,
{
method: 'POST',
body: {
action: 'APPROVED',
approvable_ids: ids,
notes: notes,
},
}
);
return bulkApproveRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async approveFinance(
id: number,
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const approveRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/finance`,
{
method: 'POST',
body: {
action: 'APPROVED',
approvable_ids: [id],
notes: notes,
},
}
);
return approveRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async bulkApproveFinance(
ids: number[],
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const bulkApproveRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/finance`,
{
method: 'POST',
body: {
action: 'APPROVED',
approvable_ids: ids,
notes: notes,
},
}
);
return bulkApproveRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async rejectManager(
id: number,
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const rejectRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/manager`,
{
method: 'POST',
body: {
action: 'REJECTED',
approvable_ids: [id],
notes: notes,
},
}
);
return rejectRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async bulkRejectManager(
ids: number[],
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const bulkRejectRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/manager`,
{
method: 'POST',
body: {
action: 'REJECTED',
approvable_ids: ids,
notes: notes,
},
}
);
return bulkRejectRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async rejectFinance(
id: number,
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const rejectRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/finance`,
{
method: 'POST',
body: {
action: 'REJECTED',
approvable_ids: [id],
notes: notes,
},
}
);
return rejectRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async bulkRejectFinance(
ids: number[],
notes?: string
): Promise<BaseApiResponse<Expense> | undefined> {
try {
const bulkRejectRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/approvals/finance`,
{
method: 'POST',
body: {
action: 'REJECTED',
approvable_ids: ids,
notes: notes,
},
}
);
return bulkRejectRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async complete(id: number): Promise<BaseApiResponse<Expense> | undefined> {
try {
const completeRes = await httpClient<BaseApiResponse<Expense>>(
`${this.basePath}/${id}/complete`,
{
method: 'POST',
}
);
return completeRes;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse<Expense>>(error)) {
return error.response?.data;
}
return undefined;
}
}
async deleteExpenseRequestDocument(
expenseId: number,
documentId: number
): Promise<BaseApiResponse | undefined> {
try {
const deleteExpenseRequestDocument = await httpClient<BaseApiResponse>(
`${this.basePath}/${expenseId}/documents/${documentId}`,
{
method: 'DELETE',
}
);
return deleteExpenseRequestDocument;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse>(error)) {
return error.response?.data;
}
return undefined;
}
}
async deleteExpenseRealizationDocument(
expenseId: number,
documentId: number
): Promise<BaseApiResponse | undefined> {
try {
const deleteExpenseRealizationDocument =
await httpClient<BaseApiResponse>(
`${this.basePath}/${expenseId}/realization-documents/${documentId}`,
{
method: 'DELETE',
}
);
return deleteExpenseRealizationDocument;
} catch (error) {
if (axios.isAxiosError<BaseApiResponse>(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<GroupedApprovals>(
'/approvals',
{
query: {
module_name: 'EXPENSES',
module_id: expenseId,
group_step_number: group ? 'true' : 'false',
page,
limit,
},
}
);
return approvalHistoryRes;
} catch (error) {
if (axios.isAxiosError<GroupedApprovals>(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');