본문 바로가기

Test

5/15(월) IT K-DT(52일차) / (비NCS)파이썬 웹 개발2 평가

 

문제

 

문제 아래 내용을 참고하여 프로그램 작성 후 업로드하세요.
내용 주어진 요구 사항을 확인한 후, 문제의 답안을 작성하세요
다음의 요구사항에 따라 제공된 데이터베이스를 참고하여 학생관리 웹사이트의 API를 작성하세요.


DATABASE명: student
학생 테이블 필드 : 일렬번호(자동증가), 학번(문자열), 이름(문자열), 연락처(문자열), 이메일, 주소(문자열), 등록된 날짜(날짜)
성적 테이블 필드 : 일렬번호(숫자), 자바점수(숫자), 파이썬점수(숫자), C언어점수(숫자), 등록된 날짜(날짜), 총점(숫자), 평균(숫자)


1. 학생을 등록한다. (10점)
2. 학생의 등록된 정보를 성적(평균)으로 내림차순으로 출력한다. (10점)
(단, 학생의 점수를 출력한다. 등록된 학생의 전체 수와 해당 학생의 석차를 같이 출력한다. 동점인 경우 학번으로 내림차순으로 함)
3. 학생정보를 수정한다. (10점)
4. 학생정보를 삭제한다. 학생정보를 삭제할 경우 점수도 같이 삭제한다. (10점)
5. 학번으로 검색한다. (10점)
(단, 학생의 점수를 출력한다.)
6. 학생점수를 등록한다. 점수를 등록할 때 총점, 평균을 계산하여 같이 저장한다. (10점)
7. 학생점수를 수정한다. 점수를 수정할 경우 총점, 평균을 계산하여 같이 저장한다. (10점)
8. 학생점수를 삭제한다. (10점)
9. Github에 push하고 해당 주소를 제출한다. (10점)
10. ORM을 사용한다. (10점)


* 아래 내용을 확인해주세요. (아래 내용이 작성되지 않을 경우 부분 감점)
1. 모든 키는 "일렬번호" 필드를 사용
2. 소스코드에는 각 프로그램 라인을 설명할 수 있는 주석문을 자세하게 작성
3. API 주소 자유롭게 생성하고 주석으로 표기, 실행 방법은 npm start로 작성 


* 제출방법
모든 파일(소스파일, SQL스크립트 파일)을 압축하여 업로드합니다. (단, node_modules는 제외하고 제출)


* 각 문제의 부분 점수는 아래와 같습니다.
상(10점), 중(7점), 하(5), 에러(3)

 

답안 및 보충

 

5/15 node.js의 서버단 구축 및 CRUD 기능 시험 간 부족했던 부분의 보완 목적으로 작성.

내 것과 다른 사람의 것을 비교해서 어떤 부분이 다른지를 확인하는 방식으로 리뷰.

test0515_상대방.zip
0.03MB
test0515_내것.zip
0.03MB

 

1. 디렉토리 및 파일

내 것: 강사님의 예제를 그대로 따오느라 필요없는 connection파일 및 auth.js파일까지 모두 포함함.

다른 사람의 것: gitignore과 .sql파일까지 모두 포함.

 

각 테이블의 생성

 

내 것

data\tweet.js

import SQ from 'sequelize' // sequelize 모듈 사용
import { sequelize } from '../db/database.js'; // database.js파일의 sequelize 매개변수 사용.

const DataTypes = SQ.DataTypes // datatypes라는 매개변수를 sequelize의 메서드를 이용하여 사용.

// 학생 테이블 필드 생성
export const Student = sequelize.define('student', {
    id: {
        type: DataTypes.INTEGER, // 일렬번호(자동증가) 생성
        autoIncrement: true,
        primaryKey: true
    },
    studentNumber: {
        type: DataTypes.STRING  // 학번(문자열) 생성
    },
    name: {
        type: DataTypes.STRING   // 이름(문자열) 생성
    },
    contact: {
        type: DataTypes.STRING   // 연락처(문자열) 생성
    },
    email: {
        type: DataTypes.STRING   // 이메일 생성
    },
    address: {
        type: DataTypes.STRING   // 주소(문자열) 생성
    },
    registeredDate: {
        type: DataTypes.DATE,   // 등록된 날짜 생성
        defaultValue: DataTypes.NOW
    },
},
    { timestamps: false, } // timestamp로 등록시간 조정
);

// 성적 테이블 필드 생성
export const Grade = sequelize.define('grade', {
    id: {
        type: DataTypes.INTEGER,  // 일렬번호(숫자) 생성
        autoIncrement: true,
        primaryKey: true
    },
    javaScore: {
        type: DataTypes.STRING   // 자바점수(숫자) 생성
    },
    pythonScore: {
        type: DataTypes.STRING  // 파이썬점수(숫자) 생성
    },
    cScore: {
        type: DataTypes.STRING   // C언어점수(숫자) 생성
    },
    registeredDate: {
        type: DataTypes.DATE,
        defaultValue: DataTypes.NOW  // 등록된 날짜 생성
    },
    totalScore: {
        type: DataTypes.STRING   // 총점(숫자) 생성
    },
    averageScore: {
        type: DataTypes.STRING  // 평균(숫자) 생성
    },
},    { timestamps: false, }  // timestamp로 등록시간 조정
);

Student.belongsTo(Grade);  // student와 grade의 join



 // join했을 때 보고싶은것만 뽑아오는 목록을 새롭게 정의.
const INCLUDE_USER = {
    attributes: [
        ['id'],
        ['studentNumber'],
        ['name'],
        [sequelize.col('grade.javaScore'), 'javaScore'],
        [sequelize.col('grade.pythonScore'), 'pythonScore'],
        [sequelize.col('grade.cScore'), 'cScore'],        
        [sequelize.literal('RANK() OVER (ORDER BY Grade.averageScore DESC'), 'rank'],
    ],
    include: {         
        model: Student,
        attributes: [],
    }
}

 // 다음 필터인 학번을 기준으로 내림차순으로 가져옴.
const ORDER_DESC = {     
    order: [['studentNumber', 'DESC']]
}

상대방의 것

\db\score.js

import SQ from 'sequelize';
import { sequelize } from './database.js';
import { Student } from './student.js';

const DataTypes = SQ.DataTypes;

// score 테이블을 생성
export const Score = sequelize.define(
    'score',
    // 컬럼들의 type과 제약조건을 설정
    {
        java: {
            type: DataTypes.INTEGER,
            allowNull: false
        },
        python: {
            type: DataTypes.INTEGER,
            allowNull: false
        },
        c: {
            type: DataTypes.INTEGER,
            allowNull: false
        },
        score_date: {
            type: DataTypes.DATE,
            defaultValue: DataTypes.NOW
        },
        total: {
            type: DataTypes.INTEGER,
            allowNull: false
        },
        avg: {
            type: DataTypes.FLOAT,
            allowNull: false
        }
    },
    // 시간자동 생성을 막고 테이블명이 복수형으로 변하지 않도록 설정
    { timestamps: false, freezeTableName: true }
);

// 서로 num컬럼으로 1대1 참조 할 수 있도록 외래키를 설정
Student.hasOne(Score, { foreignKey: 'num' });
Score.belongsTo(Student, { foreignKey: 'num' });

\db\student.js

import SQ from 'sequelize';
import { sequelize } from './database.js';

const DataTypes = SQ.DataTypes;

// student 테이블을 생성
export const Student = sequelize.define(
    'student',
    // 컬럼들의 type과 제약조건을 설정
    {
        num: {
            type: DataTypes.INTEGER,
            autoIncrement: true,
            allowNull: false,
            primaryKey: true
        },
        id: {
            type: DataTypes.STRING(25),
            allowNull: false,
            unique: true
        },
        name: {
            type: DataTypes.STRING(45),
            allowNull: false
        },
        ph: {
            type: DataTypes.STRING(25),
            allowNull: false
        },
        email: {
            type: DataTypes.STRING(128),
            allowNull: false
        },
        address: {
            type: DataTypes.STRING(256),
            allowNull: false
        },
        regdate: {
            type: DataTypes.DATE,
            defaultValue:DataTypes.NOW
        }
    },
    // 시간자동 생성을 막고 테이블명이 복수형으로 변하지 않도록 설정
    { timestamps: false, freezeTableName: true }
);

다른 점:

1. 상대방은 student.js를 먼저 만든 후, 이후 score.js에 student.js를 import하는 방식을 사용하여 join을 함.

2. 제약조건에 모두 allowNull: false를 걸어준 후, integer과 float를 score부분에 사용.

3. 시간자동생성을 막고, 테이블이 복수형으로 변하지 않게 설정: timestamps:false, freezeTableName: true

4. 테이블의 생성과 관련된 코드를 난 data.js에 모두 넣었지만 상대방은 db폴더에 나누어서 넣음.

 

DB의 연결

내 것

db\database.js

import {config} from '../config.js';
import SQ from 'sequelize';

const {host, user, database, password } = config.db;
// config.db에서 host, user, database, password를 가져옴.

export const sequelize = new SQ.Sequelize(database, user, password, {
    host,
    dialect: 'mysql',
    logging: false,    // log를 남기지 않겠다는 의미.
})

상대방의 것

db\database.js

import { config } from '../config.js';
import SQ from 'sequelize';

// config에서 환경변수를 가져와 저장
const { host, user, database, password } = config.db;

// sequelize에 환경변수들을 넣어 MySQL과 연결하고 시간을 서울 기준으로 설정
export const sequelize = new SQ.Sequelize(database, user, password, {
    host,
    dialect: 'mysql',
    logging: false,
    timezone: 'Asia/Seoul'
});

다른 점:

1. timezone을 Asia/Seoul로 작성하여 시간을 서울기준으로 설정함.

 

data 디렉토리

나의 것

data\tweet.js

import SQ from 'sequelize' // sequelize 모듈 사용
import { sequelize } from '../db/database.js'; // database.js파일의 sequelize 매개변수 사용.


// 1번 문제. 학생을 등록한다. (10점)
export async function registerStudent(user){
    return Student.create(user).then((data)=>data.datavalues.id);
}

// 2. 학생의 등록된 정보를 성적(평균)으로 내림차순으로 출력한다. (10점)
// (단, 학생의 점수를 출력한다. 등록된 학생의 전체 수와 해당 학생의 석차를 같이 출력한다. 동점인 경우 학번으로 내림차순으로 함)
export async function findGrade() {
    return INCLUDE_USER.findOne({where:{id}})
}

// 3. 학생정보를 수정한다. (10점)
export async function updateStudentInfo(id) {
    return Student.update(id).then((data)=>data.datavalues.id)
}


// 4. 학생정보를 삭제한다. 학생정보를 삭제할 경우 점수도 같이 삭제한다. (10점)
export async function deleteStudent() {
    return Student.destroy();
}


// 5. 학번으로 검색한다. (10점) (단, 학생의 점수를 출력한다.)
export async function findById(id) {
    return INCLUDE_USER.findOne({where:{id}})
}


// 6. 학생점수를 등록한다. 점수를 등록할 때 총점, 평균을 계산하여 같이 저장한다. (10점)
export async function registerGrade(user){
    return Grade.create(user)
    .then((data)=>data.datavalues.id)
    .then(totalScore, averageScore)
}


// 7. 학생점수를 수정한다. 점수를 수정할 경우 총점, 평균을 계산하여 같이 저장한다. (10점)
export async function updateGrade(id) {
    return Grade.update(id)
    .then((data)=>data.datavalues.id)
    .then(totalScore, averageScore)
}



// 8. 학생점수를 삭제한다. (10점)
export async function deleteGrade() {
    return Grade.destroy();
}

상대방의 것

data\score.js

import { Score } from '../db/score.js';

// num값으로 특정 학생의 성적을 반환
export async function getByNum(num) {
    return Score.findOne({ where: { num } });
}

// score객체를 받아 새로운 학생성적을 생성해주며 생성 할 경우 해당 성적의 num값을 반환
export async function insert(score){
    return Score.create(score).then((data) => data.dataValues.num);
}

// score객체에 담긴 값으로 특정 학생의 성적을 가져와 oldeScore 객체에 담았으며 oldeScore에 score를 일부 값들로 덮어씌워 저장후 수정된 값을 반환
export async function update(score) {
    return Score.findOne({ where: { num: score.num } }).then((oldScore) => {
        oldScore.java = score.java;
        oldScore.python = score.python;
        oldScore.c = score.c;
        oldScore.total = score.total;
        oldScore.avg = score.avg;
        return oldScore.save();
    });
}

// num으로 특정 학생 성적을 가져와 삭제
export async function remove(num){
    return Score.findOne({ where: { num } }).then((score) => {
        score.destroy();
    });
}

data\student.js

import { Student } from '../db/student.js';
import { Score } from '../db/score.js';
import { Sequelize } from 'sequelize';

// 출력을 해줄 때 student테이블과 score테이블을 join하기 위한 객체
const INCLUDE_STUDENT = {
    attributes: [
        // 평균 점수로 각각 석차를 함께 출력
        [Sequelize.literal(`RANK() OVER (ORDER BY score.avg DESC)`), 'rank'],
        'num',
        'id',
        'name',
        'ph',
        'email',
        'address',
        'regdate',
        // score테이블의 컬럼을 join
        [Sequelize.col('score.java'), 'java'],
        [Sequelize.col('score.python'), 'python'],
        [Sequelize.col('score.c'), 'c'],
        [Sequelize.col('score.total'), 'total'],
        [Sequelize.col('score.avg'), 'avg'],
        [Sequelize.col('score.score_date'), 'score_date']
    ],
    include: {
        // join할 테이블을 설정
        model: Score,
        attributes: []
    }
}

// 평균점수로 내림차순 정렬 하고 만약 평균 점수가 같을 경우 학번으로 내림차순 정렬
const ORDER_DESC = {
    order: [['avg', 'DESC'], ['id', 'DESC']]
}

// student객체를 받아 새로운 학생정보를 생성해주며 생성 할 경우 해당 학생의 num값을 반환
export async function insert(student){
    return Student.create(student).then((data) => data.dataValues.num);
}

// 모든 학생 정보를 위에 선언한 join형태로 반환해주며 정렬
export async function getAll(){
    return Student.findAll({ ...INCLUDE_STUDENT, ...ORDER_DESC});
}

// 학번으로 검색한 학생의 정보를 위에 선언한 join형태로 반환
export async function getById(id){
    return Student.findOne({
        where: { id },
        ...INCLUDE_STUDENT
    });
}

// pk값인 num으로 검색한 학생정보를 반환
export async function getByNum(num){
    return Student.findByPk(num);
}

// student객체에 담긴 값으로 특정 학생의 정보를 가져와 oldeStudent 객체에 담았으며 oldstudent에 student를 일부 값들로 덮어씌워 저장후 수정된 값을 반환
export async function update(student){
    return Student.findByPk(student.num).then((oldStudent) => {
        oldStudent.name = student.name;
        oldStudent.ph = student.ph;
        oldStudent.email = student.email;
        oldStudent.address = student.address;
        return oldStudent.save();
    });
}

// num으로 특정 학생 정보를 가져와 삭제
export async function remove(num){
    return Student.findByPk(num).then((student) => {
        student.destroy();
    });
}

1번 문제

학생을 등록한다. (10점)

 

나의 것


data\student.js

export async function registerStudent(user){
    return Student.create(user).then((data)=>data.datavalues.id);
}

controller\student.js

export async function register(req, res, next){
    const id = req.body.id;
    const data = await tweetRepository.registerStudent(id);
    res.status(201).json(data);
}


router\student.js
router.post('/', isAuth, tweetController.register);

상대방의 것


data\student.js

// 학번으로 검색한 학생의 정보를 위에 선언한 join형태로 반환
export async function getById(id){
    return Student.findOne({
        where: { id },
        ...INCLUDE_STUDENT
    });
}

controller\student.js

// 학생 정보 생성 메소드
export async function create(req, res) {
    // body에 존재하는 id, name, ph, email, address를 선언
    const { id, name, ph, email, address } = req.body;
    // getById로 학번 검색을 하여 결과값을 found에 선언
    const found = await studentRepository.getById(id);
    // found에 값이 담길 경우 이미 존재하는 학번이라고 알리며 409 에러페이지 발생
    if(found){
        return res.status(409).json({ message: `${id}학번 학생은 이미 존재합니다.` });
    }
    // 위에 검사를 무사히 통과 할 경우 값들을 객체로 만들어 insert를 실행
    await studentRepository.insert({
        id,
        name,
        ph,
        email,
        address
    });
    // 성공시에 201페이지를 출력
    res.status(201).json({ message: `${name} 학생이 등록 되었습니다.` });
}

router\student.js
// 학생 등록
// POST: http://localhost:8080/student/
/*
JSON
{
    "id": 학번,
    "name": 이름,
    "ph": 연락처,
    "email": 이메일,
    "address": 주소
}
*/
router.post('/', validateCreateStudent, studentController.create);

2번 문제

학생의 등록된 정보를 성적(평균)으로 내림차순으로 출력한다. (10점)
(단, 학생의 점수를 출력한다. 등록된 학생의 전체 수와 해당 학생의 석차를 같이 출력한다. 동점인 경우 학번으로 내림차순으로 함)

 

나의 것


data\student.js

export async function findGrade() {
    return INCLUDE_USER.findOne({where:{id}})
}

controller\student.js

export async function showGrade(req, res, next){
    const id = req.params.id;
    const data = await tweetRepository.findGrade(id);
        if(data){
            res.status(200).json(data);
        }else{
            res.status(404).json({message: `id (${id}) not found` })
        }
}


router\student.js
router.get('/student', isAuth, tweetController.showGrade);

상대방의 것


data\student.js

// 학번으로 검색한 학생의 정보를 위에 선언한 join형태로 반환
export async function getById(id){
    return Student.findOne({
        where: { id },
        ...INCLUDE_STUDENT
    });
}

controller\student.js

// 학생 정보 생성 메소드
export async function create(req, res) {
    // body에 존재하는 id, name, ph, email, address를 선언
    const { id, name, ph, email, address } = req.body;
    // getById로 학번 검색을 하여 결과값을 found에 선언
    const found = await studentRepository.getById(id);
    // found에 값이 담길 경우 이미 존재하는 학번이라고 알리며 409 에러페이지 발생
    if(found){
        return res.status(409).json({ message: `${id}학번 학생은 이미 존재합니다.` });
    }
    // 위에 검사를 무사히 통과 할 경우 값들을 객체로 만들어 insert를 실행
    await studentRepository.insert({
        id,
        name,
        ph,
        email,
        address
    });
    // 성공시에 201페이지를 출력
    res.status(201).json({ message: `${name} 학생이 등록 되었습니다.` });
}

router\student.js
// 학생 등록
// POST: http://localhost:8080/student/
/*
JSON
{
    "id": 학번,
    "name": 이름,
    "ph": 연락처,
    "email": 이메일,
    "address": 주소
}
*/
router.post('/', validateCreateStudent, studentController.create);

3번 문제

학생정보를 수정한다. (10점)

 

나의 것


data\student.js

export async function updateStudentInfo(id) {
    return Student.update(id).then((data)=>data.datavalues.id)
}

controller\student.js

export async function update(req, res, next){
    const id = req.params.id;
    const text = req.body.text;
    const data = await tweetRepository.updateStudentInfo(id); 
    if(!data){
        res.status(404).json({message: `id (${id}) not found` })
    }
    if(data.userId !== req.userId){
        return res.sendStatus(403);  
    }
    const updated = await tweetRepository.update(id, text);
    res.status(200).json(updated); 
}


router\student.js
router.put('/student:id', isAuth, tweetController.update);

상대방의 것


data\student.js

// student객체에 담긴 값으로 특정 학생의 정보를 가져와 oldeStudent 객체에 담았으며 oldstudent에 student를 일부 값들로 덮어씌워 저장후 수정된 값을 반환
export async function update(student){
    return Student.findByPk(student.num).then((oldStudent) => {
        oldStudent.name = student.name;
        oldStudent.ph = student.ph;
        oldStudent.email = student.email;
        oldStudent.address = student.address;
        return oldStudent.save();
    });
}


controller\student.js

export async function modify(req, res) {
    // params에 담겨있는 id를 가져와 num으로 선언
    const num = req.params.id;
    // body에 존재하는 name, ph, email, address를 선언
    const { name, ph, email, address } = req.body;
    // getByNum으로 학생 정보를 가져와 student에 선언
    const student = await studentRepository.getByNum(num);
    
    // student에 값이 담기지 않을 경우 404에러페이지를 출력
    if(!student){
        res.status(404).json({ message: '학생 num을 확인해주세요' });
    }
    // student에 값이 담길경우 값들을 객체로 만들어 update를 실행
    else{
        const updated = await studentRepository.update({
            num,
            name,
            ph,
            email,
            address
        });
        // 성공시에 200페이지에 수정된 값들을 출력
        res.status(200).json(updated);
    }
}


router\student.js
// 학생 수정
// PUT: http://localhost:8080/student/num값
/*
{
    "name": 이름,
    "ph": 연락처,
    "email": 이메일,
    "address": 주소
}
*/
router.put('/:id', validateUpdateStudent, studentController.modify);


 

4번 문제

학생정보를 삭제한다. 학생정보를 삭제할 경우 점수도 같이 삭제한다. (10점)

 

나의 것


data\student.js

export async function deleteStudent() {
    return Student.destroy();
}


controller\student.js

export async function deleted(req,res,next){
    const id = req.params.id;
    const data = await tweetRepository.deleteStudent(id); 
    if(!data){
        res.status(404).json({message: `id (${id}) not found` })
    }
    if(data.userId !== req.userId){
        return res.sendStatus(403);  
    }
    await tweetRepository.remove(id);
    res.sendStatus(204);
}

router\student.js
router.delete('/student:id', isAuth, tweetController.deleted);

상대방의 것


data\student.js

// num으로 특정 학생 정보를 가져와 삭제
export async function remove(num){
    return Student.findByPk(num).then((student) => {
        student.destroy();
    });
}

controller\student.js

// 학생 정보 삭제 메소드
export async function drop(req, res) {
    // params에 담겨있는 id를 가져와 num으로 선언
    const num = req.params.id;
    // studentRepository에 getByNum으로 학생 정보를 가져와 student에 선언
    const student = await studentRepository.getByNum(num);
    // scoreRepository에 getByNum으로 학생 성적을 가져와 score에 선언
    const score = await scoreRepository.getByNum(num);

    // student에 값이 담기지 않을 경우 404에러페이지를 출력
    if(!student){
        res.status(404).json({ message: '학생 num을 확인해주세요' });
    }   
    else{
        // score에 값이 담길 경우 학생의 성적이 존재하는 것이므로 성적을 먼저 삭제
        if(score){
            await scoreRepository.remove(num);
        }
        // 이후 학생 정보를 삭제 후 204페이지 출력
        await studentRepository.remove(num);
        res.sendStatus(204);
    }
}

router\student.js
// 학생 삭제
// DELETE: http://localhost:8080/student/num값
router.delete('/:id', studentController.drop);

 

5번 문제

학번으로 검색한다. (10점) (단, 학생의 점수를 출력한다.)

 

나의 것


data\student.js

export async function findById(id) {
    return INCLUDE_USER.findOne({where:{id}})
}

controller\student.js

export async function showByStudentNum(req, res, next){
    const id = req.params.id;
    const data = await tweetRepository.findById(id);
        if(data){
            res.status(200).json(data);
        }else{
            res.status(404).json({message: `id (${id}) not found` })
        }
}



router\student.js
router.get('/student', isAuth, tweetController.showByStudentNum);

상대방의 것


data\student.js

// 학번으로 검색한 학생의 정보를 위에 선언한 join형태로 반환
export async function getById(id){
    return Student.findOne({
        where: { id },
        ...INCLUDE_STUDENT
    });
}

controller\student.js

// 학생 검색 메소드
export async function showOne(req, res) {
    // params에 담겨있는 id를 가져와 id로 선언
    const id = req.params.id;
    // getById로 학번 검색을 하여 반환값을 data에 선언
    const data = await studentRepository.getById(id);

    // data에 값이 담길 경우에 200페이지에 학생 정보를 담은 data를 출력
    if(data){
        res.status(200).json(data);
    }
    // data에 값이 안담길 경우에는 해당 학번이 없는 것이므로 404에러 페이지를 출력
    else{
        res.status(404).json({ message: `${id}학번은 존재하지 않습니다.` })
    }
}

router\student.js
// 학번으로 학생 조회
// GET: http://localhost:8080/student/학번(id)
router.get('/:id', studentController.showOne);

 

6번 문제

학생점수를 등록한다. 점수를 등록할 때 총점, 평균을 계산하여 같이 저장한다. (10점)

 

나의 것


data\student.js

export async function registerGrade(user){
    return Grade.create(user)
    .then((data)=>data.datavalues.id)
    .then(totalScore, averageScore)
}


controller\student.js

export async function registerGrade(req, res, next){
    const {text} = req.body;
    const data = await tweetRepository.registerStudentGrades(text, req.userId);
    res.status(201).json(data);
}


router\student.js
router.post('/student', isAuth, tweetController.registerGrade);

상대방의 것


data\score.js

// score객체를 받아 새로운 학생성적을 생성해주며 생성 할 경우 해당 성적의 num값을 반환
export async function insert(score){
    return Score.create(score)
}

controller\score.js

// 학생 성적 생성 메소드
export async function create(req, res) {
    // body에 존재하는 num, java, python, c를 선언
    const { num, java, python, c } = req.body;
    // scoreRepository에 getByNum으로 학생 성적을 가져와 foundScore에 선언
    const foundScore = await scoreRepository.getByNum(num);
    // studentRepository getByNum으로 학생 정보를 가져와 foundStudent 선언
    const foundStudent = await studentRepository.getByNum(num);

    // 학생 성적이 담길 경우 이미 존재하는 것이므로 409에러페이지 출력
    if(foundScore){
        return res.status(409).json({ message: `이미 성적이 등록 되어있습니다.` });
    }

    // 학생 정보가 담기지 않을 경우 409에러페이지를 출력
    if(!foundStudent){
        return res.status(409).json({ message: `없는 학생입니다.` });
    }

    // 위 조건을 모두 통과할 경우 값들을 객체로 만들어 insert를 실행
    const i = await scoreRepository.insert({
        num,
        java,
        python,
        c,
        total: java + python + c,
        avg: (java + python + c) / 3
    });
    console.log(i);

    // 성공시 201페이지를 출력
    res.status(201).json({ message: `성적이 등록 되었습니다.` });
}

router\score.js
// 점수 등록
// POST: http://localhost:8080/score/
/*
{
    "num": 학생num,
    "java": java점수,
    "python": python점수,
    "c": c언어 점수
}
*/
router.post('/', validateCreateScore, scoreController.create);

 

7번 문제

학생점수를 수정한다. 점수를 수정할 경우 총점, 평균을 계산하여 같이 저장한다. (10점)

 

나의 것


data\student.js

export async function updateGrade(id) {
    return Grade.update(id)
    .then((data)=>data.datavalues.id)
    .then(totalScore, averageScore)
}

controller\student.js

export async function updateGrade(req, res, next){
    const id = req.params.id;
    const text = req.body.text;
    const data = await tweetRepository.updateStudentGrades(id); 
    if(!data){
        res.status(404).json({message: ` id (${id}) not found` })
    }
    if(data.userId !== req.userId){
        return res.sendStatus(403);  
    }
    const updated = await tweetRepository.update(id, text);
    res.status(200).json(updated); 
}


router\student.js
router.put('/student:id', isAuth, tweetController.updateGrade);

상대방의 것


data\score.js

// score객체에 담긴 값으로 특정 학생의 성적을 가져와 oldeScore 객체에 담았으며 oldeScore에 score를 일부 값들로 덮어씌워 저장후 수정된 값을 반환
export async function update(score) {
    return Score.findOne({ where: { num: score.num } }).then((oldScore) => {
        oldScore.java = score.java;
        oldScore.python = score.python;
        oldScore.c = score.c;
        oldScore.total = score.total;
        oldScore.avg = score.avg;
        return oldScore.save();
    });
}

controller\score.js

// 학생 성적 수정 메소드
export async function modify(req, res) {
    // params에 담겨있는 id를 가져와 num으로 선언
    const num = req.params.id;
    // body에 존재하는 java, python, c를 선언
    const { java, python, c } = req.body;
    // getByNum으로 학생 성적을 가져와 score에 선언
    const score = await scoreRepository.getByNum(num);

    // score에 값이 담기지 않을 경우 404에러페이지를 출력
    if(!score){
        res.status(404).json({ message: '학생 num을 확인해주세요' });
    }
    // score에 값이 담길경우 값들을 객체로 만들어 update를 실행
    else{
        const updated = await scoreRepository.update({
            num,
            java,
            python,
            c,
            total: java + python + c,
            avg: (java + python + c) / 3
        });
        // 성공시에 200페이지에 수정된 값들을 출력
        res.status(200).json(updated);
    }
}


router\score.js
// 점수 수정
// PUT: http://localhost:8080/score/num값
/*
{
    "java": java점수,
    "python": python점수,
    "c": c언어 점수
}
*/
router.put('/:id', scoreController.modify);

 

8번 문제

학생점수를 삭제한다. (10점)

 

나의 것


data\student.js

export async function deleteGrade() {
    return Grade.destroy();
}

controller\student.js

export async function deleteGrade(req,res,next){
    const id = req.params.id;
    const data = await tweetRepository.deleteStudentGrades(id); 
    if(!data){
        res.status(404).json({message: `id (${id}) not found` })
    }
    if(data.userId !== req.userId){
        return res.sendStatus(403); 
    }
    await tweetRepository.remove(id);
    res.sendStatus(204);
}

router\student.js
router.delete('/student:id', isAuth, tweetController.deleteGrade);

상대방의 것


data\score.js

// num으로 특정 학생 성적을 가져와 삭제
export async function remove(num){
    return Score.findOne({ where: { num } }).then((score) => {
        score.destroy();
    });
}

controller\score.js

// 학생 성적 삭제 메소드
export async function drop(req, res) {
    // params에 담겨있는 id를 가져와 num으로 선언
    const num = req.params.id;
    // getByNum으로 학생 성적을 가져와 score에 선언
    const score = await scoreRepository.getByNum(num);

    // score에 값이 담기지 않을 경우 404에러페이지를 출력
    if(!score){
        res.status(404).json({ message: '학생 num을 확인해주세요' });
    }
    // score에 값이 담길 경우 학생의 성적이 존재하는 것이므로 삭제
    else{
        await scoreRepository.remove(num);
        res.sendStatus(204);
    }
}

router\score.js
// 점수 삭제
// DELETE: http://localhost:8080/score/num값
router.delete('/:id', scoreController.drop);

// router 객체를 export
export default router;