mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
543 lines
13 KiB
TypeScript
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');
|