import { BadRequestException, Injectable } from "@nestjs/common"; import { CreateAnnouncementDto } from "./DTO/create-announcement.dto"; import { SearchAnnouncementQueryDto } from "./DTO/search-announcement-query.dto"; import { AnnouncementRepository } from "./repositories/announcement.repository"; import { UserAnnouncementRepository } from "./repositories/user-announcement.repository"; import { AnnouncementMessage, CommonMessage } from "../../common/enums/message.enum"; import { DanakServicesService } from "../danak-services/providers/danak-services.service"; import { UsersService } from "../users/providers/users.service"; import { PaginationUtils } from "../utils/providers/pagination.utils"; @Injectable() export class AnnouncementService { constructor( private readonly announcementRepository: AnnouncementRepository, private readonly userAnnouncementRepository: UserAnnouncementRepository, private readonly danakServicesService: DanakServicesService, private readonly usersService: UsersService, ) {} async createAnnouncement(createAnnouncementDto: CreateAnnouncementDto) { let service; let groups; if (createAnnouncementDto.serviceId) { service = await this.danakServicesService.findServiceById(createAnnouncementDto.serviceId); } if (createAnnouncementDto.groupIds) { groups = await this.usersService.getUserGroupsByIds(createAnnouncementDto.groupIds); } //TODO: Create Queue for publishAT const announcement = this.announcementRepository.create({ ...createAnnouncementDto, service, targetGroups: groups?.userGroups, }); await this.announcementRepository.save(announcement); return { message: CommonMessage.CREATED, announcement, }; } async getAllAnnouncements(queryDto: SearchAnnouncementQueryDto, userId: string) { const { limit, skip } = PaginationUtils(queryDto); const queryBuilder = this.announcementRepository .createQueryBuilder("announcement") .leftJoin("announcement.service", "danak_service") .addSelect(["danak_service.id", "danak_service.name"]) .leftJoin("announcement.targetGroups", "group") .addSelect(["group.id", "group.name"]) .leftJoinAndSelect("announcement.userAnnouncements", "userAnnouncements", "userAnnouncements.userId = :userId", { userId }); if (queryDto.since) { queryBuilder.andWhere("announcement.createdAt >= :since", { since: queryDto.since }); } if (queryDto.publishAt) { queryBuilder.andWhere("announcement.publishAt >= :publishAt", { publishAt: queryDto.publishAt }); } if (queryDto.q) { queryBuilder.andWhere("announcement.title LIKE :q", { q: `%${queryDto.q}%` }); } queryBuilder.orderBy("announcement.createdAt", "DESC"); const [announcements, count] = await queryBuilder.skip(skip).take(limit).getManyAndCount(); return { announcements, count }; } async getAllAnnouncementsByUser(queryDto: SearchAnnouncementQueryDto, userId: string) { const { limit, skip } = PaginationUtils(queryDto); const queryBuilder = this.announcementRepository .createQueryBuilder("announcement") .leftJoin("announcement.service", "danak_service") .addSelect(["danak_service.id", "danak_service.name"]) .leftJoin("announcement.targetGroups", "group") .addSelect(["group.id", "group.name"]) .leftJoin("group.users", "groupUser") .leftJoinAndSelect("announcement.userAnnouncements", "userAnnouncements", "userAnnouncements.userId = :userId", { userId }) .where("announcement.isPublic = :isPublic", { isPublic: true }) // Check if the announcement is public .orWhere("groupUser.id = :userId", { userId }); if (queryDto.since) { queryBuilder.andWhere("announcement.createdAt >= :since", { since: queryDto.since }); } if (queryDto.publishAt) { queryBuilder.andWhere("announcement.publishAt >= :publishAt", { publishAt: queryDto.publishAt }); } if (queryDto.q) { queryBuilder.andWhere("announcement.title LIKE :q", { q: `%${queryDto.q}%` }); } queryBuilder.orderBy("announcement.createdAt", "DESC"); const rawResults = await queryBuilder.getRawMany(); const [, count] = await queryBuilder.skip(skip).take(limit).getManyAndCount(); const transformedResults = rawResults.map((raw) => ({ id: raw.announcement_id, createdAt: raw.announcement_createdAt, updatedAt: raw.announcement_updatedAt, title: raw.announcement_title, content: raw.announcement_content, publishAt: raw.announcement_publishAt, service: { id: raw.danak_service_id, name: raw.danak_service_name, }, isImportant: raw.announcement_isImportant, targetGroups: raw.group_id ? [{ id: raw.group_id, name: raw.group_name }] : [], isPublic: raw.announcement_isPublic, isRead: raw.userAnnouncements_isRead ? true : false, })); return { transformedResults, count }; } async getOneAnnouncement(id: string, userId: string) { const announcement = await this.announcementRepository.findOneBy({ id }); if (!announcement) throw new BadRequestException(AnnouncementMessage.NOT_FOUND); const userAnnouncement = this.userAnnouncementRepository.create({ announcement: { id: announcement.id }, user: { id: userId }, isRead: true, }); await this.userAnnouncementRepository.save(userAnnouncement); return { announcement }; } async getPublicAnnouncements() { const announcements = await this.announcementRepository.find({ where: { isPublic: true }, relations: ["service", "targetGroups"] }); return { announcements }; } async getAnnouncementByService(queryDto: SearchAnnouncementQueryDto, serviceId: string) { const { limit, skip } = PaginationUtils(queryDto); const queryBuilder = this.announcementRepository .createQueryBuilder("announcement") .leftJoin("announcement.service", "danak_service") .addSelect(["danak_service.id", "danak_service.name"]) .leftJoin("announcement.targetGroups", "group") .addSelect(["group.id", "group.name"]) .where("danak_service.id = :serviceId", { serviceId }); if (queryDto.since) { queryBuilder.andWhere("announcement.createdAt >= :since", { since: queryDto.since }); } if (queryDto.publishAt) { queryBuilder.andWhere("announcement.publishAt >= :publishAt", { publishAt: queryDto.publishAt }); } if (queryDto.q) { queryBuilder.andWhere("announcement.title LIKE :q", { q: `%${queryDto.q}%` }); } queryBuilder.orderBy("announcement.createdAt", "DESC"); const [announcements, count] = await queryBuilder.skip(skip).take(limit).getManyAndCount(); return { announcements, count, paginate: true }; } }