feat(api): add POST /api/items/{partNumber}/bom/merge endpoint #51

Merged
forbes merged 2 commits from issue-45-bom-merge into main 2026-02-09 01:21:45 +00:00
Owner

Closes #45, closes #46

Adds the BOM merge endpoint used by FreeCAD's silo-mod plugin to sync assembly-derived BOM entries with the server.

Merge Rules

  • Added: entries in request but not in server BOM → auto-created with source='assembly'
  • Quantity changed: existing entries with different quantity → auto-updated
  • Unchanged: same part and quantity → skipped
  • Unreferenced: assembly-sourced entries in server BOM but not in request → flagged as warnings (never auto-deleted). Manual entries are silently ignored.

Response Format

{
  "status": "merged",
  "diff": {
    "added": [{"part_number": "PRT-100", "quantity": 1}],
    "removed": [{"part_number": "PRT-400", "quantity": 2}],
    "quantity_changed": [{"part_number": "F01-001", "old_quantity": 8, "new_quantity": 12}],
    "unchanged": [{"part_number": "PRT-200", "quantity": 1}]
  },
  "warnings": [{"type": "unreferenced", "part_number": "PRT-400", "message": "..."}],
  "resolve_url": "/items/ASM-001/bom"
}

Also emits SSE bom.merged event on successful merge (#46).

Depends on: #50 (source column)

Closes #45, closes #46 Adds the BOM merge endpoint used by FreeCAD's silo-mod plugin to sync assembly-derived BOM entries with the server. ### Merge Rules - **Added**: entries in request but not in server BOM → auto-created with `source='assembly'` - **Quantity changed**: existing entries with different quantity → auto-updated - **Unchanged**: same part and quantity → skipped - **Unreferenced**: assembly-sourced entries in server BOM but not in request → flagged as warnings (never auto-deleted). Manual entries are silently ignored. ### Response Format ```json { "status": "merged", "diff": { "added": [{"part_number": "PRT-100", "quantity": 1}], "removed": [{"part_number": "PRT-400", "quantity": 2}], "quantity_changed": [{"part_number": "F01-001", "old_quantity": 8, "new_quantity": 12}], "unchanged": [{"part_number": "PRT-200", "quantity": 1}] }, "warnings": [{"type": "unreferenced", "part_number": "PRT-400", "message": "..."}], "resolve_url": "/items/ASM-001/bom" } ``` Also emits SSE `bom.merged` event on successful merge (#46). **Depends on**: #50 (source column)
forbes added 2 commits 2026-02-09 01:15:41 +00:00
Promote BOM source from metadata JSONB to a dedicated VARCHAR(20)
column with CHECK constraint ('manual' or 'assembly').

- Add migration 012_bom_source.sql (column, data migration, cleanup)
- Add Source field to Relationship and BOMEntry structs
- Update all SQL queries (GetBOM, GetWhereUsed, GetExpandedBOM, Create)
- Update API response/request types with source field
- Update CSV/ODS export to read e.Source instead of metadata
- Update CSV import to set source on relationship directly
- Update frontend types and BOMTab to use top-level source field
Add BOM merge endpoint for syncing assembly-derived BOM entries from
FreeCAD's silo-mod plugin.

Merge rules:
- Added: entries in request but not in server BOM are auto-created
  with source='assembly'
- Quantity changed: existing entries with different quantity are
  auto-updated
- Unchanged: same part and quantity are skipped
- Unreferenced: assembly-sourced entries in server BOM but not in
  request are flagged as warnings (never auto-deleted)
- Manual entries are silently ignored in unreferenced detection

Also emits SSE 'bom.merged' event on successful merge (#46).
forbes added 1 commit 2026-02-09 01:21:42 +00:00
forbes merged commit 64075d88b5 into main 2026-02-09 01:21:45 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/silo#51