พิมพ์รายงาน แบบฟอร์มเอกสาร และตัวออกแบบ
ระบบมีงานพิมพ์ 2 สาย คือ (1) พิมพ์รายงาน: backend เรนเดอร์เป็น PDF แล้วแสดงใน iframe (2) พิมพ์เอกสารซื้อ/ขาย/บัญชี: เบราว์เซอร์โหลดข้อมูลแล้วพิมพ์เองด้วย window.print()
ตัวออกแบบ 2 ตัว (FastReportDesignerScreen, FormDesignerScreen) สร้างโครงรายงาน/แบบฟอร์มเป็น JSON แล้วบันทึกเป็น template ผ่าน report/run ของ backend
ทำงานอย่างไร
1) พิมพ์รายงาน: GlobalReportPrintModal
- เปิดจากปุ่ม "พิมพ์" ของ
UniversalReportScreen(ดู จอรายงานกลาง (Universal Report Screen)) ส่งbasePayload(เงื่อนไข + คอลัมน์ล่าสุด) เข้ามา - เมื่อ
openเป็นจริง จะเรียกrenderPdfFromBackend(GlobalReportPrintModal.tsx:2350-2358) ->fetchBackendReportPdf->POST /api/process/report/pdf-> ได้blobเก็บด้วยURL.createObjectURLแสดงใน<iframe>และ revoke URL ตอนปิด/ถอด component (renderPdfFromBackendเริ่ม:2291,:2330-2340,:2359-2365) - ปุ่ม "สั่งพิมพ์ออกเครื่องพิมพ์" สั่ง
iframe.contentWindow.print()ถ้าไม่มี iframe ให้เปิดแท็บใหม่ (:2375-2387); ปุ่มดาวน์โหลดใช้ชื่อไฟล์จาก headerContent-Dispositionของ backend (fetchBackendReportPdf,query-client.ts:1029-1050) ReportPrintSettings(:53-80) คือค่าตั้งหน้ากระดาษทั้งหมด:paperSize(A4/A3/Letter/Legal/A5/Continuous),orientation,fontSizePt(ค่าเริ่ม 8.5),colorMode,printTheme(6 ธีม เช่นsml_emerald,corporate_navy),density,gridStyle,showZebra/showRowNumber/showCompanyHeader/showSignatureBlock,signatureLabels,footerNote,groupByColumn/subGroupByColumn,reportLang- เก็บค่าตั้งใน
localStorageคีย์sml_global_report_print_prefs_v2(:104,useGlobalReportPrintSettings:119-170); ตอนโหลดจะล้างcustomTitle/customSubtitle/groupByColumn/subGroupByColumnทิ้งเสมอ (ไม่ข้ามเมนู) และยอมรับfontSizePtเฉพาะช่วง 6.5-13.0 - รายงานภาษาอังกฤษ: ถ้า
reportLang === "en"เบราว์เซอร์แปลชื่อคอลัมน์ ชื่อเรื่อง ป้ายลายเซ็น และ footer ด้วยtranslateThaiToEnglishก่อนส่ง payload (:2294-2322) ไม่ได้ให้ backend แปล - แผง SQL ใน
GlobalReportStudioPanelมีช่องพิมพ์คำสั่งภาษาคน ->POST /api/process/workflow/ai-report-sqlได้sql, explanation, suggestedGroupBy, columnsกลับมา แล้วหน้าจอใส่ SQL ในช่องแก้ไขและสั่งทดสอบรันทันที (GlobalReportPrintModal.tsx:1235-1252) - ส่วนอื่นใน
GlobalReportPrintModal.tsxที่หน้ารายงานใช้:GlobalReportPageSetupBar(:722, แถบตั้งหน้ากระดาษ),GlobalReportStudioPanel(:1167, แผงล่างมี 3 tabsql | columns | templatesตามStudioTabKey:698),computeAutoColumnWidthsFromData(:332, คำนวณความกว้างคอลัมน์ % จากข้อมูลจริง),normalizeColumnOverridesWidthPct(:264),buildInitialColumnOverrides/mergeColumnOverrides(:659,:682)
2) พิมพ์เอกสาร: GlobalDocFormPrintModal (shared, ~9,800 บรรทัด)
- เป็น modal เดียวที่
UniversalTransScreenใช้พิมพ์ทุกเอกสาร (UniversalTransScreen.tsx:108,:4247) โดยส่งmenuKey,transFlag(s),docKind,docNo, ข้อมูลคู่ค้า และรายการสินค้าเข้าไป (ดู จอเอกสารธุรกรรมแบบเดียวกันทุกจอ (UniversalTransScreen)) - พิมพ์ด้วย
window.print()+ CSS@media print(GlobalDocFormPrintModal.tsx:4294-4325,:4877) ไม่ผ่าน/api/process/report/pdf - นับเป็น "พิมพ์เอกสารที่บันทึกแล้ว" ได้เมื่อ
isActualSavedMode = isSavedMode && dbRecord?.verified(:2640) คือโหลดเอกสารกลับจาก DB ด้วยfetchSavedDocFromDb(:2318) ยืนยันแล้วเท่านั้น - โหลดข้อมูลหัว/รายการเอกสารเองด้วย
queryListตามชนิดเอกสาร:gl_journal+gl_journal_detail(:2321-2336),cb_chq_list(:2384-2392),ap_ar_trans+ap_ar_trans_detail(:2443-2476),ic_trans+ic_trans_detail(:2525-2558) และข้อมูลบริษัท/คู่ค้า (erp_company_profile,ap_supplier/ar_customer+_detail,:2109-2147) - แม่แบบสำเร็จรูป
READY_DOC_FORM_TEMPLATES(:205, 18 แบบ) แต่ละอันระบุgroupKey(เช่นsale_invoice,purchase_pr_po,payment_voucher),legalRef, ธงisFullTaxInvoice/isAbbrTaxInvoice/isTouristVatRefund/isCnDnและdefaultTransFlags;getLockedTemplatesForTransScreen(:582) เลือกกลุ่มแม่แบบที่อนุญาตตามtransFlag+ ชื่อเมนู - ขนาดกระดาษ
DOC_PAPER_SIZES(:690): A4, A5, Letter, Continuous 9x11, Continuous 9x5.5, Thermal 80mm, Thermal 58mm (DocPaperSizeId:667-674); สไตล์modern_standard | corporate_classic | executive_minimal | thermal_80mm(:760-764) - ส่วนประกอบของกระดาษสลับ/ซ่อน/จัดลำดับได้ (
DEFAULT_DOC_SECTION_ORDER:947,HeaderPieceId,PartyPieceId, ความกว้างคอลัมน์DEFAULT_DOC_COL_WIDTHS_PCT:967) calculateThaiTouristVatRefund(:113) คำนวณยอดคืน VAT นักท่องเที่ยวสำหรับแบบtourist_vrt(กรอบคำร้อง ภ.พ.10 / e-VRT,:916,:958); ตัวเลขเงื่อนไขอยู่ใน comment และฟังก์ชันนี้ (เกณฑ์ทางกฎหมายต้องตรวจกับแหล่งทางการก่อนอ้างอิง ยังไม่ยืนยัน)
ที่เก็บค่าของแบบฟอร์มเอกสาร
| ข้อมูล | ที่เก็บ | ที่มา |
|---|---|---|
| ค่าตั้งแบบพิมพ์ล่าสุดต่อเมนู | localStorage sml_doc_form_prefs_v2 |
GlobalDocFormPrintModal.tsx:1211, :4118-4132 |
| ชุด preset ที่ตั้งชื่อ | localStorage sml_doc_form_named_presets_v1 |
:1212 |
layout ต่อเมนู / ค่ากลาง __GLOBAL__ |
DB ตาราง erp_business_ext (entity_type='doc_form_layout', ON CONFLICT (entity_type, entity_code)) |
:2014-2019, :4143-4166 |
| preset ชื่อที่แชร์ | erp_business_ext entity_type='doc_form_layout_preset' |
:2049, :4225-4228 |
| จำนวนครั้งที่พิมพ์ (audit) | erp_business_ext entity_type='doc_print_audit' คีย์ <transFlag>:<docNo> เก็บ print_count, last_printed_at, unsaved_attempt_count |
:4294-4322, :2253 |
| แม่แบบที่ผูกกับ "รูปแบบเอกสาร" | UPDATE erp_doc_format SET form_code=... เมื่อบันทึก layout |
:4170-4177 |
- บันทึกด้วย
queryExecที่ประกอบ SQL string เองและ escape'ด้วยreplace(/'/g, "''"); การพิมพ์เอกสารที่ยังไม่บันทึกจะนับเป็นunsaved_attempt_count(ผ่าน eventbeforeprint,:2640-2672) และมี proponSaveBeforePrintให้จอเรียกhandleSaveก่อนพิมพ์ (UniversalTransScreen.tsx:4256) DocFormatScreen(account/master/DocFormatScreen.tsx:37,:1155) นำREADY_DOC_FORM_TEMPLATESไปแสดงเป็นตัวเลือกform_codeในจอตั้งรูปแบบเอกสาร
3) ตัวออกแบบรายงาน: FastReportDesignerScreen (~4,060 บรรทัด)
- ลงทะเบียนผ่าน
createReportDesignerScreen(screenRegistry.tsx:101-127) ซึ่งเลือกจอตามvariant/menuKey:
| เมนู (รหัสเมนู) | menuKey |
variant | จอ |
|---|---|---|---|
| ออกแบบรายงาน (1.13) | fast_report_designer |
fast_report |
FastReportDesignerScreen |
| สร้าง/แก้ไขแบบฟอร์ม (1.12) | menu_form_edit |
form_designer |
FormDesignerScreen |
| ออกแบบงบการเงิน (1.9.7) | menu_gl_report_design |
gl_statement |
FastReportDesignerScreen (เปิด tab account) |
| นำเข้ารายงาน (1.10.22) | menu_import_report |
import_report |
FastReportDesignerScreen |
| นำเข้ารายงานสาขา (1.10.23) | menu_import_report_branch |
import_report + branchMode |
FastReportDesignerScreen |
| นำเข้าแบบฟอร์ม (1.10.20) | menu_import_formdesign |
import_report (แต่ wrapper เปลี่ยนเป็น FormDesignerScreen เพราะ menuKey ตรง, screenRegistry.tsx:109) |
FormDesignerScreen initialImportMode |
(ที่มา: screenRegistry.tsx:101-127, ลงทะเบียน :190-262; หมายเหตุ: หมายเลขรหัสเมนูอ้างตาม code ในรายการลงทะเบียน)
- โครง JSON
SmlReportDesignJSON(schemaVersion: "sml.report.json.v1",:145-163):menuId, menuName, reportType (0..8), header, refNo, paperSize, orientation, fontSizePt, conditions[], queries[] (Query 1..7 พร้อม fields), account (งบการเงิน); ประเภทรายงาน 9 แบบSML_FASTREPORT_TYPES(0 ทั่วไป ... 8 บัญชี) - tab ฝั่งขวา:
condition, query1..query7, account, options, json(DesignerTabKey:866-878) - ดู Preview = เรียก
runBackendReport(report/run) ด้วยcustomSqlที่แทนค่า#from_date#,#to_date#,#from_code#,#keyword#แล้ว (:1056-1110) ปุ่ม Get Field รันqueryForGetFieldหรือSELECT * FROM <ตาราง> LIMIT 1เพื่อค้นคอลัมน์ (:1190-1215) - แผงซ้าย Resource/Schema โหลดรายชื่อตารางจริงจาก
information_schema.columnsด้วยqueryListจำกัด 400 แถว (:1155-1175) - บันทึก =
runBackendReportด้วยmenuKey: "fast_report_designer"+templateAction: "save"โดยใส่ JSON ทั้งก้อนไว้ในfooterNote(JSON.stringify(nextDesign),:1323-1327); ลบ =templateAction: "delete"(:1371) ต้องมีสิทธิ์rights.canDelete; แก้ไข/บันทึกถูกห้ามเมื่อrights.readOnly(:1287) - ส่งออก/นำเข้าไฟล์
<id>.report.jsonด้วยBlob/FileReader(:1404-1430,:1380-1400) ไม่ใช้ XML แล้ว (ข้อความสถานะ "JSON-First เลิกใช้ XML 100%",:897)
4) ตัวออกแบบแบบฟอร์ม: FormDesignerScreen (~5,540 บรรทัด) + formDesignerPresets.ts (~3,320 บรรทัด)
- JSON
SmlFormDesignJSON(schemaVersion: "sml.formdesign.json.v1",formDesignerPresets.ts:201-213):formCode, formName, formType, pageSetup, pages[], queries[], imageList[]; ชนิดฟอร์ม 4 แบบSML_FORM_TYPES(0 ทั้งหมด, 1 พิมพ์เอกสาร, 2 บาร์โค้ดสินค้า, 3 ป้ายชื่อขนส่ง) - เครื่องมือวาด
FormDrawToolType(:7-19): Pointer, Label, TextField, SpecialLabel, Table, Line, Rectangle, RoundedRectangle, Ellipse, Picture, ImageField, Barcode; หน่วยไม้บรรทัด cm/mm/inch/pixel;CM_TO_PX = 37.795...(96 DPI) presetsในไฟล์: พื้นหลังสำเร็จรูปBUILTIN_BACKGROUND_FORM_PRESETS(:293), แบบฟอร์มมาตรฐานSML_STANDARD_FORM_TEMPLATES(:510, แต่ละอันมีbuildDesign()),createDefaultFormQueries(:457) และฟังก์ชันตัวเลขเป็นตัวอักษรnumberToThaiBahtText(:1771) /numberToEnglishBahtText(:1815)- โหลดรายการฟอร์มด้วย
queryListจากตารางformdesign(+ ข้อมูลตัวอย่างจากic_trans,ic_trans_detail,erp_company_profile) (FormDesignerScreen.tsx:986-1020) - บันทึก =
runBackendReportด้วยmenuKey: "menu_form_edit"+templateAction: "save",footerNote: JSON.stringify(nextDesign), ชื่อ template"<formCode> : <formName>"(:1736-1805); ข้อความยืนยันระบุว่าเขียนลงตารางformdesignและerp_report_template(:1804); ตรงนี้ตารางจริงที่ backend เขียน (ยังไม่ยืนยัน ไม่ได้อ่านโค้ด backend) - นำเข้าไฟล์ JSON ของฟอร์ม
handleImportFormJson(:1831)
ข้อควรระวัง
- รูปแบบรายงาน (template) กับดีไซน์ JSON ใช้กลไกเดียวกัน: ส่ง
templateActionผ่านreport/run; เวลาเพิ่ม/ลบรูปแบบต้องส่งเงื่อนไขรายงานครบชุด เพราะ endpoint คือรันรายงานจริงอีกรอบ - พิมพ์รายงาน (PDF จาก backend) กับพิมพ์เอกสาร (
window.print()ในเบราว์เซอร์) ไม่ใช่โค้ดชุดเดียวกัน แก้หน้าตาเอกสารต้องแก้ในGlobalDocFormPrintModal.tsxส่วนรายงานต้องแก้ฝั่ง backend renderer ด้วย GlobalDocFormPrintModalประกอบ SQL ด้วย string และ escape เองหลายจุด ถ้าเพิ่มช่องดึงข้อมูลใหม่ต้อง escape'ให้ครบ (ดู ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder))- ไฟล์ designer ใหญ่มาก (4-5 พันบรรทัด) ให้ค้นด้วยชื่อฟังก์ชัน เช่น
handleSaveFormToDatabase,handleRunPreview,handleImportJsonFileแทนการอ่านทั้งไฟล์
ที่มาในโค้ด
frontend/account/report/GlobalReportPrintModal.tsx:53-170settings, localStorage;:2270-2390modal พิมพ์ PDFfrontend/account/report/FastReportDesignerScreen.tsx:100-200type JSON;:880-945state/tab;:1056-1110preview;:1287-1380save/delete;:1404importfrontend/account/report/FormDesignerScreen.tsx:986-1020โหลดรายการ;:1736-1830บันทึก/นำเข้าfrontend/account/report/formDesignerPresets.ts:7-218type และชนิดฟอร์ม;:1771,:1815ตัวเลขเป็นข้อความfrontend/shared/components/GlobalDocFormPrintModal.tsx:56-100, 205, 582, 667-690, 1277, 2014, 4118-4177, 4294-4325frontend/account/tabs/screenRegistry.tsx:101-127createReportDesignerScreenfrontend/account/transaction/UniversalTransScreen.tsx:4247เรียก modal พิมพ์เอกสาร
ดูเพิ่ม
จอรายงานกลาง (Universal Report Screen) | จอเอกสารธุรกรรมแบบเดียวกันทุกจอ (UniversalTransScreen) | เส้นทาง API ฝั่ง Next.js ที่ส่งต่อไป Go backend (API proxy routes) | ทะเบียนหน้าจอและโครงเมนู (Screen registry & smlMenu) | ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder) | ภาพรวม Frontend ของ SML Ai Account (Frontend overview) | ภาพรวมระบบบัญชี SML AI Account (Accounting Overview)