Refactor Pedimento data structure and update forms

- Expanded the PedimentoDates, PedimentoPayments, PedimentoTransportMeans, and PedimentoValidation interfaces to include additional fields.
- Updated the dates, payments, transport, and validation tab forms to initialize form data directly from the Pedimento object, removing unnecessary API calls for data loading.
- Enhanced the payload construction in the edit page to conditionally include sub-resources only if they contain values, improving data handling during creation and update operations.
- Adjusted the form bindings to reflect the new structure and ensure proper data flow between the components.
This commit is contained in:
2025-11-18 18:20:04 -06:00
parent 84006e3410
commit 404333f35e
15 changed files with 648 additions and 672 deletions

View File

@@ -23,10 +23,21 @@ class PedimentoDatesBase(BaseModel):
capture_time: Optional[time] = Field(None, description="Capture time")
class PedimentoDatesCreate(PedimentoDatesBase):
"""Schema for creating a new Pedimento Dates"""
class PedimentoDatesCreate(BaseModel):
"""Schema for creating a new Pedimento Dates - pedimento_id and tenant_id are set by backend"""
pass
entry_date: Optional[datetime] = Field(None, description="Entry date")
pedimento_date: Optional[datetime] = Field(None, description="Pedimento date")
payment_date: Optional[datetime] = Field(None, description="Payment date")
rectification_payment_date: Optional[datetime] = Field(None, description="Rectification payment date")
extraction_date: Optional[datetime] = Field(None, description="Extraction date")
submission_date: Optional[datetime] = Field(None, description="Submission date")
eucan_date: Optional[datetime] = Field(None, description="EUCAN date")
original_date: Optional[datetime] = Field(None, description="Original date")
start_date: Optional[datetime] = Field(None, description="Start date")
end_date: Optional[datetime] = Field(None, description="End date")
capture_date: Optional[datetime] = Field(None, description="Capture date")
capture_time: Optional[time] = Field(None, description="Capture time")
class PedimentoDatesUpdate(BaseModel):

View File

@@ -25,14 +25,23 @@ class PedimentoPaymentsBase(BaseModel):
total_cash_paid: Optional[int] = Field(None, description="Total cash paid")
total_contributions: Optional[int] = Field(None, description="Total contributions")
counter_payment: Optional[int] = Field(None, description="Counter payment")
pece_code: Optional[str] = Field(None, max_length=5, description="PECE code")
payment_id: Optional[int] = Field(None, description="Payment ID")
pece_code: Optional[str] = Field(None, max_length=5, description="PECE code")
class PedimentoPaymentsCreate(PedimentoPaymentsBase):
"""Schema for creating a new Pedimento Payments"""
class PedimentoPaymentsCreate(BaseModel):
"""Schema for creating a new Pedimento Payments - pedimento_id and tenant_id are set by backend"""
pass
acknowledgment: Optional[str] = Field(None, max_length=20, description="Acknowledgment")
operation_number: Optional[str] = Field(None, max_length=14, description="Operation number")
bank_code: Optional[int] = Field(None, description="Bank code")
cashier: Optional[str] = Field(None, max_length=2, description="Cashier")
date: Optional[Date] = Field(None, description="Date")
time: Optional[Time] = Field(None, description="Time")
shift: Optional[str] = Field(None, max_length=1, description="Shift")
total_cash_paid: Optional[int] = Field(None, description="Total cash paid")
total_contributions: Optional[int] = Field(None, description="Total contributions")
counter_payment: Optional[int] = Field(None, description="Counter payment")
pece_code: Optional[str] = Field(None, max_length=5, description="PECE code")
class PedimentoPaymentsUpdate(BaseModel):
@@ -48,8 +57,7 @@ class PedimentoPaymentsUpdate(BaseModel):
total_cash_paid: Optional[int] = None
total_contributions: Optional[int] = None
counter_payment: Optional[int] = None
pece_code: Optional[str] = Field(None, max_length=5)
payment_id: Optional[int] = None
pece_code: Optional[str] = Field(None, max_length=5)
class PedimentoPaymentsResponse(PedimentoPaymentsBase):

View File

@@ -15,10 +15,13 @@ class PedimentoTransportMeansBase(BaseModel):
departure: Optional[str] = Field(None, max_length=2, description="Departure")
class PedimentoTransportMeansCreate(PedimentoTransportMeansBase):
"""Schema for creating a new Pedimento Transport Means"""
class PedimentoTransportMeansCreate(BaseModel):
"""Schema for creating a new Pedimento Transport Means - pedimento_id and tenant_id are set by backend"""
pass
destination: Optional[int] = Field(None, description="Destination")
entry_exit: Optional[str] = Field(None, max_length=2, description="Entry/exit")
arrival: Optional[str] = Field(None, max_length=2, description="Arrival")
departure: Optional[str] = Field(None, max_length=2, description="Departure")
class PedimentoTransportMeansUpdate(BaseModel):

View File

@@ -27,10 +27,17 @@ class PedimentoValidationBase(BaseModel):
responsible_id: Optional[int] = Field(None, description="Responsible ID")
class PedimentoValidationCreate(PedimentoValidationBase):
"""Schema for creating a new Pedimento Validation"""
class PedimentoValidationCreate(BaseModel):
"""Schema for creating a new Pedimento Validation - pedimento_id and tenant_id are set by backend"""
pass
validator: Optional[str] = Field(None, max_length=3, description="Validator")
validation_ack: Optional[str] = Field(None, max_length=8, description="Validation acknowledgment")
pre_ack: Optional[str] = Field(None, max_length=8, description="Previous acknowledgment")
line_signature: Optional[str] = Field(None, max_length=50, description="Line signature")
electronic_signature: Optional[str] = Field(None, max_length=999, description="Electronic signature")
certificate_number: Optional[str] = Field(None, max_length=99, description="Certificate number")
validator_id: Optional[int] = Field(None, description="Validator ID")
responsible_id: Optional[int] = Field(None, description="Responsible ID")
class PedimentoValidationUpdate(BaseModel):

View File

@@ -5,22 +5,22 @@ from typing import Optional
from pydantic import BaseModel, ConfigDict, Field
from .pedimento_config_additional import PedimentoConfigAdditionalCreate
from .pedimento_config_calculations import PedimentoConfigCalculationsCreate
from .pedimento_config_parameters import PedimentoConfigParametersCreate
from .pedimento_config_surcharges import PedimentoConfigSurchargesCreate
from .pedimento_config_update_rectification import PedimentoConfigUpdateRectificationCreate
from .pedimento_config_updates import PedimentoConfigUpdatesCreate
from .pedimento_customs_offices import PedimentoCustomsOfficesCreate
from .pedimento_dates import PedimentoDatesCreate
from .pedimento_decrementables import PedimentoDecrementablesCreate
from .pedimento_incrementables import PedimentoIncrementablesCreate
from .pedimento_indexes import PedimentoIndexesCreate
from .pedimento_payments import PedimentoPaymentsCreate
from .pedimento_rectification_destination import PedimentoRectificationDestinationCreate
from .pedimento_rectification_origin import PedimentoRectificationOriginCreate
from .pedimento_transport_means import PedimentoTransportMeansCreate
from .pedimento_validation import PedimentoValidationCreate
from .pedimento_config_additional import PedimentoConfigAdditionalCreate, PedimentoConfigAdditionalResponse
from .pedimento_config_calculations import PedimentoConfigCalculationsCreate, PedimentoConfigCalculationsResponse
from .pedimento_config_parameters import PedimentoConfigParametersCreate, PedimentoConfigParametersResponse
from .pedimento_config_surcharges import PedimentoConfigSurchargesCreate, PedimentoConfigSurchargesResponse
from .pedimento_config_update_rectification import PedimentoConfigUpdateRectificationCreate, PedimentoConfigUpdateRectificationResponse
from .pedimento_config_updates import PedimentoConfigUpdatesCreate, PedimentoConfigUpdatesResponse
from .pedimento_customs_offices import PedimentoCustomsOfficesCreate, PedimentoCustomsOfficesResponse
from .pedimento_dates import PedimentoDatesCreate, PedimentoDatesResponse
from .pedimento_decrementables import PedimentoDecrementablesCreate, PedimentoDecrementablesResponse
from .pedimento_incrementables import PedimentoIncrementablesCreate, PedimentoIncrementablesResponse
from .pedimento_indexes import PedimentoIndexesCreate, PedimentoIndexesResponse
from .pedimento_payments import PedimentoPaymentsCreate, PedimentoPaymentsResponse
from .pedimento_rectification_destination import PedimentoRectificationDestinationCreate, PedimentoRectificationDestinationResponse
from .pedimento_rectification_origin import PedimentoRectificationOriginCreate, PedimentoRectificationOriginResponse
from .pedimento_transport_means import PedimentoTransportMeansCreate, PedimentoTransportMeansResponse
from .pedimento_validation import PedimentoValidationCreate, PedimentoValidationResponse
class OperationType(IntEnum):
@@ -50,8 +50,22 @@ class PedimentosBase(BaseModel):
usd_value: Optional[Decimal] = Field(None, description="USD value")
paid_price: Optional[Decimal] = Field(None, description="Paid price")
gross_weight: Optional[Decimal] = Field(None, description="Gross weight")
exchange_rate: Optional[Decimal] = Field(None, description="Exchange rate")
exchange_rate: Optional[Decimal] = Field(None, description="Exchange rate")
class PedimentosCreate(PedimentosBase):
"""Schema for creating a new Pedimento"""
# Override to make required fields non-optional
year: str = Field(..., max_length=2, description="Year")
customs_office: str = Field(..., max_length=2, description="Customs office")
license: str = Field(..., max_length=4, description="License")
pedimento_number: str = Field(..., max_length=7, description="Pedimento number")
client_id: int = Field(..., description="Client ID")
operation_type: int = Field(..., description="Operation type")
pedimento_type: int = Field(..., description="Pedimento type")
regime: str = Field(..., max_length=3, description="Regime")
status: str = Field(..., max_length=30, description="Status")
pedimento_dates: Optional[PedimentoDatesCreate] = None
pedimento_decrementables: Optional[PedimentoDecrementablesCreate] = None
pedimento_incrementables: Optional[PedimentoIncrementablesCreate] = None
@@ -69,37 +83,41 @@ class PedimentosBase(BaseModel):
pedimento_config_update_rectification: Optional[PedimentoConfigUpdateRectificationCreate] = None
pedimento_config_updates: Optional[PedimentoConfigUpdatesCreate] = None
class PedimentosCreate(PedimentosBase):
"""Schema for creating a new Pedimento"""
# Override to make required fields non-optional
year: str = Field(..., max_length=2, description="Year")
customs_office: str = Field(..., max_length=2, description="Customs office")
license: str = Field(..., max_length=4, description="License")
pedimento_number: str = Field(..., max_length=7, description="Pedimento number")
client_id: int = Field(..., description="Client ID")
operation_type: int = Field(..., description="Operation type")
pedimento_type: int = Field(..., description="Pedimento type")
regime: str = Field(..., max_length=3, description="Regime")
status: str = Field(..., max_length=30, description="Status")
class PedimentosUpdate(BaseModel):
"""Schema for updating a Pedimento"""
year: Optional[str] = Field(..., max_length=2)
customs_office: Optional[str] = Field(..., max_length=2)
license: Optional[str] = Field(..., max_length=4)
pedimento_number: Optional[str] = Field(..., max_length=7)
client_id: Optional[int]
operation_type: Optional[OperationType]
pedimento_type: Optional[int]
pedimento_code: Optional[str] = Field(..., max_length=2)
regime: Optional[str] = Field(..., max_length=3)
status: Optional[str] = Field(..., max_length=30)
year: Optional[str] = Field(None, max_length=2)
customs_office: Optional[str] = Field(None, max_length=2)
license: Optional[str] = Field(None, max_length=4)
pedimento_number: Optional[str] = Field(None, max_length=7)
client_id: Optional[int] = None
operation_type: Optional[int] = None
pedimento_type: Optional[int] = None
pedimento_code: Optional[str] = Field(None, max_length=2)
regime: Optional[str] = Field(None, max_length=3)
status: Optional[str] = Field(None, max_length=30)
usd_value: Optional[Decimal] = None
paid_price: Optional[Decimal] = None
gross_weight: Optional[Decimal] = None
exchange_rate: Optional[Decimal] = None
# Sub-resources
pedimento_dates: Optional[PedimentoDatesCreate] = None
pedimento_decrementables: Optional[PedimentoDecrementablesCreate] = None
pedimento_incrementables: Optional[PedimentoIncrementablesCreate] = None
pedimento_indexes: Optional[PedimentoIndexesCreate] = None
pedimento_validation: Optional[PedimentoValidationCreate] = None
pedimento_customs_offices: Optional[PedimentoCustomsOfficesCreate] = None
pedimento_payments: Optional[PedimentoPaymentsCreate] = None
pedimento_rectification_destination: Optional[PedimentoRectificationDestinationCreate] = None
pedimento_rectification_origin: Optional[PedimentoRectificationOriginCreate] = None
pedimento_transport_means: Optional[PedimentoTransportMeansCreate] = None
pedimento_config_additional: Optional[PedimentoConfigAdditionalCreate] = None
pedimento_config_calculations: Optional[PedimentoConfigCalculationsCreate] = None
pedimento_config_parameters: Optional[PedimentoConfigParametersCreate] = None
pedimento_config_surcharges: Optional[PedimentoConfigSurchargesCreate] = None
pedimento_config_update_rectification: Optional[PedimentoConfigUpdateRectificationCreate] = None
pedimento_config_updates: Optional[PedimentoConfigUpdatesCreate] = None
class PedimentosResponse(PedimentosBase):
@@ -108,5 +126,22 @@ class PedimentosResponse(PedimentosBase):
id: int
tenant_id: int
created_at: datetime
pedimento_dates: Optional[PedimentoDatesResponse] = None
pedimento_decrementables: Optional[PedimentoDecrementablesResponse] = None
pedimento_incrementables: Optional[PedimentoIncrementablesResponse] = None
pedimento_indexes: Optional[PedimentoIndexesResponse] = None
pedimento_validation: Optional[PedimentoValidationResponse] = None
pedimento_customs_offices: Optional[PedimentoCustomsOfficesResponse] = None
pedimento_payments: Optional[PedimentoPaymentsResponse] = None
pedimento_rectification_destination: Optional[PedimentoRectificationDestinationResponse] = None
pedimento_rectification_origin: Optional[PedimentoRectificationOriginResponse] = None
pedimento_transport_means: Optional[PedimentoTransportMeansResponse] = None
pedimento_config_additional: Optional[PedimentoConfigAdditionalResponse] = None
pedimento_config_calculations: Optional[PedimentoConfigCalculationsResponse] = None
pedimento_config_parameters: Optional[PedimentoConfigParametersResponse] = None
pedimento_config_surcharges: Optional[PedimentoConfigSurchargesResponse] = None
pedimento_config_update_rectification: Optional[PedimentoConfigUpdateRectificationResponse] = None
pedimento_config_updates: Optional[PedimentoConfigUpdatesResponse] = None
model_config = ConfigDict(from_attributes=True)

View File

@@ -49,7 +49,6 @@ class PedimentoPayments(Base, TenantScopedMixin, TimestampMixin):
id: Mapped[int] = mapped_column(Integer)
pedimento_id: Mapped[int] = mapped_column(Integer, nullable=False)
payment_id: Mapped[int] = mapped_column(Integer)
acknowledgment: Mapped[str] = mapped_column(String(20))
operation_number: Mapped[str] = mapped_column(String(14))

View File

@@ -35,10 +35,10 @@ async def list_payments(
return payments
@router.get("/{payment_id}", response_model=PedimentoPaymentsResponse)
@router.get("/{id}", response_model=PedimentoPaymentsResponse)
async def get_payment(
pedimento_id: int,
payment_id: int,
id: int,
company_id: int = Query(..., description="Company ID"),
db: Session = Depends(get_core_db),
current_user: Dict[str, Any] = Depends(get_current_user),
@@ -47,7 +47,7 @@ async def get_payment(
tenant_id = validate_access_to_resource(db, company_id, current_user)
payment = PedimentoPaymentsService.get_by_id(
db, payment_id, pedimento_id, tenant_id, company_id
db, id, pedimento_id, tenant_id, company_id
)
if not payment:
raise HTTPException(status_code=404, detail="Payment not found")
@@ -74,10 +74,10 @@ async def create_payment(
return payment
@router.put("/{payment_id}", response_model=PedimentoPaymentsResponse)
@router.put("/{id}", response_model=PedimentoPaymentsResponse)
async def update_payment(
pedimento_id: int,
payment_id: int,
id: int,
data: PedimentoPaymentsUpdate,
company_id: int = Query(..., description="Company ID"),
db: Session = Depends(get_core_db),
@@ -87,7 +87,7 @@ async def update_payment(
tenant_id = validate_access_to_resource(db, company_id, current_user)
payment = PedimentoPaymentsService.update(
db, payment_id, pedimento_id, tenant_id, company_id, data
db, id, pedimento_id, tenant_id, company_id, data
)
if not payment:
raise HTTPException(status_code=404, detail="Payment not found")
@@ -95,10 +95,10 @@ async def update_payment(
return payment
@router.delete("/{payment_id}", status_code=204)
@router.delete("/{id}", status_code=204)
async def delete_payment(
pedimento_id: int,
payment_id: int,
id: int,
company_id: int = Query(..., description="Company ID"),
db: Session = Depends(get_core_db),
current_user: Dict[str, Any] = Depends(get_current_user),
@@ -107,7 +107,7 @@ async def delete_payment(
tenant_id = validate_access_to_resource(db, company_id, current_user)
success = PedimentoPaymentsService.delete(
db, payment_id, pedimento_id, tenant_id, company_id
db, id, pedimento_id, tenant_id, company_id
)
if not success:
raise HTTPException(status_code=404, detail="Payment not found")

View File

@@ -6,7 +6,8 @@ import logging
from typing import Any, Dict, List, Optional
from sqlalchemy import desc
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, joinedload
from sqlalchemy.orm import selectinload
from ..dtos.pedimentos import PedimentosCreate, PedimentosUpdate
@@ -85,8 +86,31 @@ class PedimentosService:
query = query.filter(Pedimentos.year == filters["year"])
total = query.count()
# Eager load all relationships for the response schema
items = (
query.order_by(desc(Pedimentos.created_at)).offset(skip).limit(limit).all()
query.options(
selectinload(Pedimentos.pedimento_dates),
selectinload(Pedimentos.pedimento_decrementables),
selectinload(Pedimentos.pedimento_incrementables),
selectinload(Pedimentos.pedimento_indexes),
selectinload(Pedimentos.pedimento_validation),
selectinload(Pedimentos.pedimento_customs_offices),
selectinload(Pedimentos.pedimento_payments),
selectinload(Pedimentos.pedimento_rectification_destination),
selectinload(Pedimentos.pedimento_rectification_origin),
selectinload(Pedimentos.pedimento_transport_means),
selectinload(Pedimentos.pedimento_config_additional),
selectinload(Pedimentos.pedimento_config_calculations),
selectinload(Pedimentos.pedimento_config_parameters),
selectinload(Pedimentos.pedimento_config_surcharges),
selectinload(Pedimentos.pedimento_config_update_rectification),
selectinload(Pedimentos.pedimento_config_updates),
)
.order_by(desc(Pedimentos.created_at))
.offset(skip)
.limit(limit)
.all()
)
return items, total
@@ -113,6 +137,26 @@ class PedimentosService:
if company_id is not None:
query = query.filter(Pedimentos.company_id == company_id)
# Eager load all relationships for the response schema
query = query.options(
selectinload(Pedimentos.pedimento_dates),
selectinload(Pedimentos.pedimento_decrementables),
selectinload(Pedimentos.pedimento_incrementables),
selectinload(Pedimentos.pedimento_indexes),
selectinload(Pedimentos.pedimento_validation),
selectinload(Pedimentos.pedimento_customs_offices),
selectinload(Pedimentos.pedimento_payments),
selectinload(Pedimentos.pedimento_rectification_destination),
selectinload(Pedimentos.pedimento_rectification_origin),
selectinload(Pedimentos.pedimento_transport_means),
selectinload(Pedimentos.pedimento_config_additional),
selectinload(Pedimentos.pedimento_config_calculations),
selectinload(Pedimentos.pedimento_config_parameters),
selectinload(Pedimentos.pedimento_config_surcharges),
selectinload(Pedimentos.pedimento_config_update_rectification),
selectinload(Pedimentos.pedimento_config_updates),
)
return query.first()
@@ -247,23 +291,25 @@ class PedimentosService:
# Helper function para actualizar o crear objetos relacionados
def update_or_create_related(service_class, model_class, data_attr):
if not hasattr(pedimento_data, data_attr):
# Obtener datos del payload completo (no solo exclude_unset)
full_data = pedimento_data.model_dump()
if data_attr not in full_data:
return
data = getattr(pedimento_data, data_attr)
data = full_data[data_attr]
if not data:
return
existing = service_class.get_by_pedimento_id(db, pedimento_id, tenant_id)
if existing:
# Actualizar existente
update_dict = data.model_dump(exclude_unset=True)
for field, value in update_dict.items():
setattr(existing, field, value)
for field, value in data.items():
if hasattr(existing, field):
setattr(existing, field, value)
else:
# Crear nuevo
obj_dict = data.model_dump()
obj = model_class(**obj_dict)
obj = model_class(**data)
obj.pedimento_id = pedimento_id
obj.tenant_id = tenant_id
obj.company_id = company_id

View File

@@ -17,8 +17,7 @@ export interface PedimentoPayments {
total_cash_paid?: number | null;
total_contributions?: number | null;
counter_payment?: number | null;
pece_code?: string | null;
payment_id?: number | null;
pece_code?: string | null;
created_at: string;
}
@@ -33,8 +32,7 @@ export interface CreatePedimentoPaymentsData {
total_cash_paid?: number | null;
total_contributions?: number | null;
counter_payment?: number | null;
pece_code?: string | null;
payment_id?: number | null;
pece_code?: string | null;
}
export interface UpdatePedimentoPaymentsData {
@@ -48,8 +46,7 @@ export interface UpdatePedimentoPaymentsData {
total_cash_paid?: number | null;
total_contributions?: number | null;
counter_payment?: number | null;
pece_code?: string | null;
payment_id?: number | null;
pece_code?: string | null;
}
export const pedimentoPaymentsApi = {

View File

@@ -9,22 +9,47 @@ export interface PedimentoDates {
entry_date?: string | null;
pedimento_date?: string | null;
payment_date?: string | null;
rectification_payment_date?: string | null;
extraction_date?: string | null;
submission_date?: string | null;
eucan_date?: string | null;
original_date?: string | null;
start_date?: string | null;
end_date?: string | null;
capture_date?: string | null;
capture_time?: string | null;
}
export interface PedimentoPayments {
payment_form?: string | null;
bank_identifier?: string | null;
acknowledgment?: string | null;
operation_number?: string | null;
bank_code?: string | null;
cashier?: string | null;
date?: string | null;
time?: string | null;
shift?: string | null;
total_cash_paid?: string | null;
total_contributions?: string | null;
counter_payment?: string | null;
pece_code?: string | null;
}
export interface PedimentoTransportMeans {
arrival_key?: string | null;
arrival_data?: string | null;
departure_key?: string | null;
departure_data?: string | null;
destination?: number | null;
entry_exit?: string | null;
arrival?: string | null;
departure?: string | null;
}
export interface PedimentoValidation {
document?: string | null;
validator?: string | null;
validation_ack?: string | null;
pre_ack?: string | null;
line_signature?: string | null;
electronic_signature?: string | null;
certificate_number?: string | null;
validator_id?: number | null;
responsible_id?: number | null;
}
export interface Pedimento {
@@ -49,7 +74,7 @@ export interface Pedimento {
pedimento_dates?: PedimentoDates | null;
pedimento_payments?: PedimentoPayments | null;
pedimento_transport_means?: PedimentoTransportMeans | null;
pedimento_validation?: PedimentoValidation | null;
pedimento_validation?: PedimentoValidation | null;
}
export interface PedimentoListResponse {

View File

@@ -1,90 +1,42 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Skeleton } from '$lib/components/ui/skeleton';
import { pedimentoDatesApi, type PedimentoDates } from '$lib/api/dashboard/a76/pedimento-dates';
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
let {
pedimentoId,
pedimento,
formData = $bindable(),
exists = $bindable()
}: {
pedimentoId: number | null;
pedimento: Pedimento | null;
formData?: any;
exists?: boolean;
} = $props();
let loading = $state(true);
onMount(async () => {
await loadDates();
});
async function loadDates() {
// Si no hay pedimentoId (modo creación), inicializar vacío
if (!pedimentoId) {
// Inicializar formData inmediatamente
const datesData = pedimento?.pedimento_dates;
if (datesData) {
exists = true;
if (!formData) {
formData = {
entry_date: '',
pedimento_date: '',
payment_date: '',
rectification_payment_date: '',
extraction_date: '',
submission_date: '',
eucan_date: '',
original_date: '',
start_date: '',
end_date: '',
capture_date: '',
capture_time: ''
entry_date: datesData.entry_date ? datesData.entry_date.substring(0, 10) : '',
pedimento_date: datesData.pedimento_date ? datesData.pedimento_date.substring(0, 10) : '',
payment_date: datesData.payment_date ? datesData.payment_date.substring(0, 10) : '',
rectification_payment_date: datesData.rectification_payment_date ? datesData.rectification_payment_date.substring(0, 10) : '',
extraction_date: datesData.extraction_date ? datesData.extraction_date.substring(0, 10) : '',
submission_date: datesData.submission_date ? datesData.submission_date.substring(0, 10) : '',
eucan_date: datesData.eucan_date ? datesData.eucan_date.substring(0, 10) : '',
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 || ''
};
exists = false;
loading = false;
return;
}
loading = true;
try {
const response = await pedimentoDatesApi.get(pedimentoId);
if (response.error) {
// No existe o hay error - inicializar vacío
exists = false;
formData = {
entry_date: '',
pedimento_date: '',
payment_date: '',
rectification_payment_date: '',
extraction_date: '',
submission_date: '',
eucan_date: '',
original_date: '',
start_date: '',
end_date: '',
capture_date: '',
capture_time: ''
};
} else if (response.data) {
exists = true;
formData = {
entry_date: response.data.entry_date ? response.data.entry_date.substring(0, 10) : '',
pedimento_date: response.data.pedimento_date ? response.data.pedimento_date.substring(0, 10) : '',
payment_date: response.data.payment_date ? response.data.payment_date.substring(0, 10) : '',
rectification_payment_date: response.data.rectification_payment_date ? response.data.rectification_payment_date.substring(0, 10) : '',
extraction_date: response.data.extraction_date ? response.data.extraction_date.substring(0, 10) : '',
submission_date: response.data.submission_date ? response.data.submission_date.substring(0, 10) : '',
eucan_date: response.data.eucan_date ? response.data.eucan_date.substring(0, 10) : '',
original_date: response.data.original_date ? response.data.original_date.substring(0, 10) : '',
start_date: response.data.start_date ? response.data.start_date.substring(0, 10) : '',
end_date: response.data.end_date ? response.data.end_date.substring(0, 10) : '',
capture_date: response.data.capture_date ? response.data.capture_date.substring(0, 10) : '',
capture_time: response.data.capture_time || ''
};
}
} catch (e) {
console.error('Error loading dates:', e);
exists = false;
} else {
exists = false;
if (!formData) {
formData = {
entry_date: '',
pedimento_date: '',
@@ -99,8 +51,6 @@
capture_date: '',
capture_time: ''
};
} finally {
loading = false;
}
}
</script>
@@ -113,15 +63,8 @@
</Card.Description>
</Card.Header>
<Card.Content>
{#if loading}
<div class="space-y-4">
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
</div>
{:else}
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Fecha de Entrada -->
<div class="space-y-2">
<Label for="entry_date">Fecha de Entrada</Label>
@@ -243,6 +186,5 @@
</div>
</div>
</div>
{/if}
</Card.Content>
</Card.Root>
</Card.Content>
</Card.Root>

View File

@@ -1,106 +1,54 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Skeleton } from '$lib/components/ui/skeleton';
import { pedimentoPaymentsApi } from '$lib/api/dashboard/a76/pedimento-payments';
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
let {
pedimentoId,
pedimento,
formData = $bindable(),
exists = $bindable()
}: {
pedimentoId: number | null;
pedimento: Pedimento | null;
formData?: any;
exists?: boolean;
} = $props();
let loading = $state(true);
onMount(async () => {
await loadPayments();
});
async function loadPayments() {
// Si no hay pedimentoId (modo creación), inicializar vacío
if (!pedimentoId) {
// Inicializar formData inmediatamente
const paymentsData = pedimento?.pedimento_payments;
if (paymentsData) {
exists = true;
if (!formData) {
formData = {
acknowledgment: '',
operation_number: '',
bank_code: null,
cashier: '',
date: '',
time: '',
shift: '',
total_cash_paid: null,
total_contributions: null,
counter_payment: null,
pece_code: '',
payment_id: null
acknowledgment: paymentsData.acknowledgment || '',
operation_number: paymentsData.operation_number || '',
bank_code: paymentsData.bank_code || '',
cashier: paymentsData.cashier || '',
date: paymentsData.date ? paymentsData.date.substring(0, 10) : '',
time: paymentsData.time || '',
shift: paymentsData.shift || '',
total_cash_paid: paymentsData.total_cash_paid || '',
total_contributions: paymentsData.total_contributions || '',
counter_payment: paymentsData.counter_payment || '',
pece_code: paymentsData.pece_code || '',
};
exists = false;
loading = false;
return;
}
loading = true;
try {
const response = await pedimentoPaymentsApi.get(pedimentoId);
if (response.error) {
// No existe o hay error - inicializar vacío
exists = false;
formData = {
acknowledgment: '',
operation_number: '',
bank_code: null,
cashier: '',
date: '',
time: '',
shift: '',
total_cash_paid: null,
total_contributions: null,
counter_payment: null,
pece_code: '',
payment_id: null
};
} else if (response.data) {
exists = true;
formData = {
acknowledgment: response.data.acknowledgment || '',
operation_number: response.data.operation_number || '',
bank_code: response.data.bank_code || null,
cashier: response.data.cashier || '',
date: response.data.date || '',
time: response.data.time || '',
shift: response.data.shift || '',
total_cash_paid: response.data.total_cash_paid || null,
total_contributions: response.data.total_contributions || null,
counter_payment: response.data.counter_payment || null,
pece_code: response.data.pece_code || '',
payment_id: response.data.payment_id || null
};
}
} catch (e) {
console.error('Error loading payments:', e);
exists = false;
} else {
exists = false;
if (!formData) {
formData = {
acknowledgment: '',
operation_number: '',
bank_code: null,
bank_code: '',
cashier: '',
date: '',
time: '',
shift: '',
total_cash_paid: null,
total_contributions: null,
counter_payment: null,
pece_code: '',
payment_id: null
total_cash_paid: '',
total_contributions: '',
counter_payment: '',
pece_code: '',
};
} finally {
loading = false;
}
}
</script>
@@ -113,145 +61,128 @@
</Card.Description>
</Card.Header>
<Card.Content>
{#if loading}
<div class="space-y-4">
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
</div>
{:else}
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Acuse -->
<div class="space-y-2">
<Label for="acknowledgment">Acuse</Label>
<Input
id="acknowledgment"
bind:value={formData.acknowledgment}
placeholder="Máx. 20 caracteres"
maxlength={20}
/>
</div>
<!-- Número de Operación -->
<div class="space-y-2">
<Label for="operation_number">Número de Operación</Label>
<Input
id="operation_number"
bind:value={formData.operation_number}
placeholder="Máx. 14 caracteres"
maxlength={14}
/>
</div>
<!-- Código de Banco -->
<div class="space-y-2">
<Label for="bank_code">Código de Banco</Label>
<Input
id="bank_code"
type="number"
bind:value={formData.bank_code}
placeholder="Código numérico"
/>
</div>
<!-- Cajero -->
<div class="space-y-2">
<Label for="cashier">Cajero</Label>
<Input
id="cashier"
bind:value={formData.cashier}
placeholder="Máx. 2 caracteres"
maxlength={2}
/>
</div>
<!-- Fecha -->
<div class="space-y-2">
<Label for="date">Fecha</Label>
<Input
id="date"
type="date"
bind:value={formData.date}
/>
</div>
<!-- Hora -->
<div class="space-y-2">
<Label for="time">Hora</Label>
<Input
id="time"
type="time"
bind:value={formData.time}
/>
</div>
<!-- Turno -->
<div class="space-y-2">
<Label for="shift">Turno</Label>
<Input
id="shift"
bind:value={formData.shift}
placeholder="1 carácter"
maxlength={1}
/>
</div>
<!-- Total Efectivo Pagado -->
<div class="space-y-2">
<Label for="total_cash_paid">Total Efectivo Pagado</Label>
<Input
id="total_cash_paid"
type="number"
bind:value={formData.total_cash_paid}
placeholder="Monto en efectivo"
/>
</div>
<!-- Total Contribuciones -->
<div class="space-y-2">
<Label for="total_contributions">Total Contribuciones</Label>
<Input
id="total_contributions"
type="number"
bind:value={formData.total_contributions}
placeholder="Monto total"
/>
</div>
<!-- Pago en Ventanilla -->
<div class="space-y-2">
<Label for="counter_payment">Pago en Ventanilla</Label>
<Input
id="counter_payment"
type="number"
bind:value={formData.counter_payment}
placeholder="Monto"
/>
</div>
<!-- Código PECE -->
<div class="space-y-2">
<Label for="pece_code">Código PECE</Label>
<Input
id="pece_code"
bind:value={formData.pece_code}
placeholder="Máx. 5 caracteres"
maxlength={5}
/>
</div>
<!-- ID de Pago -->
<div class="space-y-2">
<Label for="payment_id">ID de Pago</Label>
<Input
id="payment_id"
type="number"
bind:value={formData.payment_id}
placeholder="Identificador"
/>
</div>
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Acuse -->
<div class="space-y-2">
<Label for="acknowledgment">Acuse</Label>
<Input
id="acknowledgment"
bind:value={formData.acknowledgment}
maxlength={20}
placeholder="Acuse"
/>
</div>
<!-- Número de Operación -->
<div class="space-y-2">
<Label for="operation_number">Número de Operación</Label>
<Input
id="operation_number"
bind:value={formData.operation_number}
maxlength={14}
placeholder="Número de operación"
/>
</div>
<!-- Código Bancario -->
<div class="space-y-2">
<Label for="bank_code">Código Bancario</Label>
<Input
id="bank_code"
type="number"
bind:value={formData.bank_code}
placeholder="Código del banco"
/>
</div>
<!-- Cajero -->
<div class="space-y-2">
<Label for="cashier">Cajero</Label>
<Input
id="cashier"
bind:value={formData.cashier}
maxlength={2}
placeholder="Cajero"
/>
</div>
<!-- Fecha -->
<div class="space-y-2">
<Label for="date">Fecha</Label>
<Input
id="date"
type="date"
bind:value={formData.date}
/>
</div>
<!-- Hora -->
<div class="space-y-2">
<Label for="time">Hora</Label>
<Input
id="time"
type="time"
bind:value={formData.time}
/>
</div>
<!-- Turno -->
<div class="space-y-2">
<Label for="shift">Turno</Label>
<Input
id="shift"
bind:value={formData.shift}
maxlength={1}
placeholder="Turno"
/>
</div>
<!-- Total Pagado en Efectivo -->
<div class="space-y-2">
<Label for="total_cash_paid">Total Pagado en Efectivo</Label>
<Input
id="total_cash_paid"
type="number"
bind:value={formData.total_cash_paid}
placeholder="Total en efectivo"
/>
</div>
<!-- Total Contribuciones -->
<div class="space-y-2">
<Label for="total_contributions">Total Contribuciones</Label>
<Input
id="total_contributions"
type="number"
bind:value={formData.total_contributions}
placeholder="Total contribuciones"
/>
</div>
<!-- Pago en Mostrador -->
<div class="space-y-2">
<Label for="counter_payment">Pago en Mostrador</Label>
<Input
id="counter_payment"
type="number"
bind:value={formData.counter_payment}
placeholder="Pago en mostrador"
/>
</div>
<!-- Código PECE -->
<div class="space-y-2">
<Label for="pece_code">Código PECE</Label>
<Input
id="pece_code"
bind:value={formData.pece_code}
maxlength={5}
placeholder="Código PECE"
/>
</div>
</div>
{/if}
</div>
</Card.Content>
</Card.Root>

View File

@@ -1,74 +1,40 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Skeleton } from '$lib/components/ui/skeleton';
import { pedimentoTransportApi } from '$lib/api/dashboard/a76/pedimento-transport';
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
let {
pedimentoId,
pedimento,
formData = $bindable(),
exists = $bindable()
}: {
pedimentoId: number | null;
pedimento: Pedimento | null;
formData?: any;
exists?: boolean;
} = $props();
let loading = $state(true);
onMount(async () => {
await loadTransport();
});
async function loadTransport() {
// Si no hay pedimentoId (modo creación), inicializar vacío
if (!pedimentoId) {
// Inicializar formData inmediatamente
const transportData = pedimento?.pedimento_transport_means;
if (transportData) {
exists = true;
if (!formData) {
formData = {
destination: null,
entry_exit: '',
arrival: '',
departure: ''
destination: transportData.destination || '',
entry_exit: transportData.entry_exit || '',
arrival: transportData.arrival || '',
departure: transportData.departure || ''
};
exists = false;
loading = false;
return;
}
loading = true;
try {
const response = await pedimentoTransportApi.get(pedimentoId);
if (response.error) {
// No existe o hay error - inicializar vacío
exists = false;
formData = {
destination: null,
entry_exit: '',
arrival: '',
departure: ''
};
} else if (response.data) {
exists = true;
formData = {
destination: response.data.destination || null,
entry_exit: response.data.entry_exit || '',
arrival: response.data.arrival || '',
departure: response.data.departure || ''
};
}
} catch (e) {
console.error('Error loading transport:', e);
exists = false;
} else {
exists = false;
if (!formData) {
formData = {
destination: null,
destination: '',
entry_exit: '',
arrival: '',
departure: ''
};
} finally {
loading = false;
}
}
</script>
@@ -81,61 +47,52 @@
</Card.Description>
</Card.Header>
<Card.Content>
{#if loading}
<div class="space-y-4">
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
</div>
{:else}
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Destino -->
<div class="space-y-2">
<Label for="destination">Destino</Label>
<Input
id="destination"
type="number"
bind:value={formData.destination}
placeholder="Código de destino"
/>
</div>
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Destino -->
<div class="space-y-2">
<Label for="destination">Destino</Label>
<Input
id="destination"
type="number"
bind:value={formData.destination}
placeholder="Destino"
/>
</div>
<!-- Entrada/Salida -->
<div class="space-y-2">
<Label for="entry_exit">Entrada/Salida</Label>
<Input
id="entry_exit"
bind:value={formData.entry_exit}
placeholder="Máx. 2 caracteres"
maxlength={2}
/>
</div>
<!-- Entrada/Salida -->
<div class="space-y-2">
<Label for="entry_exit">Entrada/Salida</Label>
<Input
id="entry_exit"
bind:value={formData.entry_exit}
maxlength={2}
placeholder="Entrada/Salida"
/>
</div>
<!-- Llegada -->
<div class="space-y-2">
<Label for="arrival">Llegada</Label>
<Input
id="arrival"
bind:value={formData.arrival}
placeholder="Máx. 2 caracteres"
maxlength={2}
/>
</div>
<!-- Llegada -->
<div class="space-y-2">
<Label for="arrival">Llegada</Label>
<Input
id="arrival"
bind:value={formData.arrival}
maxlength={2}
placeholder="Llegada"
/>
</div>
<!-- Salida -->
<div class="space-y-2">
<Label for="departure">Salida</Label>
<Input
id="departure"
bind:value={formData.departure}
placeholder="Máx. 2 caracteres"
maxlength={2}
/>
</div>
<!-- Salida -->
<div class="space-y-2">
<Label for="departure">Salida</Label>
<Input
id="departure"
bind:value={formData.departure}
maxlength={2}
placeholder="Salida"
/>
</div>
</div>
{/if}
</div>
</Card.Content>
</Card.Root>

View File

@@ -1,79 +1,39 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Textarea } from '$lib/components/ui/textarea';
import { Skeleton } from '$lib/components/ui/skeleton';
import { pedimentoValidationApi } from '$lib/api/dashboard/a76/pedimento-validation';
import type { Pedimento } from '$lib/api/dashboard/a76/pedimentos';
let {
pedimentoId,
pedimento,
formData = $bindable(),
exists = $bindable()
}: {
pedimentoId: number | null;
pedimento: Pedimento | null;
formData?: any;
exists?: boolean;
} = $props();
let loading = $state(true);
onMount(async () => {
await loadValidation();
});
async function loadValidation() {
// Si no hay pedimentoId (modo creación), inicializar vacío
if (!pedimentoId) {
// Inicializar formData inmediatamente
const validationData = pedimento?.pedimento_validation;
if (validationData) {
exists = true;
if (!formData) {
formData = {
validator: '',
validation_ack: '',
pre_ack: '',
line_signature: '',
electronic_signature: '',
certificate_number: '',
validator_id: null,
responsible_id: null
validator: validationData.validator || '',
validation_ack: validationData.validation_ack || '',
pre_ack: validationData.pre_ack || '',
line_signature: validationData.line_signature || '',
electronic_signature: validationData.electronic_signature || '',
certificate_number: validationData.certificate_number || '',
validator_id: validationData.validator_id || '',
responsible_id: validationData.responsible_id || ''
};
exists = false;
loading = false;
return;
}
loading = true;
try {
const response = await pedimentoValidationApi.get(pedimentoId);
if (response.error) {
// No existe o hay error - inicializar vacío
exists = false;
formData = {
validator: '',
validation_ack: '',
pre_ack: '',
line_signature: '',
electronic_signature: '',
certificate_number: '',
validator_id: null,
responsible_id: null
};
} else if (response.data) {
exists = true;
formData = {
validator: response.data.validator || '',
validation_ack: response.data.validation_ack || '',
pre_ack: response.data.pre_ack || '',
line_signature: response.data.line_signature || '',
electronic_signature: response.data.electronic_signature || '',
certificate_number: response.data.certificate_number || '',
validator_id: response.data.validator_id || null,
responsible_id: response.data.responsible_id || null
};
}
} catch (e) {
console.error('Error loading validation:', e);
exists = false;
} else {
exists = false;
if (!formData) {
formData = {
validator: '',
validation_ack: '',
@@ -81,11 +41,9 @@
line_signature: '',
electronic_signature: '',
certificate_number: '',
validator_id: null,
responsible_id: null
validator_id: '',
responsible_id: ''
};
} finally {
loading = false;
}
}
</script>
@@ -98,110 +56,96 @@
</Card.Description>
</Card.Header>
<Card.Content>
{#if loading}
<div class="space-y-4">
<Skeleton class="h-10 w-full" />
<Skeleton class="h-10 w-full" />
<Skeleton class="h-32 w-full" />
<Skeleton class="h-32 w-full" />
</div>
{:else}
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Validador -->
<div class="space-y-2">
<Label for="validator">Validador</Label>
<Input
id="validator"
bind:value={formData.validator}
placeholder="Máx. 3 caracteres"
maxlength={3}
/>
</div>
<!-- Acuse de Validación -->
<div class="space-y-2">
<Label for="validation_ack">Acuse de Validación</Label>
<Input
id="validation_ack"
bind:value={formData.validation_ack}
placeholder="Máx. 8 caracteres"
maxlength={8}
/>
</div>
<!-- Pre-acuse -->
<div class="space-y-2">
<Label for="pre_ack">Pre-acuse</Label>
<Input
id="pre_ack"
bind:value={formData.pre_ack}
placeholder="Máx. 8 caracteres"
maxlength={8}
/>
</div>
<!-- Número de Certificado -->
<div class="space-y-2">
<Label for="certificate_number">Número de Certificado</Label>
<Input
id="certificate_number"
bind:value={formData.certificate_number}
placeholder="Máx. 99 caracteres"
maxlength={99}
/>
</div>
<!-- ID de Validador -->
<div class="space-y-2">
<Label for="validator_id">ID de Validador</Label>
<Input
id="validator_id"
type="number"
bind:value={formData.validator_id}
placeholder="Identificador numérico"
/>
</div>
<!-- ID de Responsable -->
<div class="space-y-2">
<Label for="responsible_id">ID de Responsable</Label>
<Input
id="responsible_id"
type="number"
bind:value={formData.responsible_id}
placeholder="Identificador numérico"
/>
</div>
<div class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Validador -->
<div class="space-y-2">
<Label for="validator">Validador</Label>
<Input
id="validator"
bind:value={formData.validator}
maxlength={3}
placeholder="Validador"
/>
</div>
<!-- Firma de Línea -->
<!-- Acuse de Validación -->
<div class="space-y-2">
<Label for="line_signature">Firma de Línea</Label>
<Label for="validation_ack">Acuse de Validación</Label>
<Input
id="validation_ack"
bind:value={formData.validation_ack}
maxlength={8}
placeholder="Acuse de validación"
/>
</div>
<!-- Acuse Previo -->
<div class="space-y-2">
<Label for="pre_ack">Acuse Previo</Label>
<Input
id="pre_ack"
bind:value={formData.pre_ack}
maxlength={8}
placeholder="Acuse previo"
/>
</div>
<!-- Firma Línea de Captura -->
<div class="space-y-2">
<Label for="line_signature">Firma Línea de Captura</Label>
<Input
id="line_signature"
bind:value={formData.line_signature}
placeholder="Máx. 50 caracteres"
maxlength={50}
placeholder="Firma línea de captura"
/>
</div>
<!-- Firma Electrónica -->
<div class="space-y-2">
<div class="space-y-2 md:col-span-2">
<Label for="electronic_signature">Firma Electrónica</Label>
<Textarea
<Input
id="electronic_signature"
bind:value={formData.electronic_signature}
placeholder="Ingresa la firma electrónica..."
rows={6}
class="resize-none font-mono text-sm"
maxlength={999}
placeholder="Firma electrónica"
/>
</div>
<!-- Número de Certificado -->
<div class="space-y-2">
<Label for="certificate_number">Número de Certificado</Label>
<Input
id="certificate_number"
bind:value={formData.certificate_number}
maxlength={99}
placeholder="Número de certificado"
/>
</div>
<!-- ID de Validador -->
<div class="space-y-2">
<Label for="validator_id">ID de Validador</Label>
<Input
id="validator_id"
type="number"
bind:value={formData.validator_id}
placeholder="ID de validador"
/>
</div>
<!-- ID de Responsable -->
<div class="space-y-2">
<Label for="responsible_id">ID de Responsable</Label>
<Input
id="responsible_id"
type="number"
bind:value={formData.responsible_id}
placeholder="ID de responsable"
/>
<p class="text-sm text-muted-foreground">
Firma electrónica del pedimento (máximo 999 caracteres).
</p>
</div>
</div>
{/if}
</div>
</Card.Content>
</Card.Root>

View File

@@ -66,6 +66,7 @@
success = false;
try {
// Validar campos requeridos para creación
if (data.isCreate && generalFormData) {
const requiredFields = {
@@ -109,28 +110,98 @@
usd_value: generalFormData?.usd_value || undefined,
paid_price: generalFormData?.paid_price || undefined,
gross_weight: generalFormData?.gross_weight || undefined,
exchange_rate: generalFormData?.exchange_rate || undefined,
// Sub-recursos
pedimento_dates: (datesFormData?.entry_date || datesFormData?.pedimento_date || datesFormData?.payment_date) ? {
entry_date: datesFormData.entry_date || null,
pedimento_date: datesFormData.pedimento_date || null,
payment_date: datesFormData.payment_date || null
} : undefined,
pedimento_payments: (paymentsFormData?.payment_form || paymentsFormData?.bank_identifier) ? {
payment_form: paymentsFormData.payment_form || null,
bank_identifier: paymentsFormData.bank_identifier || null
} : undefined,
pedimento_transport_means: (transportFormData?.arrival_key || transportFormData?.arrival_data || transportFormData?.departure_key || transportFormData?.departure_data) ? {
arrival_key: transportFormData.arrival_key || null,
arrival_data: transportFormData.arrival_data || null,
departure_key: transportFormData.departure_key || null,
departure_data: transportFormData.departure_data || null
} : undefined,
pedimento_validation: validationFormData?.document ? {
document: validationFormData.document || null
} : undefined
exchange_rate: generalFormData?.exchange_rate || undefined
};
// Solo agregar sub-recursos en modo UPDATE (no en CREATE)
// Y solo si tienen valores reales (no enviar objetos vacíos/null)
if (!data.isCreate) {
// Dates - solo enviar si hay al menos un campo con valor
if (datesFormData) {
const hasDateValue = datesFormData.entry_date || datesFormData.pedimento_date ||
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;
if (hasDateValue) {
payload.pedimento_dates = {
entry_date: datesFormData.entry_date || null,
pedimento_date: datesFormData.pedimento_date || null,
payment_date: datesFormData.payment_date || null,
rectification_payment_date: datesFormData.rectification_payment_date || null,
extraction_date: datesFormData.extraction_date || null,
submission_date: datesFormData.submission_date || null,
eucan_date: datesFormData.eucan_date || null,
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
};
}
}
// Payments - solo enviar si hay al menos un campo con valor
if (paymentsFormData) {
const hasPaymentValue = paymentsFormData.acknowledgment || paymentsFormData.operation_number ||
paymentsFormData.bank_code || paymentsFormData.cashier || paymentsFormData.date ||
paymentsFormData.time || paymentsFormData.shift || paymentsFormData.total_cash_paid ||
paymentsFormData.total_contributions || paymentsFormData.counter_payment ||
paymentsFormData.pece_code;
if (hasPaymentValue) {
payload.pedimento_payments = {
acknowledgment: paymentsFormData.acknowledgment || null,
operation_number: paymentsFormData.operation_number || null,
bank_code: paymentsFormData.bank_code || null,
cashier: paymentsFormData.cashier || null,
date: paymentsFormData.date || null,
time: paymentsFormData.time || null,
shift: paymentsFormData.shift || null,
total_cash_paid: paymentsFormData.total_cash_paid || null,
total_contributions: paymentsFormData.total_contributions || null,
counter_payment: paymentsFormData.counter_payment || null,
pece_code: paymentsFormData.pece_code || null,
};
}
}
// Transport - solo enviar si hay al menos un campo con valor
if (transportFormData) {
const hasTransportValue = transportFormData.destination || transportFormData.entry_exit ||
transportFormData.arrival || transportFormData.departure;
if (hasTransportValue) {
payload.pedimento_transport_means = {
destination: transportFormData.destination || null,
entry_exit: transportFormData.entry_exit || null,
arrival: transportFormData.arrival || null,
departure: transportFormData.departure || null
};
}
}
// Validation - solo enviar si hay al menos un campo con valor
if (validationFormData) {
const hasValidationValue = validationFormData.validator || validationFormData.validation_ack ||
validationFormData.pre_ack || validationFormData.line_signature ||
validationFormData.electronic_signature || validationFormData.certificate_number ||
validationFormData.validator_id || validationFormData.responsible_id;
if (hasValidationValue) {
payload.pedimento_validation = {
validator: validationFormData.validator || null,
validation_ack: validationFormData.validation_ack || null,
pre_ack: validationFormData.pre_ack || null,
line_signature: validationFormData.line_signature || null,
electronic_signature: validationFormData.electronic_signature || null,
certificate_number: validationFormData.certificate_number || null,
validator_id: validationFormData.validator_id || null,
responsible_id: validationFormData.responsible_id || null
};
}
}
}
// Eliminar campos undefined para no enviarlos
Object.keys(payload).forEach(key => {
if (payload[key as keyof typeof payload] === undefined) {
@@ -140,9 +211,9 @@
let newPedimentoId = pedimentoId;
if (data.isCreate) {
if (data.isCreate) {
// Crear nuevo pedimento con todos sus sub-recursos
const response = await pedimentosApi.create(payload as CreatePedimentoData);
const response = await pedimentosApi.create(payload as CreatePedimentoData);
if (response.error) {
const errorMsg = typeof response.error === 'string' ? response.error : 'Error al crear el pedimento';
throw new Error(errorMsg);
@@ -153,12 +224,12 @@
// Redirigir a la página de edición
await goto(`/dashboard/pedimentos/edit/${newPedimentoId}`);
return;
} else {
} else {
// Actualizar pedimento existente con todos sus sub-recursos
const response = await pedimentosApi.update(pedimentoId!, payload as UpdatePedimentoData);
const response = await pedimentosApi.update(pedimentoId!, payload as UpdatePedimentoData);
if (response.error) throw new Error(response.error);
}
success = true;
setTimeout(() => {
success = false;
@@ -380,7 +451,7 @@
<Tabs.Content value="dates">
<DatesTabForm
pedimentoId={pedimentoId}
pedimento={data.pedimento}
bind:formData={datesFormData}
bind:exists={datesExists}
/>
@@ -388,7 +459,7 @@
<Tabs.Content value="payments">
<PaymentsTabForm
pedimentoId={pedimentoId}
pedimento={data.pedimento}
bind:formData={paymentsFormData}
bind:exists={paymentsExists}
/>
@@ -396,7 +467,7 @@
<Tabs.Content value="transport">
<TransportTabForm
pedimentoId={pedimentoId}
pedimento={data.pedimento}
bind:formData={transportFormData}
bind:exists={transportExists}
/>
@@ -404,7 +475,7 @@
<Tabs.Content value="validation">
<ValidationTabForm
pedimentoId={pedimentoId}
pedimento={data.pedimento}
bind:formData={validationFormData}
bind:exists={validationExists}
/>