Skip to content

Conversation

@MathewMigliore
Copy link
Contributor

Pull Request Template

Description

Fixes a crash in Finkok cancellation when the SOAP response omits apps:EstatusUUID (empty in demo). The update safely handles missing EstatusUUID, falls back to CodEstatus if present, and parses EstatusUUID from the embedded Acuse XML when available. This prevents AttributeError while preserving existing behavior.

Fixes # (53)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

Requires external Finkok demo credentials/services and SAT availability

Test Configuration:

  • Firmware version: N/A
  • Hardware: N/A
  • Toolchain: N/A
  • SDK: N/A

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

Copilot AI review requested due to automatic review settings January 18, 2026 19:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a crash in Finkok cancellation operations when the SOAP response omits the EstatusUUID field. The fix implements a three-tier fallback strategy: first attempting to use EstatusUUID, then falling back to CodEstatus, and finally parsing the status from the embedded Acuse XML if both are missing.

Changes:

  • Refactored acuse_bytes extraction to avoid redundant computation
  • Implemented fallback logic to safely handle missing status fields
  • Allowed code parameter to be None when all status sources are unavailable

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +238 to +252
estatus_uuid_elem = root.find(".//apps:EstatusUUID", self.namespaces)
if estatus_uuid_elem is not None:
code = estatus_uuid_elem.text
else:
cod_estatus_elem = root.find(".//apps:CodEstatus", self.namespaces)
code = cod_estatus_elem.text if cod_estatus_elem is not None else None

if code is None and acuse_bytes:
try:
acuse_root = etree.fromstring(acuse_bytes)
estatus_in_acuse = acuse_root.find(".//*[local-name()='EstatusUUID']")
if estatus_in_acuse is not None and estatus_in_acuse.text:
code = estatus_in_acuse.text
except Exception:
pass
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The fallback logic for determining the status code when EstatusUUID is missing could benefit from inline comments explaining each fallback step. This would help maintainers understand why the code tries EstatusUUID first, then CodEstatus, and finally parses the Acuse XML. Consider adding comments like:

  • "Try primary status field EstatusUUID"
  • "Fallback to CodEstatus if EstatusUUID is missing"
  • "Last resort: extract EstatusUUID from embedded Acuse XML"

Copilot uses AI. Check for mistakes.
Comment on lines +251 to +252
except Exception:
pass
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The bare except clause catches all exceptions during Acuse XML parsing, which may hide legitimate errors like encoding issues or malformed XML structures. Consider being more specific about which exceptions to catch (e.g., etree.XMLSyntaxError, UnicodeDecodeError, AttributeError) or at minimum logging the caught exception for debugging purposes.

Suggested change
except Exception:
pass
except (etree.XMLSyntaxError, UnicodeDecodeError, AttributeError) as exc:
getLogger(__name__).debug(
"Failed to parse Acuse XML while extracting EstatusUUID: %s",
exc,
)

Copilot uses AI. Check for mistakes.
code = estatus_in_acuse.text
except Exception:
pass

Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The code now allows None to be assigned to the code parameter, but the type annotation in CancelationAcknowledgment (satcfdi/pacs/init.py line 41) specifies 'code: str | dict' without including None. This creates a type inconsistency. The type annotation should be updated to 'code: str | dict | None' to accurately reflect the possible values and maintain type safety.

Suggested change
# Ensure `code` matches the expected type annotation (str | dict)
if code is None:
code = ""

Copilot uses AI. Check for mistakes.
Comment on lines +238 to 257
estatus_uuid_elem = root.find(".//apps:EstatusUUID", self.namespaces)
if estatus_uuid_elem is not None:
code = estatus_uuid_elem.text
else:
cod_estatus_elem = root.find(".//apps:CodEstatus", self.namespaces)
code = cod_estatus_elem.text if cod_estatus_elem is not None else None

if code is None and acuse_bytes:
try:
acuse_root = etree.fromstring(acuse_bytes)
estatus_in_acuse = acuse_root.find(".//*[local-name()='EstatusUUID']")
if estatus_in_acuse is not None and estatus_in_acuse.text:
code = estatus_in_acuse.text
except Exception:
pass

return CancelationAcknowledgment(
code=root.find(".//apps:EstatusUUID", self.namespaces).text,
acuse=unescape(ack.text).encode(),
code=code,
acuse=acuse_bytes,
)
Copy link

Copilot AI Jan 18, 2026

Choose a reason for hiding this comment

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

The new fallback logic for handling missing EstatusUUID is not covered by tests. Since this repository uses comprehensive automated testing (as evidenced by existing tests in tests/test_pac_finkok.py), consider adding test cases that specifically validate:

  1. Response with missing EstatusUUID but present CodEstatus
  2. Response with missing both EstatusUUID and CodEstatus but EstatusUUID available in Acuse XML
  3. Response with all status fields missing (code should be None)

This would ensure the bug fix works correctly and prevent regression.

Copilot uses AI. Check for mistakes.
@satcfdi satcfdi merged commit 4b78e05 into SAT-CFDI:main Jan 19, 2026
5 of 6 checks passed
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