import { BadRequestException, Injectable } from "@nestjs/common"; 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"; 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"; @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, paginate: true }; } /***************************************** */ // 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 announcements = 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 { announcements, count, paginate: true }; // } /***************************************** */ async getAllAnnouncementsByUser(queryDto: SearchAnnouncementQueryDto, userId: string) { const { limit, skip } = PaginationUtils(queryDto); const queryBuilder = this.announcementRepository .createQueryBuilder("announcement") .leftJoin("announcement.service", "service") .addSelect(["service.id", "service.name"]) .leftJoin("announcement.targetGroups", "group") .addSelect(["group.id", "group.name"]) .leftJoin("group.users", "groupUser") .leftJoin("service.subscriptionPlans", "subscriptionPlan") .leftJoin( "UserSubscription", "userSubscription", "userSubscription.planId = subscriptionPlan.id AND userSubscription.userId = :userId", { userId }, ) .leftJoinAndSelect("announcement.userAnnouncements", "userAnnouncements", "userAnnouncements.userId = :userId", { userId }) .where("announcement.isPublic = :isPublic", { isPublic: true }) .orWhere("groupUser.id = :userId", { userId }) .orWhere("userSubscription.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 rawResults = await queryBuilder.getRawMany(); const [, count] = await queryBuilder.skip(skip).take(limit).getManyAndCount(); const announcements = 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.service_id, name: raw.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 { announcements, count, paginate: true }; } /***************************************** */ 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 }; } }