chore: user announcement
This commit is contained in:
@@ -132,6 +132,7 @@ export const enum AnnouncementMessage {
|
|||||||
SERVICE_MUST_BE_UUID = "شناسه سرویس باید یک UUID معتبر باشد",
|
SERVICE_MUST_BE_UUID = "شناسه سرویس باید یک UUID معتبر باشد",
|
||||||
GROUP_MUST_BE_UUID = "شناسه گروه کاربران باید یک UUID معتبر باشد",
|
GROUP_MUST_BE_UUID = "شناسه گروه کاربران باید یک UUID معتبر باشد",
|
||||||
SERVICE_MUST_BE_ID = "ایدی سرویس اجباری است",
|
SERVICE_MUST_BE_ID = "ایدی سرویس اجباری است",
|
||||||
|
NOT_FOUND = "اطلاعیه ای با این ایدی یافت نشد",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const enum CriticismMessage {
|
export const enum CriticismMessage {
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import { AnnouncementService } from "./announcement.service";
|
|||||||
import { CreateAnnouncementDto } from "./DTO/create-announcement.dto";
|
import { CreateAnnouncementDto } from "./DTO/create-announcement.dto";
|
||||||
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||||
import { Roles } from "../../common/decorators/roles.decorator";
|
import { Roles } from "../../common/decorators/roles.decorator";
|
||||||
|
import { UserDec } from "../../common/decorators/user.decorator";
|
||||||
|
import { ParamDto } from "../../common/DTO/param.dto";
|
||||||
import { SearchCriticismQueryDto } from "../criticisms/DTO/search-criticism-query.dto";
|
import { SearchCriticismQueryDto } from "../criticisms/DTO/search-criticism-query.dto";
|
||||||
|
import { User } from "../users/entities/user.entity";
|
||||||
import { RoleEnum } from "../users/enums/role.enum";
|
import { RoleEnum } from "../users/enums/role.enum";
|
||||||
|
|
||||||
@ApiTags("Announcements")
|
@ApiTags("Announcements")
|
||||||
@@ -24,13 +27,33 @@ export class AnnouncementController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@Roles(RoleEnum.ADMIN)
|
@Roles(RoleEnum.ADMIN, RoleEnum.USER)
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: "Get all announcements ===> login as admin",
|
description: "Get all announcements ===> login as admin",
|
||||||
})
|
})
|
||||||
@Get()
|
@Get()
|
||||||
async getAllAnnouncements(@Query() queryDto: SearchCriticismQueryDto) {
|
async getAllAnnouncements(@Query() queryDto: SearchCriticismQueryDto, @UserDec() user: User) {
|
||||||
return await this.announcementService.getAllAnnouncements(queryDto);
|
return await this.announcementService.getAllAnnouncements(queryDto, user.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AuthGuards()
|
||||||
|
@Roles(RoleEnum.ADMIN, RoleEnum.USER, RoleEnum.VISITOR)
|
||||||
|
@ApiProperty({
|
||||||
|
description: "Get all announcements ===> login as user",
|
||||||
|
})
|
||||||
|
@Get("user")
|
||||||
|
async getAllAnnouncementsByUser(@Query() queryDto: SearchCriticismQueryDto, @UserDec() user: User) {
|
||||||
|
return await this.announcementService.getAllAnnouncementsByUser(queryDto, user.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AuthGuards()
|
||||||
|
@Roles(RoleEnum.ADMIN, RoleEnum.USER, RoleEnum.VISITOR)
|
||||||
|
@ApiProperty({
|
||||||
|
description: "Get one announcements with id",
|
||||||
|
})
|
||||||
|
@Get(":id")
|
||||||
|
getAnnouncement(@Param() paramDto: ParamDto, @UserDec() user: User) {
|
||||||
|
return this.announcementService.getOneAnnouncement(paramDto.id, user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@@ -46,7 +69,7 @@ export class AnnouncementController {
|
|||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: "Get all public announcements",
|
description: "Get all public announcements",
|
||||||
})
|
})
|
||||||
@Get(":serviceId")
|
@Get("/service/:serviceId")
|
||||||
async getAnnouncementsByService(@Query() queryDto: SearchCriticismQueryDto, @Param("serviceId") serviceId: string) {
|
async getAnnouncementsByService(@Query() queryDto: SearchCriticismQueryDto, @Param("serviceId") serviceId: string) {
|
||||||
return await this.announcementService.getAnnouncementByService(queryDto, serviceId);
|
return await this.announcementService.getAnnouncementByService(queryDto, serviceId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import { Announcement } from "./entities/announcement.entity";
|
|||||||
import { AnnouncementRepository } from "./repositories/announcement.repository";
|
import { AnnouncementRepository } from "./repositories/announcement.repository";
|
||||||
import { DanakServicesModule } from "../danak-services/danak-services.module";
|
import { DanakServicesModule } from "../danak-services/danak-services.module";
|
||||||
import { UsersModule } from "../users/users.module";
|
import { UsersModule } from "../users/users.module";
|
||||||
|
import { UserAnnouncement } from "./entities/user-announcement.entity";
|
||||||
|
import { UserAnnouncementRepository } from "./repositories/user-announcement.repository";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Announcement]), DanakServicesModule, UsersModule],
|
imports: [TypeOrmModule.forFeature([Announcement, UserAnnouncement]), DanakServicesModule, UsersModule],
|
||||||
providers: [AnnouncementService, AnnouncementRepository],
|
providers: [AnnouncementService, AnnouncementRepository, UserAnnouncementRepository],
|
||||||
controllers: [AnnouncementController],
|
controllers: [AnnouncementController],
|
||||||
exports: [TypeOrmModule],
|
exports: [TypeOrmModule],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { Injectable } from "@nestjs/common";
|
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
import { CreateAnnouncementDto } from "./DTO/create-announcement.dto";
|
import { CreateAnnouncementDto } from "./DTO/create-announcement.dto";
|
||||||
import { SearchAnnouncementQueryDto } from "./DTO/search-announcement-query.dto";
|
import { SearchAnnouncementQueryDto } from "./DTO/search-announcement-query.dto";
|
||||||
import { AnnouncementRepository } from "./repositories/announcement.repository";
|
import { AnnouncementRepository } from "./repositories/announcement.repository";
|
||||||
import { CommonMessage } from "../../common/enums/message.enum";
|
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 { DanakServicesService } from "../danak-services/providers/danak-services.service";
|
||||||
import { UsersService } from "../users/providers/users.service";
|
import { UsersService } from "../users/providers/users.service";
|
||||||
import { PaginationUtils } from "../utils/providers/pagination.utils";
|
import { PaginationUtils } from "../utils/providers/pagination.utils";
|
||||||
@@ -12,6 +13,7 @@ import { PaginationUtils } from "../utils/providers/pagination.utils";
|
|||||||
export class AnnouncementService {
|
export class AnnouncementService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly announcementRepository: AnnouncementRepository,
|
private readonly announcementRepository: AnnouncementRepository,
|
||||||
|
private readonly userAnnouncementRepository: UserAnnouncementRepository,
|
||||||
private readonly danakServicesService: DanakServicesService,
|
private readonly danakServicesService: DanakServicesService,
|
||||||
private readonly usersService: UsersService,
|
private readonly usersService: UsersService,
|
||||||
) {}
|
) {}
|
||||||
@@ -38,7 +40,7 @@ export class AnnouncementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllAnnouncements(queryDto: SearchAnnouncementQueryDto) {
|
async getAllAnnouncements(queryDto: SearchAnnouncementQueryDto, userId: string) {
|
||||||
const { limit, skip } = PaginationUtils(queryDto);
|
const { limit, skip } = PaginationUtils(queryDto);
|
||||||
|
|
||||||
const queryBuilder = this.announcementRepository
|
const queryBuilder = this.announcementRepository
|
||||||
@@ -46,7 +48,8 @@ export class AnnouncementService {
|
|||||||
.leftJoin("announcement.service", "danak_service")
|
.leftJoin("announcement.service", "danak_service")
|
||||||
.addSelect(["danak_service.id", "danak_service.name"])
|
.addSelect(["danak_service.id", "danak_service.name"])
|
||||||
.leftJoin("announcement.targetGroups", "group")
|
.leftJoin("announcement.targetGroups", "group")
|
||||||
.addSelect(["group.id", "group.name"]);
|
.addSelect(["group.id", "group.name"])
|
||||||
|
.leftJoinAndSelect("announcement.userAnnouncements", "userAnnouncements", "userAnnouncements.userId = :userId", { userId });
|
||||||
|
|
||||||
if (queryDto.since) {
|
if (queryDto.since) {
|
||||||
queryBuilder.andWhere("announcement.createdAt >= :since", { since: queryDto.since });
|
queryBuilder.andWhere("announcement.createdAt >= :since", { since: queryDto.since });
|
||||||
@@ -67,6 +70,68 @@ export class AnnouncementService {
|
|||||||
return { announcements, count };
|
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() {
|
async getPublicAnnouncements() {
|
||||||
const announcements = await this.announcementRepository.find({ where: { isPublic: true }, relations: ["service", "targetGroups"] });
|
const announcements = await this.announcementRepository.find({ where: { isPublic: true }, relations: ["service", "targetGroups"] });
|
||||||
return { announcements };
|
return { announcements };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Column, Entity, Index, ManyToMany, ManyToOne } from "typeorm";
|
import { Column, Entity, Index, ManyToMany, ManyToOne, OneToMany } from "typeorm";
|
||||||
|
|
||||||
|
import { UserAnnouncement } from "./user-announcement.entity";
|
||||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
import { DanakService } from "../../danak-services/entities/danak-service.entity";
|
import { DanakService } from "../../danak-services/entities/danak-service.entity";
|
||||||
import { UserGroup } from "../../users/entities/user-group.entity";
|
import { UserGroup } from "../../users/entities/user-group.entity";
|
||||||
@@ -32,4 +33,7 @@ export class Announcement extends BaseEntity {
|
|||||||
isPublicAnnouncement(): boolean {
|
isPublicAnnouncement(): boolean {
|
||||||
return this.isPublic;
|
return this.isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OneToMany(() => UserAnnouncement, (userAnnouncement) => userAnnouncement.announcement)
|
||||||
|
userAnnouncements: UserAnnouncement[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
|
||||||
|
|
||||||
|
import { Announcement } from "./announcement.entity";
|
||||||
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
import { User } from "../../users/entities/user.entity"; // Assuming you have a User entity
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class UserAnnouncement extends BaseEntity {
|
||||||
|
@ManyToOne(() => User, (user) => user.userAnnouncements, { onDelete: "CASCADE" })
|
||||||
|
@JoinColumn({ name: "userId" })
|
||||||
|
user: User;
|
||||||
|
|
||||||
|
@ManyToOne(() => Announcement, (announcement) => announcement.userAnnouncements, { onDelete: "CASCADE" })
|
||||||
|
@JoinColumn({ name: "announcementId" })
|
||||||
|
announcement: Announcement;
|
||||||
|
|
||||||
|
@Column({ type: "boolean", default: false })
|
||||||
|
isRead: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { Repository } from "typeorm";
|
||||||
|
|
||||||
|
import { UserAnnouncement } from "../entities/user-announcement.entity";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserAnnouncementRepository extends Repository<UserAnnouncement> {
|
||||||
|
constructor(@InjectRepository(UserAnnouncement) userAnnouncementRepository: Repository<UserAnnouncement>) {
|
||||||
|
super(userAnnouncementRepository.target, userAnnouncementRepository.manager, userAnnouncementRepository.queryRunner);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Column, Entity } from "typeorm";
|
||||||
|
|
||||||
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class UserSettings extends BaseEntity {
|
||||||
|
@Column({ type: "varchar", length: 150 })
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
@Column({ type: "json" })
|
||||||
|
fields: Record<string, any>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserSettingsService {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { InjectRepository } from "@nestjs/typeorm";
|
||||||
|
import { Repository } from "typeorm";
|
||||||
|
|
||||||
|
import { UserSettings } from "../entities/user-settings.entity";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserSettingsRepository extends Repository<UserSettings> {
|
||||||
|
constructor(@InjectRepository(UserSettings) userSettingsRepository: Repository<UserSettings>) {
|
||||||
|
super(userSettingsRepository.target, userSettingsRepository.manager, userSettingsRepository.queryRunner);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { Controller } from "@nestjs/common";
|
||||||
|
|
||||||
|
@Controller("user-settings")
|
||||||
|
export class UserSettingsController {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Module } from "@nestjs/common";
|
||||||
|
import { TypeOrmModule } from "@nestjs/typeorm";
|
||||||
|
|
||||||
|
import { UserSettings } from "./entities/user-settings.entity";
|
||||||
|
import { UserSettingsService } from "./providers/user-setttings.service";
|
||||||
|
import { UserSettingsRepository } from "./repositories/user-settings.repository";
|
||||||
|
import { UserSettingsController } from "./user-settings.controller";
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([UserSettings])],
|
||||||
|
providers: [UserSettingsService, UserSettingsRepository],
|
||||||
|
controllers: [UserSettingsController],
|
||||||
|
exports: [TypeOrmModule],
|
||||||
|
})
|
||||||
|
export class UserSettingsModule {}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany } from "typ
|
|||||||
import { Role } from "./role.entity";
|
import { Role } from "./role.entity";
|
||||||
import { UserGroup } from "./user-group.entity";
|
import { UserGroup } from "./user-group.entity";
|
||||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||||
|
import { UserAnnouncement } from "../../announcements/entities/user-announcement.entity";
|
||||||
import { Criticism } from "../../criticisms/entities/criticism.entity";
|
import { Criticism } from "../../criticisms/entities/criticism.entity";
|
||||||
import { DanakService } from "../../danak-services/entities/danak-service.entity";
|
import { DanakService } from "../../danak-services/entities/danak-service.entity";
|
||||||
import { TicketMessage } from "../../tickets/entities/ticket-message.entity";
|
import { TicketMessage } from "../../tickets/entities/ticket-message.entity";
|
||||||
@@ -54,4 +55,7 @@ export class User extends BaseEntity {
|
|||||||
@ManyToMany(() => DanakService, (danakService) => danakService.users)
|
@ManyToMany(() => DanakService, (danakService) => danakService.users)
|
||||||
@JoinTable()
|
@JoinTable()
|
||||||
danakServices: DanakService[];
|
danakServices: DanakService[];
|
||||||
|
|
||||||
|
@OneToMany(() => UserAnnouncement, (userAnnouncement) => userAnnouncement.user)
|
||||||
|
userAnnouncements: UserAnnouncement[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user