File manager - Edit - /var/www/sme-os.tech.cm.in.th/generate_dfd_diagrams.py
Back
import matplotlib.pyplot as plt import matplotlib.patches as patches import matplotlib.font_manager as fm import numpy as np import os # Font setup for Thai rendering font_path = "C:/Windows/Fonts/THSarabunNew.ttf" font_bold_path = "C:/Windows/Fonts/THSarabunNew Bold.ttf" if not os.path.exists(font_path): font_path = "C:/Windows/Fonts/tahoma.ttf" font_bold_path = "C:/Windows/Fonts/tahomabd.ttf" prop_title = fm.FontProperties(fname=font_bold_path, size=22) prop_subtitle = fm.FontProperties(fname=font_bold_path, size=16) prop_entity = fm.FontProperties(fname=font_bold_path, size=14) prop_proc_id = fm.FontProperties(fname=font_bold_path, size=14) prop_proc_text = fm.FontProperties(fname=font_path, size=13) prop_store_id = fm.FontProperties(fname=font_bold_path, size=13) prop_store_text = fm.FontProperties(fname=font_path, size=12.5) prop_label = fm.FontProperties(fname=font_path, size=11.5) # ========================================== # GANE & SARSON SHAPES # ========================================== def draw_entity_gs(ax, cx, cy, w=22, h=10, title="Entity", subtitle="", bg="#F8FAFC", border="#1E293B"): x = cx - w/2 y = cy - h/2 rect = patches.Rectangle((x, y), w, h, linewidth=2.2, edgecolor=border, facecolor=bg, zorder=5) ax.add_patch(rect) shadow = patches.Rectangle((x + 0.6, y - 0.6), w, h, facecolor="#CBD5E1", edgecolor="none", zorder=3) ax.add_patch(shadow) if subtitle: ax.text(cx, cy + 1.4, title, ha='center', va='center', fontproperties=prop_entity, color="#0F172A", zorder=6) ax.text(cx, cy - 2.0, subtitle, ha='center', va='center', fontproperties=prop_proc_text, color="#475569", zorder=6) else: ax.text(cx, cy, title, ha='center', va='center', fontproperties=prop_entity, color="#0F172A", zorder=6) def draw_process_gs(ax, cx, cy, w=24, h=12.5, pid="0", pname="Process Name", bg="#EFF6FF", border="#1D4ED8"): x = cx - w/2 y = cy - h/2 top_band_h = h * 0.32 r_box = patches.FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.2,rounding_size=2.0", linewidth=2.2, edgecolor=border, facecolor=bg, zorder=5) ax.add_patch(r_box) ax.plot([x + 0.2, x + w - 0.2], [y + h - top_band_h, y + h - top_band_h], color=border, linewidth=1.6, zorder=6) ax.text(cx, y + h - top_band_h/2, f"No. {pid}", ha='center', va='center', fontproperties=prop_proc_id, color=border, zorder=7) body_cy = y + (h - top_band_h) / 2 lines = pname.split('\n') if len(lines) == 1: ax.text(cx, body_cy, lines[0], ha='center', va='center', fontproperties=prop_proc_text, color="#0F172A", zorder=7) elif len(lines) == 2: ax.text(cx, body_cy + 1.3, lines[0], ha='center', va='center', fontproperties=prop_proc_text, color="#0F172A", zorder=7) ax.text(cx, body_cy - 1.6, lines[1], ha='center', va='center', fontproperties=prop_proc_text, color="#334155", zorder=7) else: ax.text(cx, body_cy, pname, ha='center', va='center', fontproperties=prop_proc_text, color="#0F172A", zorder=7) def draw_datastore_gs(ax, cx, cy, w=24, h=6.8, sid="D1", sname="Data Store", bg="#FFFFFF", border="#334155"): x = cx - w/2 y = cy - h/2 id_w = 6.0 rect = patches.Rectangle((x, y), w, h, facecolor=bg, edgecolor='none', zorder=4) ax.add_patch(rect) ax.plot([x, x + id_w], [y + h, y + h], color=border, linewidth=2.2, zorder=5) ax.plot([x, x + id_w], [y, y], color=border, linewidth=2.2, zorder=5) ax.plot([x, x], [y, y + h], color=border, linewidth=2.2, zorder=5) ax.plot([x + id_w, x + id_w], [y, y + h], color=border, linewidth=2.0, zorder=5) ax.plot([x + id_w, x + w], [y + h, y + h], color=border, linewidth=2.2, zorder=5) ax.plot([x + id_w, x + w], [y, y], color=border, linewidth=2.2, zorder=5) ax.text(x + id_w/2, cy, sid, ha='center', va='center', fontproperties=prop_store_id, color=border, zorder=6) ax.text(x + id_w + (w - id_w)/2, cy, sname, ha='center', va='center', fontproperties=prop_store_text, color="#0F172A", zorder=6) # ========================================== # CLEAR FLOW ARROW (NO OVERLAP / OFFSET LABELS) # ========================================== def draw_flow_clear(ax, x1, y1, x2, y2, label="", label_offset=(0, 3.5), rad=0.0, color="#1E293B", lw=1.8): """ วาดลูกศร Data Flow ชัดเจน 100% โดยป้ายข้อความจะอยู่คู่ขนานด้านข้าง (Offset) ไม่ทับเส้น ไม่บังลูกศร และไม่บังหัวลูกศร """ conn = f"arc3,rad={rad}" if rad != 0 else "arc3,rad=0" # 1. วาดเส้นลูกศรคมชัดที่ zorder สูง ax.annotate("", xy=(x2, y2), xytext=(x1, y1), arrowprops=dict(arrowstyle="-|>", color=color, lw=lw, mutation_scale=15, connectionstyle=conn), zorder=10) # 2. คำนวณตำแหน่งป้ายข้อความที่ไม่ทับเส้น if label: # จุดกึ่งกลาง mx = (x1 + x2) / 2.0 my = (y1 + y2) / 2.0 # ถ้ามี rad (เส้นโค้ง) ให้ขยับจุดกึ่งกลางตามส่วนโค้ง if rad != 0: dx = x2 - x1 dy = y2 - y1 norm = np.sqrt(dx*dx + dy*dy) + 1e-6 # เวกเตอร์ตั้งฉาก px = -dy / norm py = dx / norm mx += px * rad * norm * 0.5 my += py * rad * norm * 0.5 # บวก offset ผู้ใช้กำหนด lx = mx + label_offset[0] ly = my + label_offset[1] # ข้อความลอยอยู่เหนือหรือข้างเส้น พร้อมกรอบสีขาวขอบบาง ax.text(lx, ly, label, ha='center', va='center', fontproperties=prop_label, color="#0F172A", bbox=dict(boxstyle="round,pad=0.25", facecolor="#FFFFFF", edgecolor="#94A3B8", alpha=0.98, lw=0.9), zorder=15) # ========================================== # 1. DFD LEVEL 0 (Context Diagram - Process 0) # ========================================== def generate_dfd_level_0(): fig, ax = plt.subplots(figsize=(14, 9.5), dpi=300) ax.set_xlim(0, 130) ax.set_ylim(0, 100) ax.set_aspect('equal') ax.axis('off') ax.text(65, 96, "แผนภาพกระแสข้อมูลระดับที่ 0 (DFD Level 0 / Context Diagram)", ha='center', va='center', fontproperties=prop_title, color="#0F172A") ax.text(65, 91.5, "ระบบบริหารจัดการร้านอาหารและสั่งอาหารออนไลน์ (SME Restaurant OS)", ha='center', va='center', fontproperties=prop_subtitle, color="#2563EB") draw_process_gs(ax, 65, 50, w=34, h=18, pid="0", pname="ระบบบริหารจัดการร้านอาหาร\n(SME Restaurant OS)", bg="#EFF6FF", border="#2563EB") draw_entity_gs(ax, 16, 76, w=22, h=11, title="ลูกค้า", subtitle="(Customer)", bg="#ECFDF5", border="#059669") draw_entity_gs(ax, 16, 24, w=22, h=11, title="พนักงานครัว / บาร์", subtitle="(Kitchen / Chef)", bg="#FFFBEB", border="#D97706") draw_entity_gs(ax, 114, 76, w=22, h=11, title="ผู้ดูแลร้านค้า / แคชเชียร์", subtitle="(Store Admin)", bg="#F5F3FF", border="#7C3AED") draw_entity_gs(ax, 114, 24, w=22, h=11, title="ผู้ดูแลระบบส่วนกลาง", subtitle="(Super Admin)", bg="#FDF2F8", border="#DB2777") # Customer <-> Process 0 (แยก 2 เส้นไม่ทับกัน ชัดเจน) draw_flow_clear(ax, 27, 80, 48, 59, label="1. คำสั่งซื้อ / ข้อมูลชำระเงิน", label_offset=(-2, 4.5), rad=0.08, color="#059669") draw_flow_clear(ax, 48, 52, 27, 72, label="2. เมนู / เวลารอจริง / ใบเสร็จ", label_offset=(-2, -4.5), rad=-0.08, color="#0284C7") # Kitchen <-> Process 0 draw_flow_clear(ax, 48, 46, 27, 28, label="1. รายการคิวออเดอร์ (KDS)", label_offset=(-3, 4.5), rad=0.08, color="#0284C7") draw_flow_clear(ax, 27, 20, 48, 40, label="2. อัปเดตสถานะปรุงเสร็จ", label_offset=(-2, -4.5), rad=-0.08, color="#D97706") # Store Admin <-> Process 0 draw_flow_clear(ax, 103, 80, 82, 59, label="1. จัดการเมนู / โต๊ะ / เคลียร์ยอด", label_offset=(3, 4.5), rad=-0.08, color="#7C3AED") draw_flow_clear(ax, 82, 52, 103, 72, label="2. รายงานยอดขาย / แจ้งเตือน", label_offset=(2, -4.5), rad=0.08, color="#0284C7") # Super Admin <-> Process 0 draw_flow_clear(ax, 103, 28, 82, 46, label="1. จัดการสิทธิ์ / อนุมัติแพ็กเกจ", label_offset=(3, -4.5), rad=-0.08, color="#DB2777") draw_flow_clear(ax, 82, 40, 103, 20, label="2. ภาพรวมร้านค้าและระบบ", label_offset=(2, 4.5), rad=0.08, color="#0284C7") plt.tight_layout() plt.savefig("dfd_level_0.png", dpi=300, bbox_inches='tight') plt.close() # ========================================== # 2. DFD LEVEL 1 (7 Main Processes Overview) # ========================================== def generate_dfd_level_1_overview(): fig, ax = plt.subplots(figsize=(17, 13), dpi=300) ax.set_xlim(0, 170) ax.set_ylim(0, 125) ax.set_aspect('equal') ax.axis('off') ax.text(85, 120, "แผนภาพกระแสข้อมูลระดับที่ 1 (DFD Level 1)", ha='center', va='center', fontproperties=prop_title, color="#0F172A") ax.text(85, 115.5, "แสดง 7 กระบวนการหลักและแหล่งจัดเก็บข้อมูล D1 - D6 (SME Restaurant OS)", ha='center', va='center', fontproperties=prop_subtitle, color="#2563EB") # Entities draw_entity_gs(ax, 16, 92, w=20, h=10, title="ลูกค้า", subtitle="(Customer)", bg="#ECFDF5", border="#059669") draw_entity_gs(ax, 16, 32, w=20, h=10, title="พนักงานครัว", subtitle="(Chef / KDS)", bg="#FFFBEB", border="#D97706") draw_entity_gs(ax, 154, 90, w=20, h=10, title="ผู้ดูแลร้านค้า", subtitle="(Store Admin)", bg="#F5F3FF", border="#7C3AED") draw_entity_gs(ax, 154, 30, w=20, h=10, title="ผู้ดูแลส่วนกลาง", subtitle="(Super Admin)", bg="#FDF2F8", border="#DB2777") # Left Column Processes (Customer & Kitchen) draw_process_gs(ax, 52, 98, w=23, h=11.5, pid="4.0", pname="รับคำสั่งซื้อ\n(Order Processing)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax, 52, 70, w=23, h=11.5, pid="5.0", pname="จัดการคิวห้องครัว\n(KDS Queue)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax, 52, 42, w=23, h=11.5, pid="6.0", pname="คำนวณเวลารออาหาร\n(Lead Time Engine)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax, 52, 14, w=23, h=11.5, pid="7.0", pname="ชำระเงิน/ออกใบเสร็จ\n(Payment & Bill)", bg="#EFF6FF", border="#2563EB") # Right Column Processes (Admin & Master) draw_process_gs(ax, 118, 98, w=23, h=11.5, pid="1.0", pname="ยืนยันตัวตน/สิทธิ์\n(Authentication)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax, 118, 70, w=23, h=11.5, pid="2.0", pname="จัดการโต๊ะ/QR Code\n(Tables & QR Token)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax, 118, 42, w=23, h=11.5, pid="3.0", pname="จัดการเมนูอาหาร/สต็อก\n(Menu Management)", bg="#EFF6FF", border="#2563EB") # Center Data Stores D1 - D6 draw_datastore_gs(ax, 85, 105, w=23, h=6.5, sid="D1", sname="users / tenants", bg="#FFFFFF", border="#334155") draw_datastore_gs(ax, 85, 87, w=23, h=6.5, sid="D2", sname="tables_qr", bg="#FFFFFF", border="#334155") draw_datastore_gs(ax, 85, 69, w=23, h=6.5, sid="D3", sname="menus / categories", bg="#FFFFFF", border="#334155") draw_datastore_gs(ax, 85, 51, w=23, h=6.5, sid="D4", sname="orders / items", bg="#FFFFFF", border="#334155") draw_datastore_gs(ax, 85, 33, w=23, h=6.5, sid="D5", sname="kitchen_queues", bg="#FFFFFF", border="#334155") draw_datastore_gs(ax, 85, 14, w=23, h=6.5, sid="D6", sname="payments", bg="#FFFFFF", border="#334155") # Admin Flows (Clear side offsets) draw_flow_clear(ax, 144, 93, 130, 98, label="เข้าสู่ระบบ", label_offset=(0, 3.5)) draw_flow_clear(ax, 106, 101, 97, 105, label="ตรวจสิทธิ์ D1", label_offset=(0, 3.5)) draw_flow_clear(ax, 144, 87, 130, 74, label="จัดการผังโต๊ะ", label_offset=(2, 3.5)) draw_flow_clear(ax, 106, 74, 97, 85, label="บันทึก Token D2", label_offset=(-2, 3.5)) draw_flow_clear(ax, 146, 83, 130, 46, label="จัดการเมนู/ราคา", label_offset=(3, 3.5), rad=-0.08) draw_flow_clear(ax, 106, 46, 97, 67, label="บันทึกเมนู D3", label_offset=(-2, 3.5)) # Customer Flows draw_flow_clear(ax, 26, 95, 40, 98, label="สแกนสั่งอาหาร", label_offset=(0, 3.5)) draw_flow_clear(ax, 64, 101, 73, 90, label="ตรวจ Token D2", label_offset=(-2, 3.5)) draw_flow_clear(ax, 73, 71, 64, 95, label="ดึงเมนู D3", label_offset=(-2, -3.5)) draw_flow_clear(ax, 64, 93, 73, 55, label="บันทึกออเดอร์ D4", label_offset=(-2, -3.5)) draw_flow_clear(ax, 52, 92, 52, 76, label="ส่งเข้าคิวครัว", label_offset=(7, 0)) # Kitchen Flows draw_flow_clear(ax, 64, 68, 73, 36, label="สร้างคิว D5", label_offset=(2, 3.5)) draw_flow_clear(ax, 40, 70, 26, 37, label="แสดงจอ KDS", label_offset=(-3, 3.5)) draw_flow_clear(ax, 26, 30, 40, 66, label="อัปเดตปรุงเสร็จ", label_offset=(-3, -3.5)) # Lead Time Flows draw_flow_clear(ax, 73, 33, 64, 39, label="ดึงคิวรอ D5", label_offset=(0, 3.5)) draw_flow_clear(ax, 40, 42, 22, 87, label="ส่งเวลาคาดการณ์", label_offset=(-4, -3.5), rad=0.12) # Payment Flows draw_flow_clear(ax, 16, 87, 40, 16, label="แจ้งชำระ/ส่งสลิป", label_offset=(-5, -3.5), rad=0.18) draw_flow_clear(ax, 64, 14, 73, 14, label="บันทึกชำระ D6", label_offset=(0, 3.5)) draw_flow_clear(ax, 52, 20, 19, 87, label="แจ้งผล/ออกใบเสร็จ", label_offset=(-3, 3.5), rad=-0.15) plt.tight_layout() plt.savefig("dfd_level_1_overview.png", dpi=300, bbox_inches='tight') plt.close() # ========================================== # 3. DFD LEVEL 2 - PART 1 (Admin Sub-systems: 1.0, 2.0, 3.0) # ========================================== def generate_dfd_level_2_admin(): fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(23, 8.5), dpi=300) # 1.0 Auth Sub-system ax1.set_xlim(0, 100); ax1.set_ylim(0, 100); ax1.set_aspect('equal'); ax1.axis('off') ax1.text(50, 96, "DFD Level 2: กระบวนการ 1.0 ยืนยันตัวตน", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax1, 14, 50, w=18, h=10, title="ผู้ใช้/Admin", subtitle="(Users)", bg="#F5F3FF", border="#7C3AED") draw_process_gs(ax1, 50, 78, w=22, h=11, pid="1.1", pname="ตรวจสอบ Login\n(Validate Password)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax1, 50, 48, w=22, h=11, pid="1.2", pname="Super Admin Mode\n(Impersonation)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax1, 50, 18, w=22, h=11, pid="1.3", pname="ออก Session Token\n(Generate Session)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax1, 84, 78, w=20, h=6, sid="D1.1", sname="users") draw_datastore_gs(ax1, 84, 48, w=20, h=6, sid="D1.2", sname="tenants") draw_flow_clear(ax1, 23, 54, 38, 78, label="กรอก Username/PW", label_offset=(0, 3.5)) draw_flow_clear(ax1, 62, 78, 73, 78, label="เช็ค password", label_offset=(0, 3.5)) draw_flow_clear(ax1, 50, 72, 50, 54, label="สิทธิ์ถูกต้อง", label_offset=(6, 0)) draw_flow_clear(ax1, 62, 48, 73, 48, label="ดึงร้านผู้เช่า", label_offset=(0, 3.5)) draw_flow_clear(ax1, 50, 42, 50, 24, label="กำหนด Scope", label_offset=(6, 0)) draw_flow_clear(ax1, 38, 18, 23, 46, label="สร้าง Session ผ่าน", label_offset=(-3, -3.5)) # 2.0 Table Sub-system ax2.set_xlim(0, 100); ax2.set_ylim(0, 100); ax2.set_aspect('equal'); ax2.axis('off') ax2.text(50, 96, "DFD Level 2: กระบวนการ 2.0 จัดการโต๊ะอาหาร", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax2, 14, 50, w=18, h=10, title="ผู้ดูแลร้านค้า", subtitle="(Store Admin)", bg="#F5F3FF", border="#7C3AED") draw_process_gs(ax2, 50, 78, w=22, h=11, pid="2.1", pname="สร้างผังโต๊ะอาหาร\n(Add Tables)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax2, 50, 48, w=22, h=11, pid="2.2", pname="สร้าง Dynamic QR Token\n(Gen QR URL)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax2, 50, 18, w=22, h=11, pid="2.3", pname="สลับสถานะเปิด/ย้ายโต๊ะ\n(Occupied/Move)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax2, 84, 60, w=20, h=6, sid="D2", sname="tables_qr") draw_flow_clear(ax2, 23, 54, 38, 78, label="กำหนดเลขโต๊ะ", label_offset=(0, 3.5)) draw_flow_clear(ax2, 50, 72, 50, 54, label="โต๊ะที่เพิ่มใหม่", label_offset=(6, 0)) draw_flow_clear(ax2, 62, 48, 73, 58, label="บันทึก QR Token", label_offset=(0, 3.5)) draw_flow_clear(ax2, 23, 46, 38, 20, label="สั่งย้ายโต๊ะ", label_offset=(0, -3.5)) draw_flow_clear(ax2, 62, 20, 73, 58, label="อัปเดต status", label_offset=(0, -3.5)) # 3.0 Menu Sub-system ax3.set_xlim(0, 100); ax3.set_ylim(0, 100); ax3.set_aspect('equal'); ax3.axis('off') ax3.text(50, 96, "DFD Level 2: กระบวนการ 3.0 จัดการเมนูและสต็อก", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax3, 14, 50, w=18, h=10, title="ผู้ดูแลร้านค้า", subtitle="(Store Admin)", bg="#F5F3FF", border="#7C3AED") draw_process_gs(ax3, 50, 78, w=22, h=11, pid="3.1", pname="จัดการหมวดหมู่อาหาร\n(Categories)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax3, 50, 48, w=22, h=11, pid="3.2", pname="เพิ่ม/แก้ไขรายการเมนู\n(Menu CRUD)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax3, 50, 18, w=22, h=11, pid="3.3", pname="เปิด-ปิดสต็อกหมดด่วน\n(Toggle Stock)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax3, 84, 78, w=20, h=6, sid="D3.1", sname="categories") draw_datastore_gs(ax3, 84, 35, w=20, h=6, sid="D3.2", sname="menus") draw_flow_clear(ax3, 23, 54, 38, 78, label="สร้างหมวดหมู่", label_offset=(0, 3.5)) draw_flow_clear(ax3, 62, 78, 73, 78, label="บันทึกลง D3.1", label_offset=(0, 3.5)) draw_flow_clear(ax3, 23, 50, 38, 48, label="บันทึกราคา/รูป", label_offset=(0, 3.5)) draw_flow_clear(ax3, 62, 48, 73, 38, label="บันทึกลง D3.2", label_offset=(0, 3.5)) draw_flow_clear(ax3, 23, 46, 38, 20, label="กดหมดด่วน", label_offset=(0, -3.5)) draw_flow_clear(ax3, 62, 20, 73, 34, label="อัปเดต is_available", label_offset=(0, -3.5)) plt.tight_layout() plt.savefig("dfd_level_2_admin.png", dpi=300, bbox_inches='tight') plt.close() # ========================================== # 4. DFD LEVEL 2 - PART 2 (Customer & Kitchen Sub-systems: 4.0, 5.0, 6.0, 7.0) # ========================================== def generate_dfd_level_2_customer(): fig, ((ax4, ax5), (ax6, ax7)) = plt.subplots(2, 2, figsize=(19, 15), dpi=300) # 4.0 Order Sub-system ax4.set_xlim(0, 100); ax4.set_ylim(0, 100); ax4.set_aspect('equal'); ax4.axis('off') ax4.text(50, 96, "DFD Level 2: กระบวนการ 4.0 รับคำสั่งซื้อ (Order Processing)", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax4, 14, 52, w=18, h=10, title="ลูกค้า", subtitle="(Customer)", bg="#ECFDF5", border="#059669") draw_process_gs(ax4, 48, 78, w=22, h=11, pid="4.1", pname="สแกน/ตรวจ QR Token\n(Validate Token)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax4, 48, 48, w=22, h=11, pid="4.2", pname="เลือกอาหาร/ระบุออปชัน\n(Select Menu Items)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax4, 48, 18, w=22, h=11, pid="4.3", pname="ยืนยันบันทึกออเดอร์\n(Confirm Order)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax4, 84, 78, w=20, h=6, sid="D2", sname="tables_qr") draw_datastore_gs(ax4, 84, 48, w=20, h=6, sid="D3", sname="menus") draw_datastore_gs(ax4, 84, 24, w=20, h=6, sid="D4", sname="orders") draw_datastore_gs(ax4, 84, 10, w=20, h=6, sid="D5", sname="kitchen_queues") draw_flow_clear(ax4, 23, 56, 36, 76, label="สแกน QR โต๊ะ", label_offset=(0, 3.5)) draw_flow_clear(ax4, 60, 78, 73, 78, label="ตรวจสถานะโต๊ะ", label_offset=(0, 3.5)) draw_flow_clear(ax4, 48, 72, 48, 54, label="โต๊ะถูกต้อง", label_offset=(6, 0)) draw_flow_clear(ax4, 73, 48, 60, 48, label="ดึงรายการเมนู", label_offset=(0, 3.5)) draw_flow_clear(ax4, 23, 50, 36, 48, label="เลือกอาหาร/จำนวน", label_offset=(0, 3.5)) draw_flow_clear(ax4, 48, 42, 48, 24, label="ส่งตะกร้า", label_offset=(5, 0)) draw_flow_clear(ax4, 23, 46, 36, 20, label="กดยืนยันสั่ง", label_offset=(0, -3.5)) draw_flow_clear(ax4, 60, 20, 73, 24, label="บันทึกลง D4", label_offset=(0, 3.5)) draw_flow_clear(ax4, 60, 15, 73, 10, label="ส่งคิวเข้า D5", label_offset=(0, -3.5)) # 5.0 KDS Sub-system ax5.set_xlim(0, 100); ax5.set_ylim(0, 100); ax5.set_aspect('equal'); ax5.axis('off') ax5.text(50, 96, "DFD Level 2: กระบวนการ 5.0 จัดการคิวครัว (KDS)", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax5, 86, 52, w=18, h=10, title="พนักงานครัว", subtitle="(Kitchen / Chef)", bg="#FFFBEB", border="#D97706") draw_process_gs(ax5, 50, 78, w=22, h=11, pid="5.1", pname="จัดลำดับคิวปรุงอาหาร\n(Enqueue Station)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax5, 50, 48, w=22, h=11, pid="5.2", pname="แสดงผลหน้าจอ KDS\n(Display Orders)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax5, 50, 18, w=22, h=11, pid="5.3", pname="เปลี่ยนสถานะการปรุง\n(Update Status)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax5, 16, 78, w=20, h=6, sid="D5", sname="kitchen_queues") draw_datastore_gs(ax5, 16, 18, w=20, h=6, sid="D4", sname="orders") draw_flow_clear(ax5, 27, 78, 38, 78, label="ดึงออเดอร์ใหม่", label_offset=(0, 3.5)) draw_flow_clear(ax5, 50, 72, 50, 54, label="คิวที่จัดแล้ว", label_offset=(6, 0)) draw_flow_clear(ax5, 62, 48, 76, 52, label="ส่งขึ้นจอ KDS", label_offset=(0, 3.5)) draw_flow_clear(ax5, 76, 46, 62, 20, label="กดเสร็จ/ยกเลิก", label_offset=(0, -3.5)) draw_flow_clear(ax5, 38, 18, 27, 18, label="อัปเดต D4/D5", label_offset=(0, 3.5)) # 6.0 Lead Time Sub-system ax6.set_xlim(0, 100); ax6.set_ylim(0, 100); ax6.set_aspect('equal'); ax6.axis('off') ax6.text(50, 96, "DFD Level 2: กระบวนการ 6.0 คำนวณเวลารออาหาร", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_datastore_gs(ax6, 18, 78, w=20, h=6, sid="D5", sname="kitchen_queues") draw_datastore_gs(ax6, 18, 38, w=20, h=6, sid="D3", sname="menus") draw_process_gs(ax6, 52, 78, w=22, h=11, pid="6.1", pname="นับจำนวนคิวที่ค้างทำ\n(Active Queue Count)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax6, 52, 48, w=22, h=11, pid="6.2", pname="คำนวณค่าน้ำหนักเวลา\n(Time Weight Engine)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax6, 52, 18, w=22, h=11, pid="6.3", pname="ประเมินเวลารวมส่งออก\n(Push Wait Time)", bg="#EFF6FF", border="#2563EB") draw_entity_gs(ax6, 86, 18, w=18, h=10, title="หน้าจอลูกค้า", subtitle="(Customer Screen)", bg="#ECFDF5", border="#059669") draw_flow_clear(ax6, 29, 78, 40, 78, label="ดึงคิวค้างทำ", label_offset=(0, 3.5)) draw_flow_clear(ax6, 52, 72, 52, 54, label="จำนวนจาน", label_offset=(5, 0)) draw_flow_clear(ax6, 29, 38, 40, 48, label="เวลาปรุงมาตรฐาน", label_offset=(0, 3.5)) draw_flow_clear(ax6, 52, 42, 52, 24, label="ผลรวมเวลา", label_offset=(5, 0)) draw_flow_clear(ax6, 64, 18, 76, 18, label="ส่งเวลา 12-15 นาที", label_offset=(0, 3.5)) # 7.0 Payment Sub-system ax7.set_xlim(0, 100); ax7.set_ylim(0, 100); ax7.set_aspect('equal'); ax7.axis('off') ax7.text(50, 96, "DFD Level 2: กระบวนการ 7.0 ชำระเงินและออกใบเสร็จ", ha='center', va='center', fontproperties=prop_subtitle, color="#0F172A") draw_entity_gs(ax7, 14, 78, w=18, h=10, title="ลูกค้า", subtitle="(Customer)", bg="#ECFDF5", border="#059669") draw_process_gs(ax7, 50, 78, w=22, h=11, pid="7.1", pname="สรุปยอด/QR PromptPay\n(Calculate Total)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax7, 50, 48, w=22, h=11, pid="7.2", pname="ตรวจสอบสลิป/รับเงิน\n(Verify Payment)", bg="#EFF6FF", border="#2563EB") draw_process_gs(ax7, 50, 18, w=22, h=11, pid="7.3", pname="ออกใบเสร็จ/ปิดโต๊ะ\n(Close Table Bill)", bg="#EFF6FF", border="#2563EB") draw_datastore_gs(ax7, 84, 78, w=20, h=6, sid="D4", sname="orders") draw_datastore_gs(ax7, 84, 48, w=20, h=6, sid="D6", sname="payments") draw_datastore_gs(ax7, 84, 18, w=20, h=6, sid="D2", sname="tables_qr") draw_flow_clear(ax7, 24, 78, 38, 78, label="เรียกเก็บเงิน", label_offset=(0, 3.5)) draw_flow_clear(ax7, 62, 78, 73, 78, label="ดึงยอดสั่ง D4", label_offset=(0, 3.5)) draw_flow_clear(ax7, 50, 72, 50, 54, label="แสดงยอดชำระ", label_offset=(6, 0)) draw_flow_clear(ax7, 62, 48, 73, 48, label="บันทึกสลิป D6", label_offset=(0, 3.5)) draw_flow_clear(ax7, 50, 42, 50, 24, label="ชำระสำเร็จ", label_offset=(5, 0)) draw_flow_clear(ax7, 62, 18, 73, 18, label="เคลียร์โต๊ะ D2", label_offset=(0, 3.5)) draw_flow_clear(ax7, 38, 18, 23, 72, label="ส่งใบเสร็จให้ลูกค้า", label_offset=(-3, 3.5), rad=0.1) plt.tight_layout() plt.savefig("dfd_level_2_customer.png", dpi=300, bbox_inches='tight') plt.close() if __name__ == "__main__": generate_dfd_level_0() generate_dfd_level_1_overview() generate_dfd_level_2_admin() generate_dfd_level_2_customer() print("All DFD Diagrams (Level 0, Level 1, Level 2 Admin & Customer) regenerated with 100% crystal clear labels!")
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.23 |
proxy
|
phpinfo
|
Settings