feat: added complaint section

This commit is contained in:
2026-07-27 15:10:36 +03:30
parent 19e648a299
commit eb8d87bd48
13 changed files with 215 additions and 2 deletions
+3 -1
View File
@@ -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 {}
+4
View File
@@ -23,3 +23,7 @@ export enum AuthMessages {
export enum OrganMessages {
ORGAN_NOT_FOUND = 'ارگان مورد نظر پیدا نشد!'
}
export enum ComplaintMessages {
COMPLAINT_NOT_FOUND = 'شکایت مورد نظر پیدا نشد!'
}
+34
View File
@@ -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);
}
}
+13
View File
@@ -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 {}
+41
View File
@@ -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<Complaint> {
const complaint = this.complaintRepository.create(createComplaintDto);
await this.complaintRepository.save(complaint);
return complaint;
}
async findAll(): Promise<Complaint[]> {
return this.complaintRepository.find();
}
async findOneOrFail(id: string): Promise<Complaint> {
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<Complaint> {
const complaint = await this.findOneOrFail(id);
Object.assign(complaint, updateComplaintDto);
return complaint;
}
async remove(id: string): Promise<Complaint> {
const complaint = await this.findOneOrFail(id);
await this.complaintRepository.remove(complaint);
return complaint;
}
}
+38
View File
@@ -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;
}
@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateComplaintDto } from './create-complaint.dto';
export class UpdateComplaintDto extends PartialType(CreateComplaintDto) {}
@@ -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;
}
+4
View File
@@ -0,0 +1,4 @@
export enum ComplaintStatus {
WAITING_FOR_RESPONSE = 'waiting_for_response',
ANSWERED = 'answered'
}
@@ -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<Complaint> {
constructor(
@InjectRepository(Complaint) complaintRepository: ComplaintRepository,
) {
super(
complaintRepository.target,
complaintRepository.manager,
complaintRepository.queryRunner,
);
}
}
+5 -1
View File
@@ -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[];
}
@@ -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<Organ> {
constructor(@InjectRepository(Organ) organRepository: Repository<Organ>) {
super(organRepository.target, organRepository.manager, organRepository.queryRunner);
+6
View File
@@ -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[];
}