GBS Sales Order & Purchase Order — Flow & Definitions
1. Tổng quan luồng làm việc
GBS SO/PO là hệ thống yêu cầu đơn hàng nội bộ. Form được tạo trên eCentric, qua duyệt Finance, sau đó tự động đồng bộ sang GBS (ERPNext bên Boxme) để xử lý kế toán/xuất hóa đơn.
Các bên tham gia
- User — người tạo SO/PO (Submitter)
- Finance — duyệt L1 trên eCentric (vai trò: Finance Approver)
- System — sync engine tự động giữa 2 nền tảng
- GBS Team — Revenue Verifier + Revenue Manager bên Boxme
Sơ đồ tổng thể
flowchart LR
Start([Bắt đầu]):::startNode --> Create[User tạo SO/PO trên form]
Create --> FinReview{Finance review}
FinReview -->|Phê duyệt| Sync[Sync sang GBS]
FinReview -->|Send back| CanSua[Trạng thái Cần sửa]
CanSua --> EditForm[User chỉnh sửa form]
EditForm --> Resubmit[Submit lại]
Resubmit --> FinReview
Sync --> GBSReview[GBS Verifier/Manager review]
GBSReview -->|Approve| Done([Approved - To Bill]):::endNode
GBSReview -->|Reject| GBSReject[GBS Rejected]
GBSReject --> Resubmit
classDef startNode fill:#d1fae5,stroke:#10b981
classDef endNode fill:#fce7f3,stroke:#ec4899
Sự khác biệt giữa SO và PO
| Khía cạnh | Sales Order (SO) | Purchase Order (PO) |
|---|---|---|
| Mục đích | Đơn hàng bán (revenue) | Đơn hàng mua (cost) |
| Boxme workflow | GBS Services Sales Order Approval (chain Verifier → Manager) | PO Approval Workflow (1 step Submit → Pending Verifier) |
| Có Parent SO? | Không | Có thể (PO tạo từ SO sẽ link) |
| Auto-advance sau sync | Có (v12) — Services tự lên Pending Revenue Manager | Chưa có (cần click Submit on GBS thủ công) |
2. Happy path — flow chi tiết từng bước
Bước 1: User tạo form
Vào menu SO Request hoặc PO Request (sidebar). Điền form gồm các trường bắt buộc: title, customer/supplier, brand, project, dates, items (item_code, qty, rate), taxes template, store, attachments.
- Trạng thái local:
Pending - Submitter tự động lấy từ session email (
frappe.session.user) — kể cả nếu form gửi rỗng (defensive fallback v7). - Attachments upload trực tiếp lên SharePoint qua Upload Session, không qua server proxy.
Bước 2: Finance duyệt
Finance vào All Tickets → tab GBS SO/PO → mở doc → click Approve (hoặc Send back/Reject).
- Approve → status local =
Approved→ triggers sync hook (After Save). - Send back → status =
Cần sửa→ user thấy banner đỏ + button "Sửa & Submit lại". - Reject → status =
Rejected→ kết thúc, không tiếp tục.
Bước 3: Sync sang GBS (tự động)
Sync code sync_gbs_so_outgoing (v13) hoặc sync_gbs_po_outgoing chạy ngay sau Save khi status = Approved.
- POST mới: gửi toàn bộ payload (title, customer, items, taxes, project, custom_store, etc.) lên boxme. Tạo doc với workflow_state = Draft.
- Sau POST thành công cho Services SO: auto fire
apply_workflow "Submit for Approval"→ boxme đi Pending Revenue Manager. (v12) - Attachments: tách rời upload SharePoint anonymous link + POST File record sang boxme.
Bước 4: GBS Team review
Verifier (trucdt@boxme.asia...) review → Manager (thuynt2@boxme.asia...) approve.
- Boxme state chuyển: Pending Revenue Verifier → Pending Revenue Manager → Approved.
- Sau Approved: docstatus = 1, status = "To Bill", invoice-ready.
Bước 5: Polling đồng bộ trạng thái về
poll_gbs_status chạy mỗi 15 phút (cron) cập nhật gbs_status trên local. User cũng có thể click "Check Status" button thủ công.
State diagram chi tiết
stateDiagram-v2
[*] --> Pending : User submit form
Pending --> Approved : Finance approve
Pending --> CanSua : Finance send back
CanSua --> Pending : User edit + resubmit
Approved --> GBSDraft : Sync POST
GBSDraft --> GBSPendingManager : Auto Submit for Approval (Services)
GBSPendingManager --> GBSApproved : Manager approve
GBSPendingManager --> GBSRejected : Manager reject
GBSRejected --> Approved : User resubmit cycle
GBSApproved --> [*] : Invoice ready
state CanSua {
[*] --> ClickResubmit
ClickResubmit --> FormEdit
FormEdit --> SubmitAgain
SubmitAgain --> [*]
}
3. Error paths & Edge cases
3.1. GBS reject — Resubmit cycle
Khi GBS Verifier/Manager reject, boxme state = Rejected, poll cập nhật local gbs_status = "Rejected".
- Detail page hiện banner đỏ + button Resubmit (chỉ submitter mới thấy).
- Click Resubmit →
resubmit_gbs_docset status = "Cần sửa" + redirect đến form edit mode. - User chỉnh sửa fields/items/attachments → submit lại →
resubmit_gbs_so/posave toàn bộ field thay đổi + reset status = Pending. - Finance approve lại → sync v13 detect
resubmit_count > pushed_count→ apply Resubmit transition trên boxme (Rejected → Draft) → settle loop ~1s (defends race condition) → PUT updated fields → auto Submit for Approval lại (Services).
sequenceDiagram
autonumber
actor User
actor Finance
participant eCentric
participant Sync as Sync v13
participant Boxme
Boxme->>eCentric: Rejected (qua poll)
User->>eCentric: Click Resubmit
eCentric->>User: Redirect form edit
User->>eCentric: Edit + Submit lại
eCentric->>Finance: Status Pending
Finance->>eCentric: Approve
eCentric->>Sync: Trigger
Sync->>Boxme: apply_workflow Resubmit
Boxme-->>Sync: Rejected → Draft
Note over Sync: Settle loop 1s (race defense)
Sync->>Boxme: PUT updated fields
Boxme-->>Sync: 200 OK
Sync->>Boxme: apply Submit for Approval
Boxme-->>Sync: Draft → Pending Manager
3.2. Race condition giữa apply_workflow và PUT (v13 fix)
Boxme có cache lag giữa workflow commit và state validate. Khi sync apply Resubmit (Rejected → Draft) thành công rồi PUT ngay → có thể 417 vì state cache chưa refresh.
3.3. Doc đã finalized — không PUT nữa (v13 fix)
Sau khi boxme team Approve (docstatus = 1, state = Approved/Cancelled), doc bị locked không sửa được. Nếu local resubmit_count > pushed_count mismatch nào đó còn sót → sync sẽ retry PUT → 417 vô tận.
boxme.docstatus. Nếu = 1 → skip PUT + bump tracker + clear sync_error → no more retry loop.
3.4. Consumer Goods skip-chain prevention (v4/v5 guard)
Boxme workflow design: chỉ "Submit for Approval" transitions yêu cầu order_type.endswith('Services'). Với Consumer Goods orders, workflow chỉ có "Submit" → Approved (skip-chain).
3.5. Rate input parseFloat vi-VN (form fix v2)
Khi user nhập rate dạng 12.962.962,962 (vi-VN với dấu phẩy thập phân), native form handler strip cả dấu phẩy trước khi parseFloat → biến 12,96 triệu thành 12 tỷ.
ec-gbs-rate-input-fix v2 với smart detection: phát hiện dấu phẩy (decimal vi-VN), preserve precision. Override native focusin/focusout handlers via capture phase + stopImmediatePropagation.
3.6. Submitter empty fallback (v7)
Nếu form quên gửi submittedBy field (auto-fill JS lỗi), submit endpoint dùng frappe.session.user fallback. Đảm bảo submitter luôn có giá trị → Resubmit button hiển thị đúng cho người tạo doc.
3.7. PUT lên Pending Verifier/Manager state (chưa fix)
Trường hợp: doc đã Pending Verifier/Manager trên boxme, user resubmit local → sync cố PUT update fields → 417 vì allow_edit perm chỉ cho Verifier/Manager. Sales User (commercial@ecentric.vn) không edit được.
4. Định nghĩa từng trường
Định nghĩa tự động tải từ DocType EC Field Description (single source of truth). Khi anh cập nhật từ điển, trang này tự load lại.