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,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);
}
}