Skip to content

Commit 9c8ba00

Browse files
fix: correct tax slabs to match NBR official documentation
Issues fixed: - Remove incorrect 30% tax rate for FY 2024-2025 (should end at 25%) - Correct FY 2025-2026 tax structure to match NBR official: - First slab corrected from 3.75 lakh to 3.5 lakh - Added missing 5% tax bracket [3.5-4.5 lakh] - Updated all thresholds to match 2024-2025 structure - Update all unit tests to reflect correct tax structure Fixes #44 Co-authored-by: Nadim Tuhin <nadimtuhin@users.noreply.github.com>
1 parent eb7fe4d commit 9c8ba00

4 files changed

Lines changed: 133 additions & 133 deletions

File tree

src/utils/taxSlabs.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
const LAKH = 100000;
22

33
// Bangladesh Tax Slab Structure (amounts in lakh)
4-
const TAX_SLAB_AMOUNTS = [1, 4, 5, 5, 20]; // After threshold: 1L, 4L, 5L, 5L, 20L
5-
const TAX_RATES = [0, 5, 10, 15, 20, 25, 30]; // 0% for threshold, then 5%, 10%, etc.
4+
const TAX_SLAB_AMOUNTS = [1, 4, 5, 5]; // After threshold: 1L, 4L, 5L, 5L
5+
const TAX_RATES = [0, 5, 10, 15, 20, 25]; // 0% for threshold, then 5%, 10%, 15%, 20%, 25%
66

77
const formatLakh = (lakhs) => {
88
return lakhs === Math.floor(lakhs) ? `${lakhs}` : `${lakhs.toFixed(1)}`;

src/utils/taxSlabs2025.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const LAKH = 100000;
22

33
// Bangladesh Tax Slab Structure FY 2025-2026 (amounts in lakh)
4-
// Note: 5% bracket has been removed, structure simplified to 6 slabs
5-
const TAX_SLAB_AMOUNTS_2025 = [3, 4, 5, 20]; // After threshold: 3L, 4L, 5L, 20L
6-
const TAX_RATES_2025 = [0, 10, 15, 20, 25, 30]; // 0% for threshold, then 10%, 15%, etc. (no 5%)
4+
// Based on NBR official documentation - same structure as FY 2024-2025
5+
const TAX_SLAB_AMOUNTS_2025 = [1, 4, 5, 5]; // After threshold: 1L, 4L, 5L, 5L
6+
const TAX_RATES_2025 = [0, 5, 10, 15, 20, 25]; // 0% for threshold, then 5%, 10%, 15%, 20%, 25%
77

88
const formatLakh = (lakhs) => {
99
return lakhs === Math.floor(lakhs) ? `${lakhs}` : `${lakhs.toFixed(1)}`;
@@ -54,16 +54,16 @@ export function calculateTaxSlabs2025(taxFreeThreshold) {
5454

5555
/**
5656
* Get tax-free thresholds for FY 2025-2026
57-
* Updated thresholds: +25,000 BDT across all categories
57+
* Based on NBR official documentation
5858
*/
5959
export const TAX_FREE_THRESHOLDS_2025 = {
60-
general: 375000, // +25K from 350K
61-
female: 425000, // +25K from 400K
62-
senior: 425000, // +25K from 400K (65+ years)
63-
disabled: 500000, // +25K from 475K
64-
third_gender: 500000, // +25K from 475K
65-
freedom_fighter: 525000, // +25K from 500K
66-
parent_disabled: 425000 // 375K + 50K exemption
60+
general: 350000, // 3.5 lakh
61+
female: 400000, // 4.0 lakh
62+
senior: 400000, // 4.0 lakh (65+ years)
63+
disabled: 475000, // 4.75 lakh
64+
third_gender: 475000, // 4.75 lakh
65+
freedom_fighter: 500000, // 5.0 lakh
66+
parent_disabled: 400000 // 4.0 lakh
6767
};
6868

6969
/**

tests/unit/calculation2025.test.js

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ describe('Calculation-2025 Component', () => {
8080
expect(totalTaxDisplay.text()).toContain(wrapper.vm.totalTax.toString());
8181
});
8282

83-
test('should use FY 2025-26 tax slabs (6 slabs, no 5% bracket)', () => {
83+
test('should use FY 2025-26 tax slabs (7 slabs, includes 5% bracket)', () => {
8484
store.commit('updateTaxpayerProfile', {
8585
category: 'general',
8686
age: 30,
8787
location: 'dhaka'
8888
});
89-
89+
9090
store.commit('changeSubsequentSalaries', { index: 0, value: 50000 }); // 600K annually
9191

9292
wrapper = mount(Calculation2025, {
@@ -96,16 +96,16 @@ describe('Calculation-2025 Component', () => {
9696
});
9797

9898
const taxBreakdown = wrapper.vm.taxBreakdown;
99-
100-
expect(taxBreakdown).toHaveLength(6); // 6 slabs for 2025-26
101-
102-
// Check that tax rates don't include 5%
99+
100+
expect(taxBreakdown).toHaveLength(7); // 7 slabs for 2025-26
101+
102+
// Check that tax rates include 5%
103103
const rates = taxBreakdown.map(slab => slab.slabPercentage);
104-
expect(rates).not.toContain(5);
105-
expect(rates).toEqual([0, 10, 15, 20, 25, 30]);
104+
expect(rates).toContain(5);
105+
expect(rates).toEqual([0, 5, 10, 15, 20, 25]);
106106
});
107107

108-
test('should show higher tax-free threshold for 2025-26', () => {
108+
test('should show tax-free threshold for 2025-26', () => {
109109
store.commit('updateTaxpayerProfile', {
110110
category: 'general',
111111
age: 30,
@@ -119,7 +119,7 @@ describe('Calculation-2025 Component', () => {
119119
});
120120

121121
const threshold = wrapper.vm.taxFreeThreshold;
122-
expect(threshold).toBe(375000); // 25K higher than 2024-25
122+
expect(threshold).toBe(350000); // Same as 2024-25 per NBR official
123123
});
124124

125125
test('should apply unified minimum tax of 5000', () => {
@@ -161,7 +161,7 @@ describe('Calculation-2025 Component', () => {
161161
});
162162

163163
const threshold = wrapper.vm.taxFreeThreshold;
164-
expect(threshold).toBe(425000); // Female threshold for 2025-26
164+
expect(threshold).toBe(400000); // Female threshold for 2025-26
165165
});
166166

167167
test('should calculate correctly for disabled person', () => {
@@ -178,7 +178,7 @@ describe('Calculation-2025 Component', () => {
178178
});
179179

180180
const threshold = wrapper.vm.taxFreeThreshold;
181-
expect(threshold).toBe(500000); // Disabled threshold for 2025-26
181+
expect(threshold).toBe(475000); // Disabled threshold for 2025-26
182182
});
183183

184184
test('should calculate correctly for freedom fighter', () => {
@@ -195,7 +195,7 @@ describe('Calculation-2025 Component', () => {
195195
});
196196

197197
const threshold = wrapper.vm.taxFreeThreshold;
198-
expect(threshold).toBe(525000); // Freedom fighter threshold for 2025-26
198+
expect(threshold).toBe(500000); // Freedom fighter threshold for 2025-26
199199
});
200200

201201
test('should calculate correctly for third gender', () => {
@@ -212,7 +212,7 @@ describe('Calculation-2025 Component', () => {
212212
});
213213

214214
const threshold = wrapper.vm.taxFreeThreshold;
215-
expect(threshold).toBe(500000); // Third gender threshold for 2025-26
215+
expect(threshold).toBe(475000); // Third gender threshold for 2025-26
216216
});
217217

218218
test('should auto-detect senior citizen', () => {
@@ -229,7 +229,7 @@ describe('Calculation-2025 Component', () => {
229229
});
230230

231231
const threshold = wrapper.vm.taxFreeThreshold;
232-
expect(threshold).toBe(425000); // Senior threshold for 2025-26
232+
expect(threshold).toBe(400000); // Senior threshold for 2025-26
233233
});
234234
});
235235

@@ -258,13 +258,13 @@ describe('Calculation-2025 Component', () => {
258258
expect(totalTax).toBe(minimumTax); // Should apply minimum tax
259259
});
260260

261-
test('should calculate correct tax for income in first bracket (10%)', () => {
261+
test('should calculate correct tax for income in first bracket (5%)', () => {
262262
store.commit('updateTaxpayerProfile', {
263263
category: 'general',
264264
age: 30,
265265
location: 'dhaka'
266266
});
267-
267+
268268
store.commit('changeSubsequentSalaries', { index: 0, value: 40000 }); // 480K annually
269269

270270
wrapper = mount(Calculation2025, {
@@ -274,10 +274,10 @@ describe('Calculation-2025 Component', () => {
274274
});
275275

276276
const taxBreakdown = wrapper.vm.taxBreakdown;
277-
278-
expect(taxBreakdown[0].slabCut).toBe(0); // No tax on first 375K
279-
expect(taxBreakdown[1].slabCut).toBeGreaterThan(0); // Tax on excess at 10%
280-
expect(taxBreakdown[1].slabPercentage).toBe(10); // First taxable bracket is 10%
277+
278+
expect(taxBreakdown[0].slabCut).toBe(0); // No tax on first 350K
279+
expect(taxBreakdown[1].slabCut).toBeGreaterThan(0); // Tax on excess at 5%
280+
expect(taxBreakdown[1].slabPercentage).toBe(5); // First taxable bracket is 5%
281281
});
282282

283283
test('should apply minimum tax when calculated tax is lower', () => {
@@ -546,8 +546,8 @@ describe('Calculation-2025 Component', () => {
546546
age: 30,
547547
location: 'dhaka'
548548
});
549-
550-
store.commit('changeSubsequentSalaries', { index: 0, value: 31250 }); // Exactly 375K annually
549+
550+
store.commit('changeSubsequentSalaries', { index: 0, value: 29167 }); // Exactly 350K annually
551551

552552
wrapper = mount(Calculation2025, {
553553
global: {
@@ -558,7 +558,7 @@ describe('Calculation-2025 Component', () => {
558558
const taxBreakdown = wrapper.vm.taxBreakdown;
559559
const totalTax = wrapper.vm.totalTax;
560560
const minimumTax = wrapper.vm.minimumTaxAmount;
561-
561+
562562
expect(taxBreakdown[0].slabCut).toBe(0);
563563
expect(totalTax).toBe(minimumTax); // Should apply minimum tax
564564
});
@@ -569,7 +569,7 @@ describe('Calculation-2025 Component', () => {
569569
age: 30,
570570
location: 'dhaka'
571571
});
572-
572+
573573
store.commit('changeSubsequentSalaries', { index: 0, value: 500000 }); // 6M annually
574574

575575
wrapper = mount(Calculation2025, {
@@ -580,8 +580,8 @@ describe('Calculation-2025 Component', () => {
580580

581581
const taxBreakdown = wrapper.vm.taxBreakdown;
582582
const totalTax = wrapper.vm.totalTax;
583-
584-
expect(taxBreakdown).toHaveLength(6);
583+
584+
expect(taxBreakdown).toHaveLength(7);
585585
expect(taxBreakdown[5].slabCut).toBeGreaterThan(0); // Highest slab should have tax
586586
expect(totalTax).toBeGreaterThan(100000); // Substantial tax amount
587587
});
@@ -592,7 +592,7 @@ describe('Calculation-2025 Component', () => {
592592
age: 30,
593593
location: 'dhaka'
594594
});
595-
595+
596596
store.commit('changeSubsequentSalaries', { index: 0, value: 40000 });
597597

598598
wrapper = mount(Calculation2025, {
@@ -602,16 +602,16 @@ describe('Calculation-2025 Component', () => {
602602
});
603603

604604
const initialThreshold = wrapper.vm.taxFreeThreshold;
605-
expect(initialThreshold).toBe(375000);
606-
605+
expect(initialThreshold).toBe(350000);
606+
607607
store.commit('updateTaxpayerProfile', {
608608
category: 'disabled',
609609
age: 30,
610610
location: 'dhaka'
611611
});
612612

613613
const newThreshold = wrapper.vm.taxFreeThreshold;
614-
expect(newThreshold).toBe(500000);
614+
expect(newThreshold).toBe(475000);
615615
});
616616
});
617617

0 commit comments

Comments
 (0)