Skip to content

Commit

Permalink
Merge pull request #77 from Xitija/my-cohort
Browse files Browse the repository at this point in the history
PS-1931 - API to create dynamic form. PS-2109 API to move cohort to academic year
  • Loading branch information
Shubham4026 authored Oct 29, 2024
2 parents 7e7de6a + b2b7153 commit f5f8e16
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 25 deletions.
11 changes: 11 additions & 0 deletions src/adapters/cohortacademicyearservicelocator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CohortAcademicYearDto } from "src/cohortAcademicYear/dto/cohort-academicyear.dto";
import { Request, Response } from "express";

export interface IServiceLocatorCohortAcademicYear {
createCohortAcademicYear(
tenantId: string,
request: Request,
cohortAcademicYearDto: CohortAcademicYearDto,
response: Response
);
}
3 changes: 2 additions & 1 deletion src/adapters/postgres/cohort-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,13 +974,14 @@ export class PostgresCohortService {
public async getCohortHierarchyData(requiredData, res) {
// my cohort
const apiId = APIID.COHORT_LIST;

const userAcademicYear: any[] =
await this.postgresCohortMembersService.isUserExistForYear(
requiredData.academicYearId,
requiredData.userId
);

if (userAcademicYear.length !== 1) {
if (userAcademicYear.length === 0) {
return APIResponse.error(
res,
apiId,
Expand Down
84 changes: 80 additions & 4 deletions src/adapters/postgres/cohortAcademicYear-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,90 @@
import { Injectable } from "@nestjs/common";
import { HttpStatus, Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { CohortAcademicYear } from "src/cohortAcademicYear/entities/cohortAcademicYear.entity";
import { Repository } from "typeorm";
import jwt_decode from "jwt-decode";
import { IServiceLocatorCohortAcademicYear } from "../cohortacademicyearservicelocator";
import { Request, Response } from "express";
import { CohortAcademicYearDto } from "src/cohortAcademicYear/dto/cohort-academicyear.dto";
import { APIID } from "@utils/api-id.config";
import APIResponse from "src/common/responses/response";
import { API_RESPONSES } from "@utils/response.messages";
import { PostgresAcademicYearService } from "./academicyears-adapter";
import { Cohort } from "src/cohort/entities/cohort.entity";

@Injectable()
export class CohortAcademicYearService {
export class CohortAcademicYearService implements IServiceLocatorCohortAcademicYear {

constructor(
private readonly postgresAcademicYearService: PostgresAcademicYearService,
@InjectRepository(Cohort)
private readonly cohortRepository: Repository<Cohort>,
@InjectRepository(CohortAcademicYear)
private readonly cohortAcademicYearRepository: Repository<CohortAcademicYear>
) {}
private readonly cohortAcademicYearRepository: Repository<CohortAcademicYear>,
) { }

async createCohortAcademicYear(tenantId: string, request: Request, cohortAcademicYearDto: CohortAcademicYearDto, response: Response) {
const apiId = APIID.ADD_COHORT_TO_ACADEMIC_YEAR;
try {
const decoded: any = jwt_decode(request.headers.authorization);
cohortAcademicYearDto.createdBy = decoded?.sub;
cohortAcademicYearDto.updatedBy = decoded?.sub;

const existingCohort = await this.cohortRepository.findOne({
where: { cohortId: cohortAcademicYearDto.cohortId, status: 'active' },
});


if (!existingCohort) {
return APIResponse.error(
response,
apiId,
HttpStatus.NOT_FOUND.toLocaleString(),
API_RESPONSES.COHORT_NOT_FOUND,
HttpStatus.NOT_FOUND
);
}

// verify if the academic year id is valid
const academicYear =
await this.postgresAcademicYearService.getActiveAcademicYear(
cohortAcademicYearDto.academicYearId,
tenantId
);

if (!academicYear) {
return APIResponse.error(
response,
apiId,
HttpStatus.NOT_FOUND.toLocaleString(),
API_RESPONSES.ACADEMICYEAR_NOT_FOUND,
HttpStatus.NOT_FOUND
);
}

const createdAcademicYear = await this.insertCohortAcademicYear(cohortAcademicYearDto.cohortId, cohortAcademicYearDto.academicYearId, cohortAcademicYearDto.createdBy, cohortAcademicYearDto.updatedBy);

if (createdAcademicYear) {
return APIResponse.success(
response,
apiId,
createdAcademicYear,
HttpStatus.OK,
API_RESPONSES.ADD_COHORT_TO_ACADEMIC_YEAR
);
}

} catch (error) {
const errorMessage = error.message || "Internal server error";
return APIResponse.error(
response,
apiId,
"Internal Server Error",
errorMessage,
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}

async insertCohortAcademicYear(
cohortId: string,
Expand Down
14 changes: 11 additions & 3 deletions src/adapters/postgres/fields-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class PostgresFieldsService implements IServicelocatorfields {
private fieldsRepository: Repository<Fields>,
@InjectRepository(FieldValues)
private fieldsValuesRepository: Repository<FieldValues>
) {}
) { }

async getFormCustomField(requiredData, response) {
const apiId = "FormData";
Expand Down Expand Up @@ -1224,8 +1224,8 @@ export class PostgresFieldsService implements IServicelocatorfields {
...(getFields?.includes("All")
? {}
: getFields?.length
? { name: In(getFields.filter(Boolean)) }
: {}),
? { name: In(getFields.filter(Boolean)) }
: {}),
};

const validContextTypes = contextType?.filter(Boolean);
Expand Down Expand Up @@ -1516,4 +1516,12 @@ export class PostgresFieldsService implements IServicelocatorfields {
result = await Promise.all(result);
return result;
}

public async getFieldsByIds(fieldIds: string[]) {
return this.fieldsRepository.find({
where: {
fieldId: In(fieldIds)
}
})
}
}
1 change: 1 addition & 0 deletions src/adapters/postgres/user-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,7 @@ export class PostgresUserService implements IServicelocator {
"email",
"temporaryPassword",
"createdBy",
"deviceId"
],
});
if (!userDetails) {
Expand Down
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { FormsModule } from "./forms/forms.module";
import { CoursePlannerModule } from "./course-planner/course-planner.module";
import { HttpService } from "@utils/http-service";
import { AcademicyearsModule } from "./academicyears/academicyears.module";
import { CohortAcademicYearModule } from "./cohortAcademicYear/cohortAcademicYear.module";

@Module({
imports: [
Expand All @@ -43,6 +44,7 @@ import { AcademicyearsModule } from "./academicyears/academicyears.module";
FormsModule,
CoursePlannerModule,
AcademicyearsModule,
CohortAcademicYearModule
],
controllers: [AppController],
providers: [AppService, HttpService],
Expand Down
45 changes: 45 additions & 0 deletions src/cohortAcademicYear/cohortAcademicYear.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
Controller, Headers, Post, UseFilters, UsePipes, Req,
Res, ValidationPipe,
BadRequestException,
Body
} from '@nestjs/common';
import { ApiBadRequestResponse, ApiBasicAuth, ApiBody, ApiCreatedResponse, ApiHeader, ApiInternalServerErrorResponse, ApiTags } from '@nestjs/swagger';
import { APIID } from '@utils/api-id.config';
import { API_RESPONSES } from '@utils/response.messages';
import { isUUID } from 'class-validator';
import { Response, Request } from 'express';
import { AllExceptionsFilter } from 'src/common/filters/exception.filter';
import { CohortAcademicYearDto } from './dto/cohort-academicyear.dto';
import { CohortAcademicYearAdapter } from './cohortacademicyearsadaptor';

@ApiTags("CohortAcademicYear")
@Controller('cohort-academic-year')
export class CohortAcademicYearController {

constructor(private readonly cohortAcademicYearAdapter: CohortAcademicYearAdapter) { }

@UseFilters(new AllExceptionsFilter(APIID.ADD_COHORT_TO_ACADEMIC_YEAR))
@Post("/create")
@ApiBasicAuth("access-token")
@ApiCreatedResponse({ description: "Form has been created successfully." })
@ApiBadRequestResponse({ description: "Bad request." })
@ApiInternalServerErrorResponse({ description: "Internal Server Error." })
@UsePipes(new ValidationPipe())
@ApiBody({ type: CohortAcademicYearDto })
@ApiHeader({
name: "tenantid",
})
public async createCohortAcademicYear(
@Headers() headers,
@Req() request: Request,
@Body() cohortAcademicYearDto: CohortAcademicYearDto,
@Res() response: Response
) {
let tenantId = headers["tenantid"];
if (tenantId && !isUUID(tenantId)) {
throw new BadRequestException(API_RESPONSES.TENANTID_VALIDATION);
}
return this.cohortAcademicYearAdapter.buildAcademicYears().createCohortAcademicYear(tenantId, request, cohortAcademicYearDto, response);
}
}
25 changes: 20 additions & 5 deletions src/cohortAcademicYear/cohortAcademicYear.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import { Module } from "@nestjs/common";
import { CohortAcademicYear } from "./entities/cohortAcademicYear.entity";
import { CohortAcademicYearService } from "../adapters/postgres/cohortAcademicYear-adapter";
// import { CohortAcademicYearController } from './cohortAcademicYear.controller';
import { CohortAcademicYearController } from "./cohortAcademicYear.controller";
import { TypeOrmModule } from "@nestjs/typeorm";
import { CohortAcademicYearAdapter } from "./cohortacademicyearsadaptor";
import { PostgresAcademicYearService } from "src/adapters/postgres/academicyears-adapter";
import { PostgresModule } from "src/adapters/postgres/postgres-module";
import { Cohort } from "src/cohort/entities/cohort.entity";
import { AcademicYear } from "src/academicyears/entities/academicyears-entity";

@Module({
imports: [],
// controllers: [CohortAcademicYearController],
providers: [CohortAcademicYearService],
imports: [
PostgresModule,
TypeOrmModule.forFeature([
CohortAcademicYear,
Cohort,
AcademicYear
]),
],
controllers: [CohortAcademicYearController],
providers: [CohortAcademicYearAdapter, CohortAcademicYearService, PostgresAcademicYearService],
exports: [CohortAcademicYearService]
})
export class CohortAcademicYearModule {}
export class CohortAcademicYearModule { }
18 changes: 18 additions & 0 deletions src/cohortAcademicYear/cohortacademicyearsadaptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Injectable } from "@nestjs/common";
import { IServiceLocatorCohortAcademicYear } from "src/adapters/cohortacademicyearservicelocator";
import { CohortAcademicYearService } from "src/adapters/postgres/cohortAcademicYear-adapter";

@Injectable()
export class CohortAcademicYearAdapter {
constructor(
private readonly postgresProviders: CohortAcademicYearService
) {}
buildAcademicYears(): IServiceLocatorCohortAcademicYear {
let adapter: IServiceLocatorCohortAcademicYear;
switch (process.env.ADAPTERSOURCE) {
case "postgres":
adapter = this.postgresProviders;
}
return adapter;
}
}
34 changes: 34 additions & 0 deletions src/cohortAcademicYear/dto/cohort-academicyear.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
IsNotEmpty,
IsUUID,
} from "class-validator";
import { ApiProperty } from "@nestjs/swagger";
import { Expose } from "class-transformer";

export class CohortAcademicYearDto {

@ApiProperty({
type: String,
description: "cohortId",
default: "",
})
@Expose()
@IsNotEmpty()
@IsUUID(undefined, { message: "Cohort Id must be a valid UUID" })
cohortId: string;

@ApiProperty({
type: String,
description: "academicYearId",
default: "",
})
@Expose()
@IsNotEmpty()
@IsUUID(undefined, { message: "Academic Year Id must be a valid UUID" })
academicYearId: string;

createdBy: string;

updatedBy: string;

}
12 changes: 10 additions & 2 deletions src/cohortMembers/dto/cohortMembers.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Exclude, Expose } from "class-transformer";
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { Expose } from "class-transformer";
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsUUID } from "class-validator";

export class CohortMembersDto {
Expand Down Expand Up @@ -28,6 +28,14 @@ export class CohortMembersDto {
@IsUUID(undefined, { message: "Cohort Id must be a valid UUID" })
cohortId: string;

@ApiProperty({
type: String,
description: "cohortAcademicYearId",
default: "",
})
@Expose()
@IsNotEmpty()
@IsUUID(undefined, { message: "cohortAcademicYearId Id must be a valid UUID" })
cohortAcademicYearId: string;

//userId
Expand Down
3 changes: 3 additions & 0 deletions src/common/utils/api-id.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ export const APIID = {
ACADEMICYEAR_CREATE: "api.academicyear.create",
ACADEMICYEAR_LIST: "api.academicyear.list",
ACADEMICYEAR_GET: "api.academicyear.get",
FORM_GET: "api.form.read",
FORM_CREATE: "api.form.create",
ADD_COHORT_TO_ACADEMIC_YEAR: 'api.create.cohortAcademicYear',
};
7 changes: 7 additions & 0 deletions src/common/utils/response.messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export const API_RESPONSES = {
COHORT_MEMBER_GET_SUCCESSFULLY: 'Cohort members details fetched successfully.',
COHORTMEMBER_NOTFOUND: 'Invalid input: Cohort Member not exist.',
ACADEMICYEAR_GET_SUCCESSFULLY: 'Get Successfully Academic year list',
FORM_CREATED_SUCCESSFULLY: 'Form created successfully',
ADD_COHORT_TO_ACADEMIC_YEAR: 'Cohort added with academic year successfully',
COHORT_NOT_FOUND: 'Cohort not found',
FORM_EXISTS: 'Form already exists',
INVALID_FORM: 'Invalid form',
INVALID_CONTEXT: (context) => `Invalid context: ${context}`,
INVALID_CONTEXTTYPE: (context, validContextTypes) => `Invalid contextType. For the context '${context}', it must be one of: ${validContextTypes}`,
COHORTID_NOTFOUND_FOT_THIS_YEAR: (cohortId) => `Cohort with cohortId ${cohortId} does not exist for this academic year`,
MAPPING_EXIST_BW_USER_AND_COHORT: (userId, cohortId) => `Mapping already exists for userId ${userId} and cohortId ${cohortId} for this academic year`,
COHORT_NOTMAPPED_WITH_USER: (removeCohortId, userId) => `Cohort Id ${removeCohortId} is not mapped to user Id${userId}} for this academic year`,
Expand Down
Loading

0 comments on commit f5f8e16

Please sign in to comment.