feat(frontend): integrate inter-project material transfer into ChangeInventoryPage and ArrivalsPage

- Add PROJECT_TRANSFER tab under reductions in ChangeInventoryPage
- Render complete material spec form with destination project selector
- Show matching stock preview in source warehouse
- Add transfer history table with in-transit edit modal and cancellation dialog
- Add incoming transfer cards in ArrivalsPage with 100% full delivery allocation
This commit is contained in:
2026-09-23 22:31:10 +03:30
parent b326cf64bf
commit 856513b6d7
4 changed files with 742 additions and 21 deletions
+28
View File
@@ -30,6 +30,10 @@ import type {
Supplier,
TransactionType,
Warehouse,
ProjectTransfer,
ProjectTransferCreateIn,
ProjectTransferUpdateIn,
ProjectTransferReceiveIn,
} from "./types";
const BASE_URL = (import.meta.env?.VITE_API_BASE_URL as string | undefined)?.trim() || "/api/v1";
@@ -1746,4 +1750,28 @@ export const apiV26 = {
attributes: [],
}),
},
projectTransfers: {
list: async (projectId?: string | null, direction: "outgoing" | "incoming" | "all" = "all", status?: string): Promise<ProjectTransfer[]> => {
const q = new URLSearchParams();
if (projectId) q.set("project_id", projectId);
if (direction) q.set("direction", direction);
if (status) q.set("status", status);
const qs = q.toString() ? `?${q.toString()}` : "";
return getData<ProjectTransfer[]>(`/inventory/project-transfers${qs}`);
},
get: async (id: string, projectId?: string | null): Promise<ProjectTransfer> =>
getData<ProjectTransfer>(projectId ? `/inventory/project-transfers/${id}?project_id=${projectId}` : `/inventory/project-transfers/${id}`),
create: async (body: ProjectTransferCreateIn, projectId?: string | null): Promise<ProjectTransfer> =>
postData<ProjectTransfer>(projectId ? `/inventory/project-transfers?project_id=${projectId}` : `/inventory/project-transfers`, body),
update: async (id: string, patch: ProjectTransferUpdateIn, projectId?: string | null): Promise<ProjectTransfer> =>
patchData<ProjectTransfer>(projectId ? `/inventory/project-transfers/${id}?project_id=${projectId}` : `/inventory/project-transfers/${id}`, patch),
delete: async (id: string, projectId?: string | null): Promise<{ ok: boolean; message: string }> =>
deleteData(projectId ? `/inventory/project-transfers/${id}?project_id=${projectId}` : `/inventory/project-transfers/${id}`),
onTheWay: async (projectId?: string | null): Promise<ProjectTransfer[]> =>
getData<ProjectTransfer[]>(projectId ? `/pm/transfers/on-the-way?project_id=${projectId}` : `/pm/transfers/on-the-way`),
receive: async (id: string, body: ProjectTransferReceiveIn, projectId?: string | null): Promise<ProjectTransfer> =>
postData<ProjectTransfer>(projectId ? `/inventory/project-transfers/${id}/receive?project_id=${projectId}` : `/inventory/project-transfers/${id}/receive`, body),
},
};