เครื่องฟอร์มแบบ schema และจอตั้งค่าระบบ
จอกรอกข้อมูลแบบฟอร์ม (ข้อมูลบริษัท, ข้อเลือกพิเศษ, ลูกค้า, เจ้าหนี้, สินค้า, หน่วยนับ, คลัง, พนักงาน) ประกาศฟิลด์เป็น ScreenSchema ไว้ใน src/config/schemas/* แล้วให้ <SchemaForm /> วาด (หัวไฟล์ schema.ts:1-9)
name ของฟิลด์ต้องเป็นชื่อคอลัมน์จริงใน PostgreSQL เพื่อให้สร้าง SQL ได้ตรงๆ
ทำงานอย่างไร
นิยาม schema (src/lib/schema.ts)
FieldType(14-34):code, text, textarea, number, password, checkbox, radio, select, lookup, date, image, label, blank, heading;blankใช้เว้นช่องใน grid ให้ผังตรงจอ SML เดิม,headingคือหัวกลุ่ม.FieldDef(42):name, label (ไทย), type, span, rows, maxLength, required, placeholder, choices, inline, lookup, help, hidden(values), disabled(values), min/max/step, resourceOnly(resourceOnly= ไม่มีคอลัมน์ใน DB).LookupKind(~68-97) บอกประเภทหน้าต่างค้นหา (branch, department, warehouse, shelf, currency, user_group, gl_account, province/amper/tambon, ar/ap type/group, ic_unit/category/group/brand/...,font) - ผ่านแผนที่ใน ตารางรายการและหน้าต่างค้นหา (SmlDataList, SmlLookupModal, SmlLookupInput).SectionDef(105;columns1-4, ค่าเริ่ม 2),TabDef(id,label,sections),ScreenSchema(table,title+tabsหรือsections).- ตัวช่วย:
collectFields(130),emptyValue(138; checkbox=false, number=0, select/radio=ตัวเลือกแรก, อื่นๆ=""),blankRecord(153),toDbRecord(172; checkbox -> 0/1),fromDbRecord(194; 0/1 -> checkbox,code-> ตัวพิมพ์ใหญ่, select/radio คงชนิดของ choice),findEmptyRequired(229; ข้ามฟิลด์ที่hidden).
สถานะฟอร์ม useRecordForm(schema, initial?) (useRecordForm.ts:16)
- เก็บ
baseline(ค่าที่โหลดล่าสุด) กับvalues(ค่าปัจจุบัน); คืนvalues, setField, setMany, load, dirtyFields, isDirty, emptyRequired, canSave. dirtyFields= ชื่อฟิลด์ที่values[k] !== baseline[k];load(next)ตั้งทั้ง baseline และ values เป็นค่าใหม่ (ใช้หลังโหลด/บันทึก).
ตัววาด (account/form/)
SchemaForm({sections, form, onLookup, lookupNames, onLookupNameChange, readOnlyFields, readOnly})(SchemaForm.tsx:281) วนSchemaSection(220) = การ์ดมีหัวข้อ + grid; แต่ละช่องFieldRow(78) ข้ามถ้าfield.hidden?.(values).- ช่องที่แก้แล้วยังไม่บันทึก (
dirty) ถูกไฮไลต์สีส้ม (classfld-dirtyในFieldControl.tsx:36; กรอบaccentของ radio ในSchemaForm.tsx).radioวาดเป็นfieldsetเต็มแถวเหมือน GroupBox ของ WinForms. FieldControl(FieldControl.tsx:24) วาดตามtype:codeบังคับตัวพิมพ์ใหญ่ + monospace,textarea,numberผ่านNumberBox(ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts)),dateผ่านDateBox,lookupผ่านSmlLookupInput,image(เป็นกล่องเปล่าข้อความ "ยังไม่ได้เลือกรูป" ไม่มีปุ่มอัปโหลด, 273-283),lookupที่เป็นfontเลือกจากรายการSTANDARD_REPORT_FONTS.- ซ่อนฟิลด์ตามรุ่นผลิตภัณฑ์:
isSchemaFieldHiddenByEdition(SchemaForm.tsx:40) ซ่อนฟิลด์ GL (STARTER_HIDDEN_GL_FIELDS), สาขา/แผนก (STARTER_HIDDEN_BRANCH_DEPT_FIELDS) เมื่อรุ่นไม่มี GL / สาขา, และฟิลด์เฉพาะรุ่น Pro (PRO_ONLY_SCHEMA_FIELDSเช่นmulti_currency,home_currency,use_compare_unit) เมื่อไม่มีความสามารถขั้นสูง - อ่านจากuseEdition()ดู ทะเบียนหน้าจอและโครงเมนู (Screen registry & smlMenu).
จอ "ข้อมูลบริษัท" CompanyProfileForm (account/config/CompanyProfileForm.tsx:28, menu menu_company_profile)
- โหลด
SELECT * FROM erp_company_profile LIMIT 1->load(fromDbRecord(companyProfileSchema, row))(49-55). schema ที่src/config/schemas/companyProfile.tsมี 2 section (identity,address). - บันทึก (
save, ~68): ต้องมีrights.canEdit(ไม่งั้นเปิดกล่อง "ไม่มีสิทธิ์บันทึกข้อมูล") -> ตรวจcompany_name_1ไม่ว่าง -> ตรวจemptyRequired->queryExecBatch(["DELETE FROM erp_company_profile", buildInsertSql(...)])ใน transaction เดียว (107-116) ตามที่ SML เดิมทำ (ลบแล้วใส่ใหม่ ตาราง 1 แถว).
จอ "กำหนดข้อเลือกพิเศษต่างๆ" OptionsForm (account/config/OptionsForm.tsx:57, menu menu_option; 688 บรรทัด)
- schema
erpOptionSchema(erpOption/index.ts:46) มี 9 แท็บ ตามลำดับ:system, gl, item, sale, sync, mis, wallet, etax, mobillyst(ไฟล์tab1System.ts...tab9Mobillyst.ts). ฟิลด์กระจาย 4 ตาราง แยกด้วยคำนำหน้าชื่อ: (ไม่มี) =erp_option,thaiqr.=erp_thai_qr_config,etax.=erp_option_etax_inet,mobillyst.=erp_option_mobillyst(TABLE_PREFIX,index.ts:22-26);mergeOptionTables(33) รวม 4 ตารางกลับเป็น record แบนตอนโหลด. - เปิดจอแล้วอยู่แท็บ
business_types(ชนิดธุรกิจ,OptionsForm.tsx:92) ซึ่งตั้งผ่านuseEdition(businessTypes,toggleBusinessType) และปุ่มapplyRecommendedOptionsใส่ค่าแนะนำตามชนิดธุรกิจ (getRecommendedOptionsForBusinessTypes,editionConfig). ชนิดธุรกิจเก็บทั้งในเครื่องและคอลัมน์erp_option.business_types(166-168). - แท็บที่ซ่อนตามรุ่น:
glเมื่อไม่มี GL;sync,mis,mobillystเมื่อไม่มีความสามารถ Pro (visibleOptionTabs, 72-86). มีตัวนับจำนวนช่องที่แก้ต่อแท็บ (dirtyByTab, 196-205). - บันทึก (
save, 207-): ต้องrights.canEdit-> ตัดค่าข้อความที่มี~ให้เหลือส่วนหน้าก่อน~(sanitizedValues, 218-224; เหตุผลของรูปแบบนี้ยังไม่ยืนยัน) -> แยกฟิลด์ตามคำนำหน้า 4 กลุ่ม ->buildInsertFieldsSqlต่อกลุ่ม (ตัดคำนำหน้าออกด้วยcolumnNameTransform) ->queryExecBatchชุดเดียว:DELETE FROM erp_option,DELETE FROM erp_thai_qr_config WHERE config_type = 0,DELETE FROM erp_option_etax_inet,DELETE FROM erp_option_mobillystแล้ว insert ใหม่ (286-295). - หลังบันทึกสำเร็จ:
setSmlYearType(year_type===1?1:0)+refreshSmlDecimalSettings()(297-298) ให้ทศนิยม/ปี พ.ศ. ทั้งระบบเปลี่ยนทันที (ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts)), แสดงกล่อง "บันทึกข้อมูลเสร็จเรียบร้อย" แล้วเรียกonClose. - ช่อง lookup ใช้
SmlLookupModalผ่านhandleLookup(127-138); ฟิลด์fontไม่เปิดหน้าต่างค้นหา.
ผู้ใช้อื่นของเครื่องฟอร์ม: จอหลักข้อมูลที่ใช้ SchemaForm/useRecordForm ด้วย ได้แก่ CustomerScreen/CustomerDetailScreen, SupplierScreen/SupplierDetailScreen, ItemScreen, UnitScreen, WarehouseScreen, EmployeeScreen (schema ใน arCustomer.ts, arCustomerDetail.ts, apSupplier.ts, apSupplierDetail.ts, icInventory.ts, icUnit.ts, icWarehouse.ts, erpUser.ts) - ดู รายการจอข้อมูลหลักแบบตารางเดียว (IC_MASTER_CONFIGS).
ข้อควรระวัง
- ชื่อฟิลด์ใน schema = ชื่อคอลัมน์จริง; ถ้าเพิ่มฟิลด์ที่ไม่มีคอลัมน์ต้องใส่
resourceOnly: trueมิฉะนั้นbuildInsertSqlจะใส่คอลัมน์นั้นใน SQL (sml-query-builder.ts:268-285). - จอตั้งค่าใช้ DELETE แล้ว INSERT ทั้งแถว (ตาราง 1 แถว) ใน transaction เดียว - ฟิลด์ที่ไม่อยู่ใน schema จะหายไปจากแถวหลังบันทึก.
- ค่า
numberจาก DB ที่เป็นข้อความถูกเก็บเป็น string เพื่อไม่ให้เสียความละเอียด (fromDbRecord, 203-209) ดู ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts).
ที่มาในโค้ด
frontend/src/lib/schema.ts:14-34,42-62,105-136,138-250- ชนิดฟิลด์, FieldDef, SectionDef, แปลง DBfrontend/src/hooks/useRecordForm.ts:16-68- สถานะฟอร์ม, dirtyfrontend/account/form/SchemaForm.tsx:11-76,78-205,220-280,281-310- ซ่อนตามรุ่น, FieldRow, Sectionfrontend/account/form/FieldControl.tsx:24-60- ตัววาดตามชนิดfrontend/account/config/CompanyProfileForm.tsx:28-135- โหลด/บันทึกข้อมูลบริษัทfrontend/account/config/OptionsForm.tsx:57-137,196-300- ชนิดธุรกิจ, แท็บ, บันทึก 4 ตารางfrontend/src/config/schemas/erpOption/index.ts:22-60- 9 แท็บ, คำนำหน้าตารางfrontend/src/lib/sml-query-builder.ts:263-285-buildInsertSql
ดูเพิ่ม
ภาพรวม Frontend ของ SML Ai Account (Frontend overview) · รายการจอข้อมูลหลักแบบตารางเดียว (IC_MASTER_CONFIGS) · จอข้อมูลหลักมาตรฐานและจอ master-detail (StandardMasterScreen / MasterDetailScreen) · ตารางรายการและหน้าต่างค้นหา (SmlDataList, SmlLookupModal, SmlLookupInput) · ตัวเรียก API และตัวประกอบ SQL ฝั่งเบราว์เซอร์ (api-client, query-client, sml-query-builder) · ตัวเลข เงิน ภาษี และปี พ.ศ. ฝั่ง frontend (numeric.ts) · พื้นที่ทำงานแบบแท็บ MDI และสิทธิ์จอ (TabWorkspace)