190 lines
5.6 KiB
TypeScript
190 lines
5.6 KiB
TypeScript
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<number>
|
|
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)
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
}
|