7.3 KiB
sub-invest-codebase-A-mapping
HEADLINE: 30 cột Excel map GỌN vào 27 field Supplier: 1 ignore (STT) + 27 direct-field (cột 2–28, mỗi field dùng đúng 1 lần) + 2 cột audit-provenance (NGÀY/NGƯỜI CẬP NHẬT) KHÔNG có field khớp trực-tiếp → cần owner quyết. Seed 4 NCC (DbInitializer.cs:2775-2782) đã là precedent transform sống cho 27 mapping.
LANE A — COLUMN→FIELD MAPPING (verified vs source thật)
Nguồn verify: src/Backend/SolutionErp.Domain/Master/Supplier.cs:5-36 (27 field), SupplierType.cs:3-11, SupplierStatus.cs:3-8, precedent transform DbInitializer.cs:2775-2782 (seed 4 NCC thật đã map 30→27), audit AuditingInterceptor.cs:44-49 + BaseEntity.cs:6-9.
Bảng mapping đủ 30 dòng
| # | Excel col (r4) | → target field | kind | transform / note |
|---|---|---|---|---|
| 1 | STT | — | ignore | Số dòng, không persist |
| 2 | GÓI THẦU | PackageCategory |
direct-field | Free-text. Seed vd "10-Nhôm kính+Face Mặt dựng" |
| 3 | PHÂN LOẠI (NTP/NCC/Cả hai) | Type (SupplierType, non-null) |
enum-map | Trim+ci: NCC→NhaCungCap(1) · NTP→NhaThauPhu(2) · Cả hai→CaHai(6). (Enum còn TĐ=3/ĐVDV=4/CĐT=5 nếu source có). Non-nullable → giá trị lạ phải reject-row hoặc default (owner) |
| 4 | TÊN VIẾT TẮT | Code (required) |
direct-field | = Mã NCC dùng trong mã HĐ. Trim+UPPER khuyến nghị (seed: TRUONGGIANG). Là khóa idempotent/dedup |
| 5 | TÊN CÔNG TY | Name (required) |
direct-field | Tên đầy đủ. KHÔNG tạo cột companyName mới — reuse Name gốc |
| 6 | ĐỊA CHỈ XUẤT HÓA ĐƠN | Address |
direct-field | = "địa chỉ xuất HĐ/đăng ký" (comment field khớp). Reuse cột gốc, KHÔNG tạo invoiceAddress |
| 7 | ĐỊA CHỈ VĂN PHÒNG | OfficeAddress |
direct-field | 4 NCC seed để trống → field vẫn là target đúng |
| 8 | SỐ ĐT CÔNG TY | Phone |
direct-field | Phone công-ty (phân biệt cột 21) |
| 9 | FAX | Fax |
direct-field | Chỉ TGN có (seed "0251.2814663") |
| 10 | SỐ TÀI KHOẢN+TÊN+CN.NH | BankAccount |
direct-field · COMPOSITE | Giữ RAW 1 ô (precedent: "100212127 Ngân hàng Eximbank - Chi Nhánh Hòa Bình"). Entity KHÔNG có AccountName/BankBranch → không tách |
| 11 | SỐ TK PHỤ | SecondaryBankAccount |
direct-field | 4 NCC seed để trống, field đúng target |
| 12 | MÃ SỐ THUẾ | TaxCode |
direct-field | Giữ raw kể cả có space ("0312 251 859"). Có thể null (DONGDUONG) |
| 13 | NGƯỜI ĐẠI DIỆN PHÁP LUẬT | LegalRepresentative |
direct-field | Giữ prefix "Ông/Bà" như seed |
| 14 | CHỨC VỤ ĐẠI DIỆN | LegalRepTitle |
direct-field | vd "GIÁM ĐỐC ĐIỀU HÀNH" |
| 15 | GIẤY ỦY QUYỀN | AuthorizationNote |
direct-field | Free-text dài (số GUQ+ngày+người ủy quyền) |
| 16 | Link GUQ | LinkGuq |
direct-field · NAS path | Giữ RAW backslash @"01. GPKD_HSNL_GUQ\02.Trường giang\...pdf" — KHÔNG normalize \→/ |
| 17 | Link GPKD | LinkGpkd |
direct-field · NAS path | như trên |
| 18 | Link HSNL | LinkHsnl |
direct-field · NAS path | như trên |
| 19 | NGƯỜI LH CHÍNH | ContactPerson |
direct-field | Người liên hệ chính (seed "Mr. Việt") |
| 20 | CHỨC VỤ NGƯỜI LH | ContactTitle |
direct-field | vd "Kinh doanh" |
| 21 | SĐT CHÍNH | ContactPhone |
direct-field | Phone người-LH (KHÁC cột 8 phone công-ty) |
| 22 | Email |
direct-field | ||
| 23 | ĐỊA CHỈ GỬI THƯ | MailingAddress |
direct-field | Địa chỉ thứ-3 (khác cột 6 & 7) |
| 24 | NGƯỜI NHẬN THƯ/SĐT | MailRecipient |
direct-field · COMPOSITE | Giữ RAW "MS Thủy / 036 405 0016" (name+phone gộp). Entity không có field tách |
| 25 | NGUỒN GIỚI THIỆU | ReferralSource |
direct-field | vd "Tái sử dụng DA trước" |
| 26 | NGƯỜI PHỤ TRÁCH(PMH) | OwnerPmh |
direct-field | vd "Bình" |
| 27 | TÌNH TRẠNG HIỆN TẠI | Status (SupplierStatus?, nullable) |
enum-map | Strip emoji + trim: ✅ Đang hoạt động→DangHoatDong(1) · Blacklist/đen→Blacklist(2) · Ngừng hợp tác→NgungHopTac(3). Nullable → giá trị lạ = null OK |
| 28 | GHI CHÚ/LÝ DO BLACKLIST | Note |
direct-field | Target ĐÚNG cho Note. (Seed để Note=null vì đã un-cram legacy — import thì col 28 mới là Note thật; coherence: khi Status=Blacklist thì lý-do nằm ở đây) |
| 29 | NGÀY CẬP NHẬT CUỐI | (audit) UpdatedAt? |
KHÔNG có field khớp | ⚠️ Map UpdatedAt = futile: AuditingInterceptor.cs:48 GHI ĐÈ UpdatedAt=now mỗi save. → ignore / gộp-Note / đề-xuất-field-mới (xem openQuestions) |
| 30 | NGƯỜI CẬP NHẬT | (audit) UpdatedBy? |
KHÔNG có field khớp | ⚠️ UpdatedBy là Guid? (userId), Excel là tên người (text) → type mismatch + bị AuditingInterceptor.cs:49 ghi đè. Không direct-map được |
Kiểm chứng độ-phủ (0 sót)
- 27/27 field entity được map đúng 1 lần (9 core + 18 expansion) — cột 2–28 (27 cột).
- Cột 1 STT = ignore.
- Cột 29–30 = audit-provenance, KHÔNG field khớp trực tiếp → quyết định owner.
- Tổng: 1 ignore + 27 direct + 2 no-field = 30 ✓.
3 nhóm cần transform đặc-biệt (đã đánh dấu trong bảng)
- COMPOSITE (2): cột 10 BankAccount + cột 24 MailRecipient → giữ RAW (precedent seed đã giữ raw, entity thiếu sub-field để tách).
- ENUM-MAP (2): cột 3 Type (trim+ci, non-null → cần rule giá-trị-lạ) + cột 27 Status (strip emoji, nullable → lạ=null).
- NAS path (3): cột 16/17/18 → giữ raw backslash, KHÔNG đổi
\→/. - Chung mọi cột: normalize
\n/whitespace trong header r4 (multi-line) + trim cell; skip#REF!ở r2 (chỉ parse tên r4).
Lưu ý reuse-cột (tránh orphan)
Cột 5/6 map thẳng Name/Address gốc — KHÔNG tạo companyName/invoiceAddress mới (sẽ orphan cột seed live). 18 expansion field vốn purpose-built đúng cho Excel này (Mig 62), khớp 1-1 cột 2,7,9,10,11,13-18,20,21,23-27.
Open Questions
1. Cột 29-30 (NGÀY/NGƯỜI CẬP NHẬT) xử lý sao? — KHÔNG có field khớp (audit fields UpdatedAt/UpdatedBy bị AuditingInterceptor ghi đè + UpdatedBy là Guid≠tên). 3 lựa chọn: (a) ignore — audit tự stamp import-time (mất provenance nguồn); (b) gộp-Note — nối "Cập nhật cuối 01/07/2027 bởi Bình" vào Note (giữ provenance, không thêm schema); (c) đề-xuất-field-mới SourceUpdatedAt DateTime? + SourceUpdatedBy string? (+2 cột Mig 63, sạch nhất nhưng thêm migration).
2. PHÂN LOẠI (col 3, non-nullable Type) khi gặp giá-trị-lạ ngoài NTP/NCC/Cả hai → reject-row hay default về NhaCungCap? (Status nullable nên không vướng — lạ=null).
3. Composite cột 10 & 24 — xác nhận giữ RAW (theo precedent seed) hay owner muốn tách sub-field (cần thêm cột AccountName/BankBranch/RecipientPhone → Mig mới)?
4. Code (col 4) là khóa idempotent — import gặp Code đã tồn tại thì skip / fill-nulls / overwrite? (Ảnh hưởng Lane B robustness).