diff --git a/backend/alembic/versions/add_timestamps_to_classes.py b/backend/alembic/versions/add_timestamps_to_classes.py
deleted file mode 100644
index a2b4f554..00000000
--- a/backend/alembic/versions/add_timestamps_to_classes.py
+++ /dev/null
@@ -1,67 +0,0 @@
-"""Add timestamp fields to classes table
-
-Revision ID: add_timestamps_classes
-Revises: 7937209f9718
-Create Date: 2025-11-16 00:20:00.000000
-
-"""
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision: str = 'add_timestamps_classes'
-down_revision: Union[str, None] = '7937209f9718'
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
- # Add created_at column with default value
- op.execute("""
- ALTER TABLE a76.classes
- ADD COLUMN created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
- """)
-
- # Add updated_at column with default value
- op.execute("""
- ALTER TABLE a76.classes
- ADD COLUMN updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL
- """)
-
- # Add deleted_at column (nullable for soft deletes)
- op.execute("""
- ALTER TABLE a76.classes
- ADD COLUMN deleted_at TIMESTAMP WITH TIME ZONE
- """)
-
- # Create trigger to auto-update updated_at
- op.execute("""
- CREATE OR REPLACE FUNCTION a76.update_classes_updated_at()
- RETURNS TRIGGER AS $$
- BEGIN
- NEW.updated_at = CURRENT_TIMESTAMP;
- RETURN NEW;
- END;
- $$ language 'plpgsql';
- """)
-
- op.execute("""
- CREATE TRIGGER update_classes_updated_at
- BEFORE UPDATE ON a76.classes
- FOR EACH ROW
- EXECUTE FUNCTION a76.update_classes_updated_at();
- """)
-
-
-def downgrade() -> None:
- # Drop trigger and function
- op.execute("DROP TRIGGER IF EXISTS update_classes_updated_at ON a76.classes")
- op.execute("DROP FUNCTION IF EXISTS a76.update_classes_updated_at()")
-
- # Drop columns
- op.execute("ALTER TABLE a76.classes DROP COLUMN IF EXISTS deleted_at")
- op.execute("ALTER TABLE a76.classes DROP COLUMN IF EXISTS updated_at")
- op.execute("ALTER TABLE a76.classes DROP COLUMN IF EXISTS created_at")
diff --git a/backend/api/v1/modules/a76/clients_and_providers/dto.py b/backend/api/v1/modules/a76/clients_and_providers/dto.py
index 10fa8858..f77df843 100644
--- a/backend/api/v1/modules/a76/clients_and_providers/dto.py
+++ b/backend/api/v1/modules/a76/clients_and_providers/dto.py
@@ -4,7 +4,7 @@ Reemplaza schemas.py siguiendo enfoque DDD y estilo NestJS
"""
from decimal import Decimal
-from typing import Literal, Optional
+from typing import List, Literal, Optional
from pydantic import BaseModel, Field
@@ -119,7 +119,7 @@ class ClientProviderCreateDTO(BaseModel):
is_national_provider: Optional[str] = Field(
None, max_length=2, description="Is national provider"
)
- enabled_disabled: Optional[int] = Field(None, description="Enabled/Disabled status")
+ is_active: Optional[bool] = Field(None, description="Enabled/Disabled status")
# Nested DTOs
address: Optional[ClientProviderAddressDTO] = Field(
@@ -162,7 +162,7 @@ class ClientProviderUpdateDTO(BaseModel):
is_national_provider: Optional[str] = Field(
None, max_length=2, description="Is national provider"
)
- enabled_disabled: Optional[int] = Field(None, description="Enabled/Disabled status")
+ is_active: Optional[bool] = Field(None, description="Enabled/Disabled status")
# Nested DTOs
address: Optional[ClientProviderAddressDTO] = Field(
@@ -194,7 +194,7 @@ class ClientProviderResponseDTO(BaseModel):
position: Optional[str] = None
incoterm: Optional[str] = None
is_national_provider: Optional[str] = None
- enabled_disabled: Optional[int] = None
+ is_active: Optional[bool] = None
tenant_id: int
company_id: int
@@ -215,7 +215,7 @@ class ClientProviderBasicDTO(BaseModel):
short_name: Optional[str] = None
rfc: Optional[str] = None
client_or_provider: Optional[str] = None
- enabled_disabled: Optional[int] = None
+ is_active: Optional[bool] = None
class Config:
from_attributes = True
@@ -231,3 +231,15 @@ class ClientProviderListDTO(BaseModel):
class Config:
from_attributes = True
+
+
+class ClientProviderPaginatedResponseDTO(BaseModel):
+ """DTO para respuesta paginada de clientes/proveedores"""
+
+ items: List[ClientProviderResponseDTO]
+ total: int
+ page: int
+ page_size: int
+
+ class Config:
+ from_attributes = True
diff --git a/backend/api/v1/modules/a76/clients_and_providers/models.py b/backend/api/v1/modules/a76/clients_and_providers/models.py
index da2a02eb..ea9a7f7d 100644
--- a/backend/api/v1/modules/a76/clients_and_providers/models.py
+++ b/backend/api/v1/modules/a76/clients_and_providers/models.py
@@ -15,7 +15,8 @@ from sqlalchemy import (
PrimaryKeyConstraint,
SmallInteger,
String,
- Enum as PgEnum
+ Enum as PgEnum,
+ Boolean
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from enum import Enum
@@ -60,8 +61,8 @@ class ClientProvider(Base, TenantScopedMixin):
responsible: Mapped[Optional[str]] = mapped_column(String(80))
position: Mapped[Optional[str]] = mapped_column(String(30))
incoterm: Mapped[Optional[str]] = mapped_column(String(19))
- is_national_provider: Mapped[Optional[str]] = mapped_column(String(2))
- enabled_disabled: Mapped[Optional[int]] = mapped_column(SmallInteger)
+ is_national_provider: Mapped[Optional[bool]] = mapped_column(Boolean)
+ is_active: Mapped[Optional[bool]] = mapped_column(Boolean)
# Relationships
address: Mapped[Optional["ClientProviderAddress"]] = relationship(
diff --git a/backend/api/v1/modules/a76/clients_and_providers/routes.py b/backend/api/v1/modules/a76/clients_and_providers/routes.py
index 68e74d13..970b71ad 100644
--- a/backend/api/v1/modules/a76/clients_and_providers/routes.py
+++ b/backend/api/v1/modules/a76/clients_and_providers/routes.py
@@ -9,136 +9,57 @@ from core.security import get_current_user, validate_access_to_resource
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from api.v1.common.tenant_crud_routes import TenantCRUDRoutes
+from .models import ClientOrProviderEnum
from .dto import (
ClientProviderBasicDTO,
ClientProviderCreateDTO,
ClientProviderResponseDTO,
ClientProviderUpdateDTO,
+ ClientProviderPaginatedResponseDTO,
)
from .service import ClientProviderService
from .models import ClientProvider
-# Create base CRUD router using TenantCRUDRoutes factory
-base_router = TenantCRUDRoutes(
- service=ClientProviderService,
- create_schema=ClientProviderCreateDTO,
- update_schema=ClientProviderUpdateDTO,
- response_schema=ClientProviderResponseDTO,
- prefix="",
- tags=[],
- resource_name="Client/Provider",
- id_name="id", # Using numeric ID
- enable_list=True, # Enable GET /clients-providers with pagination
- enable_filters=True, # Enable filtering
- default_page_size=50,
- max_page_size=100,
-).router
-
# Create main router to add custom endpoints
router = APIRouter(prefix="/clients-providers")
-# Include base CRUD routes
-router.include_router(base_router, prefix="")
-
-# Custom endpoints
-@router.get("/clients", response_model=List[ClientProviderBasicDTO])
-async def get_clients_only(
+@router.get("/", response_model=ClientProviderPaginatedResponseDTO)
+async def get_clients_and_providers(
company_id: int = Query(..., description="Company ID"),
+ type: Optional[ClientOrProviderEnum] = Query(
+ None, description="Type of entity (client or provider)"
+ ),
+ active: Optional[bool] = Query(None, description="Active status"),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000),
db: Session = Depends(get_core_db),
current_user: dict = Depends(get_current_user),
):
- """Get only clients (client_or_provider = 'client')"""
+ """Get clients and providers"""
tenant_id = validate_access_to_resource(db, company_id, current_user)
-
- clients = (
- db.query(ClientProvider)
- .filter(
- ClientProvider.tenant_id == tenant_id,
- ClientProvider.company_id == company_id,
- ClientProvider.client_or_provider == "client"
- )
- .offset(skip)
- .limit(limit)
- .all()
+
+ query = db.query(ClientProvider).filter(
+ ClientProvider.tenant_id == tenant_id,
+ ClientProvider.company_id == company_id,
)
- return [ClientProviderBasicDTO.model_validate(c) for c in clients]
+ if type is not None:
+ query = query.filter(ClientProvider.client_or_provider == type)
-@router.get("/providers", response_model=List[ClientProviderBasicDTO])
-async def get_providers_only(
- company_id: int = Query(..., description="Company ID"),
- skip: int = Query(0, ge=0),
- limit: int = Query(100, ge=1, le=1000),
- db: Session = Depends(get_core_db),
- current_user: dict = Depends(get_current_user),
-):
- """Get only providers (client_or_provider = 'provider')"""
- tenant_id = validate_access_to_resource(db, company_id, current_user)
-
- providers = (
- db.query(ClientProvider)
- .filter(
- ClientProvider.tenant_id == tenant_id,
- ClientProvider.company_id == company_id,
- ClientProvider.client_or_provider == "provider"
- )
- .offset(skip)
- .limit(limit)
- .all()
- )
- return [ClientProviderBasicDTO.model_validate(p) for p in providers]
+ if active is not None:
+ query = query.filter(ClientProvider.is_active == active)
+ total = query.count()
+ clients = query.offset(skip).limit(limit).all()
-@router.get("/search/rfc/{rfc}", response_model=List[ClientProviderBasicDTO])
-async def search_by_rfc(
- rfc: str,
- company_id: int = Query(..., description="Company ID"),
- db: Session = Depends(get_core_db),
- current_user: dict = Depends(get_current_user),
-):
- """Search clients/providers by RFC"""
- tenant_id = validate_access_to_resource(db, company_id, current_user)
-
- clients = (
- db.query(ClientProvider)
- .filter(
- ClientProvider.tenant_id == tenant_id,
- ClientProvider.company_id == company_id,
- ClientProvider.rfc.ilike(f"%{rfc}%")
- )
- .all()
- )
- return [ClientProviderBasicDTO.model_validate(c) for c in clients]
-
-
-@router.patch("/{client_id}/toggle-status", response_model=ClientProviderResponseDTO)
-async def toggle_clients_and_providers_status(
- client_id: int,
- company_id: int = Query(..., description="Company ID"),
- db: Session = Depends(get_core_db),
- current_user: dict = Depends(get_current_user),
-):
- """Toggle client/provider enabled/disabled status"""
- tenant_id = validate_access_to_resource(db, company_id, current_user)
-
- client = ClientProviderService.get_by_id(db, client_id, tenant_id, company_id)
- if not client:
- raise HTTPException(status_code=404, detail="Client/Provider not found")
-
- # Toggle status (1 = enabled, 0 = disabled)
- client.enabled_disabled = 1 if client.enabled_disabled == 0 else 0
-
- try:
- db.commit()
- db.refresh(client)
- return client
- except Exception as e:
- db.rollback()
- raise HTTPException(status_code=500, detail="Error updating status")
+ return {
+ "items": [ClientProviderResponseDTO.model_validate(c) for c in clients],
+ "total": total,
+ "page": (skip // limit) + 1,
+ "page_size": limit,
+ }
@router.get("/{client_id}/basic", response_model=ClientProviderBasicDTO)
@@ -150,9 +71,59 @@ async def get_clients_and_providers_basic_info(
):
"""Get basic information for a client/provider (without address and programs)"""
tenant_id = validate_access_to_resource(db, company_id, current_user)
-
+
client = ClientProviderService.get_by_id(db, client_id, tenant_id, company_id)
if not client:
raise HTTPException(status_code=404, detail="Client/Provider not found")
-
+
return ClientProviderBasicDTO.model_validate(client)
+
+
+@router.post("/", response_model=ClientProviderResponseDTO)
+async def create_client_provider(
+ client_data: ClientProviderCreateDTO,
+ company_id: int = Query(..., description="Company ID"),
+ db: Session = Depends(get_core_db),
+ current_user: dict = Depends(get_current_user),
+):
+ """Create a new client/provider"""
+ tenant_id = validate_access_to_resource(db, company_id, current_user)
+
+ return ClientProviderService.create(db, client_data, tenant_id, company_id)
+
+
+@router.patch("/{client_id}", response_model=ClientProviderResponseDTO)
+async def update_client_provider(
+ client_id: int,
+ client_data: ClientProviderUpdateDTO,
+ company_id: int = Query(..., description="Company ID"),
+ db: Session = Depends(get_core_db),
+ current_user: dict = Depends(get_current_user),
+):
+ """Update a client/provider"""
+ tenant_id = validate_access_to_resource(db, company_id, current_user)
+
+ client = ClientProviderService.update(
+ db, client_id, tenant_id, company_id, client_data
+ )
+ if not client:
+ raise HTTPException(status_code=404, detail="Client/Provider not found")
+
+ return client
+
+
+@router.delete("/{client_id}", response_model=bool)
+async def delete_client_provider(
+ client_id: int,
+ company_id: int = Query(..., description="Company ID"),
+ db: Session = Depends(get_core_db),
+ current_user: dict = Depends(get_current_user),
+):
+ """Delete a client/provider"""
+ tenant_id = validate_access_to_resource(db, company_id, current_user)
+
+ success = ClientProviderService.delete(db, client_id, tenant_id, company_id)
+ if not success:
+ raise HTTPException(status_code=404, detail="Client/Provider not found")
+
+ return success
diff --git a/backend/api/v1/modules/a76/clients_and_providers/service.py b/backend/api/v1/modules/a76/clients_and_providers/service.py
index c9bc22e3..5a329673 100644
--- a/backend/api/v1/modules/a76/clients_and_providers/service.py
+++ b/backend/api/v1/modules/a76/clients_and_providers/service.py
@@ -61,13 +61,17 @@ class ClientProviderService:
)
if filters.get("status"):
enabled = 1 if filters["status"] == "enabled" else 0
- query = query.filter(ClientProvider.enabled_disabled == enabled)
+ query = query.filter(ClientProvider.is_active == enabled)
total = query.count()
- clients = query.options(
- joinedload(ClientProvider.address),
- joinedload(ClientProvider.programs)
- ).offset(skip).limit(limit).all()
+ clients = (
+ query.options(
+ joinedload(ClientProvider.address), joinedload(ClientProvider.programs)
+ )
+ .offset(skip)
+ .limit(limit)
+ .all()
+ )
return clients, total
@@ -79,8 +83,7 @@ class ClientProviderService:
return (
db.query(ClientProvider)
.options(
- joinedload(ClientProvider.address),
- joinedload(ClientProvider.programs)
+ joinedload(ClientProvider.address), joinedload(ClientProvider.programs)
)
.filter(
ClientProvider.id == client_id,
@@ -102,9 +105,7 @@ class ClientProviderService:
# Create main client/provider
data_dict = client_data.model_dump(exclude={"address", "programs"})
db_client = ClientProvider(
- **data_dict,
- tenant_id=tenant_id,
- company_id=company_id
+ **data_dict, tenant_id=tenant_id, company_id=company_id
)
db.add(db_client)
@@ -112,8 +113,8 @@ class ClientProviderService:
# Create address if provided
if client_data.address:
- db_address = ClientProviderAddress(
- tenant_id=tenant_id,
+ db_address = ClientProviderAddress(
+ tenant_id=tenant_id,
company_id=company_id,
client_id=db_client.id,
**client_data.address.model_dump(exclude_unset=True),
@@ -122,7 +123,7 @@ class ClientProviderService:
# Create programs if provided
if client_data.programs:
- db_programs = ClientProviderPrograms(
+ db_programs = ClientProviderPrograms(
tenant_id=tenant_id,
company_id=company_id,
client_id=db_client.id,
@@ -210,9 +211,7 @@ class ClientProviderService:
)
@staticmethod
- def delete(
- db: Session, client_id: int, tenant_id: int, company_id: int
- ) -> bool:
+ def delete(db: Session, client_id: int, tenant_id: int, company_id: int) -> bool:
"""Delete a client/provider"""
client = ClientProviderService.get_by_id(db, client_id, tenant_id, company_id)
if not client:
@@ -351,7 +350,7 @@ class ClientProviderService:
)
if enabled_only:
- query = query.filter(ClientProvider.enabled_disabled == 1)
+ query = query.filter(ClientProvider.is_active == 1)
# Contar total
total = query.count()
@@ -478,59 +477,4 @@ class ClientProviderService:
logger.error(f"Error deleting client/provider {client_id}: {str(e)}")
raise HTTPException(
status_code=500, detail="Error deleting client/provider"
- )
-
- def get_clients_only(
- self, skip: int = 0, limit: int = 100
- ) -> List[ClientProviderBasicDTO]:
- """Obtiene solo clientes (client)"""
- query = self.db.query(ClientProvider).filter(
- ClientProvider.client_or_provider == "client"
- )
- clients = query.offset(skip).limit(limit).all()
- return [ClientProviderBasicDTO.model_validate(client) for client in clients]
-
- def get_providers_only(
- self, skip: int = 0, limit: int = 100
- ) -> List[ClientProviderBasicDTO]:
- """Obtiene solo proveedores (provider)"""
- query = self.db.query(ClientProvider).filter(
- ClientProvider.client_or_provider == "provider"
- )
- providers = query.offset(skip).limit(limit).all()
- return [
- ClientProviderBasicDTO.model_validate(provider) for provider in providers
- ]
-
- def search_by_rfc(self, rfc: str) -> List[ClientProviderBasicDTO]:
- """Busca clientes/proveedores por RFC"""
- clients = (
- self.db.query(ClientProvider)
- .filter(ClientProvider.rfc.ilike(f"%{rfc}%"))
- .all()
- )
- return [ClientProviderBasicDTO.model_validate(client) for client in clients]
-
- def toggle_status(self, client_id: str) -> Optional[ClientProviderResponseDTO]:
- """Cambia el estado habilitado/deshabilitado"""
- client = (
- self.db.query(ClientProvider)
- .filter(ClientProvider.client_id == client_id)
- .first()
- )
- if not client:
- return None
-
- # Toggle status (1 = habilitado, 0 = deshabilitado)
- client.enabled_disabled = 1 if client.enabled_disabled == 0 else 0
-
- try:
- self.db.commit()
- logger.info(
- f"Client/Provider status toggled: {client_id} -> {client.enabled_disabled}"
- )
- return self._get_client_with_relations(client_id)
- except Exception as e:
- self.db.rollback()
- logger.error(f"Error toggling status for {client_id}: {str(e)}")
- raise HTTPException(status_code=500, detail="Error updating status")
+ )
\ No newline at end of file
diff --git a/backend/api/v1/modules/a76/parts/dto.py b/backend/api/v1/modules/a76/parts/dto.py
index 1414fd82..e21e7772 100644
--- a/backend/api/v1/modules/a76/parts/dto.py
+++ b/backend/api/v1/modules/a76/parts/dto.py
@@ -67,7 +67,7 @@ class PartCreateDTO(BaseModel):
added_value: Optional[Decimal] = Field(None, description="Added value")
# Status and media
- enabled_disabled: Optional[int] = Field(None, description="Enabled/Disabled status")
+ is_active: Optional[bool] = Field(None, description="Enabled/Disabled status")
creation_date: Optional[int] = Field(None, description="Creation date")
part_photo: Optional[str] = Field(
None, max_length=255, description="Part photo URL"
@@ -132,7 +132,7 @@ class PartUpdateDTO(BaseModel):
added_value: Optional[Decimal] = Field(None, description="Added value")
# Status and media
- enabled_disabled: Optional[int] = Field(None, description="Enabled/Disabled status")
+ is_active: Optional[bool] = Field(None, description="Enabled/Disabled status")
part_photo: Optional[str] = Field(
None, max_length=255, description="Part photo URL"
)
@@ -178,7 +178,7 @@ class PartResponseDTO(BaseModel):
added_value: Optional[Decimal] = None
# Status and dates
- enabled_disabled: Optional[int] = None
+ is_active: Optional[bool] = None
creation_date: Optional[int] = None
modification_date: Optional[int] = None
modification_date_iso: Optional[datetime] = None
@@ -200,7 +200,7 @@ class PartBasicDTO(BaseModel):
part_class: Optional[str] = None
unit_cost: Optional[Decimal] = None
currency_key: Optional[str] = None
- enabled_disabled: Optional[int] = None
+ is_active: Optional[bool] = None
class Config:
from_attributes = True
diff --git a/backend/api/v1/modules/a76/parts/models.py b/backend/api/v1/modules/a76/parts/models.py
index ef8b325b..b961c272 100644
--- a/backend/api/v1/modules/a76/parts/models.py
+++ b/backend/api/v1/modules/a76/parts/models.py
@@ -16,6 +16,7 @@ from sqlalchemy import (
SmallInteger,
String,
UniqueConstraint,
+ Boolean,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
@@ -90,7 +91,7 @@ class Part(Base, TenantScopedMixin):
added_value: Mapped[Optional[Decimal]] = mapped_column(Numeric(23, 8))
# Status and dates
- enabled_disabled: Mapped[Optional[int]] = mapped_column(SmallInteger)
+ is_active: Mapped[Optional[bool]] = mapped_column(Boolean)
creation_date: Mapped[Optional[int]] = mapped_column() # FECHACREACIONPARTE
modification_date: Mapped[Optional[int]] = mapped_column() # FECHAMODIFICA
modification_date_iso: Mapped[Optional[datetime]] = (
diff --git a/backend/api/v1/modules/a76/parts/routes.py b/backend/api/v1/modules/a76/parts/routes.py
index e271cb12..0f5996b6 100644
--- a/backend/api/v1/modules/a76/parts/routes.py
+++ b/backend/api/v1/modules/a76/parts/routes.py
@@ -348,7 +348,7 @@ async def get_part_basic_info(
part_class=part.part_class,
unit_cost=part.unit_cost,
currency_key=part.currency_key,
- enabled_disabled=part.enabled_disabled,
+ is_active=part.is_active,
)
diff --git a/backend/api/v1/modules/a76/parts/service.py b/backend/api/v1/modules/a76/parts/service.py
index d8ba3d06..48c2eab9 100644
--- a/backend/api/v1/modules/a76/parts/service.py
+++ b/backend/api/v1/modules/a76/parts/service.py
@@ -221,7 +221,7 @@ class PartService:
return None
# Toggle status (assuming 1 = enabled, 0 = disabled)
- db_part.enabled_disabled = 1 if db_part.enabled_disabled == 0 else 0
+ db_part.is_active = 1 if db_part.is_active == 0 else 0
db.commit()
db.refresh(db_part)
@@ -257,8 +257,8 @@ class PartService:
)
# Partes habilitadas vs deshabilitadas
- enabled_parts = db.query(Part).filter(Part.enabled_disabled == 1).count()
- disabled_parts = db.query(Part).filter(Part.enabled_disabled == 0).count()
+ enabled_parts = db.query(Part).filter(Part.is_active == 1).count()
+ disabled_parts = db.query(Part).filter(Part.is_active == 0).count()
return {
"total_parts": total_parts,
diff --git a/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/routes.py b/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/routes.py
index 93d2ed7c..76533e83 100644
--- a/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/routes.py
+++ b/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/routes.py
@@ -16,15 +16,21 @@ def list_code_pedimento_regimens(
page: int = Query(1, ge=1, description="Número de página"),
page_size: int = Query(50, ge=1, le=100, description="Tamaño de página"),
code: str = Query(None, description="Filter by code"),
+ regime: str = Query(None, description="Filter by regime"),
+ type: str = Query(None, description="Filter by type"),
db: Session = Depends(get_core_db),
current_user: dict = Depends(get_current_user),
):
skip = (page - 1) * page_size
query = db.query(CodePedimentoRegimen)
-
+
if code is not None:
query = query.filter(CodePedimentoRegimen.pedimento_code == code)
-
+ if regime is not None:
+ query = query.filter(CodePedimentoRegimen.regime == regime)
+ if type is not None:
+ query = query.filter(CodePedimentoRegimen.type == type)
+
items = query.offset(skip).limit(page_size).all()
total = query.count()
return {
diff --git a/frontend/src/lib/api/dashboard/a76/clients-providers.ts b/frontend/src/lib/api/dashboard/a76/clients-providers.ts
index 40faa07d..773de3b0 100644
--- a/frontend/src/lib/api/dashboard/a76/clients-providers.ts
+++ b/frontend/src/lib/api/dashboard/a76/clients-providers.ts
@@ -31,8 +31,8 @@ export interface ClientProvider {
domicile_fiscal?: string | null;
foreign_tax_id?: string | null;
client_or_provider?: string | null;
- enabled_disabled?: number;
- tenant_id: number;
+ is_active?: boolean;
+ tenant_id: number;
address?: ClientProviderAddress | null;
programs?: ClientProviderPrograms | null;
}
@@ -46,7 +46,7 @@ export interface ClientProviderBasic {
domicile_fiscal?: string | null;
foreign_tax_id?: string | null;
client_or_provider?: string | null;
- enabled_disabled?: number;
+ is_active?: boolean;
tenant_id: number;
}
@@ -65,7 +65,7 @@ export interface CreateClientProviderData {
domicile_fiscal?: string | null;
foreign_tax_id?: string | null;
client_or_provider?: string | null;
- enabled_disabled?: number;
+ is_active?: boolean;
address?: Omit | null;
programs?: Omit | null;
}
@@ -78,7 +78,7 @@ export interface UpdateClientProviderData {
domicile_fiscal?: string | null;
foreign_tax_id?: string | null;
client_or_provider?: string | null;
- enabled_disabled?: number;
+ is_active?: boolean;
address?: Partial | null;
programs?: Partial | null;
}
@@ -100,7 +100,7 @@ export const clientsProvidersApi = {
page: page.toString(),
page_size: pageSize.toString()
});
-
+
if (filters) {
Object.entries(filters).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
@@ -108,7 +108,7 @@ export const clientsProvidersApi = {
}
});
}
-
+
return api.get(
`/v1/a76/clients-providers?${params.toString()}`
);
@@ -166,7 +166,7 @@ export const clientsProvidersApi = {
/**
* Crea un nuevo cliente/proveedor
- * @param companyId - ID de la compañía
+ * @param companyId - ID de la compañía
* @param data - Datos del cliente/proveedor a crear
*/
create: (companyId: number, data: CreateClientProviderData) =>
diff --git a/frontend/src/lib/api/dashboard/a76/customs-brokers.ts b/frontend/src/lib/api/dashboard/a76/customs-brokers.ts
index d6a15c7c..17a82200 100644
--- a/frontend/src/lib/api/dashboard/a76/customs-brokers.ts
+++ b/frontend/src/lib/api/dashboard/a76/customs-brokers.ts
@@ -19,7 +19,7 @@ export interface CustomsBroker {
tax_id?: string | null;
personal_id?: string | null;
position?: string | null;
- license?: string | null;
+ license: string;
company?: string | null;
contact?: string | null;
tenant_id: string;
@@ -117,6 +117,14 @@ export const customsBrokersApi = {
return api.delete(`/v1/a76/customs-brokers/${brokerKey}?company_id=${companyId}`);
},
+ /**
+ * Actualiza la información de un agente aduanal
+ */
+ update: (brokerKey: string, data: CreateCustomsBrokerData) => {
+ const companyId = data.company_id;
+ return api.put(`/v1/a76/customs-brokers/${brokerKey}?company_id=${companyId}`, data);
+ },
+
/**
* Actualiza la información de VU de un agente aduanal
*/
diff --git a/frontend/src/lib/api/dashboard/a76/pedimento-dates.ts b/frontend/src/lib/api/dashboard/a76/pedimento-dates.ts
index 7e99ef9e..1cbe8ef4 100644
--- a/frontend/src/lib/api/dashboard/a76/pedimento-dates.ts
+++ b/frontend/src/lib/api/dashboard/a76/pedimento-dates.ts
@@ -17,8 +17,6 @@ export interface PedimentoDates {
original_date?: string | null;
start_date?: string | null;
end_date?: string | null;
- capture_date?: string | null;
- capture_time?: string | null;
created_at: string;
}
@@ -33,8 +31,6 @@ export interface CreatePedimentoDatesData {
original_date?: string | null;
start_date?: string | null;
end_date?: string | null;
- capture_date?: string | null;
- capture_time?: string | null;
}
export interface UpdatePedimentoDatesData {
@@ -48,8 +44,6 @@ export interface UpdatePedimentoDatesData {
original_date?: string | null;
start_date?: string | null;
end_date?: string | null;
- capture_date?: string | null;
- capture_time?: string | null;
}
export const pedimentoDatesApi = {
diff --git a/frontend/src/lib/api/dashboard/a76/pedimentos.ts b/frontend/src/lib/api/dashboard/a76/pedimentos.ts
index 339ada55..3e93e440 100644
--- a/frontend/src/lib/api/dashboard/a76/pedimentos.ts
+++ b/frontend/src/lib/api/dashboard/a76/pedimentos.ts
@@ -15,9 +15,7 @@ export interface PedimentoDates {
eucan_date?: string | null;
original_date?: string | null;
start_date?: string | null;
- end_date?: string | null;
- capture_date?: string | null;
- capture_time?: string | null;
+ end_date?: string | null;
}
export interface PedimentoPayments {
diff --git a/frontend/src/lib/components/dashboard/classes/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/classes/create-edit-dialog.svelte
index cac2f932..a61219e4 100644
--- a/frontend/src/lib/components/dashboard/classes/create-edit-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/classes/create-edit-dialog.svelte
@@ -9,6 +9,7 @@
import { materialTypesApi, type MaterialType } from "$lib/api/dashboard/refrence_data/material_types";
import { companyStore } from "$lib/stores/company.svelte";
import { onMount } from 'svelte';
+ import { LoaderCircle, Home } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -248,21 +249,7 @@
{#if companyStore.activeCompany}
-
+
{companyStore.activeCompany.name}
@@ -426,26 +413,7 @@
{#if loading}
-
+
{/if}
{isEditing ? "Guardar cambios" : "Crear"}
diff --git a/frontend/src/lib/components/dashboard/clients_and_providers/data-table-actions.svelte b/frontend/src/lib/components/dashboard/clients_and_providers/data-table-actions.svelte
index 982cc4dc..888b9488 100644
--- a/frontend/src/lib/components/dashboard/clients_and_providers/data-table-actions.svelte
+++ b/frontend/src/lib/components/dashboard/clients_and_providers/data-table-actions.svelte
@@ -90,7 +90,7 @@
Ver detalles
Editar
- {isToggling ? 'Cambiando...' : item.enabled_disabled === 1 ? 'Desactivar' : 'Activar'}
+ {isToggling ? 'Cambiando...' : item.is_active === true ? 'Desactivar' : 'Activar'}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/clients_and_providers/delete-dialog.svelte b/frontend/src/lib/components/dashboard/clients_and_providers/delete-dialog.svelte
index 2d0963be..f0b8d48c 100644
--- a/frontend/src/lib/components/dashboard/clients_and_providers/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/clients_and_providers/delete-dialog.svelte
@@ -3,6 +3,7 @@
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { clientsProvidersApi, type ClientProvider } from "$lib/api/dashboard/a76/clients-providers";
import { companyStore } from "$lib/stores/company.svelte";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -97,26 +98,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/clients_and_providers/details-dialog.svelte b/frontend/src/lib/components/dashboard/clients_and_providers/details-dialog.svelte
index 592a85e7..fe478312 100644
--- a/frontend/src/lib/components/dashboard/clients_and_providers/details-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/clients_and_providers/details-dialog.svelte
@@ -85,7 +85,7 @@
Estado
- {#if item.enabled_disabled === 1}
+ {#if item.is_active === true}
Activo
diff --git a/frontend/src/lib/components/dashboard/customs_brokers/data-table-actions.svelte b/frontend/src/lib/components/dashboard/customs_brokers/data-table-actions.svelte
index 5a6f7281..3696cbd7 100644
--- a/frontend/src/lib/components/dashboard/customs_brokers/data-table-actions.svelte
+++ b/frontend/src/lib/components/dashboard/customs_brokers/data-table-actions.svelte
@@ -5,6 +5,7 @@
import type { CustomsBroker } from "./columns.js";
import DetailsDialog from "./details-dialog.svelte";
import DeleteDialog from "./delete-dialog.svelte";
+ import EditDialog from "./edit-dialog.svelte";
let {
broker,
@@ -16,6 +17,7 @@
let showDetailsDialog = $state(false);
let showDeleteDialog = $state(false);
+ let showEditDialog = $state(false);
function handleCopyKey() {
navigator.clipboard.writeText(broker.broker_key);
@@ -31,6 +33,10 @@
showDetailsDialog = true;
}
+ function handleEdit() {
+ showEditDialog = true;
+ }
+
function handleDelete() {
showDeleteDialog = true;
}
@@ -64,6 +70,9 @@
Ver detalles
+
+ Editar
+
Eliminar
@@ -72,4 +81,5 @@
+
diff --git a/frontend/src/lib/components/dashboard/customs_brokers/delete-dialog.svelte b/frontend/src/lib/components/dashboard/customs_brokers/delete-dialog.svelte
index bf2ffa39..0658bd95 100644
--- a/frontend/src/lib/components/dashboard/customs_brokers/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/customs_brokers/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { customsBrokersApi, type CustomsBroker } from "$lib/api/dashboard/a76/customs-brokers";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -92,26 +93,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
Eliminando...
{:else}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/customs_brokers/edit-dialog.svelte b/frontend/src/lib/components/dashboard/customs_brokers/edit-dialog.svelte
new file mode 100644
index 00000000..e5bfeebb
--- /dev/null
+++ b/frontend/src/lib/components/dashboard/customs_brokers/edit-dialog.svelte
@@ -0,0 +1,384 @@
+
+
+
+
+
+ Editar Agente Aduanal
+
+ Modifica los datos del agente aduanal {broker?.broker_key}.
+
+
+
+
+
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte b/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte
index 01f9bba9..1aa00270 100644
--- a/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte
+++ b/frontend/src/lib/components/dashboard/pedimentos/data-table-actions.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu";
import { pedimentosApi, type Pedimento } from "$lib/api/dashboard/a76/pedimentos";
+ import { EllipsisVertical, Pencil, LoaderCircle, Trash2 } from 'lucide-svelte';
let {
item,
@@ -62,21 +63,7 @@
{#snippet child({ props })}
Abrir menú
-
+
{/snippet}
@@ -84,63 +71,15 @@
Acciones
-
+
Editar
{#if loading}
-
+
{:else}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte
index 897a610c..5377d232 100644
--- a/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte
+++ b/frontend/src/lib/components/dashboard/pedimentos/edit/dates-tab-form.svelte
@@ -30,8 +30,6 @@
original_date: datesData.original_date ? datesData.original_date.substring(0, 10) : '',
start_date: datesData.start_date ? datesData.start_date.substring(0, 10) : '',
end_date: datesData.end_date ? datesData.end_date.substring(0, 10) : '',
- capture_date: datesData.capture_date ? datesData.capture_date.substring(0, 10) : '',
- capture_time: datesData.capture_time || ''
};
}
} else {
@@ -48,7 +46,6 @@
original_date: '',
start_date: '',
end_date: '',
- capture_date: '',
capture_time: ''
};
}
@@ -163,27 +160,7 @@
type="date"
bind:value={formData.end_date}
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte
index bc488ea7..6c7e5ffc 100644
--- a/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte
+++ b/frontend/src/lib/components/dashboard/pedimentos/edit/general-tab-form.svelte
@@ -5,26 +5,175 @@
import * as Select from '$lib/components/ui/select';
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
import type { PedimentoCode } from '$lib/api/dashboard/refrence_data/pedimento_codes';
+ import type { CustomsSection } from '$lib/api/dashboard/refrence_data/customs_sections';
+ import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers';
+ import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers';
+ import type { CodePedimentoRegimen } from '$lib/api/dashboard/refrence_data/code_pedimento_regimens';
let {
pedimento,
formData = $bindable(),
- pedimentoCodes = []
+ pedimentoCodes = [],
+ customsSections = [],
+ customsBrokers = [],
+ clients = [],
+ codePedimentoRegimens = []
}: {
pedimento: Pedimento | null;
formData?: any;
pedimentoCodes?: PedimentoCode[];
+ customsSections?: CustomsSection[];
+ customsBrokers?: CustomsBroker[];
+ clients?: ClientProvider[];
+ codePedimentoRegimens?: CodePedimentoRegimen[];
} = $props();
- // Debug: verificar que los datos llegan
- $effect(() => {
- console.log('pedimentoCodes:', pedimentoCodes.length, 'items');
+ // Extraer regímenes únicos de codePedimentoRegimens
+ const uniqueRegimens = $derived(
+ Array.from(new Set(codePedimentoRegimens.map(r => r.regimen_code).filter((code): code is string => code !== null)))
+ .sort()
+ .map(code => ({ code, label: code }))
+ );
+
+ // Funciones de mapeo entre type_code (E/I) y operation_type (1/2)
+ function typeCodeToOperationType(typeCode: string | null | undefined): number | null {
+ if (!typeCode) return null;
+ // E = Exportación = 1, I = Importación = 2
+ if (typeCode.toUpperCase() === 'E') return 1;
+ if (typeCode.toUpperCase() === 'I') return 2;
+ return null;
+ }
+
+ function operationTypeToTypeCode(operationType: number | null | undefined): string | null {
+ if (operationType === null || operationType === undefined) return null;
+ // 1 = Exportación = E, 2 = Importación = I
+ if (operationType === 1) return 'E';
+ if (operationType === 2) return 'I';
+ return null;
+ }
+
+ // Opciones filtradas para Régimen y Tipo de Operación basadas en las selecciones actuales
+ // NOTA: La Clave NO se filtra, siempre muestra todas las opciones
+
+ const filteredRegimens = $derived(() => {
+ // Si hay clave o tipo de operación seleccionado, filtrar
+ if (formData.pedimento_code || formData.operation_type !== null) {
+ const matches = codePedimentoRegimens.filter(r => {
+ const matchesCode = !formData.pedimento_code || r.pedimento_code === formData.pedimento_code;
+ const matchesType = formData.operation_type === null || r.type_code === operationTypeToTypeCode(formData.operation_type);
+ return matchesCode && matchesType;
+ });
+ const validRegimens = new Set(matches.map(m => m.regimen_code).filter((code): code is string => code !== null));
+ return Array.from(validRegimens).sort().map(code => ({ code, label: code }));
+ }
+ return uniqueRegimens;
});
+ const filteredOperationTypes = $derived(() => {
+ // Si hay clave o régimen seleccionado, filtrar
+ if (formData.pedimento_code || formData.regime) {
+ const matches = codePedimentoRegimens.filter(r => {
+ const matchesCode = !formData.pedimento_code || r.pedimento_code === formData.pedimento_code;
+ const matchesRegime = !formData.regime || r.regimen_code === formData.regime;
+ return matchesCode && matchesRegime;
+ });
+ const validTypes = new Set(matches.map(m => typeCodeToOperationType(m.type_code)).filter(t => t !== null));
+ return operationOptions.filter(opt => validTypes.has(opt.value));
+ }
+ return operationOptions;
+ });
+
+ // Reactive synchronization between Clave, Régimen, and Tipo de Operación
+ // REGLA: La Clave es el campo principal y NUNCA se modifica automáticamente
+ // Solo se auto-llenan Régimen y Tipo de Operación basándose en la Clave
+
+ // Cuando cambia la Clave del Pedimento
+ $effect(() => {
+ const currentCode = formData.pedimento_code;
+ if (!currentCode) return;
+
+ const matches = codePedimentoRegimens.filter(r => r.pedimento_code === currentCode);
+
+ if (matches.length === 0) return;
+
+ // Verificar si los valores actuales de régimen y tipo son válidos para esta clave
+ const currentIsValid = matches.some(m => {
+ const matchesRegime = !formData.regime || m.regimen_code === formData.regime;
+ const matchesType = formData.operation_type === null || m.type_code === operationTypeToTypeCode(formData.operation_type);
+ return matchesRegime && matchesType;
+ });
+
+ // Si los valores actuales son válidos, NO auto-llenar
+ if (currentIsValid && (formData.regime || formData.operation_type !== null)) {
+ return;
+ }
+
+ // Si solo hay un match y no hay valores válidos, auto-llenar
+ if (matches.length === 1) {
+ const match = matches[0];
+ if (match.regimen_code && formData.regime !== match.regimen_code) {
+ formData.regime = match.regimen_code;
+ }
+ const expectedOpType = typeCodeToOperationType(match.type_code);
+ if (expectedOpType !== null && formData.operation_type !== expectedOpType) {
+ formData.operation_type = expectedOpType;
+ }
+ }
+ });
+
+ // Cuando cambia el Régimen
+ $effect(() => {
+ const currentRegime = formData.regime;
+ if (!currentRegime) return;
+
+ const matches = codePedimentoRegimens.filter(r => r.regimen_code === currentRegime);
+
+ if (matches.length === 0) return;
+
+ // Si hay clave seleccionada, solo validar (NO auto-llenar tipo de operación)
+ if (formData.pedimento_code) {
+ const exactMatch = matches.find(m => m.pedimento_code === formData.pedimento_code);
+ }
+ // Si hay tipo de operación pero no clave, no hacer nada
+ // (el usuario debe seleccionar la clave primero)
+ });
+
+ // Cuando cambia el Tipo de Operación
+ $effect(() => {
+ const currentType = formData.operation_type;
+ if (currentType === null || currentType === undefined) return;
+
+ const expectedTypeCode = operationTypeToTypeCode(currentType);
+ const matches = codePedimentoRegimens.filter(r => r.type_code === expectedTypeCode);
+
+ if (matches.length === 0) return;
+
+ // Si hay clave seleccionada, actualizar régimen (forzar si no hay match exacto)
+ if (formData.pedimento_code) {
+ const exactMatch = matches.find(m => m.pedimento_code === formData.pedimento_code);
+ if (exactMatch?.regimen_code && formData.regime !== exactMatch.regimen_code) {
+ formData.regime = exactMatch.regimen_code;
+ } else if (!exactMatch) {
+ // No hay match exacto - buscar cualquier match con la clave actual
+ const allMatchesForClave = codePedimentoRegimens.filter(r => r.pedimento_code === formData.pedimento_code);
+ if (allMatchesForClave.length > 0) {
+ // Forzar el régimen al primer match disponible para esta clave
+ const firstMatch = allMatchesForClave[0];
+ if (firstMatch.regimen_code) formData.regime = firstMatch.regimen_code;
+ }
+ }
+ }
+ // Si hay régimen pero no clave, no hacer nada
+ // (el usuario debe seleccionar la clave primero)
+ });
+
+ // Obtener el año actual (últimos 2 dígitos)
+ const currentYear = String(new Date().getFullYear()).slice(-2);
+
// Inicializar formData con los valores del pedimento (o vacío si es null)
if (!formData) {
formData = {
- year: pedimento?.year || '',
+ year: pedimento?.year || currentYear,
customs_office: pedimento?.customs_office || '',
license: pedimento?.license || '',
pedimento_number: pedimento?.pedimento_number || '',
@@ -41,6 +190,13 @@
};
}
+ // Asegurar que el año siempre esté actualizado con el año actual
+ $effect(() => {
+ if (formData && !pedimento?.year) {
+ formData.year = currentYear;
+ }
+ });
+
const operationOptions = [
{ value: 1, label: 'Exportación' },
{ value: 2, label: 'Importación' },
@@ -85,6 +241,8 @@
placeholder="23"
maxlength={2}
class="text-center"
+ disabled
+ readonly
/>
@@ -92,15 +250,28 @@
-
-
+
-
+ formData.customs_office = v ?? ''}
+ >
+
+
+ {formData.customs_office || 'Sel...'}
+
+
+
+ {#each customsSections as section}
+
+
+ {section.customs_code} - {section.section_name}
+
+
+ {/each}
+
+
@@ -109,13 +280,26 @@
-
+ formData.license = v ?? ''}
+ >
+
+
+ {formData.license || 'Sel...'}
+
+
+
+ {#each customsBrokers as broker}
+
+
+ {broker.broker_key} - {broker.name || ''}
+
+
+ {/each}
+
+
@@ -137,29 +321,24 @@
-
-
-
-
-
-
-
+
formData.operation_type = v ? Number(v) : null}
+ value={String(formData.client_id ?? '')}
+ onValueChange={(v: string) => formData.client_id = v ? Number(v) : null}
>
- {operationOptions.find(o => o.value === formData.operation_type)?.label || 'Seleccionar...'}
+
+ {clients.find(c => c.id === formData.client_id)?.name || 'Seleccionar cliente...'}
+
-
- {#each operationOptions as option}
-
+
+ {#each clients as client}
+
+
+ {client.name}
+
+
{/each}
@@ -176,40 +355,81 @@
/>
-
-
-
- formData.pedimento_code = v ?? ''}
- >
-
-
- {pedimentoCodes.find(o => o.code === formData.pedimento_code)?.code || 'Seleccionar...'}
-
-
-
- {#each pedimentoCodes as code}
-
-
- {code.code} - {code.description}
-
-
- {/each}
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+ formData.pedimento_code = v ?? ''}
+ >
+
+
+ {pedimentoCodes.find(o => o.code === formData.pedimento_code)?.code || 'Sel...'}
+
+
+
+ {#each pedimentoCodes as code}
+
+
+ {code.code} - {code.description}
+
+
+ {/each}
+
+
+
+
+
+
+
+ formData.regime = v ?? ''}
+ >
+
+
+ {formData.regime || 'Sel...'}
+
+
+
+ {#each filteredRegimens() as regimen}
+
+
+ {regimen.code}
+
+
+ {/each}
+
+
+
+
+
+
+
+ formData.operation_type = v ? Number(v) : null}
+ >
+
+ {operationOptions.find(o => o.value === formData.operation_type)?.label || 'Seleccionar...'}
+
+
+ {#each filteredOperationTypes() as option}
+
+ {/each}
+
+
+
+
+
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte
index 73d891e6..3f6031ce 100644
--- a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { codePedimentoRegimensApi, type CodePedimentoRegimen } from "$lib/api/dashboard/refrence_data/code_pedimento_regimens";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte
index 88ddcb9b..45c75b8d 100644
--- a/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { containersApi, type Container } from "$lib/api/dashboard/refrence_data/containers";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -84,26 +85,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/reference_data/customs_sections/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/customs_sections/delete-dialog.svelte
index f71a9d60..f2e3a3ff 100644
--- a/frontend/src/lib/components/dashboard/reference_data/customs_sections/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/customs_sections/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { customsSectionsApi, type CustomsSection } from "$lib/api/dashboard/refrence_data/customs_sections";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
diff --git a/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/delete-dialog.svelte
index 17878734..220f9e5c 100644
--- a/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/customs_warehouses/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { customsWarehousesApi, type CustomsWarehouse } from "$lib/api/dashboard/refrence_data/customs_warehouses";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
diff --git a/frontend/src/lib/components/dashboard/reference_data/material_types/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/material_types/delete-dialog.svelte
index 7bfb8a17..642bb106 100644
--- a/frontend/src/lib/components/dashboard/reference_data/material_types/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/material_types/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { materialTypesApi, type MaterialType } from "$lib/api/dashboard/refrence_data/material_types";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -88,26 +89,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/reference_data/payment_methods/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/payment_methods/delete-dialog.svelte
index f5ff98e7..2b23c0cf 100644
--- a/frontend/src/lib/components/dashboard/reference_data/payment_methods/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/payment_methods/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { paymentMethodsApi, type PaymentMethod } from "$lib/api/dashboard/refrence_data/payment_methods";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -84,26 +85,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/delete-dialog.svelte
index 4c7ba519..27eceaa1 100644
--- a/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/pedimento_regimens/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { pedimentoRegimensApi, type PedimentoRegimen } from "$lib/api/dashboard/refrence_data/pedimento_regimens";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -84,26 +85,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/reference_data/states/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/states/create-edit-dialog.svelte
index 927f1ccf..cb24372d 100644
--- a/frontend/src/lib/components/dashboard/reference_data/states/create-edit-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/states/create-edit-dialog.svelte
@@ -4,6 +4,7 @@
import { Input } from "$lib/components/ui/input";
import { Label } from "$lib/components/ui/label";
import { statesApi, type State, type CreateStateData, type UpdateStateData } from "$lib/api/dashboard/refrence_data/states";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -195,26 +196,7 @@
{#if loading}
-
+
{/if}
{isEditing ? "Guardar cambios" : "Crear"}
diff --git a/frontend/src/lib/components/dashboard/reference_data/states/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/states/delete-dialog.svelte
index d52d5553..24e0c6e1 100644
--- a/frontend/src/lib/components/dashboard/reference_data/states/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/states/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { statesApi, type State } from "$lib/api/dashboard/refrence_data/states";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -96,26 +97,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/dashboard/reference_data/transport_modes/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/transport_modes/delete-dialog.svelte
index 13462cc5..cc05607a 100644
--- a/frontend/src/lib/components/dashboard/reference_data/transport_modes/delete-dialog.svelte
+++ b/frontend/src/lib/components/dashboard/reference_data/transport_modes/delete-dialog.svelte
@@ -2,6 +2,7 @@
import { Button } from "$lib/components/ui/button";
import * as AlertDialog from "$lib/components/ui/alert-dialog";
import { transportModesApi, type TransportMode } from "$lib/api/dashboard/refrence_data/transport_modes";
+ import { LoaderCircle } from 'lucide-svelte';
let {
open = $bindable(false),
@@ -84,26 +85,7 @@
class="bg-destructive text-destructive-foreground hover:bg-destructive/90"
>
{#if loading}
-
+
{/if}
Eliminar
diff --git a/frontend/src/lib/components/login-form.svelte b/frontend/src/lib/components/login-form.svelte
index 11961b10..ebb3726a 100644
--- a/frontend/src/lib/components/login-form.svelte
+++ b/frontend/src/lib/components/login-form.svelte
@@ -10,6 +10,7 @@
import { Input } from "$lib/components/ui/input/index.js";
import { Button } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
+ import { FileText, ShieldCheck } from 'lucide-svelte';
import type { HTMLAttributes } from "svelte/elements";
import { page } from '$app/state';
import { enhance } from '$app/forms';
@@ -203,14 +204,10 @@
diff --git a/frontend/src/routes/dashboard/+page.svelte b/frontend/src/routes/dashboard/+page.svelte
index 105fd63a..71473c62 100644
--- a/frontend/src/routes/dashboard/+page.svelte
+++ b/frontend/src/routes/dashboard/+page.svelte
@@ -1,5 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/src/routes/dashboard/clients_and_providers/+page.server.ts b/frontend/src/routes/dashboard/clients_and_providers/+page.server.ts
index f27c7557..dc458a5f 100644
--- a/frontend/src/routes/dashboard/clients_and_providers/+page.server.ts
+++ b/frontend/src/routes/dashboard/clients_and_providers/+page.server.ts
@@ -4,9 +4,9 @@ import { getAuthTokens, authenticatedFetch } from '$lib/server/api';
export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => {
// Esperar a que el layout padre valide/refresque el token
const parentData = await parent();
-
+
const { accessToken } = getAuthTokens(cookies);
-
+
if (!accessToken) {
return {
error: 'No authenticated',
@@ -22,20 +22,20 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => {
// Obtener parámetros de paginación de la URL
const page = parseInt(url.searchParams.get('page') || '1');
const pageSize = parseInt(url.searchParams.get('page_size') || '50');
-
+
// Obtener company_id de múltiples fuentes (en orden de prioridad):
// 1. URL query param (permite cambiar vía navegación)
// 2. Cookie active_company_id (setted por el team-switcher)
// 3. Primera compañía del usuario (fallback)
const companyIdParam = url.searchParams.get('company_id');
const cookieCompanyId = cookies.get('active_company_id');
-
- const companyId = companyIdParam
+
+ const companyId = companyIdParam
? parseInt(companyIdParam)
: cookieCompanyId
? parseInt(cookieCompanyId)
: parentData.companies?.[0]?.id;
-
+
if (!companyId) {
return {
error: 'No company selected',
@@ -47,9 +47,17 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => {
};
}
+ // Construir URL con parámetros
+ let apiUrl = `v1/a76/clients-providers?company_id=${companyId}&page=${page}&page_size=${pageSize}`;
+
+ const type = url.searchParams.get('type');
+ if (type && type !== 'both') {
+ apiUrl += `&type=${type}`;
+ }
+
// Usar authenticatedFetch para manejar automáticamente el refresh de tokens
const response = await authenticatedFetch(
- `v1/a76/clients-providers?company_id=${companyId}&page=${page}&page_size=${pageSize}`,
+ apiUrl,
{},
cookies,
fetch
@@ -62,7 +70,7 @@ export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => {
statusText: response.statusText,
error: errorText
});
-
+
return {
error: `Error ${response.status}: ${response.statusText}`,
items: [],
diff --git a/frontend/src/routes/dashboard/clients_and_providers/+page.svelte b/frontend/src/routes/dashboard/clients_and_providers/+page.svelte
index 0995b3d6..2d25421a 100644
--- a/frontend/src/routes/dashboard/clients_and_providers/+page.svelte
+++ b/frontend/src/routes/dashboard/clients_and_providers/+page.svelte
@@ -6,6 +6,10 @@
import CreateEditDialog from '$lib/components/dashboard/clients_and_providers/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import * as Select from '$lib/components/ui/select';
+ import { Plus, RefreshCw } from 'lucide-svelte';
+ import { page } from '$app/stores';
+ import { goto } from '$app/navigation';
import type { PageData } from './$types';
import { browser } from '$app/environment';
import { companyStore } from '$lib/stores/company.svelte';
@@ -16,6 +20,22 @@
// Estado para el diálogo de crear
let showCreateDialog = $state(false);
+ // Estado para el filtro de tipo
+ let selectedType = $state
($page.url.searchParams.get('type') || 'both');
+
+ // Actualizar URL cuando cambia el filtro
+ function handleTypeChange(value: string) {
+ selectedType = value;
+ const url = new URL(window.location.href);
+ if (value === 'both') {
+ url.searchParams.delete('type');
+ } else {
+ url.searchParams.set('type', value);
+ }
+ goto(url.toString(), { keepFocus: true, noScroll: true, replaceState: true });
+ reloadData();
+ }
+
// Sincronizar token de cookies a localStorage al montar el componente
onMount(() => {
if (browser) {
@@ -77,7 +97,8 @@
const response = await clientsProvidersApi.list(
companyStore.activeCompany.id,
currentPage + 1,
- pageSize
+ pageSize,
+ selectedType !== 'both' ? { type: selectedType } : undefined
);
if (response.error) {
@@ -121,7 +142,8 @@
const response = await clientsProvidersApi.list(
companyStore.activeCompany.id,
1,
- pageSize
+ pageSize,
+ selectedType !== 'both' ? { type: selectedType } : undefined
);
if (response.error) {
@@ -174,21 +196,7 @@
-
+
Nuevo Cliente/Proveedor
@@ -216,25 +224,23 @@
{/if}
-
-
+
+
+
+ {selectedType === 'both' ? 'Todos' : selectedType === 'client' ? 'Clientes' : 'Proveedores'}
+
+
+ Todos
+ Clientes
+ Proveedores
+
+
+
+
Actualizar
+
diff --git a/frontend/src/routes/dashboard/customs_brokers/+page.svelte b/frontend/src/routes/dashboard/customs_brokers/+page.svelte
index 7ccfb44c..fe9682fd 100644
--- a/frontend/src/routes/dashboard/customs_brokers/+page.svelte
+++ b/frontend/src/routes/dashboard/customs_brokers/+page.svelte
@@ -11,6 +11,7 @@
import type { PageData } from './$types';
import { browser } from '$app/environment';
import { companyStore } from '$lib/stores/company.svelte';
+ import { Plus, Search, Trash2 } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -175,21 +176,7 @@
-
+
Nuevo Agente Aduanal
@@ -226,44 +213,15 @@
Buscando...
{:else}
-
+
Buscar
{/if}
- {#if searchedBroker}
-
-
- Limpiar
-
+ {#if searchedBroker}
+
+
+ Limpiar
+
{/if}
diff --git a/frontend/src/routes/dashboard/general_catalogs/classes/+page.svelte b/frontend/src/routes/dashboard/general_catalogs/classes/+page.svelte
index 458d83ec..247de471 100644
--- a/frontend/src/routes/dashboard/general_catalogs/classes/+page.svelte
+++ b/frontend/src/routes/dashboard/general_catalogs/classes/+page.svelte
@@ -9,6 +9,7 @@
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
+ import { Plus, Filter, Trash2, RefreshCw } from 'lucide-svelte';
import { browser } from '$app/environment';
// Estado para la lista de classes
@@ -255,21 +256,7 @@
-
+
Nueva Clase
@@ -305,38 +292,11 @@
-
+
Filtrar
-
+
@@ -364,21 +324,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/pedimentos/+page.svelte b/frontend/src/routes/dashboard/pedimentos/+page.svelte
index 8a90390c..711d5173 100644
--- a/frontend/src/routes/dashboard/pedimentos/+page.svelte
+++ b/frontend/src/routes/dashboard/pedimentos/+page.svelte
@@ -10,6 +10,7 @@
import type { PageData } from './$types';
import { browser } from '$app/environment';
import { companyStore } from '$lib/stores/company.svelte';
+ import { Plus, Filter, Trash2, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -260,21 +261,7 @@
-
+
Nuevo Pedimento
@@ -322,38 +309,11 @@
-
+
Filtrar
-
+
@@ -381,21 +341,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts
index 7c17e4c9..d34b2f0c 100644
--- a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts
+++ b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.server.ts
@@ -9,6 +9,13 @@ export const load: PageServerLoad = async ({ params, cookies, fetch }) => {
throw redirect(302, '/login');
}
+ // Obtener el company_id de la cookie para ambas ramas (new y edit)
+ const companyId = await getActiveCompanyId(cookies, fetch);
+
+ if (!companyId) {
+ throw error(400, 'No se encontró una compañía seleccionada');
+ }
+
// Cargar pedimento_codes (datos de referencia)
const pedimentoCodesPromise = authenticatedFetch(
'v1/public/refrence_data/pedimento-codes?page=1&page_size=100',
@@ -17,16 +24,63 @@ export const load: PageServerLoad = async ({ params, cookies, fetch }) => {
fetch
);
+ // Cargar customs_sections (datos de referencia)
+ const customsSectionsPromise = authenticatedFetch(
+ 'v1/public/refrence_data/customs-sections?page=1&page_size=100',
+ {},
+ cookies,
+ fetch
+ );
+
+ // Cargar customs_brokers (datos de referencia)
+ const customsBrokersPromise = authenticatedFetch(
+ `v1/a76/customs-brokers?company_id=${companyId}`,
+ {},
+ cookies,
+ fetch
+ );
+
+ // Cargar clientes (para el select de client_id)
+ const clientsPromise = authenticatedFetch(
+ `v1/a76/clients-providers?company_id=${companyId}&type=client&page=1&page_size=1000`,
+ {},
+ cookies,
+ fetch
+ );
+
+ // Cargar code-pedimento-regimens (para interdependencia de campos)
+ const codePedimentoRegimensPromise = authenticatedFetch(
+ 'v1/public/refrence_data/code-pedimento-regimens?page=1&page_size=100',
+ {},
+ cookies,
+ fetch
+ );
+
// Si el ID es "new", es una creación
if (params.id === 'new') {
- const pedimentoCodesResponse = await pedimentoCodesPromise;
+ const [pedimentoCodesResponse, customsSectionsResponse, customsBrokersResponse, clientsResponse, codePedimentoRegimensResponse] = await Promise.all([
+ pedimentoCodesPromise,
+ customsSectionsPromise,
+ customsBrokersPromise,
+ clientsPromise,
+ codePedimentoRegimensPromise
+ ]);
+
const pedimentoCodes = pedimentoCodesResponse.ok ? await pedimentoCodesResponse.json() : { items: [] };
-
+ const customsSections = customsSectionsResponse.ok ? await customsSectionsResponse.json() : { items: [] };
+ const customsBrokers = customsBrokersResponse.ok ? await customsBrokersResponse.json() : { items: [] };
+ const clients = clientsResponse.ok ? await clientsResponse.json() : { items: [] };
+ const codePedimentoRegimens = codePedimentoRegimensResponse.ok ? await codePedimentoRegimensResponse.json() : { items: [] };
+
return {
pedimento: null,
pedimentoId: null,
isCreate: true,
- pedimentoCodes: pedimentoCodes.items || []
+ pedimentoCodes: pedimentoCodes.items || [],
+ customsSections: customsSections.items || [],
+ customsBrokers: customsBrokers.items || [],
+ clients: clients.items || [],
+ codePedimentoRegimens: codePedimentoRegimens.items || []
};
}
@@ -36,12 +90,7 @@ export const load: PageServerLoad = async ({ params, cookies, fetch }) => {
}
try {
- // Obtener el company_id de la cookie
- const companyId = await getActiveCompanyId(cookies, fetch);
-
- if (!companyId) {
- throw error(400, 'No se encontró una compañía seleccionada');
- }
+
// Cargar el pedimento desde el backend usando authenticatedFetch
const response = await authenticatedFetch(
@@ -63,15 +112,30 @@ export const load: PageServerLoad = async ({ params, cookies, fetch }) => {
const pedimento = await response.json();
- // Cargar pedimento_codes
- const pedimentoCodesResponse = await pedimentoCodesPromise;
+ // Cargar pedimento_codes y customs_sections
+ const [pedimentoCodesResponse, customsSectionsResponse, customsBrokersResponse, clientsResponse, codePedimentoRegimensResponse] = await Promise.all([
+ pedimentoCodesPromise,
+ customsSectionsPromise,
+ customsBrokersPromise,
+ clientsPromise,
+ codePedimentoRegimensPromise
+ ]);
+
const pedimentoCodes = pedimentoCodesResponse.ok ? await pedimentoCodesResponse.json() : { items: [] };
+ const customsSections = customsSectionsResponse.ok ? await customsSectionsResponse.json() : { items: [] };
+ const customsBrokers = customsBrokersResponse.ok ? await customsBrokersResponse.json() : { items: [] };
+ const clients = clientsResponse.ok ? await clientsResponse.json() : { items: [] };
+ const codePedimentoRegimens = codePedimentoRegimensResponse.ok ? await codePedimentoRegimensResponse.json() : { items: [] };
return {
pedimento,
pedimentoId,
isCreate: false,
- pedimentoCodes: pedimentoCodes.items || []
+ pedimentoCodes: pedimentoCodes.items || [],
+ customsSections: customsSections.items || [],
+ customsBrokers: customsBrokers.items || [],
+ clients: clients.items || [],
+ codePedimentoRegimens: codePedimentoRegimens.items || []
};
} catch (e) {
console.error('Error loading pedimento:', e);
diff --git a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
index 3e1d4d1e..27e9f9b8 100644
--- a/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
+++ b/frontend/src/routes/dashboard/pedimentos/edit/[id]/+page.svelte
@@ -7,6 +7,18 @@
import { Button } from '$lib/components/ui/button';
import { Badge } from '$lib/components/ui/badge';
import { Separator } from '$lib/components/ui/separator';
+ import {
+ ArrowLeft,
+ CircleAlert,
+ CircleCheck,
+ FileText,
+ Calendar,
+ CreditCard,
+ Truck,
+ ShieldCheck,
+ LoaderCircle,
+ Save
+ } from 'lucide-svelte';
import type { PageData } from './$types';
// Importar los componentes de cada pestaña (ahora sin botones de guardar propios)
@@ -19,12 +31,20 @@
// Importar solo la API de pedimentos
import { pedimentosApi, type CreatePedimentoData, type UpdatePedimentoData } from '$lib/api/dashboard/a76/pedimentos';
import type { PedimentoCode } from '$lib/api/dashboard/refrence_data/pedimento_codes';
+ import type { CustomsSection } from '$lib/api/dashboard/refrence_data/customs_sections';
+ import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers';
+ import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers';
+ import type { CodePedimentoRegimen } from '$lib/api/dashboard/refrence_data/code_pedimento_regimens';
interface ExtendedPageData {
pedimentoId?: number | null;
pedimento?: any;
isCreate?: boolean;
pedimentoCodes?: PedimentoCode[];
+ customsSections?: CustomsSection[];
+ customsBrokers?: CustomsBroker[];
+ clients?: ClientProvider[];
+ codePedimentoRegimens?: CodePedimentoRegimen[];
user?: any;
companies?: any[];
authenticated?: boolean;
@@ -133,8 +153,7 @@
datesFormData.payment_date || datesFormData.rectification_payment_date ||
datesFormData.extraction_date || datesFormData.submission_date ||
datesFormData.eucan_date || datesFormData.original_date ||
- datesFormData.start_date || datesFormData.end_date ||
- datesFormData.capture_date || datesFormData.capture_time;
+ datesFormData.start_date || datesFormData.end_date;
if (hasDateValue) {
payload.pedimento_dates = {
@@ -148,8 +167,6 @@
original_date: datesFormData.original_date || null,
start_date: datesFormData.start_date || null,
end_date: datesFormData.end_date || null,
- capture_date: datesFormData.capture_date || null,
- capture_time: datesFormData.capture_time || null
};
}
}
@@ -267,20 +284,7 @@
-
+
{#if data.isCreate}
@@ -312,21 +316,7 @@
{#if error}
-
+
Error
{error}
@@ -334,217 +324,105 @@
{#if success}
-
+
Éxito
Todos los cambios se guardaron correctamente
{/if}
-
-
-
-
-
- General
-
-
-
- Fechas
-
-
-
- Pagos
-
-
-
- Transporte
-
-
-
- Validación
-
-
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cancelar
-
-
- {#if saving}
-
- Guardando todos los cambios...
- {:else}
-
- Guardar Todos los Cambios
- {/if}
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte
index a72beb5f..6da7f104 100644
--- a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Registro
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/containers/+page.svelte b/frontend/src/routes/dashboard/reference_data/containers/+page.svelte
index 98af455c..060fce7d 100644
--- a/frontend/src/routes/dashboard/reference_data/containers/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/containers/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Contenedor
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/countries/+page.svelte b/frontend/src/routes/dashboard/reference_data/countries/+page.svelte
index fd5ec3ef..4a54e322 100644
--- a/frontend/src/routes/dashboard/reference_data/countries/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/countries/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/countries/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo País
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/currency_types/+page.svelte b/frontend/src/routes/dashboard/reference_data/currency_types/+page.svelte
index f47264c8..38062c10 100644
--- a/frontend/src/routes/dashboard/reference_data/currency_types/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/currency_types/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/currency_types/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,22 +121,8 @@
-
- Nueva Moneda
+
+ Nuevo Tipo de Moneda
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/customs_sections/+page.svelte b/frontend/src/routes/dashboard/reference_data/customs_sections/+page.svelte
index a45491b7..b8b95f42 100644
--- a/frontend/src/routes/dashboard/reference_data/customs_sections/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/customs_sections/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nueva Sección
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.svelte b/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.svelte
index 82b7c178..f09cab30 100644
--- a/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/customs_warehouses/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Recinto
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/incoterms/+page.svelte b/frontend/src/routes/dashboard/reference_data/incoterms/+page.svelte
index 217d1c6c..201ce115 100644
--- a/frontend/src/routes/dashboard/reference_data/incoterms/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/incoterms/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/incoterms/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo Incoterm
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/invoice_types/+page.svelte b/frontend/src/routes/dashboard/reference_data/invoice_types/+page.svelte
index 1ba35154..72f1f62c 100644
--- a/frontend/src/routes/dashboard/reference_data/invoice_types/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/invoice_types/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/invoice_types/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo Tipo de Factura
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/material_types/+page.svelte b/frontend/src/routes/dashboard/reference_data/material_types/+page.svelte
index 66589b3f..94ee7d33 100644
--- a/frontend/src/routes/dashboard/reference_data/material_types/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/material_types/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Tipo de Material
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/payment_methods/+page.svelte b/frontend/src/routes/dashboard/reference_data/payment_methods/+page.svelte
index 860a48f3..a4800ec3 100644
--- a/frontend/src/routes/dashboard/reference_data/payment_methods/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/payment_methods/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Método de Pago
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.svelte b/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.svelte
index dec3a448..3761f69a 100644
--- a/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/pedimento_codes/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/pedimento_codes/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,22 +121,8 @@
-
- Nueva Clave de Pedimento
+
+ Nuevo Código de Pedimento
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.svelte b/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.svelte
index 39d1a31f..e636522f 100644
--- a/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/pedimento_regimens/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Régimen de Pedimento
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/sectors/+page.svelte b/frontend/src/routes/dashboard/reference_data/sectors/+page.svelte
index 3621eb21..fd4fe48a 100644
--- a/frontend/src/routes/dashboard/reference_data/sectors/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/sectors/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/sectors/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo Sector
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/states/+page.svelte b/frontend/src/routes/dashboard/reference_data/states/+page.svelte
index b164088c..82b50e2d 100644
--- a/frontend/src/routes/dashboard/reference_data/states/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/states/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Estado
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/transport_modes/+page.svelte b/frontend/src/routes/dashboard/reference_data/transport_modes/+page.svelte
index 774372d8..fd4c7553 100644
--- a/frontend/src/routes/dashboard/reference_data/transport_modes/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/transport_modes/+page.svelte
@@ -8,6 +8,7 @@
import { Button } from '$lib/components/ui/button';
import type { PageData } from './$types';
import { browser } from '$app/environment';
+ import { Plus, RefreshCw } from 'lucide-svelte';
// Los datos iniciales vienen del servidor
let { data }: { data: PageData } = $props();
@@ -120,21 +121,7 @@
-
+
Nuevo Modo de Transporte
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/transport_types/+page.svelte b/frontend/src/routes/dashboard/reference_data/transport_types/+page.svelte
index 28c96469..a8a57d47 100644
--- a/frontend/src/routes/dashboard/reference_data/transport_types/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/transport_types/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/transport_types/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo Tipo de Transporte
@@ -160,21 +147,7 @@
-
+
Actualizar
diff --git a/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.svelte b/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.svelte
index 81e18284..380c9771 100644
--- a/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.svelte
+++ b/frontend/src/routes/dashboard/reference_data/valuation_methods/+page.svelte
@@ -6,6 +6,7 @@
import CreateEditDialog from '$lib/components/dashboard/reference_data/valuation_methods/create-edit-dialog.svelte';
import * as Card from '$lib/components/ui/card';
import { Button } from '$lib/components/ui/button';
+ import { Plus, RefreshCw } from 'lucide-svelte';
import type { PageData } from './$types';
import { browser } from '$app/environment';
@@ -120,21 +121,7 @@
-
+
Nuevo Método de Valoración
@@ -160,21 +147,7 @@
-
+
Actualizar