import { Injectable , BadRequestException , NotFoundException } from '@nestjs/common' ; import { InjectRepository } from '@nestjs/typeorm' ; import { Validator } from 'class-validator' ; import { EntriesRepository } from 'src/shared/Repositories/entries.repository' ; import { EntriesEntity } from 'src/shared/Entities/entries.entity' ; import { CreateEntryDto } from '../Dto/create-entry.dto' ; import { TitlesRepository } from 'src/shared/Repositories/title.repository' ; import { serializerService , ISerializeResponse } from 'src/shared/Services/serializer.service' ; import { UsersRepository } from 'src/shared/Repositories/users.repository' ; import { StatusOk } from 'src/shared/Types' ; @ Injectable ( ) export class EntryService { private validator : Validator ; constructor ( @ InjectRepository ( EntriesRepository ) private readonly entriesRepository , @ InjectRepository ( TitlesRepository ) private readonly titlesRepository , @ InjectRepository ( UsersRepository ) private readonly usersRepository ) { this . validator = new Validator ( ) ; } async getEntry ( entryId ) { if ( ! this . validator . isMongoId ( entryId ) ) throw new BadRequestException ( 'Id must be a type of MongoId' ) ; const entry = await this . entriesRepository . getEntry ( entryId ) ; return serializerService . serializeResponse ( 'entry_detail' , entry ) ; } async getEntriesByTitleId ( { titleId , query } ) { const result = await this . entriesRepository . getEntriesByTitleId ( { titleId , query } ) ; return serializerService . serializeResponse ( 'entry_list' , result ) ; } async getEntriesByAuthorOfIt ( { username , query } ) { const result = await this . entriesRepository . getEntriesByAuthorOfIt ( { username , query } ) ; return serializerService . serializeResponse ( 'entry_list_of_author' , result ) ; } async getFeaturedEntryByTitleId ( { titleId } ) { const result = await this . entriesRepository . getFeaturedEntryByTitleId ( { titleId } ) ; return serializerService . serializeResponse ( 'featured_entry' , result ) ; } async updateEntry ( username , entryId , text ) { if ( ! this . validator . isMongoId ( entryId ) ) throw new BadRequestException ( 'Id must be a type of MongoId' ) ; const entry = await this . entriesRepository . updateEntry ( username , entryId , text ) ; return serializerService . serializeResponse ( 'entry_detail' , entry ) ; } async createEntry ( writtenBy , dto ) { dto . text = dto . text . replace ( /^\s+|\s+$/g , '' ) ; if ( dto . text . length === 0 ) throw new BadRequestException ( 'Entry text can not be whitespace' ) ; try { await this . titlesRepository . updateEntryCount ( dto . titleId , 1 ) ; } catch ( err ) { throw new NotFoundException ( 'Title could not found by given id' ) ; } const newEntry = await this . entriesRepository . createEntry ( writtenBy , dto ) ; return serializerService . serializeResponse ( 'updated_entry' , newEntry ) ; } async undoVoteOfEntry ( { entryId , username , isUpVoted } ) { if ( ! this . validator . isMongoId ( entryId ) ) throw new BadRequestException ( 'Id must be a type of MongoId' ) ; try { await this . entriesRepository . findOneOrFail ( entryId ) ; } catch ( e ) { throw new NotFoundException ( 'Entry could not found by given id' ) ; } await this . entriesRepository . undoVoteOfEntry ( { entryId , isUpVoted , username } ) ; return { status : 'ok' , message : 'Entry has been un voted' } ; } async voteEntry ( { entryId , username , isUpVoted } ) { if ( ! this . validator . isMongoId ( entryId ) ) throw new BadRequestException ( 'Id must be a type of MongoId' ) ; try { await this . entriesRepository . findOneOrFail ( entryId ) ; } catch ( e ) { throw new BadRequestException ( 'Entry could not found by given id' ) ; } await this . entriesRepository . voteEntry ( { entryId , isUpVoted , username } ) ; return { status : 'ok' , message : 'Entry has been voted' } ; } async deleteEntry ( username , role , entryId ) { if ( ! this . validator . isMongoId ( entryId ) ) throw new BadRequestException ( 'Id must be a type of MongoId' ) ; await this . usersRepository . getUserByUsername ( username ) ; const entry = await this . entriesRepository . deleteEntry ( username , role , entryId ) ; await this . titlesRepository . updateEntryCount ( entry . title_id , - 1 ) ; return { status : 'ok' , message : 'Entry has been deleted' } ; } async deleteEntriesBelongsToUsername ( username ) { await this . usersRepository . getUserByUsername ( username ) ; const entries = await this . entriesRepository . deleteEntriesBelongsToUsername ( username ) ; const entriesWithTitleId = [ ... entries . reduce ( ( previous , current ) => { if ( ! previous . has ( current . title_id ) ) previous . set ( current . title_id , { id : current . title_id , entryCount : 1 } ) ; else previous . get ( current . title_id ) . entryCount ++ ; return previous ; } , new Map ) . values ( ) ] ; entriesWithTitleId . map ( async ( item ) => { await this . titlesRepository . updateEntryCount ( item . id , - item . entryCount ) ; } ) ; return { status : 'ok' , message : 'Entries are deleted' } ; } }