অধ্যায় ১৯ — Advance, Credit Note ও Debit Note
Volume 1 · Part 2 — Core Business Accounting · Chapter 19
পূর্বশর্ত: অধ্যায় ১৩ (Sales — cancel বনাম credit note), অধ্যায় ১৪ ও ১৬ (allocation, unapplied, advance-এর সমন্বয়), অধ্যায় ১৫ (Purchase — buildDocumentEntry)
১. Learning Objective
এই অধ্যায় শেষে আপনি পারবেন:
Advance দুই দিকে — customer advance (liability), advance to supplier (asset) — পুরো জীবনচক্র লিখতে
Advance, deferred revenue, unapplied receipt — তিন "cousin"-কে আলাদা করতে
Credit note (আপনি গ্রাহককে) আর debit note (আপনি supplier-কে) — কখন, কেন, entry কী — বলতে
Reversal বনাম credit note: "document ভুল ছিল" বনাম "নতুন ঘটনা ঘটেছে" — সিদ্ধান্ত নিতে
Note-কে মূল invoice/bill-এর সাথে line-ধরে বাঁধতে, আর সীমা (invoice-এর বেশি নয়) রাখতে
Payment হয়ে যাওয়া invoice-এ credit note — party-র credit balance — সামলাতে (ফেরত / পরের invoice)
VAT-এ note-এর প্রভাব: output VAT কমে (CN), input VAT কমে (DN) — note-এর মাসে
Supplier-এর credit note আর আপনার debit note — একই ঘটনা, দুই কাগজ — একবার লেখা
buildDocumentEntry(doc, ±1) দিয়ে চারটি document (SV, PB, CN, DN) এক rule-এ চালাতে
Advance aging, credit note register, party credit balance report — তিনটি তৈরি করতেসময়: পড়া ৫০ মিনিট + অনুশীলন ৫৫ মিনিট।
২. Concept Explanation
যা যা “অধ্যায় ১৯-এ” বলে রেখেছি
অধ্যায় ১৩ deferred বনাম advance — "invoice হলে সমন্বয় (অধ্যায় ১৯)"
অধ্যায় ১৪ সালমার advance 50,000 → JV Dr 2160 / Cr A/R "অধ্যায় ১৯-এর আগাম"
অধ্যায় ১৫ laptop ফেরত → DN-10-0006 "অধ্যায় ১৯-এর আগাম"
অধ্যায় ১৬ রফিকের advance 40,000 → JV Dr A/P / Cr 1140
অধ্যায় ১৩ invoice ভুল, গ্রাহকের হাতে চলে গেছে → "reversal নয়, credit note"এগুলো তিনটি document-এর গল্প — advance (টাকা document-এর আগে), credit note (invoice-এর পরে কমানো), debit note (bill-এর পরে কমানো)। তিনটির মিল: কোনোটাই নিজে বিক্রি বা ক্রয় নয়; আগের বা পরের একটা document-কে বদলায়।
Advance — টাকা আগে, document পরে
Customer advance (2160, liability): গ্রাহক টাকা দিলেন, invoice হয়নি। গ্রাহকের কাছে আপনার দেনা — সেবা বা ফেরত।
টাকা এল: Dr 1120 Bank Cr 2160 Customer Advance [গ্রাহক]
invoice হলো: Dr 1130 A/R [গ্রাহক] Cr Revenue / 2180, Cr 2140 (স্বাভাবিক)
সমন্বয়: Dr 2160 [গ্রাহক] Cr 1130 A/R [গ্রাহক] ← advance খরচ হলো
(বা ফেরত: Dr 2160 [গ্রাহক] Cr 1120 Bank)Advance to supplier (1140, asset): আয়না।
টাকা গেল: Dr 1140 Advance [supplier] Cr 1120 Bank
bill এল: Dr Expense/Asset, 1160 Cr 2110 A/P [supplier] (স্বাভাবিক)
সমন্বয়: Dr 2110 A/P [supplier] Cr 1140 Advance [supplier]
(বা ফেরত: Dr 1120 Bank Cr 1140 Advance [supplier])দুটো নকশা-সিদ্ধান্ত। প্রথম: advance-এর account-ও party-ধরে — 2160 আর 1140 control account-এর মতো subledger রাখে (কার advance কত)। দ্বিতীয়: সমন্বয় একটা allocation — অধ্যায় ১৪/১৬-এর source_type = 'advance' — সাথে একটা JV যা control account থেকে advance account-এ সরায়। Allocation table বলে কোন invoice-এ, JV বলে GL-এ কত।
তিন cousin — advance, deferred, unapplied
তিনটিই “গ্রাহকের কাছে দেনা”, তিনটিই Balance Sheet-এ liability, তিনটি আলাদা:
advance (2160) deferred (2180) unapplied (1130 Cr)
───────────── ────────────── ─────────────── ───────────────────
invoice আছে? না হ্যাঁ হ্যাঁ, কিন্তু মেলে না
টাকা এসেছে? হ্যাঁ হয়তো হ্যাঁ
কাজ হয়েছে? না না হ্যাঁ (invoice-এর)
কী হবে invoice-এ সমন্বয় recognition allocate / ফেরত
কে তৈরি করে গ্রাহক, ইচ্ছাকৃত আপনি, আগে invoice ভুল / বেশি payment
অধ্যায় ১৯ ১৩, ১৭ ১৪Unapplied receipt আর advance-এর পার্থক্য সবচেয়ে সূক্ষ্ম — দুটোই “টাকা এল, invoice-এ বাঁধা নেই”। পার্থক্য অভিপ্রায়: advance ইচ্ছাকৃত, ভবিষ্যৎ কাজের জন্য, চুক্তি/quotation-এর বিপরীতে; unapplied দুর্ঘটনা। Software-এ: receipt-এ is_advance পতাকা → Cr 2160, নইলে Cr 1130। পতাকাটা মানুষ দেন — receipt-এর সময়।
Credit note — invoice-এর পরে কমানো
Invoice গেছে, গ্রাহক বলছেন: একটা module পাইনি / দাম বেশি ধরা হয়েছে / পণ্য ফেরত দিচ্ছি / আপনি ছাড় দিতে রাজি হয়েছেন। Invoice ঠিকই ছিল তখন; এখন একটা নতুন ঘটনা। তাই invoice বদলানো নয় — একটা নতুন document, credit note:
CN-12-0001 (against SV-09-0003, করিম)
Dr 4180 Sales Returns & Allowances 20,000 ← contra-revenue, এ মাসে
Dr 2140 VAT Payable 3,000 ← output VAT কমল
Cr 1130 A/R [করিম] 23,000 ← পাওনা কমল
allocation: SV-09-0003 credit_note 23,000 → open কমলতিনটি নিয়ম:
১. সবসময় একটা মূল invoice-এর বিপরীতে, line-ধরে — কোন line, কত পরিমাণ/অঙ্ক
২. মোট credit ≤ মূল invoice (এক invoice-এ বহু CN হতে পারে, যোগফল সীমার ভিতরে)
৩. নিজের gapless নম্বর (CN-), নিজের তারিখ, নিজের মাস — VAT return-এ এ মাসেইRevenue কমে 4180-এ, note-এর মাসে — সেপ্টেম্বরের 4110 বদলায় না। সেপ্টেম্বর ছাপা হয়ে গেছে; ডিসেম্বরে জানা গেল, ডিসেম্বরেই। (Contract/deferred line-এর CN — 2180 কমে, billed_to_date কমে, revenue নয়; অধ্যায় ১৭-এর position।)
Debit note — bill-এর পরে কমানো
আয়না। Supplier-এর bill post হয়েছে; laptop ত্রুটিপূর্ণ, ফেরত:
DN-10-0006 (against PB-10-0003, টেক সাপ্লাই)
Dr 2110 A/P [টেক সাপ্লাই] 1,38,000 ← দেনা কমল
Cr 1510 Computer Equipment 1,20,000 ← মূল account-ই কমে
Cr 1160 VAT Receivable 18,000 ← input VAT কমলSales-এ contra account (4180) — কারণ “কত বিক্রি, কত ফেরত” আলাদা দেখা দরকার। Purchase-এ মূল account-ই কমে — asset ফেরত গেলে asset কমে, খরচ ফেরত গেলে খরচ কমে। (Inventory-তে stock-ও কমে — অধ্যায় ২৭।)
নামের ফাঁদ: একই ঘটনায় supplier আপনাকে “credit note” পাঠান, আপনি নিজের খাতায় “debit note” লেখেন। দুটো কাগজ, একটা entry। আপনার DN আগে (মাল ফেরতের দিনে); তার CN এলে শুধু নম্বর লিখে রাখুন — counterparty_note_no। অধ্যায় ১৬-এ statement মেলেনি ঠিক এই কারণে: আপনার DN ছিল, তার CN ছিল না।
উল্টো দিকও আছে — কম দেখা যায়: আপনি গ্রাহককে debit note (কম bill করেছিলেন, বাড়তি charge) আর supplier আপনাকে debit note (কম bill করেছিল)। কাঠামো একই, চিহ্ন উল্টো। Software-এ চারটিই একটা notes table — section ৫।
Reversal বনাম credit note — সিদ্ধান্তের গাছ
অধ্যায় ১৩-এর cancelInvoice() আর এই অধ্যায়ের credit note — কোনটা কখন:
invoice-এ সমস্যা
│
├── document-টাই ভুল ছিল (ভুল গ্রাহক, দুবার, ভুল অঙ্ক টাইপ)
│ │
│ ├── গ্রাহকের হাতে যায়নি, period খোলা → CANCEL (reversal, একই মাস)
│ │ invoice cancelled, নম্বর থাকে
│ │
│ └── গ্রাহকের হাতে গেছে / period বন্ধ → CREDIT NOTE পুরো + নতুন invoice
│ (তার খাতায় আপনার invoice আছে —
│ মুছবেন না, কাটুন)
│
└── document ঠিক ছিল, পরে কিছু ঘটল (ফেরত, বিতর্ক, ছাড়)
→ CREDIT NOTE, আংশিক বা পুরো, নিজের মাসেমূল প্রশ্ন: কাগজটা কি পৃথিবীতে বেরিয়ে গেছে? বেরিয়ে গেলে মুছে ফেলা যায় না — গ্রাহকের A/P-তে, তার VAT return-এ আছে। শুধু কাটা যায়, নতুন কাগজ দিয়ে। Reversal মানে “ঘটেনি”; credit note মানে “ঘটেছিল, এখন কমল”। অধ্যায় ৪৩-এ পুরো architecture।
Payment হয়ে যাওয়া invoice-এ credit note
সালমার invoice অক্টোবরে paid। ডিসেম্বরে ১০,০০০ + VAT-এর concession। CN-এর entry একই — কিন্তু allocate করার মতো open invoice নেই:
Dr 4180 10,000 / Dr 2140 1,500 / Cr 1130 [সালমা] 11,500
allocation: কিছু না — SV-10-0001 open 0
সালমার subledger: 11,500 Cr ← credit balance, unapplied noteঅধ্যায় ১৪-এর unapplied receipt-এর মতোই: subledger-এ credit, statement-এ বার্তা, দুটো পথ — ফেরত (Dr 1130 / Cr Bank) বা পরের invoice-এ allocate (allocations: document = নতুন invoice, source = credit_note)। ৩০ দিনের বেশি পড়ে থাকলে সতর্কতা — গ্রাহকের টাকা আপনার কাছে।
Proforma — যে invoice invoice নয়
Advance চাওয়ার জন্য “proforma invoice” পাঠানো হয় — quotation-এর ভাইয়ের মতো। এটা accounting document নয়: entry নেই, A/R নেই, VAT নেই, gapless নম্বরের sequence আলাদা (PF-)। Developer-রা এটাকে sales_invoices-এ status = proforma করে রাখেন, তারপর কেউ post করে ফেলে। আলাদা table, বা quotations-এর একটা প্রকার। Advance এলে proforma-র reference থাকে, entry advance-এর।
VAT — note-এর মাসে
Credit note output VAT কমায়, debit note input VAT কমায় — note-এর তারিখের মাসে, মূল invoice-এর মাসে নয়। VAT return-এ আলাদা লাইন (“adjustment”)। দেশভেদে শর্ত: CN-এ মূল invoice-এর নম্বর ও তারিখ লেখা বাধ্যতামূলক, নির্দিষ্ট সময়ের (৬ মাস / ১ বছর) পরে VAT সমন্বয় নয় — config, অধ্যায় ৫৫। Advance-এ VAT — কিছু দেশে advance পাওয়ার সময়েই output VAT দিতে হয়; এই বইয়ে invoice-এ; ব্যতিক্রম অধ্যায় ৫৫।
৩. Accounting Rule
Advance
| ঘটনা | Debit | Credit |
|---|---|---|
| Customer advance এল | Bank | Customer Advance [গ্রাহক] |
| Invoice-এ সমন্বয় | Customer Advance [গ্রাহক] | A/R [গ্রাহক] |
| Advance ফেরত | Customer Advance [গ্রাহক] | Bank |
| Supplier-কে advance | Advance to Supplier [supplier] | Bank |
| Bill-এ সমন্বয় | A/P [supplier] | Advance to Supplier [supplier] |
| Advance ফেরত পেলেন | Bank | Advance to Supplier [supplier] |
Note
| ঘটনা | Debit | Credit |
|---|---|---|
| Credit note গ্রাহককে | Sales Returns & Allowances (বা Deferred), VAT Payable | A/R [গ্রাহক] |
| Debit note supplier-কে | A/P [supplier] | মূল account (Expense/Asset/Inventory), VAT Receivable |
| Debit note গ্রাহককে (বাড়তি charge) | A/R [গ্রাহক] | Revenue, VAT Payable |
| Credit note supplier থেকে, তার bill কমে | A/P [supplier] | মূল account, VAT Receivable |
সীমা
Σ CN (invoice) ≤ invoice.grand_total line-ধরে: qty ≤ মূল qty − আগের ফেরত
Σ DN (bill) ≤ bill.grand_total
মূল document cancelled হলে note নয়Reversal না note
document ভুল + বেরোয়নি + period খোলা → cancel (reversal, একই মাস)
নইলে → note, নিজের মাসেRevenue/VAT-এর মাস
CN: 4180 (contra) note-এর মাসে; মূল মাসের revenue অপরিবর্তিত
deferred/contract line হলে 2180 কমে, billed_to_date কমে
DN: মূল account কমে, note-এর মাসে
VAT: note-এর মাসে, adjustment হিসেবেUnapplied note
open invoice নেই → party credit balance → ফেরত বা পরের invoice-এ allocate
৩০ দিনে সতর্কতা৪. Real Business Example
ডিসেম্বর ২০২৫ — পুরনো সুতো বাঁধার মাস
১ ডিসেম্বরে A/R-এর open items (অধ্যায় ১৪-এর অক্টোবর থেকে; নভেম্বরে নদী গ্রুপের invoice ও receipt কাটাকাটি):
SV-09-0003 করিম ট্রেডার্স open 38,000 (due 15-10 — ৪৭ দিন overdue)
unapplied রহিম (3,100)
────────
GL 1130 34,900
অধ্যায় ১৬-এ নভেম্বরে করিমের 38,000 আশা করা হয়েছিল — আসেনি। কারণ এ মাসে জানা গেল।০২-১২ — করিম: “একটা module পাইনি, ৩৮,০০০ দেব না”
ফোন, আলোচনা: module-টা সত্যিই delivery হয়নি (২০,০০০ + VAT)। Invoice সেপ্টেম্বরে ঠিকই ছিল — তখন পরিকল্পনায় ছিল। Document ভুল নয়; নতুন ঘটনা: credit note।
CN-12-0001 against SV-09-0003, line 2 (module B), reason: not_delivered
Dr 4180 Sales Returns & Allowances 20,000
Dr 2140 VAT Payable 3,000
Cr 1130 A/R [করিম] 23,000
allocation: SV-09-0003 credit_note 23,000 → open 15,000সেপ্টেম্বরের revenue ৩,৮০,০০০-ই থাকল; ডিসেম্বরের Income Statement-এ 4180-এ ২০,০০০। Reversal করলে সেপ্টেম্বর বদলাত — আর সেপ্টেম্বরের VAT return জমা হয়ে গেছে।
০৫-১২ — রহিম ৩,১০০ ফেরত চাইলেন (অধ্যায় ১৪-এর unapplied)
PV-12-0002 refund, party = customer
Dr 1130 A/R [রহিম] 3,100
Cr 1120 Bank — Prime 3,100
রহিমের subledger: 0Refund হলো payments-এ kind = payment, party_type = customer — supplier-কে payment-এর মতোই, শুধু control account 1130। Allocation: unapplied receipt RV-10-0004-এর বিপরীতে (source = refund)।
০৮-১২ — সাগর লিমিটেড: জানুয়ারির project-এর advance ১,০০,০০০
RV-12-0003 is_advance = true, reference: proforma PF-12-0002
Dr 1120 Bank — Prime 1,00,000
Cr 2160 Customer Advance [সাগর] 1,00,000
A/R স্পর্শ হয়নি। 2160 subledger: সাগর 1,00,000Proforma PF-12-0002 — কোনো entry নেই, sales_invoices-এ নেই।
১০-১২ — করিম ১৫,০০০ দিলেন
RV-12-0004
Dr 1120 Bank 15,000
Cr 1130 A/R [করিম] 15,000
allocation: SV-09-0003 receipt 15,000 → open 0 → paid
SV-09-0003: 1,38,000 = receipt 1,00,000 + CN 23,000 + receipt 15,000 ✓১৫-১২ — সালমা: paid invoice-এ concession ১০,০০০ + VAT
CN-12-0002 against SV-10-0001 (paid), reason: price_adjustment
Dr 4180 Sales Returns & Allowances 10,000
Dr 2140 VAT Payable 1,500
Cr 1130 A/R [সালমা] 11,500
allocation: নেই — open invoice নেই
সালমার subledger: 11,500 Cr ← unapplied credit note
statement-এ: "আপনার হিসাবে 11,500 জমা; পরের invoice-এ সমন্বয় হবে"১৮-১২ — টেক সাপ্লাইয়ের credit note “CN-TS-0412” এল (laptop ফেরতের)
আমাদের খাতায়: DN-10-0006, 1,38,000 — অক্টোবরেই লেখা
তার CN: 1,38,000, 15-12
entry: নেই
DN-10-0006.counterparty_note_no = 'CN-TS-0412', counterparty_note_date = 15-12
supplier statement (অধ্যায় ১৬): এবার মিলবে২০-১২ — অফিস মার্টের একটা চেয়ার ভাঙা: ৮,০০০ + VAT ফেরত; bill নভেম্বরে paid
DN-12-0003 against PB-11-0002, line 3, qty 1, reason: damaged
Dr 2110 A/P [অফিস মার্ট] 9,200
Cr 1520 Furniture & Fixtures 8,000
Cr 1160 VAT Receivable 1,200
allocation: নেই — PB-11-0002 paid
অফিস মার্টের subledger: 9,200 Dr ← supplier আমাদের দেবেAsset কমল ৮,০০০ (ফেরত), input VAT কমল, আর supplier-এর কাছে পাওনা। A/P-তে debit balance — অধ্যায় ১৬-এর unapplied payment-এর ভাই।
২২-১২ — SV-12-0009 ভুল গ্রাহকের নামে issue হলো, PDF পাঠানোর আগেই ধরা পড়ল
document ভুল? হ্যাঁ (ভুল party)
বেরিয়েছে? না
period? ডিসেম্বর, খোলা
→ cancelInvoice(SV-12-0009) — অধ্যায় ১৩-এর reversal, একই দিনে
নতুন SV-12-0010 ঠিক গ্রাহকের নামেCredit note নয় — কারণ কাগজটা পৃথিবীতে যায়নি। একই ভুল ২ জানুয়ারিতে ধরা পড়লে (ডিসেম্বর বন্ধ): CN-01-0001 পুরো অঙ্কে + নতুন invoice — দুটোই জানুয়ারিতে।
২৮-১২ — অফিস মার্ট ৯,২০০ ফেরত দিল
RV-12-0007 party = supplier
Dr 1120 Bank 9,200
Cr 2110 A/P [অফিস মার্ট] 9,200
allocation: DN-12-0003 refund 9,200
অফিস মার্ট: 0৩১ ডিসেম্বর — তিন স্তর, দুই দিক
A/R 1130:
opening 34,900
− CN-12-0001 23,000
+ PV-12-0002 (refund রহিম) 3,100
− RV-12-0004 15,000
− CN-12-0002 11,500
− SV-12-0009 + reversal 0
+ SV-12-0010 … (ধরা যাক 0-এর জন্য বাদ)
───────
closing (11,500) Cr ← সালমার credit balance
subledger: করিম 0, রহিম 0, সালমা 11,500 Cr, নদী 0 ✓
open items: কোনো open invoice নেই; unapplied CN 11,500 ✓1130-এর ব্যালেন্স credit — Balance Sheet-এ asset-এর ঘরে ঋণাত্মক নয়, liability-তে reclassify (অধ্যায় ১৪-এর নিয়ম)। Auditor-এর ভাষায় “customer credit balances”।
2160 Customer Advance:
সাগর লিমিটেড 1,00,000 invoice নেই, project জানুয়ারিতে
advance aging: 23 দিন — ঠিক আছে; ৯০ দিন পার হলে প্রশ্নA/P 2110 (অধ্যায় ১৬-এর ১,২৬,০০০ থেকে):
opening 1,26,000
− PV-11-0009 (PDC 05-12) 1,26,000 ← টেক সাপ্লাই বন্ধ
+ ডিসেম্বরের bill (অধ্যায় ১৮) …
− DN-12-0003 9,200
+ RV-12-0007 9,200
অফিস মার্ট: 0; টেক সাপ্লাই: 0 (DN-এর counterparty মিলেছে)Credit / Debit Note Register — ডিসেম্বর
CREDIT NOTES (sales) — ডিসেম্বর ২০২৫
তারিখ Ref গ্রাহক against reason Net VAT মোট
02-12 CN-12-0001 করিম SV-09-0003 not_delivered 20,000 3,000 23,000
15-12 CN-12-0002 সালমা SV-10-0001 price_adj. 10,000 1,500 11,500
────── ───── ──────
30,000 4,500 34,500
→ VAT return: output VAT adjustment −4,500
→ 4180: 30,000 == GL ✓
DEBIT NOTES (purchase) — ডিসেম্বর ২০২৫
20-12 DN-12-0003 অফিস মার্ট PB-11-0002 damaged 8,000 1,200 9,200
→ VAT return: input VAT adjustment −1,200
(DN-10-0006 অক্টোবরের register-এ; counterparty CN-TS-0412 এ মাসে link হলো — entry নয়)৫. Implementation — Software ও Database
একটা notes table — চার দিক
notes
id, company_id
document_type VARCHAR(20) -- sales | purchase
kind VARCHAR(10) -- credit | debit
note_no VARCHAR(40) -- CN-12-0001 / DN-12-0003; (type,kind)-ধরে gapless
party_id BIGINT FK -- customer বা supplier
original_type VARCHAR(20) -- sales_invoice | purchase_invoice
original_id BIGINT FK NOT NULL -- মূল document — বাধ্যতামূলক
reason_code VARCHAR(30) -- return | not_delivered | price_adjustment
-- | discount | damaged | shortage | cancellation
reason TEXT NOT NULL
note_date DATE
posting_date DATE
subtotal, tax_total, grand_total DECIMAL(18,4)
counterparty_note_no VARCHAR(60) NULL -- supplier-এর CN নম্বর (purchase debit note-এ)
counterparty_note_date DATE NULL
status VARCHAR(20) -- draft | approved | posted | cancelled
approved_by, journal_entry_id
UNIQUE (company_id, document_type, kind, note_no)
INDEX (original_type, original_id)note_lines
id, note_id, line_no
original_line_id BIGINT FK NOT NULL -- মূল invoice/bill-এর line
quantity DECIMAL(18,4) -- ফেরতের পরিমাণ (থাকলে)
unit_price, line_net, tax_amount DECIMAL(18,4)
account_id BIGINT FK -- CN: 4180 / 2180; DN: মূল line-এর accountচারটি সমন্বয় (document_type × kind) একটাই table-এ। কোন জোড়া কী:
sales credit CN গ্রাহককে A/R কমে সাধারণ
sales debit DN গ্রাহককে A/R বাড়ে বাড়তি charge, কম
purchase debit DN supplier-কে A/P কমে সাধারণ
purchase credit supplier-এর DN A/P বাড়ে supplier কম bill করেছিল, কমPosting — একই rule, direction
অধ্যায় ১৫-এর buildDocumentEntry(doc, direction)-এ note ঢোকে direction উল্টে:
directionOf(doc):
sales_invoice → +1 (party Dr, lines Cr)
purchase_invoice → −1 (party Cr, lines Dr)
note(sales, credit) → −1 (invoice-এর উল্টো)
note(sales, debit) → +1
note(purchase, debit) → +1 (bill-এর উল্টো)
note(purchase, credit) → −1
postNote(note, by):
যাচাই:
note.status == 'approved'
original.status NOT IN ('draft', 'cancelled')
প্রতিটি line: original_line ∈ original.lines
quantity ≤ original_line.qty − Σ আগের note qty (একই line)
Σ note.grand_total (এই + আগের, same original) ≤ original.grand_total
period(note.posting_date) খোলা; নইলে খোলা period, log
purchase debit note-এ VAT সমন্বয়ের সময়সীমা (config)
lineAccount(l):
sales credit: original_line.obligation_id ? 2180 : 4180 -- contract → deferred
purchase debit: original_line.debit_account_id -- মূল account
sales debit: original_line.revenue_account_id
purchase credit: original_line.debit_account_id
entry = buildDocumentEntry(note, directionOf(note))
post(entry)
-- contract line হলে position ঠিক করুন (অধ্যায় ১৭)
প্রতিটি line WHERE obligation_id: contract.billed_to_date −= l.line_net
-- allocation: মূল document open থাকলে
open = original.open_amount
a = min(note.grand_total, open)
যদি a > 0: allocate(note, [(original, a)]) -- source = credit_note / debit_note
-- বাকি (note.grand_total − a): party credit balance — unapplied note
note.status = 'posted'buildDocumentEntry()-তে TDS-এর line উল্টো চিহ্নে যায় — note-এও তাই: TDS-সহ bill-এর DN-এ 2150-ও কমে (TDS ইতিমধ্যে সরকারকে দেওয়া থাকলে — জটিল, অধ্যায় ৫৬; এখানে সতর্কতা)।
Advance — receipt-এর একটা পতাকা
payments (+)
is_advance BOOLEAN NOT NULL DEFAULT false
reference_doc VARCHAR(60) NULL -- proforma / quotation / contract নম্বর
applied_to_date DECIMAL(18,4) NOT NULL DEFAULT 0
refunded_to_date DECIMAL(18,4) NOT NULL DEFAULT 0
CHECK (applied_to_date + refunded_to_date <= amount)
open_advance(p) = p.amount − applied_to_date − refunded_to_datepostPayment()-এ (অধ্যায় ১১): is_advance হলে control account-এর বদলে advance account:
receipt, customer, is_advance → Cr 2160 (party) নইলে Cr 1130
payment, supplier, is_advance → Dr 1140 (party) নইলে Dr 21102160 আর 1140 — দুটোই party subledger রাখে (posted_lines.party_id), control account-এর মতো যাচাই: GL 2160 == Σ open_advance (customer)।
Advance-এর সমন্বয়
Invoice issue-র সময় (অধ্যায় ১৩-এর issueInvoice()-এর পরে):
applyAdvance(invoice, advance_payment, amount, by):
যাচাই:
advance.party_id == invoice.customer_id
amount ≤ open_advance(advance)
amount ≤ invoice.open_amount
entry = JV(posting_date = invoice.invoice_date,
source_type = 'advance_adjustment')
Dr 2160 (party) amount
Cr 1130 (party) amount
post(entry)
INSERT allocations (sales_invoice, invoice, 'advance', advance.id, amount)
advance.applied_to_date += amount
invoice.open_amount −= amount (allocate()-এর ভিতরে)Supplier-এ আয়না — Dr 2110 / Cr 1140, source = 'advance', bill-এ। UI: invoice তৈরির সময় গ্রাহকের open advance দেখান, default পুরোটা allocate, ব্যবহারকারী বদলাতে পারেন।
Refund:
refundAdvance(advance, amount, by):
payment(kind = payment, party = customer, refund_of = advance.id)
Dr 2160 (party) / Cr Bank
advance.refunded_to_date += amountUnapplied note — credit balance
CN-এর যে অংশ কোনো invoice-এ বাঁধা নেই:
unapplied_note(n) = n.grand_total − Σ allocations WHERE source = (credit_note, n.id)
পরে নতুন invoice এলে:
allocate(note, [(new_invoice, amount)]) -- source = credit_note, doc = নতুন invoice
-- GL entry নেই: CN post-এ 1130 আগেই কমেছে; শুধু কোন invoice-এ, তা এখন ঠিক হলো
ফেরত:
payment(kind = payment, party = customer, refund_of_note = n.id)
Dr 1130 (party) / Cr Bank
allocations: source = refundঅধ্যায় ১৪-এর receipt_allocations-এর source_type তালিকায় দুটো যোগ: refund, আর credit_note এখন দুই দিকে — মূল invoice-এ (open কমাতে) ও নতুন invoice-এ (unapplied note খরচ করতে)। CHECK-এ (অধ্যায় ১৬) refund যোগ করুন।
Reversal না note — কোডে
canCancel(invoice):
return invoice.sent_at IS NULL -- PDF/email যায়নি
and period(invoice.invoice_date) খোলা
and invoice.open_amount == invoice.grand_total -- কোনো allocation নেই
UI: "Cancel" button শুধু canCancel() হলে; নইলে "Issue credit note"sent_at — invoice email/print হওয়ার timestamp (অধ্যায় ১৩-এ ছিল না; যোগ করুন)। এটাই “কাগজ পৃথিবীতে গেছে কি না”।
Report
১. CN register / DN register — মাস-ধরে, reason-ধরে; VAT return-এর adjustment
২. Advance aging — open_advance > 0, বয়স; ৯০ দিনে সতর্কতা (টাকা নিয়ে কাজ হয়নি)
৩. Party credit balances — A/R-এ Cr, A/P-এ Dr; Balance Sheet reclassification-এর তালিকা
৪. Return rate — reason 'return'/'damaged'-এর CN ÷ sales, গ্রাহক/item-ধরে (ব্যবসার প্রশ্ন)
৫. Counterparty pending — purchase DN যার counterparty_note_no নেই, ৬০ দিনের বেশিরাতের যাচাই
৫০. প্রতিটি original: Σ notes.grand_total (posted) ≤ original.grand_total
৫১. GL 2160 == Σ open_advance (customer); GL 1140 == Σ open_advance (supplier)
৫২. notes.status = 'posted' কিন্তু journal_entry_id IS NULL → ০ সারি
৫৩. unapplied note ৩০ দিনের বেশি → সতর্কতা; advance ৯০ দিনের বেশি invoice ছাড়া → সতর্কতা
৫৪. purchase debit note, counterparty_note_no NULL, ৬০ দিন → সতর্কতা (supplier-কে তাগাদা)
৫৫. GL 4180 == Σ sales credit note lines (account 4180)
৫৬. note-এর party ≠ original-এর party → ০ সারিTest হিসেবে
test "credit note মূল মাসের revenue বদলায় না":
inv = issue(Sep, 4110, 3,80,000)
cn = post(creditNote(inv, Dec, line 20,000 VAT15))
assert revenue(4110, Sep) == 3,80,000
assert Δ 4180 (Dec) == +20,000; Δ 2140 == −3,000; Δ 1130 == −23,000
assert inv.open_amount == 15,000
test "CN invoice-এর বেশি নয়":
assert rejects creditNote(inv, line 1,50,000) -- inv 1,38,000
test "paid invoice-এ CN → credit balance, পরে allocate GL ছাড়া":
inv paid; cn = post(creditNote(inv, 11,500))
assert subledger(সালমা) == −11,500; unapplied_note(cn) == 11,500
g = snapshot(); inv2 = issue(সালমা, 50,000)
allocate(cn, [(inv2, 11,500)])
assert snapshot() == g; inv2.open_amount == 38,500
test "একই rule চার দিক":
প্রতিটি doc in [SV, PB, CN(sales), DN(purchase)]:
e = buildDocumentEntry(doc, directionOf(doc))
assert e.balanced()
assert CN.line(1130).credit > 0; DN.line(2110).debit > 0
test "advance: 2160-এ, A/R নয়; invoice-এ সমন্বয়":
adv = receive(সাগর, 1,00,000, is_advance)
assert Δ 2160 == −1,00,000 (Cr); Δ 1130 == 0
inv = issue(সাগর, 2,30,000); applyAdvance(inv, adv, 1,00,000)
assert Δ 2160 == +1,00,000; inv.open_amount == 1,30,000; open_advance(adv) == 0
test "cancel শুধু বেরোনোর আগে":
inv = issue(...); assert canCancel(inv)
send(inv); assert not canCancel(inv)
test "supplier-এর CN এলে entry নেই":
dn = post(debitNote(bill, 1,38,000)); g = snapshot()
linkCounterparty(dn, 'CN-TS-0412', 15-12)
assert snapshot() == g৬. Financial Statement Impact
INCOME STATEMENT (ডিসেম্বর)
4110 Software Dev. Income (নদী গ্রুপ 3,00,000 — অধ্যায় ১৭)
4180 Sales Returns & Allowances (30,000) ← contra; net revenue-র নিচে
(1520 asset 8,000 কমল — Income Statement-এ নয়)
BALANCE SHEET (৩১ ডিসেম্বর)
1130 A/R 0 (সালমার 11,500 Cr → liability-তে)
Customer credit balances 11,500 ← reclassified
2160 Customer Advance 1,00,000 (সাগর)
2140 VAT Payable −4,500 এ মাসের CN-এ
1160 VAT Receivable −1,200 DN-এ
1520 Furniture −8,000
CASH FLOW (operating)
advance এল +1,00,000 ← টাকা এসেছে, আয় নয়
refund গেল −3,100
supplier ফেরত দিল +9,200Income Statement-এ revenue দুই লাইনে দেখানোর রীতি: gross revenue − returns & allowances = net revenue। 4180 আলাদা রাখার কারণ এটাই — ম্যানেজমেন্ট জানতে চায় কত ফেরত আসছে, কেন। Purchase-এ contra নেই — asset ফেরত গেলে asset-ই কমে; Balance Sheet-এ শুধু ৭২,০০০-এর furniture।
Cash Flow-তে advance-এর ১,০০,০০০ ডিসেম্বরে operating inflow — যদিও আয় জানুয়ারি-ফেব্রুয়ারিতে হবে। অধ্যায় ১৭-এর তিন সংখ্যার গল্প, উল্টো দিক থেকে: এবার cash আগে, revenue পরে।
৭. Common Developer Mistakes
| ভুল | কী ঘটে | সঠিক পথ |
|---|---|---|
| ভুল invoice “edit” করা post-এর পরে | গ্রাহকের কাগজ আর আপনার খাতা আলাদা; audit trail নেই | cancel (reversal) বা CN — immutable |
| বেরিয়ে যাওয়া invoice cancel | গ্রাহকের A/P-তে আছে, আপনার নেই; VAT return মেলে না | sent_at → শুধু CN |
| CN-এ মূল মাসের revenue কমানো | ছাপা report বদলায়, VAT return জমা হয়ে গেছে | 4180, note-এর মাসে |
| CN মূল invoice ছাড়া (“free-standing”) | কিসের credit? VAT return-এ reference নেই | original_id NOT NULL, line-ধরে |
| CN invoice-এর বেশি | ঋণাত্মক invoice | Σ ≤ original, যাচাই ৫০ |
| Advance A/R-এ Cr (unapplied-এর মতো) | দেনা asset-এর ভিতরে লুকায়, aging নষ্ট | is_advance → 2160 |
| Advance revenue-তে | টাকা এল, আয় হলো — কাজ হয়নি | 2160, invoice-এ সমন্বয় |
| Advance সমন্বয়ে JV নেই, শুধু allocation | 2160 কখনো কমে না | JV Dr 2160 / Cr 1130 + allocation |
Proforma sales_invoices-এ | কেউ post করে ফেলে, gapless নম্বর নষ্ট | আলাদা table / quotation |
| Supplier-এর CN এলে দ্বিতীয় entry | দুবার কমল | আপনার DN একবার, counterparty নম্বর link |
| Supplier-এর CN-এর অপেক্ষায় DN না লেখা | মাল গেছে, দেনা কমেনি, statement মেলে না | DN ফেরতের দিনে |
| Paid invoice-এ CN → “Misc Income” | গ্রাহকের টাকা আপনার আয় | credit balance, ফেরত/পরের invoice |
| CN-এর জন্য আলাদা posting কোড | পঞ্চম copy, পঞ্চম bug | buildDocumentEntry(note, ±1) |
| Note-এ VAT মূল invoice-এর মাসে | VAT return সংশোধন | note-এর মাসে, adjustment |
| Credit balance report নেই | Balance Sheet-এ A/R কম দেখায়, liability লুকায় | party credit balances, reclassify |
প্রথম দুটোই মূল। “Edit” button-টা যে system-এ আছে, সেখানে বাকি সব নিয়ম অর্থহীন — কারণ যেকোনো সংখ্যা যেকোনো সময় বদলানো যায়। Post হওয়া document immutable; বদলাতে হলে নতুন document — এটাই এই অধ্যায়ের এক বাক্য, আর অধ্যায় ৪৩ ও ৪৫-এর ভিত্তি।
৮. Exercises
সেট ক — entry ও allocation
১। গ্রাহক advance 60,000 দিলেন ০৫-১২। invoice ২০-১২, 1,15,000 (VAT সহ)।
গ্রাহক বাকিটা দিলেন ০৫-০১। তিনটি entry + allocation। ৩১-১২-এ 2160,
1130?
২। ১ নম্বরে গ্রাহক project বাতিল করলেন ১০-১২, advance ফেরত চাইলেন,
আপনি 10,000 কেটে রাখলেন (চুক্তি অনুযায়ী)। entry? 10,000 কোন account?
৩। Invoice 2,30,000 (VAT সহ), ২টা line। গ্রাহক line 2-এর অর্ধেক ফেরত
দিলেন (net 40,000)। CN লিখুন — line-ধরে, VAT সহ। invoice open কত?
৪। ৩ নম্বরের invoice আগেই paid। CN-এর পরে কী? গ্রাহক ফেরত চাইলেন —
entry। গ্রাহক বললেন "পরের invoice-এ কাটুন" — পরের invoice 50,000
এলে allocation ও open।
৫। Supplier-এর bill 92,000 (VAT সহ), paid। ৮,০০০ + VAT-এর মাল ফেরত।
DN লিখুন। supplier ফেরত না দিয়ে পরের bill-এ কাটলেন (পরের bill
46,000) — allocation।
৬। Supplier-কে advance 40,000; bill এল 50,000, TDS 10%। সমন্বয়ের JV,
allocation, open, payment (অধ্যায় ১৬-এর রফিক — নিজে আবার লিখুন)।সেট খ — reversal না note
৭। প্রতিটির জন্য cancel না CN, কেন:
(ক) invoice ভুল অঙ্কে, ২ ঘণ্টা আগে, email যায়নি
(খ) invoice ভুল অঙ্কে, গ্রাহক email পেয়েছেন, একই দিন
(গ) invoice ঠিক, গ্রাহক ৩ সপ্তাহ পরে পণ্য ফেরত দিলেন
(ঘ) invoice দুবার issue হয়েছে (duplicate), দ্বিতীয়টা পাঠানো হয়নি,
কিন্তু মাস বন্ধ
(ঙ) invoice ঠিক গ্রাহক, ভুল VAT হার, পাঠানো হয়েছে
৮। (ঘ)-এর জন্য CN দিলে 4180-এ একটা অঙ্ক বসবে যেটা "ফেরত" নয়,
"duplicate"। Return rate report নষ্ট হবে। সমাধান?
৯। Contract invoice (অধ্যায় ১৭) 2,40,000 deferred-এ। গ্রাহক চুক্তি
কমালেন, CN 40,000। entry কোন account-এ — 4180 না 2180? position
কী হবে? recognized অংশে CN হলে?সেট গ — কোনটা ভুল
১০। advance receipt: Dr Bank / Cr 4110 Revenue — "টাকা তো এসেছে"
১১। advance receipt: Dr Bank / Cr 1130 A/R [গ্রাহক] — "unapplied-এর মতো"
১২। CN: Dr 4110 Revenue / Dr 2140 / Cr A/R — ডিসেম্বরে, সেপ্টেম্বরের invoice-এ
১৩। CN: original_id NULL — "গ্রাহককে ছাড় দিচ্ছি, কোনো invoice-এ নয়"
১৪। DN: Dr 2110 / Cr 4180 — supplier-কে ফেরত, "return তো"
১৫। Supplier-এর CN এল → Dr 2110 / Cr 1510 — DN আগেই লেখা ছিল
১৬। UPDATE sales_invoices SET grand_total = … WHERE status = 'issued'সেট ঘ — নকশা
১৭। notes table-এ চারটি (document_type, kind)। প্রতিটির direction,
party account, line account — table আকারে। কোনটা সবচেয়ে কম
দরকার, বাদ দিলে কী হারায়?
১৮। allocations.source_type-এ এখন: receipt, payment, discount,
credit_note, debit_note, write_off, advance, refund। credit_note
দুই দিকে (মূল invoice ও নতুন invoice) — CHECK constraint কীভাবে
লিখবেন? একটা CN-এর Σ allocation ≤ CN total — কোথায় যাচাই?
১৯। Inventory-র item ফেরত (অধ্যায় ২৭-এর আগাম): CN-এ stock বাড়ে, COGS
কমে। CN-এর কোন ধাপে? ফেরত মাল "ভালো" না "নষ্ট" — কে বলবে, কখন?
note_lines-এ এখন কী column রেখে দেবেন?
২০। Advance-এ VAT (দেশভেদে): advance পাওয়ার সময়েই output VAT।
entry কী হবে? invoice-এ সমন্বয়ের সময় VAT দুবার না হয় — কীভাবে?
config কোথায়?উত্তর আছে Workbook-এর Answer Key, অধ্যায় ১৯-এ।
৯. Developer Challenge
একটি AdjustmentDocumentService নকশা করুন — advance (দুই দিক), credit note, debit note — আর Part 2-র সব document-কে একটা DocumentPostingService-এ আনুন: SV, PB, CN, DN, receipt, payment, advance, refund।
যা যা নকশা করবেন:
১.
notes+note_lines— চারটি (type, kind), gapless নম্বর (type, kind)-ধরে,original_id NOT NULL, line-ধরে qty/amount সীমা,counterparty_note_no। Contract line-এর CN-এ 2180 ওbilled_to_date(অধ্যায় ১৭) — position ঋণাত্মক হয়ে গেলে (recognized > নতুন billed) কী?২.
directionOf(doc)+buildDocumentEntry()— Part 2-র প্রতিটি document একটাই function-এ। প্রতিটির জন্য test: balanced, party account সঠিক দিকে, VAT সঠিক account ও দিকে, TDS (থাকলে)। Direction-এর বাইরে কোন document-এifলাগে — সেটাই নকশার ফাঁক; তালিকা করুন।৩. Advance —
is_advance, 2160/1140 party subledger,applyAdvance()(JV + allocation),refundAdvance(), আংশিক সমন্বয় (advance 1,00,000, invoice 60,000 → বাকি 40,000 পরের invoice-এ), advance aging, project বাতিলে কাটা রাখা (exercise ২)।৪. Unapplied note — credit balance, statement-এ বার্তা, ফেরত বা পরের invoice-এ allocate (GL ছাড়া), ৩০ দিনে সতর্কতা। A/R-এর credit balance আর A/P-এর debit balance — Balance Sheet reclassification-এর query (অধ্যায় ২১-এর জন্য)।
৫. Cancel বনাম note —
sent_at,canCancel(), UI-তে একটাই button যা ঠিক কাজটা করে; period বন্ধ থাকলে CN-এর posting_date; “duplicate invoice” reason_code যাতে return rate নষ্ট না হয় (exercise ৮)।৬. Register ও VAT — CN/DN register মাস-ধরে, VAT return-এর adjustment line, দেশভেদে সময়সীমা config, মূল invoice-এর নম্বর/তারিখ note-এ ছাপা।
৭. Immutability — post হওয়া invoice/bill/note-এ
UPDATEআটকান: database trigger? application layer? দুটোই? কোন column বদলানো যাবে (narration? attachment?) — তালিকা ও যুক্তি। অধ্যায় ৪৫-এর audit trail-এর জন্য এখন কী রাখবেন?৮. রাতের যাচাই ৫০–৫৬। ৫১ ব্যর্থ হলে (GL 2160 ≠ Σ open advance): advance সমন্বয়ে JV হয়েছে কিন্তু
applied_to_dateবাড়েনি — নাকি উল্টো? কীভাবে আলাদা করবেন?২ আর ৭ নম্বরটাই আসল পরীক্ষা — আর এটাই Part 2-র শেষ পরীক্ষা। অধ্যায় ১৩-এর Developer Challenge-এ বলেছিলাম posting rule এমন হোক যাতে purchase একই কাঠামোয় চলে; অধ্যায় ১৫-এ direction এল; এখন আটটা document একটা function-এ। যদি সত্যিই একটাই function হয়, Part 5-এর Posting Rule Engine (অধ্যায় ৩৮) আপনার লেখা হয়ে গেছে। আর immutability — “post-এর পরে edit নেই, শুধু নতুন document” — এই এক নিয়ম না মানলে Part 2-র বাকি সব নিয়ম কাগজে থাকে, software-এ নয়।
১০. Summary Card
তিন document, এক চরিত্র
advance টাকা document-এর আগে 2160 (L) / 1140 (A) party-ধরে; invoice/bill-এ সমন্বয়
credit note invoice-এর পরে কমানো Dr 4180 (বা 2180), Dr 2140; Cr 1130
debit note bill-এর পরে কমানো Dr 2110; Cr মূল account, Cr 1160
কোনোটাই নিজে বিক্রি/ক্রয় নয় — আগের document-কে বদলায়তিন cousin
advance invoice নেই, কাজ নেই, ইচ্ছাকৃত → invoice-এ সমন্বয়
deferred invoice আছে, কাজ নেই → recognition
unapplied invoice আছে, মেলে না, দুর্ঘটনা → allocate / ফেরতReversal না note
document ভুল + বেরোয়নি + period খোলা + allocation নেই → cancel
নইলে → note, নিজের মাসে, মূল document-এর reference সহ
post হওয়া document immutable; বদল = নতুন documentNote-এর নিয়ম
original_id বাধ্যতামূলক; line-ধরে; Σ ≤ original
revenue/VAT note-এর মাসে (4180 contra); মূল মাস অপরিবর্তিত
open invoice নেই → credit balance → ফেরত / পরের invoice (GL ছাড়া allocate)
supplier-এর CN = আপনার DN-এর counterparty নম্বর — দ্বিতীয় entry নয়Direction
SV +1 PB −1 CN(sales) −1 DN(purchase) +1 — একটাই buildDocumentEntry()Developer checklist
□ notes + note_lines, (type, kind), gapless, original_id NOT NULL, সীমা
□ directionOf() → buildDocumentEntry() — আট document এক rule
□ payments.is_advance → 2160/1140, party subledger
□ applyAdvance(): JV + allocation source 'advance'; refundAdvance()
□ allocations.source_type: + refund; credit_note দুই দিকে; CHECK
□ unapplied note: credit balance, statement, ৩০ দিন
□ canCancel(): sent_at, period, allocation; UI একটাই button
□ contract line CN → 2180, billed_to_date
□ counterparty_note_no link — entry নয়
□ proforma আলাদা table
□ post হওয়া document immutable (trigger + app)
□ report: CN/DN register (VAT adjustment), advance aging, credit balances, return rate
□ রাতে: Σ note ≤ original, 2160/1140 == Σ open advance, JE link, বয়স,
counterparty, 4180, party মিলPart 2 শেষ
অধ্যায় ১১ থেকে ১৯ — নয়টি অধ্যায়, একটা software company-র আগস্ট ২০২৫ থেকে ফেব্রুয়ারি ২০২৬। Cash Book থেকে শুরু, তারপর ব্যাংকের সাথে মেলানো, বিক্রি, পাওনা, ক্রয়, দেনা, আয়-খরচের মাস, মাসের শেষের সমন্বয়, আর শেষে যা কিছু আগের document-কে বদলায়। প্রতিটি অধ্যায়ে একটাই GL, একটাই allocation table, একটাই posting rule — শুধু direction বদলেছে।
এখন যা আছে: প্রতিটি মাসের শেষে একটা Trial Balance যার প্রতিটি সংখ্যার নিচে একটা তালিকা — কোন invoice, কোন bill, কোন prepaid, কোন accrual, কোন contract। Part 3 — Financial Statements সেই Trial Balance থেকে শুরু: অধ্যায় ২০-এ Income Statement — এই কয়েক মাসের 4xxx আর 5xxx দিয়ে, “ব্যবসা কেমন চলল” এক পাতায়।
Part 2-র project ও exit criteria — Projects ও Exit Criteria পাতায়।