Skip to content
Snippets Groups Projects
Commit 611e8cc8 authored by Ivan Alglave's avatar Ivan Alglave
Browse files

feat: Tracking is now fully functionnal except PDF upload part (TODO by Amine)

parent 099068fb
No related branches found
No related tags found
1 merge request!5Crud internship
import { IConfig } from './config.model'; import { IConfig } from './config.model';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import * as path from 'path'; import * as path from 'path';
import { exit } from 'process';
// Store file local path in var for lisibility // Store file local path in var for lisibility
const CONFIG_DEV = 'config.json'; const CONFIG_DEV = 'config.json';
...@@ -22,10 +23,11 @@ switch (process.env.NODE_ENV) { ...@@ -22,10 +23,11 @@ switch (process.env.NODE_ENV) {
) as IConfig; ) as IConfig;
break; break;
default: default:
// This shouldn't happen // This happens when the environment isn't set
console.log('\x1b[31mFATAL: Cannot load config.\x1b[0m'); console.log(
config = null; '\x1b[31mFATAL: Cannot load config.\nInvalid application environment. Did you read the \x1b[4mREADME\x1b[0m\x1b[31m ?\x1b[0m',
break; );
exit(-1);
} }
// Export config // Export config
......
import { Injectable, NotFoundException } from '@nestjs/common'; import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose'; import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose'; import { Model } from 'mongoose';
import { BAD_REQUEST, CONFLICT, INTERNAL } from 'src/shared/HttpError'; import { BAD_REQUEST, CONFLICT } from 'src/shared/HttpError';
import { STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION } from 'src/shared/InternshipState'; import {
isStateValid,
STATE_COMPANY_SIGNS_INTERNSHIP_AGREEMENT,
STATE_DEAN_SIGNS_INTERNSHIP_AGREEMENT,
STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION,
STATE_RESPONSIBLE_SIGNS_INTERNSHIP_AGREEMENT,
STATE_SECRETARY_ESTABLISHES_INTERNSHIP_AGREEMENT,
STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION,
STATE_STUDENT_SIGNS_INTERNSHIP_AGREEMENT,
} from 'src/shared/InternshipState';
import { CreateInternshipDto } from '../dto/create-internship.dto'; import { CreateInternshipDto } from '../dto/create-internship.dto';
import { InternshipDto } from '../dto/internship.dto'; import { InternshipDto } from '../dto/internship.dto';
import { Internship } from '../schemas/internship.schema'; import { Internship } from '../schemas/internship.schema';
...@@ -78,6 +87,128 @@ export class InternshipDao { ...@@ -78,6 +87,128 @@ export class InternshipDao {
); );
}); });
private updateTrackingState = (
studentId: string,
state: string,
nextState: string,
contentHolder: string,
content: string | boolean,
callback: (err: any, value: any) => void,
) => {
this._internshipModel.findOneAndUpdate(
{
studentId,
'tracking.state': state,
},
{
$set: {
'tracking.state': nextState,
[contentHolder]: content,
},
},
{
new: true,
runValidators: true,
},
callback,
);
};
findByStudentIdAndUpdateTracking = (
studentId: string,
state: string,
content: string | boolean,
): Promise<Internship | void> =>
new Promise((resolve, reject) => {
if (!isStateValid(state)) reject(BAD_REQUEST);
console.log(typeof content);
let nextState: string, contentHolder: string;
let valid = false;
switch (state) {
case STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION: {
if (typeof content === 'boolean' && content === true) {
nextState = STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION;
contentHolder = 'tracking.studentEntersInternshipInformation';
valid = true;
} else reject(BAD_REQUEST);
break;
}
case STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION: {
if (typeof content === 'boolean' && content === true) {
// content === true -> Responsible agrees with internship
nextState = STATE_SECRETARY_ESTABLISHES_INTERNSHIP_AGREEMENT;
contentHolder = 'tracking.responsibleAcceptsInternshipInformation';
valid = true;
} else if (typeof content === 'boolean' && content === false) {
// content === false -> Responsible did not agree with internship, go back to student entering information
nextState = STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION;
contentHolder = 'tracking.responsibleAcceptsInternshipInformation';
valid = true;
} else reject(BAD_REQUEST);
break;
}
case STATE_SECRETARY_ESTABLISHES_INTERNSHIP_AGREEMENT: {
if (typeof content !== 'string') reject(BAD_REQUEST);
else {
nextState = STATE_STUDENT_SIGNS_INTERNSHIP_AGREEMENT;
contentHolder = 'tracking.secretaryEstablishesInternshipAgreement';
valid = true;
}
break;
}
case STATE_STUDENT_SIGNS_INTERNSHIP_AGREEMENT: {
if (typeof content !== 'string') reject(BAD_REQUEST);
else {
nextState = STATE_RESPONSIBLE_SIGNS_INTERNSHIP_AGREEMENT;
contentHolder = 'tracking.studentSignsInternshipAgreement';
valid = true;
}
break;
}
case STATE_RESPONSIBLE_SIGNS_INTERNSHIP_AGREEMENT: {
if (typeof content !== 'string') reject(BAD_REQUEST);
else {
nextState = STATE_COMPANY_SIGNS_INTERNSHIP_AGREEMENT;
contentHolder = 'tracking.responsibleSignsInternshipAgreement';
valid = true;
}
break;
}
case STATE_COMPANY_SIGNS_INTERNSHIP_AGREEMENT: {
if (typeof content !== 'string') reject(BAD_REQUEST);
else {
nextState = STATE_DEAN_SIGNS_INTERNSHIP_AGREEMENT;
contentHolder = 'tracking.companySignsInternshipAgreement';
valid = true;
}
break;
}
case STATE_DEAN_SIGNS_INTERNSHIP_AGREEMENT: {
if (typeof content !== 'string') reject(BAD_REQUEST);
else {
nextState = '/';
contentHolder = 'tracking.deanSignsInternshipAgreement';
valid = true;
}
break;
}
}
if (valid) {
this.updateTrackingState(
studentId,
state,
nextState,
contentHolder,
content,
(err, value) => {
if (err) reject(err);
else if (!value) reject(BAD_REQUEST);
else resolve(value);
},
);
}
});
findByStudentIdAndRemove = (studentId: string): Promise<Internship | void> => findByStudentIdAndRemove = (studentId: string): Promise<Internship | void> =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
this._internshipModel.findOneAndDelete({ studentId }, {}, (err) => { this._internshipModel.findOneAndDelete({ studentId }, {}, (err) => {
......
...@@ -18,25 +18,25 @@ import { InternshipService } from './internships.service'; ...@@ -18,25 +18,25 @@ import { InternshipService } from './internships.service';
@Controller('internships') @Controller('internships')
@UseInterceptors(HttpInterceptor) @UseInterceptors(HttpInterceptor)
export class InternshipsController { export class InternshipsController {
constructor(private readonly _groupsService: InternshipService) {} constructor(private readonly _internshipsService: InternshipService) {}
@Get() @Get()
findAll(): Promise<InternshipEntity[] | void> { findAll(): Promise<InternshipEntity[] | void> {
return this._groupsService.findAll(); return this._internshipsService.findAll();
} }
@Get(':studentId') @Get(':studentId')
findOne( findOne(
@Param() params: { studentId: string }, @Param() params: { studentId: string },
): Promise<InternshipEntity | void> { ): Promise<InternshipEntity | void> {
return this._groupsService.findOne(params.studentId); return this._internshipsService.findOne(params.studentId);
} }
@Post() @Post()
create( create(
@Body() internshipDto: CreateInternshipDto, @Body() internshipDto: CreateInternshipDto,
): Promise<InternshipEntity> { ): Promise<InternshipEntity> {
return this._groupsService.create(internshipDto); return this._internshipsService.create(internshipDto);
} }
@Put(':studentId') @Put(':studentId')
...@@ -44,23 +44,28 @@ export class InternshipsController { ...@@ -44,23 +44,28 @@ export class InternshipsController {
@Param() params: { studentId: string }, @Param() params: { studentId: string },
@Body() internshipDto: CreateInternshipDto, @Body() internshipDto: CreateInternshipDto,
): Promise<InternshipEntity | void> { ): Promise<InternshipEntity | void> {
return this._groupsService.update(params.studentId, internshipDto); return this._internshipsService.update(params.studentId, internshipDto);
} }
@Put(':studentId/tracking') @Put(':studentId/tracking')
updateState( updateState(
@Param() params: { studentId: string }, @Param() params: { studentId: string },
@Body() body: { state: string; content: string }, @Body() body: { state: string; content?: string | boolean },
) { ): Promise<InternshipEntity | void> {
if (!InternshipStates.isStateValid(body.state)) if (!InternshipStates.isStateValid(body.state))
throw BAD_TRACKING_STATE(body.state); throw BAD_TRACKING_STATE(body.state);
// Treat request and update tracking -> implement service + dao // AMINE : Handle PDF file upload -> save file in /pdf/ folder and set content as local file URL. In case of step with no file, set content as true/false
return this._internshipsService.updateTracking(
params.studentId,
body.state,
body.content,
);
} }
@Delete(':studentId') @Delete(':studentId')
delete( delete(
@Param() params: { studentId: string }, @Param() params: { studentId: string },
): Promise<InternshipEntity | void> { ): Promise<InternshipEntity | void> {
return this._groupsService.delete(params.studentId); return this._internshipsService.delete(params.studentId);
} }
} }
...@@ -22,6 +22,17 @@ export class InternshipService { ...@@ -22,6 +22,17 @@ export class InternshipService {
): Promise<InternshipEntity | void> => ): Promise<InternshipEntity | void> =>
this._internshipsDao.findByStudentIdAndUpdate(studentId, internship); this._internshipsDao.findByStudentIdAndUpdate(studentId, internship);
updateTracking = (
studentId: string,
state: string,
content: string | boolean,
): Promise<InternshipEntity | void> =>
this._internshipsDao.findByStudentIdAndUpdateTracking(
studentId,
state,
content,
);
delete = (studentId: string): Promise<InternshipEntity | void> => delete = (studentId: string): Promise<InternshipEntity | void> =>
this._internshipsDao.findByStudentIdAndRemove(studentId); this._internshipsDao.findByStudentIdAndRemove(studentId);
} }
import { ValidationPipe } from '@nestjs/common'; import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { exit } from 'process';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import config from './config'; import config from './config';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule);
const env = process.env.NODE_ENV; const env = process.env.NODE_ENV;
const app = await NestFactory.create(AppModule);
if (env === 'dev') { if (env === 'dev') {
app.enableCors(); app.enableCors();
} else if (env === 'prod') { } else if (env === 'prod') {
// enableCors for SPECIFIC origin only, aka the way it's supposed to be // enableCors for SPECIFIC origin only, aka the way it's supposed to be
} else { } else {
console.log( // unknown environement ?
'\x1b[31mFATAL: Invalid application environment.\nDid you read the \x1b[4mREADME\x1b[0m\x1b[31m ?\x1b[0m',
);
exit(-1);
} }
await app.useGlobalPipes( await app.useGlobalPipes(
new ValidationPipe({ new ValidationPipe({
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment