first commit

This commit is contained in:
Stefan Hacker
2026-01-29 01:16:54 +01:00
commit 31f807fbd0
12106 changed files with 2480685 additions and 0 deletions
@@ -0,0 +1,75 @@
import { Response } from 'express';
import * as appSettingService from '../services/appSetting.service.js';
import { ApiResponse, AuthRequest } from '../types/index.js';
export async function getAllSettings(req: AuthRequest, res: Response): Promise<void> {
try {
const settings = await appSettingService.getAllSettings();
res.json({ success: true, data: settings } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Einstellungen',
} as ApiResponse);
}
}
export async function getPublicSettings(req: AuthRequest, res: Response): Promise<void> {
try {
const settings = await appSettingService.getPublicSettings();
res.json({ success: true, data: settings } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Einstellungen',
} as ApiResponse);
}
}
export async function updateSetting(req: AuthRequest, res: Response): Promise<void> {
try {
const { key } = req.params;
const { value } = req.body;
if (value === undefined) {
res.status(400).json({
success: false,
error: 'Wert ist erforderlich',
} as ApiResponse);
return;
}
await appSettingService.setSetting(key, String(value));
res.json({ success: true, message: 'Einstellung gespeichert' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Speichern der Einstellung',
} as ApiResponse);
}
}
export async function updateSettings(req: AuthRequest, res: Response): Promise<void> {
try {
const settings = req.body;
if (!settings || typeof settings !== 'object') {
res.status(400).json({
success: false,
error: 'Einstellungen sind erforderlich',
} as ApiResponse);
return;
}
for (const [key, value] of Object.entries(settings)) {
await appSettingService.setSetting(key, String(value));
}
res.json({ success: true, message: 'Einstellungen gespeichert' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Speichern der Einstellungen',
} as ApiResponse);
}
}
+132
View File
@@ -0,0 +1,132 @@
import { Request, Response } from 'express';
import * as authService from '../services/auth.service.js';
import { AuthRequest, ApiResponse } from '../types/index.js';
// Mitarbeiter-Login
export async function login(req: Request, res: Response): Promise<void> {
try {
const { email, password } = req.body;
if (!email || !password) {
res.status(400).json({
success: false,
error: 'E-Mail und Passwort erforderlich',
} as ApiResponse);
return;
}
const result = await authService.login(email, password);
res.json({ success: true, data: result } as ApiResponse);
} catch (error) {
res.status(401).json({
success: false,
error: error instanceof Error ? error.message : 'Anmeldung fehlgeschlagen',
} as ApiResponse);
}
}
// Kundenportal-Login
export async function customerLogin(req: Request, res: Response): Promise<void> {
try {
const { email, password } = req.body;
if (!email || !password) {
res.status(400).json({
success: false,
error: 'E-Mail und Passwort erforderlich',
} as ApiResponse);
return;
}
const result = await authService.customerLogin(email, password);
res.json({ success: true, data: result } as ApiResponse);
} catch (error) {
res.status(401).json({
success: false,
error: error instanceof Error ? error.message : 'Anmeldung fehlgeschlagen',
} as ApiResponse);
}
}
export async function me(req: AuthRequest, res: Response): Promise<void> {
try {
if (!req.user) {
res.status(401).json({
success: false,
error: 'Nicht authentifiziert',
} as ApiResponse);
return;
}
// Kundenportal-Login
if (req.user.isCustomerPortal && req.user.customerId) {
const customer = await authService.getCustomerPortalUser(req.user.customerId);
if (!customer) {
res.status(404).json({
success: false,
error: 'Kunde nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: customer } as ApiResponse);
return;
}
// Mitarbeiter-Login
if (!req.user.userId) {
res.status(401).json({
success: false,
error: 'Ungültige Authentifizierung',
} as ApiResponse);
return;
}
const user = await authService.getUserById(req.user.userId);
if (!user) {
res.status(404).json({
success: false,
error: 'Benutzer nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Benutzerdaten',
} as ApiResponse);
}
}
export async function register(req: Request, res: Response): Promise<void> {
try {
const { email, password, firstName, lastName, roleIds } = req.body;
if (!email || !password || !firstName || !lastName) {
res.status(400).json({
success: false,
error: 'Alle Pflichtfelder müssen ausgefüllt sein',
} as ApiResponse);
return;
}
const user = await authService.createUser({
email,
password,
firstName,
lastName,
roleIds: roleIds || [2], // Default to employee role
});
res.status(201).json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error:
error instanceof Error
? error.message
: 'Benutzer konnte nicht erstellt werden',
} as ApiResponse);
}
}
@@ -0,0 +1,71 @@
import { Request, Response } from 'express';
import * as cancellationPeriodService from '../services/cancellation-period.service.js';
import { ApiResponse } from '../types/index.js';
export async function getCancellationPeriods(req: Request, res: Response): Promise<void> {
try {
const includeInactive = req.query.includeInactive === 'true';
const periods = await cancellationPeriodService.getAllCancellationPeriods(includeInactive);
res.json({ success: true, data: periods } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Kündigungsfristen',
} as ApiResponse);
}
}
export async function getCancellationPeriod(req: Request, res: Response): Promise<void> {
try {
const period = await cancellationPeriodService.getCancellationPeriodById(parseInt(req.params.id));
if (!period) {
res.status(404).json({
success: false,
error: 'Kündigungsfrist nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: period } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Kündigungsfrist',
} as ApiResponse);
}
}
export async function createCancellationPeriod(req: Request, res: Response): Promise<void> {
try {
const period = await cancellationPeriodService.createCancellationPeriod(req.body);
res.status(201).json({ success: true, data: period } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Kündigungsfrist',
} as ApiResponse);
}
}
export async function updateCancellationPeriod(req: Request, res: Response): Promise<void> {
try {
const period = await cancellationPeriodService.updateCancellationPeriod(parseInt(req.params.id), req.body);
res.json({ success: true, data: period } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Kündigungsfrist',
} as ApiResponse);
}
}
export async function deleteCancellationPeriod(req: Request, res: Response): Promise<void> {
try {
await cancellationPeriodService.deleteCancellationPeriod(parseInt(req.params.id));
res.json({ success: true, message: 'Kündigungsfrist gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Kündigungsfrist',
} as ApiResponse);
}
}
@@ -0,0 +1,71 @@
import { Request, Response } from 'express';
import * as contractDurationService from '../services/contract-duration.service.js';
import { ApiResponse } from '../types/index.js';
export async function getContractDurations(req: Request, res: Response): Promise<void> {
try {
const includeInactive = req.query.includeInactive === 'true';
const durations = await contractDurationService.getAllContractDurations(includeInactive);
res.json({ success: true, data: durations } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Laufzeiten',
} as ApiResponse);
}
}
export async function getContractDuration(req: Request, res: Response): Promise<void> {
try {
const duration = await contractDurationService.getContractDurationById(parseInt(req.params.id));
if (!duration) {
res.status(404).json({
success: false,
error: 'Laufzeit nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: duration } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Laufzeit',
} as ApiResponse);
}
}
export async function createContractDuration(req: Request, res: Response): Promise<void> {
try {
const duration = await contractDurationService.createContractDuration(req.body);
res.status(201).json({ success: true, data: duration } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Laufzeit',
} as ApiResponse);
}
}
export async function updateContractDuration(req: Request, res: Response): Promise<void> {
try {
const duration = await contractDurationService.updateContractDuration(parseInt(req.params.id), req.body);
res.json({ success: true, data: duration } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Laufzeit',
} as ApiResponse);
}
}
export async function deleteContractDuration(req: Request, res: Response): Promise<void> {
try {
await contractDurationService.deleteContractDuration(parseInt(req.params.id));
res.json({ success: true, message: 'Laufzeit gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Laufzeit',
} as ApiResponse);
}
}
@@ -0,0 +1,187 @@
import { Request, Response } from 'express';
import * as contractService from '../services/contract.service.js';
import * as contractCockpitService from '../services/contractCockpit.service.js';
import { ApiResponse, AuthRequest } from '../types/index.js';
export async function getContracts(req: AuthRequest, res: Response): Promise<void> {
try {
const { customerId, type, status, search, page, limit } = req.query;
// Für Kundenportal-Benutzer: nur eigene + vertretene Kunden-Verträge anzeigen
let customerIds: number[] | undefined;
if (req.user?.isCustomerPortal && req.user.customerId) {
// Eigene Customer-ID + alle vertretenen Kunden-IDs
customerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
}
const result = await contractService.getAllContracts({
customerId: customerId ? parseInt(customerId as string) : undefined,
customerIds, // Wird nur für Kundenportal-Benutzer gesetzt
type: type as any,
status: status as any,
search: search as string,
page: page ? parseInt(page as string) : undefined,
limit: limit ? parseInt(limit as string) : undefined,
});
res.json({
success: true,
data: result.contracts,
pagination: result.pagination,
} as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Verträge',
} as ApiResponse);
}
}
export async function getContract(req: AuthRequest, res: Response): Promise<void> {
try {
const contract = await contractService.getContractById(parseInt(req.params.id));
if (!contract) {
res.status(404).json({
success: false,
error: 'Vertrag nicht gefunden',
} as ApiResponse);
return;
}
// Für Kundenportal-Benutzer: Zugriff nur auf eigene + vertretene Kunden-Verträge
if (req.user?.isCustomerPortal && req.user.customerId) {
const allowedCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
if (!allowedCustomerIds.includes(contract.customerId)) {
res.status(403).json({
success: false,
error: 'Kein Zugriff auf diesen Vertrag',
} as ApiResponse);
return;
}
}
res.json({ success: true, data: contract } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Vertrags',
} as ApiResponse);
}
}
export async function createContract(req: Request, res: Response): Promise<void> {
try {
const contract = await contractService.createContract(req.body);
res.status(201).json({ success: true, data: contract } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Vertrags',
} as ApiResponse);
}
}
export async function updateContract(req: Request, res: Response): Promise<void> {
try {
const contract = await contractService.updateContract(parseInt(req.params.id), req.body);
res.json({ success: true, data: contract } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Vertrags',
} as ApiResponse);
}
}
export async function deleteContract(req: Request, res: Response): Promise<void> {
try {
await contractService.deleteContract(parseInt(req.params.id));
res.json({ success: true, message: 'Vertrag gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Vertrags',
} as ApiResponse);
}
}
export async function createFollowUp(req: Request, res: Response): Promise<void> {
try {
const contract = await contractService.createFollowUpContract(parseInt(req.params.id));
res.status(201).json({ success: true, data: contract } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Folgevertrags',
} as ApiResponse);
}
}
export async function getContractPassword(req: Request, res: Response): Promise<void> {
try {
const password = await contractService.getContractPassword(parseInt(req.params.id));
if (password === null) {
res.status(404).json({
success: false,
error: 'Kein Passwort hinterlegt',
} as ApiResponse);
return;
}
res.json({ success: true, data: { password } } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Entschlüsseln des Passworts',
} as ApiResponse);
}
}
export async function getSimCardCredentials(req: Request, res: Response): Promise<void> {
try {
const credentials = await contractService.getSimCardCredentials(parseInt(req.params.simCardId));
res.json({ success: true, data: credentials } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Entschlüsseln der SIM-Karten-Daten',
} as ApiResponse);
}
}
export async function getInternetCredentials(req: Request, res: Response): Promise<void> {
try {
const credentials = await contractService.getInternetCredentials(parseInt(req.params.id));
res.json({ success: true, data: credentials } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Entschlüsseln des Internet-Passworts',
} as ApiResponse);
}
}
export async function getSipCredentials(req: Request, res: Response): Promise<void> {
try {
const credentials = await contractService.getSipCredentials(parseInt(req.params.phoneNumberId));
res.json({ success: true, data: credentials } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Entschlüsseln des SIP-Passworts',
} as ApiResponse);
}
}
// ==================== VERTRAGS-COCKPIT ====================
export async function getCockpit(req: AuthRequest, res: Response): Promise<void> {
try {
const cockpitData = await contractCockpitService.getCockpitData();
res.json({ success: true, data: cockpitData } as ApiResponse);
} catch (error) {
console.error('Cockpit error:', error);
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Vertrags-Cockpits',
} as ApiResponse);
}
}
@@ -0,0 +1,71 @@
import { Request, Response } from 'express';
import * as contractCategoryService from '../services/contractCategory.service.js';
import { ApiResponse } from '../types/index.js';
export async function getContractCategories(req: Request, res: Response): Promise<void> {
try {
const includeInactive = req.query.includeInactive === 'true';
const categories = await contractCategoryService.getAllContractCategories(includeInactive);
res.json({ success: true, data: categories } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Vertragskategorien',
} as ApiResponse);
}
}
export async function getContractCategory(req: Request, res: Response): Promise<void> {
try {
const category = await contractCategoryService.getContractCategoryById(parseInt(req.params.id));
if (!category) {
res.status(404).json({
success: false,
error: 'Vertragskategorie nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: category } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Vertragskategorie',
} as ApiResponse);
}
}
export async function createContractCategory(req: Request, res: Response): Promise<void> {
try {
const category = await contractCategoryService.createContractCategory(req.body);
res.status(201).json({ success: true, data: category } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Vertragskategorie',
} as ApiResponse);
}
}
export async function updateContractCategory(req: Request, res: Response): Promise<void> {
try {
const category = await contractCategoryService.updateContractCategory(parseInt(req.params.id), req.body);
res.json({ success: true, data: category } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Vertragskategorie',
} as ApiResponse);
}
}
export async function deleteContractCategory(req: Request, res: Response): Promise<void> {
try {
await contractCategoryService.deleteContractCategory(parseInt(req.params.id));
res.json({ success: true, message: 'Vertragskategorie gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Vertragskategorie',
} as ApiResponse);
}
}
@@ -0,0 +1,441 @@
import { Response } from 'express';
import * as contractTaskService from '../services/contractTask.service.js';
import * as contractService from '../services/contract.service.js';
import * as customerService from '../services/customer.service.js';
import * as appSettingService from '../services/appSetting.service.js';
import { ApiResponse, AuthRequest } from '../types/index.js';
// ==================== ALL TASKS (Dashboard & Task List) ====================
export async function getAllTasks(req: AuthRequest, res: Response): Promise<void> {
try {
const { status, customerId } = req.query;
// Für Kundenportal: Filter auf erlaubte Kunden
let customerPortalCustomerIds: number[] | undefined;
let customerPortalEmails: string[] | undefined;
if (req.user?.isCustomerPortal && req.user.customerId) {
customerPortalCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
const customers = await customerService.getCustomersByIds(customerPortalCustomerIds);
customerPortalEmails = customers
.map((c: { id: number; portalEmail: string | null }) => c.portalEmail)
.filter((email: string | null): email is string => !!email);
}
const tasks = await contractTaskService.getAllTasks({
status: status as 'OPEN' | 'COMPLETED' | undefined,
customerId: customerId ? parseInt(customerId as string) : undefined,
customerPortalCustomerIds,
customerPortalEmails,
});
res.json({ success: true, data: tasks } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Aufgaben',
} as ApiResponse);
}
}
export async function getTaskStats(req: AuthRequest, res: Response): Promise<void> {
try {
// Für Kundenportal: Filter auf erlaubte Kunden
let customerPortalCustomerIds: number[] | undefined;
let customerPortalEmails: string[] | undefined;
if (req.user?.isCustomerPortal && req.user.customerId) {
customerPortalCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
const customers = await customerService.getCustomersByIds(customerPortalCustomerIds);
customerPortalEmails = customers
.map((c: { id: number; portalEmail: string | null }) => c.portalEmail)
.filter((email: string | null): email is string => !!email);
}
const stats = await contractTaskService.getTaskStats({
customerPortalCustomerIds,
customerPortalEmails,
});
res.json({ success: true, data: stats } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Statistik',
} as ApiResponse);
}
}
// ==================== TASKS BY CONTRACT ====================
export async function getTasks(req: AuthRequest, res: Response): Promise<void> {
try {
const contractId = parseInt(req.params.contractId);
const { status } = req.query;
// Prüfe Zugriff auf den Vertrag
const contract = await contractService.getContractById(contractId);
if (!contract) {
res.status(404).json({
success: false,
error: 'Vertrag nicht gefunden',
} as ApiResponse);
return;
}
// Für Kundenportal: Zugriffsprüfung
if (req.user?.isCustomerPortal && req.user.customerId) {
const allowedCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
if (!allowedCustomerIds.includes(contract.customerId)) {
res.status(403).json({
success: false,
error: 'Kein Zugriff auf diesen Vertrag',
} as ApiResponse);
return;
}
}
// Für Kundenportal-Benutzer: Lade E-Mails der erlaubten Kunden
let customerPortalEmails: string[] | undefined;
if (req.user?.isCustomerPortal && req.user.customerId) {
const allowedCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
const customers = await customerService.getCustomersByIds(allowedCustomerIds);
customerPortalEmails = customers
.map((c: { id: number; portalEmail: string | null }) => c.portalEmail)
.filter((email: string | null): email is string => !!email);
}
const tasks = await contractTaskService.getTasksByContract({
contractId,
status: status as 'OPEN' | 'COMPLETED' | undefined,
customerPortalEmails,
});
res.json({ success: true, data: tasks } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Aufgaben',
} as ApiResponse);
}
}
export async function createTask(req: AuthRequest, res: Response): Promise<void> {
try {
const contractId = parseInt(req.params.contractId);
const { title, description, visibleInPortal } = req.body;
if (!title) {
res.status(400).json({
success: false,
error: 'Titel ist erforderlich',
} as ApiResponse);
return;
}
const createdBy = req.user?.email;
// Für Kundenportal-Benutzer: visibleInPortal wird automatisch auf true gesetzt
const finalVisibleInPortal = req.user?.isCustomerPortal ? true : visibleInPortal;
const task = await contractTaskService.createTask({
contractId,
title,
description,
visibleInPortal: finalVisibleInPortal,
createdBy,
});
res.status(201).json({ success: true, data: task } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Aufgabe',
} as ApiResponse);
}
}
// Für Kundenportal-Benutzer: Support-Anfrage erstellen (ohne contracts:update Permission)
export async function createSupportTicket(req: AuthRequest, res: Response): Promise<void> {
try {
// Prüfe ob Support-Tickets aktiviert sind
const supportEnabled = await appSettingService.getSettingBool('customerSupportTicketsEnabled');
if (!supportEnabled) {
res.status(403).json({
success: false,
error: 'Support-Anfragen sind nicht aktiviert',
} as ApiResponse);
return;
}
const contractId = parseInt(req.params.contractId);
const { title, description } = req.body;
if (!title) {
res.status(400).json({
success: false,
error: 'Titel ist erforderlich',
} as ApiResponse);
return;
}
// Prüfe Zugriff auf den Vertrag
const contract = await contractService.getContractById(contractId);
if (!contract) {
res.status(404).json({
success: false,
error: 'Vertrag nicht gefunden',
} as ApiResponse);
return;
}
// Zugriffsprüfung für Kundenportal
if (req.user?.customerId) {
const allowedCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
if (!allowedCustomerIds.includes(contract.customerId)) {
res.status(403).json({
success: false,
error: 'Kein Zugriff auf diesen Vertrag',
} as ApiResponse);
return;
}
}
const createdBy = req.user?.email;
const task = await contractTaskService.createTask({
contractId,
title,
description,
visibleInPortal: true, // Immer sichtbar im Portal
createdBy,
});
res.status(201).json({ success: true, data: task } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Support-Anfrage',
} as ApiResponse);
}
}
export async function updateTask(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
const { title, description, visibleInPortal } = req.body;
const task = await contractTaskService.updateTask(taskId, {
title,
description,
visibleInPortal,
});
res.json({ success: true, data: task } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Aufgabe',
} as ApiResponse);
}
}
export async function completeTask(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
const task = await contractTaskService.completeTask(taskId);
res.json({ success: true, data: task } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Abschließen der Aufgabe',
} as ApiResponse);
}
}
export async function reopenTask(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
const task = await contractTaskService.reopenTask(taskId);
res.json({ success: true, data: task } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Wiedereröffnen der Aufgabe',
} as ApiResponse);
}
}
export async function deleteTask(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
await contractTaskService.deleteTask(taskId);
res.json({ success: true, message: 'Aufgabe gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Aufgabe',
} as ApiResponse);
}
}
// ==================== SUBTASKS ====================
export async function createSubtask(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
const { title } = req.body;
if (!title) {
res.status(400).json({
success: false,
error: 'Titel ist erforderlich',
} as ApiResponse);
return;
}
const createdBy = req.user?.email;
const subtask = await contractTaskService.createSubtask({
taskId,
title,
createdBy,
});
res.status(201).json({ success: true, data: subtask } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Unteraufgabe',
} as ApiResponse);
}
}
// Kundenportal: Antwort auf eigenes Ticket erstellen
export async function createCustomerReply(req: AuthRequest, res: Response): Promise<void> {
try {
const taskId = parseInt(req.params.taskId);
const { title } = req.body;
if (!title) {
res.status(400).json({
success: false,
error: 'Antwort ist erforderlich',
} as ApiResponse);
return;
}
// Hole den Task
const task = await contractTaskService.getTaskById(taskId);
if (!task) {
res.status(404).json({
success: false,
error: 'Anfrage nicht gefunden',
} as ApiResponse);
return;
}
// Prüfe ob der Kunde berechtigt ist (eigenes Ticket oder freigegebener Kunde)
if (req.user?.isCustomerPortal && req.user.customerId) {
const allowedCustomerIds = [req.user.customerId, ...(req.user.representedCustomerIds || [])];
const customers = await customerService.getCustomersByIds(allowedCustomerIds);
const allowedEmails = customers
.map((c: { id: number; portalEmail: string | null }) => c.portalEmail)
.filter((email: string | null): email is string => !!email);
// Task muss entweder visibleInPortal sein ODER vom Kunden erstellt worden sein
const isOwnTask = task.createdBy && allowedEmails.includes(task.createdBy);
if (!task.visibleInPortal && !isOwnTask) {
res.status(403).json({
success: false,
error: 'Kein Zugriff auf diese Anfrage',
} as ApiResponse);
return;
}
} else {
res.status(403).json({
success: false,
error: 'Nur für Kundenportal-Benutzer',
} as ApiResponse);
return;
}
const createdBy = req.user?.email;
const subtask = await contractTaskService.createSubtask({
taskId,
title,
createdBy,
});
res.status(201).json({ success: true, data: subtask } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Antwort',
} as ApiResponse);
}
}
export async function updateSubtask(req: AuthRequest, res: Response): Promise<void> {
try {
const subtaskId = parseInt(req.params.subtaskId);
const { title } = req.body;
if (!title) {
res.status(400).json({
success: false,
error: 'Titel ist erforderlich',
} as ApiResponse);
return;
}
const subtask = await contractTaskService.updateSubtask(subtaskId, { title });
res.json({ success: true, data: subtask } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Unteraufgabe',
} as ApiResponse);
}
}
export async function completeSubtask(req: AuthRequest, res: Response): Promise<void> {
try {
const subtaskId = parseInt(req.params.subtaskId);
const subtask = await contractTaskService.completeSubtask(subtaskId);
res.json({ success: true, data: subtask } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Abschließen der Unteraufgabe',
} as ApiResponse);
}
}
export async function reopenSubtask(req: AuthRequest, res: Response): Promise<void> {
try {
const subtaskId = parseInt(req.params.subtaskId);
const subtask = await contractTaskService.reopenSubtask(subtaskId);
res.json({ success: true, data: subtask } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Wiedereröffnen der Unteraufgabe',
} as ApiResponse);
}
}
export async function deleteSubtask(req: AuthRequest, res: Response): Promise<void> {
try {
const subtaskId = parseInt(req.params.subtaskId);
await contractTaskService.deleteSubtask(subtaskId);
res.json({ success: true, message: 'Unteraufgabe gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Unteraufgabe',
} as ApiResponse);
}
}
@@ -0,0 +1,475 @@
import { Request, Response } from 'express';
import * as customerService from '../services/customer.service.js';
import * as authService from '../services/auth.service.js';
import { ApiResponse } from '../types/index.js';
// Customer CRUD
export async function getCustomers(req: Request, res: Response): Promise<void> {
try {
const { search, type, page, limit } = req.query;
const result = await customerService.getAllCustomers({
search: search as string,
type: type as 'PRIVATE' | 'BUSINESS',
page: page ? parseInt(page as string) : undefined,
limit: limit ? parseInt(limit as string) : undefined,
});
res.json({ success: true, data: result.customers, pagination: result.pagination } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Kunden',
} as ApiResponse);
}
}
export async function getCustomer(req: Request, res: Response): Promise<void> {
try {
const customer = await customerService.getCustomerById(parseInt(req.params.id));
if (!customer) {
res.status(404).json({ success: false, error: 'Kunde nicht gefunden' } as ApiResponse);
return;
}
res.json({ success: true, data: customer } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden des Kunden' } as ApiResponse);
}
}
export async function createCustomer(req: Request, res: Response): Promise<void> {
try {
const data = { ...req.body };
// Convert birthDate string to Date if present
if (data.birthDate) {
data.birthDate = new Date(data.birthDate);
}
const customer = await customerService.createCustomer(data);
res.status(201).json({ success: true, data: customer } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Kunden',
} as ApiResponse);
}
}
export async function updateCustomer(req: Request, res: Response): Promise<void> {
try {
const data = { ...req.body };
// Convert birthDate string to Date if present
if (data.birthDate) {
data.birthDate = new Date(data.birthDate);
}
const customer = await customerService.updateCustomer(parseInt(req.params.id), data);
res.json({ success: true, data: customer } as ApiResponse);
} catch (error) {
console.error('Update customer error:', error);
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Kunden',
} as ApiResponse);
}
}
export async function deleteCustomer(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteCustomer(parseInt(req.params.id));
res.json({ success: true, message: 'Kunde gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Kunden',
} as ApiResponse);
}
}
// Addresses
export async function getAddresses(req: Request, res: Response): Promise<void> {
try {
const addresses = await customerService.getCustomerAddresses(parseInt(req.params.customerId));
res.json({ success: true, data: addresses } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden der Adressen' } as ApiResponse);
}
}
export async function createAddress(req: Request, res: Response): Promise<void> {
try {
const address = await customerService.createAddress(parseInt(req.params.customerId), req.body);
res.status(201).json({ success: true, data: address } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Adresse',
} as ApiResponse);
}
}
export async function updateAddress(req: Request, res: Response): Promise<void> {
try {
const address = await customerService.updateAddress(parseInt(req.params.id), req.body);
res.json({ success: true, data: address } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Adresse',
} as ApiResponse);
}
}
export async function deleteAddress(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteAddress(parseInt(req.params.id));
res.json({ success: true, message: 'Adresse gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Adresse',
} as ApiResponse);
}
}
// Bank Cards
export async function getBankCards(req: Request, res: Response): Promise<void> {
try {
const showInactive = req.query.showInactive === 'true';
const cards = await customerService.getCustomerBankCards(
parseInt(req.params.customerId),
showInactive
);
res.json({ success: true, data: cards } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden der Bankkarten' } as ApiResponse);
}
}
export async function createBankCard(req: Request, res: Response): Promise<void> {
try {
const card = await customerService.createBankCard(parseInt(req.params.customerId), req.body);
res.status(201).json({ success: true, data: card } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Bankkarte',
} as ApiResponse);
}
}
export async function updateBankCard(req: Request, res: Response): Promise<void> {
try {
const card = await customerService.updateBankCard(parseInt(req.params.id), req.body);
res.json({ success: true, data: card } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Bankkarte',
} as ApiResponse);
}
}
export async function deleteBankCard(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteBankCard(parseInt(req.params.id));
res.json({ success: true, message: 'Bankkarte gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Bankkarte',
} as ApiResponse);
}
}
// Identity Documents
export async function getDocuments(req: Request, res: Response): Promise<void> {
try {
const showInactive = req.query.showInactive === 'true';
const docs = await customerService.getCustomerDocuments(
parseInt(req.params.customerId),
showInactive
);
res.json({ success: true, data: docs } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden der Ausweise' } as ApiResponse);
}
}
export async function createDocument(req: Request, res: Response): Promise<void> {
try {
const doc = await customerService.createDocument(parseInt(req.params.customerId), req.body);
res.status(201).json({ success: true, data: doc } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Ausweises',
} as ApiResponse);
}
}
export async function updateDocument(req: Request, res: Response): Promise<void> {
try {
const doc = await customerService.updateDocument(parseInt(req.params.id), req.body);
res.json({ success: true, data: doc } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Ausweises',
} as ApiResponse);
}
}
export async function deleteDocument(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteDocument(parseInt(req.params.id));
res.json({ success: true, message: 'Ausweis gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Ausweises',
} as ApiResponse);
}
}
// Meters
export async function getMeters(req: Request, res: Response): Promise<void> {
try {
const showInactive = req.query.showInactive === 'true';
const meters = await customerService.getCustomerMeters(
parseInt(req.params.customerId),
showInactive
);
res.json({ success: true, data: meters } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden der Zähler' } as ApiResponse);
}
}
export async function createMeter(req: Request, res: Response): Promise<void> {
try {
const meter = await customerService.createMeter(parseInt(req.params.customerId), req.body);
res.status(201).json({ success: true, data: meter } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Zählers',
} as ApiResponse);
}
}
export async function updateMeter(req: Request, res: Response): Promise<void> {
try {
const meter = await customerService.updateMeter(parseInt(req.params.id), req.body);
res.json({ success: true, data: meter } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Zählers',
} as ApiResponse);
}
}
export async function deleteMeter(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteMeter(parseInt(req.params.id));
res.json({ success: true, message: 'Zähler gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Zählers',
} as ApiResponse);
}
}
// Meter Readings
export async function getMeterReadings(req: Request, res: Response): Promise<void> {
try {
const readings = await customerService.getMeterReadings(parseInt(req.params.meterId));
res.json({ success: true, data: readings } as ApiResponse);
} catch (error) {
res.status(500).json({ success: false, error: 'Fehler beim Laden der Zählerstände' } as ApiResponse);
}
}
export async function addMeterReading(req: Request, res: Response): Promise<void> {
try {
const reading = await customerService.addMeterReading(parseInt(req.params.meterId), req.body);
res.status(201).json({ success: true, data: reading } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Hinzufügen des Zählerstands',
} as ApiResponse);
}
}
export async function updateMeterReading(req: Request, res: Response): Promise<void> {
try {
const reading = await customerService.updateMeterReading(
parseInt(req.params.meterId),
parseInt(req.params.readingId),
req.body
);
res.json({ success: true, data: reading } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Zählerstands',
} as ApiResponse);
}
}
export async function deleteMeterReading(req: Request, res: Response): Promise<void> {
try {
await customerService.deleteMeterReading(
parseInt(req.params.meterId),
parseInt(req.params.readingId)
);
res.json({ success: true, data: null } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Zählerstands',
} as ApiResponse);
}
}
// ==================== PORTAL SETTINGS ====================
export async function getPortalSettings(req: Request, res: Response): Promise<void> {
try {
const settings = await customerService.getPortalSettings(parseInt(req.params.customerId));
if (!settings) {
res.status(404).json({ success: false, error: 'Kunde nicht gefunden' } as ApiResponse);
return;
}
// Passwort-Hash nicht zurückgeben, nur ob ein Passwort gesetzt ist
res.json({
success: true,
data: {
id: settings.id,
portalEnabled: settings.portalEnabled,
portalEmail: settings.portalEmail,
portalLastLogin: settings.portalLastLogin,
hasPassword: !!settings.portalPasswordHash,
},
} as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Portal-Einstellungen',
} as ApiResponse);
}
}
export async function updatePortalSettings(req: Request, res: Response): Promise<void> {
try {
const { portalEnabled, portalEmail } = req.body;
const settings = await customerService.updatePortalSettings(parseInt(req.params.customerId), {
portalEnabled,
portalEmail,
});
res.json({ success: true, data: settings } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Portal-Einstellungen',
} as ApiResponse);
}
}
export async function setPortalPassword(req: Request, res: Response): Promise<void> {
try {
const { password } = req.body;
if (!password || password.length < 6) {
res.status(400).json({
success: false,
error: 'Passwort muss mindestens 6 Zeichen lang sein',
} as ApiResponse);
return;
}
await authService.setCustomerPortalPassword(parseInt(req.params.customerId), password);
res.json({ success: true, message: 'Passwort gesetzt' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Setzen des Passworts',
} as ApiResponse);
}
}
export async function getPortalPassword(req: Request, res: Response): Promise<void> {
try {
const password = await authService.getCustomerPortalPassword(parseInt(req.params.customerId));
res.json({ success: true, data: { password } } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Abrufen des Passworts',
} as ApiResponse);
}
}
// ==================== REPRESENTATIVE MANAGEMENT ====================
export async function getRepresentatives(req: Request, res: Response): Promise<void> {
try {
// Wer kann diesen Kunden vertreten (representedBy)?
const representedBy = await customerService.getRepresentedByList(parseInt(req.params.customerId));
res.json({ success: true, data: representedBy } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Vertreter',
} as ApiResponse);
}
}
export async function addRepresentative(req: Request, res: Response): Promise<void> {
try {
const { representativeId, notes } = req.body;
const representative = await customerService.addRepresentative(
parseInt(req.params.customerId),
parseInt(representativeId),
notes
);
res.status(201).json({ success: true, data: representative } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Hinzufügen des Vertreters',
} as ApiResponse);
}
}
export async function removeRepresentative(req: Request, res: Response): Promise<void> {
try {
await customerService.removeRepresentative(
parseInt(req.params.customerId),
parseInt(req.params.representativeId)
);
res.json({ success: true, message: 'Vertreter entfernt' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Entfernen des Vertreters',
} as ApiResponse);
}
}
export async function searchForRepresentative(req: Request, res: Response): Promise<void> {
try {
const { search } = req.query;
if (!search || typeof search !== 'string' || search.length < 2) {
res.json({ success: true, data: [] } as ApiResponse);
return;
}
const customers = await customerService.searchCustomersForRepresentative(
search,
parseInt(req.params.customerId)
);
res.json({ success: true, data: customers } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler bei der Suche',
} as ApiResponse);
}
}
@@ -0,0 +1,166 @@
// ==================== EMAIL PROVIDER CONTROLLER ====================
import { Request, Response } from 'express';
import * as emailProviderService from '../services/emailProvider/emailProviderService.js';
import { ApiResponse } from '../types/index.js';
// ==================== CONFIG CRUD ====================
export async function getProviderConfigs(req: Request, res: Response): Promise<void> {
try {
const configs = await emailProviderService.getAllProviderConfigs();
res.json({ success: true, data: configs } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Email-Provider',
} as ApiResponse);
}
}
export async function getProviderConfig(req: Request, res: Response): Promise<void> {
try {
const id = parseInt(req.params.id);
const config = await emailProviderService.getProviderConfigById(id);
if (!config) {
res.status(404).json({
success: false,
error: 'Email-Provider nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: config } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Email-Providers',
} as ApiResponse);
}
}
export async function createProviderConfig(req: Request, res: Response): Promise<void> {
try {
const config = await emailProviderService.createProviderConfig(req.body);
res.status(201).json({ success: true, data: config } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Email-Providers',
} as ApiResponse);
}
}
export async function updateProviderConfig(req: Request, res: Response): Promise<void> {
try {
const id = parseInt(req.params.id);
const config = await emailProviderService.updateProviderConfig(id, req.body);
res.json({ success: true, data: config } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Email-Providers',
} as ApiResponse);
}
}
export async function deleteProviderConfig(req: Request, res: Response): Promise<void> {
try {
const id = parseInt(req.params.id);
await emailProviderService.deleteProviderConfig(id);
res.json({ success: true, message: 'Email-Provider gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Email-Providers',
} as ApiResponse);
}
}
// ==================== EMAIL OPERATIONS ====================
export async function testConnection(req: Request, res: Response): Promise<void> {
try {
// Option 1: Provider-ID für gespeicherten Provider
const id = req.body?.id ? parseInt(req.body.id) : undefined;
// Option 2: Testdaten aus Body (für Test im Modal mit ungespeicherten Daten)
const testData = req.body && req.body.type ? {
type: req.body.type as 'PLESK' | 'CPANEL' | 'DIRECTADMIN',
apiUrl: req.body.apiUrl,
apiKey: req.body.apiKey || undefined,
username: req.body.username || undefined,
password: req.body.password || undefined,
domain: req.body.domain,
} : undefined;
const result = await emailProviderService.testProviderConnection({ id, testData });
res.json({ success: result.success, data: result } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Verbindungstest fehlgeschlagen',
} as ApiResponse);
}
}
export async function checkEmailExists(req: Request, res: Response): Promise<void> {
try {
const { localPart } = req.params;
const result = await emailProviderService.checkEmailExists(localPart);
res.json({ success: true, data: result } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler bei der E-Mail-Prüfung',
} as ApiResponse);
}
}
export async function provisionEmail(req: Request, res: Response): Promise<void> {
try {
const { localPart, customerEmail } = req.body;
if (!localPart || !customerEmail) {
res.status(400).json({
success: false,
error: 'localPart und customerEmail sind erforderlich',
} as ApiResponse);
return;
}
const result = await emailProviderService.provisionEmail(localPart, customerEmail);
res.json({ success: result.success, data: result } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler bei der E-Mail-Provisionierung',
} as ApiResponse);
}
}
export async function deprovisionEmail(req: Request, res: Response): Promise<void> {
try {
const { localPart } = req.params;
const result = await emailProviderService.deprovisionEmail(localPart);
res.json({ success: result.success, data: result } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der E-Mail',
} as ApiResponse);
}
}
export async function getProviderDomain(req: Request, res: Response): Promise<void> {
try {
const domain = await emailProviderService.getProviderDomain();
res.json({ success: true, data: { domain } } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Domain',
} as ApiResponse);
}
}
@@ -0,0 +1,71 @@
import { Request, Response } from 'express';
import * as platformService from '../services/platform.service.js';
import { ApiResponse } from '../types/index.js';
export async function getPlatforms(req: Request, res: Response): Promise<void> {
try {
const includeInactive = req.query.includeInactive === 'true';
const platforms = await platformService.getAllPlatforms(includeInactive);
res.json({ success: true, data: platforms } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Vertriebsplattformen',
} as ApiResponse);
}
}
export async function getPlatform(req: Request, res: Response): Promise<void> {
try {
const platform = await platformService.getPlatformById(parseInt(req.params.id));
if (!platform) {
res.status(404).json({
success: false,
error: 'Vertriebsplattform nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: platform } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Vertriebsplattform',
} as ApiResponse);
}
}
export async function createPlatform(req: Request, res: Response): Promise<void> {
try {
const platform = await platformService.createPlatform(req.body);
res.status(201).json({ success: true, data: platform } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Vertriebsplattform',
} as ApiResponse);
}
}
export async function updatePlatform(req: Request, res: Response): Promise<void> {
try {
const platform = await platformService.updatePlatform(parseInt(req.params.id), req.body);
res.json({ success: true, data: platform } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Vertriebsplattform',
} as ApiResponse);
}
}
export async function deletePlatform(req: Request, res: Response): Promise<void> {
try {
await platformService.deletePlatform(parseInt(req.params.id));
res.json({ success: true, message: 'Vertriebsplattform gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Vertriebsplattform',
} as ApiResponse);
}
}
@@ -0,0 +1,71 @@
import { Request, Response } from 'express';
import * as providerService from '../services/provider.service.js';
import { ApiResponse } from '../types/index.js';
export async function getProviders(req: Request, res: Response): Promise<void> {
try {
const includeInactive = req.query.includeInactive === 'true';
const providers = await providerService.getAllProviders(includeInactive);
res.json({ success: true, data: providers } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Anbieter',
} as ApiResponse);
}
}
export async function getProvider(req: Request, res: Response): Promise<void> {
try {
const provider = await providerService.getProviderById(parseInt(req.params.id));
if (!provider) {
res.status(404).json({
success: false,
error: 'Anbieter nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: provider } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Anbieters',
} as ApiResponse);
}
}
export async function createProvider(req: Request, res: Response): Promise<void> {
try {
const provider = await providerService.createProvider(req.body);
res.status(201).json({ success: true, data: provider } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Anbieters',
} as ApiResponse);
}
}
export async function updateProvider(req: Request, res: Response): Promise<void> {
try {
const provider = await providerService.updateProvider(parseInt(req.params.id), req.body);
res.json({ success: true, data: provider } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Anbieters',
} as ApiResponse);
}
}
export async function deleteProvider(req: Request, res: Response): Promise<void> {
try {
await providerService.deleteProvider(parseInt(req.params.id));
res.json({ success: true, message: 'Anbieter gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Anbieters',
} as ApiResponse);
}
}
@@ -0,0 +1,76 @@
import { Request, Response } from 'express';
import * as stressfreiEmailService from '../services/stressfreiEmail.service.js';
import { ApiResponse } from '../types/index.js';
export async function getEmailsByCustomer(req: Request, res: Response): Promise<void> {
try {
const customerId = parseInt(req.params.customerId);
const includeInactive = req.query.includeInactive === 'true';
const emails = await stressfreiEmailService.getEmailsByCustomerId(customerId, includeInactive);
res.json({ success: true, data: emails } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Stressfrei-Wechseln Adressen',
} as ApiResponse);
}
}
export async function getEmail(req: Request, res: Response): Promise<void> {
try {
const email = await stressfreiEmailService.getEmailById(parseInt(req.params.id));
if (!email) {
res.status(404).json({
success: false,
error: 'Stressfrei-Wechseln Adresse nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: email } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Stressfrei-Wechseln Adresse',
} as ApiResponse);
}
}
export async function createEmail(req: Request, res: Response): Promise<void> {
try {
const customerId = parseInt(req.params.customerId);
const email = await stressfreiEmailService.createEmail({
...req.body,
customerId,
});
res.status(201).json({ success: true, data: email } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Stressfrei-Wechseln Adresse',
} as ApiResponse);
}
}
export async function updateEmail(req: Request, res: Response): Promise<void> {
try {
const email = await stressfreiEmailService.updateEmail(parseInt(req.params.id), req.body);
res.json({ success: true, data: email } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Stressfrei-Wechseln Adresse',
} as ApiResponse);
}
}
export async function deleteEmail(req: Request, res: Response): Promise<void> {
try {
await stressfreiEmailService.deleteEmail(parseInt(req.params.id));
res.json({ success: true, message: 'Stressfrei-Wechseln Adresse gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Stressfrei-Wechseln Adresse',
} as ApiResponse);
}
}
@@ -0,0 +1,73 @@
import { Request, Response } from 'express';
import * as tariffService from '../services/tariff.service.js';
import { ApiResponse } from '../types/index.js';
export async function getTariffs(req: Request, res: Response): Promise<void> {
try {
const providerId = parseInt(req.params.providerId);
const includeInactive = req.query.includeInactive === 'true';
const tariffs = await tariffService.getTariffsByProvider(providerId, includeInactive);
res.json({ success: true, data: tariffs } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Tarife',
} as ApiResponse);
}
}
export async function getTariff(req: Request, res: Response): Promise<void> {
try {
const tariff = await tariffService.getTariffById(parseInt(req.params.id));
if (!tariff) {
res.status(404).json({
success: false,
error: 'Tarif nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: tariff } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Tarifs',
} as ApiResponse);
}
}
export async function createTariff(req: Request, res: Response): Promise<void> {
try {
const providerId = parseInt(req.params.providerId);
const tariff = await tariffService.createTariff({ ...req.body, providerId });
res.status(201).json({ success: true, data: tariff } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Tarifs',
} as ApiResponse);
}
}
export async function updateTariff(req: Request, res: Response): Promise<void> {
try {
const tariff = await tariffService.updateTariff(parseInt(req.params.id), req.body);
res.json({ success: true, data: tariff } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Tarifs',
} as ApiResponse);
}
}
export async function deleteTariff(req: Request, res: Response): Promise<void> {
try {
await tariffService.deleteTariff(parseInt(req.params.id));
res.json({ success: true, message: 'Tarif gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Tarifs',
} as ApiResponse);
}
}
+163
View File
@@ -0,0 +1,163 @@
import { Request, Response } from 'express';
import * as userService from '../services/user.service.js';
import { ApiResponse } from '../types/index.js';
// Users
export async function getUsers(req: Request, res: Response): Promise<void> {
try {
const { search, isActive, roleId, page, limit } = req.query;
const result = await userService.getAllUsers({
search: search as string,
isActive: isActive !== undefined ? isActive === 'true' : undefined,
roleId: roleId ? parseInt(roleId as string) : undefined,
page: page ? parseInt(page as string) : undefined,
limit: limit ? parseInt(limit as string) : undefined,
});
res.json({
success: true,
data: result.users,
pagination: result.pagination,
} as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Benutzer',
} as ApiResponse);
}
}
export async function getUser(req: Request, res: Response): Promise<void> {
try {
const user = await userService.getUserById(parseInt(req.params.id));
if (!user) {
res.status(404).json({
success: false,
error: 'Benutzer nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden des Benutzers',
} as ApiResponse);
}
}
export async function createUser(req: Request, res: Response): Promise<void> {
try {
const user = await userService.createUser(req.body);
res.status(201).json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen des Benutzers',
} as ApiResponse);
}
}
export async function updateUser(req: Request, res: Response): Promise<void> {
try {
const user = await userService.updateUser(parseInt(req.params.id), req.body);
res.json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren des Benutzers',
} as ApiResponse);
}
}
export async function deleteUser(req: Request, res: Response): Promise<void> {
try {
await userService.deleteUser(parseInt(req.params.id));
res.json({ success: true, message: 'Benutzer gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen des Benutzers',
} as ApiResponse);
}
}
// Roles
export async function getRoles(req: Request, res: Response): Promise<void> {
try {
const roles = await userService.getAllRoles();
res.json({ success: true, data: roles } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Rollen',
} as ApiResponse);
}
}
export async function getRole(req: Request, res: Response): Promise<void> {
try {
const role = await userService.getRoleById(parseInt(req.params.id));
if (!role) {
res.status(404).json({
success: false,
error: 'Rolle nicht gefunden',
} as ApiResponse);
return;
}
res.json({ success: true, data: role } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Rolle',
} as ApiResponse);
}
}
export async function createRole(req: Request, res: Response): Promise<void> {
try {
const role = await userService.createRole(req.body);
res.status(201).json({ success: true, data: role } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Erstellen der Rolle',
} as ApiResponse);
}
}
export async function updateRole(req: Request, res: Response): Promise<void> {
try {
const role = await userService.updateRole(parseInt(req.params.id), req.body);
res.json({ success: true, data: role } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Aktualisieren der Rolle',
} as ApiResponse);
}
}
export async function deleteRole(req: Request, res: Response): Promise<void> {
try {
await userService.deleteRole(parseInt(req.params.id));
res.json({ success: true, message: 'Rolle gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
success: false,
error: error instanceof Error ? error.message : 'Fehler beim Löschen der Rolle',
} as ApiResponse);
}
}
// Permissions
export async function getPermissions(req: Request, res: Response): Promise<void> {
try {
const permissions = await userService.getAllPermissions();
res.json({ success: true, data: permissions } as ApiResponse);
} catch (error) {
res.status(500).json({
success: false,
error: 'Fehler beim Laden der Berechtigungen',
} as ApiResponse);
}
}