Files
lti-web-client/src/services/api/marketing/marketing.ts
T
2026-01-30 15:53:51 +07:00

184 lines
5.0 KiB
TypeScript

import { isResponseError } from '@/lib/api-helper';
import { BaseApiService } from '@/services/api/base';
import { httpClient, httpClientFetcher } from '@/services/http/client';
import { BaseApiResponse } from '@/types/api/api-general';
import {
Marketing,
CreateSalesOrderPayload,
UpdateSalesOrderPayload,
CreateDeliveryOrderPayload,
UpdateDeliveryOrderPayload,
} from '@/types/api/marketing/marketing';
import toast from 'react-hot-toast';
import * as XLSX from 'xlsx';
import { formatCurrency, formatDate, formatTitleCase } from '@/lib/helper';
/**
* 💡 Helper untuk membuat respons dummy
* @param data Data yang akan dimasukkan ke dalam body respons
*/
const createDummyResponse = <T>(data: T): BaseApiResponse<T> => ({
code: 200,
status: 'success',
message: 'Data retrieved successfully (MOCK)',
data: data,
});
export class SalesOrderService extends BaseApiService<
Marketing,
CreateSalesOrderPayload,
UpdateSalesOrderPayload
> {
constructor(basePath: string = '/marketing') {
super(basePath);
}
/**
* Approve single marketing data
*/
async singleApproval(
id: number,
action: 'APPROVED' | 'REJECTED',
notes?: string
): Promise<BaseApiResponse<{ message: string }> | undefined> {
try {
const path = `${this.basePath}/approvals`;
return await httpClient<BaseApiResponse<{ message: string }>>(path, {
method: 'POST',
body: {
action: action,
approvable_ids: [id],
notes: notes || `${action} marketing ${id}`,
},
});
} catch (error) {
throw error;
}
}
/**
* Bulk approve
*/
async bulkApprovals(
ids: number[],
action: 'APPROVED' | 'REJECTED',
notes?: string
): Promise<BaseApiResponse<{ message: string }> | undefined> {
try {
const path = `${this.basePath}/approvals`;
return await httpClient<BaseApiResponse<{ message: string }>>(path, {
method: 'POST',
body: {
action: action,
approvable_ids: ids,
notes: notes || `${action} marketing ${ids.join(', ')}`,
},
});
} catch (error) {
throw error;
}
}
/**
* Delivery
*/
async delivery(
id: number,
notes?: string
): Promise<BaseApiResponse<{ message: string }> | undefined> {
try {
const path = `${this.basePath}/approvals`;
return await httpClient<BaseApiResponse<{ message: string }>>(path, {
method: 'POST',
body: {
action: 'APPROVED',
approvable_ids: [id],
notes: notes || `Delivery marketing ${id}`,
},
});
} catch (error) {
throw error;
}
}
}
class MarketingExportService extends BaseApiService<
Marketing,
unknown,
unknown
> {
constructor(basePath: string = '/marketing') {
super(basePath);
}
/**
* Export to Excel
*/
async exportToExcel(initialQueryString: string) {
const params = new URLSearchParams(initialQueryString);
const queryString = `?${params.toString()}`;
try {
const marketingData = await httpClientFetcher<
BaseApiResponse<Marketing[]>
>(`${this.basePath}${queryString}`);
if (isResponseError(marketingData)) {
toast.error('Gagal melakukan export marketing! Coba lagi.');
return;
}
const rows = marketingData.data;
const formattedRows = [];
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
const approval = row.latest_approval;
const isRejected = approval?.action === 'REJECTED';
// Calculate grand total from sales_order products
const grandTotal =
row.sales_order
?.map((product) => product.total_price)
.reduce((a, b) => a + b, 0) ?? 0;
// Get product names
const products =
row.sales_order
?.map((product) => product.product_warehouse?.product?.name)
.filter(Boolean)
.join(', ') ?? '';
formattedRows.push({
'No. Order': row.so_number,
Tanggal: formatDate(row.so_date, 'DD-MM-YYYY'),
Status: isRejected
? 'Ditolak'
: formatTitleCase(approval?.step_name || ''),
Customer: row.customer?.name || '',
'Grand Total': formatCurrency(grandTotal),
Products: products,
Notes: row.notes || '',
});
}
const ws = XLSX.utils.json_to_sheet(formattedRows);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'marketing');
// triggers download in browser
XLSX.writeFile(wb, 'marketing.xlsx');
} catch (error) {
toast.error('Gagal melakukan export marketing! Coba lagi.');
}
}
}
export const SalesOrderApi = new SalesOrderService('/marketing/sales-orders');
export const DeliveryOrderApi = new BaseApiService<
Marketing,
CreateDeliveryOrderPayload,
UpdateDeliveryOrderPayload
>('/marketing/delivery-orders');
export const MarketingApi = new MarketingExportService('/marketing');