การออกแบบโมเดลเก็บข้อมูลธุรกรรมการค้าเหมือนนักบัญชี

สวัสดีครับผม

ก็พอมีเวลาว่างมาเขียนแชร์กันอีก จริงๆอยากเขียนความรู้นี้มานานแล้ว แต่ไปสนใจเรื่องอื่นก่อน เพราะผมคิดว่า ความรู้เรื่องหลักการบันทึกบัญชีนี้ สำคัญมากต่อการออกแบบ Data(Domain) Models หรือ โครงสร้างข้อมูลสำหรับเก็บธุรกรรมที่เกิดจากกิจกรรมต่างๆที่เกิดขึ้นในโมเดลธุรกิจทุกชนิดเลยทีเดียว

การบัญชี คือ การจัดการส่วนของกระบวนการจดบันทึกรายการค้า (Entry)

การบัญชีมีสิ่งที่ต้องจัดการ ได้แก่ วิธีการบันทึกรายการค้า, การจัดหมวดหมู่รายการค้า, การสรุปรายงานรายการค้า และการวิเคราะห์รายการค้า

ผมคิดว่า ถ้าเราออกแบบส่วนโครงสร้างข้อมูลโดยใช้หลักการบัญชีออกแบบ Data Model เพื่อเก็บข้อมูลรายการค้า หรือธุรกรรมทางการค้าต่างๆที่เกิดขึ้นทั้งหมดในระบบซอฟแวร์ที่เราพัฒนาขึ้น เราจะสามารถเก็บข้อมูลทุกๆธุรกรรมที่เกิดขึ้นได้จากโมเดลธุรกิจที่เราพัฒนาอยู่ได้ ถูกต้อง แบบไม่มีหลุดเลย ดูตัวอย่างที่ผมจะนำเสนอ ต่อไปนี้ครับ

ผมจะขออธิบายสมการบัญชีก่อน เพราะ สำคัญต่อการออกแบบ Data Model เพื่อเก็บบันทึกรายการค้าแบบระบบคู่ ต่อไป

สมการบัญชี หรือที่เรียกว่า สมการงบดุล (The balance sheet equation) เป็น สมการหลักสำหรับบันทึกรายการค้าที่เรียกว่า ระบบบันทึกรายการค้าแบบคู่ คือ แต่ละธุรกรรมการค้า จะถูกบันทึก สองด้านคือ debit และ credit โดยที่ debit เท่ากับ credit เสมอ สมการบัญชี เขียนแบบนี้ครับ

สินทรัพย์ (Assets) = หนี้สิน (Liabilities) + ส่วนของเจ้าของ (Owner’s/Stockholder’s Equity, Capital)

Owner’s Equity = Contributed Capital + Retained Earnings

Retained Earnings = Net Income – Dividends

และ

 Net Income = Income − Expenses

Capital ในทางเศรษฐศาสตร์ คือ สินค้าที่แท้จริง ไม่ใช่ เงิน หรือ หุ้น หรือ สินทรัพย์ทางการเงินต่างๆ เช่น สินค้า (Goods) และ สิทธิการได้รับบริการ (Eligibility Services) ที่มีประโยชน์ส่งเสริมการผลิต หรือบริการในโมเดลธุรกิจ คือถ้าเป็นเงิน ก็ต้องเปลี่ยนให้เป็น สินค้า หรือบริการก่อน ก็จะเป็น Capital

Contributed Capital คือ ทรัพย์สินที่สนับสนุนธุรกรรมทางการค้า

Retained Earnings คือ ส่วนรายได้ที่สำรองไว้

Dividends คือ ส่วนที่กันไว้ปันผล

Net Income คือ รายได้ ลบ รายจ่าย ที่เกิดขึ้น จากการค้า

ในหลักการบันทึกบัญชี เขาจะบันทึกโดยเปลี่ยนเป็นหน่วยเงินตรา สกุลเดียวกันทั้งหมดก่อนบันทึกเสมอ

ตัวอย่าง การบันทึกรายการค้าแบบง่าย

หมายเลขธุรกรรม สินทรัพย์ หนี้สิน ส่วนของเจ้าของ รายการค้า
1 +1000 +1000 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
2 +200 +200 ซื้อสินทรัพย์ ด้วยการกู้ยืมเงิน 200 บาท
3 -500 -500 ขายสินทรัพย์ 500 บาท ได้เงินสด แล้วจ่ายหนี้
4 +1000 +600 +400 ซื้อสินทรัพย์ ด้วยทุนส่วนตัว 400 และ กู้ยืม 600
5 +300 +300 รับเงินจากธุรกิจ 300
6 -200 -200 จ่ายค่าเช่าทุก 200
7 +400 -400 มีการจ่าย แต่บันทึกรายการจ่ายไว้ก่อน
8 -500 -500 จ่ายหนี้ด้วยทุกตัวเอง

ต่อไปนี้ เป็นการใช้ การบันทึกโดยใช้ระบบธุรกรรมคู่ ที่มีประจุเป็น debit และ credit จะไม่ใช้สัญลักษณ์ +, –

#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท

หุ้น เป็นสินทรัพย์ ชนิดหนึ่ง

เงินสด ก็เป็น สินทรัพย์ ชนิดหนึ่ง เหมือนกัน

เนื่องจาก ธุรกรรมการค้านี้ ไม่มี บัญชี เงินสด จึงบันทึกใน บัญชีทุนส่วนของเจ้าของไว้ ดังนั้น จะบันทึกบัญชี แบบนี้

Debit บัญชีหุ้น 1000 บาท

Credit บัญชีส่วนของเจ้าของ 1000 บาท

จะเห็นว่า การบันทึกรายการค้าครั้งนี้ ถูกต้อง เพราะ บัญชีหุ้น = บัญชีส่วนของเจ้าของ หรือ Debit เท่ากับ Credit

รายการค้า Debit Credit
#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
บัญชีหุ้น 1000
บัญชีส่วนของเจ้าของ 1000

ถ้ากรณี ส่วนของเจ้าของ มีบัญชีเงินสด อยู่แล้ว เกิดจาก รายการเปิดบัญชี (Opening Entry) เราจะต้องบันทึกรายการค้า ตามจริงแบบนี้

รายการค้า Debit Credit
#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
บัญชีเงินสด 1000
บัญชีส่วนของเจ้าของ 1000
บัญชีหุ้น 1000
บัญชีเงินสด 1000

นำรายการมาบันทึก แยกประเภทบัญชี ได้แบบนี้

Code 101: บัญชีเงินสด

Debit Credit
เจ้าของนำเงินสดมาลงทุน 1000
ซื้อหุ้น 1000

Code 111: บัญชีหุ้น

Debit Credit
ซื้อหุ้น 1000

Code 301: บัญชีส่วนของเจ้าของ

Debit Credit
นำเงินสดมาลงทุน 1000

เมื่อนำ บัญชีแยกประเภทมาหาดุล โดยเอา ด้าน Debit ลบ Credit แล้วถ้ามีค่าเป็น + ให้เป็นดุลด้าน Debit และ ถ้าเป็น – ให้ไว้ดุลด้าน Credit เราจะได้

บัญชีเงินสด เท่ากับ 0

บัญชีหุ้น เท่ากับ +1000  และ

บัญชีส่วนของเจ้าของ เท่ากับ -1000

ซึ่งจะเห็นว่า Debit เท่ากับ Credit การบันทึกบัญชีนี้ จึงถูกต้อง

เมื่อนำแนวคิดการบันทึกแบบนักบัญชีมาออกแบบ Data Model สำหรับ ใช้เก็บข้อมูลลงฐานข้อมูล ก็จะได้ออกมาแบบนี้ครับ (ดูภาพ Accounting Data Model)

Entry (#ID, Amount, Currency, EntryType, BookedDate, Description)

Account (#ID, Code, AccountType, EffectiveFrom, EffectiveTo)

AccountingTransaction(#EntryID, #AccountID, TransactionCode)

 

เมื่อนำตัวอย่างซื้อหุ้น มาบันทึกโดยใช้โครงสร้าง Data Model ที่ออกแบบไว้ข้างต้น ผลลัพธ์จะออกมาเป็นรูปแบบนี้ครับ

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
IV-1 1 101 Assets 1 1000 Debit เจ้าของนำเงินสดมาลงทุน
IV-1 1 101 Assets 2 1000 Credit ซื้อหุ้น
IV-1 2 102 Assets 3 1000 Debit ซื้อหุ้น
IV-1 3 301 Equity 4 1000 Credit นำเงินสดมาลงทุน

โดย เราสามารถกำหนดกฏตรวจสอบ การบันทึกรายการค้า ด้วยเงื่อนไงนี้

[ Sum of Debit (Amount) = Sum of Credit (Amount) ]

ตัวอย่าง 2: ธุรกิจซื้อสินค้ามาเพื่อขาย จำนวน 10 ชิ้น รวมเป็นเงินทั้งหมด 10000 บาท โดยกู้เงินมาซื้อ

ตัวอย่างนี้ กระทบ บัญชีหนี้ (201) และ บัญชีสินค้าคงเหลือ (121)

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ซื้อสินค้า 10 ชิ้น 10000

Code 201: บัญชีเจ้าหนี้

Debit Credit
กู้ยืมซื้อสินค้า 10000

เมื่อเก็บลง Data Model จะได้แบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
IV-2 4 121 Assets 5 10000 Debit ซื้อสินค้า 10 ชิ้น
IV-2 5 201 Liabilities 6 10000 Credit กู้ยืมซื้อสินค้า


ตัวอย่างที่ 3:
จากตัวอย่างที่ 2 มีการขายสินค้า จำนวน 2 ชิ้น

ได้ เป็นเงินสด โดยที่ตั้งขายไว้ ชิ้นละ 1500 บาท บัญชีที่กระทบ มีดังนี้ บัญชีรายรับ (311), บัญชีเงินสด (101), บัญชีต้นทุนสินค้า (321), บัญชีสินค้าคงเหลือ (121)

Code 101: บัญชีเงินสด

Debit Credit
ขายสินค้า 2 ชิ้น 3000

Code 311: บัญชีรายรับ

Debit Credit
ขายสินค้า 2 ชิ้น 3000

Code 321: บัญชีต้นทุนสินค้า/บริการ

Debit Credit
ขายสินค้า 2 ชิ้น 2000

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ขายสินค้า 2 ชิ้น 2000

ข้อมูลเก็บลง Data Model จะมีลักษณะแบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
REV-1 1 101 Assets 7 3000 Debit เงินสดรับ
REV-1 6 311 Equity 8 3000 Credit ขายสินค้าได้ 2 ชิ้น
REV-1 7 321 Equity 9 2000 Debit ต้นทุนสินค้า 2 ชิ้น
REV-1 4 121 Assets 10 2000 Credit ต้นทุนสินค้า 2 ชิ้น

ตัวอย่างที่ 4: ลูกค้าซื้อสินค้า 3 ชิ้น ราคา 4500 บาท มีค่าขนส่งอีก 100 บาท ผ่านออนไลย์ ชำระผ่านบัตรเครดิต

บัญชีที่กระทบ บัญชีรายรับ (311), บัญชีลูกหนี้ (111), บัญชีต้นทุนสินค้า (321), บัญชีสินค้าคงเหลือ (121), บัญชีเจ้าหนี้ (201)

Code 111: บัญชีลูกหนี้

Debit Credit
ขายสินค้า 3 ชิ้น บวก ค่าขนส่ง 4600

Code 311: บัญชีรายรับ

Debit Credit
ขายสินค้า 3 ชิ้น 4500
ค่าขนส่ง 100

Code 321: บัญชีต้นทุนสินค้า

Debit Credit
ขายสินค้า 3 ชิ้น 3000
ค่าขนส่ง 100

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ขายสินค้า 3 ชิ้น 3000

Code 201: บัญชีเจ้าหนี้

Debit Credit
ค่าขนส่ง 100

ข้อมูลเก็บลง Data Model จะมีลักษณะแบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
REV-2 1 111 Assets 11 4600 Debit ขายสินค้า 3 ชิ้น บวก ค่าขนส่ง
REV-2 6 311 Equity 12 4500 Credit ขายสินค้า 3 ชิ้น
REV-2 6 311 Equity 13 100 Credit ค่าขนส่ง
REV-2 7 321 Equity 14 3000 Debit ขายสินค้า 3 ชิ้น
REV-2 7 321 Equity 15 100 Debit ค่าขนส่ง
REV-2 4 121 Assets 16 3000 Credit ขายสินค้า 3 ชิ้น
REV-2 5 201 Equity 17 100 Credit ค่าขนส่ง

มีธุรกรรมขายสินค้ามา พอสมควรแล้ว ลองสร้างรายงานจาก Data Model ของเราดูครับ ข้างล่างนี้เป็นตัวอย่าง สรุปรายงานขาย

มูลค่าขายรวม: 7600 บาท

ต้นทุนขายรวม: 5100 บาท

กำไรสุัทธิ: 2500 บาท

ตัวอย่างข้างต้นเป็นโมเดลธุรกิจแบบซื้อของมาขาย เพื่อให้เข้าใจการนำหลักการบันทึกบัญชีมากขึ้น ต่อไปนี้เป็นตัวอย่างของธุรกรรมการค้าของโมเดลธุรกิจธนาคาร

ตัวอย่าง 5: ลูกค้านำเงินสดมาฝาก 100000 บาท

บัญชีที่กระทบ  บัญชีเงินสด (101),  บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
DEP-1 1 101 Assets 18 100000 Debit ฝากเงิน
DEP-1 5 201 Liabilities 19 100000 Credit ฝากเงิน

ตัวอย่าง 6: ธนาคารปล่อยกู้ให้ลูกค้าจำนวน 100000 บาท โอนเงินเข้าบัญชีลูกค้า

บัญชีที่กระทบ  บัญชีลูกหนี้ (111), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
LON-1 8 111 Assets 20 100000 Debit กู้เงิน
LON-1 5 201 Liabilities 21 100000 Credit โอนเงินเข้าบัญชี

ตัวอย่าง 7: ธนาคารจ่ายดอกเบี้ยเงินฝากประจำเดือน 1 จำนวน 1000 บาท ตัดผ่านระบบ

บัญชีที่กระทบ บัญชีต้นทุนสินค้า/บริการ (321), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
INT-1 7 321 Equity 22 1000 Debit ดอกเบี้ยเงินฝาก
INT-1 5 201 Liabilities 23 1000 Credit ดอกเบี้ยเงินฝาก

ตัวอย่าง 8: ธนาคารรับชำระเงินจากลูกค้าเงินกู้งวดที่ 1 คิดเป็นเงินต้น 8000 บาท และดอกเบี้ย 2000 บาท ด้วยเงินสด

บัญชีที่กระทบ บัญชีเงินสด (101), บัญชีลูกหนี้ (111), บัญชีรายรับ (311), บัญชีต้นทุนสินค้า/บริการ (321)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
RELON-1 1 101 Assets 24 10000 Debit ชำระเงินกู้งวด 1
RELON-1 6 311 Equity 25 8000 Credit เงินต้น
RELON-1 6 311 Equity 26 2000 Credit ดอกเบี้ย
RELON-1 7 321 Equity 27 8000 Debit หักยอดลูกหนี้
RELON-1 8 111 Assets 28 8000 Credit หักยอดลูกหนี้

อธิบาย: รายการค้าที่ 24 รับชำระมาเป็นเงินสด 10000 จึง Debit บัญชีเงินสด โดย แยกรับเป็น เงินต้น 8000 และ ดอกเบี้ย 2000 ดังนั้นจึงต้อง Credit ที่ บัญชีรายรับ ของรายการค้าที่ 25, 26 ส่วนรายการค้าที่ 27 และ 28 เป็นปรับลดยอดลูกหนี้ อีก 8000 สำหรับลูกค้าคนนี้

แถมให้อีกโมเดลก็แล้วกัน ตัวอย่างต่อไปนี้เป็น ธุรกรรมการค้าของโมเดลธุรกิจประกันภัย

ตัวอย่าง 9: ลูกค้ามาซื้อกรมธรรม์ประกันภัย จ่ายเบี้ยมูลค่า 1000 บาท ด้วยเงินสด คุ้มครองทุกเรื่องเป็นระยะเวลา 1 เดือน ด้วยทุนเอาประกันจำกัดไว้ที่ 100000 บาท

บัญชีที่กระทบ บัญชีเงินสด (101), บัญชีรายรับ (311), บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
SPOLI-1 1 101 Assets 29 1000 Debit ขายกรมธรรม์ประกันภัย
SPOLI -1 6 311 Equity 30 1000 Credit ขายกรมธรรม์ประกันภัย
SPOLI -1 4 121 Assets 31 100000 Debit กรมธรรม์ประกันภัย
SPOLI -1 5 201 Liabilities 32 100000 Credit ทุนเอาประกัน

อธิบาย: รายการค้าที่ 29 รับเงินสดเข้ามา จึง Debit บัญชีเงินสด ไป 1000 เนื่องจากเป็นรายการขาย เป็นรายรับ จึงต้อง Credit บัญชีรายรับด้วย อีก 1000 สำหรับรายการค้าที่ 31, 32 เป็นการสร้างสิทธ์ ซึ่งเป็นสัญญากรมธรรม์ประกันภัย ว่าจะคุ้มครอง (Coverage) ด้วยเหตุใดๆแล้วแต่ตกลง ด้วยทุนเอาประกัน หรือ สามารถเรียกร้องค่าเสียหายได้สูงสุด ไม่เกิน 100000 ในระยะเวลา 1 เดือน สำหรับตัวข้อมูลระยะเวาลนี้ จะเก็บไว้ใน Data Model สำหรับ กรมธรรม์ประกันภัย (Policy) จะไม่แสดงให้ดู

ตัวอย่าง 10: ลูกค้าเรียกร้องค่าสินไหมทดแทน (Claim) ด้วยค่าเสียหาย 500 บาท จ่ายเงินสด

บัญชีที่กระทบ บัญชีต้นทุนสินค้า/บริการ (321), บัญชีเงินสด (101), บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
CLM-1 7 321 Equity 33 500 Debit เรียกร้องค่าสินไหมทดแทน
CLM-1 1 101 Assets 34 500 Credit เรียกร้องค่าสินไหมทดแทน
CLM-1 5 201 Liabilities 35 500 Debit คุ้มครอง
CLM-1 4 121 Assets 36 500 Credit คุ้มครอง

ตัวอย่าง 11: กรมธรรม์ประกันภัยหมดเวลาคุ้มครอง ใช้ทุนไป 500 เหลือทุนเอาประกันที่หมดเวลา 99500

บัญชีที่กระทบ บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
EPOLI-1 7 321 Equity 37 99500 Debit สิ้นสุดความคุ้มครอง
EPOLI-1 1 101 Assets 38 99500 Credit สิ้นสุดความคุ้มครอง

Code แสดงไว้ที่นี่ครับ SourceCode

มันก็ดูยากพอสมควรนะครับผมคิดว่า ก็ไปศึกษาเพิ่มเติมในหลักการบัญชีเบื้องต้น แล้วนำไปออกแบบระบบดูนะครับ มันมีประโยชน์มาก ถึงแม้ว่าจะยาก แต่มันก็คุ้ม และจบปัญหาต่างๆได้แน่นอนครับ

อ่านเพิ่มเติม

“Think like Accountant, Do like Programmer”

ขอบคุณครับ

#:P

#accounting, #data-model, #ddd, #domain-model