총 4개의 테이블 추가
테이블간 연결은 정적 테이블간 연결되는게 아니다!
정적인 테이블끼리 연결하게 되면 차후에 테이블간 관계를 변경하거나 끊어내기 어려워지기 때문에 정적인 테이블간의 관계는 동적인(Action)테이블로 연결해준다
예를 들어 상품 주문시에는 동적 테이블인 판매 테이블의 데이터가 변화하며,
이때 동적 테이블인 판매 테이블의 데이터만 바뀌고 정적 테이블인 물품 테이블이나 커뮤니티 테이블의 변화는 없다
sell(판매) 테이블에 판매유무값 (key: chk)를 추가하여
판매중 = 1, 판매중지 = 0 으로 값을 설정한다.
✔️등록되어있는 데이터를 삭제하는 경우 데이터를 완전히 없애버리는게 아니라 여러테이블과의 관계, 거래기록을 추후에 확인할 수 있도록 판매유무값의 key만 바꿔서 판매중지 상태로 전환해두어야 한다
📃 Question
Data A라는 데이터를 DB에 등록한 후 삭제하였다
이후에 같은내용의 Data A를 등록했다면?
✏️ 먼저 등록한 Data A와 나중에 등록된 Data A는 같은 DB값이 아니다
이후에 등록된 DataA는 DB에 새로운 데이터가 하나 더 추가되었다고 생각하면 된다
💡 내용이 같다고 데이터도 같은게 아니다 !
DB에서는 이후 입력된 Data A를 앞전에 존재했던 Data A와 아예 다른데이터로 인식한다
📃 item 하위테이블인 itemimage에 이미지가 등록되어 있는경우, item 테이블은 삭제가 불가능 할 수도 있다
테이블 A의 하위 테이블에 데이터가 등록된 경우
1. 하위테이블의 데이터가 삭제된 후
2. 테이블 A의 삭제가 진행되어야 한다
model은 DB와 language간에 제약없이 데이터를 이동하기 위해 사용하며, 데이터를 더욱 구조적으로 저장하기 위해 변수를 지정해주는 역할을 한다
위처럼 model을 중심으로 데이터와 프로그램이 매칭되어 있는 상황에서
다양한 데이터와 다양한 프로그램(Spring, Java, C#등..)이 존재한다.
데이터와 프로그램의 중심에 위치한 model은 어떤 프로그램을 사용하던 데이터를 같은형태로 유지시켜 꺼내주는 중간자 역할을 한다
model을 잘 만들기 위해서는 설계도면(ERD)을 잘 설계되어 있어야 하며, java를 포함한 일부 언어들은 설계도면(ERD) 설계시 모델이 자동으로 생성되기도 한다
ex_categorymodel, ex_itemmodel, ex_itemimagemodel 생성 후
📁routes/
1. ex_category.js
2. ex_item.js
3. ex_itemimage.js 의 순서로 생성한다
1-2-3 의 순서로 생성하는 이유는
➡️ ex_item테이블에서 물품 생성시 categorycode키가 외래키(FK)로 참조되는데, 이때 categorycode키는 N-N(Not Null)이기 때문에 ex_category가 먼저 생성이 되어야 ex_item을 만들 수 있기 때문이다.
ex_item.js, ex_category.js, ex_itemimage.js 생성 후
📁app.js에 등록해준다.
📁routes /ex_category 파일 생성시
자동생성목록(Sequence) =>_id 는 제외한다
➡️기본키 _id를 직접 지정할것이기 때문!(AAA, BBB, CCC)
💡물품조회는 post 로 한다!
get을 보내면 주소에 '&'을 계속 붙이기때문에 배열로 해주는게 좋다
get으로 100개, 10000개를 url로 보낼 수는 없으니까..
판매에 등록된 물품만 가져오고 {"arr":[1001, 1002, 1003]}
배열로 전송된 물품번호 중 해당하는것 물품만 조회할것!
📁routes/ex_sell.js 생성
router.post('/insert.json', ex_auth.checkToken, async function(req, res, next) {
try {
const email = req.body.TID; //토큰에서 이메일 정보 추출
const communityno = Number(req.body.communityno);
const itemno = Number(req.body.itemno);
// 이메일이 커뮤니티에 가입된 회원인지 확인
const query = { memberid : email, communityno : communityno };
const result = await Register.findOne(query).select({_id:1})
if(result !== null) {
// 위에서 커뮤니티 가입한 회원이 인증이 되어야 판매등록 가능
const obj = new Sell();
obj.communityno = communityno;
obj.itemno = itemno ;
const result1 = await obj.save();
if(result1 !== null){
return res.send({status:200, result : result1});
}
}
return res.send({status:0}) // 커뮤니티에 가입된 회원이 아님!
}
catch(e) {
console.error(e);
return res.send({status:-1, result:e});
}
});
회원정보와 판매를 이어주는게 아니라
커뮤니티에 등록된(가입한)사용자만 판매등록이 가능하게 해야한다!
💡 community 테이블은 register에서 회원정보를 불러올 수 있다
커뮤니티에 가입된 회원의 정보는
➡️ register 테이블을 통해 member 테이블에서 알 수 있다
즉, register에서 memberid와 community가 일치하는 정보를 찾아온다.
community 테이블에서 회원정보 가져오는게 아니다!
router.delete('/delete.json', ex_auth.checkToken, async function(req, res, next) {
try {
const email = req.body.TID; //토큰에서 이메일 정보 추출
const communityno = Number(req.body.communityno);
// 이메일이 커뮤니티에 가입된 회원인지 확인
const query = { memberid : email, communityno : communityno };
const result = await Register.findOne(query).select({_id:1})
if(result !== null) {
// 위에 인증이 다 되어야 여기서 삭제수행
// 지우는게 아니라 chk의 키 값을 1(판매중=기본값) => 0(판매중지)을 바꾸기!
const query = {_id : Number(req.body._id)}
const obj = await Sell.findOne(query);
obj.chk = 0;
const result1 = await obj.save();
if(result1 !== null){
return res.send({status:200, result:result1});
}
}
return res.send({status:0}) // 커뮤니티에 가입된 회원이 아님!
}
catch(e) {
console.error(e);
return res.send({status:-1, result:e});
}
});
토큰과 함께 body로
{"communityno" : 커뮤니티번호, "_id"(sell에 들어갔던) : 판매번호} 를 보내준다 (아이템번호는 필요하지 않음)
데이터를 지우는게 아니라 chk값을 1 (판매중) ➡️ 0 (판매중지)으로 바꿔준다
🧑💻 실습 해보기
router.post('/sellupdate.json', ex_auth.checkToken, async function(req, res, next) {
try {
const email = req.body.TID; //토큰에서 이메일 정보 추출
const communityno = Number(req.body.communityno);
// 이메일이 커뮤니티에 가입된 회원인지 확인
const query = { memberid : email, communityno : communityno };
const result = await Register.findOne(query).select({_id:1})
if(result !== null) {
// 위에 인증이 다 되어야 여기서 삭제수행
// chk의 키 값을 0(판매중지) => 1(판매중=기본값)을 바꾸기!
const query = {_id : Number(req.body._id)}
const obj = await Sell.findOne(query);
obj.chk = 1;
const result1 = await obj.save();
if(result1 !== null){
return res.send({status:200, result:result1});
}
}
return res.send({status:0}) // 커뮤니티에 가입된 회원이 아님!
}
catch(e) {
console.error(e);
return res.send({status:-1, result:e});
}
});
📁 components/MyPage.vue
커뮤니티 개설하기 페이지 ➡️ '회원목록', '물품관리' 버튼생성
<v-window-item value="five">
<v-btn flat color="secondary" @click="dialog=true">
커뮤니티 개설하기
</v-btn>
<v-table>
<thead>
<tr>
<th class="text-left">
번호
</th>
<th class="text-left">
제목
</th>
<th class="text-left">
내용
</th>
<th class="text-left">
등록일
</th>
<th class="text-left">
버튼
</th>
</tr>
</thead>
<tbody>
<tr v-for="tmp of state.rows" :key="tmp">
<td >{{tmp._id}}</td>
<td>{{tmp.name}}</td>
<td>{{tmp.content}}</td>
<td>{{tmp.regdate}}</td>
<td>
<v-btn style="cursor:pointer"
@click="handleCommunityMember(tmp._id)">회원목록</v-btn>
<v-btn @click="handleCommunityItem(tmp._id)">물품관리</v-btn>
</td>
</tr>
</tbody>
</v-table>
<div class="text-center">
<v-pagination
v-model="state.pages"
:length="state.page"
@click="handlePage"
></v-pagination>
</div>
</v-window-item>
📁components/itemCommunityPage.vue 생성
routes > index.js 등록
<template>
<div class="box">
{{state}}
<!-- {{state.cate}} -->
<div>
<h3>판매등록 페이지</h3>
물품명 : <input type="text" style="border: 1px solid #cccccc" v-model="state.name" /><br/>
내용 : <input type="text" style="border: 1px solid #cccccc" v-model="state.content" /><br/>
가격 : <input type="text" style="border: 1px solid #cccccc" v-model="state.price" /><br/>
수량 : <input type="text" style="border: 1px solid #cccccc" v-model="state.quantity" /><br/>
분류 :
<!-- DB에 저장된 카테고리 목록이 나와야한다! -->
<select style="border: 1px solid #cccccc" v-model="state.cate">
<option v-for="tmp of state.category" :key="tmp" :value="tmp._id">{{tmp.name}}</option>
</select><br/>
<button style="border: 1px solid #cccccc" @click="handleInsert">판매등록</button>
<hr />
</div>
<div>
<h3>판매물품목록</h3>
<table>
<tr>
</tr>
</table>
</div>
</div>
</template>
:value="_id" => v-model로 보내는 값
v-model => v-model에 걸어야 변경된 값을 가져갈 수 있다
💡 {{state}} 대신 watch 사용하면 변화를 감지할떄마다 콘솔창에 찍어준다!
watch(state, ()=> {
console.log('watch =>',state)
});
import { useRoute } from 'vue-router';
export default {
setup () {
const route = useRoute();
//생략//
const state = reactive({
code: Number(route.query.code),