diff --git a/src/app.module.ts b/src/app.module.ts index 9367c4296bbffba3212bbbb485a87b6314e0ac88..bd865e20070f5af8fc4c7d0a5cc01279da7b7d69 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -18,6 +18,7 @@ import { validate } from "./env.validation"; import { BerkasBimbingan } from "./entities/berkasBimbingan.entity"; import { PendaftaranSidsem } from "./entities/pendaftaranSidsem"; import { DosenBimbinganModule } from "./dosen-bimbingan/dosen-bimbingan.module"; +import { PenggunaModule } from "./pengguna/pengguna.module"; @Module({ imports: [ @@ -48,6 +49,7 @@ import { DosenBimbinganModule } from "./dosen-bimbingan/dosen-bimbingan.module"; DashboardModule, BimbinganModule, DosenBimbinganModule, + PenggunaModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/bimbingan/bimbingan.module.ts b/src/bimbingan/bimbingan.module.ts index e38f36070808080e8d7a21c402c302b65b180795..b77070fda6099172ac83112b4163af9a742f656d 100644 --- a/src/bimbingan/bimbingan.module.ts +++ b/src/bimbingan/bimbingan.module.ts @@ -6,6 +6,9 @@ import { Bimbingan } from "src/entities/bimbingan.entity"; import { PendaftaranTesis } from "src/entities/pendaftaranTesis.entity"; import { DosenBimbingan } from "src/entities/dosenBimbingan.entity"; import { BerkasBimbingan } from "src/entities/berkasBimbingan.entity"; +import { PenggunaModule } from "src/pengguna/pengguna.module"; +import { PenggunaService } from "src/pengguna/pengguna.service"; +import { Pengguna } from "src/entities/pengguna.entity"; @Module({ imports: [ @@ -14,10 +17,12 @@ import { BerkasBimbingan } from "src/entities/berkasBimbingan.entity"; PendaftaranTesis, DosenBimbingan, BerkasBimbingan, + Pengguna, ]), + PenggunaModule, ], controllers: [BimbinganController], - providers: [BimbinganService], + providers: [BimbinganService, PenggunaService], exports: [BimbinganService], }) export class BimbinganModule {} diff --git a/src/bimbingan/bimbingan.service.ts b/src/bimbingan/bimbingan.service.ts index 44a2824feaff3feff7d4381ce7ea879698f21d36..825ce9109b5ac2c4be8f5e68aa0e600b2eda67e0 100644 --- a/src/bimbingan/bimbingan.service.ts +++ b/src/bimbingan/bimbingan.service.ts @@ -24,6 +24,7 @@ import { UpdateStatusResDto, } from "./bimbingan.dto"; import { BerkasBimbingan } from "src/entities/berkasBimbingan.entity"; +import { PenggunaService } from "src/pengguna/pengguna.service"; @Injectable() export class BimbinganService { @@ -36,12 +37,15 @@ export class BimbinganService { private dosenBimbinganRepository: Repository<DosenBimbingan>, @InjectRepository(BerkasBimbingan) private berkasBimbinganRepository: Repository<BerkasBimbingan>, + private penggunaService: PenggunaService, ) {} async getByMahasiswaId( mahasiswaId: string, user: AuthDto, ): Promise<GetByMahasiswaIdResDto> { + await this.penggunaService.isMahasiswaAktifOrFail(mahasiswaId); + const pendaftaran = await this.pendaftaranTesisRepository.findOne({ where: { mahasiswa: { id: mahasiswaId }, @@ -159,7 +163,7 @@ export class BimbinganService { user: AuthDto, dto: UpdateStatusDto, ): Promise<UpdateStatusResDto> { - const bimbingan = await this.getByBimbinganId(user, dto.bimbinganId); + const bimbingan = await this.getByBimbinganId(user, dto.bimbinganId); // already check if mahasiswa is aktif await this.bimbinganRepository.update(bimbingan.id, { disahkan: dto.status, @@ -189,6 +193,10 @@ export class BimbinganService { throw new NotFoundException("Bimbingan tidak ditemukan"); } + if (!bimbingan.pendaftaran.mahasiswa.aktif) { + throw new BadRequestException("Bimbingan milik mahasiswa tidak aktif"); + } + if ( !user.roles.includes(RoleEnum.ADMIN) && !bimbingan.pendaftaran.dosenBimbingan diff --git a/src/dashboard/dashboard.service.ts b/src/dashboard/dashboard.service.ts index 7486c3326544ea25525f44d9f8652422c24b6d6c..f168aa396a89aaf5a062d1c061baffa0ad988f45 100644 --- a/src/dashboard/dashboard.service.ts +++ b/src/dashboard/dashboard.service.ts @@ -41,6 +41,7 @@ export class DashboardService { dosenId, }, ) + .where("mahasiswa.aktif = true") .andWhere("pendaftaranTesis.status = :status", { status: RegStatus.APPROVED, }); @@ -94,7 +95,7 @@ export class DashboardService { .createQueryBuilder("pendaftaranTesis") .select("pendaftaranTesis.jalurPilihan", "jalurPilihan") .addSelect("COUNT(*)", "count") - .leftJoin("pendaftaranTesis.topik", "topik") + .leftJoin("pendaftaranTesis.mahasiswa", "mahasiswa") .innerJoin( "pendaftaranTesis.dosenBimbingan", "dosenBimbingan", @@ -103,6 +104,7 @@ export class DashboardService { dosenId, }, ) + .where("mahasiswa.aktif = true") .andWhere("pendaftaranTesis.status = :status", { status: RegStatus.APPROVED, }) diff --git a/src/dosen-bimbingan/dosen-bimbingan.module.ts b/src/dosen-bimbingan/dosen-bimbingan.module.ts index 5fef686432cab313dc8ac0c825577a31d2df4bcd..1721d9d65412532695c2c187b62f6aec9e248070 100644 --- a/src/dosen-bimbingan/dosen-bimbingan.module.ts +++ b/src/dosen-bimbingan/dosen-bimbingan.module.ts @@ -3,16 +3,11 @@ import { DosenBimbinganController } from "./dosen-bimbingan.controller"; import { DosenBimbinganService } from "./dosen-bimbingan.service"; import { AuthModule } from "src/auth/auth.module"; import { TypeOrmModule } from "@nestjs/typeorm"; -import { PendaftaranTesis } from "src/entities/pendaftaranTesis.entity"; -import { DosenBimbingan } from "src/entities/dosenBimbingan.entity"; import { Pengguna } from "src/entities/pengguna.entity"; import { CustomStrategy } from "src/middlewares/custom.strategy"; @Module({ - imports: [ - TypeOrmModule.forFeature([PendaftaranTesis, DosenBimbingan, Pengguna]), - AuthModule, - ], + imports: [TypeOrmModule.forFeature([Pengguna]), AuthModule], controllers: [DosenBimbinganController], providers: [DosenBimbinganService, CustomStrategy], }) diff --git a/src/entities/pengguna.entity.ts b/src/entities/pengguna.entity.ts index e1d014aa3f0e121befc89647f955816e7192de1a..1b4971a18ab5a34f1f1e501d10aaf464b752b553 100644 --- a/src/entities/pengguna.entity.ts +++ b/src/entities/pengguna.entity.ts @@ -55,6 +55,10 @@ export class Pengguna { @Column({ type: "text", nullable: true }) kontak: string; + @ApiHideProperty() + @Column({ type: "boolean", default: true }) + aktif: boolean; + @OneToMany(() => PendaftaranTesis, (pendaftaran) => pendaftaran.mahasiswa) pendaftaranTesis: PendaftaranTesis[]; } diff --git a/src/pengguna/pengguna.module.ts b/src/pengguna/pengguna.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..3e5276cbb4849fcc7453b7b2618834fcd3a2f3c7 --- /dev/null +++ b/src/pengguna/pengguna.module.ts @@ -0,0 +1,11 @@ +import { Module } from "@nestjs/common"; +import { PenggunaService } from "./pengguna.service"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { Pengguna } from "src/entities/pengguna.entity"; + +@Module({ + imports: [TypeOrmModule.forFeature([Pengguna])], + providers: [PenggunaService], + exports: [PenggunaService], +}) +export class PenggunaModule {} diff --git a/src/pengguna/pengguna.service.ts b/src/pengguna/pengguna.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..28281715431f789c616d7213ec8a8cea18b7c80c --- /dev/null +++ b/src/pengguna/pengguna.service.ts @@ -0,0 +1,24 @@ +import { Injectable, NotFoundException } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Pengguna, RoleEnum } from "src/entities/pengguna.entity"; +import { ArrayContains, Repository } from "typeorm"; + +@Injectable() +export class PenggunaService { + constructor( + @InjectRepository(Pengguna) + private penggunaRepo: Repository<Pengguna>, + ) {} + + async isMahasiswaAktifOrFail(id: string) { + const mhs = await this.penggunaRepo.findOneBy({ + id, + aktif: true, + roles: ArrayContains([RoleEnum.S2_MAHASISWA]), + }); + + if (!mhs) { + throw new NotFoundException("Mahasiswa aktif tidak ditemukan"); + } + } +} diff --git a/src/registrasi-tesis/registrasi-tesis.controller.ts b/src/registrasi-tesis/registrasi-tesis.controller.ts index e740095162f52433c0eee3d60f64becfa21fa45d..0ac28aece930cb6f6c9ea7ec037540d9ec3d5f1e 100644 --- a/src/registrasi-tesis/registrasi-tesis.controller.ts +++ b/src/registrasi-tesis/registrasi-tesis.controller.ts @@ -52,7 +52,7 @@ export class RegistrasiTesisController { ) {} @ApiOperation({ - summary: "Create new registration. Roles: S2_MAHASISWA, ADMIN", + summary: "Create new registration. Roles: S2_MAHASISWA", }) @ApiCreatedResponse({ type: IdDto }) @ApiNotFoundResponse({ description: "Penerima atau topik tidak ditemukan" }) @@ -61,7 +61,7 @@ export class RegistrasiTesisController { "Mahasiswa sedang memiliki pendaftaran aktif atau judul dan deskripsi topik baru tidak ada", }) @UseGuards(CustomAuthGuard, RolesGuard) - @Roles(RoleEnum.S2_MAHASISWA, RoleEnum.ADMIN) + @Roles(RoleEnum.S2_MAHASISWA) @Post() async createTopicRegistration( @Body() topicRegistrationDto: RegDto, diff --git a/src/registrasi-tesis/registrasi-tesis.module.ts b/src/registrasi-tesis/registrasi-tesis.module.ts index 8e177eb6d1e247ef6efa907c4492c47944f36317..0b64d44cec70b955ad05a008eedd82f63760e1c3 100644 --- a/src/registrasi-tesis/registrasi-tesis.module.ts +++ b/src/registrasi-tesis/registrasi-tesis.module.ts @@ -8,6 +8,8 @@ import { RegistrasiTesisService } from "./registrasi-tesis.service"; import { Topik } from "src/entities/topik.entity"; import { CustomStrategy } from "src/middlewares/custom.strategy"; import { AuthModule } from "src/auth/auth.module"; +import { PenggunaModule } from "src/pengguna/pengguna.module"; +import { PenggunaService } from "src/pengguna/pengguna.service"; @Module({ imports: [ @@ -18,8 +20,9 @@ import { AuthModule } from "src/auth/auth.module"; Topik, ]), AuthModule, + PenggunaModule, ], controllers: [RegistrasiTesisController], - providers: [RegistrasiTesisService, CustomStrategy], + providers: [RegistrasiTesisService, CustomStrategy, PenggunaService], }) export class RegistrasiTesisModule {} diff --git a/src/registrasi-tesis/registrasi-tesis.service.ts b/src/registrasi-tesis/registrasi-tesis.service.ts index f3c861c89e458bc01c61645c1ee816158523beaf..c2f221a3092661d1fc9e9c491863b181e9d62c6f 100644 --- a/src/registrasi-tesis/registrasi-tesis.service.ts +++ b/src/registrasi-tesis/registrasi-tesis.service.ts @@ -25,6 +25,7 @@ import { UpdatePembimbingBodyDto, UpdateStatusBodyDto, } from "./registrasi-tesis.dto"; +import { PenggunaService } from "src/pengguna/pengguna.service"; @Injectable() export class RegistrasiTesisService { @@ -38,6 +39,7 @@ export class RegistrasiTesisService { @InjectRepository(DosenBimbingan) private dosenBimbinganRepository: Repository<DosenBimbingan>, private dataSource: DataSource, + private penggunaService: PenggunaService, ) {} async createTopicRegistration( @@ -124,6 +126,8 @@ export class RegistrasiTesisService { isNewestOnly: boolean, idPenerima?: string, ) { + await this.penggunaService.isMahasiswaAktifOrFail(mahasiswaId); + const baseQuery = this.pendaftaranTesisRepository .createQueryBuilder("pt") .select("pt.id") @@ -208,56 +212,33 @@ export class RegistrasiTesisService { "latest", "latest.latest_mahasiswaId = pt.mahasiswaId AND pt.waktuPengiriman = latest.latestPengiriman", ) - .innerJoinAndSelect("pt.topik", "topik"); + .innerJoin("pt.mahasiswa", "mahasiswa") + .where("mahasiswa.aktif = true"); if (options.idPenerima) { - baseQuery.where("pt.penerimaId = :idPenerima", { + baseQuery.andWhere("pt.penerimaId = :idPenerima", { idPenerima: options.idPenerima, }); totalMahasiswa = baseQuery.getCount(); } - let totalDiterima: Promise<number>; - let totalProses: Promise<number>; - let totalDitolak: Promise<number>; + const totalDiterima = baseQuery + .clone() + .andWhere("pt.status = :status", { status: RegStatus.APPROVED }) + .getCount(); - if (options.idPenerima) { - // where used - totalDiterima = baseQuery - .clone() - .andWhere("pt.status = :status", { status: RegStatus.APPROVED }) - .getCount(); - - totalProses = baseQuery - .clone() - .andWhere("pt.status IN (:...status)", { - status: [RegStatus.NOT_ASSIGNED, RegStatus.INTERVIEW], - }) - .getCount(); - - totalDitolak = baseQuery - .clone() - .andWhere("pt.status = :status", { status: RegStatus.REJECTED }) - .getCount(); - } else { - totalDiterima = baseQuery - .clone() - .where("pt.status = :status", { status: RegStatus.APPROVED }) - .getCount(); - - totalProses = baseQuery - .clone() - .where("pt.status IN (:...status)", { - status: [RegStatus.NOT_ASSIGNED, RegStatus.INTERVIEW], - }) - .getCount(); - - totalDitolak = baseQuery - .clone() - .where("pt.status = :status", { status: RegStatus.REJECTED }) - .getCount(); - } + const totalProses = baseQuery + .clone() + .andWhere("pt.status IN (:...status)", { + status: [RegStatus.NOT_ASSIGNED, RegStatus.INTERVIEW], + }) + .getCount(); + + const totalDitolak = baseQuery + .clone() + .andWhere("pt.status = :status", { status: RegStatus.REJECTED }) + .getCount(); const [total, diterima, proses, ditolak] = await Promise.all([ totalMahasiswa, @@ -311,45 +292,32 @@ export class RegistrasiTesisService { ); baseQuery - .innerJoinAndSelect("pt.topik", "topik") .innerJoinAndSelect("pt.penerima", "penerima") - .innerJoinAndSelect("pt.mahasiswa", "mahasiswa"); + .innerJoinAndSelect("pt.mahasiswa", "mahasiswa") + .where("mahasiswa.aktif = true"); - let whereUsed = false; if (options.idPenerima) { - baseQuery.where("pt.penerimaId = :idPenerima", { + baseQuery.andWhere("pt.penerimaId = :idPenerima", { idPenerima: options.idPenerima, }); - - whereUsed = true; } if (options.search) { - const bracket = new Brackets((qb) => - qb - .where("mahasiswa.nama ILIKE :search", { - search: `%${options.search}%`, - }) - .orWhere("mahasiswa.nim ILIKE :search", { - search: `%${options.search}%`, - }), + baseQuery.andWhere( + new Brackets((qb) => + qb + .where("mahasiswa.nama ILIKE :search", { + search: `%${options.search}%`, + }) + .orWhere("mahasiswa.nim ILIKE :search", { + search: `%${options.search}%`, + }), + ), ); - - if (whereUsed) { - baseQuery.andWhere(bracket); - } else { - baseQuery.where(bracket); - whereUsed = true; - } } if (options.status) { - if (whereUsed) { - baseQuery.andWhere("pt.status = :status", { status: options.status }); - } else { - baseQuery.where("pt.status = :status", { status: options.status }); - whereUsed = true; - } + baseQuery.andWhere("pt.status = :status", { status: options.status }); } if (options.order_by) { @@ -444,6 +412,8 @@ export class RegistrasiTesisService { dto: UpdateInterviewBodyDto, idPenerima?: string, ) { + await this.penggunaService.isMahasiswaAktifOrFail(mahasiswaId); + const minDate = new Date(); minDate.setDate(minDate.getDate() + 2); @@ -486,6 +456,8 @@ export class RegistrasiTesisService { dto: UpdateStatusBodyDto, idPenerima?: string, ) { + await this.penggunaService.isMahasiswaAktifOrFail(mahasiswaId); + const newestReg = await this.getNewestRegByMhsOrFail(mahasiswaId); if (newestReg && idPenerima && newestReg.penerima.id !== idPenerima) { @@ -531,6 +503,8 @@ export class RegistrasiTesisService { mahasiswaId: string, { pembimbing_ids: dosen_ids }: UpdatePembimbingBodyDto, ) { + await this.penggunaService.isMahasiswaAktifOrFail(mahasiswaId); + const newestReg = await this.getNewestRegByMhsOrFail(mahasiswaId); if (newestReg.status !== RegStatus.APPROVED)