|
- import { clientAuthFetch } from "@/app/utils/clientAuthFetch";
- import { NEXT_PUBLIC_API_URL } from "@/config/api";
-
- const BASE = `${NEXT_PUBLIC_API_URL}/chart`;
-
- function buildParams(params: Record<string, string | number | undefined>) {
- const p = new URLSearchParams();
- Object.entries(params).forEach(([k, v]) => {
- if (v !== undefined && v !== "") p.set(k, String(v));
- });
- return p.toString();
- }
-
- export interface StockTransactionsByDateRow {
- date: string;
- inQty: number;
- outQty: number;
- totalQty: number;
- }
-
- export interface DeliveryOrderByDateRow {
- date: string;
- orderCount: number;
- totalQty: number;
- }
-
- export interface PurchaseOrderByStatusRow {
- status: string;
- count: number;
- }
-
- export interface StockInOutByDateRow {
- date: string;
- inQty: number;
- outQty: number;
- }
-
- export interface TopDeliveryItemsRow {
- itemCode: string;
- itemName: string;
- totalQty: number;
- }
-
- export interface StockBalanceTrendRow {
- date: string;
- balance: number;
- }
-
- export interface ConsumptionTrendByMonthRow {
- month: string;
- outQty: number;
- }
-
- export interface StaffDeliveryPerformanceRow {
- date: string;
- staffName: string;
- orderCount: number;
- totalMinutes: number;
- }
-
- export interface StaffOption {
- staffNo: string;
- name: string;
- }
-
- export async function fetchStaffDeliveryPerformanceHandlers(): Promise<StaffOption[]> {
- const res = await clientAuthFetch(`${BASE}/staff-delivery-performance-handlers`);
- if (!res.ok) throw new Error("Failed to fetch staff list");
- const data = await res.json();
- if (!Array.isArray(data)) return [];
- return (data as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- staffNo: String(r.staffNo ?? ""),
- name: String(r.name ?? ""),
- }));
- }
-
- // Job order
- export interface JobOrderByStatusRow {
- status: string;
- count: number;
- }
-
- export interface JobOrderCountByDateRow {
- date: string;
- orderCount: number;
- }
-
- export interface JobOrderCreatedCompletedRow {
- date: string;
- createdCount: number;
- completedCount: number;
- }
-
- export interface ProductionScheduleByDateRow {
- date: string;
- scheduledItemCount: number;
- totalEstProdCount: number;
- }
-
- export interface PlannedDailyOutputRow {
- itemCode: string;
- itemName: string;
- dailyQty: number;
- }
-
- export async function fetchJobOrderByStatus(
- targetDate?: string
- ): Promise<JobOrderByStatusRow[]> {
- const q = targetDate ? buildParams({ targetDate }) : "";
- const res = await clientAuthFetch(
- q ? `${BASE}/job-order-by-status?${q}` : `${BASE}/job-order-by-status`
- );
- if (!res.ok) throw new Error("Failed to fetch job order by status");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- status: String(r.status ?? ""),
- count: Number(r.count ?? 0),
- }));
- }
-
- export async function fetchJobOrderCountByDate(
- startDate?: string,
- endDate?: string
- ): Promise<JobOrderCountByDateRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/job-order-count-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch job order count by date");
- const data = await res.json();
- return normalizeChartRows(data, "date", ["orderCount"]);
- }
-
- export async function fetchJobOrderCreatedCompletedByDate(
- startDate?: string,
- endDate?: string
- ): Promise<JobOrderCreatedCompletedRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(
- `${BASE}/job-order-created-completed-by-date?${q}`
- );
- if (!res.ok) throw new Error("Failed to fetch job order created/completed");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- createdCount: Number(r.createdCount ?? 0),
- completedCount: Number(r.completedCount ?? 0),
- }));
- }
-
- export interface JobMaterialPendingPickedRow {
- date: string;
- pendingCount: number;
- pickedCount: number;
- }
-
- export async function fetchJobMaterialPendingPickedByDate(
- startDate?: string,
- endDate?: string
- ): Promise<JobMaterialPendingPickedRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/job-material-pending-picked-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch job material pending/picked");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- pendingCount: Number(r.pendingCount ?? 0),
- pickedCount: Number(r.pickedCount ?? 0),
- }));
- }
-
- export interface JobProcessPendingCompletedRow {
- date: string;
- pendingCount: number;
- completedCount: number;
- }
-
- export async function fetchJobProcessPendingCompletedByDate(
- startDate?: string,
- endDate?: string
- ): Promise<JobProcessPendingCompletedRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/job-process-pending-completed-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch job process pending/completed");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- pendingCount: Number(r.pendingCount ?? 0),
- completedCount: Number(r.completedCount ?? 0),
- }));
- }
-
- export interface JobEquipmentWorkingWorkedRow {
- date: string;
- workingCount: number;
- workedCount: number;
- }
-
- export async function fetchJobEquipmentWorkingWorkedByDate(
- startDate?: string,
- endDate?: string
- ): Promise<JobEquipmentWorkingWorkedRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/job-equipment-working-worked-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch job equipment working/worked");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- workingCount: Number(r.workingCount ?? 0),
- workedCount: Number(r.workedCount ?? 0),
- }));
- }
-
- export async function fetchProductionScheduleByDate(
- startDate?: string,
- endDate?: string
- ): Promise<ProductionScheduleByDateRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(
- `${BASE}/production-schedule-by-date?${q}`
- );
- if (!res.ok) throw new Error("Failed to fetch production schedule by date");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- scheduledItemCount: Number(r.scheduledItemCount ?? r.scheduleCount ?? 0),
- totalEstProdCount: Number(r.totalEstProdCount ?? 0),
- }));
- }
-
- export async function fetchPlannedDailyOutputByItem(
- limit = 20
- ): Promise<PlannedDailyOutputRow[]> {
- const res = await clientAuthFetch(
- `${BASE}/planned-daily-output-by-item?limit=${limit}`
- );
- if (!res.ok) throw new Error("Failed to fetch planned daily output");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- itemCode: String(r.itemCode ?? ""),
- itemName: String(r.itemName ?? ""),
- dailyQty: Number(r.dailyQty ?? 0),
- }));
- }
-
- /** Planned production by date and by item (production_schedule). */
- export interface PlannedOutputByDateAndItemRow {
- date: string;
- itemCode: string;
- itemName: string;
- qty: number;
- }
-
- export async function fetchPlannedOutputByDateAndItem(
- startDate?: string,
- endDate?: string
- ): Promise<PlannedOutputByDateAndItemRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(
- q ? `${BASE}/planned-output-by-date-and-item?${q}` : `${BASE}/planned-output-by-date-and-item`
- );
- if (!res.ok) throw new Error("Failed to fetch planned output by date and item");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- date: String(r.date ?? ""),
- itemCode: String(r.itemCode ?? ""),
- itemName: String(r.itemName ?? ""),
- qty: Number(r.qty ?? 0),
- }));
- }
-
- export async function fetchStaffDeliveryPerformance(
- startDate?: string,
- endDate?: string,
- staffNos?: string[]
- ): Promise<StaffDeliveryPerformanceRow[]> {
- const p = new URLSearchParams();
- if (startDate) p.set("startDate", startDate);
- if (endDate) p.set("endDate", endDate);
- (staffNos ?? []).forEach((no) => p.append("staffNo", no));
- const q = p.toString();
- const res = await clientAuthFetch(
- q ? `${BASE}/staff-delivery-performance?${q}` : `${BASE}/staff-delivery-performance`
- );
- if (!res.ok) throw new Error("Failed to fetch staff delivery performance");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => {
- // Accept camelCase or lowercase keys (JDBC/DB may return different casing)
- const row = r as Record<string, unknown>;
- return {
- date: String(row.date ?? row.Date ?? ""),
- staffName: String(row.staffName ?? row.staffname ?? ""),
- orderCount: Number(row.orderCount ?? row.ordercount ?? 0),
- totalMinutes: Number(row.totalMinutes ?? row.totalminutes ?? 0),
- };
- });
- }
-
- export async function fetchStockTransactionsByDate(
- startDate?: string,
- endDate?: string
- ): Promise<StockTransactionsByDateRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/stock-transactions-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch stock transactions by date");
- const data = await res.json();
- return normalizeChartRows(data, "date", ["inQty", "outQty", "totalQty"]);
- }
-
- export async function fetchDeliveryOrderByDate(
- startDate?: string,
- endDate?: string
- ): Promise<DeliveryOrderByDateRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/delivery-order-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch delivery order by date");
- const data = await res.json();
- return normalizeChartRows(data, "date", ["orderCount", "totalQty"]);
- }
-
- export async function fetchPurchaseOrderByStatus(
- targetDate?: string
- ): Promise<PurchaseOrderByStatusRow[]> {
- const q = targetDate
- ? buildParams({ targetDate })
- : "";
- const res = await clientAuthFetch(
- q ? `${BASE}/purchase-order-by-status?${q}` : `${BASE}/purchase-order-by-status`
- );
- if (!res.ok) throw new Error("Failed to fetch purchase order by status");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- status: String(r.status ?? ""),
- count: Number(r.count ?? 0),
- }));
- }
-
- export async function fetchStockInOutByDate(
- startDate?: string,
- endDate?: string
- ): Promise<StockInOutByDateRow[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(`${BASE}/stock-in-out-by-date?${q}`);
- if (!res.ok) throw new Error("Failed to fetch stock in/out by date");
- const data = await res.json();
- return normalizeChartRows(data, "date", ["inQty", "outQty"]);
- }
-
- export interface TopDeliveryItemOption {
- itemCode: string;
- itemName: string;
- }
-
- export async function fetchTopDeliveryItemsItemOptions(
- startDate?: string,
- endDate?: string
- ): Promise<TopDeliveryItemOption[]> {
- const q = buildParams({ startDate: startDate ?? "", endDate: endDate ?? "" });
- const res = await clientAuthFetch(
- q ? `${BASE}/top-delivery-items-item-options?${q}` : `${BASE}/top-delivery-items-item-options`
- );
- if (!res.ok) throw new Error("Failed to fetch item options");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- itemCode: String(r.itemCode ?? ""),
- itemName: String(r.itemName ?? ""),
- }));
- }
-
- export async function fetchTopDeliveryItems(
- startDate?: string,
- endDate?: string,
- limit = 10,
- itemCodes?: string[]
- ): Promise<TopDeliveryItemsRow[]> {
- const p = new URLSearchParams();
- if (startDate) p.set("startDate", startDate);
- if (endDate) p.set("endDate", endDate);
- p.set("limit", String(limit));
- (itemCodes ?? []).forEach((code) => p.append("itemCode", code));
- const q = p.toString();
- const res = await clientAuthFetch(`${BASE}/top-delivery-items?${q}`);
- if (!res.ok) throw new Error("Failed to fetch top delivery items");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- itemCode: String(r.itemCode ?? ""),
- itemName: String(r.itemName ?? ""),
- totalQty: Number(r.totalQty ?? 0),
- }));
- }
-
- export async function fetchStockBalanceTrend(
- startDate?: string,
- endDate?: string,
- itemCode?: string
- ): Promise<StockBalanceTrendRow[]> {
- const q = buildParams({
- startDate: startDate ?? "",
- endDate: endDate ?? "",
- itemCode: itemCode ?? "",
- });
- const res = await clientAuthFetch(`${BASE}/stock-balance-trend?${q}`);
- if (!res.ok) throw new Error("Failed to fetch stock balance trend");
- const data = await res.json();
- return normalizeChartRows(data, "date", ["balance"]);
- }
-
- export async function fetchConsumptionTrendByMonth(
- year?: number,
- startDate?: string,
- endDate?: string,
- itemCode?: string
- ): Promise<ConsumptionTrendByMonthRow[]> {
- const q = buildParams({
- year: year ?? "",
- startDate: startDate ?? "",
- endDate: endDate ?? "",
- itemCode: itemCode ?? "",
- });
- const res = await clientAuthFetch(`${BASE}/consumption-trend-by-month?${q}`);
- if (!res.ok) throw new Error("Failed to fetch consumption trend");
- const data = await res.json();
- return ((Array.isArray(data) ? data : []) as Record<string, unknown>[]).map((r: Record<string, unknown>) => ({
- month: String(r.month ?? ""),
- outQty: Number(r.outQty ?? 0),
- }));
- }
-
- /** Normalize rows: ensure date key is string and numeric keys are numbers (backend may return BigDecimal/Long). */
- function normalizeChartRows<T>(
- rows: unknown[],
- dateKey: string,
- numberKeys: string[]
- ): T[] {
- if (!Array.isArray(rows)) return [];
- return rows.map((r: unknown) => {
- const row = r as Record<string, unknown>;
- const out: Record<string, unknown> = {};
- out[dateKey] = row[dateKey] != null ? String(row[dateKey]) : "";
- numberKeys.forEach((k) => {
- out[k] = Number(row[k]) || 0;
- });
- return out as T;
- });
- }
|