diff --git a/web/src/api/types.ts b/web/src/api/types.ts index 7dfb081..e6dc1f0 100644 --- a/web/src/api/types.ts +++ b/web/src/api/types.ts @@ -212,6 +212,38 @@ export interface UpdateBOMEntryRequest { metadata?: Record; } +// BOM Merge +export interface MergeBOMResponse { + status: string; + diff: MergeBOMDiff; + warnings: MergeWarning[]; + resolve_url: string; +} + +export interface MergeBOMDiff { + added: MergeDiffEntry[]; + removed: MergeDiffEntry[]; + quantity_changed: MergeQtyChange[]; + unchanged: MergeDiffEntry[]; +} + +export interface MergeDiffEntry { + part_number: string; + quantity: number | null; +} + +export interface MergeQtyChange { + part_number: string; + old_quantity: number | null; + new_quantity: number | null; +} + +export interface MergeWarning { + type: string; + part_number: string; + message: string; +} + // Schema properties export interface PropertyDef { type: string; diff --git a/web/src/components/items/BOMTab.tsx b/web/src/components/items/BOMTab.tsx index 3cffebf..b9f6352 100644 --- a/web/src/components/items/BOMTab.tsx +++ b/web/src/components/items/BOMTab.tsx @@ -46,6 +46,7 @@ export function BOMTab({ partNumber, isEditor }: BOMTabProps) { const unitCost = (e: BOMEntry) => Number(meta(e).unit_cost) || 0; const extCost = (e: BOMEntry) => unitCost(e) * (e.quantity ?? 0); const totalCost = entries.reduce((sum, e) => sum + extCost(e), 0); + const assemblyCount = entries.filter((e) => e.source === "assembly").length; const formToRequest = () => ({ child_part_number: form.child_part_number, @@ -139,12 +140,15 @@ export function BOMTab({ partNumber, isEditor }: BOMTabProps) { /> - setForm({ ...form, source: e.target.value })} - placeholder="Source" style={inputStyle} - /> + > + + + + + {isEditor && assemblyCount > 0 && ( +
+ {assemblyCount} assembly-sourced{" "} + {assemblyCount === 1 ? "entry" : "entries"}. Entries removed from the + FreeCAD assembly will remain here until manually deleted. +
+ )} +
{e.child_part_number} - +
{e.source ?? ""} + {e.source === "assembly" ? ( + assembly + ) : e.source === "manual" ? ( + manual + ) : ( + "—" + )} +