Skip to content

Map MyData receipt-level Void on non-8.6 cases to refund flow#671

Open
StefanKert wants to merge 1 commit into
mainfrom
claude/heuristic-borg-651d0b
Open

Map MyData receipt-level Void on non-8.6 cases to refund flow#671
StefanKert wants to merge 1 commit into
mainfrom
claude/heuristic-borg-651d0b

Conversation

@StefanKert
Copy link
Copy Markdown
Member

Summary

myDATA's CancelInvoice endpoint is reserved for direct ERP/AADE users and is not callable through the e-Invoice Provider channel (see market-gr#133). The provider-legal equivalent of a cancellation is a credit-note / refund-slip document, which the SCU already produces for ReceiptCaseFlags.Refund.

Until now, receipt-level Void on anything other than Order0x3004 (the 8.6 path) threw "Voiding of documents is not supported for this invoice type. Please use refund." This PR removes that wall: Void on non-8.6 cases now routes through the existing refund flow.

Source case Resulting myDATA document
Receipt + Void 11.4 retail refund slip (multipleConnectedMarks)
Invoice + Void + prior MARK 5.1 credit note - associated (correlatedInvoices)
Invoice + Void without prior MARK 5.2 credit note - non-associated
PaymentTransfer + Void 8.5 refund payment transfer

In all four cases line amounts, VAT and payment amounts are negated, matching what Refund already produces.

What stays unchanged

  • Order0x3004 + Void → 8.6 keeps the dedicated totalCancelDeliveryOrders + multipleConnectedMarks cancellation path (market-gr#116).
  • DeliveryNote0x0005 + Void + HasTransportInformation → 9.3 keeps the dedicated /myDataProvider/CancelDeliveryNote endpoint (market-gr#119).
  • Providers still cannot call CancelInvoice directly — market-gr#133 stands.

Design

A single IsEffectiveRefund() extension on ReceiptRequest returns true when either Refund is set, or Void is set on a non-Order0x3004 case. Eight call sites swap from IsFlag(ReceiptCaseFlags.Refund) to this helper:

  • AADEMappings: type resolution for receipt → 11.4, invoice → 5.1/5.2, payment-transfer → 8.5, and the IncomeClassificationType net-amount sign.
  • AADEFactory: correlatedInvoices vs multipleConnectedMarks placement, line and payment amount negation, and 9.3 reverseDeliveryNote.

The two "Voiding not supported" throws stay as defense-in-depth — only reachable if someone overrides Void+Order0x3004 to a non-8.6 invoice type via mydataoverride.

Tests

  • New VoidAsRefundTests.cs (8 tests): type resolution for each invoice family, the 8.6 regression guard, amount negation + mark placement, and the helper semantics.
  • Updated CancelInvoiceValidationTests.cs Test 11: previously asserted the throw; now asserts an Item114 document with negated amounts and multipleConnectedMarks populated.
  • Unchanged: full CancelInvoiceValidationTests (8.6 path) and PartiallyCancelInvoiceValidationTests (per-item recType=7) suites continue to pass.

819/819 unit tests green; build clean.

Related

Test plan

  • Local: dotnet test scu-gr/test/fiskaltrust.Middleware.SCU.GR.MyData.UnitTest/ — 819/819 pass
  • Sandbox: replay SignRequestReceipt_VoidReceipt_1 (Receipt + Void) → 11.4 retail refund slip with negative amounts and multipleConnectedMarks populated
  • Sandbox: replay SignRequestReceipt_VoidReceipt_2 → matching refund-shaped document
  • Sandbox regression: existing 8.6 restaurant-order void still emits totalCancelDeliveryOrders=true via SendInvoices
  • Sandbox regression: existing 9.3 delivery-note void still calls /myDataProvider/CancelDeliveryNote

🤖 Generated with Claude Code

AADE's CancelInvoice endpoint is reserved for direct ERP/AADE users and
is not callable through the e-Invoice Provider channel (market-gr#133).
The provider-legal equivalent of a cancellation is a credit-note /
refund-slip document, which the SCU already produces for Refund.

Introduce a single IsEffectiveRefund() helper that returns true when
either Refund is set, or Void is set on a non-Order0x3004 case. Route
the four type-resolution call sites in AADEMappings (Item84/Item85,
Item111/Item114, Item11/Item51/52, line net amount) and the four
shape/amount call sites in AADEFactory (correlatedInvoices vs
multipleConnectedMarks placement, line and payment amount negation,
9.3 reverseDeliveryNote) through the helper. The two "Voiding not
supported" throws stay as defense-in-depth — only reachable if someone
overrides Void+Order0x3004 to a non-8.6 invoice type.

The 8.6 totalCancelDeliveryOrders cancellation (#116) and the dedicated
9.3 CancelDeliveryNote endpoint (#119) paths are unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@StefanKert StefanKert requested a review from a team as a code owner May 22, 2026 10:43
@github-actions github-actions Bot added market-gr Related to the greek market area-tests Affects the test labels May 22, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a94b5c94d3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +49 to +50
|| (receiptRequest.ftReceiptCase.IsFlag(ReceiptCaseFlags.Void)
&& !receiptRequest.ftReceiptCase.IsCase(ReceiptCase.Order0x3004));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Base effective-refund on resolved type, not only receipt case

IsEffectiveRefund() treats every Void that is not Order0x3004 as refund-shaped before overrides are applied. In CreateInvoiceDocType, 8.6-specific void handling (SetInvoiceHeaderFieldsForVoid) runs before ApplyMyDataOverride, so a Void receipt/invoice with mydataoverride.invoiceHeader.invoiceType = "8.6" now bypasses the old guard, gets refund-negated rows, and can end up as final type 8.6 without the required 8.6 cancellation header/validation path. This is a new inconsistent-output path introduced by the helper condition.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-tests Affects the test market-gr Related to the greek market

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant