diff --git a/CLAUDE.md b/CLAUDE.md index 2c0a8e5..32f855c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,7 +48,7 @@ Cada menú abre primero una **lista de los últimos documentos** (barra de filtr - Probar contra el SAP real con la extensión de Chrome (`list_connected_browsers` debe mostrar un navegador). Si no conecta, usar Chrome headless por CDP. - **No escribir contraseñas en formularios**: obtener el token con `curl` a `/api/auth/login` (la clave de prueba se lee de `EmployeesInfo` solo para eso, nunca se imprime ni se guarda) e inyectar solo el token en `localStorage` (`erp_session`). - Al terminar: cerrar la sesión de prueba (`POST /api/auth/logout`), borrar `erp_session`/`erp_theme` del navegador, cerrar la pestaña, apagar los servidores y borrar archivos temporales (token, `apps/api/data/`). No dejar páginas de demostración fuera de `/dev/componentes`. -- **Escrituras a SAP (POST/PATCH):** el usuario autorizó (2026-10-14) escribir en `SBODemoCL`, su ambiente propio de pruebas; ya se probaron crear/actualizar órdenes de venta y de compra, reemplazo de líneas y el 412 por conflicto. Documentos de prueba creados: orden de venta 315 y orden de compra 2883 (comentario "PRUEBA basic-erp"). Aun así, avisar antes de escribir en cualquier otra base. +- **Escrituras a SAP (POST/PATCH):** el usuario autorizó (2026-10-14) escribir en `SBODemoCL`, su ambiente propio de pruebas; ya se probaron crear/actualizar órdenes de venta y de compra, reemplazo de líneas y el 412 por conflicto. Documentos de prueba creados: orden de venta 315 (cerrada, copiada a la entrega 580) y orden de compra 2883 (cerrada, copiada a la recepción 299). Aun así, avisar antes de escribir en cualquier otra base. - Los tests no detectan todo: el foco tras crear una línea (se pedía antes de que existiera la fila) solo falló en el navegador real. ## Estado y próximos pasos @@ -56,7 +56,7 @@ Cada menú abre primero una **lista de los últimos documentos** (barra de filtr Hecho (commits en `main`): monorepo · API (config, capa SAP con sesión compartida y cola, login, permisos SQLite, proxy `/api/sl`) · web (temas, login, layout con menú por permisos, `sbo-value-help`, campos y filas compuestas, listas con filtros, ventana/toolbar/pestañas/menús, grilla de líneas, `/dev/componentes`). Pendiente, en orden: -1. **Paso 9 — formulario de documentos:** hecho para ventas y compras (`document-form.page`, `document-model.ts`: cargar, crear, actualizar con `If-Match`/412, navegación, totales con `SalesTaxCodes` (también en compras), solo lectura), probado con SAP simulado y contra `SBODemoCL` (leer, crear, actualizar, líneas, 412). Un código escrito a mano (socio, artículo, almacén, impuesto) se resuelve al salir del campo con `SlLookupApi` (mismo recurso y filtro base que la lista "…"); si no existe se avisa. Falta: "Copiar de/a", botón PDF, fila del flete, toolbar de ancho completo, formularios de inventario y solicitudes de compra. +1. **Paso 9 — formulario de documentos:** hecho para ventas y compras (`document-form.page`, `document-model.ts`: cargar, crear, actualizar con `If-Match`/412, navegación, totales con `SalesTaxCodes` (también en compras), solo lectura), probado con SAP simulado y contra `SBODemoCL` (leer, crear, actualizar, líneas, 412). Un código escrito a mano (socio, artículo, almacén, impuesto) se resuelve al salir del campo con `SlLookupApi` (mismo recurso y filtro base que la lista "…"); si no existe se avisa. "Copiar de/a" hecho (`document-copy.ts`: flujos estándar y `BaseType/BaseEntry/BaseLine`; probado: orden de compra 2883 → recepción 299, orden de venta 315 → entrega 580, ambas órdenes quedaron cerradas). Falta: botón PDF, fila del flete, toolbar de ancho completo, formularios de inventario y solicitudes de compra. 2. Pantallas de maestros (`Items`, `BusinessPartners`: Clientes/Proveedores, Artículos), hoy "no disponible". 3. ~~Pantalla web de permisos~~ — hecha (`/admin/permisos`). 4. Auditoría (`audit_log` en SQLite; hoy solo líneas `AUDIT` en el log) y `nestjs-cls` para el usuario en los logs. diff --git a/apps/web/README.md b/apps/web/README.md index 3adcb11..1aac868 100644 --- a/apps/web/README.md +++ b/apps/web/README.md @@ -132,6 +132,7 @@ Lo usan las pantallas con `partner` en su `DocumentScreen` (ventas y compras); e - **Códigos escritos a mano**: al salir del campo (socio con `resolveOnLeave` en `sbo-lookup-field`; artículo, almacén e impuesto en la grilla) se buscan con `SlLookupApi` (`core/sl/sl-lookup.ts`) en la misma lista que abre "…": se normaliza el código y se completa nombre/descripción; si no existe se avisa (en el campo o en la barra de estado) y la celda vuelve a su valor. - **Crear**: valida sin SAP (socio, fecha, al menos una línea con artículo, cantidad > 0), quita campos vacíos y filas en blanco, y abre el documento creado. - **Actualizar**: envía solo la cabecera que cambió y, si cambiaron las líneas, todas con `B1S-ReplaceCollectionsOnPatch: true`. Lleva `If-Match` con el `odata.etag` leído: si otro usuario cambió el documento, SAP responde **412**, no se guarda nada y se ofrece "Recargar". +- **Copiar a / Copiar de** (`document-copy.ts`): los flujos estándar (oferta → orden → entrega → factura → nota de crédito, y los de compras) están en `COPY_FLOWS`. *Copiar a* (documento guardado, abierto y sin cambios) abre el documento de destino nuevo con el origen en el estado de la navegación; *Copiar de* (documento nuevo) lista los abiertos del origen elegido, del mismo socio si ya se indicó. Se copian las líneas abiertas con la cantidad pendiente y `BaseType/BaseEntry/BaseLine`, con lo que SAP enlaza y cierra el origen. - **Cerrado o cancelado**: solo lectura (sin botón de guardar). - **Navegación** primero / anterior / siguiente / último por `DocEntry`. - La lógica sin Angular está en `document-model.ts` (totales, payload, validación, navegación) y el acceso HTTP en `core/sl/sl-document.ts`. diff --git a/apps/web/src/app/features/documents/document-form.page.html b/apps/web/src/app/features/documents/document-form.page.html index 106c782..c895754 100644 --- a/apps/web/src/app/features/documents/document-form.page.html +++ b/apps/web/src/app/features/documents/document-form.page.html @@ -105,7 +105,7 @@ @if (copyListScreen(); as src) { (() => copySources(this.screen.path).map((p) => ({ id: p, label: menuLabel(p), disabled: !this.isNew() })), ); + protected readonly copyListTitle = computed(() => menuLabel(this.copyListFor() ?? '')); protected readonly copyListScreen = computed(() => DOCUMENT_SCREENS.find((s) => s.path === this.copyListFor())); /** Documentos abiertos del origen elegido, del mismo socio si ya se indicó. */ protected readonly copyListFilter = computed(() => {