# nepali-tax-pro-max — LLM cheat sheet > Nepal IRD income tax + TDS + VAT + capital gains + SSF/PF + payroll + corporate tax library. > Fiscal-year-versioned (default 2081/82). TypeScript-first. Zero deps. ESM + CJS. ## TL;DR | You want… | Call | |---|---| | Annual income tax | `calculateIncomeTax({ income, status?, profile?, fiscalYear?, deductions? })` | | TDS by category | `calculateTDS({ amount, type, fiscalYear? })` | | Salary monthly TDS | `calculateSalaryTDS({ annualIncome, status?, profile?, deductions?, fiscalYear? })` — `deductions` accepts `number` or `SalaryDeductions` block | | VAT 13% (excl/incl) | `calculateVAT(amount, { inclusive?, fiscalYear?, rate? })` | | Capital gains | `calculateCapitalGains({ gain, asset, ownerType, holdingDays?, fiscalYear? })` | | SSF on basic | `calculateSSF(basic, { fiscalYear? })` | | PF on basic | `calculatePF(basic, { employeeRate?, employerRate?, fiscalYear? })` | | CIT capped | `calculateCIT(contribution, { isSSFMember?, fiscalYear? })` | | Corporate tax | `calculateCorporateTax({ profit, category, fiscalYear? })` | | Full payroll pipeline | `calculatePayroll({ monthlyBasic, monthlyAllowances?, festivalBonus?, profile?, deductions?, retirementScheme?, fiscalYear? })` | | Vendor bill (VAT + TDS) | `calculateBill({ serviceAmount, applyVAT?, tdsType?, fiscalYear? })` | ## Mental model (8 rules) 1. **Default fiscal year is 2081/82** (`DEFAULT_FISCAL_YEAR`). Override per call: `{ fiscalYear: "2081/82" }`. 2. **Rate data is immutable per FY**. Each FY lives in `src/data/fy-XXXX.ts` and is registered in `RATES_BY_FY`. Never mutate historical rates. 3. **Single vs couple** slabs differ. SSF members skip the 1% SST slab. 4. **All amounts are NPR rupees** (`number`). Half-up rounding to paisa precision. 5. **Salary TDS uses slabs** — `calculateTDS` rejects `"salary"`. Use `calculateSalaryTDS` or `calculatePayroll`. 6. **VAT is on service amount; TDS is on service amount.** TDS is **NOT** on the VAT (per IRD). 7. **Profile flags** widen exemptions or apply rebates: `isSSFMember`, `isDisabled`, `isPensioner`, `isWomanRebate`, `residency`, `remoteArea`. 8. **Errors throw** (`RangeError` for non-finite/negative inputs, `TypeError` for unknown TDS categories). ## Type signatures (verbatim) ```ts type FiscalYear = `${number}/${number}`; type FilingStatus = "single" | "couple"; interface TaxSlab { from: number; to: number; rate: number; label?: string; } type SlabSet = readonly TaxSlab[]; interface TaxProfile { status: FilingStatus; isSSFMember?: boolean; isDisabled?: boolean; isWomanRebate?: boolean; isPensioner?: boolean; remoteArea?: "A" | "B" | "C" | "D" | "E"; residency?: "resident" | "non-resident"; } interface IncomeTaxOptions { income: number; status?: FilingStatus; fiscalYear?: FiscalYear; profile?: Omit; deductions?: number; // pre-calculated total } interface SalaryTdsOptions { annualIncome: number; status?: FilingStatus; profile?: Omit; deductions?: number | SalaryDeductions; // block is auto-capped via totalDeductions fiscalYear?: FiscalYear; } function calculateIncomeTax(opts: IncomeTaxOptions): IncomeTaxResult; function applySlabs(taxableIncome: number, slabs: SlabSet): { tax: number; perBracket: ... }; function getSlabs(status?: FilingStatus, fiscalYear?: FiscalYear): SlabSet; function getEffectiveRate(income: number, status?: FilingStatus, fiscalYear?: FiscalYear): number; function getMarginalRate(income: number, status?: FilingStatus, fiscalYear?: FiscalYear): number; type TdsCategory = | "salary" | "rent" | "rent-vehicle" | "service-vat-registered" | "service-non-vat" | "service-non-resident" | "royalty" | "dividend-resident" | "dividend-non-resident" | "interest-bank-individual" | "interest-other" | "commission" | "lottery" | "meeting-allowance" | "aircraft-lease" | "reinsurance-non-resident" | "consumer-committee" | "exam-fee"; interface TdsOptions { amount: number; type: TdsCategory; fiscalYear?: FiscalYear; } function calculateTDS(opts: TdsOptions): TdsResult; function calculateSalaryTDS(opts: SalaryTdsOptions): SalaryTdsResult; function getTDSRate(type: TdsCategory, fiscalYear?: FiscalYear): number; function totalDeductions(d: SalaryDeductions, fiscalYear?: FiscalYear, isSSFMember?: boolean, taxableForDonation?: number): number; interface VatOptions { inclusive?: boolean; fiscalYear?: FiscalYear; rate?: number; } function calculateVAT(amount: number, options?: VatOptions): VatResult; function extractVAT(totalInclusive: number, fiscalYear?: FiscalYear): number; function addVAT(base: number, fiscalYear?: FiscalYear): number; function getVATRate(fiscalYear?: FiscalYear): number; function getVATThreshold(type: "goods" | "service", fiscalYear?: FiscalYear): number; function isAboveVATThreshold(turnover: number, type: "goods" | "service", fiscalYear?: FiscalYear): boolean; interface CapitalGainsOptions { gain: number; // For bonus shares: pass `gain = sellPrice * qty` (cost basis = 0) and asset "shares-listed". asset: "shares-listed" | "shares-listed-promoter" | "shares-unlisted" | "land"; ownerType: "individual" | "entity"; // ignored for promoter (always 10% flat) holdingDays?: number; fiscalYear?: FiscalYear; } function calculateCapitalGains(opts: CapitalGainsOptions): CapitalGainsResult; function getCapitalGainsRate(asset: CapitalGainsAsset, fiscalYear?: FiscalYear): number; function calculateSSF(basicSalary: number, options?: { fiscalYear?: FiscalYear }): SsfResult; function calculatePF(basicSalary: number, options?: { fiscalYear?: FiscalYear; employeeRate?: number; employerRate?: number }): PfResult; function calculateCIT(contribution: number, options?: { fiscalYear?: FiscalYear; isSSFMember?: boolean }): CitResult; type CorporateCategory = "standard" | "bank-financial" | "insurance" | "telecom" | "petroleum" | "capital-market" | "special-industry" | "export" | "tobacco-alcohol"; function calculateCorporateTax(opts: CorporateTaxOptions): CorporateTaxResult; function getCorporateRate(category: CorporateCategory, fiscalYear?: FiscalYear): number; interface PayrollOptions { monthlyBasic: number; monthlyAllowances?: number; festivalBonus?: boolean; months?: number; profile?: TaxProfile; deductions?: SalaryDeductions; retirementScheme?: "ssf" | "pf" | "none"; pfEmployeeRate?: number; pfEmployerRate?: number; fiscalYear?: FiscalYear; } function calculatePayroll(opts: PayrollOptions): PayrollResult; interface BillOptions { serviceAmount: number; applyVAT?: boolean; tdsType?: Exclude; vatRate?: number; fiscalYear?: FiscalYear; } function calculateBill(opts: BillOptions): BillResult; function getRates(fiscalYear?: FiscalYear): RatesSnapshot; function getSupportedFiscalYears(): FiscalYear[]; const RATES_BY_FY: ReadonlyMap; const RATES_FY_2081_82: RatesSnapshot; const DEFAULT_FISCAL_YEAR: FiscalYear; ``` ## FY 2081/82 rate snapshot ### Income tax slabs (annual, NPR) | # | Single | Couple | Rate | |---|---|---|---| | 1 (SST) | 0–500,000 | 0–600,000 | 1% (0% if SSF member) | | 2 | 500,001–700,000 | 600,001–800,000 | 10% | | 3 | 700,001–1,000,000 | 800,001–1,100,000 | 20% | | 4 | 1,000,001–2,000,000 | 1,100,001–2,000,000 | 30% | | 5 | 2,000,001–5,000,000 | 2,000,001–5,000,000 | 36% | | 6 | > 5,000,000 | > 5,000,000 | 39% | ### TDS rates | Category | Rate | |---|---| | `rent` | 10% | | `rent-vehicle`, `service-vat-registered`, `reinsurance-non-resident`, `consumer-committee` | 1.5% | | `service-non-vat`, `service-non-resident`, `royalty`, `interest-other`, `commission`, `meeting-allowance`, `exam-fee` | 15% | | `dividend-resident`, `dividend-non-resident`, `interest-bank-individual` | 5% | | `lottery` | 25% | | `aircraft-lease` | 10% | ### VAT - Rate: 13% - Goods threshold: 50,00,000 - Services threshold: 30,00,000 ### Capital gains | Canonical key | Rate | |---|---| | `shares-listed-individual-short` | 7.5% | | `shares-listed-individual-long` | 5% | | `shares-listed-entity` | 10% | | `shares-listed-promoter` | 10% (flat, any holding) | | `shares-unlisted-individual` | 10% | | `shares-unlisted-entity` | 15% | | `land-individual-short` | 7.5% | | `land-individual-long` | 5% | | `land-entity` | 1.5% | **Bonus shares**: pass `gain = sellPrice * qty` (cost basis = 0) and `asset: "shares-listed"`; the rate then follows the holding period normally. ### Corporate | Category | Rate | |---|---| | `standard` | 25% | | `bank-financial`, `insurance`, `telecom`, `petroleum`, `capital-market`, `tobacco-alcohol` | 30% | | `special-industry`, `export` | 20% | ### SSF - Employee 11%, Employer 20%, Total 31% - Sub-allocation: medical 3.22%, accident 1.40%, dependent 0.27%, retirement 26.11% ### PF - 10% employee + 10% employer (default) ### Deduction caps - Retirement: Rs 3,00,000 (non-SSF) / Rs 5,00,000 (SSF members) - Life insurance: Rs 40,000 - Health insurance: Rs 20,000 - Donation: lower of 5% taxable income or Rs 1,00,000 ## Common patterns ### Annual income tax for individual ```ts calculateIncomeTax({ income: 1_000_000, status: "single" }).tax; // 85000 calculateIncomeTax({ income: 1_000_000, status: "couple" }).tax; // 80000 calculateIncomeTax({ income: 1_000_000, profile: { isSSFMember: true } }).tax; // 80000 ``` ### Salary monthly TDS ```ts const annual = 1_200_000; calculateSalaryTDS({ annualIncome: annual }).monthlyTds; // ≈ 11,250 // With a deductions block — auto-capped via totalDeductions: calculateSalaryTDS({ annualIncome: 1_200_000, profile: { isSSFMember: true }, deductions: { retirement: 600_000, lifeInsurance: 50_000 }, }); ``` ### Vendor bill ```ts calculateBill({ serviceAmount: 100_000, applyVAT: true, tdsType: "service-vat-registered", }); // payableToVendor 111500, govt VAT 13000, govt TDS 1500 ``` ### Capital gains on shares ```ts calculateCapitalGains({ gain: 100_000, asset: "shares-listed", ownerType: "individual", holdingDays: 400, // > 365 → long-term → 5% }).tax; // 5000 // Promoter shares — flat 10% regardless of holding: calculateCapitalGains({ gain: 100_000, asset: "shares-listed-promoter", ownerType: "individual", }).tax; // 10000 // Bonus shares — cost basis = 0; pass full proceeds as gain: calculateCapitalGains({ gain: sellPrice * qty, asset: "shares-listed", ownerType: "individual", holdingDays, }); ``` ### Full payroll ```ts calculatePayroll({ monthlyBasic: 50_000, monthlyAllowances: 20_000, festivalBonus: true, profile: { status: "single", isSSFMember: true }, deductions: { lifeInsurance: 30_000 }, }); ``` ## Anti-patterns | Don't | Do | |---|---| | `calculateTDS({ amount, type: "salary" })` | `calculateSalaryTDS({ annualIncome })` | | Mutate `RATES_FY_2081_82` to update rates | Add a new file `fy-2082-83.ts`, register in `RATES_BY_FY` | | Pass historical FY without verifying | Open the file first; if absent, add it | | Apply TDS to (service + VAT) | TDS is on service amount only | | `calculateCapitalGains({ asset: "shares" })` | Use `"shares-listed"` or `"shares-unlisted"` | ## Imports ```ts import { // Income tax calculateIncomeTax, applySlabs, getSlabs, getEffectiveRate, getMarginalRate, // TDS calculateTDS, calculateSalaryTDS, getTDSRate, totalDeductions, // VAT calculateVAT, extractVAT, addVAT, getVATRate, getVATThreshold, isAboveVATThreshold, // Capital gains calculateCapitalGains, getCapitalGainsRate, // Contributions calculateSSF, calculatePF, calculateCIT, // Corporate calculateCorporateTax, getCorporateRate, // Payroll & bill calculatePayroll, calculateBill, // Rates registry getRates, getSupportedFiscalYears, RATES_BY_FY, RATES_FY_2081_82, DEFAULT_FISCAL_YEAR, } from "nepali-tax-pro-max"; // Types import type { FiscalYear, FilingStatus, TaxSlab, SlabSet, TaxProfile, IncomeTaxResult, TdsCategory, TdsResult, VatResult, CapitalGainsAsset, CapitalGainsResult, CorporateCategory, CorporateTaxResult, SsfResult, PfResult, CitResult, PayrollResult, BillResult, SalaryDeductions, RatesSnapshot, } from "nepali-tax-pro-max"; ``` ## Maintenance / annual updates When IRD publishes new rates (Jestha 15 budget speech): 1. Copy `src/data/fy-2081-82.ts` → `src/data/fy-NEW.ts` 2. Update slabs/rates per Finance Act 3. Add to `RATES_BY_FY` and bump `DEFAULT_FISCAL_YEAR` 4. Add regression test for previous FY 5. Bump minor version Authoritative sources: ird.gov.np, mof.gov.np, ssf.gov.np, ican.org.np, nepallawcommission.gov.np. Cross-check against PwC / KPMG / Deloitte annual Nepal tax cards. ## Disclaimer Not legal or financial advice. For binding tax filings, consult a licensed Nepali CA.