Add ExpectedAsset CSV import + bot search/pick for pre-known inventory
CI / test (push) Failing after 8s
CI / test (push) Failing after 8s
Lets the operator upload a CSV of already-known assets (asset tag, model, serial, old area/assignee) before an office-move walk, via a new session-authed /inventory-scans/import page. The Telegram bot gains a "tim trong list" search step at the asset-tag prompt: picking a match pre-fills tag/serial and offers one-tap "giu nguyen" buttons for the old area/assignee, then marks that row matched once the scan is created. Follows the same-day decision to turn off local OCR (qwen2.5vl via Ollama) for this feature -- see CLAUDE.md and the ITAM/Ollama vault notes for the accuracy/speed numbers behind that call. Deviates from repo convention same as the InventoryScan work above: no Vitest coverage (manual smoke test only, via simulated webhook calls), hand-written migration, not through the ba->pm->feature-implementer-> test-runner->code-reviewer pipeline. tsc/lint are clean.
This commit is contained in:
@@ -565,6 +565,40 @@ model InventoryScan {
|
||||
telegramChatId String? @map("telegram_chat_id")
|
||||
telegramMessageId Int? @map("telegram_message_id")
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
// Back-reference for ExpectedAsset.matchedScanId -- set once someone
|
||||
// picks this scan's pre-uploaded row via the bot's "🔍 Tìm trong list"
|
||||
// step. No @relation attribute needed here; the FK lives on the other
|
||||
// side.
|
||||
expectedAsset ExpectedAsset?
|
||||
|
||||
@@map("inventory_scans")
|
||||
}
|
||||
|
||||
// A row from a pre-move Excel/CSV export of known assets (asset tag,
|
||||
// model, old area/owner), uploaded via POST /api/expected-assets/import
|
||||
// before an office-move walk starts (2026-08-21 decision -- team decided
|
||||
// plain manual entry was faster/more reliable than local OCR for ~300-400
|
||||
// assets, see docs/asset-license-management.md, but typing in a KNOWN
|
||||
// asset tag from scratch during the walk is still wasted effort when it's
|
||||
// sitting right here). Purely a lookup/staging table for the bot's "🔍 Tìm
|
||||
// trong list" picker -- modelText/oldAreaText/oldAssigneeText are free
|
||||
// text straight from the import file, deliberately NOT FK'd into
|
||||
// AssetModel/Area/Employee: import-file text won't reliably match this
|
||||
// app's catalog IDs/spelling, and forcing that match at import time would
|
||||
// block the whole import on one typo instead of just being a soft
|
||||
// "here's the old value" suggestion during the walk. Marked matched (via
|
||||
// matchedScanId) once someone actually picks it while creating a scan, so
|
||||
// it stops showing up in future searches.
|
||||
model ExpectedAsset {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
assetTag String? @map("asset_tag")
|
||||
modelText String @map("model_text")
|
||||
serialNumber String? @map("serial_number")
|
||||
oldAreaText String? @map("old_area_text")
|
||||
oldAssigneeText String? @map("old_assignee_text")
|
||||
matchedScanId String? @unique @map("matched_scan_id") @db.Uuid
|
||||
matchedScan InventoryScan? @relation(fields: [matchedScanId], references: [id])
|
||||
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
|
||||
@@map("expected_assets")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user