ยอดเงิน ส่วนลด VAT และการปิดบิลลงบัญชี
ค่าเงินทั้งหมดใน AutoCare คำนวณด้วย *big.Rat ผ่าน appprocess.ParseDecimalRat และ FormatRat(x, 2) และเก็บในคอลัมน์ NUMERIC(18,2) (handler.go:2250-2300) ไม่มีการใช้ float
1. คำนวณยอดใบงาน recalculateJobTotals (handler.go:2226-2302)
ฟังก์ชันนี้ถูกเรียกหลังเพิ่มรายการ หลังอนุมัติ upsell หลังอนุมัติส่วนลด และทุกครั้งที่ Rebuild
- อะไหล่และค่าแรง: รวม
line_totalของทุกบรรทัด ถ้าitem_category = "LABOR"จะนับเป็นsubtotal_laborบรรทัดอื่นนับเป็นsubtotal_parts(handler.go:2255-2259) - ค่าคอมช่าง:
tech_commission_amt = SUM(tech_fee_amt)(handler.go:2254) - ส่วนลดท้ายบิล =
turn_in_discount+coupon_discount+owner_special_discountโดยส่วนลดตัวสุดท้ายนับเฉพาะเมื่อdiscount_request_status = 'APPROVED'(handler.go:2262-2270) ยอดรวมนี้ส่งต่อเป็นDiscountWord - VAT และยอดสุทธิ ไม่ได้คำนวณเองใน AutoCare แต่เรียก
h.process.TransTotalsด้วยค่าTransType 2, TransFlag 44, VatType 0, VatRate "7"ซึ่งเป็นชุดเดียวกับที่ใช้ตอนโพสต์จริง หน้าจอจึงแสดงยอดเท่ากับใบกำกับที่จะออก (handler.go:2271-2290) ผลที่ได้บันทึกเป็นvat_amountและgrand_total - บรรทัดที่ไม่มี
item_codeยังนับในยอดอะไหล่และค่าแรง แต่ไม่ถูกส่งเข้า TransTotals ถ้าใบงานไม่มีบรรทัดที่มีรหัสเลย VAT และยอดสุทธิจะเป็น 0 (handler.go:2251-2253, 2272-2289) - ตอนรับรถ
create_intake_jobคิด VAT ตั้งต้นแบบรวมในnet × 7 / 107(handler.go:1040-1046) แต่ค่านี้ถูกแทนที่เมื่อ recalc หรือ rebuild ทำงาน
2. VatType 0 คำนวณอย่างไร
TransTotals โหลดค่าตั้งค่าบริษัทด้วย loadGridOptions (trans.go:756-772) จากนั้น vatCalc กรณี vatType 0 (แยกนอก) ทำงานตามตัวเลือก (transcalc.go:135-176)
DiscountType ≠ 1: คิด VAT จากฐานก่อนหักส่วนลดท้ายบิล แล้วจึงหักส่วนลดออกจากยอดสุทธิDiscountType = 1และDiscountVatType = 0: หักส่วนลดจากฐานภาษีก่อน ถ้าส่วนลดมากกว่าฐานภาษี ส่วนที่เกินจะไปหักจากยอดที่ไม่มีภาษีDiscountType = 1และDiscountVatType = 1: เฉลี่ยส่วนลดตามสัดส่วนระหว่างยอดที่มีภาษีและไม่มีภาษี- ปัดเศษด้วย
bcRoundตามAmountDecและRoundTypeของบริษัท
รายละเอียดเต็มอยู่ที่ การคำนวณยอดท้ายบิล VAT และส่วนลด (Document Totals / vatCalc)
3. ปิดบิล postJobToBCAccount (handler.go:2495-2753)
อ่านหัวใบงานและบรรทัด โดยดึง
item_typeจากic_inventory(handler.go:2496-2524) ลูกค้าเริ่มต้นคือAR-AC01วันที่เอกสารใช้job_dateรวมส่วนลดด้วยกฎเดียวกับข้อ 1 (handler.go:2542-2551)
เลขเอกสาร: ใช้
fixedDocNoถ้าส่งมา ถ้าไม่มีให้ใช้bc_doc_noเดิม (ยกเว้นเลขเดโมAC-INV2610-001) ถ้าไม่มีทั้งสองอย่างจะสร้างเลขใหม่เป็น"AC-INV"ต่อด้วย 9 ตัวแรกของ Stamp (handler.go:2553-2565)บรรทัดขาย: ข้ามบรรทัดที่ไม่มีรหัส ทุกบรรทัดใช้คลัง
WH1และที่เก็บSH1มีPrice,Discount,SumAmount = line_total,TaxType 0และItemTypeตามข้อมูลหลักสินค้า ใส่รหัส DOT ไว้ในLotNumber1(handler.go:2569-2606) ถ้าไม่มีบรรทัดเลย ระบบใส่บรรทัดบริการSRV-ALIGN-3Dที่มูลค่าเท่าgrand_total(handler.go:2617-2632)ขายสดหรือขายเชื่อ: ค่าเริ่มต้น
InquiryType 1คือขายสด ถ้าpayment_method = FLEET_CREDITจะเป็นInquiryType 0คือขายเชื่อ (handler.go:2634-2637)หัวเอกสาร:
DocFormatCode "AC",TransType 2,TransFlag 44,VatType 0,VatRate "7",TaxDocNoเท่ากับเลขเอกสาร,DocRefเท่ากับเลขใบงาน,DueDateเท่ากับวันที่เอกสาร,Confirmed true(handler.go:2639-2668)เรียก
TransTotalsก่อน ถ้าเป็นขายสดจะใส่แท็บรับเงินจากinvoicePay(payMethod, totals.Amount)แล้วเรียกSaveTransถ้าล้มเหลวจะลองใหม่แบบแก้ไขIsNew=false(handler.go:2669-2686) การบันทึกic_trans,cb_transและ GL เป็นหน้าที่ของ SaveTrans ดู ลำดับการบันทึกเอกสาร (Transaction Save Flow) และ การลงบัญชี Dr/Cr มาตรฐานแยกตามชนิดเอกสาร (Standard GL Posting)หลังบันทึก (เฉพาะเมื่อไม่ได้ส่ง
fixedDocNo) ทำ 5 อย่าง (handler.go:2689-2752)- ตัดสต็อกใน
autocare_tire_dot_stockของบรรทัดที่มี DOT - ปล่อยช่องซ่อมเป็น
AVAILABLEและเพิ่มยอดขายของวัน - บวกงานและค่าคอมเข้ากระเป๋าช่าง
- บวกแต้มสมาชิกให้รถ 150 แต้ม
- สร้างใบรับประกันดิจิทัล
E_WARRANTYเลขCLM-…และWRT-…
ส่วนการตั้งใบงานเป็น
BILLED_POSTED,accounting_posted = TRUE,bc_doc_noและbc_gl_posted = TRUEทำทุกครั้ง- ตัดสต็อกใน
4. แท็บรับเงิน invoicePay (handler.go:2754-2768)
payment_method |
ช่องในแท็บรับเงิน |
|---|---|
CASH |
Cash + PayCashAmount |
CREDIT_CARD |
Card |
PROMPTPAY_QR |
PromptPay |
BANK_TRANSFER |
Transfer |
| ค่าอื่น | error "วิธีรับชำระเงินไม่ถูกต้อง" |
มี unit test TestInvoicePayUsesChosenTender ตรวจตารางนี้ และตรวจว่าวิธีที่ไม่รู้จักถูกปฏิเสธ (handler_pay_test.go:10-30) ดู แท็บรับ/จ่ายเงิน และการชำระหนี้ตามบิล (Payment Tab & Bill Settlement)
หน้าเว็บมีตัวเลือก PromptPay QR, บัตรเครดิต, เงินสด และ "เครดิตลูกหนี้ Fleet 30 วัน" (AutoCareScreenContent.tsx:2510-2518) แต่ในโค้ดโพสต์ตั้ง DueDate เท่ากับวันที่เอกสาร ไม่ได้บวก 30 วัน (handler.go:2659)
ที่มาในโค้ด
backend/internal/adapter/inbound/http/autocare/handler.go:2226-2302: recalculateJobTotalsbackend/internal/adapter/inbound/http/autocare/handler.go:2495-2753: postJobToBCAccountbackend/internal/adapter/inbound/http/autocare/handler.go:2754-2768: invoicePaybackend/internal/adapter/inbound/http/autocare/handler_pay_test.go:10-30: testbackend/internal/application/process/transcalc.go:135-176: vatCalcbackend/internal/application/process/trans.go:756-772: TransTotals
ดูเพิ่ม: ขายสินค้า/บริการ และใบกำกับภาษีเต็มรูป (Sales Invoice) · หัวเอกสารสินค้า/ซื้อ/ขาย (ic_trans) · หัวสรุปการรับ/จ่ายเงิน (cb_trans) · หัวสมุดรายวันทั่วไป (gl_journal) · ขั้นตอนใบสั่งซ่อมตั้งแต่รับรถจนรับเงิน (sys-autocare-job-flow) · ขายถึงรับเงิน (Order-to-Cash)