Cuando el admin marca un turno como COMPLETADO escribe una fila en el sheet con patente, km, auto, cliente, fecha y trabajo. Auth via service account con JWT nativo (sin googleapis). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
import { agregarFilaSheet } from "@/lib/google-sheets";
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
@@ -15,5 +16,26 @@ export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id
|
||||
include: { auto: true, tipoServicio: true, cliente: true },
|
||||
});
|
||||
|
||||
if (estado === "COMPLETADO") {
|
||||
try {
|
||||
await agregarFilaSheet({
|
||||
patente: turno.auto.patente,
|
||||
kilometros: turno.kilometros,
|
||||
marca: turno.auto.marca,
|
||||
modelo: turno.auto.modelo,
|
||||
anio: turno.auto.anio,
|
||||
nroChasis: turno.auto.nroChasis,
|
||||
nombre: turno.cliente.nombre,
|
||||
apellido: turno.cliente.apellido,
|
||||
email: turno.cliente.email,
|
||||
telefono: turno.cliente.telefono,
|
||||
fecha: turno.fechaInicio,
|
||||
trabajo: turno.tipoServicio.nombre,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Error escribiendo en Google Sheet:", err);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(turno);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import crypto from "crypto";
|
||||
|
||||
const SHEET_ID = process.env.GOOGLE_SHEET_ID!;
|
||||
const SHEET_TAB = "Hoja1";
|
||||
|
||||
async function getAccessToken(): Promise<string> {
|
||||
const clientEmail = process.env.GOOGLE_CLIENT_EMAIL!;
|
||||
const privateKey = process.env.GOOGLE_PRIVATE_KEY!.replace(/\\n/g, "\n");
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
|
||||
const payload = Buffer.from(
|
||||
JSON.stringify({
|
||||
iss: clientEmail,
|
||||
scope: "https://www.googleapis.com/auth/spreadsheets",
|
||||
aud: "https://oauth2.googleapis.com/token",
|
||||
exp: now + 3600,
|
||||
iat: now,
|
||||
})
|
||||
).toString("base64url");
|
||||
|
||||
const sign = crypto.createSign("RSA-SHA256");
|
||||
sign.update(`${header}.${payload}`);
|
||||
const signature = sign.sign(privateKey, "base64url");
|
||||
|
||||
const jwt = `${header}.${payload}.${signature}`;
|
||||
|
||||
const res = await fetch("https://oauth2.googleapis.com/token", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: new URLSearchParams({
|
||||
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
||||
assertion: jwt,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await res.json() as { access_token: string };
|
||||
return data.access_token;
|
||||
}
|
||||
|
||||
export interface FilaTaller {
|
||||
patente: string;
|
||||
kilometros: number;
|
||||
marca: string;
|
||||
modelo: string;
|
||||
anio: number;
|
||||
nroChasis?: string | null;
|
||||
nombre: string;
|
||||
apellido: string;
|
||||
email: string;
|
||||
telefono: string;
|
||||
fecha: Date;
|
||||
trabajo: string;
|
||||
}
|
||||
|
||||
export async function agregarFilaSheet(fila: FilaTaller) {
|
||||
const token = await getAccessToken();
|
||||
|
||||
const fecha = fila.fecha.toLocaleDateString("es-AR", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
|
||||
const valores = [
|
||||
fila.patente,
|
||||
fila.kilometros,
|
||||
fila.marca,
|
||||
fila.modelo,
|
||||
fila.anio,
|
||||
fila.nroChasis ?? "",
|
||||
fila.nombre,
|
||||
fila.apellido,
|
||||
fila.email,
|
||||
fila.telefono,
|
||||
fecha,
|
||||
fila.trabajo,
|
||||
];
|
||||
|
||||
const url = `https://sheets.googleapis.com/v4/spreadsheets/${SHEET_ID}/values/${SHEET_TAB}!A:L:append?valueInputOption=USER_ENTERED`;
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ values: [valores] }),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const err = await res.text();
|
||||
throw new Error(`Sheets API error: ${err}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user