Merge pull request 'fix/uso-de-catalogo-sectores-empresa' (#471) from fix/uso-de-catalogo-sectores-empresa into development

Reviewed-on: ADUANASOFT/anexo76#471
This commit is contained in:
2026-06-02 17:14:35 +00:00
3 changed files with 88 additions and 4 deletions

View File

@@ -0,0 +1,37 @@
"""company prosec boolean to integer
Revision ID: 506969b0a256
Revises: a7b8c9d0e1f2
Create Date: 2026-06-02 00:00:00.000000
"""
from typing import Sequence, Union
from alembic import op
revision: str = "506969b0a256"
down_revision: Union[str, None] = "a7b8c9d0e1f2"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# Convierte prosec de boolean a integer para almacenar el ID del sector PROSEC.
# El default 'false' debe eliminarse antes de cambiar el tipo.
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec DROP DEFAULT")
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec DROP NOT NULL")
op.execute(
"ALTER TABLE a76.company ALTER COLUMN prosec TYPE integer USING prosec::int"
)
def downgrade() -> None:
op.execute(
"""
ALTER TABLE a76.company
ALTER COLUMN prosec TYPE boolean
USING CASE WHEN prosec IS NULL OR prosec = 0 THEN false ELSE true END
"""
)
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec SET DEFAULT false")
op.execute("ALTER TABLE a76.company ALTER COLUMN prosec SET NOT NULL")

View File

@@ -39,7 +39,7 @@ class Company(Base, TimestampMixin):
# Programa
program: Mapped[Optional[str]] = mapped_column(String(7))
program_number: Mapped[Optional[str]] = mapped_column(String(40))
prosec: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false")
prosec: Mapped[Optional[int]] = mapped_column(Integer, nullable=True, default=None)
prosec_authorization: Mapped[Optional[str]] = mapped_column(String(20))
# Sectores

View File

@@ -11,6 +11,7 @@
import * as Card from '$lib/components/ui/card';
import CountrySelectorDialog from '$lib/components/dashboard/goods/modales/country-selector-dialog.svelte';
import StateSelectorDialog from '$lib/components/dashboard/shared/modals/state-selector-dialog.svelte';
import SectorSelectorDialog from '$lib/components/dashboard/shared/modals/sector-selector-dialog.svelte';
import {
createCompany,
updateCompany,
@@ -19,6 +20,7 @@
uploadCompanyCertificate,
type Company
} from '$lib/api/dashboard/a76/general_catalogs/company';
import { sectorsApi } from '$lib/api/dashboard/reference_data/sectors';
import { companyStore } from '$lib/stores/company.svelte';
import { getBackendAssetUrl, getFileDisplayName } from '$lib/utils';
import { toDbDate, toInputDate } from '$lib/utils/date';
@@ -37,7 +39,8 @@
Key,
ShieldCheck,
FileSignature,
Ban
Ban,
Factory
} from 'lucide-svelte';
import { useShortcuts } from '$lib/hooks/use-shortcuts';
@@ -64,6 +67,8 @@
let activeCountryField = $state<'main_country' | 'ind1_country' | 'ind2_country'>('main_country');
let stateModalOpen = $state(false);
let activeStateField = $state<'main_state' | 'ind1_state' | 'ind2_state'>('main_state');
let sectorModalOpen = $state(false);
let prosecDisplay = $state('');
let logoFile = $state<File | null>(null);
let logoPreview = $state<string | null>(null);
@@ -408,6 +413,21 @@
cancel_key_exp: item.cancel_key_exp || 0
};
// Resolver el sector PROSEC contra el catálogo para mostrar KEY - Descripción
if (item.prosec) {
const companyId = companyStore.activeCompany?.id;
if (companyId) {
const sectorResp = await sectorsApi.get(item.prosec, companyId);
prosecDisplay = sectorResp.data
? `${sectorResp.data.key} - ${sectorResp.data.description}`
: String(item.prosec); // fallback al ID si el sector no se encontró
} else {
prosecDisplay = String(item.prosec);
}
} else {
prosecDisplay = '';
}
// Guardar la URL del logo actual si existe
if (item.logo) {
currentLogo = item.logo;
@@ -447,6 +467,11 @@
formData[relatedCountryField] = state.m3_key;
}
function handleSectorSelect(sector: { id: number; key: string; description: string }) {
formData.prosec = sector.id;
prosecDisplay = `${sector.key} - ${sector.description}`;
}
function handleLogoChange(event: Event) {
const target = event.target as HTMLInputElement;
const file = target.files?.[0];
@@ -902,8 +927,25 @@
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="grid gap-2">
<Label for="prosec">Sector PROSEC (ID)</Label>
<Input id="prosec" type="number" bind:value={formData.prosec} />
<Label for="prosec">Sector PROSEC</Label>
<div class="flex gap-2">
<Input
id="prosec"
value={prosecDisplay}
placeholder="Seleccionar sector..."
readonly
/>
<Button
type="button"
variant="outline"
size="icon"
onclick={() => (sectorModalOpen = true)}
disabled={loading}
title="Buscar Sector"
>
<Factory class="h-4 w-4" />
</Button>
</div>
</div>
<div class="grid gap-2">
<Label for="prosec_auth">Autorización PROSEC</Label>
@@ -2044,4 +2086,9 @@
<CountrySelectorDialog bind:open={countryModalOpen} onSelect={handleCountrySelect} />
<StateSelectorDialog bind:open={stateModalOpen} onSelect={handleStateSelect} />
<SectorSelectorDialog
bind:open={sectorModalOpen}
onSelect={handleSectorSelect}
onClear={() => { formData.prosec = 0; prosecDisplay = ''; }}
/>
{/if}