ยอดคงเหลือและต้นทุนสินค้า (Stock Balance and Costing)
ยอดคงเหลือและต้นทุนเป็นผลลัพธ์ที่สร้างใหม่ได้ (Rebuildable Derived Results) จากรายการดิบใน ic_trans_detail ตามหลัก Raw Data → Process → Derived (AGENTS.md ข้อ 9) ฟังก์ชันหลักคือ rebuildStockTx ใน backend/internal/application/process/service.go:1007 ส่วนหน่วยนับขนานและการดึงเอกสารอ้างอิงดู หน่วยนับขนาน Serial และการดึงเอกสารอ้างอิง (Parallel Unit, Serial, Ref Document Import)
ตารางหลัก
| ตาราง | หน้าที่ | คอลัมน์สำคัญ |
|---|---|---|
ic_inventory |
ทะเบียนสินค้า (เมนู P0017) |
unit_type, cost_type, unit_cost, balance_qty, balance_qty_2, average_cost, item_type |
ic_trans_detail |
รายการสินค้าในเอกสารทุกประเภท | trans_flag, calc_flag, qty, stand_value, divide_value, sum_amount, sum_of_cost, average_cost, is_lock_cost, sum_of_cost_fix, last_status |
ic_serial, ic_trans_serial_number |
Serial Number คงเหลือ / ผูกกับเอกสาร | ic_code, serial_number, status (0 = ว่างในคลัง, 1 = ขาย/เบิกแล้ว) |
ค่า cost_type ตาม KMS: 0 = Avg, 1 = FIFO, 2 = Lot/Expire, 3 = Serial
กฎ/วิธีทำ
- คำนวณยอดคงเหลือจากรายการดิบเท่านั้น ห้ามแก้
ic_inventory.balance_qtyตรง ให้เรียกPOST /process/stock/rebuild({ itemCodes: [...] }) ซึ่งทำใน Transaction เดียว - สูตรยอดคงเหลือ (service.go ขั้นตอน "Step 2", ราว :1066)
balance_qty = SUM(qty × calc_flag × stand_value / divide_value)(หน่วยมาตรฐานบัญชี;stand_value/divide_valueเป็น 0 หรือว่างให้ถือเป็น 1)balance_qty_2 = SUM(COALESCE(qty_2, 0) × calc_flag)(หน่วยขนานเพื่อตรวจนับจริง)- อัปเดตกลับ
ic_inventoryเฉพาะแถวที่ค่าเปลี่ยน (IS DISTINCT FROM) และไม่รวมสินค้าบริการ (item_type = 5)
- แถวที่นับเป็นสต็อกจริง กำหนดที่
stock_rebuild.go:18-29:last_status = 0, ไม่ใช่สำเนาเอกสาร (is_doc_copy),item_type IN (0,4,6),trans_flagอยู่ในรายการที่เคลื่อนไหวสต็อก และตัดบรรทัดที่ปรับเฉพาะมูลค่า (trans_flag IN (14,16,311)ที่inquiry_type IN (1,3)) ออกจากจำนวน — ภาคแสดงนี้ละเอียดกว่าสูตรสั้นใน KMS (ซึ่งกล่าวถึงis_posและcalc_flag IN (1,-1)) ให้ยึดโค้ด - กันชนกัน: ล็อกรายสินค้าด้วย
pg_advisory_xact_lock(lockStockItems) เรียงตามรหัสเพื่อกัน deadlock; ถ้าไม่ระบุสินค้าจะล็อกทั้งงาน (stockRebuildLock) - ต้นทุน: ดึงรายการเคลื่อนไหวของสินค้าที่เกี่ยวข้องรอบเดียว (ไม่วนคิวรีรายสินค้า) แล้วคำนวณรายสินค้าใน Go ด้วย
*big.Ratปัดแบบ HALF_UP (RoundHalfUp) ตามทศนิยมของerp_option.item_price_decimal/item_amount_decimal(ค่าเริ่มต้น 2, ช่วงที่ยอมรับ 1-6 —stockScales) จากนั้นเขียนเฉพาะแถวที่ต้นทุนเปลี่ยนกลับic_trans_detailด้วยUPDATE ... FROMแบบกลุ่ม - ต้นทุนเฉลี่ย (
CalculateMovingAverage, service.go:189) ไล่ตามลำดับเอกสาร- ขาเข้า (ซื้อ 12, ยกมา 54, รับคืนจากลูกค้า 46, ปรับเข้า 58/66 ฯลฯ) รวมมูลค่าแล้วหารจำนวนได้ราคาเฉลี่ยใหม่; ขาออกใช้ราคาเฉลี่ยปัจจุบัน
- บรรทัดปรับสต็อก
66ที่จำนวนติดลบถือเป็นขาออกที่ราคาเฉลี่ย (ตามคอมเมนต์ใน C#_icInfoFlag._outFlag) - โอนระหว่างคลัง
72(ออก) /70(เข้า) ไม่เปลี่ยนจำนวนและมูลค่ารวมของสินค้า: ขา 72 บันทึกจำนวน × ราคาเฉลี่ย แล้วขา 70 รับต้นทุนเดียวกันไป - บรรทัดที่ล็อกต้นทุน (
is_lock_cost = 1) ใช้sum_of_cost_fixแทนต้นทุนที่คำนวณ
- ต้นทุนคิดจากหน่วยมาตรฐานบัญชี (
qty × stand_value / divide_value) เท่านั้น ส่วนqty_2ผู้ใช้กรอกแยกอิสระ ห้ามผูกสูตรคูณตายตัวทับค่าที่กรอก - ตัวเลขเงินทุกค่าใช้ decimal/
big.Ratห้าม float ตามกฎบัญชีของโปรเจกต์ (ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch))
ข้อควรระวัง: เอกสารกับโค้ดไม่ตรงกัน (ตรวจแล้ว)
- KMS กล่าวถึง "Incremental Dirty-Date + Topological Wave Costing" (
min_dirty_date, Wave 0/1+, ไฟล์stock_cost.goและic_cost_tier.go) — ไม่พบไฟล์เหล่านี้ และค้นหาmin_dirty/ProcessStockCostในโค้ด backend ไม่พบ กลไกจริงคือrebuildStockTxที่คำนวณซ้ำทุกเอกสารของสินค้าที่ระบุ CalculateFIFOCost(service.go:355, คิว FIFO แบบ O(N)) มีอยู่แต่ค้นไม่พบการเรียกใช้นอกไฟล์ทดสอบ (stock_speed_bench_test.go);rebuildStockTxเรียกCalculateMovingAverageทุกสินค้า และcost_typeถูกใช้ในทะเบียนสินค้า รายงาน และกติกาบันทึก/Lot (item_master.go,trans_save_rules.go,trans_lot_auto.go,report_menu_ic.go) แต่ไม่ได้ใช้เลือกสูตรใน rebuild — ก่อนอ้างว่า FIFO ทำงานจริงต้องถามลุงจืดหรือตรวจเพิ่ม- KMS อ้าง
service.go#L1065-L1122สำหรับrebuildStockTxซึ่งปัจจุบันเริ่มที่บรรทัด 1007 และยาวกว่านั้น
ที่มา
docs/kms/KMS_INVENTORY_COSTING_SERIAL_PARALLEL_UNIT.md§1–§2.agents/skills/inventory-costing-and-parallel-unit/SKILL.mdWorkflow ข้อ 2, Config, Limitation- โค้ดจริง:
backend/internal/application/process/service.go,stock_rebuild.go
ดูเพิ่ม
สารบัญมาตรฐานและกฎเหล็กของ SML Ai Account (Standards Overview) · หน่วยนับขนาน Serial และการดึงเอกสารอ้างอิง (Parallel Unit, Serial, Ref Document Import) · ความถูกต้องของข้อมูล: เงิน ภาษี Transaction เดียว และ Rebuild (Data Integrity, big.Rat, ExecBatch) · ภาพรวมระบบบัญชี SML AI Account (Accounting Overview) · ภาพรวม Backend Go ของ SML Ai Account (Backend overview)