Skip to Content
Go Realm v1 is released 🎉
Accountingবই (Print Edition)অধ্যায় ১৬: Accounts Payable

অধ্যায় ১৬ — Accounts Payable

Volume 1 · Part 2 — Core Business Accounting · Chapter 16

পূর্বশর্ত: অধ্যায় ১৫ (Purchase), অধ্যায় ১৪ (Accounts Receivable — allocation ও aging), অধ্যায় ১১ (Cash ও Bank — payments, cheque, PDC)


১. Learning Objective

এই অধ্যায় শেষে আপনি পারবেন:

A/P-এর তিন স্তর — GL, supplier subledger, open bill — A/R-এর আয়নায় ব্যাখ্যা করতে Payment allocation নকশা করতে, আর A/R-এর allocation table-এর সাথে একটাই table-এ আনতে এক payment-এ বহু bill, আংশিক payment, বেশি payment — তিনটিই সামলাতে Settlement discount received-এর entry লিখতে, আর discount নেওয়া লাভজনক কি না — তা হিসাব করতে Payment run নকশা করতে: কাকে, কবে, কত — নগদের সীমার ভিতরে Supplier aging-কে cash forecast হিসেবে পড়তে Supplier-এর পাঠানো statement আপনার খাতার সাথে reconcile করতে PDC issue করলে A/P-এ কী হয়, আর কী হয় না — তা বলতে Supplier-এর bank account বদল — payment fraud-এর সবচেয়ে সাধারণ পথ — আটকাতে তিন-মুখী reconciliation: GL 2110 == subledger == open bill − unapplied — চালাতে

সময়: পড়া ৫০ মিনিট + অনুশীলন ৬০ মিনিট।


২. Concept Explanation

অপেক্ষা বনাম সিদ্ধান্ত

অধ্যায় ১৪-এ টাকা আসে — কবে আসবে, কত আসবে, আপনার হাতে নেই; আপনি তাগাদা দেন আর অপেক্ষা করেন। অধ্যায় ১৬-এ টাকা যায় — আর কবে, কত, কাকে আগে — প্রতিটি সিদ্ধান্ত আপনার।

A/R (অধ্যায় ১৪) A/P (অধ্যায় ১৬) ──────────────── ──────────────── receipt এলে allocate payment-এর আগে বাছাই, পরে allocate গ্রাহক কখন দেবেন — অনিশ্চিত আপনি কখন দেবেন — পরিকল্পনা aging: কে দিচ্ছে না aging: কাকে দিতে দেরি হচ্ছে, নগদ কত লাগবে discount allowed (আয় কমে) discount received (নেওয়া লাভজনক?) credit limit: গ্রাহককে কত দেবেন cash limit: নিজের কত আছে statement আপনি পাঠান statement supplier পাঠান, আপনি মেলান fraud: টাকা নিয়ে write-off fraud: ভুয়া supplier, বদলানো bank account

তাই এই অধ্যায়ের কাঠামো অধ্যায় ১৪-এরই — তিন স্তর, allocation, aging, statement — কিন্তু মাঝখানে একটা নতুন জিনিস: payment run। আর শেষে একটা নতুন ভয়: A/P হলো প্রতিষ্ঠান থেকে টাকা বেরোনোর সবচেয়ে বড় দরজা।

তিন স্তর — আয়না

স্তর ১ GL 2110 Accounts Payable 3,46,950 Cr স্তর ২ Subledger supplier-ধরে ব্যালেন্স বাড়িওয়ালা 61,750 ISP 9,200 টেক সাপ্লাই 2,76,000 স্তর ৩ Open items bill-ধরে বকেয়া PB-10-0001 বাড়িওয়ালা 61,750 (due 31-10) PB-10-0002 ISP 9,200 (due 28-10) PB-10-0003 টেক সাপ্লাই 2,76,000 (due 09-11) (4,14,000 − DN 1,38,000)

সূত্র একই, দিক উল্টো:

GL 2110 == Σ subledger (supplier) == Σ open bill − Σ unapplied payment

Unapplied payment — supplier-কে যা দিয়েছেন কিন্তু কোনো bill-এর সাথে বাঁধা নেই — এবার আপনার পাওনা (supplier আপনাকে ফেরত দেবেন বা পরের bill-এ কাটবেন)। A/R-এ unapplied receipt ছিল লুকানো liability; A/P-এ unapplied payment লুকানো asset। Balance Sheet-এ reclassify-এর নিয়ম একই।

Allocation — একটাই table, দুই দিক

অধ্যায় ১৪-এর receipt_allocations sales invoice-কে receipt-এর সাথে বাঁধত। এখন purchase bill-কে payment-এর সাথে বাঁধতে হবে। দুটো table নয় — অধ্যায় ১৫-এ posting rule-কে যেভাবে direction দিয়ে এক করেছি, allocation-ও তাই:

allocations document_type sales_invoice | purchase_invoice document_id source_type receipt | payment | discount | credit_note | debit_note | write_off | advance amount

একটা bill-এর open হিসাব A/R-এরই আয়না:

open = payable_total − Σ payment − Σ discount received − Σ debit note − Σ advance adjusted

তিনটি রূপও একই — আংশিক (৯-১১-এ ২,৭৬,০০০-এর বিপরীতে ১,৫০,০০০), এক payment বহু bill (এক supplier-কে তিনটা bill-এর টাকা এক transfer-এ), বেশি payment (ভুলে TDS না কেটে পুরো ৬৫,০০০ পাঠানো)। আর অধ্যায় ১৪-এর সবচেয়ে গুরুত্বপূর্ণ কথাটা এখানেও: allocation GL বদলায় নাDr A/P [supplier], Cr Bank payment post-এর সময়েই হয়ে গেছে।

Settlement discount received — নেবেন কি?

Supplier-এর শর্ত “২/১০ net ৩০”। ৯২,০০০-এর bill ১০ দিনে দিলে ৯০,১৬০:

Dr 2110 A/P [অফিস মার্ট] 92,000 ← bill পুরো বন্ধ Cr 1120 Bank 90,160 Cr 4540 Discount Received 1,840 ← আয় (4190-এর আয়না)

খরচ (বা asset) যা ছিল তাই — ৮০,০০০ furniture ৮০,০০০-ই। ছাড়টা bill-এর ঘটনা নয়, payment-এর ঘটনা, তাই আলাদা account। নীতিভেদে কেউ খরচ কমান (contra-expense); এই বইয়ে 4540, আয়।

A/R-এ প্রশ্ন ছিল “গ্রাহক ছাড় কেটেছেন কি ঠিকমতো”। A/P-এ প্রশ্ন “ছাড়টা নেওয়া উচিত কি” — আর উত্তরটা অঙ্কে:

২% ছাড়, ২০ দিন আগে দিলে (১০ দিনে, ৩০-এর বদলে) বার্ষিক হার = 2 / 98 × 365 / 20 ≈ 37%

২০ দিন আগে টাকা দিয়ে ২% বাঁচানো মানে বছরে ৩৭% return — ব্যাংক overdraft-এর সুদের (১২–১৫%) অনেক উপরে। নগদ থাকলে, বা overdraft নিলেও, ছাড় নেওয়া লাভজনক। সূত্রটা payment run-এ বসবে — system নিজেই বলবে কোন bill আগে দেওয়া বুদ্ধিমানের।

Payment run — কাকে, কবে, কত

A/R-এ receipt একটা একটা করে আসে। A/P-এ payment ব্যাচে হয় — সপ্তাহে একবার বা দুবার বসে সিদ্ধান্ত:

১. কী কী bill open — due কবে, ছাড় আছে কি, overdue কি ২. নগদ কত আছে — আর কত রাখতে হবে (বেতন, VAT, ভাড়া) ৩. বাছাই: ছাড়ের সময়সীমা আজ/কাল → প্রথমে (৩৭%) overdue → তারপর (সম্পর্ক, জরিমানা) due এই সপ্তাহে → তারপর due পরে → পরের run-এ ৪. মানুষ দেখেন, বদলান, অনুমোদন দেন ৫. execute: supplier-ধরে একটা payment, তার নিচে bill-ধরে allocation

ধাপ ৩ system-এর প্রস্তাব, ধাপ ৪ মানুষের সিদ্ধান্ত। আর ধাপ ৪-এ যিনি প্রস্তাব করেন তিনি অনুমোদন দেন না — অধ্যায় ১৫-এর bill approval-এর মতো, এখানে আরও কড়া: এটা আসল টাকা বেরোনোর মুহূর্ত।

Payment run-এর একটা গুরুত্বপূর্ণ ফল: supplier-ধরে একটা payment, bill-ধরে নয়। তিনটা bill-এর জন্য তিনটা transfer নয় — একটা transfer, তিনটা allocation। Supplier-এর remittance advice-এ তিনটা bill নম্বর — যাতে তার A/R-এ allocation ঠিক হয়।

Supplier aging — cash forecast

Bucket, due date থেকে বয়স, as-of — সব অধ্যায় ১৪-এর মতো। কিন্তু পড়ার ভঙ্গি আলাদা:

A/R aging "90+-এ কত আটকে আছে" → আদায়ের চাপ, bad debt A/P aging "আগামী ৩০ দিনে কত দিতে হবে" → নগদ লাগবে কত

তাই A/P aging-এ প্রায়ই bucket উল্টো দিকেও থাকে — due in 0–7, 8–30, 31–60 — সামনের দিকে। এটা cash flow forecast-এর কাঁচামাল (অধ্যায় ২২): সামনের মাসের A/P due + বেতন + VAT − প্রত্যাশিত receipt = নগদ ঘাটতি বা উদ্বৃত্ত।

Overdue bucket-এ টাকা থাকা A/P-তে সবসময় খারাপ নয় — কখনো ইচ্ছাকৃত (নগদ নেই, supplier-কে জানানো আছে)। কিন্তু অজান্তে overdue মানে bill অনুমোদনে আটকে আছে বা কেউ ভুলে গেছে — দুটোই রাতের যাচাইয়ে ধরা পড়া উচিত।

Supplier statement reconciliation

অধ্যায় ১৪-এ আপনি গ্রাহককে statement পাঠিয়েছেন। এবার supplier আপনাকে পাঠান — “আমার খাতায় আপনি ২,৬৪,০০০ দেবেন।” আপনার খাতায় ১,২৬,০০০। পার্থক্য ১,৩৮,০০০ — কে ঠিক?

এটা অধ্যায় ১২-এর bank reconciliation-এর হুবহু কাঠামো — দুই পাশের খাতা, line ধরে match, পার্থক্যের প্রকার:

১ timing আপনার খাতায় আছে, তার নেই অপেক্ষা / জানান → আপনার debit note, transit-এ payment ২ তার-only তার খাতায় আছে, আপনার নেই bill চান / entry → bill এখনো আসেনি, তার interest charge ৩ ভুল যেকোনো পাশে সংশোধনী / বিতর্ক → দর ভুল, দুবার bill, ভুল supplier

Reconciliation ছাড়া statement-এর সংখ্যা মেনে নেওয়া — সবচেয়ে সাধারণ overpayment-এর কারণ: supplier-এর statement-এ আপনার debit note নেই, আপনি “statement অনুযায়ী” দিয়ে দিলেন। আপনার খাতাই সত্য; statement যাচাইয়ের উপকরণ।

PDC issue — দেনা থাকে, cheque ঘোরে

Supplier-কে ৫ ডিসেম্বরের তারিখ লেখা cheque আজ (২৫ নভেম্বর) দিলেন। অধ্যায় ১১-এর নিয়ম উল্টো দিকে:

২৫-১১ payment তৈরি, status = 'draft', instrument_date = 05-12 journal entry নেই → A/P-এ 1,26,000 এখনো open, Bank কমেনি allocation নেই — কারণ payment post হয়নি ০৫-১২ scheduled কাজ post করে: Dr 2110 [টেক], Cr 1120 তারপর allocation

কিন্তু ৩০ নভেম্বরের aging-এ এই bill “overdue” দেখাবে — যদিও cheque দেওয়া আছে। তাই aging-এ একটা memo column: PDC issued। আর supplier-এর হাতে আপনার cheque আছে — তার খাতায় সে টাকা পেয়েছে ধরতেও পারে; statement reconciliation-এ এটা timing পার্থক্য।

আরেকটা সূক্ষ্মতা: আজকের তারিখের cheque দিলে A/P তখনই বন্ধ, Bank তখনই কমে — কিন্তু cheque clear হয় ৩–৭ দিন পরে। সেই ফাঁকটা bank reconciliation-এর কাজ (unpresented cheque, অধ্যায় ১২), A/P-এর নয়।

Supplier bank account — সবচেয়ে বড় দরজা

A/P-এ টাকা যায় supplier-এর bank account-এ। সেই account নম্বর কোথা থেকে আসে? Supplier master থেকে। কে বদলাতে পারেন? এই প্রশ্নটাই payment fraud-এর কেন্দ্র:

email আসে supplier-এর নামে: "আমাদের bank account বদলেছে, নতুন নম্বর…" কেউ master-এ বদলে দেন পরের payment run-এ 2,76,000 চলে যায় — অন্য কারো account-এ supplier দুই সপ্তাহ পরে ফোন করেন: "টাকা পাইনি"

এটা accounting-এর bug নয় — entry নিখুঁত, allocation নিখুঁত, তিন স্তর মিলে যায়। শুধু টাকা ভুল জায়গায়। প্রতিরোধ software-এ:

১. bank account বদল = আলাদা অনুমতি, আলাদা অনুমোদন (দুজন) ২. বদলের পরে N দিন (৭–১৪) নতুন account-এ payment আটকে থাকে — অথবা ফোনে যাচাই (email-এ নয়, master-এর পুরনো নম্বরে) ৩. payment file-এ account নম্বর master থেকে — user input থেকে কখনো নয় ৪. বদলের log: কে, কখন, আগে কী ছিল ৫. payment run-এর অনুমোদনে দেখানো: "এই supplier-এর bank account গত ৩০ দিনে বদলেছে"

অধ্যায় ৪৮-এ পুরো ছবি; এখানে schema-তে জায়গা রাখা — supplier_bank_accounts, আলাদা table, verified পতাকা সহ।

Bill-এর জীবনচক্র — শেষ অংশ

অধ্যায় ১৫-এ posted পর্যন্ত এসেছিল। এবার বাকিটা:

POSTED ├──▶ payment run-এ নির্বাচিত ──▶ PARTIALLY PAID ──▶ PAID ├──▶ PDC issued (memo; status বদলায় না) ├──▶ on hold (বিতর্ক — statement-এ মেলেনি, মাল ফেরত) → payment run বাদ দেয় └──▶ debit note (অধ্যায় ১৯) → open কমে

on_hold একটা পতাকা, status নয় — bill posted-ই থাকে (দেনা আছে), শুধু payment run তাকে প্রস্তাবে তোলে না। কারণ লেখা থাকে, আর ৩০ দিনের বেশি hold-এ থাকলে সতর্কতা।


৩. Accounting Rule

Entry

ঘটনাDebitCredit
Payment (পুরো / আংশিক / unapplied)A/P [supplier]Bank
Settlement discount সহ paymentA/P [supplier] (পুরো)Bank (নিট), Discount Received
Advance-এর সমন্বয়A/P [supplier]Advance to Supplier
Debit note (অধ্যায় ১৯)A/P [supplier]Expense/Asset, VAT Receivable
Unapplied ফেরত পাওয়াBankA/P [supplier]
TDS সরকারকে (অধ্যায় ৫৬)TDS PayableBank
PDC issue— (কিছু না, তারিখ পর্যন্ত)

Journal entry-তে যা কখনো হয় না

Payment-এ Expense (খরচ bill-এ, একবার) Discount-এ Expense কমানো (আলাদা account — নীতি হিসেবে ঠিক করা) PDC-র তারিখের আগে Bank (cheque টাকা নয়, প্রতিশ্রুতি)

Allocation

প্রতিটি open bill-এর জন্য: open = payable_total − Σ payment − Σ discount received − Σ debit note − Σ advance adjusted allocation-এর যোগফল ≤ payment-এর অঙ্ক payment − allocated = unapplied (supplier-এর কাছে আপনার পাওনা)

তিন-মুখী সূত্র

GL 2110 == Σ subledger (supplier) == Σ open bill − Σ unapplied payment

Discount নেওয়া হবে কি

বার্ষিক হার = pct / (1 − pct) × 365 / (net_days − discount_days) হার > overdraft/ঋণের সুদ → নেওয়া লাভজনক (নগদ থাকলে বা ধার করেও)

অলঙ্ঘনীয়

Payment run: প্রস্তাবকারী ≠ অনুমোদনকারী Bank account: master থেকে, বদলে দুজনের অনুমোদন + অপেক্ষা

৪. Real Business Example

নভেম্বর ২০২৫ — দেওয়ার মাস

১ নভেম্বরে open bills — অধ্যায় ১৫-এর অক্টোবর থেকে:

Bill Supplier bill due payable open ──── ──────── ──── ─── ─────── ──── PB-10-0001 বাড়িওয়ালা 01-10 31-10 61,750 61,750 ← ১ দিন overdue PB-10-0002 ISP 28-09 28-10 9,200 9,200 ← ৪ দিন overdue PB-10-0003 টেক সাপ্লাই 10-10 09-11 4,14,000 2,76,000 ← DN 1,38,000 বাদে ──────── GL 2110 3,46,950 ✓ আর: 1140 Advance to Supplier — contractor রফিক 40,000 2150 TDS Payable — অক্টোবরের ভাড়া 3,250 1120 Bank — Prime 4,60,000

০১-১১ — নভেম্বরের ভাড়ার bill, ৬৫,০০০, TDS ৫%, due ০১-১২

PB-11-0001 Dr 5220 Office Rent 65,000 Cr 2150 TDS Payable 3,250 Cr 2110 A/P [বাড়িওয়ালা] 61,750

০৩-১১ — অক্টোবরের ভাড়া transfer: ৬৫,০০০ — ভুল

নতুন accountant bill-এর ৬৫,০০০ দেখে পুরোটাই পাঠিয়ে দিলেন; payable ছিল ৬১,৭৫০।

PV-11-0001 Dr 2110 A/P [বাড়িওয়ালা] 65,000 Cr 1120 Bank — Prime 65,000 allocation: PB-10-0001 61,750 → open 0 → paid unapplied 3,250 ← বাড়িওয়ালার কাছে আপনার পাওনা

ভুলটা ধরা পড়ল allocation-এ — ৬৫,০০০ কোনো bill-এর সাথে পুরো মেলে না। Allocation না থাকলে এই ৩,২৫০ কখনো ধরা পড়ত না — subledger-এ বাড়িওয়ালা ৫৮,৫০০ দেখাত, আর সবাই ভাবত ঠিকই আছে।

০৫-১১ — ৩,২৫০ নভেম্বরের bill-এ allocate; ISP-কে ৯,২০০

allocation (GL entry নেই): unapplied PV-11-0001 3,250 → PB-11-0001 → open 58,500 PV-11-0002 Dr 2110 A/P [ISP] 9,200 Cr 1120 Bank — Prime 9,200 allocation: PB-10-0002 9,200 → paid

বাড়িওয়ালাকে জানানো হলো: “নভেম্বরে ৫৮,৫০০ পাবেন।” Journal entry একটাও নয় — শুধু allocation table-এ একটা সারি সরল।

০৭-১১ — অক্টোবরের TDS সরকারকে

PV-11-0003 Dr 2150 TDS Payable 3,250 Cr 1120 Bank — Prime 3,250

TDS-এর challan, certificate — অধ্যায় ৫৬। এখানে শুধু: এটা supplier-কে payment নয়, তাই A/P স্পর্শ হয় না, allocation নেই।

১০-১১ — টেক সাপ্লাই due ০৯-১১, ২,৭৬,০০০; নগদ টানাটানি — আংশিক

মাসের শেষে বেতন ২,৪০,০০০ যাবে। পুরোটা এখন দিলে বেতনে টান পড়বে। Supplier-কে ফোন: ১,৫০,০০০ এখন, বাকিটা ৫ ডিসেম্বরে — মেনে নিলেন।

PV-11-0004 Dr 2110 A/P [টেক সাপ্লাই] 1,50,000 Cr 1120 Bank — Prime 1,50,000 allocation: PB-10-0003 1,50,000 → open 1,26,000 → partially_paid bill note: "বাকি 05-12, ফোনে সম্মত — [নাম], 10-11"

১২-১১ — অফিস মার্ট থেকে আসবাব ৮০,০০০ + VAT ১২,০০০; শর্ত ২/১০ net ৩০

Dr কোথায়? আসবাব, threshold-এর উপরে → Asset PB-11-0002 (supplier bill: "OM-7731", bill 12-11, due 12-12, ছাড় ২২-১১ পর্যন্ত) Dr 1520 Furniture & Fixtures 80,000 Dr 1160 VAT Receivable 12,000 Cr 2110 A/P [অফিস মার্ট] 92,000

১৫-১১ — contractor রফিকের bill ৫০,০০০, TDS ১০%; advance ৪০,০০০ সমন্বয়

PB-11-0003 Dr 5270 Professional Fee 50,000 Cr 2150 TDS Payable 5,000 Cr 2110 A/P [রফিক] 45,000 JV-11-0005 advance adjustment Dr 2110 A/P [রফিক] 40,000 Cr 1140 Advance to Supplier 40,000 allocation: PB-11-0003 45,000 − advance 40,000 = open 5,000

অধ্যায় ১৪-এর সালমার advance-এর আয়না: advance asset থেকে সরে A/P কমাল; allocation-এ source_type = 'advance'

২০-১১ — Payment run

Open bills, নগদ, প্রস্তাব:

PAYMENT RUN PR-11-0002 — প্রস্তাব, 20-11-2025 Bill Supplier due open ছাড় বার্ষিক overdue ──── ──────── ─── ──── ─── ────── ─────── PB-11-0002 অফিস মার্ট 12-12 92,000 1,840 37% — PB-10-0003 টেক সাপ্লাই 09-11 1,26,000 — — 11 দিন PB-11-0001 বাড়িওয়ালা 01-12 58,500 — — — PB-11-0003 রফিক 15-12 5,000 — — — প্রস্তাব ✓ PB-11-0002 90,160 ছাড় 22-11 পর্যন্ত — আগে ✗ PB-10-0003 — PDC 05-12, ফোনে সম্মত ✓ PB-11-0001 58,500 ✓ PB-11-0003 5,000 ──────── মোট 1,53,660 Bank — Prime আজ 2,32,550 সংরক্ষিত: বেতন 30-11 (2,40,000) ← ! প্রত্যাশিত receipt এ মাসে 3,14,000 (করিম 38,000 + নদী গ্রুপ 2,76,000 — অধ্যায় ১৭) ব্যবহারযোগ্য 3,06,550 প্রস্তাবের পরে 1,52,890 ✓

তিনটি সিদ্ধান্ত পড়ুন: অফিস মার্ট প্রথমে — দুই দিন পরে ছাড় হারাবে, ৩৭%। টেক সাপ্লাই overdue, কিন্তু সম্মতি আছে — PDC। বাড়িওয়ালা due ০১-১২, পরের run ২৮-১১-এ দিলেও হতো — কিন্তু নগদ আছে, সম্পর্ক ভালো থাকুক। প্রস্তাব করলেন accountant; অনুমোদন দিলেন finance manager — আলাদা মানুষ।

Execute:

PV-11-0006 অফিস মার্ট Dr 2110 A/P [অফিস মার্ট] 92,000 Cr 1120 Bank — Prime 90,160 Cr 4540 Discount Received 1,840 allocation: PB-11-0002 payment 90,160 + discount 1,840 → paid PV-11-0007 বাড়িওয়ালা Dr 2110 A/P [বাড়িওয়ালা] 58,500 Cr 1120 Bank — Prime 58,500 allocation: PB-11-0001 58,500 → paid (3,250 unapplied + 58,500 = 61,750 ✓) PV-11-0008 রফিক Dr 2110 A/P [রফিক] 5,000 Cr 1120 Bank — Prime 5,000 allocation: PB-11-0003 5,000 → paid (advance 40,000 + 5,000 = 45,000 ✓)

তিনটা payment, একটা run — payment_run_id তিনটাতেই।

২৫-১১ — টেক সাপ্লাইকে PDC ১,২৬,০০০, তারিখ ০৫-১২

payment PV-11-0009: status = 'draft', method = cheque, instrument_date = 05-12, amount 1,26,000 journal entry: নেই A/P [টেক]: 1,26,000 open — অপরিবর্তিত bill memo: PDC issued 05-12, cheque #001187

২৬-১১ — টেক সাপ্লাইয়ের statement এল: “বকেয়া ২,৬৪,০০০”

তার খাতা (আপনি তার গ্রাহক) আপনার খাতা ─────────────────────── ────────── Invoice TS/2025/1190 4,14,000 PB-10-0003 4,14,000 Receipt 10-11 (1,50,000) PV-11-0004 (1,50,000) DN-10-0006 (1,38,000) ← তার খাতায় নেই ───────────────────────────── ────────────────────── ব্যালেন্স 2,64,000 ব্যালেন্স 1,26,000 পার্থক্য 1,38,000 = ঠিক DN-10-0006

প্রকার ১ — timing: আপনার debit note তার খাতায় credit note হিসেবে বসেনি (ফেরত laptop-এর জন্য এখনো credit note দেয়নি)। কাজ: supplier-কে credit note চাওয়া, bill-এ statement_reconciled_at = 26-11, difference = DN-10-0006 pendingPDC ইতিমধ্যে ১,২৬,০০০-এর — statement-এর ২,৬৪,০০০ দেখে দ্বিতীয় cheque নয়।

৩০ নভেম্বর — তিন স্তর মেলান

স্তর ১ — GL 2110:

opening 3,46,950 + PB-11-0001 61,750 − PV-11-0001 65,000 − PV-11-0002 9,200 − PV-11-0004 1,50,000 + PB-11-0002 92,000 + PB-11-0003 45,000 − JV-11-0005 (advance) 40,000 − PV-11-0006 92,000 − PV-11-0007 58,500 − PV-11-0008 5,000 ───────── closing 1,26,000 Cr

স্তর ২ — subledger:

টেক সাপ্লাই 1,26,000 Cr বাড়িওয়ালা 0 (61,750 + 61,750 − 65,000 − 58,500) ISP 0 অফিস মার্ট 0 রফিক 0 ──────── 1,26,000 Cr ✓

স্তর ৩ — open items:

PB-10-0003 টেক সাপ্লাই open 1,26,000 (PDC issued 05-12) unapplied 0 ──────── 1,26,000 ✓

Supplier aging — ৩০ নভেম্বর

A/P AGING — as of 30-11-2025 Supplier Current 1–30 31–60 61–90 90+ মোট memo ──────── ─────── ──── ───── ───── ─── ─── ──── টেক সাপ্লাই 1,26,000 1,26,000 PDC 05-12 (PB-10-0003, due 09-11, 21 দিন) ──────── 1,26,000 1,26,000 ✓ == GL সামনের দিকে (cash forecast): 0–7 দিনে due 1,26,000 (PDC — cheque clear হবে) 8–30 দিনে due 0 + বেতন 30-11 2,40,000 + VAT net (অধ্যায় ৫৫) ~50,000

তুলনার জন্য ১ নভেম্বরের aging: ৭১,০০০ overdue (দুই bill), ২,৭৬,০০০ current। এক মাসে সব বন্ধ, একটা বাকি — যেটা সম্মতিতে। A/P aging-এ “overdue শূন্য” লক্ষ্য নয়; “অজানা overdue শূন্য” লক্ষ্য।

মাসের নগদ

payment 3,81,110 (65,000 + 9,200 + 3,250 + 1,50,000 + 90,160 + 58,500 + 5,000) ছাড় পেয়ে বাঁচল 1,840 bill হলো (payable) 1,98,750 (61,750 + 92,000 + 45,000) A/P কমল 2,20,950 (3,46,950 → 1,26,000)

“কত bill এল” আর “কত টাকা গেল” আলাদা — অধ্যায় ১৫-এর “কত কিনলাম বনাম কত খরচ”-এর পরের ধাপ। তিনটি সংখ্যা, তিনটি report: purchase register, cash book, A/P movement।


৫. Implementation — Software ও Database

Allocation — একটা table, দুই দিক

অধ্যায় ১৪-এর receipt_allocations কে সাধারণ করুন:

allocations id BIGINT PK company_id BIGINT FK document_type VARCHAR(20) -- sales_invoice | purchase_invoice document_id BIGINT -- invoice বা bill source_type VARCHAR(20) -- receipt | payment | discount | credit_note -- | debit_note | write_off | advance source_id BIGINT -- payments.id, notes.id, JV id amount DECIMAL(18,4) -- document-এর open কমায় allocation_date DATE -- as-of aging allocated_at, allocated_by CHECK (amount > 0) CHECK ((document_type = 'sales_invoice' AND source_type IN ('receipt','discount','credit_note','write_off','advance')) OR (document_type = 'purchase_invoice' AND source_type IN ('payment','discount','debit_note','advance'))) INDEX (document_type, document_id) INDEX (source_type, source_id)

CHECK-টা গুরুত্বপূর্ণ — sales invoice-এ payment allocate হওয়া, বা bill-এ write_off — দুটোই bug, database-ই আটকাক। (Supplier-এর দেনা “write-off” করা — অর্থাৎ না দিয়ে মুছে ফেলা — হয়, কিন্তু সেটা অন্য জিনিস: Cr Other Income, আর তার নিজের অনুমোদন। অধ্যায় ১৯।)

purchase_invoices-এও একই দুটো সংরক্ষিত column:

purchase_invoices (+) amount_settled DECIMAL(18,4) NOT NULL DEFAULT 0 open_amount DECIMAL(18,4) NOT NULL -- payable_total − amount_settled on_hold BOOLEAN NOT NULL DEFAULT false hold_reason TEXT NULL pdc_payment_id BIGINT FK NULL -- memo: PDC দেওয়া আছে statement_reconciled_at DATE NULL

allocate() — direction সহ

অধ্যায় ১৪-এর allocate()-এর সাথে পার্থক্য শুধু party-র প্রকার আর document table:

allocate(source, [(doc, amount)...], by): lock source, lock প্রতিটি doc (FOR UPDATE) যাচাই: source.status == 'posted' -- PDC (draft) allocate হয় না প্রতিটি doc.party_id == source.party_id doc.document_type মেলে source.kind-এর সাথে -- payment ↔ purchase_invoice SUM(amount) ≤ unapplied(source) প্রতিটি: amount ≤ doc.open_amount doc.on_hold == false (নইলে override অনুমতি + log) প্রতিটি (doc, amount): INSERT allocations (doc.type, doc.id, source.type, source.id, amount, allocation_date = source.doc_date) doc.amount_settled += amount; doc.open_amount −= amount doc.status = open_amount == 0 ? 'paid' : 'partially_paid' -- journal entry নেই

Reallocation (০৫-১১-এর ৩,২৫০): পুরনো সারি নেই (unapplied-এর কোনো সারি ছিল না), শুধু নতুন সারি — allocations (purchase_invoice, PB-11-0001, payment, PV-11-0001, 3,250)। GL অপরিবর্তিত। ভুল bill-এ বাঁধা থাকলে: সারি মুছে নতুন সারি, দুটোই audit log-এ (অধ্যায় ৪৫)।

Payment run

payment_runs id, company_id run_no VARCHAR(40) -- PR-11-0002 run_date DATE cash_bank_account_id BIGINT FK cash_available DECIMAL(18,4) -- সেদিনের ব্যালেন্স (snapshot) cash_reserve DECIMAL(18,4) -- বেতন, VAT — বাদ রাখা status VARCHAR(20) -- proposed | approved | executed | cancelled proposed_by, approved_by, executed_at CHECK (proposed_by <> approved_by) -- segregation, database-এই payment_run_lines id, run_id bill_id BIGINT FK supplier_id BIGINT FK open_amount DECIMAL(18,4) -- প্রস্তাবের সময় discount_available DECIMAL(18,4) -- এই run-এর তারিখে দিলে annualized_rate DECIMAL(8,4) NULL pay_amount DECIMAL(18,4) -- ব্যবহারকারী বদলাতে পারেন selected BOOLEAN skip_reason TEXT NULL -- "PDC 05-12", "on hold" payment_id BIGINT FK NULL -- execute-এর পরে

প্রস্তাব:

proposePaymentRun(as_of, horizon_days, cash, reserve): budget = cash − reserve + expected_receipts(as_of, horizon_days) -- A/R aging থেকে bills = open purchase_invoices WHERE status IN ('posted','partially_paid') AND on_hold = false AND pdc_payment_id IS NULL AND (due_date ≤ as_of + horizon OR discount_deadline BETWEEN as_of AND as_of + horizon) প্রতিটি bill: disc = discountIf(bill, paid_on = as_of) -- 0 হতে পারে rate = disc > 0 ? annualized(bill.terms) : null priority = disc > 0 ? (1, −rate) -- ছাড় আগে, বড় হার আগে : due_date < as_of ? (2, due_date) -- overdue, পুরনো আগে : (3, due_date) lines = sort by priority running = 0 প্রতিটি line: pay = line.open − line.disc selected = running + pay ≤ budget যদি selected: running += pay নইলে skip_reason = "budget" INSERT payment_runs (status = proposed), lines return run -- মানুষ দেখেন, বদলান

annualized():

annualized(terms): -- "2/10 net 30" return terms.pct / (1 − terms.pct) × 365 / (terms.net_days − terms.discount_days)

Execute — supplier-ধরে একটা payment:

executePaymentRun(run, by): যাচাই: run.status == 'approved', by ≠ run.proposed_by প্রতিটি supplier in run.lines WHERE selected, GROUP BY supplier: bank = supplier.verified_bank_account() -- নিচে pmt = createPayment(kind = 'payment', party = supplier, amount = Σ pay_amount, method = transfer, bank_account = bank, payment_run_id = run.id) disc = Σ discount_available WHERE selected entry: Dr 2110 [supplier] Σ(pay + disc) Cr Bank Σ pay Cr 4540 disc (থাকলে) post(pmt) allocate(pmt, [(bill, pay) ...]) প্রতিটি bill যার disc > 0: INSERT allocations (bill, 'discount', entry.id, disc) line.payment_id = pmt.id run.status = 'executed' generate remittance advice per supplier (bill নম্বর সহ) generate bank payment file (থাকলে — অধ্যায় ৫০)

একই supplier-এর তিনটা bill → একটা payments সারি, তিনটা allocations সারি, একটা journal entry। Remittance advice-এ তিনটা bill নম্বর — supplier-এর অধ্যায় ১৪ যাতে সহজ হয়।

Discount received-এর যুক্তি

A/R-এ system সনাক্ত করত গ্রাহক ছাড় কেটেছেন কি না। A/P-এ system প্রস্তাব করে:

discountIf(bill, paid_on): যদি bill.terms.pct > 0 এবং paid_on ≤ bill.bill_date + bill.terms.discount_days এবং bill.open_amount == bill.payable_total: -- আংশিক-এ ছাড় নয় (নীতি) return bill.open_amount × bill.terms.pct return 0

শেষ শর্তটা নীতির — কিছু supplier আংশিক payment-এও আনুপাতিক ছাড় দেন; config। আর ছাড়টা VAT-সহ মোটের উপর না net-এর উপর — supplier-এর শর্ত অনুযায়ী, দেশভেদে ভিন্ন (অধ্যায় ৫৫)। উদাহরণে মোটের উপর।

Supplier bank account

supplier_bank_accounts id, supplier_id bank_name, branch, account_no, account_name, routing is_primary BOOLEAN verified BOOLEAN NOT NULL DEFAULT false verified_by, verified_at, verification_method -- phone | document | test_payment effective_from DATE -- বদলের পরে অপেক্ষা created_by, created_at replaced_id BIGINT FK NULL -- আগেরটা কোনটা ছিল supplier.verified_bank_account(): a = primary WHERE verified AND effective_from ≤ today যদি a নেই: reject("supplier-এর verified bank account নেই") যদি a.created_at > today − 30: flag("bank account সম্প্রতি বদলেছে") -- run-এর অনুমোদনে দেখান return a

Account নম্বর কখনো payment screen-এ type করা হয় না; payment file master থেকেই। verified set করা আলাদা অনুমতি, যিনি create করেছেন তিনি নন।

PDC issued

অধ্যায় ১১-এর একই কাঠামো, দিক উল্টো — kind = 'payment', status = 'draft', instrument_date ভবিষ্যৎ, journal entry নেই। বাড়তি:

issuePDC(bill, cheque_no, instrument_date, by): pmt = createPayment(kind = payment, party = bill.supplier, method = cheque, instrument_no = cheque_no, instrument_date, status = draft) bill.pdc_payment_id = pmt.id -- memo: aging-এ দেখাবে, run-এ বাদ scheduled (প্রতিদিন): প্রতিটি payments WHERE kind = payment, method = cheque, status = draft, instrument_date ≤ today: postPayment(pmt, doc_date = instrument_date) allocate(pmt, [(bill, amount)]) -- bill pdc_payment_id থেকে bill.pdc_payment_id = NULL

PDC বাতিল (supplier cheque ফেরত দিলেন): payment cancelled, pdc_payment_id = NULL, bill আবার run-এ আসবে। কোনো reversal নেই — কারণ কোনো entry ছিল না।

Supplier statement reconciliation

অধ্যায় ১২-এর matching engine পুনর্ব্যবহার — শুধু দুই পাশ বদলে:

supplier_statements id, supplier_id, statement_date, closing_balance, file_url supplier_statement_lines id, statement_id, line_date, ref, description, debit, credit matched_type / matched_id -- purchase_invoice | payment | debit_note match_status -- matched | unmatched | disputed reconcileSupplierStatement(stmt): ours = subledger lines (supplier, ≤ statement_date) auto-match: ref == supplier_bill_no | amount + date ± 3 unmatched তার পাশে → "bill আসেনি?" / "তার charge" unmatched আমাদের পাশে → "আমাদের DN তার খাতায় নেই" / "payment transit-এ" / PDC summary: তার closing − Σ(তার-only) + Σ(আমাদের-only) == আমাদের subledger ✓

২৬-১১-এর উদাহরণে: তার ২,৬৪,০০০ − ০ + (−১,৩৮,০০০ DN) = ১,২৬,০০০ ✓। Statement reconcile হলে purchase_invoices.statement_reconciled_at update — auditor-এর প্রথম প্রশ্ন “বড় supplier-দের statement মেলানো হয়েছে?”

Aging — একটাই query, direction parameter

অধ্যায় ১৪-এর query-তে sales_invoicespurchase_invoices, receiptpayment, customersupplier — আর কিছু নয়। allocations এক table হওয়ায় সত্যিই একটা query, document_type parameter:

WITH open_items AS ( SELECT d.id, d.party_id, d.due_date, d.pdc_payment_id, d.payable_total − COALESCE((SELECT SUM(a.amount) FROM allocations a WHERE a.document_type = :doc_type AND a.document_id = d.id AND a.allocation_date <= :as_of), 0) AS open_amt FROM :document_table d WHERE d.company_id = :c AND d.status NOT IN ('draft','received','cancelled') AND d.posting_date <= :as_of ), unapplied AS ( SELECT p.party_id, SUM(p.amount) − COALESCE(SUM(a.amount), 0) AS unapplied_amt FROM payments p LEFT JOIN allocations a ON a.source_type = :source_type AND a.source_id = p.id AND a.allocation_date <= :as_of WHERE p.kind = :payment_kind AND p.party_type = :party_type AND p.status = 'posted' AND p.doc_date <= :as_of GROUP BY p.party_id ) SELECT s.name, SUM(CASE WHEN :as_of <= o.due_date THEN open_amt END) AS current, SUM(CASE WHEN :as_of − o.due_date BETWEEN 1 AND 30 THEN open_amt END) AS d1_30, SUM(CASE WHEN :as_of − o.due_date BETWEEN 31 AND 60 THEN open_amt END) AS d31_60, SUM(CASE WHEN :as_of − o.due_date BETWEEN 61 AND 90 THEN open_amt END) AS d61_90, SUM(CASE WHEN :as_of − o.due_date > 90 THEN open_amt END) AS d90plus, −COALESCE(u.unapplied_amt, 0) AS unapplied, SUM(CASE WHEN o.pdc_payment_id IS NOT NULL THEN open_amt END) AS pdc_memo FROM open_items o JOIN suppliers s ON s.id = o.party_id LEFT JOIN unapplied u ON u.party_id = o.party_id WHERE o.open_amt > 0 GROUP BY s.name, u.unapplied_amt;

Cash forecast-এর জন্য একই open_items, শুধু bucket সামনের দিকে: due_date − :as_of BETWEEN 0 AND 7, 8 AND 30, …

রাতের যাচাই

২৯. GL 2110 (posted_lines) == SUM(subledger balance by supplier) == SUM(purchase_invoices.open_amount WHERE open) − SUM(unapplied payments) ৩০. প্রতিটি bill: open_amount == payable_total − SUM(allocations) ৩১. status সামঞ্জস্য: open_amount == 0 ⟺ status IN ('paid','cancelled') 0 < open < total ⟺ status == 'partially_paid' ৩২. unapplied payment ৩০ দিনের বেশি পুরনো → সতর্কতা (আপনার টাকা supplier-এর কাছে) ৩৩. overdue bill যার note নেই, hold নেই, PDC নেই → সতর্কতা ("অজানা overdue") ৩৪. on_hold ৩০ দিনের বেশি → সতর্কতা ৩৫. গত ৩০ দিনে bank account বদলানো supplier-কে payment হয়েছে যেখানে verified_by == created_by → ০ সারি ৩৬. allocation-এর supplier ≠ payment-এর supplier → ০ সারি

৩৫ নম্বরটা accounting নয় — কিন্তু এটাই সবচেয়ে বেশি টাকা বাঁচায়।

Test হিসেবে

test "allocation GL বদলায় না": pay(বাড়িওয়ালা, 65,000) g1 = balance(2110) allocate(payment, [(PB-10-0001, 61,750)]) assert balance(2110) == g1 assert unapplied(payment) == 3,250 test "discount received: A/P পুরো, Bank নিট, খরচ অপরিবর্তিত": bill = post(draft(অফিস মার্ট, line(1520, 80,000, VAT15), terms 2/10 net 30)) run = propose(as_of = bill_date + 8); approve(run, অন্য user); execute(run) assert bill.status == 'paid' assert Δ 1120 == −90,160 assert Δ 4540 == +1,840 assert Δ 1520 == +80,000 (অপরিবর্তিত) test "payment run: ছাড় আগে, budget-এর বাইরে বাদ": bills: A (ছাড় 37%, 90,000), B (overdue, 1,00,000), C (due +20, 50,000) run = propose(budget = 1,50,000) -- priority A, B, C; A 90,000 ✓; B: 1,90,000 > budget ✗; C: 1,40,000 ✓ assert selected == [A, C] assert run.lines[B].skip_reason == 'budget' test "প্রস্তাবকারী অনুমোদন দিতে পারেন না": run = propose(by = X) assert rejects approve(run, by = X) test "PDC: A/P open থাকে, তারিখে বন্ধ হয়": issuePDC(PB-10-0003, date = 05-12) assert PB-10-0003.open_amount == 1,26,000 assert Δ 1120 == 0 clock → 05-12; runScheduled() assert PB-10-0003.status == 'paid' assert Δ 1120 == −1,26,000 test "verified bank account ছাড়া payment নয়": supplier.add_bank_account(verified = false) assert rejects execute(run with supplier) test "একই aging query দুই দিক": a = aging(doc_type = sales_invoice, as_of) p = aging(doc_type = purchase_invoice, as_of) assert Σ a == gl(1130) + unapplied_receipts assert Σ p == gl(2110) + unapplied_payments

৬. Financial Statement Impact

INCOME STATEMENT (নভেম্বর) 5220 Office Rent 65,000 5270 Professional Fee 50,000 4540 Discount Received (1,840) ← আয় (বা contra-expense, নীতিভেদে) (payment কোনো খরচ তৈরি করেনি — খরচ bill-এ ছিল) BALANCE SHEET (৩০ নভেম্বর, নড়াচড়া) 2110 Accounts Payable −2,20,950 (3,46,950 → 1,26,000) 2150 TDS Payable +5,000 (→ 8,250) 1140 Advance to Supplier −40,000 (→ 0) 1520 Furniture & Fixtures +80,000 1160 VAT Receivable +12,000 1120 Bank −3,81,110 (A/P ও TDS-এর payment; বাকি Cash Book-এ) CASH FLOW (নভেম্বর) operating: supplier-দের payment −2,90,950 (3,81,110 − 90,160 furniture) investing: furniture −90,160 ← asset-এর payment

দুটো বিষয়। প্রথম, PDC-র ১,২৬,০০০ কোথাও নেই — Bank কমেনি, A/P কমেনি; Balance Sheet-এর note-এ “cheques issued, not yet due” — পাঠক জানুক। দ্বিতীয়, Cash Flow-এ furniture-এর payment investing-এ — অধ্যায় ১৫-এর Dr-সিদ্ধান্ত এখানে payment-কেও শ্রেণিবদ্ধ করল; payment নিজে জানে না সে কিসের, allocation তাকে bill-এর সাথে বেঁধে বলে দেয়। Allocation ছাড়া Cash Flow Statement-এর operating/investing ভাগ সম্ভব নয় (অধ্যায় ২২)।


৭. Common Developer Mistakes

ভুলকী ঘটেসঠিক পথ
A/P-এর জন্য দ্বিতীয় allocation tableদুটো কোড, দুটো bug, aging দুবার লেখাallocations + document_type, CHECK
Payment-এ bill ছাড়াই “supplier-কে ৬৫,০০০”overpayment কখনো ধরা পড়ে নাallocation বাধ্যতামূলক বা unapplied সতর্কতা
Unapplied payment খরচেআপনার টাকা supplier-এর কাছে, খাতায় নেইsubledger-এ debit, ৩০ দিনে সতর্কতা, statement-এ চান
Discount received-এ খরচ কমানো, bill-এর মাসেbill-এর মাসের খরচ পরের মাসে বদলায়4540, payment-এর মাসে
Payment run ছাড়া — যে bill যখনছাড় হারায়, নগদ পরিকল্পনা নেই, বেতনে টানrun: প্রস্তাব → অনুমোদন → execute
প্রস্তাব ও অনুমোদন একই userএকজনই টাকা বের করতে পারেনCHECK (proposed_by <> approved_by)
Bill-ধরে আলাদা payment১০টা bill, ১০টা transfer, ১০টা bank chargesupplier-ধরে এক payment, বহু allocation
PDC issue-তে Bank creditBank ব্যালেন্স এমন টাকা কমায় যা যায়নিdraft, instrument_date-এ post
PDC থাকা bill payment run-এদুবার paymentpdc_payment_id থাকলে বাদ
Statement-এর ব্যালেন্স মেনে paymentsupplier-এর ভুলে আপনার টাকাreconcile, আপনার খাতাই সত্য
Bank account screen-এ type করাভুল account, বা ইচ্ছাকৃতmaster থেকে, verified, অপেক্ষা
Bank account বদল একজনের হাতেBEC fraud — সবচেয়ে সাধারণ payment fraudদুজন, log, ৩০ দিনের পতাকা
Aging-এ PDC memo নেই”overdue” দেখে দ্বিতীয় chequememo column
on_hold = statusদেনা “হারিয়ে” যায় report থেকেপতাকা, status posted-ই
Aging দুই দিকে দুই queryএকটায় as-of ঠিক, অন্যটায় নয়parameter দিয়ে এক query

শেষের আগেরটা আর bank account-এর দুটো — এই অধ্যায়ের বিশেষ। A/R-এ ভুলের দাম “টাকা দেরিতে আসে”; A/P-এ ভুলের দাম “টাকা ভুল জায়গায় চলে যায়” — আর ফেরত আসে না।


৮. Exercises

সেট ক — allocation ও entry

১। Supplier-এর তিনটা open bill: A 40,000 (due 01-11), B 25,000 (due 15-11), C 60,000 (due 01-12)। ১০-১১-এ 90,000 transfer। Allocation লিখুন (FIFO)। entry কয়টা? allocation কয়টা সারি? remittance advice-এ কী লেখা থাকবে? ২। Bill 1,15,000 (VAT সহ), শর্ত ২/১০ net ৩০, bill 05-11। ১২-১১-এ দিলে কত? entry ও allocation। বার্ষিক হার কত? ৩। ২ নম্বরের bill ১৮-১১-এ দিলেন। ছাড় নেই। ব্যবহারকারী তবু 1,12,700 দিলেন — কী হবে? bill open কত? supplier কী বলবেন? ৪। ভুলে supplier-কে 20,000 বেশি দিয়েছেন। তিনি পরের bill-এ কাটবেন বললেন। এখন entry? allocation? পরের bill 50,000 এলে? ৫। ৪ নম্বরে supplier ফেরত পাঠালেন। entry। allocation table-এ কী হবে? ৬। Contractor-কে advance 30,000; bill এল 50,000, TDS 10%। entry গুলো, allocation, open কত, run-এ কত দেবেন?

সেট খ — payment run ও aging

৭। ৩০-১১-এ open bills: P due 25-11 1,00,000 ছাড় নেই Q due 15-12 80,000 2/10, bill 25-11 (ছাড় 05-12 পর্যন্ত) R due 10-12 45,000 PDC issued 10-12 S due 20-11 30,000 on hold (মাল ফেরত, DN হয়নি) T due 05-12 60,000 নগদ 2,50,000, সংরক্ষিত 1,20,000। প্রস্তাব লিখুন — ক্রম, কোনটা বাদ, কেন। মোট কত? ৮। ৭ নম্বরের aging (৩০-১১) bucket-ধরে লিখুন — R আর S কোথায়? memo column-এ কী? GL 2110 কত? ৯। ৭ নম্বরে অনুমোদনকারী Q-এর ছাড় না নিয়ে P আগে দিতে বললেন ("পুরনো supplier, রেগে আছে")। System কি আটকাবে? উচিত? ১০। Supplier-এর statement: ব্যালেন্স 3,20,000। আপনার subledger: 2,05,000। পার্থক্য 1,15,000। আপনার হাতে: DN 65,000 (গত সপ্তাহে), PDC 50,000 (তারিখ পরের মাস)। reconcile করুন — কোনটা কোন প্রকার? দ্বিতীয় cheque দেবেন?

সেট গ — কোনটা ভুল

১১। PDC issue-তে: Dr 2110 / Cr 1120, "cheque তো দিয়ে দিয়েছি" ১২। Discount received: Dr 2110 92,000 / Cr 1120 90,160 / Cr 1520 1,840 ১৩। allocations table-এ sales_invoice + source_type 'payment' একটা সারি ১৪। payment_runs: approved_by = proposed_by, "ছোট team" ১৫। Payment screen-এ bank account নম্বর একটা text field ১৬। Supplier statement-এ 2,64,000 → "statement অনুযায়ী পরিশোধ" button ১৭। Aging query: `CURRENT_DATE − bill_date`

সেট ঘ — নকশা

১৮। allocations-এ document_type দুটো, source_type সাতটা। কোন জোড়া বৈধ, কোনটা নয় — table আকারে। CHECK constraint লিখুন। ভবিষ্যতে 'employee_advance' (অধ্যায় ২৯) এলে কী বদলাবে? ১৯। Payment run-এর budget-এ "প্রত্যাশিত receipt" ধরা কতটা নিরাপদ? গ্রাহক না দিলে? দুটো নীতি লিখুন — আশাবাদী ও রক্ষণশীল — আর কোনটা কখন। ২০। একই supplier-এর দুটো bill, একটা on_hold। Run তাকে একটা payment দেবে (hold বাদে)। Remittance advice-এ hold-এর bill-টার কথা লেখা উচিত? supplier-এর দিক থেকে ভাবুন। ২১। Bank account বদলের ৭ দিনের অপেক্ষা — জরুরি payment হলে? override কে দেবেন, কী log হবে, পরে কে দেখবেন? একটা "নিরাপদ override" নকশা করুন। ২২। বহু-currency supplier (অধ্যায় ৫৪-এর আগাম): USD bill, BDT payment। allocation কোন currency-তে? bill-এর দিনের rate আর payment-এর দিনের rate আলাদা — পার্থক্য কোথায়?

উত্তর আছে Workbook-এর Answer Key, অধ্যায় ১৬-এ।


৯. Developer Challenge

একটি PayablesService নকশা করুন — payment allocation থেকে payment run, PDC, statement reconciliation, bank account নিয়ন্ত্রণ পর্যন্ত — আর অধ্যায় ১৪-এর ReceivablesService-এর সাথে যতটা সম্ভব একই কোড ভাগ করে।

যা যা নকশা করবেন:

১. allocations — একটা table, document_type + source_type, CHECK দিয়ে বৈধ জোড়া। অধ্যায় ১৪-এর receipt_allocations থেকে migration: কী বদলাবে, পুরনো data কীভাবে আসবে, downtime লাগবে কি?

২. allocate() — একটাই function দুই দিকে। কোথায় if direction লাগবেই, আর কোথায় লাগা মানে নকশা ভুল? দুজন একই payment একসাথে allocate করলে? একই bill-এ payment আর debit note একসাথে?

৩. Payment run — propose(), approve(), execute(); priority-র যুক্তি config-এ (ছাড়ের হারের সীমা, horizon, reserve-এর নিয়ম); মানুষের বদল সংরক্ষণ (কে কোন line বদলালেন, কেন); execute অর্ধেক হয়ে ব্যর্থ হলে (দুটো payment হলো, তৃতীয়টায় bank file ব্যর্থ) — কী অবস্থায় থাকবে, কীভাবে আবার চালাবেন (idempotency — অধ্যায় ৪৬)?

৪. Discount received — discountIf(), আংশিক payment-এ আনুপাতিক ছাড়ের config, VAT-সহ/ছাড়া base, আর ছাড় হাতছাড়া হলে report: “এ মাসে কত ছাড় হারালাম, কেন” — নগদের অভাবে, না অনুমোদনের দেরিতে?

৫. PDC issued — draft payment, scheduled post, pdc_payment_id memo, aging column, বাতিল। Supplier যদি cheque তারিখের আগেই deposit করেন (bank ফেরত দেয়, charge কাটে)? এটা কোন অধ্যায়ের ঘটনা — ১১, ১২, না ১৬?

৬. Supplier statement reconciliation — অধ্যায় ১২-এর matching engine কতটা পুনর্ব্যবহার করা যায়? দুই পাশের প্রকার তিনটি; প্রতিটি পার্থক্যের জন্য “পরের কাজ” (credit note চাওয়া, bill খোঁজা, বিতর্ক)। statement_reconciled_at দিয়ে report: “কোন supplier-এর statement ৯০ দিনে মেলানো হয়নি”।

৭. supplier_bank_accounts — create/verify আলাদা অনুমতি, effective_from অপেক্ষা, replaced_id chain, ৩০ দিনের পতাকা run-এর অনুমোদনে, log। একটা test: “একজন user নিজে account যোগ করে নিজে verify করে সেদিনই payment পাঠাতে পারেন না” — তিনটি স্তরে আটকান (অনুমতি, CHECK, রাতের যাচাই ৩৫)।

৮. রাতের যাচাই ২৯–৩৬। ২৯ ব্যর্থ হলে তিন স্তরের কোনটা ভুল — অধ্যায় ১৪-এর পদ্ধতিই কি চলবে? PDC কোন স্তরে সমস্যা করতে পারে?

৩ আর ৭ নম্বরটাই আসল পরীক্ষা। Payment run হলো এই বইয়ের প্রথম batch process যা টাকা বের করে — অর্ধেক হয়ে থামলে কী হয়, সেই প্রশ্নটা অধ্যায় ৪৬ ও ৪৭-এর পুরো বিষয়। আর bank account নিয়ন্ত্রণ — এটা accounting-এর কোনো নিয়ম নয়, কিন্তু accounting software-এর সবচেয়ে ব্যয়বহুল ছিদ্র। যে system-এ তিন স্তর নিখুঁত মেলে আর টাকা ভুল account-এ যায়, সেটা ব্যর্থ system।


১০. Summary Card

আয়না

A/R (অধ্যায় ১৪) A/P (অধ্যায় ১৬) control 1130 2110 source receipt payment discount 4190 Allowed (Dr) 4540 Received (Cr) unapplied লুকানো liability লুকানো asset advance 2160 (liab.) 1140 (asset) statement আপনি পাঠান আপনি মেলান নিয়ন্ত্রণ credit limit payment run + bank account

তিন স্তর

GL 2110 == Σ subledger (supplier) == Σ open bill − Σ unapplied payment প্রতিদিন যাচাই; একটাই allocations table, document_type দিয়ে

Entry

payment Dr 2110 [supplier] Cr Bank discount সহ Dr 2110 (পুরো) Cr Bank (নিট) Cr 4540 advance সমন্বয় Dr 2110 [supplier] Cr 1140 PDC issue — (instrument_date পর্যন্ত কিছু না)

Discount নেবেন?

বার্ষিক হার = pct/(1−pct) × 365/(net − disc দিন) 2/10 net 30 → 37% হার > ঋণের সুদ → নিন

Payment run

প্রস্তাব (ছাড় → overdue → due) → মানুষ বদলান → অনুমোদন (অন্য কেউ) → execute supplier-ধরে এক payment, bill-ধরে allocation, remittance advice budget = নগদ − সংরক্ষিত (+ প্রত্যাশিত receipt, নীতিভেদে)

Developer checklist

□ allocations: document_type + source_type + CHECK □ allocate() এক function, দুই দিক; GL স্পর্শ করে না □ unapplied payment: subledger debit, ৩০ দিনে সতর্কতা □ discount: payment-এর মাসে, 4540, annualized হার run-এ □ payment_runs: proposed_by ≠ approved_by (CHECK) □ supplier-ধরে এক payment, remittance advice □ PDC: draft, scheduled post, pdc_payment_id memo, run-এ বাদ □ on_hold পতাকা, status নয়; ৩০ দিনে সতর্কতা □ supplier_bank_accounts: verified, দুজন, effective_from, ৩০ দিনের পতাকা □ payment file-এ account master থেকে, কখনো input থেকে নয় □ statement reconcile: অধ্যায় ১২-এর engine, আপনার খাতাই সত্য □ aging: এক query, direction parameter, PDC memo, সামনের bucket □ রাতে: তিন স্তর, open == গণিত, status, unapplied বয়স, অজানা overdue, hold বয়স, bank account বদল, cross-supplier

পরবর্তী অধ্যায়

অধ্যায় ১৭ — Revenue ও Expense Recognition: Part 2-র প্রথম ছয় অধ্যায়ে টাকা, invoice, bill, receipt, payment — সব ঘুরে এল। আর প্রতিটিতে একটা প্রশ্ন বারবার পিছিয়ে দিয়েছি: আয়টা কোন মাসের? খরচটা কোন মাসের? অধ্যায় ১৩-এ deferred revenue, অধ্যায় ১৫-এ “যে মাসের খরচ সেই মাস”, এই অধ্যায়ে “payment কোনো খরচ তৈরি করে না” — সবগুলো একই নিয়মের টুকরো। পরের অধ্যায়ে নিয়মটা পুরো: আয় হয় কাজ সম্পন্ন হলে, খরচ হয় সুবিধা ভোগ হলে — invoice, bill, টাকা কোনোটাই নয়। আর তার সাথে একটা তিন মাসের project, যার invoice, revenue আর cash — তিনটি একেবারে আলাদা মাসে পড়ে।