Move business-context doc from workspace processes/ into repo
- docs/asset-license-management.md (moved from ../processes/, fixed relative links to stay accurate from the new location) - CLAUDE.md now points at docs/asset-license-management.md - removed stale no-git-repo-yet note, added git init/push status
This commit is contained in:
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
Web app nội bộ quản lý tài sản IT + license cho Ubisoft VN local IT. Luồng chính: Request → Approval → Procurement → Receiving → Delivery → Tracking → Thu hồi/Retire.
|
Web app nội bộ quản lý tài sản IT + license cho Ubisoft VN local IT. Luồng chính: Request → Approval → Procurement → Receiving → Delivery → Tracking → Thu hồi/Retire.
|
||||||
|
|
||||||
Business context, data model, luồng trạng thái, case đặc biệt: xem `../processes/asset-license-management.md` — đó là nguồn brainstorm chính, đừng duplicate nội dung đó ở đây, chỉ link tới.
|
Business context, data model, luồng trạng thái, case đặc biệt: xem `docs/asset-license-management.md` — đó là nguồn brainstorm chính, đừng duplicate nội dung đó ở đây, chỉ link tới.
|
||||||
|
|
||||||
## Stack (đã chốt)
|
## Stack (đã chốt)
|
||||||
|
|
||||||
- Next.js (TypeScript) full-stack
|
- Next.js (TypeScript) full-stack
|
||||||
- DB: Postgres (đã chốt 2026-07-29, xem lý do trong `../processes/asset-license-management.md`)
|
- DB: Postgres (đã chốt 2026-07-29, xem lý do trong `docs/asset-license-management.md`)
|
||||||
- DB access: **Prisma** (ORM + migrations, đã chốt 2026-07-30 — lý do trong `../processes/asset-license-management.md`). Không viết raw SQL cho app logic nữa — ngoại lệ duy nhất là hạ tầng test (`tests/setup.ts` dùng raw `pg` `Client` để tạo/xoá throwaway database, đó là test infra chứ không phải data access layer).
|
- DB access: **Prisma** (ORM + migrations, đã chốt 2026-07-30 — lý do trong `docs/asset-license-management.md`). Không viết raw SQL cho app logic nữa — ngoại lệ duy nhất là hạ tầng test (`tests/setup.ts` dùng raw `pg` `Client` để tạo/xoá throwaway database, đó là test infra chứ không phải data access layer).
|
||||||
- Validation: **Zod** (đã chốt 2026-07-30, đi cùng quyết định Prisma)
|
- Validation: **Zod** (đã chốt 2026-07-30, đi cùng quyết định Prisma)
|
||||||
- UI/CSS: **Tailwind CSS v4 + shadcn/ui (CLI `@latest`, hiện tại v4.16.0)** — nâng cấp từ Tailwind v3 + `[email protected]` ngày 2026-07-30, xem lý do quyết định trong `../processes/asset-license-management.md`. Không còn `tailwind.config.ts` — theme khai báo thẳng trong CSS qua `@theme inline { ... }` (`src/app/globals.css`), `postcss.config.js` chỉ còn plugin `@tailwindcss/postcss` (không cần `autoprefixer` riêng nữa). shadcn config: style `new-york-v4`, base color `neutral`, CSS variables bật, `tailwind.config: ""` (`components.json`) — đây là style/preset cổ điển (Radix), **không phải** 8 preset thương hiệu hoá mới của CLI hiện tại (`nova/vega/maia/lyra/mira/luma/sera/rhea`, chọn qua `-p`), vốn ép dùng theme "Nova/Vega..." + tuỳ chọn thư viện primitive khác (`--base base` = Base UI, `--base aria` = React Aria) — không dùng các preset đó cho project này. Component dùng `radix-ui` (package hợp nhất, không phải `@radix-ui/react-slot` riêng lẻ nữa) và `tw-animate-css` (thay `tailwindcss-animate`). `globals.css` còn `@import "shadcn/tailwind.css"` — 1 file CSS runtime do chính package `shadcn` (npm) publish kèm nhiều utility (data-state variants, scroll-fade, shimmer...), là dependency thật (không phải chỉ dev tool) vì cần resolve lúc build. Khi thêm component mới: `npx shadcn@latest add <component>` (đã test non-interactive OK với `components.json` này qua flag `-y --overwrite`).
|
- UI/CSS: **Tailwind CSS v4 + shadcn/ui (CLI `@latest`, hiện tại v4.16.0)** — nâng cấp từ Tailwind v3 + `[email protected]` ngày 2026-07-30, xem lý do quyết định trong `docs/asset-license-management.md`. Không còn `tailwind.config.ts` — theme khai báo thẳng trong CSS qua `@theme inline { ... }` (`src/app/globals.css`), `postcss.config.js` chỉ còn plugin `@tailwindcss/postcss` (không cần `autoprefixer` riêng nữa). shadcn config: style `new-york-v4`, base color `neutral`, CSS variables bật, `tailwind.config: ""` (`components.json`) — đây là style/preset cổ điển (Radix), **không phải** 8 preset thương hiệu hoá mới của CLI hiện tại (`nova/vega/maia/lyra/mira/luma/sera/rhea`, chọn qua `-p`), vốn ép dùng theme "Nova/Vega..." + tuỳ chọn thư viện primitive khác (`--base base` = Base UI, `--base aria` = React Aria) — không dùng các preset đó cho project này. Component dùng `radix-ui` (package hợp nhất, không phải `@radix-ui/react-slot` riêng lẻ nữa) và `tw-animate-css` (thay `tailwindcss-animate`). `globals.css` còn `@import "shadcn/tailwind.css"` — 1 file CSS runtime do chính package `shadcn` (npm) publish kèm nhiều utility (data-state variants, scroll-fade, shimmer...), là dependency thật (không phải chỉ dev tool) vì cần resolve lúc build. Khi thêm component mới: `npx shadcn@latest add <component>` (đã test non-interactive OK với `components.json` này qua flag `-y --overwrite`).
|
||||||
- Self-hosted (theo nguyên tắc chung của workspace — ưu tiên self-host hơn cloud, xem `../processes/new-office-fitout.md`)
|
- Self-hosted (theo nguyên tắc chung của workspace — ưu tiên self-host hơn cloud, xem `../processes/new-office-fitout.md`)
|
||||||
|
|
||||||
## Coding conventions
|
## Coding conventions
|
||||||
@@ -71,13 +71,13 @@ Với mỗi task cụ thể (vd "thêm API tạo Request", "màn hình bàn giao
|
|||||||
- **Tailwind + shadcn/ui setup xong (2026-07-30, ban đầu trên v3)**: `postcss.config.js`, `src/app/globals.css`, `components.json`, `src/lib/utils.ts` (`cn()`), `src/components/ui/button.tsx` (component mẫu để xác nhận pipeline chạy được). Có 1 bug phát hiện qua verify độc lập (màu token bị bọc `hsl()` chồng lên giá trị `oklch()` sẵn có → CSS không hợp lệ, silent fail lúc render dù build/lint/tsc đều xanh) — đã fix và CONFIRMED qua verify độc lập lần 2.
|
- **Tailwind + shadcn/ui setup xong (2026-07-30, ban đầu trên v3)**: `postcss.config.js`, `src/app/globals.css`, `components.json`, `src/lib/utils.ts` (`cn()`), `src/components/ui/button.tsx` (component mẫu để xác nhận pipeline chạy được). Có 1 bug phát hiện qua verify độc lập (màu token bị bọc `hsl()` chồng lên giá trị `oklch()` sẵn có → CSS không hợp lệ, silent fail lúc render dù build/lint/tsc đều xanh) — đã fix và CONFIRMED qua verify độc lập lần 2.
|
||||||
- **Nâng cấp lên Tailwind v4 + shadcn CLI `@latest` xong (2026-07-30)**: bỏ `tailwind.config.ts` (theme giờ khai trong `globals.css` qua `@theme inline`), đổi `postcss.config.js` sang `@tailwindcss/postcss`, đổi dependency (`radix-ui` thay `@radix-ui/react-slot`, `tw-animate-css` thay `tailwindcss-animate`, thêm `shadcn` làm runtime dependency vì `globals.css` import `shadcn/tailwind.css`), `button.tsx` viết lại theo registry `new-york-v4` hiện tại. **CONFIRMED qua test-runner độc lập**: install/build/tsc/lint sạch, 6/6 test Request vẫn pass (không liên quan tới UI), CSS đã compile xác nhận màu sạch (không còn kiểu bug `hsl(oklch(...))`), không còn gói v3 sót lại.
|
- **Nâng cấp lên Tailwind v4 + shadcn CLI `@latest` xong (2026-07-30)**: bỏ `tailwind.config.ts` (theme giờ khai trong `globals.css` qua `@theme inline`), đổi `postcss.config.js` sang `@tailwindcss/postcss`, đổi dependency (`radix-ui` thay `@radix-ui/react-slot`, `tw-animate-css` thay `tailwindcss-animate`, thêm `shadcn` làm runtime dependency vì `globals.css` import `shadcn/tailwind.css`), `button.tsx` viết lại theo registry `new-york-v4` hiện tại. **CONFIRMED qua test-runner độc lập**: install/build/tsc/lint sạch, 6/6 test Request vẫn pass (không liên quan tới UI), CSS đã compile xác nhận màu sạch (không còn kiểu bug `hsl(oklch(...))`), không còn gói v3 sót lại.
|
||||||
- **Rủi ro tồn đọng (dormant, chưa gãy)**: `button.tsx` mới bỏ `React.forwardRef` (convention của registry hiện tại là cho React 19), nhưng project đang pin **React 18.3.1** — nếu sau này có chỗ truyền `ref` vào `<Button>`, ref sẽ không được forward đúng cách. Hiện tại không chỗ nào trong code truyền `ref` nên chưa phát sinh lỗi — nhưng cần nhớ khi build UI thật, tránh `<Button ref={...}>` hoặc phải tự thêm lại `forwardRef` nếu cần.
|
- **Rủi ro tồn đọng (dormant, chưa gãy)**: `button.tsx` mới bỏ `React.forwardRef` (convention của registry hiện tại là cho React 19), nhưng project đang pin **React 18.3.1** — nếu sau này có chỗ truyền `ref` vào `<Button>`, ref sẽ không được forward đúng cách. Hiện tại không chỗ nào trong code truyền `ref` nên chưa phát sinh lỗi — nhưng cần nhớ khi build UI thật, tránh `<Button ref={...}>` hoặc phải tự thêm lại `forwardRef` nếu cần.
|
||||||
|
- **Git repo khởi tạo + push lên GitHub xong (2026-07-30)**: `https://github.com/toandev96/ubi-dan-itam.git` (private), remote `origin`/branch `master`. Business context (`docs/asset-license-management.md`) đã move từ `ubisoft/processes/` vào trong repo này cùng ngày, để travel theo code khi clone ở máy khác (vd VM Linux ở nhà qua Proxmox) — không còn phụ thuộc thư mục `processes/` ở workspace ngoài repo nữa cho riêng phần business context của app này.
|
||||||
|
|
||||||
## Việc còn dở
|
## Việc còn dở
|
||||||
|
|
||||||
- Bump `vitest` lên 4.x (fix advisory critical GHSA-5xrq-8626-4rwp — hiện không khai thác được vì project không chạy `vitest --ui`, nhưng nên dọn khi có breaking-change window) — không khẩn cấp.
|
- Bump `vitest` lên 4.x (fix advisory critical GHSA-5xrq-8626-4rwp — hiện không khai thác được vì project không chạy `vitest --ui`, nhưng nên dọn khi có breaking-change window) — không khẩn cấp.
|
||||||
- Rà lại advisory riêng của `next` (prod dependency, có vài high/moderate — vd SSRF qua WebSocket upgrade, middleware bypass) khi có dịp, tách biệt khỏi đợt retrofit Prisma/Zod này.
|
- Rà lại advisory riêng của `next` (prod dependency, có vài high/moderate — vd SSRF qua WebSocket upgrade, middleware bypass) khi có dịp, tách biệt khỏi đợt retrofit Prisma/Zod này.
|
||||||
- Test coverage gaps (chưa block gì, chỉ là follow-up): chưa test malformed JSON body, chưa test JSON body không phải object (array/string).
|
- Test coverage gaps (chưa block gì, chỉ là follow-up): chưa test malformed JSON body, chưa test JSON body không phải object (array/string).
|
||||||
- Chưa có git repo cho project này — chưa có version history/rollback cho bất kỳ thay đổi nào ở trên. Nên `git init` sớm trước khi làm thêm entity mới.
|
|
||||||
- `Button` (shadcn) không `forwardRef`, React đang pin 18 — dormant risk, xem note ở "Trạng thái hiện tại".
|
- `Button` (shadcn) không `forwardRef`, React đang pin 18 — dormant risk, xem note ở "Trạng thái hiện tại".
|
||||||
- Các entity còn lại: `Employee`, `AssetItem`, `License`, `PurchaseOrder`, `Receipt`, `Assignment`
|
- Các entity còn lại: `Employee`, `AssetItem`, `License`, `PurchaseOrder`, `Receipt`, `Assignment`
|
||||||
- Các state tiếp theo của Request: Pending Approval → Approved → Ordered → Received → Delivered → Closed, và nhánh Rejected/Cancelled
|
- Các state tiếp theo của Request: Pending Approval → Approved → Ordered → Received → Delivered → Closed, và nhánh Rejected/Cancelled
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# Quản lý Tài sản IT & License
|
||||||
|
|
||||||
|
## Trạng thái hiện tại
|
||||||
|
|
||||||
|
- Chưa có hệ thống tập trung — request xử lý rời rạc qua email/docx (vd `Firefly_License_Request.docx`, `Eric Pelatan.docx` ở gốc workspace `ubisoft/`, ngoài repo này). Không tracking được ai đang giữ gì, license nào sắp hết hạn/hết seat, tài sản nào sắp hết bảo hành.
|
||||||
|
- Đã chốt: kiến trúc monolith Next.js, không tách backend/frontend ở giai đoạn này (xem trigger để tách ở dưới).
|
||||||
|
- **Đã chốt: Postgres** (2026-07-29) — lý do: đảm bảo scale sau này + Power BI connect native, và bạn đã có kinh nghiệm dùng Postgres. Migrate task 1 (entity Request, state Draft) từ SQLite sang Postgres đã xong, CONFIRMED pass.
|
||||||
|
- **Đã chốt: Prisma (ORM) + Zod (validation)** (2026-07-30) — lý do Prisma over Drizzle cho solo dev: Prisma Studio (xem/sửa data qua GUI, khỏi viết psql query khi không có teammate hỏi), migration workflow tự động (`prisma migrate dev`), docs/community lớn hơn hẳn khi cần tự tra cứu một mình. Đánh đổi: nặng hơn Drizzle (query engine binary riêng, cần bước generate client), "magic" hơn raw SQL. Zod đi kèm để tận dụng type inference thay vì viết tay interface + hàm validate riêng.
|
||||||
|
- **Retrofit `Request` sang Prisma+Zod xong (2026-07-30)** — CONFIRMED qua test-runner độc lập: 6 test pass trên Postgres thật (qua `prisma migrate deploy`), type-check sạch, lint sạch. `type` chuyển từ `TEXT + CHECK` sang Postgres enum (`RequestType`) — tương đương semantics, không phải divergence. `id`/`createdAt` giữ nguyên hành vi cũ. Chi tiết đầy đủ ở `../CLAUDE.md`.
|
||||||
|
- Project scaffold (multi-agent dev workflow) đặt ngay tại repo này — xem `../CLAUDE.md`.
|
||||||
|
- File này trước đây nằm ở `ubisoft/processes/asset-license-management.md` (workspace chung, không phải git repo) — đã move vào đây (2026-07-30) vì nó gắn chặt với app này và cần update song song với code. `ubisoft/processes/README.md` vẫn giữ 1 dòng trỏ tới đây cho ai tìm từ đó.
|
||||||
|
|
||||||
|
## Mục tiêu
|
||||||
|
|
||||||
|
Theo dõi toàn bộ vòng đời tài sản/license: **Request → Approval → Procurement → Receiving → Delivery → Tracking → Thu hồi/Retire**, và trả lời nhanh được:
|
||||||
|
- Ai đang giữ máy/license nào?
|
||||||
|
- License nào sắp hết hạn hoặc hết seat?
|
||||||
|
- Tài sản nào sắp hết bảo hành?
|
||||||
|
- Chi phí/license theo phòng ban là bao nhiêu?
|
||||||
|
|
||||||
|
## Data model (sơ bộ)
|
||||||
|
|
||||||
|
| Entity | Ý nghĩa |
|
||||||
|
|---|---|
|
||||||
|
| `Employee` | id, tên, phòng ban, manager |
|
||||||
|
| `Vendor` | nhà cung cấp |
|
||||||
|
| `AssetItem` | hardware — serial number, model, ngày mua, bảo hành, trạng thái (in stock / assigned / repair / retired) |
|
||||||
|
| `License` | phần mềm — tên, vendor, tổng seat, seat đã dùng, ngày hết hạn, loại (perpetual/subscription) |
|
||||||
|
| `Request` | người yêu cầu, loại (asset/license), lý do, trạng thái |
|
||||||
|
| `PurchaseOrder` | gộp nhiều Request đã duyệt, vendor, ngày đặt, ngày dự kiến nhận |
|
||||||
|
| `Receipt` | nhận hàng — đối chiếu PO, ngày nhận, người nhận |
|
||||||
|
| `Assignment` | gán AssetItem/License cho Employee — ngày giao, ngày trả, biên bản ký nhận |
|
||||||
|
| `Request.servicenow_ticket` | field text, nhập tay số ticket ServiceNow liên quan (không tích hợp API ServiceNow ngay — volume thấp, nhập tay đủ dùng; để ngỏ cho auto-sync sau nếu cần) |
|
||||||
|
|
||||||
|
## Luồng trạng thái Request
|
||||||
|
|
||||||
|
```
|
||||||
|
Draft → Pending Approval → Approved → Ordered → Received → Delivered → Closed
|
||||||
|
↓
|
||||||
|
Rejected / Cancelled
|
||||||
|
```
|
||||||
|
|
||||||
|
## Module tương lai: Rack/Slot management + IoT (chưa build, chỉ note kiến trúc)
|
||||||
|
|
||||||
|
Mục tiêu xa hơn: biết chính xác asset nằm ở ô/slot nào trên tủ rack, và hướng dẫn người lấy đúng ô bằng đèn (pick-to-light).
|
||||||
|
|
||||||
|
**Data model thêm:**
|
||||||
|
- `Rack` (id, tên, vị trí — map với `rack-1/2/3` đã có ảnh ở `../../server-racks/`, thư mục ngoài repo này trong workspace `ubisoft/`)
|
||||||
|
- `RackSlot` (rack_id, vị trí U, `sensor_status` [empty/occupied — ghi bởi cảm biến vật lý], `assigned_asset_id` [nullable — ghi khi người dùng quét QR gán asset vào slot])
|
||||||
|
- Mismatch giữa `sensor_status` và `assigned_asset_id` (vd sensor báo occupied nhưng không có asset nào được assign) = tín hiệu cần kiểm tra thủ công (phát hiện thất thoát/quên cập nhật)
|
||||||
|
|
||||||
|
**Kiến trúc:** tách stack IoT riêng (broker MQTT hoặc tận dụng Home Assistant đã định dùng cho KNX ở văn phòng mới, xem `../../processes/new-office-fitout.md`) khỏi app chính — lý do là giao thức (MQTT/CoAP), data shape (time-series), và network/bảo mật (nên tách VLAN như camera/access control) đều khác hẳn CRUD web app. Tích hợp qua **1 bridge job** đọc/ghi trạng thái vào Postgres của app chính (`RackSlot.sensor_status`) — app chính không cần biết MQTT/HASS, Postgres vẫn là nguồn sự thật duy nhất.
|
||||||
|
|
||||||
|
**Luồng pick-to-light (tương lai):**
|
||||||
|
1. Request duyệt → nhận hàng → asset gán vào 1 `RackSlot` cụ thể → trạng thái Request thêm state mới "Ready for Pickup"
|
||||||
|
2. Người tới quét số ticket (ServiceNow, nhập tay ở trên) tại trạm quét QR gắn cạnh tủ rack → gọi API tra `RackSlot` tương ứng
|
||||||
|
3. Trạm quét = **consumer độc lập thứ 2** của app (ngoài web frontend) → endpoint này cần thiết kế như API thật (auth riêng cho thiết bị, không dựa session web) — đây là trigger hợp lệ đầu tiên để có 1 API boundary rõ ràng, dù chưa cần tách hẳn backend
|
||||||
|
4. App → bridge → publish lệnh bật đèn đúng slot qua IoT stack
|
||||||
|
5. Người lấy xong → xác nhận (quét lại hoặc sensor tự phát hiện chuyển empty) → tắt đèn, đóng Assignment/Request
|
||||||
|
|
||||||
|
QR gán asset vào slot (bước 1, thủ công hàng ngày) **không phải IoT** — chỉ là quét mã bằng camera trình duyệt/máy quét cầm tay, ghi thẳng qua API hiện có của app chính, không cần MQTT.
|
||||||
|
|
||||||
|
## Case đặc biệt cần xử lý
|
||||||
|
|
||||||
|
- Nhân viên nghỉ việc → checklist thu hồi asset + license (offboarding)
|
||||||
|
- License seat-based dùng chung (vd Adobe CC theo pool chung của phòng ban)
|
||||||
|
- Tài sản luân chuyển giữa phòng ban / chi nhánh (không phải "delivery" mới, mà là re-assign)
|
||||||
|
- Asset hỏng → gửi RMA/sửa chữa → cần state "in repair" tách khỏi "assigned"
|
||||||
|
|
||||||
|
## Quyết định kiến trúc
|
||||||
|
|
||||||
|
- Quy mô hiện tại <100 người, IT team nhỏ → **web app tự build gọn nhẹ, monolith** (Next.js full-stack, frontend + API routes chung 1 app) — self-hosted, tương tự pattern app "IT Knowledge Base + Ticket Analyzer" đã build cho `it-support.md` (workspace ngoài repo này), theo nguyên tắc chung của workspace là ưu tiên self-host hơn cloud (xem `../../processes/new-office-fitout.md`). **Không tách backend/frontend riêng ở giai đoạn này** — xem lý do & trigger để tách ở dưới.
|
||||||
|
- DB: **Postgres, đã chốt** (2026-07-29). Lý do: đảm bảo scale sau này, Power BI connect native/ổn định tới Postgres (còn SQLite cần ODBC driver gượng ép + không hợp để BI query đồng thời lúc app đang ghi), và đã có kinh nghiệm sẵn với Postgres. Cách lộ dữ liệu cho Power BI: tạo Postgres views riêng cho report (vd `v_requests_report`, `v_license_utilization`) + 1 read-only DB user trỏ Power BI vào, **không cần expose API riêng cho việc này**.
|
||||||
|
- Cron job (vd gửi email cảnh báo license sắp hết hạn hàng ngày) **không cần tách backend riêng** — làm 1 script độc lập (`scripts/send-license-expiry-emails.ts`) query thẳng Postgres, lịch chạy qua Windows Task Scheduler (đã có tiền lệ ở `xibo-signage.md`, workspace ngoài repo này) hoặc container cron riêng trong Docker. Cần chốt sau: SMTP nào, ngưỡng cảnh báo bao nhiêu ngày, gửi cho ai.
|
||||||
|
- Cân nhắc thay thế cho MVP: Airtable/Google Form nếu muốn test quy trình trước khi build — nhưng approval workflow nhiều bước + audit trail sẽ gượng ép nếu để lâu dài trên low-code.
|
||||||
|
- Reverse proxy khi deploy: **Nginx Proxy Manager** (đã chốt 2026-07-30) — tự host, có UI quản lý + tự động Let's Encrypt. Chưa dựng ngay vì app còn ở local dev, chưa tới bước deploy production. Khi deploy, app này khả năng sẽ dùng chung 1 NPM instance với các service self-host khác trong workspace (vd Xibo) thay vì mỗi app 1 reverse proxy riêng — cần xác nhận lại lúc thực sự deploy.
|
||||||
|
|
||||||
|
### Khi nào nên tách backend riêng (chưa áp dụng, chỉ ghi lại trigger)
|
||||||
|
|
||||||
|
1. Có consumer thứ 2 thật sự cần gọi API độc lập ngoài web frontend (vd trạm quét QR pick-to-light — xem module Rack/Slot ở dưới; hoặc tích hợp ServiceNow sau này)
|
||||||
|
2. Có job cần chạy tách biệt khỏi request-response của web (cron email đã quyết là chưa cần tách, chỉ cần script + scheduler)
|
||||||
|
3. Cần hạ tầng/bảo mật khác biệt (vd module IoT rack — xem dưới, lý do khác hẳn: giao thức, data shape, network)
|
||||||
|
4. Team lớn tới mức có người riêng phụ trách backend
|
||||||
|
|
||||||
|
"Muốn tích hợp với hệ thống khác" **tự nó không phải lý do để tách** — ngược lại, tích hợp chặt (vd Rack/Slot dùng chung AssetItem) là lý do để **gộp chung** app/DB thay vì làm hệ thống riêng rồi nối lại qua API.
|
||||||
|
|
||||||
|
## Process / SOP
|
||||||
|
|
||||||
|
*(Chưa có — sẽ bổ sung khi bắt đầu implement: quy trình tạo request mới, checklist nhận hàng, checklist bàn giao có ký nhận, checklist offboarding thu hồi thiết bị)*
|
||||||
|
|
||||||
|
## Việc còn dở
|
||||||
|
|
||||||
|
- Thiết kế ERD chi tiết + wireframe màn hình
|
||||||
|
- Entity còn lại: `Employee`, `AssetItem`, `License`, `PurchaseOrder`, `Receipt`, `Assignment`
|
||||||
|
- Migrate 2 request đang có (`Firefly_License_Request.docx`, `Eric Pelatan.docx`, ở workspace `ubisoft/` ngoài repo này) vào hệ thống mới sau khi có DB
|
||||||
|
- (Xa hơn, chưa ưu tiên) Rack/Slot + IoT pick-to-light, cron email cảnh báo license hết hạn, Power BI report views
|
||||||
|
|
||||||
|
## Ghi chú & bài học
|
||||||
|
|
||||||
|
- Migrate entity `Request` từ SQLite sang Postgres (2026-07-30) và setup ESLint đều đã **CONFIRMED xong** qua lượt verify độc lập (test-runner riêng, không phải agent vừa code tự chấm) — 6 test pass trên Postgres thật, lint sạch, type-check sạch. Chi tiết trạng thái nằm ở `../CLAUDE.md`, không duplicate ở đây.
|
||||||
|
|
||||||
|
---
|
||||||
|
Cập nhật lần cuối: 2026-07-30
|
||||||
Reference in New Issue
Block a user