diff --git a/apps/web/src/app/features/masters/master-lookups.ts b/apps/web/src/app/features/masters/master-lookups.ts index c3ab9f1..88c90a2 100644 --- a/apps/web/src/app/features/masters/master-lookups.ts +++ b/apps/web/src/app/features/masters/master-lookups.ts @@ -13,18 +13,21 @@ export const MASTER_LOOKUPS = { orderby: 'Code', baseFilter: `Type eq '${type === 'cSupplier' ? 'bbpgt_VendorGroup' : 'bbpgt_CustomerGroup'}'`, valueType: 'number', + nameKey: 'Name', columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')], }), currency: { title: 'Monedas', resource: 'Currencies', orderby: 'Code', + nameKey: 'Name', columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')], } satisfies VhLookup, paymentTerms: { title: 'Condiciones de pago', resource: 'PaymentTermsTypes', orderby: 'GroupNumber', + nameKey: 'PaymentTermsGroupName', valueType: 'number', columns: [col('GroupNumber', 'Código', { width: '90px', mono: true }), col('PaymentTermsGroupName', 'Nombre')], } satisfies VhLookup, @@ -32,6 +35,7 @@ export const MASTER_LOOKUPS = { title: 'Listas de precios', resource: 'PriceLists', orderby: 'PriceListNo', + nameKey: 'PriceListName', valueType: 'number', columns: [col('PriceListNo', 'Código', { width: '90px', mono: true }), col('PriceListName', 'Nombre')], } satisfies VhLookup, @@ -39,6 +43,7 @@ export const MASTER_LOOKUPS = { title: 'Empleados de ventas', resource: 'SalesPersons', orderby: 'SalesEmployeeCode', + nameKey: 'SalesEmployeeName', valueType: 'number', baseFilter: `Active eq 'tYES'`, columns: [col('SalesEmployeeCode', 'Código', { width: '90px', mono: true }), col('SalesEmployeeName', 'Nombre')], @@ -51,12 +56,14 @@ export const MASTER_LOOKUPS = { resource: 'BusinessPartners', orderby: 'CardCode', baseFilter: `CardType eq 'cSupplier'`, + nameKey: 'CardName', columns: [col('CardCode', 'Código', { width: '130px', mono: true }), col('CardName', 'Nombre')], } satisfies VhLookup, itemGroup: { title: 'Grupos de artículos', resource: 'ItemGroups', orderby: 'Number', + nameKey: 'GroupName', valueType: 'number', columns: [col('Number', 'Código', { width: '90px', mono: true }), col('GroupName', 'Nombre')], } satisfies VhLookup, diff --git a/apps/web/src/app/shared/form/lookup-field.ts b/apps/web/src/app/shared/form/lookup-field.ts index fcb82f0..fe9f1a6 100644 --- a/apps/web/src/app/shared/form/lookup-field.ts +++ b/apps/web/src/app/shared/form/lookup-field.ts @@ -19,6 +19,9 @@ import { TextInput } from './controls'; import { FieldBase } from './field-base'; import { SboField } from './sbo-field'; +/** Nombres ya consultados de los códigos de las listas con `nameKey`. */ +const NAMES = new Map(); + /** * Campo con botón "…" que abre una lista de valores (flecha dorada de SAP). * Escribir el código a mano también es válido; elegir de la lista lo rellena y emite `picked`. @@ -56,6 +59,9 @@ import { SboField } from './sbo-field'; > … + @if (name()) { + {{ name() }} + } `, - styles: ':host { display: block; }', + styles: ` + :host { display: block; } + .name { align-self: center; margin-left: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--quiet); } + `, }) export class LookupField extends FieldBase { readonly value = model(''); @@ -96,6 +105,10 @@ export class LookupField extends FieldBase { private resolved = ''; private readonly box = viewChild.required('box'); + /** Nombre de lo elegido, junto al código (`lookup.nameKey`). */ + protected readonly name = signal(''); + private nameFor = ''; + /** El usuario está escribiendo: se muestra lo que escribe y no el texto con que la lista presenta el código guardado. */ private readonly editing = signal(false); /** @@ -117,10 +130,30 @@ export class LookupField extends FieldBase { if (!this.editing()) { if (codes && v !== '') codes.ensure([v]); this.resolved = v.trim(); + void this.loadName(v.trim()); } }); } + /** El nombre del código guardado; se pregunta una vez por código (el resultado queda en `NAMES`). */ + private async loadName(code: string): Promise { + const lookup = this.lookup(); + const nameKey = lookup.nameKey; + this.nameFor = code; + if (!nameKey || !code) return void this.name.set(''); + const cacheKey = `${lookup.resource}|${lookup.baseFilter ?? ''}|${code}`; + const cached = NAMES.get(cacheKey); + if (cached !== undefined) return void this.name.set(cached); + try { + const row = await this.injector.get(SlLookupApi).find(lookup, code); + const text = row ? String(row[nameKey] ?? '') : ''; + NAMES.set(cacheKey, text); + if (this.nameFor === code) this.name.set(text); + } catch { + if (this.nameFor === code) this.name.set(''); + } + } + protected typing(text: string): void { this.editing.set(true); this.value.set(text); @@ -145,6 +178,11 @@ export class LookupField extends FieldBase { const key = this.lookup().valueKey ?? this.lookup().columns[0]?.key ?? ''; this.missing.set(null); this.lookup().codes?.remember(row); + const nameKey = this.lookup().nameKey; + if (nameKey) { + this.nameFor = String(row[this.lookup().valueKey ?? this.lookup().columns[0]?.key ?? ''] ?? ''); + this.name.set(String(row[nameKey] ?? '')); + } this.editing.set(false); this.value.set(String(row[key] ?? '')); this.resolved = this.value(); diff --git a/apps/web/src/app/shared/value-help/value-help.types.ts b/apps/web/src/app/shared/value-help/value-help.types.ts index 620d70e..234ee24 100644 --- a/apps/web/src/app/shared/value-help/value-help.types.ts +++ b/apps/web/src/app/shared/value-help/value-help.types.ts @@ -24,6 +24,8 @@ export interface VhLookup { rows?: readonly VhRow[]; /** Otros campos por los que se reconoce un código escrito a mano (`FormatCode` de una cuenta: el usuario no conoce el `_SYS…` interno). */ alsoMatch?: readonly string[]; + /** Columna con el nombre de lo elegido: el campo lo muestra junto al código (`Name` de un grupo, `SalesEmployeeName`). */ + nameKey?: string; /** Cómo se muestra el código guardado en una celda (la cuenta con su formato) y cómo se aprenden los de las filas elegidas. */ codes?: CodeDisplay; }