# MTMS (FPSMS) ↔ M18 資料對照手冊 本文件說明 **MTMS / FPSMS** 與 **M18** 之間的主檔與交易對應、同步方向,以及已知陷阱。 | 區塊 | 維護方式 | |------|----------| | 本手冊(說明、流程、陷阱) | **人手**維護 | | [`docs/generated/`](./generated/) 對照表 | **腳本產生**(見下方) | 重新產生自動表(改完 enum / mapping 後請跑): ```bash python scripts/generate_m18_mapping_docs.py ``` 匯出 **Word / Excel**(給非技術閱讀;需已安裝 `python-docx`、`openpyxl`): ```bash pip install python-docx openpyxl python scripts/export_m18_mapping_office.py ``` 產出: - `docs/exports/MTMS_M18_DATA_MAPPING.docx` - `docs/exports/MTMS_M18_DATA_MAPPING.xlsx` --- ## 1. 系統與名詞 | 名稱 | 說明 | |------|------| | **MTMS / FPSMS** | 本後端 `FPSMS-backend` + 前端 `FPSMS-frontend` | | **M18** | 外部 ERP/主檔與採購/送貨來源系統 | | **Pull** | M18 → MTMS(product / vendor / unit / currency / BOM / business unit / PO / DO) | | **Push** | MTMS → M18(例如 GRN、BOM for shop) | 設定入口:`m18/M18Config.kt`(`m18.config.*`)、scheduler 見 `application.yml` / `application-prod.yml`(`scheduler.m18Sync`、`scheduler.m18Grn`)。 主程式目錄:`src/main/java/com/ffii/fpsms/m18/`。 --- ## 2. Master API 類型(`StSearchType`) 完整表見自動產生檔: → **[generated/m18-stsearch-types.md](./generated/m18-stsearch-types.md)** 摘要: | M18 `stSearch` | MTMS 落點 | |----------------|-----------| | `pro` | `items` | | `ven` | `shop`(`type=supplier`) | | `virDept` | `shop`(`type=shop`) | | `unit` | `uom_conversion`(+ cunit) | | `cur` | `currency` | | `udfbomforshop` | `bom` / materials | 實作:`M18MasterDataService`。 --- ## 3. 貨品類型(最常查) ### 3.1 同步規則(自動表) → **[generated/m18-item-type-mapping.md](./generated/m18-item-type-mapping.md)** 程式:`M18MasterDataService.saveProduct` / `saveProducts` 依 `pro.udfProducttype`: ```text Consumable Material → consumables Non-consumable Material → non-consumables Product → fg WIP → sfg Item → item (其他,含 CMB) → mat ← default ``` Enum 定義:`modules/master/web/models/NewItemRequest.kt`(`ItemType`、`M18ItemType`)。 ### 3.2 UI 顯示(存貨) 存貨 Type 欄:`t(itemType)`,翻譯在 `FPSMS-frontend/src/i18n/zh/inventory.json`。 | `items.type` | 存貨頁(zh) | |--------------|--------------| | `mat` | 原料 | | `fg` | 成品 | | `sfg` / `wip` | 半成品 | | `consumables` / `cmb` | 消耗品 | | `non-consumables` / `nm` | 非消耗品/雜項 | > 系統 **沒有**「產品」這個 `items.type`。M18 的 **Product** 對應 MTMS **`fg`(成品)**。 ### 3.3 可手動改嗎? 可以:Settings → Items → Edit → Type(`ProductDetails.tsx`:`fg` / `wip` / `mat` / `cmb` / `nm`)。 注意:之後若再跑 **product sync**,type 會依 M18 `udfProducttype` **覆寫**(含再次落到 `mat`)。 ### 3.4 已知陷阱:`CMB` M18 實務上可出現 `"udfProducttype": "CMB"`(例如蔗糖水 `MG1852`)。 - `"CMB"` ≠ `"Consumable Material"` - 也不等於前端的 `cmb` - → sync 走 **else → `mat`** → 存貨顯示 **原料** 若要顯示消耗品:需改 mapping(例如把 `CMB` 對到 `consumables`),或在 M18 改成已支援的字串;僅手動改 MTMS 可能被下次 sync 蓋掉。 --- ## 4. 供應商與店鋪 | 方向 | M18 | MTMS | |------|-----|------| | Pull vendors | `ven` | `shop`,`ShopType.SUPPLIER`(`supplier`) | | Pull business units | `virDept` | `shop`,`ShopType.SHOP`(`shop`) | 鍵:`shop.m18Id`、`shop.code`。名稱優先 `descZhTW` → `descZhCN` → `desc`。 `ShopType`:`modules/master/enums/ShopType.kt`。 --- ## 5. 單位(UoM) | M18 | MTMS | |-----|------| | Unit master (`unit`) | `uom_conversion`(`code`、`udfudesc`、`udfShortDesc`、`m18Id`…) | | Cunit 明細 | `M18CunitService.replaceForUnit` | Item 級採購/庫存/銷售單位在 sync product price 時寫入 `item_uom`(見 `M18MasterDataService` product 區塊)。 PO/DO 行常同時保留: | 欄位 | 意義 | |------|------| | `qty` / `uomId` | MTMS 業務單位(例如採購單位換算後) | | `qtyM18` / `uomIdM18` | M18 原始單位數量 | PO 換算邏輯見 `M18PurchaseOrderService`(`convertQtyToPurchaseQty`)。 --- ## 6. 貨幣、BOM | M18 | MTMS | Service | |-----|------|---------| | Currency | `currency` | `saveCurrencies` | | BOM (`udfbomforshop`) | `bom` / `bom_material` | `saveBoms` | Shop BOM **回寫** M18:`M18BomForShopService`(push)。 --- ## 7. 交易文件(摘要) | 文件 | 方向 | MTMS 主表 | 筆記 | |------|------|-----------|------| | PO | M18 → MTMS | `purchase_order` / `purchase_order_line` | `m18Id` / data log;qty 可能換算 | | DO | M18 → MTMS | `delivery_order` / `delivery_order_line` | 含 `qtyM18`、`uomIdM18` | | GRN | MTMS → M18 | stock-in → M18 GRN API | 部分 `m18CreatedUId` **不送** GRN(見下) | ### GRN 略過規則 `m18/M18GrnRules.kt`: | M18 PO `createUid` | 備註 | 行為 | |--------------------|------|------| | `2569` | legato | 不 post GRN | | `2676` | xtech | 不 post GRN | --- ## 8. Config 鍵(對照時常用) 見 `M18Config` / `application-*.yml`: - `m18.config.seriesId.pp|pf|sc|se|sf|sr` - `m18.config.beId.pp|pf|toa` - `m18.config.supplier-not.material-po` - `m18.config.supplier.shop-po` / `oem-po` - `scheduler.m18Sync.enabled` - `scheduler.m18Grn.createEnabled` --- ## 9. 驗證用 SQL 範例 ```sql -- 某貨品目前 type(決定存貨顯示) SELECT code, name, type, m18Id, m18LastModifyDate FROM items WHERE deleted = 0 AND code = 'MG1852'; -- 統計 type 分佈 SELECT type, COUNT(*) AS cnt FROM items WHERE deleted = 0 GROUP BY type ORDER BY cnt DESC; ``` 若 M18 回傳 `udfProducttype` 可與上表比對;對不上表中「exact string」者皆會變 `mat`。 --- ## 10. 維護約定 1. **改 mapping**:先改 Kotlin enum / `when`,再跑 `python scripts/generate_m18_mapping_docs.py`,把 `docs/generated/*` 一併 commit。 2. **改說明/陷阱**:只改本檔,勿手改 `docs/generated/`。 3. **給營運/開會用**:跑 `python scripts/export_m18_mapping_office.py`,打開 `docs/exports/*.docx` / `*.xlsx`。 4. **新發現的 M18 值**(如新的 `udfProducttype`):記入 generated 腳本的 `KNOWN_UNMAPPED_M18_VALUES`,或補正式 mapping 後重生。 5. PR 若動到 `NewItemRequest.kt` / `M18MasterDataService` product type 分支,review 應檢查 generated docs 是否已更新。 --- ## 11. 相關程式索引 | 主題 | 路徑 | |------|------| | Item / M18 type enums | `modules/master/web/models/NewItemRequest.kt` | | Product sync | `m18/service/M18MasterDataService.kt` | | StSearch | `m18/model/M18MasterDataRequest.kt` | | Shop type | `modules/master/enums/ShopType.kt` | | GRN skip | `m18/M18GrnRules.kt` | | PO sync | `m18/service/M18PurchaseOrderService.kt` | | DO sync | `m18/service/M18DeliveryOrderService.kt` | | BOM→M18 | `m18/service/M18BomForShopService.kt` | | 存貨 Type 顯示 | `InventoryTable.tsx` + `i18n/zh/inventory.json` | | 物品 Type 下拉 | `CreateItem/ProductDetails.tsx` |