Merge branch 'main' into cliente/tagumedica

This commit is contained in:
George committed 2026-10-20 09:09:45 -05:00
commit 074eed6d81
14 files changed
+132 -56

No files matched your search

+1 -1
View File
@@ -60,7 +60,7 @@ Módulo genérico `apps/api/src/sapdb/` (en `main`, opcional como el Gateway): e
## Ver el nombre del campo de SAP («Campos»)
El mini-erp mostraba el nombre del campo de la base junto a cada casillero (`dbField`). Aquí es general: el botón **Campos** de la barra superior (`FieldNames`, se recuerda en `localStorage` `erp_fields`) muestra, debajo de cada etiqueta y en la cabecera de las tablas (listas, líneas de documento, tablas de filas), el nombre con el que el Service Layer lee y guarda el campo (`ItemCode`, `U_SIS_ESTLOT`); sin activarlo, el nombre sale siempre como ayuda al pasar el cursor. Los campos lo reciben con `dbName` (`FieldBase`/`SboField`); los formularios de maestros y documentos lo pasan solos desde su configuración declarativa. Pendiente: los formularios de pagos y de asientos (sus campos están escritos a mano) y las filas con varios controles (folio, grupos).
El mini-erp mostraba el nombre del campo de la base junto a cada casillero (`dbField`). Aquí es general: el botón **Campos** de la barra superior (`FieldNames`, se recuerda en `localStorage` `erp_fields`) muestra, debajo de cada etiqueta y en la cabecera de las tablas (listas, líneas de documento, tablas de filas), el nombre con el que el Service Layer lee y guarda el campo (`ItemCode`, `U_SIS_ESTLOT`); sin activarlo, el nombre sale siempre como ayuda al pasar el cursor. Los campos lo reciben con `dbName` (`FieldBase`/`SboField`); los formularios de maestros y documentos lo pasan solos desde su configuración declarativa. Cubre los formularios de maestros, de documentos (incluidas las filas con varios controles: `FolioPrefixString · FolioNumber`, `DocCurrency · DocRate`…, con `fieldDbName` en `document-layouts.ts`), de pagos y de asientos (sus campos van escritos a mano en el HTML con `dbName="…"`: un campo nuevo debe llevarlo) y las cabeceras de tablas. Solo se muestran como campos de SAP los nombres que empiezan con mayúscula (`isSapField`): las columnas internas de la interfaz (`docNum`, `_Name`) no.
## Cómo verificar cambios de interfaz
+28 -1
View File
@@ -2,7 +2,8 @@ import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { beforeEach, describe, expect, it } from 'vitest';
import { TextField } from '../shared/form';
import { FieldNames } from './field-names';
import { fieldDbName, type HeaderField } from '../features/documents/document-layouts';
import { FieldNames, isSapField } from './field-names';
@Component({ imports: [TextField], template: '<sbo-text-field label="Descripción" dbName="ItemName" [value]="\'x\'" />' })
class Host {}
@@ -32,3 +33,29 @@ describe('Ver campos', () => {
expect(TestBed.inject(FieldNames).show()).toBe(true);
});
});
describe('nombre del campo de una fila del formulario', () => {
const name = (f: HeaderField) => fieldDbName(f);
it('un campo sencillo muestra su campo y una fila con varios controles los muestra todos', () => {
expect(name({ type: 'text', key: 'NumAtCard', label: 'Nº de referencia' })).toBe('NumAtCard');
expect(name({ type: 'folio', label: 'Folio', prefixKey: 'FolioPrefixString', numberKey: 'FolioNumber' })).toBe('FolioPrefixString · FolioNumber');
expect(name({ type: 'group', label: 'Indicador', cells: [{ kind: 'text', key: 'Indicator', label: 'I' }, { kind: 'text', key: 'FolioPrefixString', label: 'P' }] })).toBe('Indicator · FolioPrefixString');
expect(name({ type: 'series', key: 'Series', label: 'Número' })).toBe('Series · DocNum');
expect(name({ type: 'currency', label: 'Moneda' })).toBe('DocCurrency · DocRate');
expect(name({ type: 'rounding', label: 'Redondeo' })).toBe('Rounding · RoundingDiffAmount');
});
it('los valores calculados muestran de dónde salen', () => {
expect(name({ type: 'computed', label: 'Total', source: 'total' })).toBe('DocTotal');
expect(name({ type: 'computed', label: 'Saldo', source: 'balance' })).toBe('DocTotal − PaidToDate');
});
});
describe('qué columnas son campos de SAP', () => {
it('los de SAP empiezan con mayúscula; los internos de la interfaz, no', () => {
for (const k of ['ItemCode', 'U_SIS_ESTLOT', 'AccounttNum']) expect(isSapField(k), k).toBe(true);
for (const k of ['docNum', 'balance', '_Name', '_manageBatches']) expect(isSapField(k), k).toBe(false);
});
});
+3
View File
@@ -2,6 +2,9 @@ import { Injectable, signal } from '@angular/core';
const KEY = 'erp_fields';
/** Un nombre de campo de SAP empieza con mayúscula (`ItemCode`, `U_SIS_X`); los de columnas internas de la interfaz (`docNum`, `_Name`) no. */
export const isSapField = (key: string): boolean => /^[A-Z]/.test(key);
/**
* «Ver campos»: muestra, junto a cada etiqueta, el nombre del campo de SAP (`ItemCode`, `U_SIS_ESTLOT`) con el que se lee
* y se guarda. Útil para quien configura el sistema o arma una consulta; el nombre también sale siempre como ayuda al
@@ -11,10 +11,10 @@
<sbo-window [title]="windowTitle()" [badge]="badge()" [status]="status()">
<div class="sbo-hdr">
<div class="sbo-col">
<sbo-select-field label="Pago a" [options]="typeOptions" [value]="docType()" (valueChange)="onType($event)" [readonly]="saved()" />
<sbo-select-field label="Pago a" dbName="DocType" [options]="typeOptions" [value]="docType()" (valueChange)="onType($event)" [readonly]="saved()" />
@if (!toAccounts()) {
<sbo-lookup-field
[label]="screen.partner.label"
[label]="screen.partner.label" dbName="CardCode"
[lookup]="partnerLookup"
[value]="cardCode()"
[readonly]="saved()"
@@ -23,17 +23,17 @@
(valueChange)="onPartnerText($event)"
(picked)="onPartner($event)"
/>
<sbo-text-field label="Nombre" [value]="cardName()" readonly />
<sbo-text-field label="Nombre" dbName="CardName" [value]="cardName()" readonly />
}
</div>
<div class="sbo-col">
@if (isNew()) {
<sbo-select-field label="Serie" [options]="seriesOptions()" [value]="series()" (valueChange)="series.set($event === null ? null : +$event)" />
<sbo-select-field label="Serie" dbName="Series" [options]="seriesOptions()" [value]="series()" (valueChange)="series.set($event === null ? null : +$event)" />
} @else {
<sbo-text-field label="Número" [value]="'' + (doc()?.['DocNum'] ?? '')" readonly />
<sbo-text-field label="Número" dbName="DocNum" [value]="'' + (doc()?.['DocNum'] ?? '')" readonly />
}
<sbo-date-field label="Fecha de contabilización" [(value)]="docDate" [readonly]="saved()" required />
<sbo-date-field label="Fecha del documento" [(value)]="taxDate" [readonly]="saved()" />
<sbo-date-field label="Fecha de contabilización" dbName="DocDate" [(value)]="docDate" [readonly]="saved()" required />
<sbo-date-field label="Fecha del documento" dbName="TaxDate" [(value)]="taxDate" [readonly]="saved()" />
</div>
</div>
@@ -66,15 +66,15 @@
<h3>Medios de pago</h3>
<div class="sbo-hdr">
<div class="sbo-col">
<sbo-lookup-field label="Cuenta de efectivo" [lookup]="accountLookup" [value]="means().cashAccount" (valueChange)="setMeans({ cashAccount: $event })" [readonly]="saved()" />
<sbo-number-field label="Efectivo" [decimals]="2" [value]="means().cashSum" (valueChange)="setMeans({ cashSum: $event })" [readonly]="saved()" />
<sbo-lookup-field label="Cuenta de transferencia" [lookup]="accountLookup" [value]="means().transferAccount" (valueChange)="setMeans({ transferAccount: $event })" [readonly]="saved()" />
<sbo-number-field label="Transferencia" [decimals]="2" [value]="means().transferSum" (valueChange)="setMeans({ transferSum: $event })" [readonly]="saved()" />
<sbo-lookup-field label="Cuenta de efectivo" dbName="CashAccount" [lookup]="accountLookup" [value]="means().cashAccount" (valueChange)="setMeans({ cashAccount: $event })" [readonly]="saved()" />
<sbo-number-field label="Efectivo" dbName="CashSum" [decimals]="2" [value]="means().cashSum" (valueChange)="setMeans({ cashSum: $event })" [readonly]="saved()" />
<sbo-lookup-field label="Cuenta de transferencia" dbName="TransferAccount" [lookup]="accountLookup" [value]="means().transferAccount" (valueChange)="setMeans({ transferAccount: $event })" [readonly]="saved()" />
<sbo-number-field label="Transferencia" dbName="TransferSum" [decimals]="2" [value]="means().transferSum" (valueChange)="setMeans({ transferSum: $event })" [readonly]="saved()" />
</div>
<div class="sbo-col">
<sbo-date-field label="Fecha de transferencia" [value]="means().transferDate" (valueChange)="setMeans({ transferDate: $event })" [readonly]="saved()" />
<sbo-text-field label="Referencia" [value]="means().transferReference" (valueChange)="setMeans({ transferReference: $event })" [readonly]="saved()" />
<sbo-lookup-field label="Cuenta de cheques" [lookup]="accountLookup" [value]="means().checkAccount" (valueChange)="setMeans({ checkAccount: $event })" [readonly]="saved()" />
<sbo-date-field label="Fecha de transferencia" dbName="TransferDate" [value]="means().transferDate" (valueChange)="setMeans({ transferDate: $event })" [readonly]="saved()" />
<sbo-text-field label="Referencia" dbName="TransferReference" [value]="means().transferReference" (valueChange)="setMeans({ transferReference: $event })" [readonly]="saved()" />
<sbo-lookup-field label="Cuenta de cheques" dbName="CheckAccount" [lookup]="accountLookup" [value]="means().checkAccount" (valueChange)="setMeans({ checkAccount: $event })" [readonly]="saved()" />
</div>
</div>
@@ -94,8 +94,8 @@
<div class="sbo-hdr" style="margin-top: 14px">
<div class="sbo-col">
<sbo-textarea-field label="Comentarios" [(value)]="remarks" [readonly]="saved()" />
<sbo-text-field label="Comentarios del asiento" [(value)]="journalRemarks" [readonly]="saved()" />
<sbo-textarea-field label="Comentarios" dbName="Remarks" [(value)]="remarks" [readonly]="saved()" />
<sbo-text-field label="Comentarios del asiento" dbName="JournalRemarks" [(value)]="journalRemarks" [readonly]="saved()" />
</div>
<div class="sbo-col">
<table class="totals">
@@ -133,7 +133,7 @@
@switch (f.type) {
@case ('partner') {
<sbo-lookup-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[required]="!!f.required"
[readonly]="readOnly() || !isNew() || locked(f)"
[value]="str(header()[f.key])"
@@ -145,7 +145,7 @@
}
@case ('checkbox') {
<sbo-checkbox-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[readonly]="readOnly() || !!f.readonly || locked(f)"
[value]="header()[f.key] === 'tYES'"
(valueChange)="setHeader(f.key, $event ? 'tYES' : 'tNO')"
@@ -153,7 +153,7 @@
}
@case ('lookup') {
<sbo-lookup-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[required]="!!f.required"
[readonly]="readOnly() || locked(f)"
[value]="str(header()[f.key])"
@@ -165,7 +165,7 @@
}
@case ('warehouse') {
<sbo-lookup-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[required]="!!f.required"
[readonly]="readOnly() || locked(f)"
[value]="str(header()[f.key])"
@@ -176,7 +176,7 @@
}
@case ('date') {
<sbo-date-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[required]="!!f.required"
[readonly]="readOnly() || locked(f)"
[value]="str(header()[f.key])"
@@ -185,7 +185,7 @@
}
@case ('select') {
<sbo-select-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[required]="!!f.required"
[readonly]="readOnly() || locked(f)"
[options]="f.options"
@@ -196,7 +196,7 @@
}
@case ('number') {
<sbo-number-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[decimals]="f.decimals"
[readonly]="readOnly() || locked(f)"
[value]="+str(header()[f.key])"
@@ -205,14 +205,14 @@
}
@case ('textarea') {
<sbo-textarea-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[readonly]="readOnly() || locked(f)"
[value]="str(header()[f.key])"
(valueChange)="setHeader(f.key, $event)"
/>
}
@case ('folio') {
<sbo-field [label]="f.label" [dbName]="f.key">
<sbo-field [label]="f.label" [dbName]="dbNames(f)">
<sbo-input
width="90px"
[maxlength]="10"
@@ -229,7 +229,7 @@
</sbo-field>
}
@case ('group') {
<sbo-field [label]="f.label" [dbName]="f.key">
<sbo-field [label]="f.label" [dbName]="dbNames(f)">
@for (c of f.cells; track c.key) {
<sbo-input
[width]="c.width"
@@ -246,7 +246,7 @@
</sbo-field>
}
@case ('series') {
<sbo-field [label]="f.label" [dbName]="f.key">
<sbo-field [label]="f.label" [dbName]="dbNames(f)">
<sbo-select
width="170px"
ariaLabel="Serie de numeración"
@@ -261,7 +261,7 @@
}
@case ('expenses') {
<div class="exp">
<h3>{{ f.label }}</h3>
<h3 [attr.title]="dbNames(f)">{{ f.label }}</h3>
<sbo-rows-table
[columns]="expenseColumns"
[rows]="expenses()"
@@ -277,7 +277,7 @@
}
@case ('contact') {
<sbo-select-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[readonly]="readOnly() || locked(f)"
[options]="contactOptions()"
placeholder=""
@@ -287,7 +287,7 @@
}
@case ('address') {
<sbo-select-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[readonly]="readOnly() || locked(f)"
[options]="f.side === 'ship' ? shipOptions() : billOptions()"
placeholder=""
@@ -302,7 +302,7 @@
</sbo-field>
}
@case ('currency') {
<sbo-field [label]="f.label" [dbName]="f.key">
<sbo-field [label]="f.label" [dbName]="dbNames(f)">
<sbo-select
width="170px"
ariaLabel="Moneda del documento"
@@ -322,7 +322,7 @@
}
@case ('rounding') {
@if (roundingEnabled()) {
<sbo-field [label]="f.label" [dbName]="f.key">
<sbo-field [label]="f.label" [dbName]="dbNames(f)">
<sbo-checkbox
ariaLabel="Redondear el total del documento"
[readonly]="readOnly() || locked(f)"
@@ -340,11 +340,11 @@
}
}
@case ('computed') {
<sbo-text-field [label]="f.label" [dbName]="f.key" readonly [value]="computedValue(f.source)" />
<sbo-text-field [label]="f.label" [dbName]="dbNames(f)" readonly [value]="computedValue(f.source)" />
}
@default {
<sbo-text-field
[label]="f.label" [dbName]="f.key"
[label]="f.label" [dbName]="dbNames(f)"
[readonly]="readOnly() || !!f.readonly || locked(f)"
[value]="str(header()[f.key])"
(valueChange)="setHeader(f.key, $event)"
@@ -35,7 +35,7 @@ import {
validateLayout,
} from './document-model';
import { SERVICE_DOC_TYPE } from './document-layouts';
import { type ComputedSource, type GroupCell, type HeaderField, PARTNER_COLUMNS, WAREHOUSE_LOOKUP, hasCurrency, hasExpenses, hasFolio, hasPartnerData, hasSeries, headerKeysOf, keysOfFields, requiredHeaderOf } from './document-layouts';
import { type ComputedSource, type GroupCell, type HeaderField, PARTNER_COLUMNS, fieldDbName, WAREHOUSE_LOOKUP, hasCurrency, hasExpenses, hasFolio, hasPartnerData, hasSeries, headerKeysOf, keysOfFields, requiredHeaderOf } from './document-layouts';
import { type AddressSide, type AddressValues, addressFromExtension, addressFromPartner, composeAddress, toExtension } from './address-fields';
import { DocumentPdf } from '../reports/document-pdf';
import { AddressDialog } from './address-dialog';
@@ -450,6 +450,8 @@ export class DocumentFormPage {
}
/** Valor de una fila de solo lectura (número del documento, datos del socio, totales). */
protected readonly dbNames = fieldDbName;
protected computedValue(source: ComputedSource): string {
switch (source) {
case 'docNum':
@@ -592,3 +592,42 @@ export const hasPartnerData = (layout: DocumentLayout): boolean => allFields(lay
export const hasCurrency = (layout: DocumentLayout): boolean => allFields(layout).some((f) => f.type === 'currency');
export const hasFolio = (layout: DocumentLayout): boolean => allFields(layout).some((f) => f.type === 'folio' || (f.type === 'group' && f.cells.some((c) => c.key === 'FolioNumber')));
/**
* Nombre(s) del campo de SAP de una fila del formulario, para «Campos» y la ayuda del cursor: el de un campo sencillo, o
* todos los de una fila con varios controles (`FolioPrefixString · FolioNumber`).
*/
export function fieldDbName(f: HeaderField): string | undefined {
switch (f.type) {
case 'folio':
return `${f.prefixKey} · ${f.numberKey}`;
case 'group':
return f.cells.map((c) => c.key).join(' · ');
case 'series':
return 'Series · DocNum';
case 'currency':
return 'DocCurrency · DocRate';
case 'rounding':
return 'Rounding · RoundingDiffAmount';
case 'expenses':
return 'DocumentAdditionalExpenses';
case 'computed':
return COMPUTED_DB_NAMES[f.source];
default:
return 'key' in f ? f.key : undefined;
}
}
const COMPUTED_DB_NAMES: Readonly<Record<ComputedSource, string>> = {
docNum: 'DocNum',
partnerName: 'CardName',
partnerTaxId: 'FederalTaxID',
subtotal: 'Σ líneas',
expenses: 'Σ DocumentAdditionalExpenses',
tax: 'VatSum',
total: 'DocTotal',
downPayment: 'DownPaymentAmount',
applied: 'PaidToDate',
balance: 'DocTotal − PaidToDate',
};
@@ -12,21 +12,21 @@
<div class="sbo-hdr">
<div class="sbo-col">
@if (isNew()) {
<sbo-select-field label="Serie" [options]="seriesOptions()" [value]="series()" (valueChange)="series.set($event === null ? null : +$event)" />
<sbo-select-field label="Serie" dbName="Series" [options]="seriesOptions()" [value]="series()" (valueChange)="series.set($event === null ? null : +$event)" />
} @else {
<sbo-text-field label="Número" [value]="'' + (doc()?.['JdtNum'] ?? '')" readonly />
<sbo-text-field label="Número" dbName="JdtNum" [value]="'' + (doc()?.['JdtNum'] ?? '')" readonly />
}
<sbo-text-field label="Comentarios" [value]="memo()" (valueChange)="set('memo', $event)" [readonly]="saved()" />
<sbo-text-field label="Comentarios" dbName="Memo" [value]="memo()" (valueChange)="set('memo', $event)" [readonly]="saved()" />
</div>
<div class="sbo-col">
<sbo-date-field label="Fecha de contabilización" [(value)]="referenceDate" [readonly]="saved()" required />
<sbo-date-field label="Fecha de vencimiento" [value]="dueDate()" (valueChange)="onDueDate($event)" [readonly]="saved()" />
<sbo-date-field label="Fecha del documento" [(value)]="taxDate" [readonly]="saved()" />
<sbo-date-field label="Fecha de contabilización" dbName="ReferenceDate" [(value)]="referenceDate" [readonly]="saved()" required />
<sbo-date-field label="Fecha de vencimiento" dbName="DueDate" [value]="dueDate()" (valueChange)="onDueDate($event)" [readonly]="saved()" />
<sbo-date-field label="Fecha del documento" dbName="TaxDate" [(value)]="taxDate" [readonly]="saved()" />
</div>
</div>
<div class="sbo-hdr">
<div class="sbo-col">
<sbo-field label="Indicador / Folio">
<sbo-field label="Indicador / Folio" dbName="Indicator · FolioPrefixString · FolioNumber">
<sbo-input width="80px" ariaLabel="Indicador" [readonly]="saved()" [value]="indicator()" (valueChange)="indicator.set($event)" />
@if (!saved()) {
<button type="button" class="sbo-btn" aria-label="Abrir la lista de indicadores" title="Lista de valores" (click)="indicatorOpen.set(true)">…</button>
@@ -36,9 +36,9 @@
</sbo-field>
</div>
<div class="sbo-col">
<sbo-text-field label="Referencia 1" [value]="reference()" (valueChange)="set('reference', $event)" [readonly]="saved()" />
<sbo-text-field label="Referencia 2" [value]="reference2()" (valueChange)="set('reference2', $event)" [readonly]="saved()" />
<sbo-text-field label="Referencia 3" [value]="reference3()" (valueChange)="set('reference3', $event)" [readonly]="saved()" />
<sbo-text-field label="Referencia 1" dbName="Reference" [value]="reference()" (valueChange)="set('reference', $event)" [readonly]="saved()" />
<sbo-text-field label="Referencia 2" dbName="Reference2" [value]="reference2()" (valueChange)="set('reference2', $event)" [readonly]="saved()" />
<sbo-text-field label="Referencia 3" dbName="Reference3" [value]="reference3()" (valueChange)="set('reference3', $event)" [readonly]="saved()" />
</div>
</div>
+4 -2
View File
@@ -22,7 +22,7 @@ let nextId = 0;
[class.link]="linkable()"
[attr.title]="dbName() ?? null"
(click)="labelClick.emit()"
>{{ label() }}@if (dbName() && names.show()) {
><span class="t">{{ label() }}</span>@if (dbName() && names.show()) {
<span class="db">{{ dbName() }}</span>
}</label
>
@@ -51,7 +51,7 @@ let nextId = 0;
text-overflow: ellipsis;
white-space: nowrap;
}
label.req::after {
label.req .t::after {
content: ' *';
color: var(--err);
}
@@ -74,6 +74,8 @@ let nextId = 0;
margin-top: -2px;
font: 10.5px/1.2 var(--mono, monospace);
color: var(--quiet);
white-space: normal;
overflow-wrap: anywhere;
}
label.link {
cursor: pointer;
+1 -1
View File
@@ -15,7 +15,7 @@
<tr>
<th class="rn">#</th>
@for (c of columns(); track c.key; let j = $index) {
<th sboColResize [style.width]="c.width" [style.text-align]="alignOf(c)" [class.req]="c.required" [attr.title]="c.key">{{ c.title }}@if (names.show()) {
<th sboColResize [style.width]="c.width" [style.text-align]="alignOf(c)" [class.req]="c.required" [attr.title]="isSap(c.key) ? c.key : null">{{ c.title }}@if (names.show() && isSap(c.key)) {
<span class="db">{{ c.key }}</span>
}</th>
@if (hasDetails() && j === detailAt()) {
+2 -1
View File
@@ -12,7 +12,7 @@ import {
output,
signal,
} from '@angular/core';
import { FieldNames } from '../../core/field-names';
import { FieldNames, isSapField } from '../../core/field-names';
import { formatNumber, parseDecimal } from '../../core/format';
import { SlLookupApi } from '../../core/sl/sl-lookup';
import type { ListRow } from '../list/list.types';
@@ -59,6 +59,7 @@ export class LinesGrid {
private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);
private readonly injector = inject(Injector);
protected readonly names = inject(FieldNames);
protected readonly isSap = isSapField;
constructor() {
// las celdas de código con texto propio (la cuenta con su formato) piden los textos de las líneas que se cargan
+3 -2
View File
@@ -1,7 +1,7 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { ChangeDetectionStrategy, Component, computed, effect, inject, input, model, signal } from '@angular/core';
import { API_URL } from '../../core/api';
import { FieldNames } from '../../core/field-names';
import { FieldNames, isSapField } from '../../core/field-names';
import { formatNumber, parseDecimal } from '../../core/format';
import { SlLookupApi } from '../../core/sl/sl-lookup';
import type { ListRow } from '../list/list.types';
@@ -32,7 +32,7 @@ const dateOnly = (v: unknown): string => (typeof v === 'string' ? v.slice(0, 10)
<tr>
<th class="rn">#</th>
@for (c of columns(); track c.key) {
<th [style.width]="c.width" [class.req]="c.required" [attr.title]="c.key">{{ c.title }}@if (fieldNames.show()) {
<th [style.width]="c.width" [class.req]="c.required" [attr.title]="isSap(c.key) ? c.key : null">{{ c.title }}@if (fieldNames.show() && isSap(c.key)) {
<span class="db">{{ c.key }}</span>
}</th>
}
@@ -186,6 +186,7 @@ export class RowsTable {
});
protected readonly fieldNames = inject(FieldNames);
protected readonly isSap = isSapField;
private readonly lookupApi = inject(SlLookupApi);
private readonly http = inject(HttpClient);
/** Nombres de los catálogos de las columnas `nameOf`, por recurso. */
+2 -2
View File
@@ -19,11 +19,11 @@
[style.text-align]="align(c)"
[class.pick]="searchable(c)"
[class.active]="c.key === activeColumnKey()"
[attr.title]="(searchable(c) ? 'Buscar en esta columna · ' : '') + c.key"
[attr.title]="(searchable(c) ? 'Buscar en esta columna' : '') + (searchable(c) && isSap(c.key) ? ' · ' : '') + (isSap(c.key) ? c.key : '') || null"
(click)="columnPicked.emit(c)"
>
{{ c.title }}
@if (names.show()) {
@if (names.show() && isSap(c.key)) {
<span class="db">{{ c.key }}</span>
}
</th>
+2 -1
View File
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
import { FieldNames } from '../../core/field-names';
import { FieldNames, isSapField } from '../../core/field-names';
import { ColResize } from '../table/col-resize';
import { Badge } from '../window/badge';
import { type ListColumn, type ListRow, alignOf, cellText, isSearchable, type Tone } from './list.types';
@@ -17,6 +17,7 @@ import { type ListColumn, type ListRow, alignOf, cellText, isSearchable, type To
})
export class DataTable {
protected readonly names = inject(FieldNames);
protected readonly isSap = isSapField;
readonly columns = input.required<readonly ListColumn[]>();
readonly rows = input.required<readonly ListRow[]>();