fiskaltrust / fiskaltrust/middleware
TicketBAI: charge item with TypeOfService=OtherService is duplicated across Entrega and PrestacionServicios
- Dominant language
- C#
- Stars
- 20
- Forks
- 11
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 13
Description
## Summary
In `TicketBaiFactory.GetFacturaDetails`, the foreign-customer branch filters charge items into two buckets — `entregaChargeItems` and `prestacionServiciosChargeItems`. **`ChargeItemCaseTypeOfService.OtherService` is present in *both* filter lists**, so any charge item whose `TypeOfService()` is `OtherService` is reported twice in the emitted XML: once under `` and once under ``. The same `` (or VAT base, or ``) ends up appearing in both branches, which both inflates the totals AEAT cross-checks and produces an XML the recipient sees as two distinct operations.
## Reproduction
Build a `ProcessRequest` with:
- A foreign `cbCustomer` (e.g. `CustomerCountry = \"FR\"`),
- A single `ChargeItem` with `ftChargeItemCase` carrying `TypeOfService = OtherService` (low byte `0x28`) and any `NatureOfVat`,
and run `TicketBaiFactory.ConvertTo`. The produced `` has *both* an `` and a `` block, each containing the full charge-item amount.
## Location
[`scu-es/src/fiskaltrust.Middleware.SCU.ES.TicketBAI.Common/TicketBaiFactory.cs`](https://github.com/fiskaltrust/middleware/blob/main/scu-es/src/fiskaltrust.Middleware.SCU.ES.TicketBAI.Common/TicketBaiFactory.cs), around the foreign-customer branch of `GetFacturaDetails`:
\`\`\`csharp
var entregaChargeItems = new List {
ChargeItemCaseTypeOfService.UnknownService,
ChargeItemCaseTypeOfService.Delivery,
ChargeItemCaseTypeOfService.Voucher,
ChargeItemCaseTypeOfService.CatalogService,
ChargeItemCaseTypeOfService.NotOwnSales,
ChargeItemCaseTypeOfService.OtherService // ← also in prestacion list
};
var prestacionServiciosChargeItems = new List {
ChargeItemCaseTypeOfService.OtherService, // ← also in entrega list
ChargeItemCaseTypeOfService.Tip,
ChargeItemCaseTypeOfService.Grant,
ChargeItemCaseTypeOfService.Receivable,
ChargeItemCaseTypeOfService.CashTransfer
};
\`\`\`
## Pre-existing
This was introduced when the foreign-customer branch was first added in [a1c14a66 \"Support for foreign customers\"](https://github.com/fiskaltrust/middleware/commit/a1c14a66) and was preserved through the recent exempt-reasons refactor in [#669](https://github.com/fiskaltrust/middleware/pull/669) — the refactor passes the same filtered lists into the new `BuildDesgloseParts` helper.
## Suggested fix
Decide which branch `OtherService` belongs in. The semantics in `fiskaltrust.ifPOS.v2` are \"a service of an unspecified kind\", which strongly suggests `PrestacionServicios` (provision of services) — i.e. **remove it from the `entregaChargeItems` list**. If there are real use cases where an `OtherService` charge item should land in `Entrega`, the input model needs a more specific `TypeOfService` rather than overloaded routing.
## Impact
Limited today because the `TicketBaiFactory` is itself only reachable for receipts that pass through the TicketBAI SCU (Araba / Bizkaia / Gipuzkoa), and the foreign-customer path is hit only when `cbCustomer.CustomerCountry != \"ES\"`. But any foreign-customer invoice that uses `OtherService` charge items today produces a malformed AEAT submission, and the refactor in #669 makes the same shape produced for exempt cases too, so the doubling now also duplicates `` and `` declarations — not just ``. Worth fixing before #669 ships.
## Related
- #669 (TicketBAI exempt-reasons support) — preserves but does not introduce this bug.
- The acceptance test [\`TicketBaiFactoryXmlAcceptanceTests.Foreign_ExportGoodsAndDomesticService_…\`](https://github.com/fiskaltrust/middleware/blob/claude/nervous-ishizaka-3555fc/scu-es/test/fiskaltrust.Middleware.SCU.ES.AcceptanceTest/TicketBaiFactoryXmlAcceptanceTests.cs) explicitly works around the bug with `Delivery`/`Tip` to demonstrate the *intended* split; comment in that test cross-references this issue.
🤖 Filed via Claude Code on behalf of @StefanKert
Contributor guide
Assessment
This issue has not been assessed yet.