import { FastifyInstance } from "fastify"; import {buildExportZip} from "../utils/export/datev"; import {s3} from "../utils/s3"; import {GetObjectCommand, PutObjectCommand} from "@aws-sdk/client-s3" import {getSignedUrl} from "@aws-sdk/s3-request-presigner"; import dayjs from "dayjs"; import {randomUUID} from "node:crypto"; import {secrets} from "../utils/secrets"; import {createSEPAExport} from "../utils/export/sepa"; import {generatedexports} from "../../db/schema"; import {eq} from "drizzle-orm"; const createDatevExport = async (server:FastifyInstance,req:any,startDate,endDate,beraternr,mandantennr) => { try { console.log(startDate,endDate,beraternr,mandantennr) // 1) ZIP erzeugen const buffer = await buildExportZip(server,req.user.tenant_id, startDate, endDate, beraternr, mandantennr) console.log("ZIP created") console.log(buffer) // 2) Dateiname & Key festlegen const fileKey = `${req.user.tenant_id}/exports/Export_${dayjs(startDate).format("YYYY-MM-DD")}_${dayjs(endDate).format("YYYY-MM-DD")}_${randomUUID()}.zip` console.log(fileKey) // 3) In S3 hochladen await s3.send( new PutObjectCommand({ Bucket: secrets.S3_BUCKET, Key: fileKey, Body: buffer, ContentType: "application/zip", }) ) // 4) Presigned URL erzeugen (24h gültig) const url = await getSignedUrl( s3, new GetObjectCommand({ Bucket: secrets.S3_BUCKET, Key: fileKey, }), { expiresIn: 60 * 60 * 24 } ) console.log(url) // 5) In Haupt-DB speichern const inserted = await server.db .insert(generatedexports) .values({ tenantId: req.user.tenant_id, startDate: new Date(startDate), endDate: new Date(endDate), validUntil: dayjs().add(24, "hours").toDate(), filePath: fileKey, url, type: "datev", }) .returning() console.log(inserted[0]) } catch (error) { console.log(error) } } const createSepaExport = async (server: FastifyInstance, req: any, idsToExport: number[], creditorBankaccountId: number) => { const exportData = await createSEPAExport(server, idsToExport, req.user.tenant_id, creditorBankaccountId) const fileKey = `${req.user.tenant_id}/exports/SEPA_${dayjs().format("YYYY-MM-DD")}_${randomUUID()}.xml` await s3.send( new PutObjectCommand({ Bucket: secrets.S3_BUCKET, Key: fileKey, Body: exportData.buffer, ContentType: "application/xml", }) ) const url = await getSignedUrl( s3, new GetObjectCommand({ Bucket: secrets.S3_BUCKET, Key: fileKey, }), { expiresIn: 60 * 60 * 24 } ) const inserted = await server.db .insert(generatedexports) .values({ tenantId: req.user.tenant_id, startDate: exportData.startDate, endDate: exportData.endDate, validUntil: dayjs().add(24, "hours").toDate(), filePath: fileKey, url, type: "sepa", }) .returning() console.log(inserted[0]) } export default async function exportRoutes(server: FastifyInstance) { //Export DATEV server.post("/exports/datev", async (req, reply) => { const { start_date, end_date, beraternr, mandantennr } = req.body as { start_date: string end_date: string beraternr: string mandantennr: string } reply.send({success:true}) setImmediate(async () => { try { await createDatevExport(server,req,start_date,end_date,beraternr,mandantennr) console.log("Job done ✅") } catch (err) { console.error("Job failed ❌", err) } }) }) server.post("/exports/sepa", async (req, reply) => { const { idsToExport, creditorBankaccountId } = req.body as { idsToExport: Array creditorBankaccountId: number } if (!idsToExport?.length || !creditorBankaccountId) { return reply.send({ success: false, message: "Belege und Gläubigerkonto sind Pflichtfelder." }) } reply.send({success:true}) setImmediate(async () => { try { await createSepaExport(server, req, idsToExport, creditorBankaccountId) console.log("Job done ✅") } catch (err) { console.error("Job failed ❌", err) } }) }) //List Exports Available for Download server.get("/exports", async (req,reply) => { const data = await server.db .select({ id: generatedexports.id, created_at: generatedexports.createdAt, tenant_id: generatedexports.tenantId, start_date: generatedexports.startDate, end_date: generatedexports.endDate, valid_until: generatedexports.validUntil, type: generatedexports.type, url: generatedexports.url, file_path: generatedexports.filePath, }) .from(generatedexports) .where(eq(generatedexports.tenantId, req.user.tenant_id)) console.log(data) reply.send(data) }) }