mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 17:38:12 +00:00
Warehouse Enhancemendt
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
|
||||
import type { FleetListFilters, FleetResourceSlug } from "@/services/fleet/fleet.service";
|
||||
import { fleetService } from "@/services/fleet/fleet.service";
|
||||
|
||||
export function useFleetList(slug: FleetResourceSlug) {
|
||||
export function useFleetList(slug: FleetResourceSlug, filters?: FleetListFilters) {
|
||||
return useQuery({
|
||||
queryKey: QUERY_KEYS.FLEET.list(slug),
|
||||
queryFn: () => fleetService.list(slug),
|
||||
queryKey: [...QUERY_KEYS.FLEET.list(slug), filters ?? {}],
|
||||
queryFn: () => fleetService.list(slug, filters),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
CreateTrainSchedulePayload,
|
||||
FreightType,
|
||||
PinWagonsPayload,
|
||||
RecordCheckpointPayload,
|
||||
TrainScheduleFilters,
|
||||
TrainSchedulePreviewPayload,
|
||||
} from "@/types/trainScheduling";
|
||||
@@ -17,6 +18,34 @@ export const useScheduleList = (freightType?: FreightType) =>
|
||||
queryFn: () => trainSchedulingService.listSchedules(freightType),
|
||||
});
|
||||
|
||||
export const useBatchBoard = () =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(),
|
||||
queryFn: () => trainSchedulingService.getBatchBoard(),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const useBatchBoardDetail = (scheduleId: string | undefined) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId ?? ""),
|
||||
queryFn: () => trainSchedulingService.getBatchBoardDetail(scheduleId!),
|
||||
enabled: Boolean(scheduleId),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const useRunAllocation = (scheduleId: string) => {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: () => trainSchedulingService.runAllocation(scheduleId),
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard() });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useScheduleDetail = (id: string | undefined, freightType?: FreightType) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(id ?? ""),
|
||||
@@ -35,10 +64,79 @@ export const useEligibleBookings = (
|
||||
enabled,
|
||||
});
|
||||
|
||||
export const useAvailableLocomotives = () =>
|
||||
export const useAvailableLocomotives = (routeId?: string) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.locomotives(),
|
||||
queryFn: () => trainSchedulingService.getAvailableLocomotives(),
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.locomotives(routeId),
|
||||
queryFn: () => trainSchedulingService.getAvailableLocomotives(routeId),
|
||||
enabled: routeId ? Boolean(routeId) : true,
|
||||
});
|
||||
|
||||
export const useBatchActions = (scheduleId?: string) => {
|
||||
const qc = useQueryClient();
|
||||
const invalidate = () => {
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.ROOT });
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.BOOKINGS.ROOT });
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoard() });
|
||||
if (scheduleId) {
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const runBatch = useMutation({
|
||||
mutationFn: (id: string) => trainSchedulingService.runBatch(id),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
const setWindow = useMutation({
|
||||
mutationFn: ({ id, status }: { id: string; status: "OPEN" | "CLOSED" }) =>
|
||||
trainSchedulingService.setBookingWindow(id, status),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
const markPaid = useMutation({
|
||||
mutationFn: (bookingId: string) => trainSchedulingService.markBookingPaid(bookingId),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
const expire = useMutation({
|
||||
mutationFn: (bookingId: string) => trainSchedulingService.expireBooking(bookingId),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
const moveSchedule = useMutation({
|
||||
mutationFn: ({ bookingId, trainScheduleId }: { bookingId: string; trainScheduleId: string }) =>
|
||||
trainSchedulingService.moveBookingSchedule(bookingId, trainScheduleId),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
return { runBatch, setWindow, markPaid, expire, moveSchedule, invalidate };
|
||||
};
|
||||
|
||||
export const useBookableSchedules = (
|
||||
originYardId?: string | null,
|
||||
destinationYardId?: string | null,
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: [
|
||||
...QUERY_KEYS.TRAIN_SCHEDULING.ROOT,
|
||||
"bookable",
|
||||
originYardId ?? "",
|
||||
destinationYardId ?? "",
|
||||
],
|
||||
queryFn: () =>
|
||||
trainSchedulingService.getBookableSchedules(
|
||||
originYardId ?? undefined,
|
||||
destinationYardId ?? undefined,
|
||||
),
|
||||
enabled: Boolean(originYardId && destinationYardId),
|
||||
});
|
||||
|
||||
export const useTrainTrack = (id: string | undefined) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.track(id ?? ""),
|
||||
queryFn: () => trainSchedulingService.getTrack(id!),
|
||||
enabled: Boolean(id),
|
||||
});
|
||||
|
||||
export const useScheduleMutations = (scheduleId?: string) => {
|
||||
@@ -52,6 +150,15 @@ export const useScheduleMutations = (scheduleId?: string) => {
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.track(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.unassignedBookings(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId),
|
||||
});
|
||||
}
|
||||
void qc.invalidateQueries({ queryKey: QUERY_KEYS.BOOKINGS.ROOT });
|
||||
};
|
||||
@@ -90,6 +197,12 @@ export const useScheduleMutations = (scheduleId?: string) => {
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
const assignUnassigned = useMutation({
|
||||
mutationFn: ({ id, bookingId }: { id: string; bookingId: string }) =>
|
||||
trainSchedulingService.assignUnassignedBooking(id, bookingId),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
const unassign = useMutation({
|
||||
mutationFn: ({ id, bookingId }: { id: string; bookingId: string }) =>
|
||||
trainSchedulingService.unassignBooking(id, bookingId),
|
||||
@@ -118,5 +231,72 @@ export const useScheduleMutations = (scheduleId?: string) => {
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
return { create, preview, assign, unassign, pin, finalize, dispatch, cancel, invalidate };
|
||||
const recordCheckpoint = useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: RecordCheckpointPayload }) =>
|
||||
trainSchedulingService.recordCheckpoint(id, payload),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
const arrive = useMutation({
|
||||
mutationFn: (id: string) => trainSchedulingService.arriveSchedule(id),
|
||||
onSuccess: invalidate,
|
||||
});
|
||||
|
||||
return {
|
||||
create,
|
||||
preview,
|
||||
assign,
|
||||
assignUnassigned,
|
||||
unassign,
|
||||
pin,
|
||||
finalize,
|
||||
dispatch,
|
||||
cancel,
|
||||
recordCheckpoint,
|
||||
arrive,
|
||||
invalidate,
|
||||
};
|
||||
};
|
||||
|
||||
export const useUnassignedBookings = (scheduleId: string | undefined) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.unassignedBookings(scheduleId ?? ""),
|
||||
queryFn: () => trainSchedulingService.getUnassignedBookings(scheduleId!),
|
||||
enabled: Boolean(scheduleId),
|
||||
});
|
||||
|
||||
export const useCompositionRemovals = (scheduleId: string | undefined) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId ?? ""),
|
||||
queryFn: () => trainSchedulingService.getCompositionRemovals(scheduleId!),
|
||||
enabled: Boolean(scheduleId),
|
||||
});
|
||||
|
||||
export const useRemoveWagonSlot = (scheduleId: string) => {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (wagonId: string) =>
|
||||
trainSchedulingService.removeWagonSlot(scheduleId, wagonId),
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateContainerItem = (scheduleId: string) => {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ itemId, containerNumber }: { itemId: string; containerNumber: string | null }) =>
|
||||
trainSchedulingService.updateContainerItem(scheduleId, itemId, { containerNumber }),
|
||||
onSuccess: () => {
|
||||
void qc.invalidateQueries({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.scheduleById(scheduleId),
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { cargoService } from '@/services/cargoService';
|
||||
import { cargoService, type DeliverCargoPayload } from '@/services/cargoService';
|
||||
|
||||
export const cargoKeys = {
|
||||
all: ['cargoes'] as const,
|
||||
@@ -53,7 +53,8 @@ export function useLoadCargo() {
|
||||
export function useDeliverCargo() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => cargoService.deliver(id),
|
||||
mutationFn: ({ id, payload }: { id: string; payload?: DeliverCargoPayload }) =>
|
||||
cargoService.deliver(id, payload),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: cargoKeys.all })
|
||||
});
|
||||
}
|
||||
|
||||
16
apps/edr-freight-web/backoffice/src/hooks/useFacilities.ts
Normal file
16
apps/edr-freight-web/backoffice/src/hooks/useFacilities.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { facilityService } from '@/services/facility.service';
|
||||
|
||||
export const facilityKeys = {
|
||||
all: ['facilities'] as const,
|
||||
list: () => ['facilities', 'list'] as const,
|
||||
detail: (id: string) => ['facilities', 'detail', id] as const,
|
||||
};
|
||||
|
||||
export function useFacilities() {
|
||||
return useQuery({
|
||||
queryKey: facilityKeys.list(),
|
||||
queryFn: () => facilityService.list().then((r) => r.data),
|
||||
});
|
||||
}
|
||||
23
apps/edr-freight-web/backoffice/src/hooks/usePayments.ts
Normal file
23
apps/edr-freight-web/backoffice/src/hooks/usePayments.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
paymentsService,
|
||||
type PaymentListFilter,
|
||||
} from "@/services/payments.service";
|
||||
|
||||
export function usePaymentList(filter?: PaymentListFilter, enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: ["payments", "list", filter ?? {}],
|
||||
queryFn: () => paymentsService.list(filter),
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
|
||||
export function usePaymentSummary(enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: ["payments", "summary"],
|
||||
queryFn: () => paymentsService.getSummary(),
|
||||
staleTime: 30_000,
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
import {
|
||||
signaturesService,
|
||||
type SaveSignaturePayload,
|
||||
} from "@/services/signatures.service";
|
||||
|
||||
const SAVED_SIGNATURE_KEY = ["me", "signature"] as const;
|
||||
|
||||
export function useMySignature() {
|
||||
return useQuery({
|
||||
queryKey: SAVED_SIGNATURE_KEY,
|
||||
queryFn: () => signaturesService.getMySignature(),
|
||||
staleTime: 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useSaveSignature() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (payload: SaveSignaturePayload) =>
|
||||
signaturesService.saveMySignature(payload),
|
||||
onSuccess: () => {
|
||||
toast.success("Signature saved");
|
||||
void qc.invalidateQueries({ queryKey: SAVED_SIGNATURE_KEY });
|
||||
},
|
||||
onError: () => toast.error("Failed to save signature"),
|
||||
});
|
||||
}
|
||||
16
apps/edr-freight-web/backoffice/src/hooks/useStations.ts
Normal file
16
apps/edr-freight-web/backoffice/src/hooks/useStations.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { trainSchedulingService } from '@/services/trainScheduling.service';
|
||||
import { QUERY_KEYS } from '@/constants/QUERY_KEYS';
|
||||
|
||||
/**
|
||||
* The 21 network stations / yards, sourced from the existing booking
|
||||
* reference-data API. Reused as the parent "Facility / Port" for warehouses.
|
||||
*/
|
||||
export function useStations() {
|
||||
return useQuery({
|
||||
queryKey: QUERY_KEYS.TRAIN_SCHEDULING.stations(),
|
||||
queryFn: () => trainSchedulingService.getStations(),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
@@ -1,15 +1,21 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { wagonService } from '@/services/wagon.service';
|
||||
|
||||
export type WagonListFilters = import('@/services/wagon.service').WagonListFilters;
|
||||
|
||||
export const wagonKeys = {
|
||||
all: ['wagons'] as const,
|
||||
list: (filters?: WagonListFilters) => [...wagonKeys.all, 'list', filters ?? {}] as const,
|
||||
byTrain: (trainId: string) => [...wagonKeys.all, 'train', trainId] as const,
|
||||
details: () => [...wagonKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...wagonKeys.details(), id] as const,
|
||||
};
|
||||
|
||||
export function useWagons() {
|
||||
return useQuery({ queryKey: wagonKeys.all, queryFn: () => wagonService.getAll().then(res => res.data) });
|
||||
export function useWagons(filters?: WagonListFilters) {
|
||||
return useQuery({
|
||||
queryKey: wagonKeys.list(filters),
|
||||
queryFn: () => wagonService.getAll(filters ?? {}).then((res) => res.data),
|
||||
});
|
||||
}
|
||||
|
||||
export const useGetWagons = useWagons;
|
||||
|
||||
@@ -2,10 +2,18 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { warehouseService } from '@/services/warehouse.service';
|
||||
import type {
|
||||
InspectionReportPayload,
|
||||
SaveAllocationRulePayload,
|
||||
SaveFeeRulePayload,
|
||||
WarehouseInvoiceFilter,
|
||||
PayInvoicePayload,
|
||||
InventoryFilter,
|
||||
InventoryInquiryFilter,
|
||||
LoadInventoryPayload,
|
||||
MoveInventoryPayload,
|
||||
ReceiveInventoryPayload,
|
||||
ReleaseOrderPayload,
|
||||
DeliverInventoryPayload,
|
||||
ReserveInventoryPayload,
|
||||
SaveWarehousePayload,
|
||||
SaveYardPayload,
|
||||
@@ -179,59 +187,93 @@ export function useReserveInventory() {
|
||||
});
|
||||
}
|
||||
|
||||
export function useInspectInventory() {
|
||||
function useInventoryMutation<TArgs>(fn: (args: TArgs) => Promise<unknown>) {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => warehouseService.inspectInventory(id),
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: ['warehouse-inventory'] }),
|
||||
});
|
||||
}
|
||||
|
||||
export function useMarkReadyForLoading() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => warehouseService.markReadyForLoading(id),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-dashboard'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useLoadInventory() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => warehouseService.loadInventory(id),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-dashboard'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDispatchInventory() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: string) => warehouseService.dispatchInventory(id),
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-dashboard'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useMoveInventory() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: MoveInventoryPayload }) =>
|
||||
warehouseService.moveInventory(id, payload),
|
||||
mutationFn: fn,
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-loadings'] });
|
||||
qc.invalidateQueries({ queryKey: warehouseKeys.all });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const useStoreInventory = () => useInventoryMutation((id: string) => warehouseService.store(id));
|
||||
export const useReserveInventory = () =>
|
||||
useInventoryMutation((payload: ReserveInventoryPayload) => warehouseService.reserve(payload));
|
||||
export const useMarkReadyForLoading = () =>
|
||||
useInventoryMutation((id: string) => warehouseService.markReadyForLoading(id));
|
||||
export const useLoadInventory = () =>
|
||||
useInventoryMutation((args: { id: string; payload: LoadInventoryPayload }) =>
|
||||
warehouseService.load(args.id, args.payload),
|
||||
);
|
||||
export const useDispatchInventory = () => useInventoryMutation((id: string) => warehouseService.dispatch(id));
|
||||
export const useMoveInventory = () =>
|
||||
useInventoryMutation((args: { id: string; payload: MoveInventoryPayload }) =>
|
||||
warehouseService.move(args.id, args.payload),
|
||||
);
|
||||
|
||||
// ── Import branch (READY_FOR_PICKUP → DELIVERED) ───────────────────────────
|
||||
export const useMarkReadyForPickup = () =>
|
||||
useInventoryMutation((id: string) => warehouseService.markReadyForPickup(id));
|
||||
export const useReleaseInventory = () =>
|
||||
useInventoryMutation((args: { id: string; payload: ReleaseOrderPayload }) =>
|
||||
warehouseService.release(args.id, args.payload),
|
||||
);
|
||||
export const useDeliverInventory = () =>
|
||||
useInventoryMutation((args: { id: string; payload: DeliverInventoryPayload }) =>
|
||||
warehouseService.deliver(args.id, args.payload),
|
||||
);
|
||||
|
||||
// ── Loading (Batch 3) ────────────────────────────────────────────────────────
|
||||
|
||||
export function useLoadableWagons(enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse', 'loadable-wagons'],
|
||||
queryFn: () => warehouseService.loadableWagons().then((r) => r.data),
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
|
||||
export function useWarehouseLoadings(params?: { bookingId?: string; wagonId?: string }) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-loadings', params ?? {}],
|
||||
queryFn: () => warehouseService.loadings(params).then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
export function useBookingSchedule(bookingId?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse', 'booking-schedule', bookingId ?? ''],
|
||||
queryFn: () => warehouseService.bookingSchedule(bookingId as string).then((r) => r.data),
|
||||
enabled: Boolean(bookingId),
|
||||
});
|
||||
}
|
||||
|
||||
export function useInventoryMovements(id?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', id, 'movements'],
|
||||
queryFn: () => warehouseService.movements(id as string).then((r) => r.data),
|
||||
enabled: Boolean(id),
|
||||
});
|
||||
}
|
||||
|
||||
export function useInventoryActivity(id?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', id, 'activity'],
|
||||
queryFn: () => warehouseService.activity(id as string).then((r) => r.data),
|
||||
enabled: Boolean(id),
|
||||
});
|
||||
}
|
||||
|
||||
export function useWarehouseDashboard() {
|
||||
return useQuery({
|
||||
queryKey: ['warehouses', 'dashboard'],
|
||||
queryFn: () => warehouseService.dashboard().then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
export function useInventoryInquiry(filter: InventoryInquiryFilter, enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: warehouseKeys.inquiry(filter),
|
||||
@@ -239,3 +281,184 @@ export function useInventoryInquiry(filter: InventoryInquiryFilter, enabled = tr
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
|
||||
// ── Batch 4.5: Arrival / Unload / Inspection ────────────────────────────────
|
||||
|
||||
export function useArrivalQueue() {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', 'arrival-queue'],
|
||||
queryFn: () => warehouseService.arrivalQueue().then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
function useArrivalInvalidation() {
|
||||
const qc = useQueryClient();
|
||||
return () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
qc.invalidateQueries({ queryKey: warehouseKeys.all });
|
||||
};
|
||||
}
|
||||
|
||||
export function useAutoUnloadArrived() {
|
||||
const onSuccess = useArrivalInvalidation();
|
||||
return useMutation({ mutationFn: () => warehouseService.autoUnloadArrived(), onSuccess });
|
||||
}
|
||||
|
||||
export function useAutoLoadReady() {
|
||||
const onSuccess = useArrivalInvalidation();
|
||||
return useMutation({ mutationFn: () => warehouseService.autoLoadReady(), onSuccess });
|
||||
}
|
||||
|
||||
export function useUnloadBooking() {
|
||||
const onSuccess = useArrivalInvalidation();
|
||||
return useMutation({
|
||||
mutationFn: (args: { bookingId: string; payload?: Record<string, unknown> }) =>
|
||||
warehouseService.unloadBooking(args.bookingId, args.payload),
|
||||
onSuccess,
|
||||
});
|
||||
}
|
||||
|
||||
export function useInspectionReports(inventoryId?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', inventoryId, 'inspection-reports'],
|
||||
queryFn: () => warehouseService.listInspectionReports(inventoryId as string).then((r) => r.data),
|
||||
enabled: Boolean(inventoryId),
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateInspectionReport() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ inventoryId, payload }: { inventoryId: string; payload: InspectionReportPayload }) =>
|
||||
warehouseService.createInspectionReport(inventoryId, payload).then((r) => r.data),
|
||||
onSuccess: (_, { inventoryId }) => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory', inventoryId, 'inspection-reports'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUploadInspectionAttachments() {
|
||||
return useMutation({
|
||||
mutationFn: ({ reportId, files }: { reportId: string; files: File[] }) =>
|
||||
warehouseService.uploadInspectionAttachments(reportId, files),
|
||||
});
|
||||
}
|
||||
|
||||
// ── Batch 5: Allocation + Fee rules / preview ───────────────────────────────
|
||||
|
||||
export function useAllocationRules() {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-allocation-rules'],
|
||||
queryFn: () => warehouseService.listAllocationRules().then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
export function useFeeRules() {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-fee-rules'],
|
||||
queryFn: () => warehouseService.listFeeRules().then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
function useRuleMutation<TArgs>(fn: (args: TArgs) => Promise<unknown>, keys: string[]) {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: fn,
|
||||
onSuccess: () => keys.forEach((k) => qc.invalidateQueries({ queryKey: [k] })),
|
||||
});
|
||||
}
|
||||
|
||||
export const useCreateAllocationRule = () =>
|
||||
useRuleMutation(
|
||||
(payload: SaveAllocationRulePayload) => warehouseService.createAllocationRule(payload),
|
||||
['warehouse-allocation-rules'],
|
||||
);
|
||||
export const useUpdateAllocationRule = () =>
|
||||
useRuleMutation(
|
||||
(args: { id: string; payload: Partial<SaveAllocationRulePayload> }) =>
|
||||
warehouseService.updateAllocationRule(args.id, args.payload),
|
||||
['warehouse-allocation-rules'],
|
||||
);
|
||||
export const useDeleteAllocationRule = () =>
|
||||
useRuleMutation((id: string) => warehouseService.deleteAllocationRule(id), ['warehouse-allocation-rules']);
|
||||
|
||||
export const useCreateFeeRule = () =>
|
||||
useRuleMutation((payload: SaveFeeRulePayload) => warehouseService.createFeeRule(payload), ['warehouse-fee-rules']);
|
||||
export const useUpdateFeeRule = () =>
|
||||
useRuleMutation(
|
||||
(args: { id: string; payload: Partial<SaveFeeRulePayload> }) =>
|
||||
warehouseService.updateFeeRule(args.id, args.payload),
|
||||
['warehouse-fee-rules'],
|
||||
);
|
||||
export const useDeleteFeeRule = () =>
|
||||
useRuleMutation((id: string) => warehouseService.deleteFeeRule(id), ['warehouse-fee-rules']);
|
||||
|
||||
export function useFeePreview(inventoryId?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', inventoryId, 'fee-preview'],
|
||||
queryFn: () => warehouseService.feePreview(inventoryId as string).then((r) => r.data),
|
||||
enabled: Boolean(inventoryId),
|
||||
});
|
||||
}
|
||||
|
||||
// ── Batch 6: Warehouse fee invoices ─────────────────────────────────────────
|
||||
|
||||
export function useWarehouseInvoices(filter?: WarehouseInvoiceFilter) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-fee-invoices', filter ?? {}],
|
||||
queryFn: () => warehouseService.listInvoices(filter).then((r) => r.data),
|
||||
});
|
||||
}
|
||||
|
||||
export function useWarehouseInvoice(id?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-fee-invoices', 'detail', id],
|
||||
queryFn: () => warehouseService.getInvoice(id as string).then((r) => r.data),
|
||||
enabled: Boolean(id),
|
||||
});
|
||||
}
|
||||
|
||||
export function useInvoicesForInventory(inventoryId?: string) {
|
||||
return useQuery({
|
||||
queryKey: ['warehouse-inventory', inventoryId, 'fee-invoices'],
|
||||
queryFn: () => warehouseService.invoicesForInventory(inventoryId as string).then((r) => r.data),
|
||||
enabled: Boolean(inventoryId),
|
||||
});
|
||||
}
|
||||
|
||||
function useInvoiceInvalidation() {
|
||||
const qc = useQueryClient();
|
||||
return () => {
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-fee-invoices'] });
|
||||
qc.invalidateQueries({ queryKey: ['warehouse-inventory'] });
|
||||
};
|
||||
}
|
||||
|
||||
export function useGenerateInvoice() {
|
||||
const onSuccess = useInvoiceInvalidation();
|
||||
return useMutation({
|
||||
mutationFn: ({ inventoryId, confirmZero }: { inventoryId: string; confirmZero?: boolean }) =>
|
||||
warehouseService.generateInvoice(inventoryId, confirmZero).then((r) => r.data),
|
||||
onSuccess,
|
||||
});
|
||||
}
|
||||
|
||||
export function useCancelInvoice() {
|
||||
const onSuccess = useInvoiceInvalidation();
|
||||
return useMutation({ mutationFn: (id: string) => warehouseService.cancelInvoice(id), onSuccess });
|
||||
}
|
||||
|
||||
export function usePayInvoice() {
|
||||
const onSuccess = useInvoiceInvalidation();
|
||||
return useMutation({
|
||||
mutationFn: ({ id, payload }: { id: string; payload: PayInvoicePayload }) =>
|
||||
warehouseService.payInvoice(id, payload),
|
||||
onSuccess,
|
||||
});
|
||||
}
|
||||
|
||||
export function useGateClearance() {
|
||||
const onSuccess = useInvoiceInvalidation();
|
||||
return useMutation({ mutationFn: (inventoryId: string) => warehouseService.gateClearance(inventoryId), onSuccess });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user