#faq#report#dev#backend#frontend#troubleshooting
เพิ่มรายงานใหม่ (เมนูรายงาน) ต้องแก้ที่ไหนบ้าง และทำไมขึ้น "ไม่พบรายงาน"
ตอบสั้น: 1 เมนู = 1 ตัวสร้างรายงานฝั่ง Go ที่ลงทะเบียนด้วย registerMenuReport(fn, "menu_key") ใน init() ของไฟล์ report_menu_*.go ส่วนหน้าจอไม่ต้องเขียนใหม่ เพราะเมนูใบทุกใบใน smlMenu.json ที่ยังไม่มีจอเฉพาะจะได้ UniversalReportScreen อัตโนมัติ (เลือกโหมดตามชื่อหมวดบนสุด) ถ้าเมนูมีในแผนผังแต่ฝั่ง Go ไม่ได้ลงทะเบียน menuKey จะได้ข้อความ "ไม่พบรายงาน <menuKey>"
รายละเอียด
ขั้นตอนเพิ่มรายงาน:
- เมนู — เพิ่มใบเมนู (
name,text,tag) ในfrontend/src/config/smlMenu.json;registerAllMenus(screenRegistry.tsx:1382) เดินทุกใบแล้วเรียกbuildDynamicScreen(:1066) ซึ่งเลือกmodeตามหมวดบนสุด (menu_po→report_po,menu_ap→report_ap,menu_ar→report_ar,menu_wh→report_wh_ppฯลฯ) ถ้าไม่ตรงหมวดใดจะเป็นreport_ic(ค่าเริ่มต้น:1333) - ตัวสร้างรายงาน (Go) — เขียนฟังก์ชัน
menuReportFunc(func(ctx, pool, reportParams) (RunReportResult, error),report_menu.go:26) แล้วลงทะเบียน key ตัวพิมพ์เล็กในinit()ของไฟล์หมวดนั้น (ตัวอย่างregisterMenuReport(...)ในreport_menu_gl_fa.go:1593) ลงทะเบียน key ซ้ำ =panic("report menu registered twice")ตอนโปรแกรมเริ่ม - รายงานสินค้า/คลัง ใช้แบบ
icSpec(report_menu_ic.go:23) ผ่านicRun(summary, detail)— กำหนดcode(ต้องไม่ซ้ำ),cols(Key = alias ใน SQL),sqlที่ต่อท้าย CTEprm(icPrm:20) อ่านค่าเป็นprm.d1/d2(วันที่),prm.fc/tc(ช่วงรหัส),prm.kw/kl(คำค้น),prm.o(JSON ของเงื่อนไขเพิ่ม) แต่ละ$1..$7ต้องอ้างครั้งเดียว มิฉะนั้น pgx ปฏิเสธพารามิเตอร์ที่ไม่ได้ใช้ - เงื่อนไขเพิ่มเติม — ประกาศใน
opts []ReportConditionด้วยcondCheck/condNumber/condText/condDate/condSelect(และชนิดranges,multi)report_conditions.go:10หน้าจอวาดช่องให้เองจากค่าที่ backend ตอบในconditions; ฝั่ง Go อ่านด้วยp.optBool/optInt/optStrและ SQL อ่านผ่านprm.o->>'key'ค่าที่ไม่ได้ประกาศถูกทิ้งโดยnormalizeReportOptions(report_options.go:23) - ชื่อ key เก่า — ถ้าต้องรองรับชื่อเดิม ใส่ใน
reportCodeAliases(report.go:209) และ/หรือREPORT_KEY_ALIASESของ proxy (frontend/src/app/api/process/report/run/route.ts:12) - สิทธิ์ —
report/runและreport/pdfอยู่ในrouteRightsเป็น read แล้ว (process/permission.go:25) ไม่ต้องเพิ่ม; ถ้า body มีcustomSqlต้อง Admin (ทำไมเข้าเมนู/กดบันทึกแล้วขึ้น 403 ไม่มีสิทธิ์ และตั้งสิทธิ์เมนูให้ผู้ใช้อย่างไร) - ทดสอบ — เพิ่ม key ในรายการที่คาดหวังของเทสต์
Test*MenusRegisteredของหมวด และรันTestICSpecsWellFormed/TestSOPOSpecsWellFormed(ตรวจ$1..$7ครั้งเดียว, ไม่มีLIMIT 50000, key ไม่เกิน 63 bytes, key = label, ทุกคอลัมน์มีAS "..."ตรงกัน —report_menu_ic_test.go:103)
ลำดับที่ RunReport เลือกตัวสร้าง (report.go:289): หา menuReports[lowerKey] ก่อน ถ้าไม่มีและไม่ใช่เมนูตัวออกแบบ ไป runLegacyReport ซึ่งรองรับเฉพาะ mode == "sql_utility" นอกนั้นตอบ "ไม่พบรายงาน" (ตรวจโดย TestRunLegacyReportRefusesUnknownMode)
ข้อควรระวัง
- ยอดเงินในผลรายงานเป็นสตริงทศนิยม รวมด้วย
big.Ratใน engine (computeExactColumnTotals) อย่าคืน float จาก SQL เป็นตัวเลขเอง (ระบบปัดเศษทศนิยมเงินอย่างไร ทำไมยอดต่างกัน 0.01) - ห้ามต่อ key ของ option จากข้อมูลผู้ใช้ลง SQL — ใช้ฟังก์ชัน
opt*กับ key คงที่เท่านั้น - รายงานที่แสดงต้นทุนต้องตั้ง
costในicSpecให้ตัดคอลัมน์เมื่อผู้ใช้ถูกซ่อนต้นทุน (itemCostHidden) และรายงานที่กรองตามสิทธิ์คลังตั้งperm(จำกัดคลัง/ที่เก็บที่ผู้ใช้เลือกได้ (perm_wh_shelf) ตั้งอย่างไร และทำไมผู้ใช้เห็นคลังไม่ครบ) - วันที่ในรายงานแปลงเป็น พ.ศ./ค.ศ. ตาม
erp_option.year_typeโดย engine (วันที่ในระบบเป็น พ.ศ. หรือ ค.ศ. ตั้งที่ไหน แล้วทำไมวันที่ในรายงานกับในบัญชีไม่ตรงกัน) - ชื่อเมนูใหม่ที่อยู่หมวดนอกตาราง
modeจะตกไปเป็นreport_icซึ่งอาจเลือกชุดปุ่มไม่ตรง ให้ตรวจbuildDynamicScreenก่อน
ดูเพิ่ม
- เครื่องมือรายงานฝั่ง Backend (Report engine / RunReport)
- ทะเบียนรายงานรายเมนูและเงื่อนไขกรอง (Menu report registry & conditions)
- มาตรฐาน Engine รายงานกลางและตัวออกแบบ JSON-First (Global Report Engine)
- จอรายงานกลาง (Universal Report Screen)
- เรียกรายงานยังไง ตั้งเงื่อนไขตรงไหน และทำไมรายงานว่างหรือไม่มีเอกสารที่ยกเลิก
- รหัสเมนู (เช่น 2.1.7 หรือ 4013) คือหน้าจอไหน และระบบเปิดหน้าจอจากรหัสยังไง
ที่มาในโค้ด
backend/internal/application/process/report_menu.go:28menuReportsและregisterMenuReport(panic เมื่อ key ซ้ำ บรรทัด 38)backend/internal/application/process/report_menu_ic.go:20icPrmและicSpec(บรรทัด 23) /icRunที่ลงทะเบียนเข้าicAllSpecsbackend/internal/application/process/report_conditions.go:10ReportConditionและตัวสร้างcond*backend/internal/application/process/report.go:289เลือกmenuReports[lowerKey]ไม่เจอ →runLegacyReport/ "ไม่พบรายงาน"backend/internal/application/process/report_menu_ic_test.go:103TestICSpecsWellFormedfrontend/account/tabs/screenRegistry.tsx:1066buildDynamicScreenและregisterAllMenus(บรรทัด 1382)frontend/src/app/api/process/report/run/route.ts:12REPORT_KEY_ALIASES