Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

20260819_po-m18id-remap.md 4.2 KiB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. # Deploy note — PO line m18Id rematch (recode)
  2. Date: 2026-08-19
  3. Branch / build: uncommitted (QA before prod)
  4. Author: agent + QA
  5. ## Summary
  6. - PO/DO sync failed when M18 recoded a product (`proId` changed, item **code** unchanged), e.g. `PFP002PO26080303` lines `20022` / `20023` / `20024`.
  7. - Sync now **links** the new M18 id onto the existing local item (same **code + type**) and **does not** rebuild/delete `item_uom`.
  8. ## Scope
  9. - Backend: `ItemsService.saveItem`, `M18MasterDataService.saveProduct` / `saveProducts`, remap helper
  10. - Frontend: none
  11. - DB / Liquibase: none
  12. - Config / ops: none (use existing `GET /m18/test/po-by-code`)
  13. ## Commits
  14. - (not committed yet)
  15. ## Safety rules (what this deploy will / will not do)
  16. | Situation | Behaviour |
  17. |-----------|-----------|
  18. | Local item already has that `m18Id` | Unchanged: normal product/PO update |
  19. | Same **code + type**, new unused `m18Id` | Update `items.m18Id` only. **No** UOM delete/rebuild, **no** QC/name wipe |
  20. | New `m18Id` already on **another** item | Refuse (keep old mapping) |
  21. | Same code, **different** type | Will **not** auto-link (same as before for type mismatch) |
  22. | Brand-new M18 product, no local code | Creates item + UOMs as before |
  23. | Scheduled product sync of already-mapped items | Unchanged full product/UOM sync |
  24. | Local PO status not `PENDING` | PO resync is **skipped** (existing rule) |
  25. ## Pre-check SQL (prod or staging, before resync)
  26. ```sql
  27. -- 1) Failed PO lines for this PO
  28. SELECT d.id, d.m18Id AS m18_line_id, d.status, d.dataLog, d.createDate
  29. FROM m18_data_log d
  30. WHERE d.refType = 'Purchase Order Line'
  31. AND d.status = 'FAIL'
  32. AND d.dataLog LIKE '%PFP002PO26080303%'
  33. ORDER BY d.id DESC
  34. LIMIT 20;
  35. -- 2) Local PO must be PENDING
  36. SELECT id, code, status, m18Id
  37. FROM purchase_order
  38. WHERE code = 'PFP002PO26080303' AND deleted = 0;
  39. -- 3) After you know the 3 M18 product codes, confirm one local row each
  40. SELECT id, code, name, type, m18Id
  41. FROM items
  42. WHERE deleted = 0 AND code IN ('CODE1', 'CODE2', 'CODE3');
  43. ```
  44. Confirm each of the three codes has **exactly one** local row, and its current `m18Id` is **not** already `20022`/`20023`/`20024` on a *different* item:
  45. ```sql
  46. SELECT id, code, m18Id FROM items
  47. WHERE deleted = 0 AND m18Id IN (20022, 20023, 20024);
  48. ```
  49. Expected before fix: **no rows** (or only unrelated items — if any, **do not** auto-resync; fix mapping manually).
  50. ## Test plan
  51. | # | Steps (who / where / data) | Expected result |
  52. |---|----|-----|
  53. | 1 | **Staging first.** Snapshot `items.m18Id` + `item_uom` counts for the 3 item codes. | Baseline recorded |
  54. | 2 | Confirm M18 products `20022`/`20023`/`20024` still have the **same codes** as local items. | Codes match; types still map to the same FPSMS `type` |
  55. | 3 | Confirm local PO `PFP002PO26080303` status is **PENDING**. | If not pending, stop — resync will skip the whole PO |
  56. | 4 | Call `GET /m18/test/po-by-code?code=PFP002PO26080303` (auth as ops). | HTTP 200; `totalFail` for those 3 lines is 0 (or success list includes the PO) |
  57. | 5 | SQL: `items.m18Id` for the 3 codes is now 20022/20023/20024. `item_uom` **row count and ids unchanged**. QC category / shelf life unchanged. | Remap-only; no UOM wipe |
  58. | 6 | UI: PO workbench / PO detail for `PFP002PO26080303` shows **6 lines** (previously 3 missing). | Failed lines created |
  59. | 7 | **Regression:** pick a normal mapped item, run scheduled or `GET /m18/product/{existingM18Id}`. | Item still updates as before; UOMs still sync |
  60. | 8 | Confirm no new `PO_LINE FAIL` email for this PO after resync. | Alert not re-sent for these 3 proIds |
  61. ## Out of scope / not tested
  62. - Recoded products whose **item code also changed** (will not auto-link)
  63. - Non-`PENDING` PO overwrite (by design skipped)
  64. - DO with the same recode (same `resolveLocalItemId` path; spot-check only if a DO uses these 3 items)
  65. - Live M18 UOM id change on the recoded product (PO qty conversion still uses existing purchase UOM)
  66. ## Rollback
  67. - Revert backend deploy (no Liquibase, no frontend).
  68. - If only `items.m18Id` was updated, restore previous `m18Id` from the pre-check snapshot. PO lines already inserted stay; delete/fix only if QA rejects the PO.
  69. - Do **not** run a full product resync on the new proIds expecting to undo UOMs — this path does not rewrite UOMs.