Skip to content

DEGIRO: Add Spanish translations for platform fees and money-market fund conversions#328

Open
CristianAbrante wants to merge 4 commits into
dickwolff:mainfrom
CristianAbrante:feature/spanish-degiro-translations
Open

DEGIRO: Add Spanish translations for platform fees and money-market fund conversions#328
CristianAbrante wants to merge 4 commits into
dickwolff:mainfrom
CristianAbrante:feature/spanish-degiro-translations

Conversation

@CristianAbrante

@CristianAbrante CristianAbrante commented Apr 28, 2026

Copy link
Copy Markdown

Added

DEGIRO Spanish-locale recognition keywords across V2 and V3 converters:

  • comisión de conectividadisPlatformFees. Spanish-language exchange connectivity fees (Comisión de conectividad con el mercado YYYY (...)) are now classified as platform fees instead of failing the security lookup.
  • fondos del mercado monetarioisIgnoredRecord. DEGIRO's internal money-market fund cash-sweep pseudo-transactions (Conversión fondos del mercado monetario: Compra/Venta ... @ ... EUR) are skipped, matching the existing behaviour for the French fonds monétaires.
  • y/oisTransactionFeeRecord. Spanish trade-fee rows (Costes de transacción y/o externos de DEGIRO) now pair with their buy/sell record so the fee ends up on the trade instead of being dropped, matching the existing en/of, and/or, und/oder, e/o keywords.
  • retención del dividendoisTransactionFeeRecord. Spanish dividend-withholding-tax rows (Retención del dividendo) now pair with the dividend record as a fee instead of being imported as a duplicate DIVIDEND activity (the description contained dividend and was matching isDividendRecord).
  • rendimiento de capitalisDividendRecord (V2 only). Spanish capital-return rows are recognised as dividends, mirroring the existing English capital return keyword. V3 routes non-buy/sell records through mapDividendRecord by default, so no change is needed there.

Fixes

  • DEGIRO Spanish account exports failing during processing with An error occurred trying to retrieve an empty symbol for market connectivity fee rows.
  • DEGIRO Spanish account exports producing invalid Ghostfolio activities (quantity: 0, unitPrice: 0, currency: "") for money-market fund internal conversion rows, which then failed Ghostfolio import validation with currency must be a valid ISO4217 currency code.
  • DEGIRO Spanish account exports logging Record <ISIN> with currency EUR was skipped because it could not be matched to a valid transaction! for every Spanish trade fee row, with the fee silently dropped from the corresponding buy/sell activity.
  • DEGIRO Spanish account exports producing duplicate DIVIDEND activities per dividend payment — one for Dividendo, one for Retención del dividendo — instead of a single dividend with the withholding tax recorded as the fee.
  • DEGIRO Spanish account exports silently dropping Rendimiento de capital rows.

Checklist

  • Added relevant changes to README (if applicable) — N/A, multilingual keyword lists are internal.
  • Added relevant test(s) — compact it.each table per converter in degiroConverterV2.test.ts and degiroConverterV3.test.ts asserting each new Spanish keyword is recognized by its classifier, with lowercase and uppercase variants to lock in the lowercase-normalization behaviour.
  • Updated the GitVersion file (if not done automatically) — left untouched.

Related issue (if applicable)

Fixes #..

Notes

This follows the existing pattern in both converters where the platform-fee, ignored-record, transaction-fee, and dividend-keyword lists already contain entries in Dutch, English, Italian, German, Portuguese, and French. Spanish was the only major DEGIRO-supported locale missing from these lists, and these were the specific terms encountered when running a real Spanish Account.csv export end-to-end.

Reproduced and verified locally on a 1398-row Spanish DEGIRO Account.csv:

Stage Before After
Connectivity-fee rows Crash on first row, full conversion aborted All rows imported as FEE activities
Money-market sweep rows Generated invalid activity (currency: "") that broke Ghostfolio import Skipped (consistent with fonds monétaires)
Spanish trade fee rows Fee dropped, was skipped because it could not be matched warning Fee correctly attached to the corresponding buy/sell
Dividend rows with withholding Two DIVIDEND activities per payment (one for the gross, one for the withholding) Single DIVIDEND activity with the withholding as the fee
Rendimiento de capital rows Silently dropped Imported as a DIVIDEND activity

End-to-end the converter now produces a valid Ghostfolio import file with no skip warnings, no empty currencies, and all activities passing ISO4217 validation.

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7d9d7dd4-2715-452c-aef3-abaa9f082f40

📥 Commits

Reviewing files that changed from the base of the PR and between 86b4e81 and 691f686.

📒 Files selected for processing (2)
  • src/converters/degiroConverterV2.test.ts
  • src/converters/degiroConverterV3.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/converters/degiroConverterV2.test.ts

Walkthrough

DeGiroConverterV2 and DeGiroConverterV3 now recognize additional Spanish transaction descriptions from DEGIRO. Both converters extend ignored-record detection with money-market fund variants. DeGiroConverterV2 adds dividend-income matching for rendimiento de capital. Both converters broaden transaction-fee detection to include dividend-withholding descriptions (retención del dividendo). Both add platform-fee detection for connectivity commissions (comisión de conectividad).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding Spanish translations to DEGIRO converters for platform fees and money-market fund conversions, which aligns with the file modifications across V2/V3 converters and their tests.
Description check ✅ Passed The description comprehensively covers all required template sections with detailed explanations of changes, fixes addressed, completed checklist items, and thorough testing validation on real Spanish DEGIRO data.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

…nto de capital'

- Add 'retención del dividendo' to isTransactionFeeRecord (V2 + V3) so the
  Spanish dividend-withholding-tax row pairs with the dividend record as a
  fee instead of being imported as a duplicate dividend activity.
- Add 'rendimiento de capital' to isDividendRecord (V2) so Spanish capital
  return records are recognized as dividends, mirroring the existing
  English 'capital return' keyword. V3 routes non-buy/sell records through
  mapDividendRecord by default, so no change is required there.
@CristianAbrante CristianAbrante marked this pull request as ready for review May 9, 2026 20:07
@CristianAbrante CristianAbrante requested a review from dickwolff as a code owner May 9, 2026 20:07

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/converters/degiroConverterV2.ts (1)

260-261: ⚡ Quick win

Add table-driven regression tests for the new Spanish classifier keywords.

These string-match rules are easy to regress; a compact fixture-based test for each new phrase (fondos del mercado monetario, rendimiento de capital, y/o, retención del dividendo, comisión de conectividad) would lock behavior and prevent locale drift between V2/V3.

Also applies to: 432-432, 446-446, 453-453

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/converters/degiroConverterV2.ts` around lines 260 - 261, Add compact
table-driven Jest tests for the new Spanish classifier keywords in
src/converters/degiroConverterV2.ts: create a data-driven fixture in
degiroConverterV2.test.ts that asserts the converter's classification function
(use the module's exported function, e.g.,
degiroConverterV2.classifyInstrumentType or the specific validator used for
keyword matching) returns the expected category for each phrase ("fondos del
mercado monetario", "rendimiento de capital", "y/o", "retención del dividendo",
"comisión de conectividad") and include entries for the other occurrences
referenced (lines with the same phrases around 432, 446, 453) so future changes
fail the test; iterate over the table with meaningful case/whitespace variants
and assert exact string-match behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/converters/degiroConverterV2.ts`:
- Around line 260-261: Add compact table-driven Jest tests for the new Spanish
classifier keywords in src/converters/degiroConverterV2.ts: create a data-driven
fixture in degiroConverterV2.test.ts that asserts the converter's classification
function (use the module's exported function, e.g.,
degiroConverterV2.classifyInstrumentType or the specific validator used for
keyword matching) returns the expected category for each phrase ("fondos del
mercado monetario", "rendimiento de capital", "y/o", "retención del dividendo",
"comisión de conectividad") and include entries for the other occurrences
referenced (lines with the same phrases around 432, 446, 453) so future changes
fail the test; iterate over the table with meaningful case/whitespace variants
and assert exact string-match behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1e7578f9-ec12-4b7b-b49f-c3a454546cdb

📥 Commits

Reviewing files that changed from the base of the PR and between 9e35bd6 and 918b7c1.

📒 Files selected for processing (2)
  • src/converters/degiroConverterV2.ts
  • src/converters/degiroConverterV3.ts

Compact it.each table per converter, asserting each of the new Spanish
keywords ('fondos del mercado monetario', 'comisión de conectividad',
'y/o', 'retención del dividendo', and 'rendimiento de capital' in V2)
is recognized by its classifier in both lowercase and uppercase form,
locking in the lowercase normalization behavior of the existing
substring-match logic.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/converters/degiroConverterV2.test.ts (1)

151-199: 💤 Low value

Solid coverage of the new Spanish classifiers; consider locking in negative cases.

The factory correctly populates date/time/product/isin and a non-empty description, so the isIgnoredRecord early-return guards are bypassed and the keyword path is actually exercised. The buy/sell ([true]) vs dividend ([false]) contexts for isTransactionFeeRecord are also handled correctly given the empty default orderId.

One gap: every row asserts expected === true, so the suite only proves these keywords match — it can't catch future over-matching (the keywords are short substrings, e.g. y/o). A couple of false rows (e.g. an unrelated description, or a dividend-context record that has an orderId) would harden the suite.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/converters/degiroConverterV2.test.ts` around lines 151 - 199, Tests only
assert positive matches, so add negative cases to prevent over-matching: extend
the table in the Spanish keyword classification test (the it.each block using
record(...) and newSut()) with rows where expected === false — e.g., a
description that contains the short substrings in an unrelated context (to test
isIgnoredRecord/isPlatformFees/isDividendRecord do not false-positive) and a
transaction-fee check with the opposite context (call isTransactionFeeRecord
with [true] when it should be false because orderId is present, and with [false]
when orderId is non-empty) — reference the classifier methods isIgnoredRecord,
isPlatformFees, isTransactionFeeRecord, isDividendRecord and the helpers
record() and newSut() so you add a couple of rows asserting false to harden the
suite.
src/converters/degiroConverterV3.test.ts (1)

182-226: 💤 Low value

Test block mirrors V2 correctly.

Factory state bypasses the isIgnoredRecord guards, and the buy/sell vs dividend isTransactionFeeRecord contexts are exercised correctly. Note the V3 suite intentionally omits the isDividendRecord case (V2-only per PR), which is consistent since V3 routes non-buy/sell records through mapDividendRecord.

Same optional observation as V2: all rows assert true, so adding a few negative cases would guard against future over-matching on the short keywords.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/converters/degiroConverterV3.test.ts` around lines 182 - 226, Tests only
assert true for Spanish keyword classifiers, leaving no negative cases to
prevent over-matching; add a few negative test rows to the it.each matrix that
assert false for each classifier (isIgnoredRecord, isPlatformFees,
isTransactionFeeRecord) using descriptions that are similar but lack the keyword
(and include mixed case variants) so the calls to
sut[method](record(description), ...extraArgs) return false; update the dataset
in src/converters/degiroConverterV3.test.ts (the it.each array) to include these
negative rows alongside the existing positives to guard against future
over-matching.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/converters/degiroConverterV2.test.ts`:
- Around line 151-199: Tests only assert positive matches, so add negative cases
to prevent over-matching: extend the table in the Spanish keyword classification
test (the it.each block using record(...) and newSut()) with rows where expected
=== false — e.g., a description that contains the short substrings in an
unrelated context (to test isIgnoredRecord/isPlatformFees/isDividendRecord do
not false-positive) and a transaction-fee check with the opposite context (call
isTransactionFeeRecord with [true] when it should be false because orderId is
present, and with [false] when orderId is non-empty) — reference the classifier
methods isIgnoredRecord, isPlatformFees, isTransactionFeeRecord,
isDividendRecord and the helpers record() and newSut() so you add a couple of
rows asserting false to harden the suite.

In `@src/converters/degiroConverterV3.test.ts`:
- Around line 182-226: Tests only assert true for Spanish keyword classifiers,
leaving no negative cases to prevent over-matching; add a few negative test rows
to the it.each matrix that assert false for each classifier (isIgnoredRecord,
isPlatformFees, isTransactionFeeRecord) using descriptions that are similar but
lack the keyword (and include mixed case variants) so the calls to
sut[method](record(description), ...extraArgs) return false; update the dataset
in src/converters/degiroConverterV3.test.ts (the it.each array) to include these
negative rows alongside the existing positives to guard against future
over-matching.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b8a8aac-3127-42ea-8cbf-4721cc245670

📥 Commits

Reviewing files that changed from the base of the PR and between 918b7c1 and 86b4e81.

📒 Files selected for processing (2)
  • src/converters/degiroConverterV2.test.ts
  • src/converters/degiroConverterV3.test.ts

…tests

Extend the it.each tables in both degiroConverterV2.test.ts and
degiroConverterV3.test.ts with negative rows that assert each classifier
returns false for unrelated phrases (real Compra/Venta/Dividendo
descriptions) and for cross-classifier overlap (the Spanish trade-fee
phrase does not match isPlatformFees or isDividendRecord). Also add a
dedicated test for the isTransactionFeeRecord dividend-context orderId
guard, asserting the early-return path returns false even for a real
'Retención del dividendo' phrase when an orderId is present.
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.

1 participant