old ,new form16 working

// Paste this function into your it 2025-26 html.txt script (after calculateAndGenerate) function downloadForm16PDF(taxRegime = null) { // Safety check for jsPDF if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert("jsPDF library is missing. Please ensure it is loaded."); return; } try { // Determine selected regime: prefer parameter -> form select -> stored statement meta const formRegime = (taxRegime || (document.getElementById('neol') ? document.getElementById('neol').value : null) || (window.latestStatement && window.latestStatement.meta && window.latestStatement.meta.slabType) || 'OLD IT SLAB').toString().toUpperCase(); const isNew = formRegime.startsWith('NEW'); // Get statement (must be generated first) const S = window.latestStatement || {}; if (!S || !S.totals) { // fallback: try to read minimal values from form alert('Please run "Calculate and Generate Statement" first so Form16 can be generated.'); return; } // Shortcut helpers const safeNum = v => { if (v === null || v === undefined || v === "") return 0; const n = Number(String(v).toString().replace(/,/g, '')); return isNaN(n) ? 0 : Math.round(n); }; const fmt = (n) => { const v = safeNum(n); return v === 0 ? "0" : v.toLocaleString('en-IN'); }; // Metadata mapping (prefer window.latestStatement.meta; fallback to form fields) const meta = S.meta || {}; const _get = (id, fallback = '') => { try { const el = document.getElementById(id); return el ? (el.value || fallback) : fallback; } catch (e) { return fallback; } }; const METADATA = { nameEmp: (meta.ddoName || _get('ddoName') || '').toString().trim() || '', nameDesig: (meta.name || meta.designation || _get('name') || _get('designation') || '').toString().trim() || '', panDed: (meta.panDed || _get('ddoPan') || '').toString().trim() || 'PANNOTREQD', tanDed: (meta.tanNo || _get('tanNo') || '').toString().trim() || '', panEmp: (meta.panno || _get('panno') || '').toString().trim() || '', fy: (meta.fy || '2025-26'), ay: (meta.ay || '2026-27'), periodFrom: (meta.periodFrom || '01/04/2025'), periodTo: (meta.periodTo || '31/03/2026'), footer: (meta.footer || "Designed By: K.SANYASI NAIDU, SGT, VISAKHAPATNAM"), date: (meta.date || (new Date()).toLocaleDateString('en-GB')), city: (meta.city || 'PADMANABHAM') }; // Totals and inputs from window.latestStatement (these keys are created by your calculateAndGenerate) const T = S.totals || {}; const I = S.inputs || {}; // Quarterly advance tax mapping: S.totals.totalAdvTax is used when monthly advTax not present // But your calculateAndGenerate created monthly advTax overrides in window.latestStatement? It stored totalAdvTax in totals // We will also check S.advTax or try to read adv-tax-override inputs when available. const advMonthly = (S.advTax && Array.isArray(S.advTax) && S.advTax.length >= 12) ? S.advTax.map(v => safeNum(v)) : (() => { // Attempt to read override inputs on page: advTax_Mar25 etc const monthsKeys = ["Mar25","Apr25","May25","Jun25","Jul25","Aug25","Sep25","Oct25","Nov25","Dec25","Jan26","Feb26"]; const arr = []; monthsKeys.forEach(k => { const el = document.getElementById('advTax_' + k); arr.push(el ? safeNum(el.value) : 0); }); // if all zeros and we have defaultAdvanceTax, use default value if (arr.every(a => a === 0)) { const defAdv = safeNum(document.getElementById('defaultAdvanceTax') ? document.getElementById('defaultAdvanceTax').value : (T.totalAdvTax || 0)); if (defAdv > 0) return new Array(12).fill(defAdv); } return arr; })(); // Compute quarter amounts from monthly advMonthly const qFromMonthly = (() => { if (!advMonthly || advMonthly.length < 12) { // fallback: use totals.totalAdvTax split evenly / or map to zero const totalAdv = safeNum(T.totalAdvTax || T.totalAdvTax || 0); const per = Math.floor(totalAdv / 4); return [per, per, per, totalAdv - per*3]; } const q1 = advMonthly.slice(0,3).reduce((a,b)=>a+b,0); const q2 = advMonthly.slice(3,6).reduce((a,b)=>a+b,0); const q3 = advMonthly.slice(6,9).reduce((a,b)=>a+b,0); const q4 = advMonthly.slice(9,12).reduce((a,b)=>a+b,0); return [q1,q2,q3,q4]; })(); // Map data for NEW or OLD // Base gross - use totalGross from totals const grossTotal = safeNum(T.totalGross || T.totalPay || 0); // If NEW regime: only gross and standard deduction 75k (per your requirement) let DATA = {}; if (isNew) { DATA = { regimeLabel: "NEW IT SLAB", gross: grossTotal, standardDeduction: 75000, hraExemption: 0, pt: 0, S80C_TotalGross: 0, S80C_Deductible: 0, S13_EWF_Gross: 0, S13_80D_Gross: 0, S13_EWF_Deductible: 0, S13_80D_Deductible: 0, housingLoanInterest: 0, educationLoan: 0, rebate: safeNum(T.rebate || 0), totalTDS: safeNum(T.totalAdvTax || T.totalTDS || 0), totalPaid: grossTotal }; } else { // OLD: take values from T and I // HRA exemption: T.hraExemption computed in calculateAndGenerate const hraExemption = safeNum(T.hraExemption || 0); // PT: T.totalPtax const pt = safeNum(T.totalPtax || 0); // 80C: sec80C_Allowed stored in totals earlier (sec80C_Allowed) const s80cAllowed = safeNum(T.sec80C_Allowed || T.sec80C || 0); const s80cGross = safeNum(T.sec80C_Total || T.sec80C_Total || 0); const housingLoanInterest = safeNum(T.housingLoanInterest || I.housingLoanInterest || 0); const educationLoan = safeNum(T.educationLoan || I.educationLoan || 0); // S13 totals (EWF, 80D) were stored as totals.totalEwf / totalEhs etc - map conservatively const S13_EWF_Gross = 0; // your calculateAndGenerate used EWF monthly; we keep gross 0 for these unless you stored them explicitly const S13_80D_Gross = 0; DATA = { regimeLabel: "OLD IT SLAB", gross: grossTotal, standardDeduction: safeNum(T.stdDeduction || T.stdDeduction || 50000), hraExemption: hraExemption, pt: pt, S80C_TotalGross: s80cGross, S80C_Deductible: s80cAllowed, S13_EWF_Gross: S13_EWF_Gross, S13_80D_Gross: S13_80D_Gross, S13_EWF_Deductible: 0, S13_80D_Deductible: 0, housingLoanInterest: housingLoanInterest, educationLoan: educationLoan, rebate: safeNum(T.rebate || 0), totalTDS: safeNum(T.totalAdvTax || T.totalTDS || 0), totalPaid: grossTotal }; } // Derived standard calculations (these follow your existing logic naming) const balance = DATA.gross - (DATA.hraExemption || 0); const totalDeductionsU16 = (DATA.standardDeduction || 0) + (DATA.pt || 0); const incSal = balance - totalDeductionsU16; const gti = incSal; // assuming other incomes are zero const S11_TotalSavings = DATA.S80C_Deductible || 0; const taxableIncome_S12 = Math.max(0, gti - S11_TotalSavings); const S13_OtherTotalGross = (DATA.S13_EWF_Gross || 0) + (DATA.S13_80D_Gross || 0); const aggregateDeductibleS13 = (DATA.S13_EWF_Deductible || 0) + (DATA.S13_80D_Deductible || 0); const S14_TotalDeductions = S11_TotalSavings + aggregateDeductibleS13; const totalIncome = Math.max(0, gti - S14_TotalDeductions); // Tax values: prefer stored totals (your calculateAndGenerate stored oldTax/newTax) const taxOnIncome = isNew ? safeNum(T.newTax || T.newTax || 0) : safeNum(T.oldTax || T.oldTax || 0); const rebate = safeNum(T.rebate || 0); const taxAfterRebate = Math.max(0, taxOnIncome - rebate); const cess = Math.round(taxAfterRebate * 0.04); const taxPayableRounded = Math.round(taxAfterRebate + cess); const taxPayableFinal = safeNum(T.totalTax || taxPayableRounded || 0); const taxPayableResult = taxPayableFinal - (DATA.totalTDS || 0); const verifiedAmount = taxPayableFinal; const annexureA_Total = taxPayableFinal; // --- Now generate PDF using jsPDF (keeps similar layout to your existing function) --- const { jsPDF } = window.jspdf; const doc = new jsPDF('p', 'pt', 'a4'); // Page geometry constants matching your file const PG_W = 595.28; const PG_H = 841.89; const LM = 25; // Left Margin const RM = 570; // Right Margin const CW = RM - LM; // Content Width let y = 30; // Vertical Cursor const ROW_H_M = 18; // Minimum Row Height const SECTION_SPACING = 6; // Small helpers (mirrors your existing functions) const font = (style, size) => { doc.setFont("helvetica", style); doc.setFontSize(size); }; const txt = (str, x, yy, options = {}) => { if (str === null || str === undefined) return; doc.text(String(str), x, yy, options); }; const right = (str, x, yy) => { if (str === null || str === undefined) return; doc.text(String(str), x, yy, { align: "right" }); }; const center = (str, yy) => { if (str === null || str === undefined) return; doc.text(String(str), PG_W / 2, yy, { align: "center" }); }; // Header & Part A similar to your existing PDF layout doc.setLineWidth(0.6); doc.rect(LM - 5, 20, CW + 10, 30); font("bold", 12); center("FORM NO.16", y + 12); y += 20; doc.rect(LM - 5, y, CW + 10, 16); font("normal", 10); center(`(${DATA.regimeLabel}) [See rule 31(1)(a)]`, y + 10); y += 16; doc.rect(LM - 5, y, CW + 10, 16); font("bold", 12); center("PART-A", y + 10); y += 16; doc.rect(LM - 5, y, CW + 10, 16); font("normal", 10); center("Certificate under section 203 of the Income-tax Act, 1961 for Tax deducted at source on Salary", y + 12); y += 20; // Name/address boxes using METADATA and meta.name (employee) const nameGridH = 50; const nameGridMidX = LM + (CW / 2); doc.setLineWidth(0.5); doc.rect(LM - 5, y, CW + 10, nameGridH); doc.line(nameGridMidX, y, nameGridMidX, y + nameGridH); font("normal", 8); txt("Name and address of the Employer", LM + 6, y + 14); txt("Name and designation of the employee", nameGridMidX + 6, y + 14); font("bold", 9); doc.text(doc.splitTextToSize(METADATA.nameEmp || (meta.ddoOffice || ''), (CW / 2) - 12), LM + 6, y + 30); doc.text(doc.splitTextToSize(METADATA.nameDesig || (meta.name || ''), (CW / 2) - 12), nameGridMidX + 6, y + 30); y += nameGridH + 4; // PAN/TAN/PAN employee row const panGridH = 40; const panGridCol1 = LM + 105; const panGridCol3 = LM + 400; doc.rect(LM - 5, y, CW + 10, panGridH); doc.line(panGridCol1, y, panGridCol1, y + panGridH); doc.line(panGridCol3, y, panGridCol3, y + panGridH); doc.line(LM - 5, y + 24, RM + 5, y + 24); font("normal", 8); txt("PAN no. of the Deductor", LM + 6, y + 12); txt("TAN No. of the Deductor", panGridCol1 + 6, y + 12); txt("PAN NO. of the Employee", panGridCol3 + 6, y + 12); font("bold", 9); txt(METADATA.panDed || 'PANNOTREQD', LM + 6, y + 36); txt(METADATA.tanDed || '', panGridCol1 + 6, y + 36); txt(METADATA.panEmp || '', panGridCol3 + 6, y + 36); y += panGridH + 4; // CIT and FY block const citGridH = 50; doc.rect(LM - 5, y, CW + 10, citGridH); doc.line(nameGridMidX, y, nameGridMidX, y + citGridH); doc.line(nameGridMidX, y + 30, RM + 5, y + 30); font("normal", 8); txt("CIT (TDS)", LM + 6, y + 12); doc.text(doc.splitTextToSize(METADATA.city || "The Commissioner of Income Tax (TDS)\nRoom No. 411, Income Tax Towers, 10-2-3 A.C. Guard.", (CW / 2) - 12), LM + 6, y + 26); txt("FINANCE YEAR", nameGridMidX + 6, y + 12); txt("Period", nameGridMidX + 110, y + 12); font("bold", 9); txt(METADATA.fy || '2025-26', nameGridMidX + 6, y + 26); font("normal", 8); txt("Assessment Year", nameGridMidX + 6, y + 38); font("bold", 9); txt(METADATA.ay || '2026-27', nameGridMidX + 6, y + 50); txt(METADATA.periodFrom || '01/04/2025', nameGridMidX + 110, y + 50); txt(METADATA.periodTo || '31/03/2026', nameGridMidX + 190, y + 50); y += citGridH + 6; // Summary of tax deducted at source - Qtr table font("normal", 8); txt("Summary of tax deducted at source", LM + 6, y + 12); y += 14; const qtrTblCols = [LM, LM + 50, LM + 180, LM + 320, LM + 450, RM]; const qtrRowH = 18; doc.rect(LM, y, CW, qtrRowH); qtrTblCols.forEach((x, i) => { if (i > 0) doc.line(x, y, x, y + qtrRowH + (4 * qtrRowH)); }); font("bold", 7); txt("Quarter", qtrTblCols[0] + 4, y + 12); txt("Receipt Numbers of", qtrTblCols[1] + 4, y + 12); txt("Amount paid / Credited", qtrTblCols[2] + 4, y + 12); txt("Amount of tax deducted", qtrTblCols[3] + 4, y + 12); txt("Amount of tax deposited /", qtrTblCols[4] + 4, y + 12); y += qtrRowH; font("normal", 8); txt("remitted in Central Govt.", qtrTblCols[4] + 4, y + 2); y += 6; // Use qFromMonthly for paid / deducted / deposited columns. const totalPaidEach = Math.round((DATA.totalPaid || DATA.gross) / 4); for (let i = 0; i < 4; i++) { doc.rect(LM, y, CW, qtrRowH); font("normal", 8); txt(`Q${i + 1}`, qtrTblCols[0] + 6, y + 12); txt("-", qtrTblCols[1] + 6, y + 12); right(fmt(totalPaidEach), qtrTblCols[3] - 6, y + 12); right(fmt(qFromMonthly[i] || 0), qtrTblCols[4] - 6, y + 12); right(fmt(qFromMonthly[i] || 0), RM - 6, y + 12); y += qtrRowH; } doc.rect(LM, y, CW, qtrRowH); font("bold", 8); txt("Total", qtrTblCols[0] + 6, y + 12); right(fmt(DATA.totalPaid || DATA.gross), qtrTblCols[3] - 6, y + 12); right(fmt(DATA.totalTDS || 0), qtrTblCols[4] - 6, y + 12); right(fmt(DATA.totalTDS || 0), RM - 6, y + 12); y += qtrRowH + SECTION_SPACING; // PART B - Salary Details (mirror existing structure) font("bold", 11); txt("PART-B (Refer Note 1)", LM + 6, y + 10); y += 12; font("normal", 8); txt("Details of Salary paid and any other income and tax deducted", LM + 6, y + 8); y += 14; // Salary Block const salaryBlockY = y; // S.No 1 doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("1", LM + 6, y + 10); txt("Gross Salary", LM + 30, y + 10); y += ROW_H_M; // (a) salary as per sec17(1) doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("(a) Salary as per provisions contained in section 17(1)", LM + 30, y + 10); right(fmt(DATA.gross), RM - 6, y + 10); y += ROW_H_M; // (b),(c) doc.rect(LM, y, CW, ROW_H_M); txt("(b) Value of perquisites under section 17(2)", LM + 30, y + 10); right("0", RM - 6, y + 10); y += ROW_H_M; doc.rect(LM, y, CW, ROW_H_M); txt("(c) Profits in lieu of salary under section 17(3)", LM + 30, y + 10); right("0", RM - 6, y + 10); y += ROW_H_M; // TOTAL (a+b+c) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("TOTAL (a+b+c)", LM + 30, y + 10); right(fmt(DATA.gross), RM - 6, y + 10); y += ROW_H_M; // S.No 2 Exemptions u/s 10 doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("2", LM + 6, y + 10); txt("Less: Exempted Allowance u/s 10:", LM + 30, y + 10); y += ROW_H_M; // HRA; in NEW regime it will be zero as DATA.hraExemption doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("A) House Rent Allowance vis 10 (2A)13(A) (Exempted only in Old Tax)", LM + 30, y + 10); right(fmt(DATA.hraExemption), RM - 6, y + 10); y += ROW_H_M; doc.rect(LM, y, CW, ROW_H_M); txt("B) Interest On Housing Loan U/S 24 (B)", LM + 30, y + 10); right(fmt(isNew ? 0 : DATA.housingLoanInterest || 0), RM - 6, y + 10); y += ROW_H_M; // S.No 3 Balance (1-2) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("3", LM + 6, y + 10); txt("Balance (1-2)", LM + 30, y + 10); const balanceVal = balance; right(fmt(balanceVal), RM - 6, y + 10); y += ROW_H_M; // Deductions U/s 16 doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("4", LM + 6, y + 10); txt("Deductions U/s 16:", LM + 30, y + 10); y += ROW_H_M; // 4(a) Standard Deduction doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("(a) Standard Deduction U/s 16(ia) (Common in New/Old Tax)", LM + 30, y + 10); right(fmt(DATA.standardDeduction), RM - 6, y + 10); y += ROW_H_M; // 4(b) Professional Tax (only in old) doc.rect(LM, y, CW, ROW_H_M); txt("(b) Professional Tax U/s 16(iii) (Only in Old Tax)", LM + 30, y + 10); right(fmt(isNew ? 0 : DATA.pt), RM - 6, y + 10); y += ROW_H_M; // 4(c) Entertainment Allowance doc.rect(LM, y, CW, ROW_H_M); txt("(c) Entertainment Allowance U/s 16(ii)", LM + 30, y + 10); right("0", RM - 6, y + 10); y += ROW_H_M; // 5 Aggregate (4a to c) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("5", LM + 6, y + 10); txt("Aggregate of 4(a) to (c)", LM + 30, y + 10); right(fmt(totalDeductionsU16), RM - 6, y + 10); y += ROW_H_M; // 6 Income chargeable under salaries (3-5) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("6", LM + 6, y + 10); txt("Income chargeable under the head 'salaries' (3-5)", LM + 30, y + 10); right(fmt(incSal), RM - 6, y + 10); y += ROW_H_M; // 7 Other income reported by employee (we assume zero) doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("7", LM + 6, y + 10); txt("Add: Any other income reported by the employee", LM + 30, y + 10); right("0", RM - 6, y + 10); y += ROW_H_M; // 8 Gross total income (6+7) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("8", LM + 6, y + 10); txt("Gross total income (6+7)", LM + 30, y + 10); right(fmt(gti), RM - 6, y + 10); y += ROW_H_M + SECTION_SPACING; // CHAPTER VI-A - 10 -> Savings (80C) only for OLD font("bold", 10); txt("9", LM + 6, y + 12); txt("Deductions under Chapter VIA", LM + 32, y + 12); y += 16; // Header row for 10 doc.rect(LM, y, CW, 16); const xGross = LM + 330; const xQual = LM + 425; const xDed = RM - 90; doc.line(xGross, y, xGross, y + 16); doc.line(xQual, y, xQual, y + 16); doc.line(xDed, y, xDed, y + 16); font("bold", 8); txt("10", LM + 6, y + 12); txt("Savings U/s 80CCE (80C, 80CCC and 80CCD (i))", LM + 32, y + 12); txt("Gross Amount", xGross + 4, y + 12); txt("Qualifying amount", xQual + 4, y + 12); txt("Deductible Amount Rs.", xDed + 4, y + 12); y += 16; // Section 80C line: Only show actual values when OLD; zero when NEW doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("A) Section 80 C (Only in Old Tax)", LM + 30, y + 10); right(fmt(isNew ? 0 : DATA.S80C_TotalGross), xGross - 6, y + 10); right(fmt(isNew ? 0 : S11_TotalSavings), xQual - 6, y + 10); right(fmt(isNew ? 0 : S11_TotalSavings), xDed - 6, y + 10); y += ROW_H_M; // 11 Total Deductible Savings (A+B+C+D) doc.rect(LM, y, CW, ROW_H_M); font("bold", 9); txt("11", LM + 6, y + 12); txt("Total Deductible Savings (A+B+C+D)", LM + 32, y + 12); right(fmt(isNew ? 0 : S11_TotalSavings), xGross - 6, y + 12); right(fmt(isNew ? 0 : S11_TotalSavings), xQual - 6, y + 12); right(fmt(isNew ? 0 : S11_TotalSavings), RM - 6, y + 12); y += ROW_H_M + 4; // 12 Taxable income (8 - 11) doc.rect(LM, y, CW, ROW_H_M); doc.line(xDed, y, xDed, y + ROW_H_M); font("bold", 9); txt("12", LM + 6, y + 12); txt("Taxable income (8 - 11)", LM + 32, y + 12); txt("Rs:", RM - 18, y + 12); right(fmt(taxableIncome_S12), RM - 6, y + 12); y += ROW_H_M + 8; // PAGE BREAK if needed - for simplicity we do addPage after the previous block doc.addPage(); y = 30; // Other Sections 80D, 80E etc (Only Old regime values shown) font("bold", 9); txt("13", LM + 6, y + 12); txt("Other Sections (80CCG, 80D, 80DDB, 80E, 80G etc) under Chapter VI-A (Only in Old Tax)", LM + 32, y + 12); y += 16; const xG_O = LM + 330; const xQ_O = LM + 425; const xD_O = RM - 90; doc.rect(LM, y, CW, 16); doc.line(xG_O, y, xG_O, y + 16); doc.line(xQ_O, y, xQ_O, y + 16); doc.line(xD_O, y, xD_O, y + 16); font("bold", 8); txt("Gross Amount", xG_O + 6, y + 12); txt("Qualify amount", xQ_O + 6, y + 12); txt("Deductible Amount Rs.", xD_O + 6, y + 12); y += 16; // a) EWF & relief doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("a) E.W.F, & S.W.F, Kerala flood, Titli relief fund", LM + 32, y + 10); right(fmt(isNew ? 0 : DATA.S13_EWF_Gross), xG_O - 6, y + 10); right(fmt(isNew ? 0 : DATA.S13_EWF_Deductible), xQ_O - 6, y + 10); y += ROW_H_M; // b) 80D doc.rect(LM, y, CW, ROW_H_M); txt("b) 80D-Medical Insurance Premium-Self, Spouse & Children", LM + 32, y + 10); right(fmt(isNew ? 0 : DATA.S13_80D_Gross), xG_O - 6, y + 10); right(fmt(isNew ? 0 : DATA.S13_80D_Deductible), xQ_O - 6, y + 10); y += ROW_H_M; // c-e others (we show zeros unless data present in S.totals) const others = ["80E-Interest on Educational Loan","80G-Donation to certain funds","Others"]; others.forEach((label) => { doc.rect(LM, y, CW, ROW_H_M); txt(label, LM + 32, y + 10); right(fmt(0), xG_O - 6, y + 10); right(fmt(0), xQ_O - 6, y + 10); y += ROW_H_M; }); // TOTAL (a+b+c+d+e) doc.rect(LM, y, CW, ROW_H_M); font("bold", 8); txt("TOTAL (a+b+c+d+e)", LM + 32, y + 12); txt("Rs:", xG_O - 18, y + 12); right(fmt(S13_OtherTotalGross), xG_O - 6, y + 12); txt("Rs:", xQ_O - 18, y + 12); right(fmt(aggregateDeductibleS13), xQ_O - 6, y + 12); y += ROW_H_M + 6; // Aggregate of deductible amount under Chap. VIA (11+13) doc.rect(LM, y, CW, ROW_H_M); font("bold", 9); txt("14", LM + 6, y + 12); txt("Aggregate of deductible amount under Chap. VIA (11+13)", LM + 32, y + 12); txt("Rs:", RM - 18, y + 12); right(fmt(S14_TotalDeductions), RM - 6, y + 12); y += ROW_H_M + 8; // TAX BLOCK (15..22) const taxBlockY = y; const taxRow = (sl, d, v, boldRow=false) => { doc.rect(LM, y, CW, ROW_H_M); font(boldRow ? "bold" : "normal", 8); const textY = y + 12; if (sl) txt(sl, LM + 6, textY); doc.text(doc.splitTextToSize(d, RM - 120 - LM), LM + 28, textY); if (v !== null && v !== undefined) { txt("Rs:", RM - 30, textY); right(fmt(v), RM - 6, textY); } y += ROW_H_M; }; taxRow("15", "Total Income (8 - 14)", totalIncome, true); taxRow("16", "Tax on total income", taxOnIncome, false); taxRow("17", "Rebate U/S 87A (Old Tax: <=5Lakh, New Tax: <=7Lakh)", rebate || 0, false); taxRow("18", "Surcharge", 0, false); taxRow("19", `Education & health cess @4% on (Tax after Rebate x 4%)`, cess, false); taxRow("20", "Tax payable (After Rebate & Cess, Rounded off)", taxPayableRounded, true); taxRow("21", "Less Relief U/s 89(1) (attach details)", 0, false); taxRow("22", `${DATA.regimeLabel} Total Tax Payable (Rounded off)`, taxPayableFinal, true); // Less TDS (23) doc.rect(LM, y, CW, ROW_H_M); font("normal", 8); txt("23", LM + 6, y + 12); txt("Less:(a) Tax deducted at source U/s 192(1)", LM + 28, y + 12); doc.line(RM - 110, y, RM - 110, y + ROW_H_M); txt("Rs:", RM - 130, y + 12); right(fmt(DATA.totalTDS || 0), RM - 6, y + 12); y += ROW_H_M + 6; // (b) tax paid by employer on behalf - left as is doc.rect(LM, y, CW, ROW_H_M); doc.line(RM - 110, y, RM - 110, y + ROW_H_M); font("normal", 8); txt(" (b)", LM + 28, y + 12); doc.text("Tax paid by the employer on behalf of the employee U/s 192 (1A) on perquisites U/s 17 (2)", LM + 48, y + 12); y += ROW_H_M + 6; // TAX PAYABLE / REFUNDABLE (24) doc.rect(LM, y, CW, ROW_H_M); font("bold", 9); txt("24", LM + 6, y + 12); txt("TAX PAYABLE / REFUNDABLE (22-23)", LM + 28, y + 12); txt("Rs:", RM - 30, y + 12); right(fmt(taxPayableResult), RM - 6, y + 12); y += ROW_H_M + 8; // Verification font("bold", 11); txt("Verification", LM + 6, y + 12); y += 16; font("normal", 9); const empShort = (METADATA.nameDesig || "").split('\n')[0] || METADATA.nameDesig; const empCapacity = (METADATA.nameDesig || "").split('\n')[1] || ""; const verifText = `I Sri/Smt.: ${empShort.replace(/^Sri\.\s*/i, '')}, Son/Daughter of Sri/smt. working in the capacity of ${empCapacity.trim() || ''}, do hereby certify that the sum of Rs: ${fmt(verifiedAmount)} /- has been deducted and deposited to the credit of the Central Government as per ${DATA.regimeLabel}.`; doc.text(doc.splitTextToSize(verifText, CW), LM + 6, y); y += 30; // Signature boxes and place/date doc.rect(LM, y, CW / 2 - 6, 50); doc.rect(LM + CW / 2 + 6, y, CW / 2 - 6, 50); font("normal", 9); txt("Place:-", LM + 10, y + 14); txt(METADATA.city, LM + 80, y + 14); txt("Date:-", LM + 10, y + 30); txt(METADATA.date || METADATA.periodTo || "31/03/2026", LM + 80, y + 30); txt("Designation:", LM + 10, y + 46); doc.text(doc.splitTextToSize(METADATA.nameEmp.split('\n')[1] || METADATA.nameDesig, 180), LM + 90, y + 46); right("Signature of person responsible for deduction of tax", RM - 6, y + 26); right(`Full Name: ${METADATA.nameEmp.split('\n')[0] || METADATA.nameEmp}`, RM - 6, y + 46); y += 64; // ANNEXURE A (Book Entry) simplified mapping -- copy your layout font("bold", 10); center("ANNEXURE A (Book Entry)", y); y += 14; const ac = [LM, LM + 40, LM + 170, LM + 270, LM + 400, RM]; const aRowH = 14; doc.rect(LM, y, CW, aRowH); ac.forEach((x, i) => { if (i > 0) doc.line(x, y, x, y + aRowH + (10 * aRowH)); }); font("bold", 7); txt("Sl.No", ac[0] + 6, y + 10); doc.text("Tax Deposited in respect\non of the employee (Rs.)", ac[1] + 6, y + 6); doc.text("Receipt Numbers of Form No 24G", ac[2] + 6, y + 10); doc.text("DDO Sequence Number in the\nBook Adjustment Mini Statement", ac[3] + 6, y + 6); doc.text("Date on which tax deposited\n(dd/mm/yy)", ac[4] + 6, y + 6); y += aRowH; for (let i = 1; i <= 12; i++) { doc.rect(LM, y, CW, aRowH); font("normal", 8); txt(`${i}.`, ac[0] + 6, y + 10); if (i === 12) { right(fmt(annexureA_Total || 0), ac[2] - 6, y + 10); txt("0", ac[3] + 6, y + 10); txt("0", ac[4] + 6, y + 10); txt(METADATA.periodTo || "31/03/2026", ac[4] + 60, y + 10); } else { right("0", ac[2] - 6, y + 10); txt("-", ac[3] + 6, y + 10); txt("-", ac[4] + 6, y + 10); txt("-", ac[4] + 60, y + 10); } y += aRowH; } doc.rect(LM, y, CW, aRowH); font("bold", 8); txt("Total", ac[0] + 6, y + 10); right(fmt(annexureA_Total), ac[2] - 6, y + 10); y += aRowH + 10; // ANNEXURE B (Challan) - produce 4 quarter rows with amounts from qFromMonthly font("bold", 10); center("ANNEXURE B (Challan)", y); y += 14; const bc = [LM, LM + 40, LM + 170, LM + 270, LM + 390, RM]; const bRowH = 14; doc.rect(LM, y, CW, bRowH); bc.forEach((x, i) => { if (i > 0) doc.line(x, y, x, y + bRowH + (4 * bRowH)); }); font("bold", 7); txt("Sl.No", bc[0] + 6, y + 10); doc.text("Challan Serial No", bc[1] + 6, y + 10); doc.text("BSR Code of Bank Branch", bc[2] + 6, y + 10); doc.text("Date of Deposit\n(dd/mm/yy)", bc[3] + 6, y + 6); doc.text("Amount of Tax Deposited (Rs.)", bc[4] + 6, y + 10); y += bRowH; for (let i = 0; i < 4; i++) { doc.rect(LM, y, CW, bRowH); font("normal", 8); txt(`${i + 1}.`, bc[0] + 6, y + 10); txt(`${i + 1}`, bc[1] + 6, y + 10); txt("0000000", bc[2] + 6, y + 10); const yr = (METADATA.periodTo || "31/03/2026").split('/').pop() || "2026"; txt(`31/03/${yr}`, bc[3] + 6, y + 10); right(fmt(qFromMonthly[i] || 0), RM - 6, y + 10); y += bRowH; } doc.rect(LM, y, CW, bRowH); font("bold", 8); txt("Total", bc[0] + 6, y + 10); right(fmt(DATA.totalTDS || 0), RM - 6, y + 10); y += bRowH + 10; // Footer credit font("normal", 8); center(METADATA.footer || "Designed By: K.SANYASI NAIDU, SGT, VISAKHAPATNAM", y); // Double border per-page (like your existing code) const pages = doc.internal.getNumberOfPages(); for (let i = 1; i <= pages; i++) { doc.setPage(i); doc.setLineWidth(0.6); doc.rect(LM - 5, 20, CW + 10, PG_H - 40); doc.setLineWidth(0.4); doc.rect(LM - 2, 23, CW + 4, PG_H - 46); } // Save file name using employee short name const empLabelRaw = (METADATA.nameDesig || METADATA.nameEmp || 'Employee').toString(); const empLabel = empLabelRaw.replace(/\s+/g,'_').replace(/[^\w\-_.]/g,''); doc.save(`Form16_${isNew ? 'NEW' : 'OLD'}_${empLabel || 'Employee'}.pdf`); } catch (err) { console.error('Form16 generation error', err); alert('Error generating Form16 PDF. Check browser console for details.'); } }

About TeacherAp

This is a short description in the author block about the author. You edit it by entering text in the "Biographical Info" field in the user admin panel.

0 Comments:

Post a Comment