feat: Enhance invoice management with new operation types and schema updates

This commit is contained in:
2025-12-09 18:02:24 -06:00
parent 7e9c8397ef
commit 6cab955276
5 changed files with 230 additions and 141 deletions

View File

@@ -81,6 +81,7 @@ def upgrade() -> None:
sa.Column("description", sa.String(length=50), nullable=False),
sa.Column("note", sa.String(length=500), nullable=False),
sa.Column("type", sa.String(length=15), nullable=False),
sa.Column("operation", sa.String(length=5), nullable=False),
sa.PrimaryKeyConstraint("key", name="invoice_types_pkey"),
schema="public",
)

View File

@@ -1,3 +1,4 @@
from enum import Enum
from typing import Optional, List
from sqlalchemy import BigInteger, Date, ForeignKey, Integer, Numeric, String, Text, TIMESTAMP
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -5,42 +6,68 @@ from core.database import Base
from datetime import datetime
from ....common.base_models import TenantScopedMixin, TimestampMixin
class OperationType(str, Enum):
IMP = "imp" # Importación
EXP = "exp" # Exportación
# --- 1. Invoice Header (invoice_header) ---
class InvoiceHeader(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_header"
__tableargs__ = {'schema': 'a76'}
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
id: Mapped[int] = mapped_column(
BigInteger, primary_key=True, autoincrement=True)
# Identifiers
legacy_id: Mapped[Optional[int]] = mapped_column(Integer) # CONSECUTIVO
operation_type: Mapped[str] = mapped_column(String(20)) # TIPOMOVIMIENTO / Clasifica IMP/EXP/SM
invoice_number: Mapped[Optional[str]] = mapped_column(String(20)) # FACTURAIMPO/FACTURAEXPO/FACTURAREMISION
project_number: Mapped[Optional[str]] = mapped_column(String(14)) # NUMPROYECTO
purchase_order: Mapped[Optional[str]] = mapped_column(String(50)) # ORDENCOMPRA
related_doc_id: Mapped[Optional[int]] = mapped_column(Integer) # IDRELDOC (Para Rectificaciones)
operation_type: Mapped[OperationType] = mapped_column(
String(3)) # TIPOMOVIMIENTO / Clasifica IMP/EXP
invoice_type: Mapped[Optional[str]] = mapped_column(
ForeignKey("public.invoice_types.key")) # TIPOFACTURA
invoice_number: Mapped[Optional[str]] = mapped_column(
String(20)) # FACTURAIMPO/FACTURAEXPO/FACTURAREMISION
project_number: Mapped[Optional[str]] = mapped_column(
String(14)) # NUMPROYECTO
purchase_order: Mapped[Optional[str]] = mapped_column(
String(50)) # ORDENCOMPRA
related_doc_id: Mapped[Optional[int]] = mapped_column(
Integer) # IDRELDOC (Para Rectificaciones)
# Dates
invoice_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAFACTURA
capture_date: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=False), default=datetime.now) # FECHACAPTURA + HORAACTUAL
invoice_date: Mapped[Optional[datetime]
] = mapped_column(Date) # FECHAFACTURA
capture_date: Mapped[datetime] = mapped_column(
TIMESTAMP(timezone=False), default=datetime.now) # FECHACAPTURA + HORAACTUAL
# Status & Control
status: Mapped[Optional[str]] = mapped_column(String(5)) # ESTATUS
traffic_light_status: Mapped[Optional[str]] = mapped_column(String(50)) # SEMAFORO / SEMAFOROEXPO/IMPO
process_log: Mapped[Optional[str]] = mapped_column(String(300)) # COMOFUEPROCESADA **<-- AÑADIDO**
comments: Mapped[Optional[str]] = mapped_column(Text) # OBSERVACIONE + OBSERVACIONI + COMENTARIOSESTATUS
status: Mapped[Optional[str]] = mapped_column(String(5)) # ESTATUS
traffic_light_status: Mapped[Optional[str]] = mapped_column(
String(50)) # SEMAFORO / SEMAFOROEXPO/IMPO
process_log: Mapped[Optional[str]] = mapped_column(
String(300)) # COMOFUEPROCESADA **<-- AÑADIDO**
# OBSERVACIONE + OBSERVACIONI + COMENTARIOSESTATUS
comments: Mapped[Optional[str]] = mapped_column(Text)
# Digital Archive Links
cfdi_uuid: Mapped[Optional[str]] = mapped_column(String(100)) # CFDIUUID
path_pdf: Mapped[Optional[str]] = mapped_column(String(500)) # CFDIPATHPDF **<-- AÑADIDO**
path_xml: Mapped[Optional[str]] = mapped_column(String(500)) # CFDIPATHXML **<-- AÑADIDO**
cfdi_uuid: Mapped[Optional[str]] = mapped_column(String(100)) # CFDIUUID
path_pdf: Mapped[Optional[str]] = mapped_column(
String(500)) # CFDIPATHPDF **<-- AÑADIDO**
path_xml: Mapped[Optional[str]] = mapped_column(
String(500)) # CFDIPATHXML **<-- AÑADIDO**
# Relationships (Para navegacion ORM)
compliance_mx: Mapped["InvoiceComplianceMx"] = relationship(back_populates="header", cascade="all, delete-orphan")
financials: Mapped["InvoiceFinancials"] = relationship(back_populates="header", cascade="all, delete-orphan")
details: Mapped[List["InvoiceSalesDetails"]] = relationship(back_populates="header", cascade="all, delete-orphan")
collections: Mapped[List["InvoiceCollections"]] = relationship(back_populates="header", cascade="all, delete-orphan")
logistics: Mapped[List["InvoiceLogistics"]] = relationship(back_populates="header", cascade="all, delete-orphan")
compliance_mx: Mapped["InvoiceComplianceMx"] = relationship(
back_populates="header", cascade="all, delete-orphan")
financials: Mapped["InvoiceFinancials"] = relationship(
back_populates="header", cascade="all, delete-orphan")
details: Mapped[List["InvoiceSalesDetails"]] = relationship(
back_populates="header", cascade="all, delete-orphan")
collections: Mapped[List["InvoiceCollections"]] = relationship(
back_populates="header", cascade="all, delete-orphan")
logistics: Mapped[List["InvoiceLogistics"]] = relationship(
back_populates="header", cascade="all, delete-orphan")
# --- 2. Compliance MX (invoice_compliance_mx) ---
@@ -48,27 +75,36 @@ class InvoiceComplianceMx(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_compliance_mx"
__tableargs__ = {'schema': 'a76'}
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoice_header.id"), primary_key=True)
invoice_id: Mapped[int] = mapped_column(
ForeignKey("invoice_header.id"), primary_key=True)
# Core Customs Data
pedimento: Mapped[Optional[str]] = mapped_column(String(19)) # PEDIMENTO/PEDIMENTOIMPO/EXPO
pedimento_code: Mapped[Optional[str]] = mapped_column(String(5)) # PEDIMENTOR1, K1
pedimento: Mapped[Optional[str]] = mapped_column(
String(19)) # PEDIMENTO/PEDIMENTOIMPO/EXPO
pedimento_code: Mapped[Optional[str]] = mapped_column(
String(5)) # PEDIMENTOR1, K1
remesa: Mapped[Optional[int]] = mapped_column(Integer)
aduana: Mapped[Optional[str]] = mapped_column(String(5)) # ADUANA_CRUCE
customs_agent: Mapped[Optional[str]] = mapped_column(String(10)) # AADUANAL
aduana: Mapped[Optional[str]] = mapped_column(String(5)) # ADUANA_CRUCE
customs_agent: Mapped[Optional[str]] = mapped_column(
String(10)) # AADUANAL
# Flags & Specific Regimes
is_mixed: Mapped[Optional[str]] = mapped_column(String(2)) # ESMIXTO **<-- AÑADIDO**
waste_type: Mapped[Optional[str]] = mapped_column(String(1)) # TIPODESPERDICIO **<-- AÑADIDO**
appendix_17: Mapped[Optional[int]] = mapped_column(Integer) # APENDICE17
is_mixed: Mapped[Optional[str]] = mapped_column(
String(2)) # ESMIXTO **<-- AÑADIDO**
waste_type: Mapped[Optional[str]] = mapped_column(
String(1)) # TIPODESPERDICIO **<-- AÑADIDO**
appendix_17: Mapped[Optional[int]] = mapped_column(Integer) # APENDICE17
# VUCEM / Digital
edocument: Mapped[Optional[str]] = mapped_column(String(50)) # EDOCUMENT
electronic_signature: Mapped[Optional[str]] = mapped_column(String(999)) # FIRMAELECTRONICA
sem_id: Mapped[Optional[int]] = mapped_column(Integer) # SEM (de SFacEntradaSM/SFacSalidaSM)
edocument: Mapped[Optional[str]] = mapped_column(String(50)) # EDOCUMENT
electronic_signature: Mapped[Optional[str]] = mapped_column(
String(999)) # FIRMAELECTRONICA
sem_id: Mapped[Optional[int]] = mapped_column(
Integer) # SEM (de SFacEntradaSM/SFacSalidaSM)
# Relationship
header: Mapped["InvoiceHeader"] = relationship(back_populates="compliance_mx")
header: Mapped["InvoiceHeader"] = relationship(
back_populates="compliance_mx")
# --- 3. Financials (invoice_financials) ---
@@ -76,28 +112,40 @@ class InvoiceFinancials(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_financials"
__tableargs__ = {'schema': 'a76'}
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoice_header.id"), primary_key=True)
currency: Mapped[Optional[str]] = mapped_column(String(3)) # CLAVEMONEDA
exchange_rate: Mapped[Optional[float]] = mapped_column(Numeric(13, 6)) # TIPOCAMBIO
invoice_id: Mapped[int] = mapped_column(
ForeignKey("invoice_header.id"), primary_key=True)
currency: Mapped[Optional[str]] = mapped_column(String(3)) # CLAVEMONEDA
exchange_rate: Mapped[Optional[float]] = mapped_column(
Numeric(13, 6)) # TIPOCAMBIO
# Merchandise Values
value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORIMPOMN/EXPOMN
value_me: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0)
customs_value_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # VALORADUANASMN **<-- AÑADIDO**
value_mn: Mapped[Optional[float]] = mapped_column(
Numeric(23, 8), default=0) # VALORIMPOMN/EXPOMN
value_me: Mapped[Optional[float]] = mapped_column(
Numeric(23, 8), default=0)
customs_value_mn: Mapped[Optional[float]] = mapped_column(
Numeric(23, 8), default=0) # VALORADUANASMN **<-- AÑADIDO**
# Costs & Taxes
freight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # FLETE
insurance: Mapped[Optional[float]] = mapped_column(Numeric(19, 8), default=0) # VALSEGUROS/SEGUROS
iva_mn: Mapped[Optional[float]] = mapped_column(Numeric(23, 8), default=0) # IVAEXPOMN / VALORIVAMN
iva_factor: Mapped[Optional[float]] = mapped_column(Numeric(17, 4)) # FACTORIVA
freight: Mapped[Optional[float]] = mapped_column(
Numeric(19, 8), default=0) # FLETE
insurance: Mapped[Optional[float]] = mapped_column(
Numeric(19, 8), default=0) # VALSEGUROS/SEGUROS
iva_mn: Mapped[Optional[float]] = mapped_column(
Numeric(23, 8), default=0) # IVAEXPOMN / VALORIVAMN
iva_factor: Mapped[Optional[float]] = mapped_column(
Numeric(17, 4)) # FACTORIVA
# Weights & Quantities
total_quantity: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # CANTEXPO / CANTIMPO
gross_weight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # PESOBRUTO **<-- AÑADIDO**
net_weight: Mapped[Optional[float]] = mapped_column(Numeric(19, 8)) # PESONETO **<-- AÑADIDO**
bundle_count: Mapped[Optional[int]] = mapped_column(Integer) # CANTBULTOS
total_quantity: Mapped[Optional[float]] = mapped_column(
Numeric(19, 8)) # CANTEXPO / CANTIMPO
gross_weight: Mapped[Optional[float]] = mapped_column(
Numeric(19, 8)) # PESOBRUTO **<-- AÑADIDO**
net_weight: Mapped[Optional[float]] = mapped_column(
Numeric(19, 8)) # PESONETO **<-- AÑADIDO**
bundle_count: Mapped[Optional[int]] = mapped_column(Integer) # CANTBULTOS
# Relationship
header: Mapped["InvoiceHeader"] = relationship(back_populates="financials")
@@ -107,25 +155,33 @@ class InvoiceLogistics(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_logistics"
__tableargs__ = {'schema': 'a76'}
logistics_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
logistics_id: Mapped[int] = mapped_column(
BigInteger, primary_key=True, autoincrement=True)
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoice_header.id"))
# Carrier Info
carrier_id: Mapped[Optional[str]] = mapped_column(String(10)) # TRANSPORTISTA
transport_mode: Mapped[Optional[str]] = mapped_column(String(15)) # TRANSPORTE
driver_name: Mapped[Optional[str]] = mapped_column(String(80)) # CONDUCTOR
is_rail: Mapped[Optional[str]] = mapped_column(String(2)) # ESFERROCARRIL
rail_id: Mapped[Optional[str]] = mapped_column(String(31)) # IDFERRORCARRIL
carrier_id: Mapped[Optional[str]] = mapped_column(
String(10)) # TRANSPORTISTA
transport_mode: Mapped[Optional[str]] = mapped_column(
String(15)) # TRANSPORTE
driver_name: Mapped[Optional[str]] = mapped_column(String(80)) # CONDUCTOR
is_rail: Mapped[Optional[str]] = mapped_column(String(2)) # ESFERROCARRIL
rail_id: Mapped[Optional[str]] = mapped_column(
String(31)) # IDFERRORCARRIL
# Vehicle & Tracking
vehicle_num: Mapped[Optional[str]] = mapped_column(String(20)) # NUMVEHICULO / NUMTRAILER
license_plate: Mapped[Optional[str]] = mapped_column(String(20)) # NUMTRASPORTE
seal_number: Mapped[Optional[str]] = mapped_column(String(15)) # PRECINTO
guide_number: Mapped[Optional[str]] = mapped_column(String(20)) # NUMEROGUIA
vehicle_num: Mapped[Optional[str]] = mapped_column(
String(20)) # NUMVEHICULO / NUMTRAILER
license_plate: Mapped[Optional[str]] = mapped_column(
String(20)) # NUMTRASPORTE
seal_number: Mapped[Optional[str]] = mapped_column(String(15)) # PRECINTO
guide_number: Mapped[Optional[str]] = mapped_column(
String(20)) # NUMEROGUIA
# Logistics Dates
entry_exit_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHAENTRADA / FECHAENVIO
entry_exit_date: Mapped[Optional[datetime]] = mapped_column(
Date) # FECHAENTRADA / FECHAENVIO
# Relationship
header: Mapped["InvoiceHeader"] = relationship(back_populates="logistics")
@@ -135,17 +191,22 @@ class InvoiceSalesDetails(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_sales_details"
__tableargs__ = {'schema': 'a76'}
detail_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
detail_id: Mapped[int] = mapped_column(
BigInteger, primary_key=True, autoincrement=True)
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoice_header.id"))
line_number: Mapped[int] = mapped_column(Integer) # LINEA
sales_order: Mapped[Optional[str]] = mapped_column(String(20)) # ORDENVENTA
line_number: Mapped[int] = mapped_column(Integer) # LINEA
sales_order: Mapped[Optional[str]] = mapped_column(
String(20)) # ORDENVENTA
# Specific Custom Fields
colors_description: Mapped[Optional[str]] = mapped_column(String(49)) # COLORES
square_color_code: Mapped[Optional[str]] = mapped_column(String(1)) # COLORCUADRITO
line_bundles: Mapped[Optional[int]] = mapped_column(Integer) # CANTBULTOS (de la linea)
colors_description: Mapped[Optional[str]
] = mapped_column(String(49)) # COLORES
square_color_code: Mapped[Optional[str]] = mapped_column(
String(1)) # COLORCUADRITO
line_bundles: Mapped[Optional[int]] = mapped_column(
Integer) # CANTBULTOS (de la linea)
# Relationship
header: Mapped["InvoiceHeader"] = relationship(back_populates="details")
@@ -155,15 +216,19 @@ class InvoiceCollections(Base, TenantScopedMixin, TimestampMixin):
__tablename__ = "invoice_collections"
__tableargs__ = {'schema': 'a76'}
collection_id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
collection_id: Mapped[int] = mapped_column(
BigInteger, primary_key=True, autoincrement=True)
invoice_id: Mapped[int] = mapped_column(ForeignKey("invoice_header.id"))
concept: Mapped[Optional[str]] = mapped_column(String(100)) # CONCEPTO
is_collected: Mapped[Optional[int]] = mapped_column(Integer) # COBRADO
collection_date: Mapped[Optional[datetime]] = mapped_column(Date) # FECHACOBRANZA
amount: Mapped[Optional[float]] = mapped_column(Numeric(23, 8)) # VALOR
collector_user: Mapped[Optional[str]] = mapped_column(String(20)) # FACTCOBRADOR
concept: Mapped[Optional[str]] = mapped_column(String(100)) # CONCEPTO
is_collected: Mapped[Optional[int]] = mapped_column(Integer) # COBRADO
collection_date: Mapped[Optional[datetime]
] = mapped_column(Date) # FECHACOBRANZA
amount: Mapped[Optional[float]] = mapped_column(Numeric(23, 8)) # VALOR
collector_user: Mapped[Optional[str]] = mapped_column(
String(20)) # FACTCOBRADOR
# Relationship
header: Mapped["InvoiceHeader"] = relationship(back_populates="collections")
header: Mapped["InvoiceHeader"] = relationship(
back_populates="collections")

View File

@@ -2,38 +2,27 @@ from typing import Optional, List
from datetime import datetime, date
from decimal import Decimal
from pydantic import BaseModel, Field
from .models import OperationType
# --- Base Schemas ---
class InvoiceHeaderBase(BaseModel):
"""Base fields for Invoice Header"""
legacy_id: Optional[int] = Field(
None, description="Legacy consecutive ID (CONSECUTIVO)")
operation_type: Optional[str] = Field(
None, max_length=20, description="Operation type: IMP/EXP/SM")
invoice_number: Optional[str] = Field(
None, max_length=20, description="Invoice number")
project_number: Optional[str] = Field(
None, max_length=14, description="Project number")
purchase_order: Optional[str] = Field(
None, max_length=50, description="Purchase order")
related_doc_id: Optional[int] = Field(
None, description="Related document ID for rectifications")
operation_type: Optional[OperationType] = Field(None, max_length=20, description="Operation type: imp/exp")
invoice_type: Optional[str] = Field(None, max_length=5, description="Invoice type key")
invoice_number: Optional[str] = Field(None, max_length=20, description="Invoice number")
project_number: Optional[str] = Field(None, max_length=14, description="Project number")
purchase_order: Optional[str] = Field(None, max_length=50, description="Purchase order")
related_doc_id: Optional[int] = Field(None, description="Related document ID for rectifications")
invoice_date: Optional[date] = Field(None, description="Invoice date")
status: Optional[str] = Field(None, max_length=5, description="Status")
traffic_light_status: Optional[str] = Field(
None, max_length=50, description="Traffic light status (SEMAFORO)")
process_log: Optional[str] = Field(
None, max_length=300, description="Processing log")
comments: Optional[str] = Field(
None, description="Comments and observations")
cfdi_uuid: Optional[str] = Field(
None, max_length=100, description="CFDI UUID")
path_pdf: Optional[str] = Field(
None, max_length=500, description="Path to PDF file")
path_xml: Optional[str] = Field(
None, max_length=500, description="Path to XML file")
traffic_light_status: Optional[str] = Field(None, max_length=50, description="Traffic light status (SEMAFORO)")
process_log: Optional[str] = Field(None, max_length=300, description="Processing log")
comments: Optional[str] = Field(None, description="Comments and observations")
cfdi_uuid: Optional[str] = Field(None, max_length=100, description="CFDI UUID")
path_pdf: Optional[str] = Field(None, max_length=500, description="Path to PDF file")
path_xml: Optional[str] = Field(None, max_length=500, description="Path to XML file")
class InvoiceComplianceMxBase(BaseModel):

View File

@@ -10,15 +10,11 @@ class InvoiceType(Base):
{"schema": "public", "extend_existing": True}, # opcional
)
key: Mapped[str] = mapped_column(
String(5), nullable=False
) # clave del tipo de factura
description: Mapped[str] = mapped_column(
String(50), nullable=False
) # descripción oficial (en español)
# observación o comentario adicional
note: Mapped[str] = mapped_column(String(500))
type: Mapped[str] = mapped_column(String(15)) # tipo
key: Mapped[str] = mapped_column(String(5), nullable=False) # clave del tipo de factura
description: Mapped[str] = mapped_column(String(50), nullable=False) # descripción oficial (en español)
note: Mapped[str] = mapped_column(String(500))# observación o comentario adicional
type: Mapped[str] = mapped_column(String(15))# tipo (MATERIAL, fixed asset, both)
operation: Mapped[str] = mapped_column(String(5)) # operación (imp, exp, both)
def __repr__(self):
return f"<InvoiceType(key={self.key}, description={self.description}, origin_type={self.origin_type})>"
return f"<InvoiceType(key={self.key}, description={self.description}, type={self.type}, operation={self.operation})>"

View File

@@ -1,38 +1,76 @@
seed = [
("DONAC", "DONACION", "", "AMBOS"),
("EXDEF", "EXPORTACION DEFINITIVA", "", "MATERIAL"),
# === TIPOS DE IMPORTACION ===
(
"TEMP",
"IMPORTACION TEMPORAL",
"IMPORTACION TEMPORAL DE MATERIA PRIMA, COMPONENTES O MATERIALES PARA SER PROCESADOS Y POSTERIORMENTE EXPORTADOS.",
"material",
"imp",
),
(
"DEF",
"IMPORTACION DEFINITIVA",
"IMPORTACION DEFINITIVA PARA NACIONALIZACION DE MERCANCIA QUE PERMANECE EN TERRITORIO NACIONAL.",
"material",
"imp",
),
(
"MEX",
"COMPRAS MEXICANAS",
"IMPORTACION DE MERCANCIA NACIONAL ADQUIRIDA DE PROVEEDORES MEXICANOS PARA INCORPORAR A PROCESO PRODUCTIVO.",
"material",
"imp",
),
(
"CR",
"CAMBIO DE REGIMEN",
"IMPORTACION POR CAMBIO DE REGIMEN DE MERCANCIA TEMPORAL QUE SE NACIONALIZA O RETORNA.",
"material",
"imp",
),
# === TIPOS DE EXPORTACION ===
("DONAC", "DONACION", "", "both", "exp"),
("EXDEF", "EXPORTACION DEFINITIVA", "", "material", "exp"),
(
"MATDE",
"MATERIA PRIMA O MATERIAL DEVUELTO",
"ESTE PROCESO CONSISTE EN SOLO DESCARGAR LAS PARTES DADAS DE ALTA EN MATERIALES QUE SON RETORNADAS SIN NINGUNA MODIFICACION (A1)",
"MATERIAL",
"material",
"exp",
),
(
"NODES",
"NO HACE DESCARGA",
"ESTE PROCESO DE ACTUALIZACION CONSISTE EN EXPORTAR UNA MERCANCIA Y NO DESCARGAR, POR LO TANTO NO EXISTE REPORTE DE DESCARGAS Y NO AFECTA SALDOS.",
"AMBOS",
"both",
"exp",
),
(
"PTERM",
"PRODUCTO TERMINADO Y VIRTUALES",
"EL PRODUCTO TERMINADO Y VIRTUALES DESCARGARAN: 1) APARTIR DE LOS COMPONENTES DE CADA PRODUCTO TERMINADO REGISTRADO EN LAS PARTIDAS DE EXPORTACION. 2) POR PARTE, CON LAS OPCIONES DE PODER DESCARGAR POR SUSTITUTO Y POR CLASE EN CASO DE INSUFICIENCIAS DEL COMPONENTE.",
"MATERIAL",
"material",
"exp",
),
(
"REPAR",
"REPARACION",
"PROCESO QUE CONSISTE EN DOS ETAPAS: 1) DESCARGA EL PRODUCTO DE REPARACION QUE SE IMPORTO PARA REPARA, 2) DESCARGA EL LISTADO DE COMPONENTES QUE SE AGREGO AL PRODUCTO DE REPARACION",
"MATERIAL",
"material",
"exp",
),
("SCRAP", "SCRAP", "", "AMBOS"),
("SCRAP", "SCRAP", "", "both", "exp"),
(
"VEMEX",
"VENTAS EN MEXICO",
"ESTE PROCESO CONSISTE EN LA VENTA EN EL MERCADO NACIONAL DE LOS PRODUCTOS.",
"AMBOS",
"both",
"exp",
),
("VIRTU", "VIRTUALES", "", "MATERIAL"),
("AFIJO", "ACTIVO FIJO", "", "ACTIVO FIJO"),
("REEXP", "REEXPEDICION", "", "ACTIVO FIJO"),
("VIRTU", "VIRTUALES", "", "material", "exp"),
# === ACTIVOS FIJOS (AMBAS OPERACIONES) ===
("AFIJO", "ACTIVO FIJO", "", "fixed asset", "both"),
("REEXP", "REEXPEDICION", "", "fixed asset", "both"),
]