diff --git a/backend/docs/Student.md b/backend/docs/Student.md
index a42a3aa69e89e4fccf659a809f0ee61bef74ced3..cf5be4bbdcbc8b824b6871333cd6d253fa779801 100644
--- a/backend/docs/Student.md
+++ b/backend/docs/Student.md
@@ -1,7 +1,7 @@
 # Student API
 
 ## Get Student Data by User Id
-- Endpoint: `/student/{id}`
+- Endpoint: `/student/{id}[?includeTranscript="true"|"false"&includeScore="true"|"false"&includeCredits="true"|"false"]`
 - HTTP Method: `GET`
 
 - Response Body (Success):
@@ -16,11 +16,137 @@
     "nik": "12345677777",
     "phone": "0812347890",
     "year": 2020,
-    "createdAt": "2021-02-17T03:35:10.494Z",
-    "updatedAt": "2021-02-17T03:35:10.494Z",
-    "advisorId": "57e19842-d712-45fd-9068-04cde6bf41f3",
-    "majorId": "d7123456-45fd-9068-0123-04cde6bf41f3",
-    "userId": "626a872a-7dbf-403a-bca3-83cb9946a9fe"
+    "createdAt": "2021-03-22T11:10:35.287Z",
+    "updatedAt": "2021-03-22T11:10:35.287Z",
+    "advisorId": "a6d2b6b1-7c03-4d9a-a12f-f32809d01639",
+    "majorId": "476cfe20-e7b2-4537-bdbc-3b76aa226ae3",
+    "userId": "052b3a5a-d51f-4cb5-ad8e-41ad94803cc5",
+    "Advisor": {
+        "id": "a6d2b6b1-7c03-4d9a-a12f-f32809d01639",
+        "userName": null,
+        "fullName": null,
+        "gender": null,
+        "nip": null,
+        "nik": null,
+        "phone": null,
+        "academicRole": "KAPRODI",
+        "createdAt": "2021-03-22T11:10:35.263Z",
+        "updatedAt": "2021-03-22T11:10:35.263Z",
+        "skillGroupId": "2d0e4681-d984-4ecb-b57f-b9b92fe6d996",
+        "userId": "052b3a5a-d51f-4cb5-ad8e-41ad94803cc5"
+    },
+    "Major": {
+        "id": "476cfe20-e7b2-4537-bdbc-3b76aa226ae3",
+        "numberCode": 235,
+        "name": "Magister Teknik Informatika",
+        "createdAt": "2021-03-22T11:10:34.922Z",
+        "updatedAt": "2021-03-22T11:10:34.922Z",
+        "facultyId": "f183c826-1b97-4b68-b448-53a0087c8c38",
+        "Faculty": {
+            "id": "f183c826-1b97-4b68-b448-53a0087c8c38",
+            "shortName": "STEI",
+            "fullName": "Sekolah Teknik Elektro dan Informatika",
+            "createdAt": "2021-03-22T11:10:34.807Z",
+            "updatedAt": "2021-03-22T11:10:34.807Z"
+        }
+    },
+    "studyPlans": [
+        {
+            "id": "94bb4598-d900-4f39-9e63-fd13bbb4c2aa",
+            "startYear": 2022,
+            "creditsTotal": 0,
+            "semester": "2",
+            "status": "DRAFT",
+            "notes": null,
+            "createdAt": "2021-03-22T11:30:01.305Z",
+            "updatedAt": "2021-03-22T11:30:01.305Z",
+            "studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
+            "studyPlanCourses": []
+        },
+        {
+            "id": "54dbfaa8-1af3-448f-b395-f6f873fdbb5d",
+            "startYear": 2022,
+            "creditsTotal": 0,
+            "semester": "1",
+            "status": "FINAL",
+            "notes": "LGTM",
+            "createdAt": "2021-03-22T11:13:28.237Z",
+            "updatedAt": "2021-03-22T11:18:29.776Z",
+            "studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
+            "studyPlanCourses": []
+        },
+        {
+            "id": "b5f12832-3ea8-4312-a077-ad26c1d1dc40",
+            "startYear": 2021,
+            "creditsTotal": 2,
+            "semester": "2",
+            "status": "FINAL",
+            "notes": "LGTM",
+            "createdAt": "2021-03-22T11:10:35.457Z",
+            "updatedAt": "2021-03-26T06:07:10.417Z",
+            "studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
+            "studyPlanCourses": [
+                {
+                    "id": "de473be6-92bd-4f66-a51a-949d69546ef5",
+                    "attendancePercentage": 0,
+                    "score": "T",
+                    "status": "APPROVED",
+                    "createdAt": "2021-03-26T06:07:10.390Z",
+                    "updatedAt": "2021-03-26T06:07:10.390Z",
+                    "courseClassId": "f52290f5-da7d-4d2b-b230-dd335d6a2247",
+                    "studyPlanId": "b5f12832-3ea8-4312-a077-ad26c1d1dc40",
+                    "CourseClass": {
+                        "courseId": "0e3ceed1-d054-4cb4-8396-05ddd58bade8"
+                    }
+                }
+            ]
+        },
+        {
+            "id": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
+            "startYear": 2021,
+            "creditsTotal": 5,
+            "semester": "1",
+            "status": "FINAL",
+            "notes": "LGTM",
+            "createdAt": "2021-03-22T11:10:35.444Z",
+            "updatedAt": "2021-03-22T11:10:35.444Z",
+            "studentId": "070d0c07-f741-4358-b90a-8bfe134e0198",
+            "studyPlanCourses": [
+                {
+                    "id": "b5f4b392-3a76-4a87-b733-d3730b65f7c9",
+                    "attendancePercentage": 0,
+                    "score": "A",
+                    "status": "APPROVED",
+                    "createdAt": "2021-04-06T12:57:16.089Z",
+                    "updatedAt": "2021-04-06T12:57:16.089Z",
+                    "courseClassId": "5ed2ff48-21ab-4152-a857-70faa5d8cfc4",
+                    "studyPlanId": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
+                    "CourseClass": {
+                        "courseId": "937a2f5c-0367-4090-8bc2-c9d9d73e7fed"
+                    }
+                },
+                {
+                    "id": "130b3fba-b1d9-4363-88ea-ba68f91914b0",
+                    "attendancePercentage": 0,
+                    "score": "B",
+                    "status": "APPROVED",
+                    "createdAt": "2021-04-06T12:57:16.108Z",
+                    "updatedAt": "2021-04-06T12:57:16.108Z",
+                    "courseClassId": "b4a2d11c-a0fa-4752-8d38-51e484737e65",
+                    "studyPlanId": "a9e9a9e8-904b-4af5-8fa2-47ca26bb7ea8",
+                    "CourseClass": {
+                        "courseId": "6ecf74c5-e667-4ea4-bc95-f535a7b11a00"
+                    }
+                }
+            ]
+        }
+    ],
+    "score": {
+        "nr": 0,
+        "ip": 3.5,
+        "ipk": 3.5
+    },
+    "creditsTotal": 7
 }
 ```
 
diff --git a/backend/src/controllers/student.js b/backend/src/controllers/student.js
index c241bb08cd967afaab597bdb5e4d1068546e7770..0a8f36102783380f9505db44e803c64d2892921d 100644
--- a/backend/src/controllers/student.js
+++ b/backend/src/controllers/student.js
@@ -1,41 +1,58 @@
+'use strict';
 const {
   Student,
-  Lecturer,
-  Major,
-  Faculty,
 } = require('../models/index');
 
+const {
+  NotExistError
+} = require('../util/error');
+
+const {
+  handleRequestWithInternalServerError,
+  handleRequestWithResourceItemNotFound
+} = require('../util/common');
+
+const {
+  getStudent,
+  getCreditsTotal,
+  getHistoricalTranscript,
+  getStudentIP,
+  getStudentIPK,
+  getStudentNR
+} = require('../util/db/student');
+
 exports.getStudentData = async(req, res) => {
-  const foundStudent = await Student.findOne({
-    where: {
-      userId: req.params.id,
-    },
-    include: [
-      {
-        model: Lecturer,
-        as: 'Advisor',
-      },
-      {
-        model: Major,
-        include: Faculty,
-      },
-    ],
-  }).catch(err => {
-    res.status(400)
-        .json({
-          status: 400,
-          message: 'Invalid uuid input.'
-        });
-  });
+  const { opts } = req;
 
-  if (foundStudent){
-    res.json(foundStudent);
-  } else {
-    res.status(400)
-        .json({
-          status: 400,
-          message: 'Student doesn\'t exist.',
-        });
+  try {
+    const student = await getStudent(opts);
+
+    if (req.includeTranscript.toLowerCase() === "true"){
+      student.dataValues.studyPlans = await getHistoricalTranscript(student.id);
+    }
+
+    if (req.includeScore.toLowerCase() === "true"){
+      const nr = await getStudentNR(student);
+      const ip = await getStudentIP(student);
+      const ipk = await getStudentIPK(student);
+      student.dataValues.score = {
+        nr,
+        ip,
+        ipk
+      };
+    }
+
+    if (req.includeCredits.toLowerCase() === "true"){
+      student.dataValues.creditsTotal = await getCreditsTotal(student);
+    }
+
+    res.json(student);
+  } catch (error) {
+    if (error instanceof NotExistError) {
+      handleRequestWithResourceItemNotFound(res, error);
+    } else {
+      handleRequestWithInternalServerError(res, error);
+    }
   }
 };
 
diff --git a/backend/src/middleware/student.js b/backend/src/middleware/student.js
new file mode 100644
index 0000000000000000000000000000000000000000..5beaf21500da99caa517cc075acedb022f69681e
--- /dev/null
+++ b/backend/src/middleware/student.js
@@ -0,0 +1,45 @@
+
+const {
+  Lecturer,
+  Major,
+  Faculty
+} = require('../models/index');
+
+const getStudentMiddleware = async(req, res, next) => {
+  const {
+    includeTranscript = "false",
+    includeScore = "false",
+    includeCredits = "false"
+  } = req.query;
+
+  const {
+    id
+  } = req.params;
+
+  req.opts = {
+    where: {
+      userId: id
+    }
+  };
+
+  req.opts.include = [
+    {
+      model: Lecturer,
+      as: 'Advisor',
+    },
+    {
+      model: Major,
+      include: Faculty,
+    },
+  ];
+
+  req.includeTranscript = includeTranscript;
+  req.includeScore = includeScore;
+  req.includeCredits = includeCredits;
+
+  next();
+};
+
+module.exports = {
+  getStudentMiddleware
+};
\ No newline at end of file
diff --git a/backend/src/routes/student.js b/backend/src/routes/student.js
index bab11558bab7aaf80a70afd34dbddc09f2d398e5..1852a2ce2679f0a46dc19e4fd07097b8c1077e7b 100644
--- a/backend/src/routes/student.js
+++ b/backend/src/routes/student.js
@@ -2,8 +2,12 @@ var express = require('express');
 var router = express.Router();
 
 var studentController = require('../controllers/student');
+const {
+  getStudentMiddleware
+} = require('../middleware/student');
 
 // GET request to get student data
+router.get('/:id', getStudentMiddleware);
 router.get('/:id', studentController.getStudentData);
 
 // PUT request to update student data
diff --git a/backend/src/test/student.controller.test.js b/backend/src/test/student.controller.test.js
index fe3b5ad47a82a893e730fbc02f41088f2ce8efb8..96cb7b5fd6c0f63ac8ea3092228554e9a45bd143 100644
--- a/backend/src/test/student.controller.test.js
+++ b/backend/src/test/student.controller.test.js
@@ -4,27 +4,36 @@ const Student = require('../models/index')['Student'];
 const Lecturer = require('../models/index')['Lecturer'];
 const Major = require('../models/index')['Major'];
 
-let chai = require('chai');
-let chaiHttp = require('chai-http');
-let server = require('../index');
-let should = chai.should();
+const chai = require('chai');
+const chaiHttp = require('chai-http');
+const server = require('../index');
+const should = chai.should();
+
+const {
+  EndpointEnum
+} = require('../enums/index');
 
 chai.use(chaiHttp);
 
-let EMAIL = 'ihsan@gmail.com';
-let PASSWORD = 'abc123';
-let SALT = 'salt';
-let DUMMY_ID = '57e19842-d712-45fd-9068-04cde6bf41f3';
-let INVALID_ID = '57e19842-d712-45fd-9068-04cde6bf41f';
-let LECTURER_USERNAME = 'di.aditia';
-let MAJOR_NAME = 'Informatika';
-let USERNAME = 'ihsan.ma';
-let FULLNAME = 'Ihsan Muhammad Asnadi';
-let GENDER = 'M';
-let NIM = '23520019';
-let NIK = '1234567890';
-let PHONE = '0823456789';
-let YEAR = 2020;
+const EMAIL = 'ihsan@gmail.com';
+const PASSWORD = 'abc123';
+const SALT = 'salt';
+const DUMMY_ID = '57e19842-d712-45fd-9068-04cde6bf41f3';
+const INVALID_ID = '57e19842-d712-45fd-9068-04cde6bf41f';
+const LECTURER_USERNAME = 'di.aditia';
+const MAJOR_NAME = 'Informatika';
+const USERNAME = 'ihsan.ma';
+const FULLNAME = 'Ihsan Muhammad Asnadi';
+const GENDER = 'M';
+const NIM = '23520019';
+const NIK = '1234567890';
+const PHONE = '0823456789';
+const YEAR = 2020;
+
+const SUCCESS_CODE = 200;
+const SERVER_ERROR_CODE = 500;
+const NOT_EXIST_ERROR_CODE = 404;
+const ERROR = "Error";
 
 describe('Student Test', () => {
 
@@ -47,16 +56,16 @@ describe('Student Test', () => {
         salt: SALT,
       });
 
-      const student = await Student.create({
+      await Student.create({
         userId: user.id,
       });
     });
 
     it('student get by user id success', (done) => {
       chai.request(server)
-        .get('/student/' + user.id)
+        .get(`${EndpointEnum.STUDENT}/${user.id}`)
         .end((err, res) => {
-          res.should.have.status(200);
+          res.should.have.status(SUCCESS_CODE);
           res.body.should.have.property('id');
           res.body.should.have.property('userName');
           res.body.should.have.property('fullName');
@@ -75,25 +84,94 @@ describe('Student Test', () => {
 
     it('student get by user id not exist', (done) => {
       chai.request(server)
-        .get('/student/' + DUMMY_ID)
+        .get(`${EndpointEnum.STUDENT}/${DUMMY_ID}`)
         .end((err, res) => {
-          res.should.have.status(400);
-          res.body.should.have.property('status').eql(400);
-          res.body.should.have.property('message').eql('Student doesn\'t exist.');
+          res.should.have.status(NOT_EXIST_ERROR_CODE);
+          res.body.should.have.property('name').eql(ERROR);
+          res.body.should.have.property('message').eql('Object doesn\'t exist.');
           done();
         });
     });
 
-      it('student get by user id invalid uuid', (done) => {
-          chai.request(server)
-              .get('/student/' + INVALID_ID)
-              .end((err, res) => {
-                  res.should.have.status(400);
-                  res.body.should.have.property('status').eql(400);
-                  res.body.should.have.property('message').eql('Invalid uuid input.');
-                  done();
-              });
-      });
+    it('student get by user id invalid uuid', (done) => {
+      chai.request(server)
+        .get(`${EndpointEnum.STUDENT}/${INVALID_ID}`)
+        .end((err, res) => {
+            res.should.have.status(SERVER_ERROR_CODE);
+            res.body.should.have.property('name').to.not.eql(null);
+            res.body.should.have.property('message').to.not.eql(null);
+            done();
+        });
+    });
+
+    it('should get by user id success include historical transcript', (done) => {
+      chai.request(server)
+        .get(`${EndpointEnum.STUDENT}/${user.id}?includeTranscript=true`)
+        .end((err, res) => {
+          res.should.have.status(SUCCESS_CODE);
+          res.body.should.have.property('id');
+          res.body.should.have.property('userName');
+          res.body.should.have.property('fullName');
+          res.body.should.have.property('gender');
+          res.body.should.have.property('nim');
+          res.body.should.have.property('nik');
+          res.body.should.have.property('phone');
+          res.body.should.have.property('studyPlans');
+          res.body.should.have.property('advisorId');
+          res.body.should.have.property('createdAt');
+          res.body.should.have.property('updatedAt');
+          res.body.should.have.property('majorId');
+          res.body.should.have.property('userId');
+          done();
+        });
+    });
+
+    it('should get by user id success include cumulative score', (done) => {
+      chai.request(server)
+        .get(`${EndpointEnum.STUDENT}/${user.id}?includeScore=true`)
+        .end((err, res) => {
+          res.should.have.status(SUCCESS_CODE);
+          res.body.should.have.property('id');
+          res.body.should.have.property('userName');
+          res.body.should.have.property('fullName');
+          res.body.should.have.property('gender');
+          res.body.should.have.property('nim');
+          res.body.should.have.property('nik');
+          res.body.should.have.property('phone');
+          res.body.should.have.property('score').to.not.eql(null);
+          res.body.score.should.have.property('nr');
+          res.body.score.should.have.property('ip');
+          res.body.score.should.have.property('ipk');
+          res.body.should.have.property('advisorId');
+          res.body.should.have.property('createdAt');
+          res.body.should.have.property('updatedAt');
+          res.body.should.have.property('majorId');
+          res.body.should.have.property('userId');
+          done();
+        });
+    });
+
+    it('should get by user id success include credits total', (done) => {
+      chai.request(server)
+        .get(`${EndpointEnum.STUDENT}/${user.id}?includeCredits=true`)
+        .end((err, res) => {
+          res.should.have.status(SUCCESS_CODE);
+          res.body.should.have.property('id');
+          res.body.should.have.property('userName');
+          res.body.should.have.property('fullName');
+          res.body.should.have.property('gender');
+          res.body.should.have.property('nim');
+          res.body.should.have.property('nik');
+          res.body.should.have.property('phone');
+          res.body.should.have.property('creditsTotal').to.not.eql(null);
+          res.body.should.have.property('advisorId');
+          res.body.should.have.property('createdAt');
+          res.body.should.have.property('updatedAt');
+          res.body.should.have.property('majorId');
+          res.body.should.have.property('userId');
+          done();
+        });
+    });
   });
 
   describe('/PUT/:id student', () => {
@@ -133,7 +211,7 @@ describe('Student Test', () => {
       };
 
       chai.request(server)
-        .put('/student/' + user.id)
+        .put(`${EndpointEnum.STUDENT}/${user.id}`)
         .send(student)
         .end((err, res) => {
           res.should.have.status(200);
@@ -145,11 +223,11 @@ describe('Student Test', () => {
 
     it('student update by user id not exist', (done) => {
       chai.request(server)
-        .get('/student/' + DUMMY_ID)
+        .get(`${EndpointEnum.STUDENT}/${DUMMY_ID}`)
         .end((err, res) => {
-          res.should.have.status(400);
-          res.body.should.have.property('status').eql(400);
-          res.body.should.have.property('message').eql('Student doesn\'t exist.');
+          res.should.have.status(NOT_EXIST_ERROR_CODE);
+          res.body.should.have.property('name').eql(ERROR);
+          res.body.should.have.property('message').eql('Object doesn\'t exist.');
           done();
         });
     });
@@ -168,7 +246,7 @@ describe('Student Test', () => {
       };
 
       chai.request(server)
-        .put('/student/' + user.id)
+        .put(`${EndpointEnum.STUDENT}/${user.id}`)
         .send(student)
         .end((err, res) => {
           res.should.have.status(400);
diff --git a/backend/src/util/db/student.js b/backend/src/util/db/student.js
new file mode 100644
index 0000000000000000000000000000000000000000..8a87b83076eac0b611d7905db9b9f74d860c70d7
--- /dev/null
+++ b/backend/src/util/db/student.js
@@ -0,0 +1,147 @@
+const {
+  StudyPlan,
+  StudyPlanCourse,
+  Student,
+  CourseClass
+} = require('../../models/index');
+
+const {
+  ScoreEnum
+} = require('../../enums/index');
+
+const {
+  NotExistError,
+} = require('../error');
+
+
+const getStudentIPK = async (student) => {
+  let cumulativeTotal = 0;
+  let cumulativeCount = 0;
+
+  let studyPlans = student.studyPlans;
+
+  if (!studyPlans){
+    studyPlans = await getHistoricalTranscript(student.id);
+  }
+
+  for (const studyPlan of studyPlans){
+    const {count, total} = getScoreOneStudyPlan(studyPlan);
+    cumulativeCount += count;
+    cumulativeTotal += total;
+  }
+
+  if (cumulativeCount !== 0) return Number((cumulativeTotal/cumulativeCount).toFixed(2));
+
+  return 0;
+}
+
+const getScoreOneStudyPlan = (studyPlan) => {
+  let count = 0;
+  let total = 0;
+
+  for (const studyPlanCourse of studyPlan.studyPlanCourses){
+    if (studyPlanCourse.score !== ScoreEnum.T.name ){
+      count += 1;
+      total += ScoreEnum[studyPlanCourse.score].value;
+    }
+  }
+
+  return {count, total};
+}
+
+const getStudentIP = async (student) => {
+  let total = 0;
+  let count = 0;
+
+  let studyPlans = student.studyPlans;
+
+  if (!studyPlans){
+    studyPlans = await getHistoricalTranscript(student.id);
+  }
+
+  let courses = []
+
+  for (const studyPlan of studyPlans){
+    for (const studyPlanCourse of studyPlan.studyPlanCourses){
+      if (studyPlanCourse.score !== ScoreEnum.T.name && !courses.includes(studyPlanCourse['CourseClass'].courseId)){
+        count += 1;
+        total += ScoreEnum[studyPlanCourse.score].value;
+        courses.push(studyPlanCourse['CourseClass'].courseId);
+      }
+    }
+  }
+
+  if (count !== 0) return Number((total/count).toFixed(2));
+
+  return 0;
+}
+
+const getStudentNR = async (student) => {
+  let studyPlans = student.studyPlans;
+
+  if (!studyPlans){
+    studyPlans = await getHistoricalTranscript(student.id);
+  }
+
+  if (studyPlans.length !== 0){
+    const currentStudyPlan = studyPlans[0];
+
+    const {count, total} = getScoreOneStudyPlan(currentStudyPlan);
+
+    if (count !== 0) return Number((total/count).toFixed(2));
+  }
+
+  return 0;
+}
+
+const getCreditsTotal = async (student) => {
+  let total = 0;
+  let studyPlans = student.studyPlans;
+
+  if (!studyPlans){
+    studyPlans = await getHistoricalTranscript(student.id);
+  }
+
+  for (const studyPlan of studyPlans){
+    total += studyPlan.creditsTotal;
+  }
+
+  return total;
+}
+
+const getStudent = async (opts) =>{
+  const student = await Student.findOne(opts);
+
+  if (!student) throw new NotExistError();
+
+  return student;
+}
+
+const getHistoricalTranscript = async (studentId) => {
+  return await StudyPlan.findAll({
+    where: {
+      studentId: studentId
+    },
+    include: [{
+      model: StudyPlanCourse,
+      as: 'studyPlanCourses',
+      include: [{
+        model: CourseClass,
+        attributes: ['courseId']
+      }]
+    }],
+    order: [
+      ['startYear', 'DESC'],
+      ['semester', 'DESC']
+    ]
+  });
+}
+
+module.exports = {
+  getStudentIPK,
+  getStudentIP,
+  getStudentNR,
+  getCreditsTotal,
+  getStudent,
+  getHistoricalTranscript
+}
\ No newline at end of file