POS ตั้งค่าร้าน/เครื่อง/โปรโมชัน และกะขาย (POS Config and Shift)
ส่วนตั้งค่าและกะขายของ POS ใช้ร่วมกันระหว่างหน้า Setup/Back office ของ SML Ai Account กับแอป POS (คอมเมนต์แพ็กเกจ pos/handler.go:1-2) มี 3 จุดเข้า: GET /api/v1/pos/bootstrap (อ่านข้อมูลหน้าตั้งค่าทั้งก้อน), POST /api/v1/pos/config (บันทึกตั้งค่าตามหมวด section), POST /api/v1/pos/shift (กะขาย/รับ-ส่งเงิน/ยกเลิกบิล/สมาชิกชั่วคราว) ดูเส้นทางและการยืนยันตัวตนที่ POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync)
ทำงานอย่างไร
ตารางและการสร้างอัตโนมัติ
posConfigDDL(pos_config.go:16) สร้างตารางด้วยCREATE TABLE IF NOT EXISTS:posconfig,pos_id,erp_thai_qr_config,pos_point_condition,pos_promotions,coupon_list,pos_period,poscashiersettle,pos_member_groups,pos_temp_members,images,sml_doc_images,erp_business_ext,pos_slip_campaign_items/brand/category/group,sml_resourceและALTER TABLE ... ADD COLUMN IF NOT EXISTSของบางคอลัมน์EnsurePosTables(:373) /ensurePosTablesPool(:381) รันครั้งเดียวต่อprovider:ฐาน(ตัวจำs.posSeedDone) ถ้า DDL คำสั่งใดพัง ข้ามไปทำต่อ ("best effort" ตามคอมเมนต์ :388)- การเพิ่มข้อมูลตัวอย่าง (ลูกค้า Walk-in, ค่า
posconfig, เครื่องตัวอย่าง, รูปสินค้าตัวอย่าง) ทำ เฉพาะฐานชื่อsmldemo(เช็คที่ :393 ฐานอื่นหยุดหลังสร้างตาราง) ส่วนรูปสินค้าตัวอย่างและการปักธงpos_sync_changeทำเมื่อเป็นsmldemoและผู้ให้บริการไม่ใช่it(:469-482) - ทุก handler เรียก
ensureSchemaAndSeed(pos/handler.go:54) ก่อนทำงาน ถ้าพลาดแค่ log ระดับ debug
อ่านหน้าตั้งค่า GET /pos/bootstrap (Bootstrap handler.go:60)
รวมหลาย SELECT ใน batch เดียวผ่าน use case Batch แล้วตอบ {ok, pos_config, pos_machines, qr_config, point_condition, promotions, coupons, member_groups, products, settlements, recent_bills, temp_members} (:227-239) ตัวจำกัดจำนวน: คูปอง 100 ล่าสุด, สินค้า 60 รายการแรก (เรียงรหัส), รายการรับ-ส่งเงิน 50 ล่าสุด, บิลล่าสุด 50 (จาก ic_trans), สมาชิกชั่วคราว 50 ล่าสุด ถ้าไม่มี QR/เงื่อนไขแต้มในฐาน จะตอบค่าเริ่มต้นในโค้ด (เช่น baht_per_point 25.00, points_per_baht_redeem 10.00, min_redeem_points 100.00; :161-186) เงินส่งเป็นข้อความ (::text)
บันทึกตั้งค่า POST /pos/config (SavePosConfig :493)
- body JSON อ่านด้วย
UseNumberไม่เกิน 1 MiB (decodeJSONMapUseNumberhandler.go:288) เลือกหมวดจากsection(ค่าเริ่มต้นstartup) ทำทั้งหมวดใน transaction เดียว หมวดที่ไม่รู้จัก = error "ไม่รู้จักหมวดตั้งค่า POS: ..." - ตัวเลขเงิน/อัตรา อ่านผ่าน
posDec(:1259) ซึ่งรับสตริงหรือjson.Numberโดยไม่ผ่านfloat64(ตามกฎ ACCOUNTING NUMBER) - หมวดและตารางที่เขียน:
sectionเขียนลง สาระ startupposconfig(upsert ตามpos_config_number)ชื่อร้าน/สาขา/เลขผู้เสียภาษี, ลูกค้าเริ่มต้น cust_code_default, ส่วนลดสมาชิก,max_pos_money,vat_type/vat_rate,service_charge_rate, หัว-ท้ายใบเสร็จ, สิทธิ์แก้ราคา/ส่วนลด/ยกเลิกบิลmachine,machinespos_id(upsert ตามmachinecodeตัวพิมพ์ใหญ่)รหัสเครื่อง, รูปแบบเลขที่เอกสาร ( doc_format,doc_format_vat_full,doc_format_cancel,doc_format_fillmoney,doc_format_cashiersettle), คลัง/ที่เก็บ (pos_ic_wht,pos_ic_shelf), สาขา/แผนก, ชนิดราคาprice_number, เครื่องพิมพ์/จอลูกค้า/ลิ้นชัก; ต้องมีmachinecodeและdoc_formatผ่านcheckPosDocFormatUnique(มี#และไม่ซ้ำเครื่องอื่น ดู POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync))qrerp_thai_qr_config(แถวpos_id = 'ALL')พร้อมเพย์/วอลเล็ต/ชื่อร้านค้า/รหัสผู้ให้บริการ pointpos_point_conditionบาทต่อแต้ม, แต้มต่อบาทที่แลก, แต้มขั้นต่ำที่แลก, ตัวคูณเดือน/วันเกิด, เกณฑ์ระดับ VIP couponcoupon_list(upsert ตามnumberตัวพิมพ์ใหญ่)มูลค่า, ยอดคงเหลือ, วันหมดอายุ, ใช้ครั้งเดียว, ลูกค้า coupon_batchcoupon_listสร้างคูปองหลายใบ ( count1-50; ค่าเริ่มต้น 5), เลขที่<prefix>-<ลำดับ>; ถ้าไม่ส่งdate_expireใช้ค่าคงที่ในโค้ด2026-12-31(:793; โปรโมชันdate_endและคูปองเดี่ยว :770, :935 ใช้ค่าเดียวกัน)promotionpos_promotionsดูด้านล่าง promotion_togglepos_promotions.is_activeเปิด/ปิดตาม promo_codepromotion_deletepos_promotionsลบตาม promo_code - โปรโมชัน:
promo_type_codeแปลงเป็นชื่อชนิด (pTypeStr) ตามโค้ด (1,3BUY_X_GET_Y; 2,5BUNDLE_QTY; 4SPECIAL_PRICE; 6SPEND_GET_ITEM; 7STEP_SPEND(ค่าเริ่มต้น); 8MEMBER_TIER; 101HOUSE_BRAND_COUPON; 102TIER_REDEMPTION) ฟิลด์ที่เขียน เช่นmin_qty,min_spend,discount_amount,discount_pct,free_qty,strict_unit_ratio,allow_mix_match,auto_add_free_item,max_qty_per_bill,customer_only, ช่วงวัน/เวลา,day_filter,items_include_json, สินค้าของแถม (:811-945) - การเปลี่ยนในตาราง
pos_id,pos_promotions,coupon_list,posconfigและอื่น ๆ ถูกจับโดย trigger ของระบบซิงก์ จึงถึงเครื่อง POS ในรอบsyncถัดไป ดู POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync) - ฟิลด์ที่ไม่ส่งมาในหมวด
machineใช้ค่าเริ่มต้นที่เขียนในโค้ด (เช่น คลังMMA01ที่เก็บSH-01สาขา00000แผนกSALE) -- ยังไม่ยืนยันว่า upsert เขียนทับทุกคอลัมน์ด้วยค่าเริ่มต้นเมื่อไม่ส่ง
กะขายและรับ-ส่งเงิน POST /pos/shift (PosShiftAction :974)
action(ค่าเริ่มต้นreceive_money), วัน/เวลาเริ่มต้นเป็นเวลาเซิร์ฟเวอร์ปัจจุบัน; ถ้าเรียกจากเครื่อง POS จริง รหัสเครื่องถูกบังคับเป็นเครื่องของโทเคน (devMachine) ไม่ใช้ค่าจาก body (:988-990); ไม่มีรหัสเครื่อง = error "ต้องระบุรหัสเครื่อง POS" (ยกเว้นreconcile_temp_member)actionผล receive_money,open_shiftเปิดกะใน pos_periodถ้าเครื่องนี้ยังไม่มีกะค้าง (period_status = 0) แล้วบันทึกรับเงินทอนเข้าลิ้นชักในposcashiersettle(trans_type = 1); เลขเอกสารไม่ระบุ =RCV-<ปีเดือน>-<เลขสุ่มจากเวลา>send_money,close_shiftclose_shiftปิดกะที่เปิดอยู่ (period_status = 1, บันทึกวันเวลาปิดและผู้ปิด) แล้วบันทึกนำส่งเงินposcashiersettle(trans_type = 2) แยกเงินสด/บัตร/คูปอง/โอน ยอดรวมคำนวณจากส่วนประกอบ ถ้ารวมได้ 0 ใช้total_amountที่ส่งมา; เลขเอกสารไม่ระบุ =SND-...cancel_billส่งต่อ CancelPosBillดู POS รับบิลขายจากเครื่องแคชเชียร์ กล่องรับบิล/ประมวลผล/ยกเลิก/ตัดสต็อกเป็นชุด (POS Bill Inbox); ต้องระบุdoc_no(เหตุผลเริ่มต้น "ลูกค้าขอยกเลิกบิล / คีย์รายการผิด")upload_temp_membersอัปโหลดสมาชิกชั่วคราวที่สร้างตอน offline ลง pos_temp_members(คีย์เบอร์โทร ข้ามแถวไม่มีเบอร์; แถวที่RECONCILEDแล้วไม่ถูกแก้; สถานะเริ่มPENDING)reconcile_temp_memberตั้งสถานะ RECONCILEDพร้อมรหัสสมาชิกปลายทาง/กลุ่ม แล้วสร้างar_customerใหม่ถ้ายังไม่มีรหัสนั้น (ไม่ระบุรหัส =AR-+ เบอร์โทร)- เลขเอกสารรับ/ส่งเงินที่ซ้ำ (
docno) จะอัปเดตแถวเดิม (ON CONFLICT (docno) DO UPDATE) -- ส่งซ้ำได้ผลเดิม - action อื่น = error "ไม่รู้จักคำสั่งกะขาย: ..."
- พื้นฐานจากโค้ด C# ตามคอมเมนต์:
_periodOpenForm.cs:123(เปิดกะเฉพาะเมื่อไม่มีกะเปิด) และ_moneyReceive.cs:79-81(บันทึกรับเงิน) ที่pos_config.go:1020-1022
ข้อสังเกตจากโค้ด (ยังไม่ยืนยันผลกระทบในใช้งานจริง)
- ค่าคงที่วันหมดอายุคูปอง
2026-12-31, ค่าเริ่มต้นรหัสสาขา00000และคลังMMA01ฝังในโค้ดของหมวดตั้งค่า (ไม่ได้อ่านจากตัวเลือกบริษัท) - สิทธิ์ผู้ใช้ระดับเมนูสำหรับ
/pos/configและ/pos/shiftไม่ได้ผ่านrouteRightsของ/process(ยังไม่ยืนยันว่ามีชั้นตรวจสิทธิ์อื่น)
ที่มาในโค้ด
backend/internal/application/process/pos_config.go:16-369-posConfigDDLbackend/internal/application/process/pos_config.go:371-488-EnsurePosTables,ensurePosTablesPool(ข้อมูลตัวอย่างเฉพาะsmldemo)backend/internal/application/process/pos_config.go:491-969-SavePosConfigทุกหมวด (startup:506,machine:587,qr:660,point:684,coupon:741,coupon_batch:779,promotion:811,promotion_toggle:946,promotion_delete:954)backend/internal/application/process/pos_config.go:972-1208-PosShiftActionbackend/internal/application/process/pos_config.go:1210-1285- ตัวช่วยfirstPresent,posStr,posInt,posDecbackend/internal/adapter/inbound/http/pos/handler.go:60-240-Bootstrapbackend/internal/adapter/inbound/http/pos/handler.go:243-296-SaveConfig,ShiftAction,decodeJSONMapUseNumberbackend/internal/adapter/inbound/http/router.go:329-348- ผูก/bootstrap,/config,/shift
ดูเพิ่ม
- POS ซิงก์ข้อมูลเครื่องแคชเชียร์ ผูกเครื่อง/ดึงส่วนต่าง/กู้คืน/รูปภาพ (POS Device Sync)
- POS รับบิลขายจากเครื่องแคชเชียร์ กล่องรับบิล/ประมวลผล/ยกเลิก/ตัดสต็อกเป็นชุด (POS Bill Inbox)
- เครื่องมือหาราคาและแก้ราคา (Price engine / price center / modify price)
- ข้อมูลหลักแบบหัว-รายการ รหัสอัตโนมัติ และเลย์เอาต์รายการ (Master-detail, code auto-run, DataList)
- ภาพรวมกลุ่ม process ของ Backend (Process overview)