feat(BillingService): add file path resolution for PDF templates
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 43s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 43s
- Implemented a new method to resolve existing file paths for PDF templates, enhancing file handling robustness. - Updated PDF storage path handling to ensure correct resolution of paths before file operations, improving error handling and reliability. - Refactored related logic to utilize the new path resolution method across various template operations.
This commit is contained in:
@@ -30,6 +30,30 @@ const toMonthDate = (value, endOfMonth = false) => {
|
||||
};
|
||||
|
||||
class BillingService {
|
||||
_resolveExistingFilePath(storedPath) {
|
||||
const rawPath = String(storedPath || '').trim();
|
||||
if (!rawPath) return null;
|
||||
|
||||
const candidates = [];
|
||||
if (path.isAbsolute(rawPath)) {
|
||||
candidates.push(rawPath);
|
||||
} else {
|
||||
const normalizedRawPath = rawPath.replace(/^\.?[\\/]/, '');
|
||||
candidates.push(path.resolve(rawPath));
|
||||
candidates.push(path.resolve(process.cwd(), rawPath));
|
||||
candidates.push(path.resolve(process.cwd(), normalizedRawPath));
|
||||
candidates.push(path.resolve(process.cwd(), 'backend', normalizedRawPath));
|
||||
candidates.push(path.resolve(process.cwd(), '..', normalizedRawPath));
|
||||
}
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (candidate && fs.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_normalizeIban(raw, withoutCountry = false) {
|
||||
const cleaned = String(raw || '').replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
|
||||
if (!cleaned) return '';
|
||||
@@ -347,7 +371,7 @@ class BillingService {
|
||||
clubId,
|
||||
name,
|
||||
description: payload?.description ? String(payload.description).trim() : null,
|
||||
pdfStoragePath: file.path,
|
||||
pdfStoragePath: path.resolve(file.path),
|
||||
pdfFilename: file.originalname,
|
||||
pdfMimeType: file.mimetype || 'application/pdf',
|
||||
isActive: true,
|
||||
@@ -386,9 +410,10 @@ class BillingService {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (template.pdfStoragePath && fs.existsSync(template.pdfStoragePath)) {
|
||||
const storedTemplatePath = this._resolveExistingFilePath(template.pdfStoragePath);
|
||||
if (storedTemplatePath) {
|
||||
try {
|
||||
fs.unlinkSync(template.pdfStoragePath);
|
||||
fs.unlinkSync(storedTemplatePath);
|
||||
} catch (error) {
|
||||
// Ignore file cleanup errors, DB deletion already succeeded.
|
||||
}
|
||||
@@ -568,7 +593,8 @@ class BillingService {
|
||||
return { status: 404, response: { success: false, error: 'Abrechnungslauf nicht gefunden' } };
|
||||
}
|
||||
await checkAccess(userToken, run.clubId);
|
||||
if (!run.template?.pdfStoragePath || !fs.existsSync(run.template.pdfStoragePath)) {
|
||||
const resolvedTemplatePath = this._resolveExistingFilePath(run.template?.pdfStoragePath);
|
||||
if (!resolvedTemplatePath) {
|
||||
return { status: 404, response: { success: false, error: 'Vorlagen-PDF nicht gefunden' } };
|
||||
}
|
||||
const computed = await this._collectTrainingSessions(run.clubId, run.periodStart, run.periodEnd);
|
||||
@@ -583,7 +609,7 @@ class BillingService {
|
||||
const generatedPath = path.resolve('uploads/billing-generated', generatedFilename);
|
||||
|
||||
await this._renderBillingPdfFromTemplate(
|
||||
run.template.pdfStoragePath,
|
||||
resolvedTemplatePath,
|
||||
generatedPath,
|
||||
run,
|
||||
sessionsWithLabel,
|
||||
@@ -656,13 +682,14 @@ class BillingService {
|
||||
const template = await BillingTemplate.findByPk(templateId);
|
||||
if (!template) return { status: 404, response: { success: false, error: 'Vorlage nicht gefunden' } };
|
||||
await checkAccess(userToken, template.clubId);
|
||||
if (!template.pdfStoragePath || !fs.existsSync(template.pdfStoragePath)) {
|
||||
const resolvedTemplatePath = this._resolveExistingFilePath(template.pdfStoragePath);
|
||||
if (!resolvedTemplatePath) {
|
||||
return { status: 404, response: { success: false, error: 'Datei nicht gefunden' } };
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
file: {
|
||||
path: path.resolve(template.pdfStoragePath),
|
||||
path: resolvedTemplatePath,
|
||||
name: template.pdfFilename,
|
||||
mimeType: template.pdfMimeType || 'application/pdf'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user