diff --git a/src/config/index.ts b/src/config/index.ts
index 916f17f78890c853628a00a582386df2355940fb..e948aaeb8cdb7af0e37d8b5ec06c5e704881c2c0 100644
--- a/src/config/index.ts
+++ b/src/config/index.ts
@@ -1,6 +1,7 @@
 import { IConfig } from './config.model';
 import { readFileSync } from 'fs';
 import * as path from 'path';
+import { exit } from 'process';
 
 // Store file local path in var for lisibility
 const CONFIG_DEV = 'config.json';
@@ -22,10 +23,11 @@ switch (process.env.NODE_ENV) {
     ) as IConfig;
     break;
   default:
-    // This shouldn't happen
-    console.log('\x1b[31mFATAL: Cannot load config.\x1b[0m');
-    config = null;
-    break;
+    // This happens when the environment isn't set
+    console.log(
+      '\x1b[31mFATAL: Cannot load config.\nInvalid application environment. Did you read the \x1b[4mREADME\x1b[0m\x1b[31m ?\x1b[0m',
+    );
+    exit(-1);
 }
 
 // Export config
diff --git a/src/internships/dao/internships.dao.ts b/src/internships/dao/internships.dao.ts
index 091d4d56a7d0f73bc45ba48029be6a446e21988e..b5bfdfc5babc8139f359b4db96dd05c6e8545377 100644
--- a/src/internships/dao/internships.dao.ts
+++ b/src/internships/dao/internships.dao.ts
@@ -1,8 +1,17 @@
 import { Injectable, NotFoundException } from '@nestjs/common';
 import { InjectModel } from '@nestjs/mongoose';
 import { Model } from 'mongoose';
-import { BAD_REQUEST, CONFLICT, INTERNAL } from 'src/shared/HttpError';
-import { STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION } from 'src/shared/InternshipState';
+import { BAD_REQUEST, CONFLICT } from 'src/shared/HttpError';
+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 { InternshipDto } from '../dto/internship.dto';
 import { Internship } from '../schemas/internship.schema';
@@ -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> =>
     new Promise((resolve, reject) => {
       this._internshipModel.findOneAndDelete({ studentId }, {}, (err) => {
diff --git a/src/internships/internships.controller.ts b/src/internships/internships.controller.ts
index 70c798990da55caabe07b1915aec4b57ce78b633..1fb011eb7d7a98fa8e58cf5981bf003c48d7033a 100644
--- a/src/internships/internships.controller.ts
+++ b/src/internships/internships.controller.ts
@@ -18,25 +18,25 @@ import { InternshipService } from './internships.service';
 @Controller('internships')
 @UseInterceptors(HttpInterceptor)
 export class InternshipsController {
-  constructor(private readonly _groupsService: InternshipService) {}
+  constructor(private readonly _internshipsService: InternshipService) {}
 
   @Get()
   findAll(): Promise<InternshipEntity[] | void> {
-    return this._groupsService.findAll();
+    return this._internshipsService.findAll();
   }
 
   @Get(':studentId')
   findOne(
     @Param() params: { studentId: string },
   ): Promise<InternshipEntity | void> {
-    return this._groupsService.findOne(params.studentId);
+    return this._internshipsService.findOne(params.studentId);
   }
 
   @Post()
   create(
     @Body() internshipDto: CreateInternshipDto,
   ): Promise<InternshipEntity> {
-    return this._groupsService.create(internshipDto);
+    return this._internshipsService.create(internshipDto);
   }
 
   @Put(':studentId')
@@ -44,23 +44,28 @@ export class InternshipsController {
     @Param() params: { studentId: string },
     @Body() internshipDto: CreateInternshipDto,
   ): Promise<InternshipEntity | void> {
-    return this._groupsService.update(params.studentId, internshipDto);
+    return this._internshipsService.update(params.studentId, internshipDto);
   }
 
   @Put(':studentId/tracking')
   updateState(
     @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))
       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(
     @Param() params: { studentId: string },
   ): Promise<InternshipEntity | void> {
-    return this._groupsService.delete(params.studentId);
+    return this._internshipsService.delete(params.studentId);
   }
 }
diff --git a/src/internships/internships.service.ts b/src/internships/internships.service.ts
index 5bdb50dd5bb6ea13ece244b2b4c14ab7c9cc11b7..9d3af2080dcac5cd1119734812c3638d8a54f3f1 100644
--- a/src/internships/internships.service.ts
+++ b/src/internships/internships.service.ts
@@ -22,6 +22,17 @@ export class InternshipService {
   ): Promise<InternshipEntity | void> =>
     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> =>
     this._internshipsDao.findByStudentIdAndRemove(studentId);
 }
diff --git a/src/main.ts b/src/main.ts
index 73418ec40e7590e32d10c7c56387f31a8057b1fd..c5c630c00749273794025342b1f60b6be049f12f 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,21 +1,17 @@
 import { ValidationPipe } from '@nestjs/common';
 import { NestFactory } from '@nestjs/core';
-import { exit } from 'process';
 import { AppModule } from './app.module';
 import config from './config';
 
 async function bootstrap() {
-  const app = await NestFactory.create(AppModule);
   const env = process.env.NODE_ENV;
+  const app = await NestFactory.create(AppModule);
   if (env === 'dev') {
     app.enableCors();
   } else if (env === 'prod') {
     // enableCors for SPECIFIC origin only, aka the way it's supposed to be
   } else {
-    console.log(
-      '\x1b[31mFATAL: Invalid application environment.\nDid you read the \x1b[4mREADME\x1b[0m\x1b[31m ?\x1b[0m',
-    );
-    exit(-1);
+    // unknown environement ?
   }
   await app.useGlobalPipes(
     new ValidationPipe({