feat: campos de usuario por su definición en SAP (valores válidos y tabla de usuario enlazada): endpoint sapdb/user-fields y campo udfField en cabeceras de documentos y maestros
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3caf94609d
commit
0629ce4068
17 files changed
+517
-11
No files matched your search
@@ -0,0 +1,72 @@
|
||||
import { ChangeDetectionStrategy, Component, computed, input, model, resource } from '@angular/core';
|
||||
import { UserFieldsApi, type UserFieldInfo } from '../../core/sl/user-fields';
|
||||
import type { VhLookup } from '../value-help/value-help.types';
|
||||
import { inject } from '@angular/core';
|
||||
import { SelectField, TextField } from './fields';
|
||||
import { FieldBase } from './field-base';
|
||||
import { LookupField } from './lookup-field';
|
||||
|
||||
/**
|
||||
* Campo de usuario de SAP (`U_*`) que se pide según como lo definió SAP: lista desplegable si tiene valores válidos,
|
||||
* ventana de selección si está enlazado a una tabla de usuario, texto en otro caso (o mientras carga, o si la base de datos
|
||||
* no está configurada). El tipo numérico se guarda como número.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'sbo-udf-field',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [LookupField, SelectField, TextField],
|
||||
template: `
|
||||
@if (kind() === 'select') {
|
||||
<sbo-select-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [options]="options()" placeholder="" [value]="str() || null" (valueChange)="emit($event)" />
|
||||
} @else if (kind() === 'lookup') {
|
||||
<sbo-lookup-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [lookup]="lookup()" [value]="str()" (valueChange)="emit($event)" resolveOnLeave />
|
||||
} @else {
|
||||
<sbo-text-field [label]="label()" [dbName]="dbName()" [required]="required()" [readonly]="readOnly()" [error]="error()" [value]="str()" (valueChange)="emit($event)" />
|
||||
}
|
||||
`,
|
||||
styles: ':host { display: block; }',
|
||||
})
|
||||
export class UdfField extends FieldBase {
|
||||
private readonly api = inject(UserFieldsApi);
|
||||
|
||||
/** Tabla del campo (`OBTN`, `OWTQ`, `@MI_TABLA`) y alias sin el `U_` (`SIS_ESTLOT`). */
|
||||
readonly table = input.required<string>();
|
||||
readonly alias = input.required<string>();
|
||||
readonly value = model<unknown>('');
|
||||
|
||||
protected readonly info = resource({
|
||||
params: () => ({ table: this.table(), alias: this.alias() }),
|
||||
loader: ({ params }) => this.api.get(params.table, params.alias),
|
||||
});
|
||||
private readonly def = computed<UserFieldInfo | null>(() => (this.info.hasValue() ? this.info.value() : null));
|
||||
|
||||
protected readonly kind = computed<'select' | 'lookup' | 'text'>(() => {
|
||||
const d = this.def();
|
||||
return d?.validValues.length ? 'select' : d?.linkedRows.length ? 'lookup' : 'text';
|
||||
});
|
||||
protected readonly str = computed(() => {
|
||||
const v = this.value();
|
||||
return v === null || v === undefined ? '' : String(v);
|
||||
});
|
||||
protected readonly options = computed(() => (this.def()?.validValues ?? []).map((v) => ({ value: v.value, label: v.description ? `${v.value} · ${v.description}` : v.value })));
|
||||
protected readonly lookup = computed<VhLookup>(() => {
|
||||
const d = this.def()!;
|
||||
return {
|
||||
title: d.description || d.linkedTable || 'Valores',
|
||||
resource: d.linkedTable ?? 'UserTable',
|
||||
columns: [
|
||||
{ key: 'code', title: 'Código', width: '140px', mono: true, searchable: true },
|
||||
{ key: 'name', title: 'Nombre', searchable: true },
|
||||
],
|
||||
rows: d.linkedRows.map((r) => ({ code: r.code, name: r.name })),
|
||||
valueKey: 'code',
|
||||
nameKey: 'name',
|
||||
codeWidth: '140px',
|
||||
};
|
||||
});
|
||||
|
||||
protected emit(v: string | number | null): void {
|
||||
const s = v === null ? '' : String(v);
|
||||
this.value.set(this.def()?.type === 'N' && s.trim() !== '' && Number.isFinite(Number(s)) ? Number(s) : s);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user