parser(comdirect): fix withholding tax sometimes (e.g. when tax >15%) being only partially regarded by detecting and adding missing amount in the post stage#5718
Conversation
… being only partially regarded by detecting and adding missing amount in the post stage
8607901 to
3b8e200
Compare
|
@Nirus2000 |
|
Hello @verybadsoldier, Converting to draft while the following items are addressed:
As a side note: we are aware that Once these are addressed, the PR can be moved back to "Ready for review". Thanks again for the contribution! Regards |
|
Hey @Nirus2000 thanks for your feedback, I really appreciate. Regarding the tests: I'll get those updated to match the project conventions, thanks for pointing that out. Regarding the approach in this PR in general: if I understand your comment correctly then you are not happy with the general direction taken to fix this, right?
Just to clarify, the fix in this PR does not happen in the preliminary dividend notification but in the post processing stage later. As my experience here is quite limited, I tried to tackle the problem without changing the core concept of how I understand the multi-stage parsers are working. Instead of doing that this way, you propose to fix the problem inside of |
|
Hello @verybadsoldier First, try to look at the two documents separately. The gross amount of the dividend entry is €187.00. Next, create the tax document. The €22.81 is the portion of the foreign withholding tax that was withheld by the foreign country but exceeds the DTA credit limit and is therefore neither credited nor refunded. Regards |
|
@Nirus2000 The root problem in the end is my lack of fundamental understanding about how all those different taxes and special cases. I'll again try to wrap my head around that but possibly I might give up at some point. |
|
Hello @verybadsoldier |
|
@Nirus2000 I fiddle around quite a bit until I had it working. In the end it worked without the additional "Zu Ihren Gunsten nach Steuern" but maybe that is more a bad sign than a good sign :D So, well yeah, let's go with your solution, you are surely more experience with this. I only have some minor code comments if you want. |
Can you summarize the commits so they're easier to read? It's too tedious to keep clicking back and forth between three commits. |
Yes, sure, I squashed it now. |
|
Hey @verybadsoldier, Your missingTaxes idea is actually really neat conceptually — you're explicitly naming the thing that causes the bug (the non-creditable chunk of foreign withholding), which makes the intent crystal clear. I Where I got a bit uneasy though: when The reason I went with But honestly the core insight in your fix is solid and you clearly understand the problem well. Nice catch on the >15% DTA limit case — that one's sneaky! Do you agree with that? Regards |
|
Hey @Nirus2000 , yes sure, makes totally sense, I am happy if your are ;) The biggest challenge for me was fixing the behavior in this special case without hurting any other cases. I was also not totally satisfied with the conditions I chose to decide when to apply the fix. There were some cases I just did not understand. E.g. As I understand it, the 4.40€ under "Quellensteuer" are actually the result of the "Kapitalertragssteuer" of the "Steuerbemessungsgrundlage" of 17.59€. But it still baffles me why the document list 0€ as Kapitalertragssteuer but lists the 4.40€ as "angerechnete Quellensteuer". Anyway, happy to go with your approach, thanks alot for guidance! |
|
|
||
| // Calculate total deducted taxes based on assessment basis and received amount after taxes, | ||
| // as this reflects the actual tax burden more accurately (including allowances and loss offset) | ||
| var totalDeductedTaxesFromAmounts = grossAssessmentBasis.subtract(grossAfterTaxes); |
There was a problem hiding this comment.
Maybe move down closer to where it is used the first time.
| @@ -1210,6 +1207,12 @@ private void addTaxesTreatmentTransaction() | |||
| if (deductedTaxes.isZero() && grossAssessmentBasis.isGreaterThan(grossBeforeTaxes)) | |||
| t.setMonetaryAmount(grossAssessmentBasis.subtract(grossBeforeTaxes)); | |||
There was a problem hiding this comment.
The value here set by call setMonetaryAmount might get overwritten in line 1214 by another call to setMonetaryAmount. Also, both calls would overwrite the value from line 1193. Possible to only set the value once to make the intent more clear?
82792b1 to
e58f90d
Compare
The document is actually consistent — here's why:
The 4,40 EUR didn't disappear — it was paid to the foreign tax authority at source, credited against the German liability, and so comdirect had nothing left to deduct ("abgeführte Steuern: 0,00 EUR"). The investor received 128,00 EUR What the importer does with this:
So the fix handles this case correctly and the existing test (hasAmount("EUR", 4.40)) continues to pass unchanged. Regards |
|
@Nirus2000 One last thing about the mysterious case The Quellensteuer does not appear in the original Then suddenly in part 2 ( |
|
That's a great observation — and it trips up most people the first time they see it. The key is: for a German issuer (Emissionsland: DEUTSCHLAND), no foreign tax is ever deducted from the cash payment itself. Allianz SE pays out EUR 128.00 and that's exactly what lands in the account — the Dividendengutschrift is a pure cash-flow document. There is nothing to deduct, so nothing appears there. The "angerechnete ausländische Quellensteuer" of EUR 4.40 shows up only in the Steuermitteilung because it is a tax attribute, not a cash deduction. Here's what actually happened: Allianz SE is a German holding company but earns income internationally. Under §36 Abs. 2 Nr. 2 EStG / §32d (5) EStG, a portion of the foreign taxes paid at company level can be attributed to shareholders and credited against their German Kapitalertragsteuer liability. Allianz SE reports this to the custodians (e.g. Clearstream), who pass it on to comdirect, who then include it in the Steuermitteilung as a tax-reducing credit. So the flow is:
In short: it never appeared in Dividende13.txt because it was never a cash deduction. It is purely a bookkeeping credit that exists only in the tax domain. Regards |
|
@Nirus2000 |
Store information about withholding tax from both PDFs separately and check in post processing stage if withholding amount was incompletely regarded in second stage. Then add the missing amount to the final tax amount if needed.