Merge pull request 'fix/clases_activo_fijo' (#174) from fix/clases_activo_fijo into development

Reviewed-on: ADUANASOFT/anexo76#174
This commit is contained in:
2026-02-27 16:55:14 +00:00
6 changed files with 72 additions and 3 deletions

View File

@@ -221,6 +221,10 @@ class ClassWithFADataResponse(BaseModel):
# FA-specific fields (embedded from a24.fa_classes)
fa_class_id: Optional[int] = None
import_tariff_code: Optional[str] = None
import_tariff_type: Optional[str] = None
export_tariff_code: Optional[str] = None
export_tariff_type: Optional[str] = None
depreciation_rate: Optional[Decimal] = None
fda_code: Optional[str] = None
eccn_code: Optional[str] = None

View File

@@ -150,6 +150,10 @@ class ClassService:
"updated_at": base_class.updated_at,
# FA extension fields (None if no FA record exists)
"fa_class_id": fa_class.id if fa_class else None,
"import_tariff_code": fa_class.import_tariff_code if fa_class else None,
"import_tariff_type": fa_class.import_tariff_type if fa_class else None,
"export_tariff_code": fa_class.export_tariff_code if fa_class else None,
"export_tariff_type": fa_class.export_tariff_type if fa_class else None,
"depreciation_rate": fa_class.depreciation_rate if fa_class else None,
"fda_code": fa_class.fda_code if fa_class else None,
"eccn_code": fa_class.eccn_code if fa_class else None,

View File

@@ -23,7 +23,60 @@ class USTariffFractionService:
limit: int = 100,
filters: Optional[Dict[str, Any]] = None,
) -> Tuple[List[USTariffFraction], int]:
"""Obtiene todas las fracciones locales con filtros opcionales."""
"""
Obtiene todas las fracciones arancelarias americanas con filtros opcionales.
Estrategia: Sitar API -> Fallback Local DB
"""
# 1. Try Sitar API
try:
sitar_service = FraccionesUSAService.get_instance()
sitar_fraccion = None
has_filters = False
if filters and filters.get("search"):
term = filters["search"]
# Sitar only filters by fraction code
if term.replace(".", "").isdigit():
sitar_fraccion = term
has_filters = True
sitar_items = await sitar_service.search(
fraccion=sitar_fraccion,
skip=skip,
limit=limit
)
# If Sitar returns empty list, attempt fallback to local DB
if not sitar_items:
logger.info(f"Sitar returned no results for USA query (filters={has_filters}). Attempting fallback to local DB.")
return USTariffFractionService._get_all_local(db, tenant_id, company_id, skip, limit, filters)
# Map items
items = [USTariffFractionMapper.to_domain(item, tenant_id, company_id) for item in sitar_items]
# Estimate total
total = len(items) + skip
if len(items) == limit:
total += 1
return items, total
except Exception as e:
logger.error(f"Error fetching USA Fractions from Sitar API, falling back to local DB: {e}")
return USTariffFractionService._get_all_local(db, tenant_id, company_id, skip, limit, filters)
@staticmethod
def _get_all_local(
db: Session,
tenant_id: int,
company_id: int,
skip: int = 0,
limit: int = 100,
filters: Optional[Dict[str, Any]] = None,
) -> Tuple[List[USTariffFraction], int]:
"""Lógica original de consulta local"""
query = db.query(USTariffFraction).filter(
USTariffFraction.tenant_id == tenant_id,
USTariffFraction.company_id == company_id,

View File

@@ -270,7 +270,7 @@ async function fetchApi<T = any>(
}
return {
error: data.message || data.detail || 'Error en la petición',
error: data.message || (typeof data.detail === 'string' ? data.detail : JSON.stringify(data.detail)) || 'Error en la petición',
status: response.status
};
}

View File

@@ -541,7 +541,7 @@
class="uppercase {validationErrors.class_code
? 'border-red-500 focus-visible:ring-red-500'
: ''}"
maxlength={20}
maxlength={8}
oninput={() => {
if (validationErrors.class_code) {
const errors = { ...validationErrors };

View File

@@ -14,6 +14,10 @@
// Tipo extendido que combina A76Class y FAClass
interface FixedAssetClassExtended extends A76Class {
fa_class_id?: number;
import_tariff_code?: string | null;
import_tariff_type?: string | null;
export_tariff_code?: string | null;
export_tariff_type?: string | null;
depreciation_rate?: number | null;
fda_code?: string | null;
eccn_code?: string | null;
@@ -578,6 +582,10 @@
cleanData.depreciation_rate != null
? Number(cleanData.depreciation_rate)
: null,
import_tariff_code: cleanData.import_tariff_code || null,
import_tariff_type: cleanData.import_tariff_type || null,
export_tariff_code: cleanData.export_tariff_code || null,
export_tariff_type: cleanData.export_tariff_type || null,
fda_code: (cleanData.fda_key ?? cleanData.fda_code) || null,
eccn_code: cleanData.eccn_code || null
},