feat(web): los campos de lista de los maestros muestran el nombre junto al código (grupo, moneda, empleado de ventas, condición de pago, lista de precios, grupo de artículos, proveedor)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f985667b90
commit
9e98160d01
3 files changed
+48
-1
No files matched your search
@@ -13,18 +13,21 @@ export const MASTER_LOOKUPS = {
|
|||||||
orderby: 'Code',
|
orderby: 'Code',
|
||||||
baseFilter: `Type eq '${type === 'cSupplier' ? 'bbpgt_VendorGroup' : 'bbpgt_CustomerGroup'}'`,
|
baseFilter: `Type eq '${type === 'cSupplier' ? 'bbpgt_VendorGroup' : 'bbpgt_CustomerGroup'}'`,
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
|
nameKey: 'Name',
|
||||||
columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')],
|
columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')],
|
||||||
}),
|
}),
|
||||||
currency: {
|
currency: {
|
||||||
title: 'Monedas',
|
title: 'Monedas',
|
||||||
resource: 'Currencies',
|
resource: 'Currencies',
|
||||||
orderby: 'Code',
|
orderby: 'Code',
|
||||||
|
nameKey: 'Name',
|
||||||
columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')],
|
columns: [col('Code', 'Código', { width: '90px', mono: true }), col('Name', 'Nombre')],
|
||||||
} satisfies VhLookup,
|
} satisfies VhLookup,
|
||||||
paymentTerms: {
|
paymentTerms: {
|
||||||
title: 'Condiciones de pago',
|
title: 'Condiciones de pago',
|
||||||
resource: 'PaymentTermsTypes',
|
resource: 'PaymentTermsTypes',
|
||||||
orderby: 'GroupNumber',
|
orderby: 'GroupNumber',
|
||||||
|
nameKey: 'PaymentTermsGroupName',
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
columns: [col('GroupNumber', 'Código', { width: '90px', mono: true }), col('PaymentTermsGroupName', 'Nombre')],
|
columns: [col('GroupNumber', 'Código', { width: '90px', mono: true }), col('PaymentTermsGroupName', 'Nombre')],
|
||||||
} satisfies VhLookup,
|
} satisfies VhLookup,
|
||||||
@@ -32,6 +35,7 @@ export const MASTER_LOOKUPS = {
|
|||||||
title: 'Listas de precios',
|
title: 'Listas de precios',
|
||||||
resource: 'PriceLists',
|
resource: 'PriceLists',
|
||||||
orderby: 'PriceListNo',
|
orderby: 'PriceListNo',
|
||||||
|
nameKey: 'PriceListName',
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
columns: [col('PriceListNo', 'Código', { width: '90px', mono: true }), col('PriceListName', 'Nombre')],
|
columns: [col('PriceListNo', 'Código', { width: '90px', mono: true }), col('PriceListName', 'Nombre')],
|
||||||
} satisfies VhLookup,
|
} satisfies VhLookup,
|
||||||
@@ -39,6 +43,7 @@ export const MASTER_LOOKUPS = {
|
|||||||
title: 'Empleados de ventas',
|
title: 'Empleados de ventas',
|
||||||
resource: 'SalesPersons',
|
resource: 'SalesPersons',
|
||||||
orderby: 'SalesEmployeeCode',
|
orderby: 'SalesEmployeeCode',
|
||||||
|
nameKey: 'SalesEmployeeName',
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
baseFilter: `Active eq 'tYES'`,
|
baseFilter: `Active eq 'tYES'`,
|
||||||
columns: [col('SalesEmployeeCode', 'Código', { width: '90px', mono: true }), col('SalesEmployeeName', 'Nombre')],
|
columns: [col('SalesEmployeeCode', 'Código', { width: '90px', mono: true }), col('SalesEmployeeName', 'Nombre')],
|
||||||
@@ -51,12 +56,14 @@ export const MASTER_LOOKUPS = {
|
|||||||
resource: 'BusinessPartners',
|
resource: 'BusinessPartners',
|
||||||
orderby: 'CardCode',
|
orderby: 'CardCode',
|
||||||
baseFilter: `CardType eq 'cSupplier'`,
|
baseFilter: `CardType eq 'cSupplier'`,
|
||||||
|
nameKey: 'CardName',
|
||||||
columns: [col('CardCode', 'Código', { width: '130px', mono: true }), col('CardName', 'Nombre')],
|
columns: [col('CardCode', 'Código', { width: '130px', mono: true }), col('CardName', 'Nombre')],
|
||||||
} satisfies VhLookup,
|
} satisfies VhLookup,
|
||||||
itemGroup: {
|
itemGroup: {
|
||||||
title: 'Grupos de artículos',
|
title: 'Grupos de artículos',
|
||||||
resource: 'ItemGroups',
|
resource: 'ItemGroups',
|
||||||
orderby: 'Number',
|
orderby: 'Number',
|
||||||
|
nameKey: 'GroupName',
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
columns: [col('Number', 'Código', { width: '90px', mono: true }), col('GroupName', 'Nombre')],
|
columns: [col('Number', 'Código', { width: '90px', mono: true }), col('GroupName', 'Nombre')],
|
||||||
} satisfies VhLookup,
|
} satisfies VhLookup,
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ import { TextInput } from './controls';
|
|||||||
import { FieldBase } from './field-base';
|
import { FieldBase } from './field-base';
|
||||||
import { SboField } from './sbo-field';
|
import { SboField } from './sbo-field';
|
||||||
|
|
||||||
|
/** Nombres ya consultados de los códigos de las listas con `nameKey`. */
|
||||||
|
const NAMES = new Map<string, string>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Campo con botón "…" que abre una lista de valores (flecha dorada de SAP).
|
* 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`.
|
* 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';
|
|||||||
>
|
>
|
||||||
…
|
…
|
||||||
</button>
|
</button>
|
||||||
|
@if (name()) {
|
||||||
|
<span class="name" [attr.title]="name()">{{ name() }}</span>
|
||||||
|
}
|
||||||
</sbo-field>
|
</sbo-field>
|
||||||
<sbo-value-help
|
<sbo-value-help
|
||||||
[open]="listOpen()"
|
[open]="listOpen()"
|
||||||
@@ -70,7 +76,10 @@ import { SboField } from './sbo-field';
|
|||||||
(closed)="closeList()"
|
(closed)="closeList()"
|
||||||
/>
|
/>
|
||||||
`,
|
`,
|
||||||
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 {
|
export class LookupField extends FieldBase {
|
||||||
readonly value = model('');
|
readonly value = model('');
|
||||||
@@ -96,6 +105,10 @@ export class LookupField extends FieldBase {
|
|||||||
private resolved = '';
|
private resolved = '';
|
||||||
private readonly box = viewChild.required<TextInput>('box');
|
private readonly box = viewChild.required<TextInput>('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. */
|
/** 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);
|
private readonly editing = signal(false);
|
||||||
/**
|
/**
|
||||||
@@ -117,10 +130,30 @@ export class LookupField extends FieldBase {
|
|||||||
if (!this.editing()) {
|
if (!this.editing()) {
|
||||||
if (codes && v !== '') codes.ensure([v]);
|
if (codes && v !== '') codes.ensure([v]);
|
||||||
this.resolved = v.trim();
|
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<void> {
|
||||||
|
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 {
|
protected typing(text: string): void {
|
||||||
this.editing.set(true);
|
this.editing.set(true);
|
||||||
this.value.set(text);
|
this.value.set(text);
|
||||||
@@ -145,6 +178,11 @@ export class LookupField extends FieldBase {
|
|||||||
const key = this.lookup().valueKey ?? this.lookup().columns[0]?.key ?? '';
|
const key = this.lookup().valueKey ?? this.lookup().columns[0]?.key ?? '';
|
||||||
this.missing.set(null);
|
this.missing.set(null);
|
||||||
this.lookup().codes?.remember(row);
|
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.editing.set(false);
|
||||||
this.value.set(String(row[key] ?? ''));
|
this.value.set(String(row[key] ?? ''));
|
||||||
this.resolved = this.value();
|
this.resolved = this.value();
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export interface VhLookup {
|
|||||||
rows?: readonly VhRow[];
|
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). */
|
/** 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[];
|
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. */
|
/** 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;
|
codes?: CodeDisplay;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user