"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAllCustomers = getAllCustomers; exports.getCustomerById = getCustomerById; exports.getCustomersByIds = getCustomersByIds; exports.createCustomer = createCustomer; exports.updateCustomer = updateCustomer; exports.deleteCustomer = deleteCustomer; exports.getCustomerAddresses = getCustomerAddresses; exports.createAddress = createAddress; exports.updateAddress = updateAddress; exports.deleteAddress = deleteAddress; exports.getCustomerBankCards = getCustomerBankCards; exports.createBankCard = createBankCard; exports.updateBankCard = updateBankCard; exports.deleteBankCard = deleteBankCard; exports.getCustomerDocuments = getCustomerDocuments; exports.createDocument = createDocument; exports.updateDocument = updateDocument; exports.deleteDocument = deleteDocument; exports.getCustomerMeters = getCustomerMeters; exports.createMeter = createMeter; exports.updateMeter = updateMeter; exports.deleteMeter = deleteMeter; exports.addMeterReading = addMeterReading; exports.getMeterReadings = getMeterReadings; exports.updateMeterReading = updateMeterReading; exports.deleteMeterReading = deleteMeterReading; exports.updatePortalSettings = updatePortalSettings; exports.getPortalSettings = getPortalSettings; exports.getCustomerRepresentatives = getCustomerRepresentatives; exports.getRepresentedByList = getRepresentedByList; exports.addRepresentative = addRepresentative; exports.removeRepresentative = removeRepresentative; exports.searchCustomersForRepresentative = searchCustomersForRepresentative; const client_1 = require("@prisma/client"); const helpers_js_1 = require("../utils/helpers.js"); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const prisma = new client_1.PrismaClient(); // Helper zum Löschen von Dateien function deleteFileIfExists(filePath) { if (!filePath) return; const absolutePath = path_1.default.join(process.cwd(), filePath); if (fs_1.default.existsSync(absolutePath)) { try { fs_1.default.unlinkSync(absolutePath); } catch (error) { console.error('Fehler beim Löschen der Datei:', absolutePath, error); } } } async function getAllCustomers(filters) { const { search, type, page = 1, limit = 20 } = filters; const { skip, take } = (0, helpers_js_1.paginate)(page, limit); const where = {}; if (type) { where.type = type; } if (search) { where.OR = [ { firstName: { contains: search } }, { lastName: { contains: search } }, { companyName: { contains: search } }, { email: { contains: search } }, { customerNumber: { contains: search } }, ]; } const [customers, total] = await Promise.all([ prisma.customer.findMany({ where, skip, take, orderBy: { createdAt: 'desc' }, include: { addresses: { where: { isDefault: true }, take: 1 }, _count: { select: { contracts: true }, }, }, }), prisma.customer.count({ where }), ]); return { customers, pagination: (0, helpers_js_1.buildPaginationResponse)(page, limit, total), }; } async function getCustomerById(id) { return prisma.customer.findUnique({ where: { id }, include: { addresses: true, bankCards: { orderBy: { isActive: 'desc' } }, identityDocuments: { orderBy: { isActive: 'desc' } }, meters: { orderBy: { isActive: 'desc' }, include: { readings: { orderBy: { readingDate: 'desc' }, }, }, }, stressfreiEmails: { orderBy: { isActive: 'desc' } }, contracts: { where: { // Deaktivierte Verträge ausblenden status: { not: client_1.ContractStatus.DEACTIVATED }, }, orderBy: [{ startDate: 'desc' }, { createdAt: 'desc' }], include: { address: true, salesPlatform: true, }, }, }, }); } async function getCustomersByIds(ids) { return prisma.customer.findMany({ where: { id: { in: ids } }, select: { id: true, portalEmail: true, }, }); } async function createCustomer(data) { return prisma.customer.create({ data: { ...data, customerNumber: (0, helpers_js_1.generateCustomerNumber)(), }, }); } async function updateCustomer(id, data) { return prisma.customer.update({ where: { id }, data, }); } async function deleteCustomer(id) { // Vor dem Löschen: Alle Dokumente (Dateien) des Kunden löschen const customer = await prisma.customer.findUnique({ where: { id }, select: { businessRegistrationPath: true, commercialRegisterPath: true, privacyPolicyPath: true }, }); const bankCards = await prisma.bankCard.findMany({ where: { customerId: id }, select: { documentPath: true }, }); const identityDocs = await prisma.identityDocument.findMany({ where: { customerId: id }, select: { documentPath: true }, }); // Kundendokumente löschen if (customer) { deleteFileIfExists(customer.businessRegistrationPath); deleteFileIfExists(customer.commercialRegisterPath); deleteFileIfExists(customer.privacyPolicyPath); } // Bankkarten- und Ausweisdokumente löschen for (const card of bankCards) { deleteFileIfExists(card.documentPath); } for (const doc of identityDocs) { deleteFileIfExists(doc.documentPath); } // Jetzt DB-Eintrag löschen (Cascade löscht die verknüpften Einträge) return prisma.customer.delete({ where: { id }, }); } // Address operations async function getCustomerAddresses(customerId) { return prisma.address.findMany({ where: { customerId }, orderBy: [{ isDefault: 'desc' }, { createdAt: 'desc' }], }); } async function createAddress(customerId, data) { // If this is set as default, unset other defaults of same type if (data.isDefault) { await prisma.address.updateMany({ where: { customerId, type: data.type }, data: { isDefault: false }, }); } return prisma.address.create({ data: { customerId, ...data, }, }); } async function updateAddress(id, data) { const address = await prisma.address.findUnique({ where: { id } }); if (!address) throw new Error('Adresse nicht gefunden'); if (data.isDefault) { await prisma.address.updateMany({ where: { customerId: address.customerId, type: data.type || address.type, id: { not: id }, }, data: { isDefault: false }, }); } return prisma.address.update({ where: { id }, data, }); } async function deleteAddress(id) { return prisma.address.delete({ where: { id } }); } // Bank card operations async function getCustomerBankCards(customerId, showInactive = false) { const where = { customerId }; if (!showInactive) { where.isActive = true; } return prisma.bankCard.findMany({ where, orderBy: [{ isActive: 'desc' }, { createdAt: 'desc' }], }); } async function createBankCard(customerId, data) { return prisma.bankCard.create({ data: { customerId, ...data, isActive: true, }, }); } async function updateBankCard(id, data) { return prisma.bankCard.update({ where: { id }, data, }); } async function deleteBankCard(id) { // Erst Datei-Pfad holen, dann Datei löschen, dann DB-Eintrag löschen const bankCard = await prisma.bankCard.findUnique({ where: { id } }); if (bankCard?.documentPath) { deleteFileIfExists(bankCard.documentPath); } return prisma.bankCard.delete({ where: { id } }); } // Identity document operations async function getCustomerDocuments(customerId, showInactive = false) { const where = { customerId }; if (!showInactive) { where.isActive = true; } return prisma.identityDocument.findMany({ where, orderBy: [{ isActive: 'desc' }, { createdAt: 'desc' }], }); } async function createDocument(customerId, data) { return prisma.identityDocument.create({ data: { customerId, ...data, isActive: true, }, }); } async function updateDocument(id, data) { return prisma.identityDocument.update({ where: { id }, data, }); } async function deleteDocument(id) { // Erst Datei-Pfad holen, dann Datei löschen, dann DB-Eintrag löschen const document = await prisma.identityDocument.findUnique({ where: { id } }); if (document?.documentPath) { deleteFileIfExists(document.documentPath); } return prisma.identityDocument.delete({ where: { id } }); } // Meter operations async function getCustomerMeters(customerId, showInactive = false) { const where = { customerId }; if (!showInactive) { where.isActive = true; } return prisma.meter.findMany({ where, include: { readings: { orderBy: { readingDate: 'desc' }, take: 5, }, }, orderBy: [{ isActive: 'desc' }, { createdAt: 'desc' }], }); } async function createMeter(customerId, data) { return prisma.meter.create({ data: { customerId, ...data, isActive: true, }, }); } async function updateMeter(id, data) { return prisma.meter.update({ where: { id }, data, }); } async function deleteMeter(id) { return prisma.meter.delete({ where: { id } }); } async function addMeterReading(meterId, data) { return prisma.meterReading.create({ data: { meterId, ...data, }, }); } async function getMeterReadings(meterId) { return prisma.meterReading.findMany({ where: { meterId }, orderBy: { readingDate: 'desc' }, }); } async function updateMeterReading(meterId, readingId, data) { // Verify the reading belongs to the meter const reading = await prisma.meterReading.findFirst({ where: { id: readingId, meterId }, }); if (!reading) { throw new Error('Zählerstand nicht gefunden'); } return prisma.meterReading.update({ where: { id: readingId }, data, }); } async function deleteMeterReading(meterId, readingId) { // Verify the reading belongs to the meter const reading = await prisma.meterReading.findFirst({ where: { id: readingId, meterId }, }); if (!reading) { throw new Error('Zählerstand nicht gefunden'); } return prisma.meterReading.delete({ where: { id: readingId }, }); } // ==================== PORTAL SETTINGS ==================== async function updatePortalSettings(customerId, data) { // Wenn Portal deaktiviert wird, Passwort-Hash nicht löschen (für spätere Reaktivierung) return prisma.customer.update({ where: { id: customerId }, data: { portalEnabled: data.portalEnabled, portalEmail: data.portalEmail, }, select: { id: true, portalEnabled: true, portalEmail: true, portalLastLogin: true, }, }); } async function getPortalSettings(customerId) { return prisma.customer.findUnique({ where: { id: customerId }, select: { id: true, portalEnabled: true, portalEmail: true, portalLastLogin: true, portalPasswordHash: true, // Nur um zu prüfen ob Passwort gesetzt (wird als boolean zurückgegeben) }, }); } // ==================== REPRESENTATIVE MANAGEMENT ==================== async function getCustomerRepresentatives(customerId) { // Holt alle Kunden, die der angegebene Kunde vertreten kann (dieser ist der Vertreter) return prisma.customerRepresentative.findMany({ where: { representativeId: customerId, isActive: true }, include: { customer: { select: { id: true, customerNumber: true, firstName: true, lastName: true, companyName: true, type: true, }, }, }, orderBy: { createdAt: 'desc' }, }); } async function getRepresentedByList(customerId) { // Holt alle Kunden, die den angegebenen Kunden vertreten können return prisma.customerRepresentative.findMany({ where: { customerId: customerId, isActive: true }, include: { representative: { select: { id: true, customerNumber: true, firstName: true, lastName: true, companyName: true, type: true, }, }, }, orderBy: { createdAt: 'desc' }, }); } async function addRepresentative(customerId, // Der Kunde, dessen Verträge eingesehen werden dürfen representativeId, // Der Kunde, der einsehen darf notes) { // Prüfen, ob beide Kunden existieren const [customer, representative] = await Promise.all([ prisma.customer.findUnique({ where: { id: customerId } }), prisma.customer.findUnique({ where: { id: representativeId } }), ]); if (!customer) { throw new Error('Kunde nicht gefunden'); } if (!representative) { throw new Error('Vertreter-Kunde nicht gefunden'); } if (customerId === representativeId) { throw new Error('Ein Kunde kann sich nicht selbst vertreten'); } // Prüfen ob der Vertreter ein Portal-Konto hat if (!representative.portalEnabled) { throw new Error('Der Vertreter-Kunde muss ein aktiviertes Portal-Konto haben'); } return prisma.customerRepresentative.upsert({ where: { customerId_representativeId: { customerId, representativeId }, }, create: { customerId, representativeId, notes, isActive: true, }, update: { isActive: true, notes, }, include: { representative: { select: { id: true, customerNumber: true, firstName: true, lastName: true, companyName: true, type: true, }, }, }, }); } async function removeRepresentative(customerId, representativeId) { // Anstatt zu löschen, setzen wir isActive auf false return prisma.customerRepresentative.update({ where: { customerId_representativeId: { customerId, representativeId }, }, data: { isActive: false }, }); } async function searchCustomersForRepresentative(search, excludeCustomerId) { // Sucht Kunden, die als Vertreter hinzugefügt werden können // Nur Kunden mit aktiviertem Portal return prisma.customer.findMany({ where: { id: { not: excludeCustomerId }, portalEnabled: true, OR: [ { firstName: { contains: search } }, { lastName: { contains: search } }, { companyName: { contains: search } }, { customerNumber: { contains: search } }, ], }, select: { id: true, customerNumber: true, firstName: true, lastName: true, companyName: true, type: true, }, take: 10, }); } //# sourceMappingURL=customer.service.js.map