Skip to content

Conversation

@marcelorodrigo
Copy link
Member

@marcelorodrigo marcelorodrigo commented Jan 16, 2026

Summary

This PR adds a comprehensive educational guide for calculating income tax on fixed-income investments in Brazil, with full integration into the application's navigation and related content.

Changes

  1. New Page: app/pages/como-calcular-imposto-de-renda.vue (210 lines)

    • Explains IR (Income Tax) calculation for CDB, RDB, LCI/LCA, and savings accounts
    • Shows IR progressive brackets: 22.5% (≤180d), 20% (181-360d), 17.5% (361-720d), 15% (>720d)
    • Documents IOF (Insurance Operations Tax) for early redemptions (<30 days)
    • Includes 4 practical calculation examples with real numbers
    • Links to 8 official sources from Receita Federal, Banco Central, and CVM
  2. Bug Fix: app/src/finance.ts

    • Fixed unsafe array access in getIOFPercentage() function
    • Added bounds checking: if (daysToRedeem >= 1 && daysToRedeem <= 30)
    • Added fallback: const pct = iofTable[index] ?? 0
    • Prevents undefined returns for invalid inputs (day 0, negative days)
  3. Navigation: app/components/NavigationBar.vue

    • Added new link to income tax guide in navigation bar
    • Uses star icon (📊) for visual distinction
    • Proper aria-label for accessibility
  4. Cross-linking: app/pages/como-calcular-juros-da-poupanca.vue

    • Added section "Impostos na Poupança" explaining tax-exempt status
    • Links to the new income tax guide for broader context
    • Helps users understand taxation across investment types

Testing

  • ✅ All 20 finance unit tests pass
  • ✅ All 7 CDB unit tests pass
  • ✅ Build succeeds with no errors
  • ✅ ESLint validation passes with no violations

Technical Details

  • Sources: Lei nº 15.191/2025, MP 1.303/2025, Lei 9.250/1995, official BCB/CVM documentation
  • Compliance: All calculations match official Receita Federal methodologies
  • Accessibility: Proper HTML semantics, alt text, aria labels
  • Performance: No bundle size increase, efficient lazy loading via Nuxt routing

Related Issues

Resolves educational guide for users to understand tax implications of fixed-income investments.

Summary by CodeRabbit

  • New Features

    • Added an Income Tax Calculation Guide covering Brazilian investment tax rules, examples and step-by-step calculation.
    • Added a navigation link to access the guide.
  • Documentation

    • Extended the savings account guide with a section about tax exemption and a link to the income tax guide.
  • Bug Fixes

    • Improved validation and fallback handling for IOF percentage calculations.

✏️ Tip: You can customize this high-level summary in your review settings.

- Create new guide page explaining IR calculation on fixed income investments (CDB, LCI/LCA, savings)
- Add 4 practical examples with real numbers showing IR, IOF, and net yield comparisons
- Include official sources: Receita Federal, Planalto, Banco Central, CVM
- Fix IOF percentage function to safely handle edge cases (days < 1)
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

The PR adds a new Portuguese Income Tax Calculation Guide page, inserts a navigation link to it, updates the savings page to reference the guide, and tightens input validation and defensive lookup logic for IOF in the finance utility.

Changes

Cohort / File(s) Summary
New Tax Guide Page
app/pages/como-calcular-imposto-de-renda.vue
New Vue SFC providing a static, structured guide on Brazilian Income Tax (IR) and IOF for investments, with examples, tables, notes, and SEO metadata via useSeoMeta.
Navigation & Cross-linking
app/components/NavigationBar.vue, app/pages/como-calcular-juros-da-poupanca.vue
Adds a NuxtLink button (with accessible label and inline SVG) to the navigation bar pointing to the new guide; inserts an "Impostos na Poupança" paragraph linking to the new guide in the poupança page.
Finance Validation
app/src/finance.ts
Tightens getIOFPercentage validation to require daysToRedeem in 1–30, uses a defensive fallback when reading iofTable[index], and returns 0 for out-of-range inputs.

Sequence Diagram(s)

(omitted — changes are UI/content additions and a small utility validation tweak; no multi-component control flow needing visualization)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 A hoppy update for the curious mind,
Tax guides and links, so neatly aligned,
Pages bloom with examples crystal-clear,
IOF checks stricter — hop without fear! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding an income tax calculation guide with navigation integration, which aligns with the primary additions across NavigationBar, new income tax page, cross-linking updates, and finance.ts improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.



📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2189db and 9095d5a.

📒 Files selected for processing (1)
  • app/pages/como-calcular-imposto-de-renda.vue
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/pages/como-calcular-imposto-de-renda.vue

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@app/pages/como-calcular-imposto-de-renda.vue`:
- Around line 78-81: The comparative note in the paragraph that begins with
"<em>Observe:</em>" must be updated to reflect the corrected IOF calculation and
the resulting (correct) lower net gain; locate that paragraph in
como-calcular-imposto-de-renda.vue (the block containing "<em>Observe:</em> O
resgate antecipado (dia 15)...") and replace the phrasing "O resgate antecipado
(dia 15) resultou em um ganho líquido de apenas R$ 34,87 contra R$ 465,00 no
exemplo anterior." with the corrected net-gain value and comparative text that
matches the fixed IOF calculation so the note accurately states the new lower
net gain.
- Around line 70-77: The IOF percentage used in the example on the
como-calcular-imposto-de-renda.vue page is wrong: use the IOF value from the IOF
table in finance.ts (day 15 → index 14 → 50%), update the narrative and computed
numbers accordingly (IOF: 50% × R$75 = R$37.50; rendimento após IOF: R$75 −
R$37.50 = R$37.50; IR (22.5%): 22.5% × R$37.50 = R$8.44 (rounded); rendimento
líquido: R$37.50 − R$8.44 = R$29.06; saldo final: R$10,000 + R$29.06 =
R$10,029.06), and ensure rounding style matches other examples; reference the
IOF array in finance.ts and the list block in the
como-calcular-imposto-de-renda.vue component to make the edits.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 658f290 and d2189db.

📒 Files selected for processing (4)
  • app/components/NavigationBar.vue
  • app/pages/como-calcular-imposto-de-renda.vue
  • app/pages/como-calcular-juros-da-poupanca.vue
  • app/src/finance.ts
🧰 Additional context used
📓 Path-based instructions (6)
{app/src/**/*.ts,app/components/**/*.{ts,tsx,vue}}

📄 CodeRabbit inference engine (AGENTS.md)

{app/src/**/*.ts,app/components/**/*.{ts,tsx,vue}}: IR (Income Tax) calculation depends on investment days: ≤180 days = 22.5%, 181-360 = 20%, 361-720 = 17.5%, >720 = 15%
Always check for null values in investment index properties (e.g., investment.di, investment.poupanca, investment.selic) before calculations

Files:

  • app/src/finance.ts
  • app/components/NavigationBar.vue
{app/src/**/*.ts,app/components/**/*.{ts,tsx,vue},test/unit/src/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

{app/src/**/*.ts,app/components/**/*.{ts,tsx,vue},test/unit/src/**/*.ts}: IOF (Insurance Operations Tax) lookup table applies only if redemption < 30 days, using table in finance.ts:22-25 (96% down to 0% across 30 days)
All currency calculations use .toFixed(2) before Number.parseFloat() to prevent floating-point errors in tax/interest math
Final IOF calculation formula: finalReturn = amount + interest - IOF - (interest - IOF) × IR%

Files:

  • app/src/finance.ts
  • app/components/NavigationBar.vue
{app/src/**/*.ts,app/components/**/*.vue,test/unit/src/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Period conversion must use exact multipliers: Days = 1, Months = 365/12 (not 30), Years = 365 (not 360) — matches BCB official practices

Files:

  • app/src/finance.ts
  • app/components/NavigationBar.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: TypeScript strict mode is enabled in tsconfig.json — prefer explicit types over any
Use ~/ alias for imports pointing to the app/ directory throughout the codebase

Files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
  • app/pages/como-calcular-juros-da-poupanca.vue
  • app/components/NavigationBar.vue
{app/src/**/*.ts,app/store/**/*.ts,app/components/**/*.{ts,tsx,vue}}

📄 CodeRabbit inference engine (AGENTS.md)

Do NOT hardcode BCB index values in code; always fetch via update-indexes.mjs which updates indicadores.json with BCB API data

Files:

  • app/src/finance.ts
  • app/components/NavigationBar.vue
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

Computed properties in Vue components should auto-recalculate when Pinia store state updates

Files:

  • app/components/NavigationBar.vue
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue}} : IR (Income Tax) calculation depends on investment days: ≤180 days = 22.5%, 181-360 = 20%, 361-720 = 17.5%, >720 = 15%
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to test/unit/src/finance.spec.ts : Tax tables (IR brackets, IOF lookup) are critical and must have comprehensive tests covering day boundaries (days 1, 30, 31) and edge cases
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/lcx.ts,test/unit/src/**/*.ts} : LCI/LCA investments are tax-exempt (no IR/IOF) in lcx.ts module
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue},test/unit/src/**/*.ts} : IOF (Insurance Operations Tax) lookup table applies only if redemption < 30 days, using table in finance.ts:22-25 (96% down to 0% across 30 days)

Applied to files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue},test/unit/src/**/*.ts} : Final IOF calculation formula: finalReturn = amount + interest - IOF - (interest - IOF) × IR%

Applied to files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to test/unit/src/finance.spec.ts : Tax tables (IR brackets, IOF lookup) are critical and must have comprehensive tests covering day boundaries (days 1, 30, 31) and edge cases

Applied to files:

  • app/src/finance.ts
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue}} : IR (Income Tax) calculation depends on investment days: ≤180 days = 22.5%, 181-360 = 20%, 361-720 = 17.5%, >720 = 15%

Applied to files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue}} : Always check for null values in investment index properties (e.g., investment.di, investment.poupanca, investment.selic) before calculations

Applied to files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to test/unit/src/**/*.ts : Test compound interest calculations using real BCB index values (e.g., 1.0003105377556554) rather than round numbers

Applied to files:

  • app/src/finance.ts
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/{cdb,lcx,poupanca}.ts,test/unit/src/**/*.ts} : Each investment module (cdb.ts, lcx.ts, poupanca.ts) must export `get<Type>Result()` function returning object with { interestAmount, taxAmount, taxPercentage, iofAmount }

Applied to files:

  • app/src/finance.ts
  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.{ts,tsx,vue},test/unit/src/**/*.ts} : All currency calculations use `.toFixed(2)` before `Number.parseFloat()` to prevent floating-point errors in tax/interest math

Applied to files:

  • app/src/finance.ts
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/**/*.ts,app/components/**/*.vue,test/unit/src/**/*.ts} : Period conversion must use exact multipliers: Days = 1, Months = 365/12 (not 30), Years = 365 (not 360) — matches BCB official practices

Applied to files:

  • app/src/finance.ts
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to app/store/investment.ts : Pinia store uses Portuguese enum names (PeriodTypes.Dias, meses, anos) internally

Applied to files:

  • app/src/finance.ts
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Main calculation orchestration happens in InvestmentSimulation.vue (lines 46-58); all investment type calculations should flow through this component

Applied to files:

  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/lcx.ts,test/unit/src/**/*.ts} : LCI/LCA investments are tax-exempt (no IR/IOF) in lcx.ts module

Applied to files:

  • app/pages/como-calcular-imposto-de-renda.vue
📚 Learning: 2026-01-15T19:58:57.917Z
Learnt from: CR
Repo: rendafixa/rendafixa.github.io PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-15T19:58:57.917Z
Learning: Applies to {app/src/poupanca.ts,test/unit/src/**/*.ts} : Savings accounts use simple monthly rates, not compound interest calculations like CDB/RDB

Applied to files:

  • app/pages/como-calcular-imposto-de-renda.vue
  • app/pages/como-calcular-juros-da-poupanca.vue
🔇 Additional comments (5)
app/components/NavigationBar.vue (1)

105-122: LGTM!

The new navigation link follows the established pattern with consistent styling, proper accessibility via aria-label, and the inline SVG icon matches the existing navigation items' structure.

app/pages/como-calcular-juros-da-poupanca.vue (1)

52-58: LGTM!

The new "Impostos na Poupança" section correctly explains that savings accounts are tax-exempt and provides a helpful cross-link to the IR guide. The placement and styling are appropriate.

app/pages/como-calcular-imposto-de-renda.vue (2)

1-51: Well-structured educational content.

The page follows good practices:

  • Proper heading hierarchy (h2 → h3 → h4)
  • Semantic HTML structure
  • External links with rel="noopener noreferrer" for security
  • IR brackets documented correctly match the getIndexIR() implementation in finance.ts

201-206: LGTM!

SEO metadata is properly configured using Nuxt's useSeoMeta composable with an appropriate title and description for the page content.

app/src/finance.ts (1)

27-33: Good defensive improvement for bounds checking.

The validation change correctly handles edge cases where daysToRedeem could be 0, negative, or greater than 30. The nullish coalescing fallback (?? 0) adds an extra layer of safety. The index calculation (day 1-30 mapping to array indices 0-29) is correct, and callers always pass integer values via Math.floor() in the duration calculation.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@sonarqubecloud
Copy link

@marcelorodrigo marcelorodrigo merged commit 8814206 into master Jan 17, 2026
6 checks passed
@marcelorodrigo marcelorodrigo deleted the imposto-de-renda branch January 17, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants