ต้นทุนแฝง/ต้นทุนนำเข้า (ic_hidden_cost_process, _ref, _item)
หน้าที่: เอกสาร "ต้นทุนแฝง & ต้นทุนนำเข้าต่างประเทศ (Landed Cost, TAS 2)" เมนู 2.22 — เอาค่าใช้จ่ายที่เกี่ยวกับการซื้อ (ค่าขนส่ง ประกัน อากร ชิปปิ้ง และเอกสารตั้งหนี้อื่น/ค่าใช้จ่ายอื่น) ไปกระจายเข้าต้นทุนของสินค้าในเอกสารซื้อ/รับสินค้า ผลคือ ใบปรับปรุงต้นทุนแบบมูลค่าอย่างเดียว (ic_trans trans_flag = 66, doc_ref = เลขที่เอกสารต้นทุนแฝง) ซึ่งทำให้ rebuild สต๊อกบวกส่วนแบ่งเข้าต้นทุนสินค้า (hidden_cost.go:15-21) ดู ต้นทุนสินค้าแบบถัวเฉลี่ยเคลื่อนที่ (Moving Average Cost) และวิธีคำนวณที่ ต้นทุนแฝง เฉลี่ยค่าใช้จ่ายเข้าสินค้า (Hidden Cost, เมนู 2.22)
เป็น 3 ตารางที่ผูกกันด้วย doc_no (ไม่มี trans_flag — doc_cancel.go:437):
ชนิดข้อมูลในวงเล็บ = ชนิดที่ ensureHiddenCostImportCols (hidden_cost.go:416-439) ใช้ตอนเพิ่มคอลัมน์ที่ยังไม่มี ถ้าฐานเดิมมีคอลัมน์ชื่อนั้นอยู่แล้ว ชนิดเดิมคงอยู่
1) หัว ic_hidden_cost_process (INSERT hidden_cost.go:534-546)
| column | ความหมาย |
|---|---|
doc_no, doc_date, doc_time, doc_format_code, branch_code, remark |
เลขที่/วันที่/รูปแบบเลขที่ (erp_doc_format — รูปแบบ/ชนิดเอกสารและเลขที่รัน) / สาขา / หมายเหตุ |
total_amount |
ค่านำเข้าที่กรอกตรง + ผลรวมมูลค่าสุทธิ (ic_trans.total_amount) ของเอกสารค่าใช้จ่าย ไม่ขึ้นกับ cal_hidden_cost_from (hidden_cost.go:226-229, :280) |
hidden_cost_amount (NUMERIC(18,2)) |
ยอดที่ปันส่วนจริง = ค่านำเข้าที่กรอกตรง + เอกสารค่าใช้จ่ายแบบสุทธิหรือก่อนภาษีตาม cal_hidden_cost_from ($6, hidden_cost.go:227-235, :281, :541) |
doc_no_adjust, doc_format_code_adjust |
เลขที่และรูปแบบของใบปรับปรุงต้นทุนที่สร้างคู่กัน (ic_trans flag 66) |
cal_hidden_cost_from |
0 = ใช้มูลค่าสุทธิ, 1 = มูลค่าก่อนภาษี (hidden_cost.go:51) |
cal_hidden_cost_follow |
วิธีเฉลี่ย: 0 ตามมูลค่าสินค้า, 1 ตามจำนวน, 2 ตามน้ำหนักจริง/หน่วยขนาน (qty_2), 3 เท่ากันทุกรายการ (hidden_cost.go:52) |
customs_entry_no (VARCHAR(50)), vessel_container_no (VARCHAR(100)) |
เลขที่ใบขนสินค้าขาเข้า, เรือ/เที่ยวบิน/ตู้คอนเทนเนอร์/ทะเบียนรถ (ตัดช่องว่างหัวท้าย hidden_cost.go:283-284) |
incoterms (VARCHAR(20) ค่าเริ่ม 'CIF'), currency_code (VARCHAR(10) ค่าเริ่ม 'THB') |
Incoterms และสกุลเงิน แปลงเป็นตัวพิมพ์ใหญ่ ว่าง = CIF / THB (hidden_cost.go:285-286) |
exchange_rate (NUMERIC(18,6) ค่าเริ่ม 1) |
อัตราแลกเปลี่ยน ($17); ว่างหรือ <= 0 = 1 (hidden_cost.go:276-279); เก็บไว้เท่านั้น ไม่ได้คูณยอดใด |
transport_value (NUMERIC(18,2)) |
ค่าขนส่ง/ระวาง ($18) |
insurance_amount, import_duty_amount, clearance_port_amount (NUMERIC(18,2)) |
ค่าประกัน, อากรขาเข้า, ชิปปิ้ง/พิธีการ/ท่าเรือ (ต้นทุนนำเข้าตรง ปัด HALF_UP 2 ตำแหน่งก่อนเก็บ hidden_cost.go:288-291) |
create_date_time_now |
เวลาสร้าง |
2) เอกสารอ้างอิง ic_hidden_cost_process_ref (INSERT hidden_cost.go:560-566)
| column | ความหมาย |
|---|---|
doc_no |
เลขที่ต้นทุนแฝง (หัว) |
ref_type |
trans_flag ของเอกสารที่อ้าง |
doc_ref_type |
index ของชนิดในกริด: ค่าใช้จ่าย 87 = 0, 260 = 1; เอกสารซื้อ 12 = 0, 310 = 1, 60 = 2 (hidden_cost.go:31-32) |
doc_ref_no, doc_ref_date, doc_ref_amount |
เอกสารที่อ้าง วันที่ และ ic_trans.total_amount |
amount_before_vat |
ยอดก่อนภาษี (เฉพาะแถวค่าใช้จ่าย; แถวซื้อเป็น 0 — hidden_cost.go:552-553) |
ฝั่งค่าใช้จ่ายคือ 87 (ตั้งหนี้อื่นๆ เจ้าหนี้) และ 260 (ค่าใช้จ่ายอื่นๆ); ฝั่งซื้อคือ 12 (ซื้อสินค้า), 310 (รับสินค้า), 60 (รับสินค้าสำเร็จรูป) — ทั้งหมดอยู่ใน หัวเอกสารสินค้า/ซื้อ/ขาย (ic_trans); เพดาน hiddenCostRefCap = 200 เอกสารต่อฝั่ง
3) รายการสินค้า ic_hidden_cost_process_item (INSERT hidden_cost.go:577-586)
| column | ความหมาย |
|---|---|
doc_no, line_number |
เลขที่ต้นทุนแฝง, ลำดับ (เริ่ม 0 จาก ORDINALITY − 1) |
billing_no, billing_date |
เลขที่/วันที่เอกสารซื้อที่สินค้ามาจาก |
item_code, wh_code, shelf_code, unit_code, remark |
สินค้า คลัง ที่เก็บ หน่วย หมายเหตุ (ทะเบียนสินค้า (ic_inventory), คลังสินค้า (ic_warehouse), พื้นที่เก็บสินค้า (ic_shelf)) |
qty |
จำนวน |
qty_2, weight (NUMERIC(18,4)) |
น้ำหนักจริง/หน่วยนับขนาน จาก ic_trans_detail.qty_2 (ว่าง = 0) เขียนค่าเดียวกันทั้งสองคอลัมน์ (v.q2 ทั้งคู่ hidden_cost.go:571, :581) — weight ไม่ใช่น้ำหนักที่ใช้ปันส่วนจริง: วิธีอื่นใช้มูลค่า/จำนวน/1 และวิธีน้ำหนักเมื่อ qty_2 = 0 ใช้ qty แทน (:240-253) แต่ weight ยังเก็บ qty_2 |
item_value |
ราคาซื้อต่อหน่วย (ic_trans_detail.price) |
item_amount, sum_amount (NUMERIC(18,2) เฉพาะ sum_amount) |
มูลค่าสินค้าเดิม = qty x price; Go ส่งค่าแบบไม่ปัด (hidden_cost.go:362) เขียนทั้งสองคอลัมน์ — คนละความหมายกับ sum_amount ของบรรทัดใบ 66 ที่เป็นส่วนแบ่ง |
adjust_amount, hidden_cost_amount (NUMERIC(18,2) เฉพาะ hidden_cost_amount) |
ส่วนแบ่งต้นทุนแฝงที่เฉลี่ยให้บรรทัด เขียนค่าเดียวกันทั้งสองคอลัมน์ (ใบ 66 บันทึกบรรทัดนี้ด้วย qty = 0, price = 0, sum_amount = adjust_amount — hidden_cost.go:504-507) |
ratio (NUMERIC(10,4)) |
สัดส่วนการเฉลี่ยเป็น เปอร์เซ็นต์ (0-100) ไม่ใช่อัตราส่วน 0-1 ปัด HALF_UP 2 ตำแหน่ง (hidden_cost.go:261-265, ชนิด :432) |
sum_total_amount (NUMERIC(18,2)) |
ต้นทุนรวมสุทธิ = มูลค่าเดิม + ส่วนแบ่ง ปัด HALF_UP 2 ตำแหน่ง (hidden_cost.go:266-268) |
average_cost (NUMERIC(18,4)) |
ต้นทุนใหม่ต่อหน่วย = (มูลค่าเดิม + ส่วนแบ่ง) / qty ปัด HALF_UP 4 ตำแหน่ง, qty <= 0 = 0 (hidden_cost.go:269-274) |
stand_value, divide_value |
อัตราแปลงหน่วย (0 ถือเป็น 1) |
กระบวนการ
- เขียน:
HiddenCostSave(hidden_cost.go:443) สร้างทั้งสามตาราง + ใบปรับปรุง 66 ใน transaction เดียว; เลขที่ว่าง = เลขถัดไปของชุด AFC (ใบปรับปรุงชุด IA) (hidden_cost.go:467,:489,doc_no_next.go:12) ปัดส่วนแบ่งที่ 2 ตำแหน่งทศนิยม (hiddenCostScale = 2,hidden_cost.go:25-26) เพื่อให้ยอดรวมส่วนแบ่งลงตัวกับsum_amountของใบ 66 - แก้ไข/ลบ: ลบใบปรับปรุงที่ผูกอยู่ (flag 66 ผ่าน
deleteTransTx) แล้วลบสามตารางตามลำดับ item → ref → หัว (dropHiddenCostTx,hidden_cost.go:392-414); ใบ 66 ถูกลบผ่านdeleteTransTxจึง rebuild สต๊อก/GL ให้อัตโนมัติ - คอลัมน์นำเข้า/ผลปันส่วน ถูกเพิ่มด้วย
ALTER TABLE … ADD COLUMN IF NOT EXISTSทุกครั้งที่บันทึก ภายใน transaction ของการบันทึก (ensureHiddenCostImportCols,hidden_cost.go:416-439เรียกที่:462): หัว 10 คอลัมน์customs_entry_no,vessel_container_no,incoterms,currency_code,exchange_rate,transport_value,insurance_amount,import_duty_amount,clearance_port_amount,hidden_cost_amount(:419-428); item 7 คอลัมน์weight,qty_2,ratio,sum_amount,hidden_cost_amount,sum_total_amount,average_cost(:430-436) — ฐานเก่าจึงอาจยังไม่มีจนกว่าจะบันทึกครั้งแรก (โครงสร้าง C#_g.dของสามตารางนี้ไม่มีคอลัมน์เหล่านี้ —D:\sml\SMLERPGlobal\_data.cs:44997-45185) - อ่าน: หน้าจอ
HiddenCostScreenอ่านทั้งสามตารางตรง (HiddenCostScreen.tsx:64-69,:74-82,:83-85,:86-94) หัวอ่านคอลัมน์เดียว เช่นcoalesce(exchange_rate, 1),coalesce(transport_value, 0)(:79-80); item ยังอ่านคู่คอลัมน์แบบสำรองกันcoalesce(NULLIF(qty_2,0), weight, 0)(:89),coalesce(NULLIF(item_amount,0), sum_amount, 0),coalesce(NULLIF(adjust_amount,0), hidden_cost_amount, 0)(:90),sum_total_amountว่าง/0 =item_amount + adjust_amount(:91);ratio,average_costอ่านตรง (:91-92)
ข้อควรระวัง
- ไม่มี
trans_flagในตารางนี้ เลขที่เอกสาร (doc_no) ต้องไม่ซ้ำภายในตารางเอง (rejectDuplicate,hidden_cost.go:479) - เป็นเอกสารที่ มีผลต่อต้นทุนสินค้า ผ่านใบ 66 เท่านั้น — ถ้าลบเฉพาะแถวในตารางนี้โดยไม่ลบใบ 66 ต้นทุนจะยังคงรวมส่วนแบ่งไว้
- ค่าเงินทุกช่องเป็น decimal ส่งเป็น string (กฎเหล็กข้อ 20)
- ฐานที่ยังไม่เคยบันทึกผ่านระบบนี้ (ยังไม่มีคอลัมน์ใหม่): รายการซ้ายเปิดได้เมื่อไม่ใส่คำค้น (SELECT ใช้แค่คอลัมน์เดิม
HiddenCostScreen.tsx:66-68) แต่ค้นด้วยคำค้นจะ error เพราะ WHERE อ้างcustoms_entry_no/vessel_container_no(:65) และเปิดเอกสารเก่าไม่ได้ เพราะ SQL ของloadDocอ้างคอลัมน์ใหม่ทั้งหัว (:78-81) และ item (:89-92) - ชื่อคอลัมน์เทียบมาตรฐาน (มาตรฐานตั้งชื่อ Database ตาราง และฟิลด์ PostgreSQL): ณ 2026-10-31 โค้ดใช้ชื่อมาตรฐานแล้ว (
exchange_ratehidden_cost.go:423,weight:430,ratio:432,average_cost:436) และไม่พบfx_rate/alloc_pct/new_unit_costในซอร์สโค้ดbackend/และfrontend/แล้ว; ชื่อหัว 6 ตัว (customs_entry_no,vessel_container_no,incoterms,insurance_amount,import_duty_amount,clearance_port_amount) ไม่อยู่ในรายการห้ามของ KMS และไม่พบใน_data.csรายละเอียดที่โน้ตมาตรฐาน
ที่มาในโค้ด
backend/internal/application/process/hidden_cost.go:15-33,:51-52,:261-274,:392-414,:416-439,:479,:533-588backend/internal/application/process/doc_cancel.go:437backend/internal/application/process/doc_no_next.go:12frontend/account/master/HiddenCostScreen.tsx:7,:65-68,:74-94docs/kms/KMS_PGSQL_NAMING_CONVENTION.md:80-88