data and layout cleanup
This commit is contained in:
@@ -58,6 +58,7 @@ This file is the running release and change log for MRP Codex. Keep it updated w
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Fresh bootstrap now creates only minimal system records; operational domains no longer start with seeded demo customers, vendors, inventory, BOMs, or warehouses
|
||||||
- Sales and purchasing detail pages now expose revision comparison directly alongside chronological revision history
|
- Sales and purchasing detail pages now expose revision comparison directly alongside chronological revision history
|
||||||
- `ROADMAP.md` now tracks remaining work only, and shipped phase history now lives in `SHIPPED.md`
|
- `ROADMAP.md` now tracks remaining work only, and shipped phase history now lives in `SHIPPED.md`
|
||||||
- Support logs now prune retained entries by age instead of only trimming by count, and admin diagnostics now reviews filtered support-log summaries instead of an unbounded flat dump
|
- Support logs now prune retained entries by age instead of only trimming by count, and admin diagnostics now reviews filtered support-log summaries instead of an unbounded flat dump
|
||||||
|
|||||||
@@ -230,8 +230,7 @@ The current inventory foundation supports:
|
|||||||
- item on-hand quantity, stock-by-location balances, and recent stock history
|
- item on-hand quantity, stock-by-location balances, and recent stock history
|
||||||
- reserved and available quantity visibility by location
|
- reserved and available quantity visibility by location
|
||||||
- item-level file attachments for drawings and support documents
|
- item-level file attachments for drawings and support documents
|
||||||
- seeded sample inventory items and a starter assembly BOM during bootstrap
|
- fresh bootstrap starts inventory and warehouse data empty so first-run environments do not include demo operational records
|
||||||
- seeded sample warehouse and stock locations during bootstrap
|
|
||||||
|
|
||||||
QOL direction:
|
QOL direction:
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ export function GanttPage() {
|
|||||||
const links = timeline?.links ?? [];
|
const links = timeline?.links ?? [];
|
||||||
const summary = timeline?.summary;
|
const summary = timeline?.summary;
|
||||||
const exceptions = timeline?.exceptions ?? [];
|
const exceptions = timeline?.exceptions ?? [];
|
||||||
|
const ganttCellHeight = 44;
|
||||||
|
const ganttScaleHeight = 56;
|
||||||
|
const ganttHeight = Math.max(420, tasks.length * ganttCellHeight + ganttScaleHeight);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-4">
|
<section className="space-y-4">
|
||||||
@@ -104,7 +107,7 @@ export function GanttPage() {
|
|||||||
</section>
|
</section>
|
||||||
<div className="grid gap-3 xl:grid-cols-[minmax(0,1.2fr)_360px]">
|
<div className="grid gap-3 xl:grid-cols-[minmax(0,1.2fr)_360px]">
|
||||||
<div
|
<div
|
||||||
className={`gantt-theme overflow-auto rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5 ${
|
className={`gantt-theme overflow-x-auto overflow-y-visible rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5 ${
|
||||||
mode === "dark" ? "wx-willow-dark-theme" : "wx-willow-theme"
|
mode === "dark" ? "wx-willow-dark-theme" : "wx-willow-theme"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
@@ -119,15 +122,19 @@ export function GanttPage() {
|
|||||||
{tasks.length} schedule rows
|
{tasks.length} schedule rows
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Gantt
|
<div style={{ height: `${ganttHeight}px`, minWidth: "100%" }}>
|
||||||
tasks={tasks.map((task: GanttTaskDto) => ({
|
<Gantt
|
||||||
...task,
|
tasks={tasks.map((task: GanttTaskDto) => ({
|
||||||
start: new Date(task.start),
|
...task,
|
||||||
end: new Date(task.end),
|
start: new Date(task.start),
|
||||||
parent: task.parentId ?? undefined,
|
end: new Date(task.end),
|
||||||
}))}
|
parent: task.parentId ?? undefined,
|
||||||
links={links}
|
}))}
|
||||||
/>
|
links={links}
|
||||||
|
cellHeight={ganttCellHeight}
|
||||||
|
scaleHeight={ganttScaleHeight}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<aside className="space-y-3">
|
<aside className="space-y-3">
|
||||||
<section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
|
<section className="rounded-[20px] border border-line/70 bg-surface/90 p-4 shadow-panel 2xl:p-5">
|
||||||
|
|||||||
@@ -122,152 +122,4 @@ export async function bootstrapAppData() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((await prisma.customer.count()) === 0) {
|
|
||||||
await prisma.customer.createMany({
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
name: "Acme Components",
|
|
||||||
email: "buyer@acme.example",
|
|
||||||
phone: "555-0101",
|
|
||||||
addressLine1: "1 Industrial Road",
|
|
||||||
addressLine2: "",
|
|
||||||
city: "Detroit",
|
|
||||||
state: "MI",
|
|
||||||
postalCode: "48201",
|
|
||||||
country: "USA",
|
|
||||||
notes: "Priority account",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Northwind Fabrication",
|
|
||||||
email: "ops@northwind.example",
|
|
||||||
phone: "555-0120",
|
|
||||||
addressLine1: "42 Assembly Ave",
|
|
||||||
addressLine2: "",
|
|
||||||
city: "Milwaukee",
|
|
||||||
state: "WI",
|
|
||||||
postalCode: "53202",
|
|
||||||
country: "USA",
|
|
||||||
notes: "Requires ASN notice",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((await prisma.vendor.count()) === 0) {
|
|
||||||
await prisma.vendor.create({
|
|
||||||
data: {
|
|
||||||
name: "SteelSource Supply",
|
|
||||||
email: "sales@steelsource.example",
|
|
||||||
phone: "555-0142",
|
|
||||||
addressLine1: "77 Mill Street",
|
|
||||||
addressLine2: "",
|
|
||||||
city: "Gary",
|
|
||||||
state: "IN",
|
|
||||||
postalCode: "46402",
|
|
||||||
country: "USA",
|
|
||||||
notes: "Lead time 5 business days",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((await prisma.inventoryItem.count()) === 0) {
|
|
||||||
const plate = await prisma.inventoryItem.create({
|
|
||||||
data: {
|
|
||||||
sku: "RM-PLATE-AL-125",
|
|
||||||
name: "Aluminum Plate 1/8in",
|
|
||||||
description: "Raw aluminum plate stock for fabricated assemblies.",
|
|
||||||
type: "PURCHASED",
|
|
||||||
status: "ACTIVE",
|
|
||||||
unitOfMeasure: "EA",
|
|
||||||
isSellable: false,
|
|
||||||
isPurchasable: true,
|
|
||||||
defaultCost: 42.5,
|
|
||||||
defaultPrice: null,
|
|
||||||
notes: "Primary sheet stock for enclosure fabrication.",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const fastener = await prisma.inventoryItem.create({
|
|
||||||
data: {
|
|
||||||
sku: "HW-SCREW-832",
|
|
||||||
name: "8-32 Socket Head Screw",
|
|
||||||
description: "Standard socket head cap screw for enclosure assemblies.",
|
|
||||||
type: "PURCHASED",
|
|
||||||
status: "ACTIVE",
|
|
||||||
unitOfMeasure: "EA",
|
|
||||||
isSellable: false,
|
|
||||||
isPurchasable: true,
|
|
||||||
defaultCost: 0.18,
|
|
||||||
defaultPrice: null,
|
|
||||||
notes: "Bulk hardware item.",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const assembly = await prisma.inventoryItem.create({
|
|
||||||
data: {
|
|
||||||
sku: "FG-CTRL-BASE",
|
|
||||||
name: "Control Base Assembly",
|
|
||||||
description: "Base enclosure assembly for standard control packages.",
|
|
||||||
type: "ASSEMBLY",
|
|
||||||
status: "ACTIVE",
|
|
||||||
unitOfMeasure: "EA",
|
|
||||||
isSellable: true,
|
|
||||||
isPurchasable: false,
|
|
||||||
defaultCost: 118,
|
|
||||||
defaultPrice: 249,
|
|
||||||
notes: "Starter BOM for the inventory foundation slice.",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
await prisma.inventoryBomLine.createMany({
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
parentItemId: assembly.id,
|
|
||||||
componentItemId: plate.id,
|
|
||||||
quantity: 2,
|
|
||||||
unitOfMeasure: "EA",
|
|
||||||
notes: "Side panel blanks",
|
|
||||||
position: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
parentItemId: assembly.id,
|
|
||||||
componentItemId: fastener.id,
|
|
||||||
quantity: 12,
|
|
||||||
unitOfMeasure: "EA",
|
|
||||||
notes: "General assembly hardware",
|
|
||||||
position: 20,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((await prisma.warehouse.count()) === 0) {
|
|
||||||
await prisma.warehouse.create({
|
|
||||||
data: {
|
|
||||||
code: "MAIN",
|
|
||||||
name: "Main Warehouse",
|
|
||||||
notes: "Primary stocking location for finished goods and purchased materials.",
|
|
||||||
locations: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
code: "RECV",
|
|
||||||
name: "Receiving",
|
|
||||||
notes: "Initial inbound inspection and receipt staging.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "STOCK-A1",
|
|
||||||
name: "Aisle A1",
|
|
||||||
notes: "General rack storage for standard material.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "FG-STAGE",
|
|
||||||
name: "Finished Goods Staging",
|
|
||||||
notes: "Outbound-ready finished assemblies.",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user