@classytic/bd-tax
v0.4.0
Published
Bangladesh tax engine — VAT, SD, TDS, VDS, income tax, Mushak forms, BIN validation, fiscal positions, and NBR return aggregation. Pure calculation library with pluggable account mapping for any ledger system.
Readme
@classytic/bd-tax
Bangladesh tax engine — VAT, SD, TDS, VDS, income tax, Mushak forms, BIN validation, fiscal positions, and NBR return aggregation.
Pure calculation library. No database, no HTTP framework, no hard
dependencies on any ledger system. Composable with any accounting backend
(@classytic/ledger-bd, QuickBooks, Xero, ERPNext, or custom).
Install
npm install @classytic/bd-taxPeer dependency: zod >= 4.0.0.
Use
Prefer subpath imports — each concern is its own entry point.
// VAT and invoice-level calculation
import { calculateVAT, calculateInvoiceTax } from '@classytic/bd-tax/calc';
// Mushak forms and BIN validation
import { buildMushak63, validateBIN } from '@classytic/bd-tax/musok';
// Rate tables and regime config
import { VAT_RATES, TURNOVER_THRESHOLDS } from '@classytic/bd-tax/config';
// Personal income tax (versioned: FY2025-26 + FY2026-27 slabs)
import { computeTax } from '@classytic/bd-tax/income-tax';
// TDS matrix (ITA 2023) / VDS service table (VDS Rules 2025)
import { calculateTds } from '@classytic/bd-tax/tds';
import { calculateVdsByServiceCode, checkVdsExemption } from '@classytic/bd-tax/vds';
// Account mapping (ledger-bd chart defaults; override at will)
import { accountFor, createAccountMapper, BD_VAT_ACCOUNT_CODES } from '@classytic/bd-tax/accounts';The root entry re-exports the most common symbols as a convenience, but subpaths are the canonical way and keep bundles tight.
When rules change
Every versioned table (VAT schedule, thresholds, TDS matrix, VDS service table) is effective-dated through one shared resolver — a fiscal-year update is always "close the old window, push a dated entry", and old documents recompute period-accurately forever. For mid-year SROs, hosts can hot-patch at boot without waiting for a release:
import { extendBdTaxRules } from '@classytic/bd-tax';
extendBdTaxRules({ vdsEntries: [...], tdsRows: [...], taxClasses: {...}, sdRates: [...] });Extensions carry the same dated windows and shadow built-ins. Full recipe: docs/updating-rules.md.
What's inside
| Subpath | Ships |
|---|---|
| ./calc | calculateVAT, extractVAT, roundPaisa, calculateSD, calculateSdThenVat, calculateTOT, determineTaxRegime, isTotEligible, calculateLineItem, calculateInvoiceTax |
| ./musok | Mushak builders: 4.3, 6.3 (invoice), 6.5 (inter-unit transfer), 6.6 (VDS certificate), 6.7 (credit note), 6.10 (≥ Tk 2 lakh statement), 9.1 (monthly + FY2026-27 quarterly), 9.2 (TOT); BIN validation helpers |
| ./config | Versioned VAT rate schedule (FY2025-26 / FY2026-27), SD rate table, three-generation turnover thresholds, regime constants |
| ./income-tax | Personal income tax (ITA 2023) — versioned slabs (FY2025-26 / FY2026-27), s.78 investment rebate, advance tax, zakat deduction, depreciation, IT-10B/10BB/11GA schemas |
| ./tds | TDS withholding matrix on the Income Tax Act 2023 (s.89/90/94/102/109/117/119/120/123) with FY-dated rows and the s.264 no-PSR uplift |
| ./vds | VDS Rules 2025 (SRO 182/2025): 45-service table keyed by NBR service code, withholding-entity gate, exemption checks, deposit/certificate mechanics, plus the dated legacy category API |
| ./accounts | accountFor, ancillaryAccounts, createAccountMapper, BD_VAT_ACCOUNT_CODES — BFRS chart mapping with override hook |
Design
- Pure functions on plain data. No I/O, no persistence, no events.
- Deterministic. Same inputs → same outputs. Clocks injected explicitly.
- Integer minor-unit arithmetic. Money stays in paisa; float math is
isolated to ratio/percent calculations using
decimal.js. - Zod schemas at the seams. Input validation is opt-in — import schemas
from
./musok/./configwhen wiring untrusted payloads. - Pluggable account mapping. The default
BD_VAT_ACCOUNT_CODESmatches@classytic/ledger-bdchart codes (2132 VAT payable, 1150 VAT receivable, 1157 transition, 2135 TDS, 2136 VDS). Override per-deployment viacreateAccountMapper({ overrides }).
Testing
npm test # unit + integration (566 tests, ~5 s)
npm run test:unit # pure calculation tests
npm run test:integration # cross-module scenarios (invoice totals, returns)
npm run typecheck
npm run lintLicense
MIT — see LICENSE.
