diff --git a/src/app.module.ts b/src/app.module.ts index 67f4453..9f36292 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,6 +7,7 @@ import { databaseConfig } from './config/typeorm.config'; import { HttpModule } from '@nestjs/axios'; import { AuthModule } from './auth/auth.module'; import { OrganModule } from './organ/organ.module'; +import { ComplaintModule } from './complaint/complaint.module'; @Module({ imports: [ @@ -18,7 +19,8 @@ import { OrganModule } from './organ/organ.module'; HttpModule.register({global: true, timeout: 10000, headers: {"Content-Type": "application/json"}}), UsersModule, AuthModule, - OrganModule + OrganModule, + ComplaintModule ], }) export class AppModule {} diff --git a/src/common/enums/messages.enum.ts b/src/common/enums/messages.enum.ts index 0867abe..d6b3081 100644 --- a/src/common/enums/messages.enum.ts +++ b/src/common/enums/messages.enum.ts @@ -22,4 +22,8 @@ export enum AuthMessages { export enum OrganMessages { ORGAN_NOT_FOUND = 'ارگان مورد نظر پیدا نشد!' +} + +export enum ComplaintMessages { + COMPLAINT_NOT_FOUND = 'شکایت مورد نظر پیدا نشد!' } \ No newline at end of file diff --git a/src/complaint/complaint.controller.ts b/src/complaint/complaint.controller.ts new file mode 100644 index 0000000..b23aab1 --- /dev/null +++ b/src/complaint/complaint.controller.ts @@ -0,0 +1,34 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { ComplaintService } from './complaint.service'; +import { CreateComplaintDto } from './dto/create-complaint.dto'; +import { UpdateComplaintDto } from './dto/update-complaint.dto'; + +@Controller('complaint') +export class ComplaintController { + constructor(private readonly complaintService: ComplaintService) {} + + @Post() + create(@Body() createComplaintDto: CreateComplaintDto) { + return this.complaintService.create(createComplaintDto); + } + + @Get() + findAll() { + return this.complaintService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.complaintService.findOneOrFail(id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateComplaintDto: UpdateComplaintDto) { + return this.complaintService.update(id, updateComplaintDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.complaintService.remove(id); + } +} diff --git a/src/complaint/complaint.module.ts b/src/complaint/complaint.module.ts new file mode 100644 index 0000000..36403b9 --- /dev/null +++ b/src/complaint/complaint.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { ComplaintService } from './complaint.service'; +import { ComplaintController } from './complaint.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { Complaint } from './entities/complaint.entity'; +import { ComplaintRepository } from './repositories/complaint.repository'; + +@Module({ + imports: [TypeOrmModule.forFeature([Complaint])], + controllers: [ComplaintController], + providers: [ComplaintService, ComplaintRepository], +}) +export class ComplaintModule {} diff --git a/src/complaint/complaint.service.ts b/src/complaint/complaint.service.ts new file mode 100644 index 0000000..0c08a37 --- /dev/null +++ b/src/complaint/complaint.service.ts @@ -0,0 +1,41 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { CreateComplaintDto } from './dto/create-complaint.dto'; +import { UpdateComplaintDto } from './dto/update-complaint.dto'; +import { ComplaintRepository } from './repositories/complaint.repository'; +import { Complaint } from './entities/complaint.entity'; +import { ComplaintMessages } from 'src/common/enums/messages.enum'; + +@Injectable() +export class ComplaintService { + constructor(private readonly complaintRepository: ComplaintRepository) {} + + async create(createComplaintDto: CreateComplaintDto): Promise { + const complaint = this.complaintRepository.create(createComplaintDto); + await this.complaintRepository.save(complaint); + return complaint; + } + + async findAll(): Promise { + return this.complaintRepository.find(); + } + + async findOneOrFail(id: string): Promise { + const complaint = await this.complaintRepository.findOne({ where: { id } }); + if (!complaint) + throw new NotFoundException(ComplaintMessages.COMPLAINT_NOT_FOUND); + + return complaint; + } + + async update(id: string, updateComplaintDto: UpdateComplaintDto): Promise { + const complaint = await this.findOneOrFail(id); + Object.assign(complaint, updateComplaintDto); + return complaint; + } + + async remove(id: string): Promise { + const complaint = await this.findOneOrFail(id); + await this.complaintRepository.remove(complaint); + return complaint; + } +} diff --git a/src/complaint/dto/create-complaint.dto.ts b/src/complaint/dto/create-complaint.dto.ts new file mode 100644 index 0000000..7a533c3 --- /dev/null +++ b/src/complaint/dto/create-complaint.dto.ts @@ -0,0 +1,38 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { IsEnum, IsNotEmpty, IsString, IsUUID } from "class-validator"; +import { ComplaintStatus } from "../enums/complaint.enum"; + +export class CreateComplaintDto { + @ApiProperty({ + example: 'شکایت من', + type: 'string' + }) + @IsString() + @IsNotEmpty() + message: string; + + @ApiProperty({ + example: 'شکایت من', + type: 'string' + }) + @IsString() + @IsNotEmpty() + subject: string; + + @ApiProperty({ + example: ComplaintStatus.WAITING_FOR_RESPONSE, + enum: ComplaintStatus + }) + @IsEnum(ComplaintStatus) + status: ComplaintStatus; + + @ApiProperty({example: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', description: 'Id of the User that made the complaint'}) + @IsUUID() + @IsNotEmpty() + userId: string; + + @ApiProperty({example: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890', description: 'Id of the Orgain the complaint is about.'}) + @IsUUID() + @IsNotEmpty() + organId: string; +} diff --git a/src/complaint/dto/update-complaint.dto.ts b/src/complaint/dto/update-complaint.dto.ts new file mode 100644 index 0000000..d017263 --- /dev/null +++ b/src/complaint/dto/update-complaint.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateComplaintDto } from './create-complaint.dto'; + +export class UpdateComplaintDto extends PartialType(CreateComplaintDto) {} diff --git a/src/complaint/entities/complaint.entity.ts b/src/complaint/entities/complaint.entity.ts new file mode 100644 index 0000000..5c6bff9 --- /dev/null +++ b/src/complaint/entities/complaint.entity.ts @@ -0,0 +1,44 @@ +import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from 'typeorm'; +import { ComplaintStatus } from '../enums/complaint.enum'; +import { User } from 'src/users/entities/user.entity'; +import { Organ } from 'src/organ/entities/organ.entity'; +import { BaseEntity } from 'src/common/entities/base.entity'; + +@Entity('complaints') +export class Complaint extends BaseEntity { + @Column({ + type: 'text', + }) + message: string; + + @Column({ + type: 'varchar', + length: 100, + }) + subject: string; + + @Column({ + type: 'enum', + enum: ComplaintStatus, + default: ComplaintStatus.WAITING_FOR_RESPONSE, + }) + status: ComplaintStatus; + + @ManyToOne(() => User, (user) => user.complaints, { + nullable: false, + onDelete: 'CASCADE', + }) + @JoinColumn({ + name: 'userId', + }) + complainant: User; + + @ManyToOne(() => Organ, (organ) => organ.complaints, { + nullable: false, + onDelete: 'CASCADE' + }) + @JoinColumn({ + name: 'organId' + }) + organ: Organ; +} diff --git a/src/complaint/enums/complaint.enum.ts b/src/complaint/enums/complaint.enum.ts new file mode 100644 index 0000000..db2695b --- /dev/null +++ b/src/complaint/enums/complaint.enum.ts @@ -0,0 +1,4 @@ +export enum ComplaintStatus { + WAITING_FOR_RESPONSE = 'waiting_for_response', + ANSWERED = 'answered' +} \ No newline at end of file diff --git a/src/complaint/repositories/complaint.repository.ts b/src/complaint/repositories/complaint.repository.ts new file mode 100644 index 0000000..953dc11 --- /dev/null +++ b/src/complaint/repositories/complaint.repository.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@nestjs/common'; +import { Repository } from 'typeorm'; +import { Complaint } from '../entities/complaint.entity'; +import { InjectRepository } from '@nestjs/typeorm'; + +@Injectable() +export class ComplaintRepository extends Repository { + constructor( + @InjectRepository(Complaint) complaintRepository: ComplaintRepository, + ) { + super( + complaintRepository.target, + complaintRepository.manager, + complaintRepository.queryRunner, + ); + } +} diff --git a/src/organ/entities/organ.entity.ts b/src/organ/entities/organ.entity.ts index 0446cda..37c4fb9 100644 --- a/src/organ/entities/organ.entity.ts +++ b/src/organ/entities/organ.entity.ts @@ -1,5 +1,6 @@ import { BaseEntity } from 'src/common/entities/base.entity'; -import { Column, Entity } from 'typeorm'; +import { Complaint } from 'src/complaint/entities/complaint.entity'; +import { Column, Entity, OneToMany } from 'typeorm'; @Entity('organs') export class Organ extends BaseEntity { @@ -13,4 +14,7 @@ export class Organ extends BaseEntity { type: 'varchar', }) logo: string; + + @OneToMany(() => Complaint, (complaint) => complaint.organ) + complaints: Complaint[]; } diff --git a/src/organ/repositories/organ.repository.ts b/src/organ/repositories/organ.repository.ts index 6256ce3..fd0c1ef 100644 --- a/src/organ/repositories/organ.repository.ts +++ b/src/organ/repositories/organ.repository.ts @@ -1,7 +1,9 @@ import { Repository } from "typeorm"; import { Organ } from "../entities/organ.entity"; import { InjectRepository } from "@nestjs/typeorm"; +import { Injectable } from "@nestjs/common"; +@Injectable() export class OrganRepository extends Repository { constructor(@InjectRepository(Organ) organRepository: Repository) { super(organRepository.target, organRepository.manager, organRepository.queryRunner); diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts index af304de..e3fec40 100644 --- a/src/users/entities/user.entity.ts +++ b/src/users/entities/user.entity.ts @@ -2,6 +2,7 @@ import { Entity, Column, ManyToMany, JoinTable, OneToMany } from 'typeorm'; import { BaseEntity } from 'src/common/entities/base.entity'; import { Exclude } from 'class-transformer'; import { UserRole } from './user-role.entity'; +import { Complaint } from 'src/complaint/entities/complaint.entity'; @Entity('users') export class User extends BaseEntity { @@ -33,4 +34,9 @@ export class User extends BaseEntity { cascade: true }) roles: UserRole[]; + + @OneToMany(() => Complaint, (complaint) => complaint.complainant, { + cascade: true + }) + complaints: Complaint[]; }