Nota de horas: datos de pago (bancarios) + periodo en el nombre del archivo
- Las notas "por pagar" ahora incluyen los datos bancarios de cobro configurados (Transferencia Nacional/Internacional: cuenta, CLABE, beneficiario, RFC, banco, SWIFT), igual que el PDF de cotizacion. Solo se muestran en las notas por pagar. - El nombre del PDF incluye el periodo cobrado (fecha minima a maxima de los registros), formato DD-MM-YYYY_DD-MM-YYYY. Ej: "Nota de horas por pagar UJ2606AG777 - 24-06-2026_24-06-2026". Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
feb88de203
commit
3824dd00be
@@ -1,6 +1,6 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { getConfigBranding } from "@/lib/config-helpers";
|
||||
import { getConfigBranding, getConfigBancaria } from "@/lib/config-helpers";
|
||||
import { generateNotaHorasPDF, type NotaHorasGrupo } from "@/lib/nota-horas-pdf";
|
||||
import {
|
||||
IVA_RATE,
|
||||
@@ -41,12 +41,13 @@ export async function POST(
|
||||
const from: string = ISO_RE.test(body?.from) ? body.from : "";
|
||||
const to: string = ISO_RE.test(body?.to) ? body.to : "";
|
||||
|
||||
const [cot, branding] = await Promise.all([
|
||||
const [cot, branding, bancaria] = await Promise.all([
|
||||
prisma.cotizacion.findUnique({
|
||||
where: { id },
|
||||
include: { cliente: true, registrosHoras: true },
|
||||
}),
|
||||
getConfigBranding(),
|
||||
getConfigBancaria(),
|
||||
]);
|
||||
if (!cot) return NextResponse.json({ error: "No encontrada" }, { status: 404 });
|
||||
|
||||
@@ -96,6 +97,32 @@ export async function POST(
|
||||
: "Periodo: todos los registros";
|
||||
const modoLabel = MODOS_AGRUPACION.find((mm) => mm.value === modo)?.label ?? "Detalle";
|
||||
|
||||
// Datos bancarios para el cobro (misma extraccion que el PDF de cotizacion).
|
||||
// Solo se muestran en las notas "por pagar" (las que se envian para cobro).
|
||||
const cfg = bancaria || {};
|
||||
const datosPago =
|
||||
estado === "por_pagar"
|
||||
? {
|
||||
razonSocial: cfg.razon_social || "URIEL JARETH ALVARADO ORTIZ",
|
||||
rfc: cfg.rfc || "AAOU970201SU7",
|
||||
cuentaNacional: cfg.cuenta_nacional || "",
|
||||
clabeNacional: cfg.clabe_interbancaria || cfg.cuenta_nacional || "",
|
||||
bancoNacional: cfg.cuenta_nacional ? "BBVA" : "",
|
||||
clabeInternacional: cfg.cuenta_internacional_swift?.match(/CLABE[^:]*:\s*(\S+)/i)?.[1] || "",
|
||||
swift: cfg.cuenta_internacional_swift?.match(/SWIFT[^:]*:\s*(\S+)/i)?.[1] || "BCMRMXMMPYM",
|
||||
}
|
||||
: undefined;
|
||||
|
||||
// Periodo cobrado para el nombre del archivo: fecha minima_maxima (DD-MM-YYYY).
|
||||
const fechasISO = regs.map((r) => r.fecha.toISOString().slice(0, 10)).sort();
|
||||
const ddmmyyyy = (iso: string) => {
|
||||
const [yy, mo, dd] = iso.split("-");
|
||||
return `${dd}-${mo}-${yy}`;
|
||||
};
|
||||
const rango = fechasISO.length
|
||||
? `${ddmmyyyy(fechasISO[0])}_${ddmmyyyy(fechasISO[fechasISO.length - 1])}`
|
||||
: "";
|
||||
|
||||
const buffer = await generateNotaHorasPDF({
|
||||
numero: cot.numero,
|
||||
proyecto: cot.proyecto,
|
||||
@@ -123,10 +150,11 @@ export async function POST(
|
||||
iva,
|
||||
total,
|
||||
etiquetaTotal: ETIQUETA_TOTAL[estado],
|
||||
datosPago,
|
||||
...branding,
|
||||
});
|
||||
|
||||
const nombre = sanitizeFilename(`${TITULO[estado]} ${cot.numero}`);
|
||||
const nombre = sanitizeFilename(`${TITULO[estado]} ${cot.numero}${rango ? ` - ${rango}` : ""}`);
|
||||
return new NextResponse(new Uint8Array(buffer), {
|
||||
headers: {
|
||||
"Content-Type": "application/pdf",
|
||||
|
||||
Reference in New Issue
Block a user