#process#master-data#master-detail#autorun#datalist#whitelist
ข้อมูลหลักแบบหัว-รายการ รหัสอัตโนมัติ และเลย์เอาต์รายการ (Master-detail, code auto-run, DataList)
หน้าข้อมูลหลักหลายหน้า (ราคา ส่วนลด ชุดสินค้า สินทรัพย์ ผังบัญชี กลุ่มผู้ใช้ ฯลฯ) บันทึก "หัว + ตารางย่อยหลายแท็บ" ในคำขอเดียวแบบ atomic ผ่าน master-detail/save โดยเว็บไม่เคยเลือกชื่อตารางหรือคอลัมน์เอง ทุก menuKey ผูกกับ spec ที่ whitelist ไว้ใน Go นอกจากนี้ไฟล์กลุ่ม master_* ยังมี route รันรหัสลูกหนี้/เจ้าหนี้อัตโนมัติ และเก็บเลย์เอาต์ DataList รายผู้ใช้
ทำงานอย่างไร
1. Master-detail (POST /process/master-detail/{save|delete})
- Input
MasterDetailInput(ฟิลด์ scope ของบริษัทมาจาก JWT):menuKey,key,scope(ครึ่งหลังของ key ประกอบ เช่นwh_code; เฉพาะ spec ที่มีscopeCol),mode(new|edit, เฉพาะ spec ที่มีตารางหัว),header(map คอลัมน์->ค่า),grids(map id ตาราง -> แถว) - Output
{key, saved: {gridId: จำนวนแถว}}; สิทธิ์ route:save=write,delete=del menuKeyที่ไม่อยู่ในmdSpecs-> error "ไม่รู้จักเมนู";keyแปลงเป็นตัวพิมพ์ใหญ่ ไม่เกิน 25 ตัวอักษร (mdMaxKeyLen); ต้องมีscopeถ้า spec มีscopeCol- spec (
mdSpec) ประกอบด้วย: ตารางหัว (hdrTable,keyCol), คอลัมน์ที่อนุญาต (hdrCols),hdrRefs(ค่าต้องมีอยู่ในตารางอื่น),hdrRanges, ตารางย่อย (grids: คอลัมน์ที่อนุญาต, ค่าคงที่fixed/fixedStr,lineColเลขบรรทัด 1..n,upper,required,ranges,skip),clear(ลบก่อนแทรกใหม่),delChildren,uses(กันลบ),itemKeyed/itemType/gate, และprep(ตรวจ/คำนวณเฉพาะเมนู) - ลำดับ
MasterDetailSave(หมดเวลา 30 วินาที, transaction เดียว):prepare: ฟิลด์/ตารางที่ไม่อยู่ใน whitelist -> "ฟิลด์ไม่ถูกต้อง"/"ไม่รู้จักตาราง"; ตรวจสินค้าถ้าitemKeyed;prepareHeader(โหมดnewแต่รหัสมีอยู่ -> "รหัส ... มีอยู่แล้ว", โหมดeditแต่ไม่พบ -> "ไม่พบรายการ");prepareGrid(เกิน 500 แถว หรือเกินmaxRowsของ grid -> "จำนวนแถวเกินกำหนด");prepของ spec;checkRefswrite: เขียนหัว ->clear-> แต่ละ grid (insertRowหรือupdateRowเมื่อupdatePKตั้งไว้) นับจำนวนแถวที่บันทึก
- ชนิดข้อมูลของทุกค่าอ่านจาก
information_schema.columnsของตารางนั้น (col, cache ต่อคำขอ) แล้วmdNormalize: ตัวเลขผ่านnormDecimal, จำนวนเต็ม (ว่าง = 0, ช่วง int32), วันที่YYYY-MM-DD(ตัดเหลือ 10 ตัว), ข้อความตรวจความยาวคอลัมน์; ค่าผูกเป็น parameter ทั้งหมด - ตัวตรวจสินค้า (
checkItem): สินค้าต้องมี,item_typeตรงกับ spec (ชุดสินค้าใช้ 3), และคอลัมน์ gate (update_priceหรือupdate_detailในic_inventory) ต้องเป็น 1 มิฉะนั้น "ไม่อนุญาตให้แก้ไขข้อมูลนี้" (ตาม C#_checkEditData) MasterDetailDelete: ตรวจuses(ถ้าtable.colยังชี้รหัสนี้ -> "ไม่อนุญาตให้ลบ ...: <ข้อความ>") แล้วลบclear+delChildren+ หัว; หน้าที่ผูกกับสินค้า (price, discount, set) ลบเฉพาะแถวของสินค้านั้น ไม่ลบสินค้า
เมนูที่ลงทะเบียนใน mdSpecs (master_detail_specs.go:144-)
| menuKey | ตารางหลัก (อ่านจากโค้ด) |
|---|---|
menu_ic_item_set |
ic_inventory_set_detail (ชุดสินค้า) |
menu_ic_purchase_price |
ic_inventory_purchase_price |
menu_ic_item_saleprice, menu_ic_all_price |
ic_inventory_price (แท็บ ปกติ/กลุ่ม/ลูกค้า) |
menu_ic_discount |
ic_inventory_discount |
menu_ic_item_formula_template, menu_ic_item_saleprice_formula |
ic_inventory_price_formula |
menu_asset_lists, menu_asset_maintenance |
as_asset*, as_asset_maintenance* |
menu_chart_of_account, menu_chart_of_account_fast |
gl_chart_of_account และตารางเชื่อม |
ic_warehouse_and_location_group, menu_ic_warehouse_locaton |
ic_warehouse_location_group*, ic_wh_shelf |
menu_ic_report_sort |
ic_report_sort_item (ตารางถูกสร้างเองถ้ายังไม่มี ที่ master_detail.go ฟังก์ชัน col) |
menu_ic_purchase_premium |
ic_purchase_permium* |
menu_setup_user_group, menu_setup_user_group_warehouse_shelf |
erp_user_group*, erp_user_group_wh_shelf (ดู สิทธิ์คลัง/ที่เก็บรายกลุ่มผู้ใช้ (perm_wh_shelf)) |
menu_sale_plan |
erp_sale_plan* |
menu_account_period, menu_view_manager_custom |
(ยังไม่ได้อ่านรายละเอียด; erp_view_table_custom/erp_view_column_custom สำหรับเมนูหลัง) |
pos_promotion_formula, menu_setup_pos_slip_campaign |
(ยังไม่ได้อ่านรายละเอียด) |
2. รหัสลูกหนี้/เจ้าหนี้อัตโนมัติ (master/nextcode, master/codeleave)
kindเลือกตารางจาก map คงที่masterCodeTables:customer->ar_customer,supplier->ap_supplier(ไม่รับชื่อตารางจาก body); รหัสยาวสุด 25 (masterCodeMaxLen); วันที่ใช้เขตเวลา UTC+7 (thaiToday)MasterNextCode(= C#MyLib._getAutoRun): เอารหัสมากสุด (ORDER BY code DESC LIMIT 1) แล้วrunRightToLeftเพิ่มตัวเลขท้ายรหัส 1 และเติมศูนย์ให้ความกว้างเดิม; ถ้ารหัสสุดท้ายมีเลขท้ายน้อยกว่า 2 หลัก (หรือไม่มี) ผลเป็นค่าว่าง (ตามที่ C# ทำ ตามคอมเมนต์)MasterCodeLeave(ตอนออกจากช่องรหัส): รหัสที่พิมพ์ตรงกับerp_doc_format.code-> รันตามรูปแบบนั้นผ่านautoRunPattern+autoRunNext(สถานะต่อเนื่องของเอกสาร กราฟโยงเอกสาร และเลขที่เอกสารถัดไป (Doc flow & numbering)) โดยไม่กรองวันที่; ถ้ารูปแบบไม่มี#-> error "รูปแบบรหัส ... ไม่มี # สำหรับเลขรัน"; ถ้าไม่ตรงรูปแบบใด ๆ ถือเป็นคำนำหน้าแล้วหารหัสถัดไปด้วยtypedPrefixNext(stock_tools.go:739) -- เฉพาะลูกค้า ถ้าerp_option.disable_ar_autorun = 1ไม่ทำอะไร (เจ้าหนี้ไม่มีตัวเลือกนี้); ถ้าผลเท่ารหัสที่พิมพ์ จะไม่เปลี่ยนช่อง- ตัวนี้ไม่จองรหัส: การบันทึกจริงยังทำจากเบราว์เซอร์ และคีย์หลักของ
ar_customer/ap_supplierกันรหัสซ้ำ (คอมเมนต์หัวไฟล์) - มี route
master/assetdepdefaults(อัตราค่าเสื่อมและวันหยุดตั้งต้นของหน้าสินทรัพย์AssetDepDefaults,asset_depreciation.go:40) -- ไม่ได้อ่านลงรายละเอียด (ยังไม่ยืนยัน)
3. เลย์เอาต์ DataList รายผู้ใช้ (master/datalistget, master/datalistsave)
- เก็บในตาราง
erp_user_datalist_config(user_code,list_key,config_jsonjsonb,updated_at; PK(user_code, list_key)) ที่ สร้างเองเมื่อใช้ครั้งแรก (datalistDDL,CREATE TABLE IF NOT EXISTS) listKeyไม่เกิน 150, ผู้ใช้ไม่เกิน 100 ตัวอักษร (แปลงพิมพ์ใหญ่); ผู้ใช้ว่าง = ตัวเองconfigต้องเป็น JSON object ที่มีcolumnsเป็น array (ไม่เกิน 500 รายการ) และขนาดรวมไม่เกิน 256 KB; ส่งnull/ว่าง = ลบเลย์เอาต์ (กลับค่าเริ่มต้น); บันทึกแบบ upsertdatalistgetคืนconfig: nullถ้าไม่เคยบันทึก- สิทธิ์: อ่าน/บันทึกของตัวเอง =
read; ระบุผู้ใช้อื่น =admin(RequiredRightที่permission.go:87, ดู การตรวจสิทธิ์เมนูของ route process (Process route rights))
จุดที่ต้องระวัง
- เพิ่มเมนูใหม่ต้องเพิ่ม spec ใน
mdSpecs; เมนูที่ไม่มีใน map จะบันทึกไม่ได้ rangesตรวจเป็นจำนวนเต็มเท่านั้น; ค่านอกช่วง -> "ค่า <col> ไม่ถูกต้อง"- เมื่อ grid เป็นแบบ
updatePK(แก้เฉพาะแถว) คอลัมน์ที่ไม่ส่งมาจะคงค่าเดิมใน DB แต่ grid ปกติ คอลัมน์ที่ไม่ส่งมาจะถูกถือเป็นค่าว่าง/ศูนย์ - ผังบัญชี (
gl_chart_of_account): ถ้าUPDATEไม่โดนแถว โค้ดจะINSERTแทน (master_detail.goฟังก์ชันupdateRow)
ที่มาในโค้ด
backend/internal/application/process/master_detail.go:14-22- คอมเมนต์หลักและหลักการ whitelistbackend/internal/application/process/master_detail.go:24-115- ค่าคงที่ ชนิดMasterDetailInput,mdSpec,mdGrid,mdEnvbackend/internal/application/process/master_detail.go:135-MasterDetailSave;:177MasterDetailDeletebackend/internal/application/process/master_detail.go:237-mdKey;:256prepare;:298prepareHeader;:338prepareGridbackend/internal/application/process/master_detail.go:416-mdNormalize;:449col;:512checkItem;:535checkRefsbackend/internal/application/process/master_detail.go:675-write;:807updateRowbackend/internal/application/process/master_detail_specs.go:144-mdSpecsbackend/internal/application/process/master_autorun.go:23-62-masterCodeTables, ตัวช่วยตรวจbackend/internal/application/process/master_autorun.go:64-MasterNextCode;:83MasterCodeLeave;:147runRightToLeftbackend/internal/application/process/master_datalist.go:50-datalistDDL;:90checkDatalistConfig;:109DatalistGet;:132DatalistSavebackend/internal/adapter/inbound/http/process/master_handler.go:20-37- routemaster/*;master_detail_handler.go:13- routemaster-detailbackend/internal/adapter/inbound/http/process/permission.go:37-47- สิทธิ์ของ route กลุ่มนี้
ดูเพิ่ม
- ข้อมูลสินค้าและข้อมูลสินค้าเพิ่มเติม (Item master & item detail)
- เครื่องมือหาราคาและแก้ราคา (Price engine / price center / modify price)
- สิทธิ์คลัง/ที่เก็บรายกลุ่มผู้ใช้ (perm_wh_shelf)
- สถานะต่อเนื่องของเอกสาร กราฟโยงเอกสาร และเลขที่เอกสารถัดไป (Doc flow & numbering)
- ตัวกระจายคำขอของ process (Process dispatcher)
- ภาพรวมกลุ่ม process ของ Backend (Process overview)