import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { ILike, IsNull, LessThanOrEqual, Repository } from 'typeorm'; import { StoredItemTransaction } from './entities/item-transaction.entity'; import { Item } from './entities/item.entity'; import { StorageSet } from './entities/storage-set.entity'; import { Storage } from './entities/storage.entity'; import { StoredItem } from './entities/stored-item.entity'; @Injectable() export class StorageService { constructor( @InjectRepository(Item) private readonly itemRepository: Repository, @InjectRepository(Storage) private readonly storageRepository: Repository, @InjectRepository(StorageSet) private readonly storageSetRepository: Repository, @InjectRepository(StoredItem) private readonly storedItemRepository: Repository, @InjectRepository(StoredItemTransaction) private readonly transactionRepository: Repository, ) {} async getStorageById(id: number, relations = []) { return this.storageRepository.findOne({ where: { id, }, relations, }); } async getStorageWithItemCount(storageId: number) { return this.storageRepository .createQueryBuilder('storage') .leftJoinAndSelect('storage.addedBy', 'addedBy') .loadRelationCountAndMap('storage.itemCount', 'storage.items') .where('storage.id = :storageId', { storageId }) .getOne(); } async getStorageByIdAndSub(id: number, sub: string, relations = []) { return this.storageRepository.findOne({ where: { id, room: { building: { groups: { members: { sub, }, }, }, }, }, relations, }); } async getStorageByIdAndBuilding( id: number, buildingId: number, relations = [], ) { return this.storageRepository.findOne({ where: { id, room: { building: { id: buildingId, }, }, }, relations, }); } async getStorageByIdAndRoom(id: number, roomId: number, relations = []) { return this.storageRepository.findOne({ where: { id, room: { id: roomId, }, }, relations, }); } async getStorageSetByIdAndSub(id: number, sub: string, relations = []) { return this.storageSetRepository.findOne({ where: { id, room: { building: { groups: { members: { sub, }, }, }, }, }, relations: ['storages', 'storages.addedBy', ...relations], }); } async getStorageSetByIdAndBuilding( id: number, buildingId: number, relations = [], ) { return this.storageSetRepository.findOne({ where: { id, room: { building: { id: buildingId, }, }, }, relations: ['storages', 'storages.addedBy', ...relations], }); } async getStorageSetByIdAndRoom(id: number, roomId: number, relations = []) { return this.storageSetRepository.findOne({ where: { id, room: { id: roomId, }, }, relations: ['storages', 'storages.addedBy', ...relations], }); } async getStoragesInRoom(roomId: number, includeWithSets = false) { const qb = this.storageRepository .createQueryBuilder('storage') .leftJoin('storage.room', 'storage.room') .leftJoin('storage.set', 'storage.set') .loadRelationCountAndMap('storage.itemCount', 'storage.items') .where('storage.room.id = :roomId', { roomId }); if (!includeWithSets) { qb.andWhere({ set: IsNull() }); } qb.addSelect( 'CASE WHEN storage.set IS NULL THEN FALSE ELSE TRUE END', 'storage.hasSet', ); return qb.getMany(); } async getStorageSetsInRoom(roomId: number) { return this.storageSetRepository .createQueryBuilder('storageSet') .leftJoin('storageSet.room', 'storageSet.room') .leftJoinAndMapMany( 'storageSet.storages', 'storageSet.storages', 'storages', ) .loadRelationCountAndMap('storages.itemCount', 'storages.items') .where('storageSet.room.id = :roomId', { roomId }) .getMany(); } async getItemsInStorage(storageId: number, relations = []) { return this.storedItemRepository.find({ where: { storage: { id: storageId, }, }, relations: ['item', ...relations], }); } async searchForItem(searchTerm: string, sub: string) { const displayName = ILike(`%${searchTerm}%`); return this.itemRepository.find({ where: [ { displayName, addedBy: { sub, }, }, { displayName, public: true, }, { displayName, addedBy: { groups: { members: { sub, }, }, }, }, ], take: 10, select: ['id', 'displayName', 'type', 'barcode', 'image', 'createdAt'], }); } async searchForItemByBarcode(barcode: string, sub: string) { return this.itemRepository.find({ where: [ { barcode, addedBy: { sub, }, }, { barcode, public: true, }, { barcode, addedBy: { groups: { members: { sub, }, }, }, }, ], take: 10, select: ['id', 'displayName', 'type', 'barcode', 'image', 'createdAt'], }); } async getItemByIdBySub(id: number, sub: string) { return this.itemRepository.findOne({ where: [ { id, addedBy: { sub, }, }, { id, public: true, }, { id, addedBy: { groups: { members: { sub, }, }, }, }, ], }); } async getItemByIdOwnedBySub(id: number, sub: string, relations = []) { return this.itemRepository.findOne({ where: { id, addedBy: { sub, }, }, relations, }); } async getExpiredOrExpiringSoonInBuilding(buildingId: number) { // 8 days return this.storedItemRepository.find({ where: { expiresAt: LessThanOrEqual(new Date(Date.now() + 691200000)), building: { id: buildingId, }, }, order: { expiresAt: 'ASC', }, take: 16, relations: ['item', 'storage'], }); } async getExpiredOrExpiringSoonForSub(sub: string) { // 8 days return this.storedItemRepository.find({ where: { expiresAt: LessThanOrEqual(new Date(Date.now() + 691200000)), building: { groups: { members: { sub, }, }, }, }, order: { expiresAt: 'ASC', }, take: 16, relations: ['item', 'building', 'storage'], }); } async getStoredItemByStorageAndId( storage: Storage, storedItemId: number, relations = [], ) { return this.storedItemRepository.findOne({ where: { id: storedItemId, storage: { id: storage.id }, }, relations, }); } async getStoredItemTransactionById( storedItemId: number, storedItemTransactionId: number, relations = [], ) { return this.transactionRepository.findOne({ where: { id: storedItemTransactionId, storedItem: { id: storedItemId }, }, relations, }); } async saveStorage(data: Partial) { const newStorage = new Storage(); Object.assign(newStorage, data); return this.storageRepository.save(newStorage); } async saveItem(data: Partial) { const newItem = new Item(); Object.assign(newItem, data); return this.itemRepository.save(newItem); } async saveStoredItem(data: Partial) { const newStoredItem = new StoredItem(); Object.assign(newStoredItem, data); return this.storedItemRepository.save(newStoredItem); } async saveStorageSet(data: Partial) { const newStorageSet = new StorageSet(); Object.assign(newStorageSet, data); return this.storageSetRepository.save(newStorageSet); } async saveStoredItemTransaction(data: Partial) { const newStoredItemTransaction = new StoredItemTransaction(); Object.assign(newStoredItemTransaction, data); return this.transactionRepository.save(newStoredItemTransaction); } }