Merge pull request 'Refactor invoice status terminology and update related logic' (#206) from fix/is_updated into development

Reviewed-on: ADUANASOFT/anexo76#206
This commit is contained in:
2026-03-13 17:57:07 +00:00
14 changed files with 58 additions and 56 deletions

View File

@@ -82,8 +82,8 @@ def invoice_processed(
company_id: int,
errors: ErrorCollector,
) -> bool:
is_processed = (
db.query(models.InvoiceHeader.is_processed)
status = (
db.query(models.InvoiceHeader.status)
.filter(
models.InvoiceHeader.id == invoice_id,
models.InvoiceHeader.tenant_id == tenant_id,
@@ -92,7 +92,7 @@ def invoice_processed(
.scalar()
)
if is_processed:
if status == models.InvoiceStatus.PROCESSED:
errors.add_error(
field="invoice_number",
message=f"La factura con el número '{invoice_id}' ya ha sido actualizada y no se puede modificar.",

View File

@@ -56,7 +56,7 @@ class InvoiceHeaderBase(BaseModel):
)
invoice_date: date = Field(..., description="Invoice date")
emission_date: Optional[date] = Field(None, description="Emission date")
is_processed: bool = Field(False, description="Status")
status: bool = Field(False, description="Status")
processed_date: Optional[datetime] = Field(None, description="Update date")
who_processed: Optional[str] = Field(None, max_length=20, description="Who processed")
capture_user: Optional[str] = Field(None, max_length=20, description="Capture user")
@@ -66,8 +66,8 @@ class InvoiceHeaderBase(BaseModel):
process_log: Optional[str] = Field(
None, max_length=300, description="Processing log"
)
is_processed_rec: Optional[int] = Field(None, description="Reception status")
is_processed_rep: Optional[str] = Field(
status_rec: Optional[int] = Field(None, description="Reception status")
status_rep: Optional[str] = Field(
None, max_length=2, description="Report status"
)
observation_es: Optional[str] = Field(None, description="Observations in Spanish")

View File

@@ -70,7 +70,9 @@ class InvoiceService:
# Apply filters if provided
if filters:
if filters.get("status") is not None:
query = query.filter(models.InvoiceHeader.is_processed == filters["status"])
status = models.InvoiceStatus.PROCESSED if filters["status"] == True else models.InvoiceStatus.PENDING
query = query.filter(models.InvoiceHeader.status == status)
if filters.get("operation_type"):
ot = filters["operation_type"]
ot_val = ot.value if hasattr(ot, "value") else ot

View File

@@ -292,7 +292,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -453,7 +453,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
company_rfc = (company.rfc or "").strip().upper() if company else ""
q_inv_expo = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -628,7 +628,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -790,7 +790,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
# Invoice lookup: imp + TEM
q = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -928,7 +928,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -1185,7 +1185,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -1443,7 +1443,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
rfc_exception_egm = False
q_inv_expo = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -1712,7 +1712,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -1978,7 +1978,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -2309,7 +2309,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -2647,7 +2647,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed, InvoiceHeader.is_processed_rep)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status, InvoiceHeader.status_rep)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -2969,7 +2969,7 @@ def _do_scan_file(job_id: str, model_target: str, config: Optional[str] = None,
with CoreSessionLocal() as session:
q_inv = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -4008,7 +4008,7 @@ def _do_insert_valid_rows(job_id: str, model_target: str, job_type_override: Opt
with CoreSessionLocal() as session:
q = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -4275,7 +4275,7 @@ def _do_insert_valid_rows(job_id: str, model_target: str, job_type_override: Opt
with CoreSessionLocal() as session:
q = (
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.is_processed)
session.query(InvoiceHeader.invoice_number, InvoiceHeader.id, InvoiceHeader.status)
.filter(
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
@@ -4913,7 +4913,7 @@ def _do_insert_valid_rows(job_id: str, model_target: str, job_type_override: Opt
header = existing_header
header.invoice_date = invoice_date
header.operation_type = op_type_value
header.is_processed = True # Mark as updated
header.status = True # Mark as updated
header.updated_date = datetime.utcnow()
capture_user = meta.get("capture_user") or "CSV"
header.who_updated = capture_user
@@ -4952,7 +4952,7 @@ def _do_insert_valid_rows(job_id: str, model_target: str, job_type_override: Opt
invoice_number=invoice_number,
invoice_date=invoice_date,
operation_type=op_type_value,
is_processed=False,
status=False,
system="CSV",
capture_date=datetime.utcnow(),
capture_user=capture_user,

View File

@@ -70,7 +70,7 @@ class DefinitiveImportService:
estatus = row[3] # C4 - Estatus (AC o NA)
# Filtrar facturas según include_cancelled
# Si include_cancelled=False, solo mostrar AC (is_processed=true)
# Si include_cancelled=False, solo mostrar AC (status=true)
# Si include_cancelled=True, mostrar todas (AC y NA)
if not filters.include_cancelled and estatus != 'AC':
continue
@@ -345,7 +345,7 @@ class DefinitiveImportService:
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
# Note: Status filter applied at Python level after CASE WHEN in SELECT
# because is_processed doesn't directly represent AC/NA status
# because status doesn't directly represent AC/NA status
# Provider filter
if filters.provider:

View File

@@ -326,8 +326,8 @@ class ExportService:
Build WHERE clause for export query.
IMPORTANT: Returns conditions WITHOUT the WHERE keyword (already in base query)
AC (Active) = is_processed = true
NA (Not Applicable/Deactivated) = is_processed = false
AC (Active) = status = true
NA (Not Applicable/Deactivated) = status = false
"""
conditions = []
@@ -344,11 +344,11 @@ class ExportService:
# CRITICAL VALIDATION: AC/NA status filter
# If include_cancelled is False (checkbox unchecked), only show AC invoices
# AC (Active) = is_processed = true
# NA (Not Applicable/Deactivated) = is_processed = false
# AC (Active) = status = true
# NA (Not Applicable/Deactivated) = status = false
if not filters.include_cancelled:
conditions.append("ih.is_processed = true")
logger.debug("Filtering only active invoices (is_processed = true)")
conditions.append("ih.status = true")
logger.debug("Filtering only active invoices (status = true)")
else:
logger.debug("Including cancelled invoices (include_cancelled = true)")

View File

@@ -16,7 +16,7 @@ class TemporaryImportQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C4,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C4,
COALESCE(ped.pedimento_code, '') AS C5,
COALESCE(ped.regime, '') AS C10,
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
@@ -92,7 +92,7 @@ class TemporaryImportQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C4,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C4,
COALESCE(ped.pedimento_code, '') AS C5,
COALESCE(fin.value_me, 0) AS C6,
COALESCE(fin.value_mn, 0) AS C7,
@@ -230,7 +230,7 @@ class DefinitiveImportQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C4,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C4,
COALESCE(ped.pedimento_code, '') AS C5,
COALESCE(ped.regime, '') AS C10,
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C11,
@@ -299,7 +299,7 @@ class DefinitiveImportQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C4,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C4,
COALESCE(ped.pedimento_code, '') AS C5,
COALESCE(fin.value_me, 0) AS C6,
COALESCE(fin.value_mn, 0) AS C7,
@@ -446,7 +446,7 @@ class RepairImportQueries:
ih.invoice_number AS C2,
COALESCE(ped.pedimento_number, '') AS C3,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C4,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C5,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C5,
COALESCE(ped.pedimento_code, '') AS C6,
COALESCE(ped.regime, '') AS C7,
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C9,
@@ -527,7 +527,7 @@ class RepairImportQueries:
ih.invoice_number,
COALESCE(ped.pedimento_number, ''),
TO_CHAR(ih.invoice_date, 'YYYYMMDD'),
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END,
COALESCE(ped.pedimento_code, ''),
COALESCE(ped.regime, ''),
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), ''),
@@ -664,7 +664,7 @@ class ExportQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C6,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C6,
COALESCE(ped.pedimento_code, '') AS C7,
COALESCE(ped.regime, '') AS C8,
COALESCE(TO_CHAR(pd.end_date, 'YYYYMMDD'), TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C10,
@@ -874,7 +874,7 @@ class ExportRepairQueries:
ih.invoice_number AS C1,
COALESCE(ped.pedimento_number, '') AS C2,
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C6,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C6,
COALESCE(ped.pedimento_code, '') AS C7,
COALESCE(ped.regime, '') AS C8,
COALESCE(TO_CHAR(pd.payment_date, 'YYYYMMDD'), '') AS C11,
@@ -943,7 +943,7 @@ class ExportRepairQueries:
TO_CHAR(ih.invoice_date, 'YYYYMMDD') AS C3,
COALESCE(fin.value_me, 0) AS C4,
COALESCE(fin.value_mn, 0) AS C5,
CASE WHEN ih.is_processed THEN 'AC' ELSE 'NA' END AS C6,
CASE WHEN ih.status THEN 'AC' ELSE 'NA' END AS C6,
COALESCE(ped.pedimento_code, '') AS C7,
COALESCE(ped.regime, '') AS C8,
COALESCE(TO_CHAR(pd.entry_date, 'YYYYMMDD'), '') AS C9,

View File

@@ -74,7 +74,7 @@ class RepairImportService:
estatus = row[3] # C5 - Estatus (AC o NA)
# Filtrar facturas según include_cancelled
# Si include_cancelled=False, solo mostrar AC (is_processed=true)
# Si include_cancelled=False, solo mostrar AC (status=true)
# Si include_cancelled=True, mostrar todas (AC y NA)
if not filters.include_cancelled and estatus != 'AC':
continue
@@ -355,7 +355,7 @@ class RepairImportService:
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
# Note: Status filter applied at Python level after CASE WHEN in SELECT
# because is_processed doesn't directly represent AC/NA status
# because status doesn't directly represent AC/NA status
# Provider filter
if filters.provider:

View File

@@ -70,7 +70,7 @@ class TemporaryImportService:
estatus = row[3] # C4 - Estatus (AC o NA)
# Filtrar facturas según include_cancelled
# Si include_cancelled=False, solo mostrar AC (is_processed=true)
# Si include_cancelled=False, solo mostrar AC (status=true)
# Si include_cancelled=True, mostrar todas (AC y NA)
if not filters.include_cancelled and estatus != 'AC':
continue
@@ -421,7 +421,7 @@ class TemporaryImportService:
where_conditions.append(f"pd.payment_date >= TO_DATE('{filters.start_date}', 'YYYYMMDD') AND pd.payment_date <= TO_DATE('{filters.end_date}', 'YYYYMMDD')")
# Note: Status filter applied at Python level after CASE WHEN in SELECT
# because is_processed doesn't directly represent AC/NA status
# because status doesn't directly represent AC/NA status
# Provider filter
if filters.provider:

View File

@@ -208,14 +208,14 @@ export interface Invoice {
invoice_date?: string | null;
capture_date: string;
emission_date?: string | null;
is_processed?: boolean | null;
status?: boolean | null;
processed_date?: string | null;
who_processed?: string | null;
capture_user?: string | null;
traffic_light_status?: string | null;
process_log?: string | null;
is_processed_rec?: number | null;
is_processed_rep?: string | null;
status_rec?: number | null;
status_rep?: string | null;
observation_es?: string | null;
observation_en?: string | null;
comments_status?: string | null;
@@ -266,14 +266,14 @@ export interface CreateInvoiceData {
proforma_number?: string | null;
invoice_date?: string | null;
emission_date?: string | null;
is_processed?: boolean | null;
status?: boolean | null;
processed_date?: string | null;
who_processed?: string | null;
capture_user?: string | null;
traffic_light_status?: string | null;
process_log?: string | null;
is_processed_rec?: number | null;
is_processed_rep?: string | null;
status_rec?: number | null;
status_rep?: string | null;
observation_es?: string | null;
observation_en?: string | null;
comments_status?: string | null;
@@ -319,7 +319,7 @@ export interface UpdateInvoiceData {
cfdi_uuid?: string | null;
path_pdf?: string | null;
path_xml?: string | null;
is_processed?: boolean | null;
status?: boolean | null;
compliance_mx?: Partial<InvoiceComplianceMx> | null;
financials?: Partial<InvoiceFinancials> | null;
logistics?: Partial<InvoiceLogistics>[] | null;

View File

@@ -284,10 +284,10 @@ export function createColumns(
}
},
{
accessorKey: "is_processed",
accessorKey: "status",
header: "Actualizado",
cell: ({ row }) => {
const isprocessed = row.original.is_processed;
const isprocessed = row.original.status;
const processedSnippet = createRawSnippet<[{ isprocessed?: boolean | null }]>((getprocessed) => {
const { isprocessed } = getprocessed();

View File

@@ -121,7 +121,7 @@
</div>
<div>
<p class="text-sm font-medium text-muted-foreground">Actualizado</p>
<p class="text-base">{invoice.is_processed ? 'Sí' : 'No'}</p>
<p class="text-base">{invoice.status ? 'Sí' : 'No'}</p>
</div>
<div class="col-span-2">

View File

@@ -679,7 +679,7 @@
const companyId = companyStore.activeCompany.id;
const response = await invoicesApi.update(selectedInvoice.id, companyId, {
id: selectedInvoice.id,
is_processed: status
status: status
});
if (response.error) {

View File

@@ -236,7 +236,7 @@ seed_invoices() {
# 1. invoice_header — una fila por factura con fecha real en cada mes
# -------------------------------------------------------------------------
exec_pg_sql "INSERT INTO a76.invoice_header
(tenant_id, company_id, system, operation_type, invoice_type, invoice_number, invoice_date, is_processed, created_at, updated_at)
(tenant_id, company_id, system, operation_type, invoice_type, invoice_number, invoice_date, status, created_at, updated_at)
VALUES
-- Abril 2025 (4 facturas)
(${TENANT_ID}, ${COMPANY_ID}, 'fixed_asset', 'imp', 'DEF', 'SEED-2025-04-001', '2025-04-03', false, '2025-04-03 08:00:00', '2025-04-03 08:00:00'),