ต้นทุนสินค้าคิดแบบไหน ถัวเฉลี่ยเคลื่อนที่คำนวณยังไง
ตอบสั้น: ระบบคิดต้นทุนแบบถัวเฉลี่ยเคลื่อนที่ (Moving Average) กับสินค้าทุกตัว โดยไล่บรรทัดเคลื่อนไหวของสินค้าตามวันที่และเวลา รายการรับเข้าจะคำนวณต้นทุนเฉลี่ยใหม่จากมูลค่าสะสมหารจำนวนสะสม ส่วนรายการจ่ายออกจะตัดมูลค่าเท่ากับจำนวนคูณต้นทุนเฉลี่ย ณ ขณะนั้น ผลลัพธ์บันทึกไว้ที่ ic_trans_detail.sum_of_cost, ic_trans_detail.average_cost และ ic_inventory.average_cost
รายละเอียด
ฟังก์ชันที่คำนวณคือ CalculateMovingAverage มันคำนวณด้วยเลขเศษส่วนแบบแม่นยำ (big.Rat) แล้วปัดแบบ HALF_UP ในแต่ละบรรทัด จำนวนทศนิยมมาจาก erp_option.item_price_decimal (ต้นทุนต่อหน่วย) และ item_amount_decimal (มูลค่า) ถ้าไม่ได้ตั้งไว้จะใช้ 2 ตำแหน่ง และรับค่าได้ 1–6 ตำแหน่ง
จำนวนฐาน: แต่ละบรรทัดแปลงเป็นหน่วยนับหลักก่อนด้วยสูตร qty × stand_value ÷ divide_value ถ้าค่าใดเป็น 0 หรือติดลบจะถือว่าเป็น 1 (ดู ขายเป็นกล่อง/โหล แต่สต็อกนับเป็นชิ้น ระบบแปลงหน่วยยังไง)
ลำดับการไล่รายการ: เรียงตามรหัสสินค้า แล้วตาม doc_date_calc (ถ้าไม่มีใช้ doc_date), ตาม doc_time_calc/doc_time, ตาม calc_flag จากมากไปน้อย (ถ้าวันเวลาเดียวกัน รายการรับจะมาก่อนรายการจ่าย และโอนเข้า 70 ถูกบังคับไปอยู่ท้ายสุด), แล้วตาม trans_flag, doc_no และ line_number
รายการรับเข้า (calc_flag บวก)
- มูลค่ารับเข้าคือ
sum_amount_exclude_vatถ้าเป็น 0 ใช้sum_amountถ้ายังเป็น 0 ใช้sum_of_costเดิม และถ้ายังไม่มีอีกใช้qty × price - ปรับปรุงเพิ่ม 66 ที่มีจำนวน และ
inquiry_typeไม่ใช่ 1: เข้าที่ต้นทุนเฉลี่ยปัจจุบัน ไม่ใช้ราคาที่พิมพ์ - รับคืนจากการขาย 48: เข้าที่ต้นทุนเฉลี่ยปัจจุบัน (ถ้าต้นทุนเฉลี่ย >0) ไม่ใช้ราคาขาย เพื่อไม่ให้กำไรขั้นต้นปนเข้าไปในต้นทุน
- 58/60 ที่ไม่มีมูลค่า: เข้าที่ต้นทุนเฉลี่ยปัจจุบัน
- ถ้าจำนวนสะสมก่อนรับเข้า ≤0 ระบบเริ่มนับใหม่จากรายการรับนี้ ประวัติตอนติดลบจะถูกทิ้ง (ดู ทำไมสต็อกติดลบได้ และตั้งห้ามติดลบที่ไหน)
- บรรทัดที่จำนวนเป็น 0 เช่น ต้นทุนแฝง (ค่าขนส่ง ค่าอากรขาเข้า (ต้นทุนแฝง / Landed Cost) เข้าต้นทุนสินค้ายังไง) จะเพิ่มเฉพาะมูลค่า แล้วคำนวณต้นทุนเฉลี่ยใหม่
รายการจ่ายออก (calc_flag ลบ)
- มูลค่าจ่ายออก = จำนวนฐาน × ต้นทุนเฉลี่ย ปัดตามจำนวนทศนิยมของมูลค่า
- ส่งคืนผู้จำหน่าย 16 ใช้ยอดเงินในเอกสารถ้ามีค่า
- 68/311 ที่จำนวนเป็น 0 ตัดเฉพาะมูลค่าตาม
sum_amount - 66 ที่จำนวนติดลบนับเป็นการจ่ายออก
- บรรทัดที่ล็อกต้นทุน (
is_lock_cost) ใช้sum_of_cost_fixตามที่ระบุไว้ - หลังจ่ายออกแล้ว ถ้าจำนวนสะสม ≤0 มูลค่าสะสมจะถูกตั้งเป็น 0 แต่ต้นทุนเฉลี่ยยังเป็นค่าเดิม
โอนย้าย 72/70: ไม่เปลี่ยนต้นทุนเฉลี่ยของสินค้า ดู โอนสินค้าระหว่างคลัง/ที่เก็บ (72/70) ทำงานยังไง ต้นทุนเปลี่ยนไหม
ภาพรวมเชิงบัญชีอยู่ที่ ต้นทุนสินค้าแบบถัวเฉลี่ยเคลื่อนที่ (Moving Average Cost) และ เคลื่อนไหวสต็อกและต้นทุน (Stock Movement & Costing)
ข้อควรระวัง
- ช่อง "ประเภทต้นทุน" (
cost_type) ในการ์ดสินค้าไม่มีผลต่อการคำนวณ ทุกตัวคิดแบบถัวเฉลี่ย (ดู ตั้งประเภทต้นทุนเป็น FIFO / LOT / มาตรฐาน ได้ไหม ระบบคิดตามที่ตั้งหรือเปล่า) - เอกสารปรับปรุงเพิ่ม 66 ที่มีจำนวน: มูลค่าสต็อกคิดจากจำนวน × ต้นทุนเฉลี่ย แต่ GL มาตรฐานเดบิตสินค้าคงเหลือด้วยยอดรวมหัวเอกสาร ทั้งสองจึงอาจไม่เท่ากัน โค้ดเขียนไว้ว่าเป็นช่องว่างที่รอลุงจืดตัดสิน (
service.go:2153) - ขั้นเติม
sum_of_costให้บรรทัด 58 ที่ไม่มีราคา ใช้ROUND(...,2)ตายตัว ไม่ได้ใช้จำนวนทศนิยมจากerp_option(service.go:1052)
ดูเพิ่ม
- ต้นทุนสินค้าแบบถัวเฉลี่ยเคลื่อนที่ (Moving Average Cost)
- ทำไมต้นทุนของเอกสารเก่าเปลี่ยนเอง ทั้งที่ไม่ได้แก้เอกสารนั้น
- คำนวณยอดสต๊อกใหม่ (Rebuild Stock) ทำอะไรบ้าง ต้องกดเมื่อไหร่
- ทำไมสต็อกติดลบได้ และตั้งห้ามติดลบที่ไหน
- ตั้งประเภทต้นทุนเป็น FIFO / LOT / มาตรฐาน ได้ไหม ระบบคิดตามที่ตั้งหรือเปล่า
- ยอดคงเหลือและต้นทุนสินค้า (Stock Balance and Costing, rebuildStockTx)
ที่มาในโค้ด
backend/internal/application/process/service.go:189CalculateMovingAverageคำนวณจำนวนฐาน รับเข้า และจ่ายออกbackend/internal/application/process/service.go:26866, 48 และ 58/60 เข้าที่ต้นทุนเฉลี่ยbackend/internal/application/process/service.go:286จำนวนสะสม ≤0 ให้เริ่มนับใหม่จากรายการรับbackend/internal/application/process/service.go:327หลังจ่ายออกจนจำนวน ≤0 ตั้งมูลค่าสะสมเป็น 0backend/internal/application/process/service.go:974อ่านitem_price_decimal/item_amount_decimalbackend/internal/application/process/service.go:1162ลำดับการไล่รายการเคลื่อนไหว