PO logic
This commit is contained in:
@@ -141,6 +141,7 @@ export function WorkOrderDetailPage() {
|
||||
<div className="flex flex-wrap gap-3">
|
||||
<Link to="/manufacturing/work-orders" className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">Back to work orders</Link>
|
||||
{workOrder.projectId ? <Link to={`/projects/${workOrder.projectId}`} className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">Open project</Link> : null}
|
||||
{workOrder.salesOrderId ? <Link to={`/sales/orders/${workOrder.salesOrderId}`} className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">Open sales order</Link> : null}
|
||||
<Link to={`/inventory/items/${workOrder.itemId}`} className="inline-flex items-center justify-center rounded-2xl border border-line/70 px-2 py-2 text-sm font-semibold text-text">Open item</Link>
|
||||
{canManage ? <Link to={`/manufacturing/work-orders/${workOrder.id}/edit`} className="inline-flex items-center justify-center rounded-2xl bg-brand px-2 py-2 text-sm font-semibold text-white">Edit work order</Link> : null}
|
||||
</div>
|
||||
@@ -170,6 +171,7 @@ export function WorkOrderDetailPage() {
|
||||
<article className="rounded-[24px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel"><p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Project</p><div className="mt-2 text-base font-bold text-text">{workOrder.projectNumber || "Unlinked"}</div></article>
|
||||
<article className="rounded-[24px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel"><p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Operations</p><div className="mt-2 text-base font-bold text-text">{workOrder.operations.length}</div></article>
|
||||
<article className="rounded-[24px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel"><p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Due Date</p><div className="mt-2 text-base font-bold text-text">{workOrder.dueDate ? new Date(workOrder.dueDate).toLocaleDateString() : "Not set"}</div></article>
|
||||
<article className="rounded-[24px] border border-line/70 bg-surface/90 px-3 py-3 shadow-panel"><p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Material Shortage</p><div className="mt-2 text-base font-bold text-text">{workOrder.materialRequirements.reduce((sum, requirement) => sum + requirement.shortageQuantity, 0)}</div></article>
|
||||
</section>
|
||||
<div className="grid gap-3 xl:grid-cols-[minmax(0,1fr)_minmax(360px,0.9fr)]">
|
||||
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
|
||||
@@ -179,6 +181,7 @@ export function WorkOrderDetailPage() {
|
||||
<div><dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Item type</dt><dd className="mt-1 text-sm text-text">{workOrder.itemType}</dd></div>
|
||||
<div><dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Output location</dt><dd className="mt-1 text-sm text-text">{workOrder.warehouseCode} / {workOrder.locationCode}</dd></div>
|
||||
<div><dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Project customer</dt><dd className="mt-1 text-sm text-text">{workOrder.projectCustomerName || "Not linked"}</dd></div>
|
||||
<div><dt className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">Demand source</dt><dd className="mt-1 text-sm text-text">{workOrder.salesOrderNumber ?? "Not linked"}</dd></div>
|
||||
</dl>
|
||||
</article>
|
||||
<article className="rounded-[28px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
|
||||
@@ -299,6 +302,8 @@ export function WorkOrderDetailPage() {
|
||||
<th className="px-3 py-3">Required</th>
|
||||
<th className="px-3 py-3">Issued</th>
|
||||
<th className="px-3 py-3">Remaining</th>
|
||||
<th className="px-3 py-3">Available</th>
|
||||
<th className="px-3 py-3">Shortage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-line/70">
|
||||
@@ -309,6 +314,8 @@ export function WorkOrderDetailPage() {
|
||||
<td className="px-3 py-3 text-text">{requirement.requiredQuantity}</td>
|
||||
<td className="px-3 py-3 text-text">{requirement.issuedQuantity}</td>
|
||||
<td className="px-3 py-3 text-text">{requirement.remainingQuantity}</td>
|
||||
<td className="px-3 py-3 text-text">{requirement.availableQuantity}</td>
|
||||
<td className="px-3 py-3 text-text">{requirement.shortageQuantity}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -17,6 +17,13 @@ export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) {
|
||||
const { workOrderId } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
const seededProjectId = searchParams.get("projectId");
|
||||
const seededItemId = searchParams.get("itemId");
|
||||
const seededSalesOrderId = searchParams.get("salesOrderId");
|
||||
const seededSalesOrderLineId = searchParams.get("salesOrderLineId");
|
||||
const seededQuantity = searchParams.get("quantity");
|
||||
const seededStatus = searchParams.get("status");
|
||||
const seededDueDate = searchParams.get("dueDate");
|
||||
const seededNotes = searchParams.get("notes");
|
||||
const [form, setForm] = useState<WorkOrderInput>(emptyWorkOrderInput);
|
||||
const [itemOptions, setItemOptions] = useState<ManufacturingItemOptionDto[]>([]);
|
||||
const [projectOptions, setProjectOptions] = useState<ManufacturingProjectOptionDto[]>([]);
|
||||
@@ -33,7 +40,25 @@ export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.getManufacturingItemOptions(token).then(setItemOptions).catch(() => setItemOptions([]));
|
||||
api.getManufacturingItemOptions(token).then((options) => {
|
||||
setItemOptions(options);
|
||||
if (mode === "create" && seededItemId) {
|
||||
const seededItem = options.find((option) => option.id === seededItemId);
|
||||
if (seededItem) {
|
||||
setForm((current) => ({
|
||||
...current,
|
||||
itemId: seededItem.id,
|
||||
salesOrderId: seededSalesOrderId || current.salesOrderId,
|
||||
salesOrderLineId: seededSalesOrderLineId || current.salesOrderLineId,
|
||||
quantity: seededQuantity ? Number.parseInt(seededQuantity, 10) || current.quantity : current.quantity,
|
||||
status: seededStatus && workOrderStatusOptions.some((option) => option.value === seededStatus) ? (seededStatus as WorkOrderInput["status"]) : current.status,
|
||||
dueDate: seededDueDate || current.dueDate,
|
||||
notes: seededNotes || current.notes,
|
||||
}));
|
||||
setItemSearchTerm(`${seededItem.sku} - ${seededItem.name}`);
|
||||
}
|
||||
}
|
||||
}).catch(() => setItemOptions([]));
|
||||
api.getManufacturingProjectOptions(token).then((options) => {
|
||||
setProjectOptions(options);
|
||||
if (mode === "create" && seededProjectId) {
|
||||
@@ -45,7 +70,7 @@ export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) {
|
||||
}
|
||||
}).catch(() => setProjectOptions([]));
|
||||
api.getWarehouseLocationOptions(token).then(setLocationOptions).catch(() => setLocationOptions([]));
|
||||
}, [mode, seededProjectId, token]);
|
||||
}, [mode, seededDueDate, seededItemId, seededNotes, seededProjectId, seededQuantity, seededSalesOrderId, seededSalesOrderLineId, seededStatus, token]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!token || mode !== "edit" || !workOrderId) {
|
||||
@@ -57,6 +82,8 @@ export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) {
|
||||
setForm({
|
||||
itemId: workOrder.itemId,
|
||||
projectId: workOrder.projectId,
|
||||
salesOrderId: workOrder.salesOrderId,
|
||||
salesOrderLineId: workOrder.salesOrderLineId,
|
||||
status: workOrder.status,
|
||||
quantity: workOrder.quantity,
|
||||
warehouseId: workOrder.warehouseId,
|
||||
|
||||
@@ -26,6 +26,8 @@ export const workOrderStatusPalette: Record<WorkOrderStatus, string> = {
|
||||
export const emptyWorkOrderInput: WorkOrderInput = {
|
||||
itemId: "",
|
||||
projectId: null,
|
||||
salesOrderId: null,
|
||||
salesOrderLineId: null,
|
||||
status: "DRAFT",
|
||||
quantity: 1,
|
||||
warehouseId: "",
|
||||
|
||||
Reference in New Issue
Block a user