chore: remove obsolete Android app configuration files
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 44s
- Deleted build.gradle.kts, gradle.properties, and gradlew files as part of the cleanup process. - Removed local.properties and various generated files from the .gradle directory to streamline the project structure. - Cleared out unnecessary build artifacts and intermediate files to improve project maintainability.
This commit is contained in:
202
backend/controllers/billingController.js
Normal file
202
backend/controllers/billingController.js
Normal file
@@ -0,0 +1,202 @@
|
||||
import fs from 'fs';
|
||||
import multer from 'multer';
|
||||
import path from 'path';
|
||||
import billingService from '../services/billingService.js';
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
const dir = 'uploads/billing-templates';
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
cb(null, dir);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname) || '.pdf';
|
||||
cb(null, `billing-template-${Date.now()}-${Math.round(Math.random() * 1e9)}${ext}`);
|
||||
}
|
||||
});
|
||||
|
||||
const upload = multer({
|
||||
storage,
|
||||
limits: { fileSize: 10 * 1024 * 1024 },
|
||||
fileFilter: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname || '').toLowerCase();
|
||||
const isPdf = ext === '.pdf' || (file.mimetype || '').includes('pdf');
|
||||
if (!isPdf) {
|
||||
return cb(new Error('Nur PDF-Dateien sind erlaubt.'));
|
||||
}
|
||||
cb(null, true);
|
||||
}
|
||||
});
|
||||
|
||||
export const uploadBillingTemplateMiddleware = upload.single('templatePdf');
|
||||
|
||||
export const listTemplates = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const result = await billingService.listTemplates(userToken, clubId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[listTemplates] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Vorlagen konnten nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const createTemplate = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const result = await billingService.createTemplate(userToken, clubId, req.body || {}, req.file);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[createTemplate] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Vorlage konnte nicht gespeichert werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteTemplate = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { templateId } = req.params;
|
||||
const result = await billingService.deleteTemplate(userToken, templateId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[deleteTemplate] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Vorlage konnte nicht gelöscht werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const updateTemplateFields = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { templateId } = req.params;
|
||||
const result = await billingService.saveTemplateFields(userToken, templateId, req.body?.fields || []);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[updateTemplateFields] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Felder konnten nicht gespeichert werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const createRun = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const result = await billingService.createRun(userToken, clubId, req.body || {});
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[createRun] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Abrechnungslauf konnte nicht erstellt werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const listRuns = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const result = await billingService.listRuns(userToken, clubId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[listRuns] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Abrechnungsläufe konnten nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const getRunDetails = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { runId } = req.params;
|
||||
const result = await billingService.getRunDetails(userToken, runId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[getRunDetails] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Abrechnungslauf konnte nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteRun = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { runId } = req.params;
|
||||
const result = await billingService.deleteRun(userToken, runId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[deleteRun] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Abrechnung konnte nicht gelöscht werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const getUserSettings = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const result = await billingService.getUserSettings(userToken, clubId);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[getUserSettings] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Einstellungen konnten nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const calculateHoursPreview = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { clubId } = req.params;
|
||||
const { monthFrom, monthTo } = req.query;
|
||||
const result = await billingService.calculateHoursPreview(userToken, clubId, monthFrom, monthTo);
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[calculateHoursPreview] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Stunden konnten nicht berechnet werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const generateRun = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { runId } = req.params;
|
||||
const result = await billingService.generateRun(userToken, runId, req.body || {});
|
||||
res.status(result.status).json(result.response);
|
||||
} catch (error) {
|
||||
console.error('[generateRun] Error:', error);
|
||||
const message = String(error?.message || '');
|
||||
if (message.includes('Formularfelder') || message.includes('Feldnamen') || message.includes('Fehlend:')) {
|
||||
return res.status(400).json({ success: false, error: message });
|
||||
}
|
||||
res.status(500).json({ success: false, error: 'Abrechnung konnte nicht erzeugt werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const downloadTemplatePdf = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { templateId } = req.params;
|
||||
const result = await billingService.downloadTemplatePdf(userToken, templateId);
|
||||
if (result.status !== 200) {
|
||||
return res.status(result.status).json(result.response);
|
||||
}
|
||||
res.setHeader('Content-Disposition', `inline; filename="${result.file.name}"`);
|
||||
res.setHeader('Content-Type', result.file.mimeType);
|
||||
return res.sendFile(result.file.path);
|
||||
} catch (error) {
|
||||
console.error('[downloadTemplatePdf] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'PDF konnte nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
|
||||
export const downloadRunPdf = async (req, res) => {
|
||||
try {
|
||||
const { authcode: userToken } = req.headers;
|
||||
const { runId } = req.params;
|
||||
const result = await billingService.downloadGeneratedRunPdf(userToken, runId);
|
||||
if (result.status !== 200) {
|
||||
return res.status(result.status).json(result.response);
|
||||
}
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${result.file.name}"`);
|
||||
res.setHeader('Content-Type', result.file.mimeType);
|
||||
return res.sendFile(result.file.path);
|
||||
} catch (error) {
|
||||
console.error('[downloadRunPdf] Error:', error);
|
||||
res.status(500).json({ success: false, error: 'Abrechnungs-PDF konnte nicht geladen werden.' });
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user