feat(web): la cuenta elegida completa la descripción de la línea de servicio y elegir el socio agrega una línea

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-19 12:28:56 -05:00
1 parent 2e74bccd65
commit 773dd7ff6a
4 files changed
+36 -2

No files matched your search

@@ -210,6 +210,15 @@ describe('DocumentFormPage', () => {
expect(navigate).toHaveBeenCalledWith(['..', 99], expect.objectContaining({ state: { created: '1099' } }));
});
it('al elegir el socio de un documento nuevo sin líneas se agrega una línea, y no se repite', async () => {
expect(page().lines()).toEqual([]);
page().onPartner({ CardCode: 'C1', CardName: 'ACME' });
await tick();
expect(page().lines()).toHaveLength(1);
page().onPartner({ CardCode: 'C2', CardName: 'OTRO' });
expect(page().lines()).toHaveLength(1);
});
describe('tipo Servicio', () => {
const headers = () => [...el().querySelectorAll('.lines-head th, table.grid thead th')].map((t) => t.textContent?.trim());
@@ -429,6 +429,8 @@ export class DocumentFormPage {
protected onPartner(row: Record<string, unknown>): void {
this.partnerName.set(text(row['CardName']));
this.partnerTaxId.set(text(row['FederalTaxID']));
// elegido el socio, el documento nuevo arranca con una línea lista para escribir
if (this.isNew() && !this.readOnly() && this.lines().length === 0) this.lines.set([this.newLine()]);
}
protected setLines(lines: readonly GridLine[]): void {
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { ANALYTIC_COLUMNS, DOCUMENT_LINE_COLUMNS, ITEMS_MULTI_ADD, lineColumnsFor, lineFieldsOf, newDocumentLine, recalcLine, uomEntryOf } from './line-columns';
import { ANALYTIC_COLUMNS, DOCUMENT_LINE_COLUMNS, ITEMS_MULTI_ADD, lineColumnsFor, lineFieldsOf, newDocumentLine, newServiceLine, recalcLine, serviceLineColumns, uomEntryOf } from './line-columns';
describe('recalcLine', () => {
it('total = cantidad × precio, redondeado a 2 decimales', () => {
@@ -148,3 +148,12 @@ describe('precio con y sin impuesto', () => {
expect(recalcLine({ ...base, Price: 50, PriceAfterVAT: 80 }, 'Quantity')).toMatchObject({ Price: 50, PriceAfterVAT: 80, LineTotal: 100 });
});
});
describe('línea de servicio', () => {
const account = serviceLineColumns()[0].lookup!;
it('al elegir la cuenta, su nombre es la descripción si la línea no tiene otra', () => {
expect(account.apply({ Code: '_SYS1', Name: 'Alquileres' }, newServiceLine())).toMatchObject({ AccountCode: '_SYS1', ItemDescription: 'Alquileres' });
expect(account.apply({ Code: '_SYS1', Name: 'Alquileres' }, { ...newServiceLine(), ItemDescription: 'Oficina' })).toMatchObject({ AccountCode: '_SYS1', ItemDescription: 'Oficina' });
});
});
@@ -212,7 +212,21 @@ export const LINE_COLUMNS = {
*/
export const serviceLineColumns = (taxResource = 'SalesTaxCodes'): readonly GridColumn[] =>
lineColumnsFor(taxResource, [
{ ...LINE_COLUMNS.account, title: 'Cuenta contable', width: '170px', required: true },
{
...LINE_COLUMNS.account,
title: 'Cuenta contable',
width: '170px',
required: true,
// al elegir la cuenta, su nombre es la descripción de la línea (si no se escribió otra)
lookup: {
...LINE_COLUMNS.account.lookup!,
apply: (account, line) => ({
...line,
AccountCode: account['Code'],
ItemDescription: filled(line['ItemDescription']) ? line['ItemDescription'] : (account['Name'] ?? ''),
}),
},
},
{ ...LINE_COLUMNS.description, width: '260px' },
LINE_COLUMNS.tax,
{ ...LINE_COLUMNS.total, readonly: false, required: true },