#accounting#transaction#save#postgres#go
ลำดับการบันทึกเอกสาร (SaveTrans)
การบันทึกเอกสาร ic_trans ทุกชนิดผ่าน SaveTrans ซึ่งทำงานทั้งหมดใน PostgreSQL transaction เดียว (timeout 60 วินาที) แบบ "ลบแล้วเขียนใหม่" ของเอกสารนั้น จากนั้น rebuild สต็อก ต้นทุน GL และเช็ค ถ้าผิดพลาดที่ขั้นใด จะ rollback ทั้งหมด
ทำงานอย่างไร
1. เตรียมข้อมูลก่อนเปิด transaction (SaveTrans trans.go:267)
- หา branch ของผู้ใช้ (ใช้กับ 72 โอนออก), เงื่อนไขขายเงินสด/ตัดชำระ
autoLotsเติม lot ให้บรรทัดขาย 44 ของสินค้า lot (trans_lot_auto.go:32)normalizeItemLinesคำนวณราคา/VAT ระดับบรรทัด และแปลงสกุลเงิน (ดู การคำนวณยอดท้ายบิล VAT และส่วนลด (Document Totals / vatCalc), หลายสกุลเงินและกำไรขาดทุนจากอัตราแลกเปลี่ยน (Multi-Currency & FX Gain/Loss))buildTransArgs(trans.go:798) แปลง input เป็นค่าที่จะ insert
กฎใน buildTransArgs
doc_noแปลงเป็นตัวพิมพ์ใหญ่ ตัดช่องว่าง และยาวไม่เกิน 25 ตัวอักษรdoc_timeค่าว่าง =08:00vat_ratescale 2,exchange_ratescale 6 (ค่าว่าง = 1)- ยอดสุทธิติดลบ = error; เอกสารยอดหัว (
headerAmountFlags) ต้องมียอดมากกว่า 0 - qty หรือยอดติดลบได้เฉพาะ flag 66; ราคาติดลบไม่ได้
- qty และ price scale 4; ยอดบรรทัด scale =
item_amount_decimal
ตัวเลขทุกช่องผ่าน decimalParser.arg (trans.go:1214): ตัด comma, ค่าว่าง = "0", ต้องตรง regex ^-?\d{1,15}(\.\d+)?$ แล้วปัด HALF_UP ตาม scale
2. ใน transaction (inTransTx trans.go:446)
checkAndSaveTransTx (trans.go:301) เรียงตามนี้
checkTransScreenSave(trans_validate.go:43): งวดบัญชีเปิด, เอกสารไม่ถูก lock, แก้ไขได้, คู่ค้ามีจริง, ยอดอ้างอิง, กฎ erp_option (ดู ด่านตรวจก่อนบันทึกเอกสารและวงเงินเครดิต (Save Rules & Credit Limit), งวดบัญชีและด่านตรวจงวดปิด (Accounting Period Guard))checkTaxDocNoเลขใบกำกับภาษีห้ามซ้ำ (ดู ทะเบียนภาษีซื้อ/ภาษีขาย และภาษีหัก ณ ที่จ่าย (VAT Register & WHT))checkHeldItems,checkRefDocItemssaveTransTx(trans.go:510)
3. saveTransTx (trans.go:510)
- ล็อกเอกสาร
lockTransDoc(trans.go:473) =pg_advisory_xact_lock(hashtext("ic_trans:<doc>:<flag>"))และล็อกสินค้าlockStockItems(service.go:992) โดยเรียงรหัสสินค้าก่อนล็อกเพื่อกัน deadlock - เอกสารใหม่ (
IsNew) ที่เลขซ้ำ = error "เลขที่เอกสารซ้ำ" - DELETE
ic_trans_serial_number,ic_trans_shipment,ic_trans_detail,ic_transของเอกสารนี้ - INSERT หัว
ic_trans(total_value,total_except_vat,discount_word,total_discount,advance_amount,total_before_vat,total_vat_value,total_after_vat,total_amount,exchange_rate,last_status= 0,tax_doc_noค่าเริ่มต้น = doc_no) - INSERT บรรทัด
ic_trans_detail(calc_flag,price_exclude_vat,sum_amount_exclude_vat,average_cost,sum_of_cost,is_lock_cost,sum_of_cost_fix,qty_2,unit_code_2ฯลฯ) - แท็บจ่าย
cb_trans/cb_trans_detailต้องเขียนก่อน GL (ดู แท็บรับ/จ่ายเงิน และการชำระหนี้ตามบิล (Payment Tab & Bill Settlement)) - VAT/WHT, มัดจำ แล้วตรวจ
checkDepositUseและrunTxChecks(ตรวจจากแถวที่เพิ่งเขียน) - POS ที่เลื่อนการตัดสต็อก:
queuePosStock docFlowTx,rebuildSerialTx, แล้วrebuildTransDerived
4. rebuildTransDerived (trans.go:593)
rebuildStockTxเฉพาะสินค้าในเอกสาร (ถ้ารายการว่างจะข้าม เพราะรายการว่างหมายถึง rebuild ทั้งหมด)SyncTransferPairเมื่อเป็น 422rebuildGLTxของเอกสารนี้ (ล็อก GL แบบ shared ด้วยlockGLSharedservice.go:1370)syncStockTransferInเมื่อเป็น 72RebuildChequeStatusเมื่อเป็น flag เช็ค (405-418, 451-456, 461-463)
กรณีพิเศษ
- 72 โอนสินค้า: เขียนบรรทัดออก (72, calc -1, คลังเริ่มต้น "01") และบรรทัดเข้า (70, calc +1, คลังเริ่มต้น "02", เวลา +1 นาที)
- 422 โอนเงิน: ต้องมีสมุดบัญชีปลายทางที่ไม่ใช่บัญชีเดียวกัน;
transfer_amountว่าง = ยอด - ค่าธรรมเนียม CreditApprovePasswordไม่ถูก echo กลับหรือเขียน log (comment ในSaveTransInput)
ที่มาในโค้ด
backend/internal/application/process/trans.go:267SaveTransbackend/internal/application/process/trans.go:301checkAndSaveTransTxbackend/internal/application/process/trans.go:446inTransTxbackend/internal/application/process/trans.go:473lockTransDocbackend/internal/application/process/trans.go:510saveTransTxbackend/internal/application/process/trans.go:593rebuildTransDerivedbackend/internal/application/process/trans.go:798buildTransArgsbackend/internal/application/process/trans.go:1214decimalParser.argbackend/internal/application/process/service.go:992lockStockItemsbackend/internal/application/process/trans_validate.go:43checkTransScreenSave