Add ENTRY_VOID movement type and integrate balance entry creation in invoice processing

- Introduced a new movement type 'ENTRY_VOID' to handle invoice reversals, ensuring net balance remains zero.
- Updated the FaLineItem DTOs to replace 'download' with 'discharge' for consistency.
- Implemented balance entry creation in the invoice processing and reverting workflows, enhancing inventory management.
- Adjusted progress tracking messages to reflect the new balance entry generation steps.
This commit is contained in:
2026-03-17 19:46:09 -05:00
parent 3eacbf18f2
commit 73462fcec3
7 changed files with 30 additions and 5 deletions

View File

@@ -74,6 +74,12 @@ class MovementType(str, Enum):
EXPIRATION = "expiration" # Balance cancelled due to deadline
REGIME_CHANGE_OUT = "regime_chg_out" # Eg. temporary → definitive (exit side)
# ── Reversal (annuls a prior ENTRY — used when un-processing an invoice) ─
# Inserting ENTRY_VOID with the same quantity as the original ENTRY leaves
# the net balance at zero, preventing any further discharges against that
# lot. A fresh ENTRY is created when the invoice is re-processed.
ENTRY_VOID = "entry_void"
# Which movement types reduce the balance (sign = -1)
NEGATIVE_MOVEMENTS = {
@@ -85,6 +91,7 @@ NEGATIVE_MOVEMENTS = {
MovementType.TRANSFER_OUT,
MovementType.EXPIRATION,
MovementType.REGIME_CHANGE_OUT,
MovementType.ENTRY_VOID,
}
# Which types count toward "used" (CANTUSADA in Anexo 24 report)

View File

@@ -56,7 +56,7 @@ class FaLineItemCreateDTO(BaseModel):
subitem_number: Optional[int] = Field(0, description="Número de subpartida")
# Special flags
download: Optional[bool] = Field(None, description="Indicador de descarga")
discharge: Optional[bool] = Field(None, description="Indicador de descarga")
own_equipment: Optional[bool] = Field(None, description="Equipo propio")
omit_annex31: Optional[bool] = Field(None, description="Omitir en Anexo 31")
@@ -108,7 +108,7 @@ class FaLineItemUpdateDTO(BaseModel):
subitem_number: Optional[int] = Field(None, description="Número de subpartida")
# Special flags
download: Optional[bool] = Field(None, description="Indicador de descarga")
discharge: Optional[bool] = Field(None, description="Indicador de descarga")
own_equipment: Optional[bool] = Field(None, description="Equipo propio")
omit_annex31: Optional[bool] = Field(None, description="Omitir en Anexo 31")
@@ -156,7 +156,7 @@ class FaLineItemResponseDTO(BaseModel):
subitem_number: Optional[int] = Field(None, description="Número de subpartida")
# Special flags
download: Optional[bool] = Field(None, description="Indicador de descarga")
discharge: Optional[bool] = Field(None, description="Indicador de descarga")
own_equipment: Optional[bool] = Field(None, description="Equipo propio")
omit_annex31: Optional[bool] = Field(None, description="Omitir en Anexo 31")