import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { Customer, Cylinder, Key, User } from 'src/model/entitites'; import { CylinderRepository, KeyRepository, KeySystemRepository, } from 'src/model/repositories'; import { KeyHandoutRepository } from 'src/model/repositories/key-handout.repository'; import { ActivityHelperService } from 'src/shared/service/activity.logger.service'; import { HelperService } from 'src/shared/service/system.helper.service'; import { FindOperator, IsNull, Not } from 'typeorm'; import { faker } from '@faker-js/faker'; import { ConfigService } from '@nestjs/config'; import { MailService } from '../mail/mail.service'; import { SseService } from '../realtime/sse/sse.service'; @Injectable() export class KeyService { constructor( private readonly keyrepository: KeyRepository, private readonly cylinderRepository: CylinderRepository, private readonly handoverRepo: KeyHandoutRepository, private readonly activityService: ActivityHelperService, private readonly helper: HelperService, private readonly configService: ConfigService, private readonly mailService: MailService, private readonly sseService: SseService ) { console.log("INIT KEYSERVICE") } get isDevelopMode(): boolean { return (this.configService.get('DEVELOP_MODE') || '').toLowerCase() == 'true'; } async getUsersKeys(user: User): Promise { let keys = await this.keyrepository.find({ where: { cylinder: { system: { managers: { id: user.id } } }, keyLost: IsNull() }, relations: ['cylinder', 'cylinder.system', 'customer'], }); for (let k of keys) { k.customer = await this.getCustomerOfLastHandout(user, k.id); } if (this.isDevelopMode) { keys = keys.filter(k => k.cylinder.some(c => c.name.toLowerCase().includes('develop') || c.system.name.toLowerCase().includes('develop'))) } return keys; } async getLostKeys(user: User): Promise { let keys = await this.keyrepository.find({ where: { cylinder: { system: { managers: { id: user.id } } }, keyLost: Not(IsNull()) }, relations: ['cylinder', 'cylinder.system', 'customer'], }); for (let k of keys) { k.customer = await this.getCustomerOfLastHandout(user, k.id); } if (this.isDevelopMode) { keys = keys.filter(k => k.cylinder.some(c => c.name.toLowerCase().includes('develop') || c.system.name.toLowerCase().includes('develop'))) } return keys; } async updateKey(user: User, key: Key) { if (!user || !user.id) { throw new HttpException('forbidden', HttpStatus.FORBIDDEN); } const k = await this.keyrepository.findOneOrFail({ where: { id: key.id, cylinder: { system: { managers: { id: user.id } } } }, relations: ['cylinder', 'cylinder.system'], withDeleted: true }); if (k.name != key.name) { await this.activityService.logKeyRenamed(user, key, key.cylinder[0].system, k.name); } if (k.keyLost != key.keyLost) { await this.activityService.logKeyLostUpdate(user, key, key.keyLost); try { const k = await this.keyrepository.findOne({ where: { id: key.id }, relations: ['cylinder', 'cylinder.system', 'cylinder.system.managers', 'cylinder.system.managers.settings'], withDeleted: false }); for (const to of k.cylinder[0].system.managers.filter(m => m.settings.sendSystemUpdateMails)) { this.mailService.sendKeyLostOrFoundMail({ key, to } ) } } catch (e) { console.error(e); } } const saved = await this.keyrepository.save(this.keyrepository.create(key)); this.sendKeysToSSE(saved); return saved; } private async sendKeysToSSE(key: Key) { const system = await this.helper.getSystemOfKey(key) for (let manager of system.managers) { const keys = await this.getUsersKeys(manager); this.sseService.sendKeysToUsers(manager.id, keys) } } async getUsersCylinders(user: User): Promise { if (!user || !user.id) { throw new HttpException('forbidden', HttpStatus.FORBIDDEN); } return this.cylinderRepository.find({ where: { system: { managers: { id: user.id } } }, order: { name: { direction: 'ASC' } }, relations: ['system'], }); } async handoverKey(user: User, data: any, keyID: string) { const key: Key = await this.keyrepository.findOneOrFail({ where: { id: keyID, cylinder: { system: { managers: { id: user.id } } } }, relations: [ 'cylinder', 'cylinder.system' ] }); key.handedOut = data.direction == 'out'; this.keyrepository.save(key); const res = await this.handoverRepo.save( this.handoverRepo.create({ customer: data.customer, direction: data.direction, timestamp: data.timestamp, key: key, user: user as any }), ); this.activityService.logKeyHandover(user, key, key.cylinder[0].system, res); try { if (key && key.cylinder && key.cylinder[0].system) { const managerOb: Key = await this.keyrepository.findOne({ where: { id: keyID }, relations: [ 'cylinder', 'cylinder.system', 'cylinder.system.managers', 'cylinder.system.managers.settings' ] }); managerOb.cylinder[0].system.managers.filter(m => m.settings.sendSystemUpdateMails).forEach(m => { this.mailService.sendKeyHandoutMail({ to: m, key, handoutAction: res }) }) } } catch (e){ console.log(e) } this.sendKeysToSSE(key); return res; } getKeyHandovers(user: User, keyID: string) { return this.handoverRepo.find({ where: { key: { cylinder: { system: { managers: { id: user.id } } }, id: keyID }, }, order: { timestamp: { direction: 'DESC' }, created: { direction: 'DESC' }, }, relations: ['customer'], }); } async getCustomerOfLastHandout (user: User, keyID: string): Promise { const handover = await this.handoverRepo.find({ where: { key: { cylinder: { system: { managers: { id: user.id } } }, id: keyID }, }, order: { timestamp: { direction: 'DESC' }, created: { direction: 'DESC' }, }, relations: ['customer'], take: 1 }); if (handover.length == 1 && handover[0].direction == 'out') { return handover[0].customer; } else { return null; } } async createKey(user: User, key: any): Promise { const k = await this.keyrepository.save(this.keyrepository.create(key)) as any as Key; this.activityService.logKeyCreated(user, key, key.cylinder[0].system); this.sendKeysToSSE(k as any) return k; } async deleteKey(user: User, id: string): Promise { const key = await this.keyrepository.findOneOrFail({ where: { id, cylinder: { system: { managers: { id: user.id } } } }, }); await this.activityService.logDeleteKey(user, key); const k = await this.keyrepository.softRemove(key); this.sendKeysToSSE(k) return k; } getDeletedKeys(user: User) { return this.keyrepository.find({ where: { cylinder: { system: { managers: { id: user.id } } }, deletedAt: Not(IsNull()), }, withDeleted: true, order: { deletedAt: { direction: 'DESC' } }, }); } async restoreKey(user: User, keyID: string): Promise { const key = await this.keyrepository.findOneOrFail({ where: { cylinder: { system: { managers: { id: user.id } } }, id: keyID }, withDeleted: true, }); key.deletedAt = null; await this.activityService.logKeyRestored(user, key); await this.helper.deleteKeyArchiveCache(); const k = await this.keyrepository.save(key); this.sendKeysToSSE(k) return k; } }