feat(plantillas): subir el documento y que la IA lo devuelva como plantilla editable
Hasta ahora crear una plantilla era escribir HTML con variables de Go a mano. Ahora se sube el documento que ya existe (.docx, .html, .txt o una foto del papel), se lee —docx con stdlib, imágenes por OCR— y la IA lo devuelve armado como plantilla con las variables del generador puestas donde iban los datos. No se guarda solo: el HTML cae en el editor para revisarlo, y si la IA devolvió sintaxis de plantilla inválida se avisa antes de guardar. PDF queda afuera por ahora; el mensaje de error dice qué hacer en su lugar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8c3ab79e88
commit
e681f41639
@@ -0,0 +1,70 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func docxDePrueba(t *testing.T, documentXML string) []byte {
|
||||
t.Helper()
|
||||
var buf bytes.Buffer
|
||||
zw := zip.NewWriter(&buf)
|
||||
w, err := zw.Create("word/document.xml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := w.Write([]byte(documentXML)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := zw.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func TestExtraerTextoDePlantillaDocx(t *testing.T) {
|
||||
xml := `<?xml version="1.0"?><w:document><w:body>` +
|
||||
`<w:p><w:r><w:t>COTIZACI&Oacute;N</w:t></w:r></w:p>` +
|
||||
`<w:p><w:r><w:t>Cliente: </w:t></w:r><w:r><w:t>Acme SAS</w:t></w:r></w:p>` +
|
||||
`<w:p><w:r><w:t>Total: $1.500.000</w:t></w:r></w:p>` +
|
||||
`</w:body></w:document>`
|
||||
|
||||
got, err := ExtraerTextoDePlantilla("cotizacion.docx", docxDePrueba(t, xml))
|
||||
if err != nil {
|
||||
t.Fatalf("ExtraerTextoDePlantilla: %v", err)
|
||||
}
|
||||
// Los runs de un mismo párrafo quedan pegados; los párrafos, en líneas.
|
||||
if !strings.Contains(got, "Cliente: Acme SAS") {
|
||||
t.Errorf("falta la línea del cliente en:\n%s", got)
|
||||
}
|
||||
if !strings.Contains(got, "Total: $1.500.000") {
|
||||
t.Errorf("falta el total en:\n%s", got)
|
||||
}
|
||||
if strings.Contains(got, "<w:") {
|
||||
t.Errorf("quedaron etiquetas XML en:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtraerTextoDePlantillaFormatoNoSoportado(t *testing.T) {
|
||||
if _, err := ExtraerTextoDePlantilla("plantilla.pdf", []byte("x")); err == nil {
|
||||
t.Error("el PDF debería devolver error explicando la alternativa")
|
||||
}
|
||||
if _, err := ExtraerTextoDePlantilla("plantilla.xyz", []byte("x")); err == nil {
|
||||
t.Error("una extensión desconocida debería devolver error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLimpiarCercaDeCodigo(t *testing.T) {
|
||||
casos := map[string]string{
|
||||
"```html\n<p>hola</p>\n```": "<p>hola</p>",
|
||||
"```\n<p>hola</p>\n```": "<p>hola</p>",
|
||||
"<p>hola</p>": "<p>hola</p>",
|
||||
}
|
||||
for in, want := range casos {
|
||||
if got := limpiarCercaDeCodigo(in); got != want {
|
||||
t.Errorf("limpiarCercaDeCodigo(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user