Plantilla de impresión de facturas

Las dos piezas de la factura de DemoUp: el documento API que produce el JSON y la plantilla Vue que lo muestra, con cada clave del JSON y su condición.

La factura de DemoUp son dos documentos dinámicos sobre la sección Ventas / Ingresos, los dos con la pregunta v.Factura. Factura JSON (tipo API) construye los datos; Factura - Moderna (tipo impresión) los incluye y los muestra con Vue.

Antes de empezar

Cómo se unen

La plantilla incluye el documento API con F.Include y le pasa su propia pregunta. La salida del documento API es el objeto data de Vue:

<script>
const data = <!--: F.Include(S.DynamicDocuments.API.FacturaJSON.ID, v.Factura) :-->;

const app = Vue.createApp({
  data() { return { data }; },
  computed: {
    resumen() { return this.data?.Resumen?.[0] || null; },
    conceptos() { return this.data?.Conceptos || []; },
    baseImponible() { return this.data?.BaseImponible || []; },
    totales() { return this.data?.Totales || []; },
    hayRE() { return this.baseImponible.some(x => Number(x?.CuotaRE || 0) > 0); },
    totalesFiltrados() { return this.totales.filter(t => t.Concepto !== 'Total'); },
    totalAbsoluto() { return this.totales.filter(t => t.Concepto === 'Total'); }
  },
  methods: {
    euro(v) { return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(Number(v || 0)); }
  }
});
app.mount('#app');
</script>

F.Include(id, ...) admite tras el ID las preguntas del documento incluido, en su orden.

El JSON

Factura JSON crea cuatro tablas con F.DataTable_New y las escribe en JSON con F.DataTable_Build(tabla, 'jsonarrayf'):

{
"Resumen": <!--: F.Write(v.JSONResumen) :-->,
"Conceptos": <!--: F.Write(v.JSONConceptos) :-->,
"BaseImponible": <!--: F.Write(v.JSONBaseImponible) :-->,
"Totales": <!--: F.Write(v.JSONTotales) :-->
}

Resumen

Una sola fila. En Vue se lee como resumen.<Clave>.

ClaveOrigen
NumeroFactura, Fecha, FechaVencimiento, FacturaRectificadaCampos de la factura. Las fechas pasan por F.Cast_DateToText(fecha, S.Enums.formatofecha.diamesaño).
ClienteNombre, ClienteNIF, ClienteDireccion, ClienteEmail, ClienteTelefono, ClienteCodigoPostal, ClientePoblacion, ClienteProvinciaDatos del cliente copiados en la factura.
EmpresaRazonSocial, EmpresaNIF, EmpresaDireccion, EmpresaEmail, EmpresaTelefono, EmpresaCodigoPostal, EmpresaPoblacion, EmpresaProvincia, EmpresaWebDatos fiscales de la empresa emisora.
LogoURLD.EmpresaActual.URLLogoFactura.
DatosFiscales, CondicionesPago, Notas, EnlacePago, DireccionEnvioTextos opcionales de la factura.

Conceptos

Una fila por línea de Lista - Ventas / Ingresos, filtrada con F.DataListLoadAddFilter por RelacionElementoContenedorListador igual a v.Factura.

ClaveCampo de I.VentasIngresosLista
ConceptoTextoPrincipal
PrecioUnidadImportePrecioUnidad
UnidadesCantidadUnidades
DtosImporteDescuentoFijoUnidad y SumaDescuentosPorcientoPorciento, formateados con F.FormatMoney y F.FormatPercentage
DescuentosImporteTotalDescuentos
TotalImporteTotalConcepto

BaseImponible

Una fila por base con importe distinto de cero: ImporteBaseImponible1, 2, 3 y ImporteBaseImponibleExenta.

ClaveOrigen
BaseImponiblev.Factura.ImporteBaseImponibleN
IVAPorcientov.Factura.ReferenciaImpuestoN.ValorPorciento
CuotaIVAv.Factura.ImporteBaseImponibleNCuotaIVA
REPorcientov.Factura.ReferenciaImpuestoN.RecargoEquivalenciaPorciento
CuotaREv.Factura.ImporteBaseImponibleNCuotaRE

Totales

Filas Concepto / Importe: Subtotal, IVA, Suplidos y Total. totalAbsoluto separa la fila Total para mostrarla aparte.

Qué se muestra y cuándo

SiempreCon v-if
resumen.NumeroFactura, resumen.Fecha, resumen.EmpresaRazonSocial, resumen.EmpresaNIF, resumen.EmpresaDireccionresumen.LogoURL, resumen.FacturaRectificada, resumen.FechaVencimiento, resumen.DireccionEnvio, resumen.CondicionesPago, resumen.Notas, resumen.EnlacePago, resumen.EmpresaEmail, conceptos y totales (si traen filas)

El bloque de cliente entero va bajo v-if="resumen.ClienteNIF". La tabla de bases usa hayRE para elegir entre cinco columnas y tres:

<table style="margin-top:20px; border-collapse:collapse; font-size:13px;">
  <thead style="background-color:#edf2f7;">
    <tr v-if="hayRE">
      <th>Tipo</th><th>Base</th><th>Cuota IVA</th><th>RE %</th><th>Cuota RE</th>
    </tr>
    <tr v-else>
      <th>Tipo</th><th>Base</th><th>Cuota</th>
    </tr>
  </thead>
  <tbody>
    <template v-for="(bi, i) in baseImponible" :key="i">
      <tr v-if="hayRE">
        <td>{{ bi.IVAPorciento }}%</td>
        <td>{{ euro(bi.BaseImponible) }}</td>
        <td>{{ euro(bi.CuotaIVA) }}</td>
        <td>{{ bi.REPorciento }}</td>
        <td>{{ euro(bi.CuotaRE) }}</td>
      </tr>
      <tr v-else>
        <td>{{ bi.IVAPorciento }}%</td>
        <td>{{ euro(bi.BaseImponible) }}</td>
        <td>{{ euro(bi.CuotaIVA) }}</td>
      </tr>
    </template>
  </tbody>
</table>

Metadatos de la plantilla

Factura - Moderna fija titulo, email_subject, email_to, email_to_name y email_body con el ID de Factura - Plantilla de Email. El detalle está en Envío de emails.

Siguiente: Ejemplos. Otra factura completa sin Vue: Impresión de factura emitida.

En esta página