Bunchee
Back to Blog

วิธี Sync Workspace ใน Frappe ด้วย Delete+Reinsert Pattern

เรียนรู้วิธีแก้ปัญหา Frappe Workspace ไม่ Update เมื่อรัน bench migrate ด้วย Delete+Reinsert Pattern พร้อมตัวอย่าง Workspace Manager

วิธี Sync Workspace ใน Frappe ด้วย Delete+Reinsert Pattern

หนึ่งในปัญหาที่นักพัฒนา Frappe/ERPNext พบบ่อยคือ Workspace ไม่ Update เมื่อรัน bench migrate บทความนี้จะอธิบายปัญหาและวิธีแก้ไข

ปัญหา

เมื่อเราแก้ไขไฟล์ JSON ของ Workspace และรัน bench migrate:

  • Workspace ใหม่ถูกสร้าง ✓
  • Workspace ที่มีอยู่แล้ว ไม่ถูก Update

เหตุผลคือ Frappe ถือว่า Workspace เป็น User-customizable Data ไม่ใช่ Configuration ดังนั้น:

  • bench migrate ไม่ Overwrite Workspace Records ที่มีอยู่
  • bench update ไม่ Apply JSON Changes
  • frappe.reload_doc() ไม่ Work สำหรับ Workspace

วิธีแก้ไข

วิธีที่ 1: Manual ผ่าน Desk UI

  1. ไปที่ Workspace List
  2. ลบ Workspace ที่ต้องการ Update
  3. รัน bench migrate
  4. Workspace จะถูกสร้างใหม่จาก JSON

วิธีที่ 2: Programmatic ด้วย workspace_manager.py

สร้างไฟล์ your_app/setup/workspace_manager.py:

import frappe

def sync_workspaces():
    """ลบและสร้าง Workspace ใหม่เพื่อ Apply JSON Changes"""
    workspaces_to_sync = [
        "Your Workspace 1",
        "Your Workspace 2",
    ]

    for ws_name in workspaces_to_sync:
        if frappe.db.exists("Workspace", ws_name):
            frappe.delete_doc("Workspace", ws_name, force=True)
            frappe.db.commit()
            print(f"Deleted workspace: {ws_name}")

    # Workspace จะถูกสร้างใหม่เมื่อรัน migrate
    print("Run 'bench migrate' to recreate workspaces")

การใช้งาน

# รัน Sync
bench --site your-site.local execute your_app.setup.workspace_manager.sync_workspaces

# จากนั้น Migrate เพื่อสร้างใหม่
bench --site your-site.local migrate

วิธีที่ 3: Hook เข้า after_migrate

ใน hooks.py:

after_migrate = [
    "your_app.setup.workspace_manager.sync_workspaces"
]

ข้อควรระวัง: วิธีนี้จะ Sync ทุกครั้งที่ Migrate อาจไม่เหมาะสำหรับทุกกรณี

Delete + Reinsert Strategy แบบเต็ม

สำหรับกรณีที่ต้องการควบคุมละเอียด:

import frappe
import json

def sync_workspace(workspace_name: str):
    """Delete และ Reinsert Workspace พร้อม Child Tables"""

    # 1. ลบ Workspace และ Child Tables ที่เกี่ยวข้อง
    if frappe.db.exists("Workspace", workspace_name):
        frappe.db.delete("Workspace", {"name": workspace_name})
        frappe.db.delete("Workspace Link", {"parent": workspace_name})
        frappe.db.delete("Workspace Shortcut", {"parent": workspace_name})
        frappe.db.delete("Workspace Chart", {"parent": workspace_name})
        frappe.db.delete("Workspace Number Card", {"parent": workspace_name})
        frappe.db.commit()
        print(f"Deleted: {workspace_name}")

    # 2. โหลด JSON File
    workspace_json_path = frappe.get_app_path(
        "your_app",
        "your_module",
        "workspace",
        workspace_name.lower().replace(" ", "_"),
        f"{workspace_name.lower().replace(' ', '_')}.json"
    )

    with open(workspace_json_path, 'r', encoding='utf-8') as f:
        workspace_data = json.load(f)

    # 3. Insert ใหม่
    doc = frappe.get_doc(workspace_data)
    doc.flags.ignore_permissions = True
    doc.flags.ignore_links = True
    doc.insert(ignore_permissions=True)

    # 4. Commit และ Clear Cache
    frappe.db.commit()
    frappe.cache().flushall()
    print(f"Recreated: {workspace_name}")


def sync_all_workspaces():
    """Sync ทุก Workspaces ของ App"""
    workspaces = [
        "Dashboard",
        "Settings",
        "Reports",
    ]

    for ws in workspaces:
        sync_workspace(ws)

ข้อควรระวัง

  1. Backup ก่อน Delete - User Customizations จะหายไป
  2. ระบุเฉพาะ Workspaces ของ App - อย่าลบ Workspaces ของ Frappe/ERPNext Core
  3. Clear Cache - ต้อง Clear Redis Cache หลัง Sync

โครงสร้าง Workspace JSON

{
  "doctype": "Workspace",
  "name": "Your Workspace",
  "label": "Your Workspace",
  "module": "Your Module",
  "icon": "organization",
  "public": 1,
  "content": "[...]",
  "links": [...],
  "shortcuts": [...],
  "charts": [...],
  "number_cards": [...]
}

สรุป

Frappe Workspace ไม่ Update อัตโนมัติเมื่อ Migrate เพราะถูกออกแบบให้ User สามารถ Customize ได้ วิธีแก้คือใช้ Delete + Reinsert Pattern:

  1. ลบ Workspace ที่มีอยู่
  2. รัน bench migrate เพื่อสร้างใหม่จาก JSON
  3. Clear Cache

หรือใช้ Workspace Manager Script เพื่อ Automate Process นี้

เอกสารอ้างอิง