docs(19-02): complete item and thread service COALESCE merge plan
- SUMMARY.md with task commits, decisions, and verification results - STATE.md updated with position, progress, and decisions - ROADMAP.md updated with plan progress
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
---
|
||||
phase: 19-reference-item-model-tags-schema
|
||||
plan: 02
|
||||
subsystem: services
|
||||
tags: [item-service, thread-service, coalesce, reference-items, catalog-link]
|
||||
|
||||
requires:
|
||||
- phase: 19-reference-item-model-tags-schema
|
||||
plan: 01
|
||||
provides: globalItemId FK on items and threadCandidates, tags tables
|
||||
provides:
|
||||
- COALESCE merge pattern in item service for transparent reference item data
|
||||
- Branched thread resolution (reference vs standalone items)
|
||||
- Catalog-linked candidates with merged global item display data
|
||||
- Cleaned items route without link/unlink endpoints
|
||||
affects: [19-03, client-hooks, mcp-tools]
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "COALESCE merge: LEFT JOIN globalItems with CASE WHEN for name, weight, price, image"
|
||||
- "Branched resolution: candidate.globalItemId determines reference vs standalone item creation"
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- src/server/services/item.service.ts
|
||||
- src/server/services/thread.service.ts
|
||||
- src/server/routes/items.ts
|
||||
- tests/services/item.service.test.ts
|
||||
- tests/services/thread.service.test.ts
|
||||
|
||||
key-decisions:
|
||||
- "COALESCE with CASE WHEN pattern ensures standalone items are unaffected by globalItems JOIN"
|
||||
- "Reference item resolution omits weight/price/productUrl - those come from global item via COALESCE on read"
|
||||
- "Image fallback: item's own imageFilename takes precedence, global imageUrl used as fallback"
|
||||
|
||||
patterns-established:
|
||||
- "Reference items: service layer transparently merges global data via SQL COALESCE, clients see unified shape"
|
||||
- "Branched resolution: resolveThread checks candidate.globalItemId to determine item creation strategy"
|
||||
|
||||
requirements-completed: [CATFLOW-03, CATFLOW-04, CATFLOW-05, CATFLOW-06]
|
||||
|
||||
duration: 8min
|
||||
completed: 2026-04-05
|
||||
---
|
||||
|
||||
# Phase 19 Plan 02: Item & Thread Service COALESCE Merge Summary
|
||||
|
||||
**COALESCE merge pattern in item/thread services for transparent reference item data, branched thread resolution, and link/unlink endpoint removal**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 8 min
|
||||
- **Started:** 2026-04-05T18:31:23Z
|
||||
- **Completed:** 2026-04-05T18:39:00Z
|
||||
- **Tasks:** 2
|
||||
- **Files modified:** 5
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Item service getAllItems and getItemById use LEFT JOIN + COALESCE to transparently merge global item data for reference items
|
||||
- createItem accepts globalItemId, looks up global item for brand+model fallback name (items.name is NOT NULL)
|
||||
- duplicateItem preserves globalItemId and purchasePriceCents from source
|
||||
- Thread service getThreadWithCandidates merges global item data for catalog-linked candidates
|
||||
- createCandidate stores globalItemId on candidate row
|
||||
- resolveThread branches: reference items get globalItemId set with no weight/price copy; standalone items get full data copy
|
||||
- Removed link/unlink endpoints from items route (replaced by direct globalItemId FK)
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Item service COALESCE merge + reference item creation + tests** - `d1ffd79` (feat)
|
||||
2. **Task 2: Thread service candidate globalItemId + branched resolution + route cleanup + tests** - `8a5ee73` (feat)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `src/server/services/item.service.ts` - LEFT JOIN globalItems with COALESCE in getAllItems/getItemById, globalItemId in createItem/duplicateItem/updateItem
|
||||
- `src/server/services/thread.service.ts` - LEFT JOIN globalItems in getThreadWithCandidates, globalItemId in createCandidate, branched resolveThread
|
||||
- `src/server/routes/items.ts` - Removed link/unlink endpoints and imports of linkItemToGlobal, unlinkItemFromGlobal, linkItemSchema
|
||||
- `tests/services/item.service.test.ts` - 10 new tests for reference item creation, merged data retrieval, purchasePriceCents
|
||||
- `tests/services/thread.service.test.ts` - 6 new tests for catalog-linked candidates and branched resolution
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- Used COALESCE with CASE WHEN pattern (not simple COALESCE) to ensure standalone items are completely unaffected by the LEFT JOIN
|
||||
- Reference item resolution intentionally omits weight, price, and productUrl from the insert - those come from the global item via COALESCE on read
|
||||
- Image fallback order: item's own imageFilename first, global item's imageUrl second (user uploads override catalog images)
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None - plan executed exactly as written.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None - all data paths are fully wired.
|
||||
|
||||
---
|
||||
*Phase: 19-reference-item-model-tags-schema*
|
||||
*Completed: 2026-04-05*
|
||||
Reference in New Issue
Block a user