
-SimpleCartList.vue
// TODO: 주문페이지 이동 함수
goOrder() {
this.$router.push("/simple-order");
}
-SimpleOrderList.vue
-> 디자인

<template>
<div>
<!-- {/* dname start */} -->
<div class="row mb-5 justify-content-center">
<!-- {/* w-50 : 크기 조정, mx-auto : 중앙정렬(margin: 0 auto), justify-content-center */} -->
<div class="col-12 w-50 input-group mb-3">
<input
type="text"
class="form-control"
placeholder="Search by Title"
/>
<div class="input-group-append">
<button
class="btn btn-outline-secondary"
type="button"
>
Search
</button>
</div>
</div>
</div>
<!-- {/* dname end */} -->
<!-- {/* paging 시작 */} -->
<div class="mb-3">
Items per Page:
<select >
<option>
</option>
</select>
</div>
<b-pagination
v-model="page"
:total-rows="count"
:per-page="pageSize"
></b-pagination>
<!-- {/* paging 끝 */} -->
<div class="row">
<div >
<div class="row g-0 p-3">
<div class="col-md-4 p-3 border">
<img
class="img-fluid rounded-start"
alt="..."
style="{ height: 15 + 'vh', width: 5 + 'vw' }"
/>
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">물품 : </h5>
<h5 class="card-title">
가격 :
</h5>
<h5 class="card-title">개수 : </h5>
</div>
</div>
</div>
</div>
</div>
<!-- {/* 배송지 시작 */} -->
<div class="col-12 mx-auto">
<div class="row g-3 align-items-center mb-3">
<div class="col-3">
<label htmlFor="deliveryAddr" class="col-form-label">
Delivery Address
</label>
</div>
<div class="col-9">
<input
type="text"
id="deliveryAddr"
required
class="form-control"
placeholder="deliveryAddr"
name="deliveryAddr"
/>
</div>
</div>
<div class="row g-3 align-items-center mb-3">
<div class="col-3">
<label htmlFor="deliveryMsg" class="col-form-label">
Melivery Message
</label>
</div>
<div class="col-9">
<input
type="text"
id="deliveryMsg"
required
class="form-control"
placeholder="deliveryMsg"
name="deliveryMsg"
/>
</div>
</div>
</div>
<!-- {/* 배송지 끝 */} {/* 버튼 시작 */} -->
<div class="row d-flex justify-content-end">
<!-- {/* 취소 버튼 시작 */} -->
<button
type="button"
class="btn btn-danger w-25 me-3"
>
Cancel Order
</button>
<!-- {/* 취소 버튼 끝 */} {/* 결재 버튼 시작 */} -->
<button type="button" class="btn btn-warning w-25">
Go Approval
</button>
<!-- {/* 결재 버튼 끝 */} -->
</div>
<!-- {/* 버튼 끝 */} -->
</div>
</template>
-> 데이터바인딩 속성 정의
<script>
export default {
// TODO: 데이터 바인딩 속성 정의
data() {
return {
simpleCart: [], // 장바구니 객체배열
searchTitle: "", // 검색어
// 배송 입력 속성 정의
deliveryAmount: 3000, // 기본 : 3000, 배송비
deliveryAddr: "", // 배송지 주소
deleveryMsg: "", // 배송 메세지
// 공통 페이징 속성
page: 1, // 현재페이지번호
count: 0, // 전체 데이터개수
pageSize: 3, // 화면에 보여질 개수
pageSizes: [3, 6, 9], // 화면에 보여질 개수배열
};
},
}
</script>
-> 함수정의
// TODO: 함수 정의
methods: {
// TODO: 장바구니 전체 조회 : 화면 뜰때 실행
async retrieveSimpleCart() {
try {
// TODO: 공통 장바구니 전체 조회 서비스 함수 실행
// TODO: 비동기 코딩 : async ~ await
let response = await SimpleCartService.getAll(
this.searchTitle,
this.page - 1,
this.pageSize
);
const { simpleCart, totalItems } = response.data;
this.simpleCart = simpleCart;
this.count = totalItems;
// 로깅
console.log(response.data); // 웹브라우저 콘솔탭에 벡엔드 데이터 표시
} catch (e) {
console.log(e); // 웹브라우저 콘솔탭에 에러 표시
}
},
// TODO: 주문 함수 : 1) 주문 테이블 + 주문상세 테이블 insert
// TODO: 2) 결재 페이지로 이동
goApproval() {},
// TODO: 주문 취소 : 장바구니 전체 페이지로 다시 이동
cancelOrder() {},
// TODO: 공통 페이징 함수 : select 태그
pageSizeChange() {
this.page = 1; // 현재페이지번호 : 1
this.retrieveSimpleCart(); // 재조회
},
},
// TODO: 화면이 뜰때 장바구니 전체 조회
mounted() {
this.retrieveSimpleCart();
},
};
-> 주문함수
1) 주문 테이블 + 주문상세 테이블 insert
2) 결재 페이지로 이동
◈ js 날짜 객체
// 날짜 포맷 : yyyy-mm-dd hh:mi:ss 형태
// 년도 : now.getFullYear()
// 월 : now.getMonth()
// 일 : now.getDate()
// 시 : now.getHours()
// 분 : now.getMinutes()
// 초 : now.getSeconds()
① 주문날짜 : 현재날짜
let now = new Date(); // js 날짜 객체
let formatNow = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
② 장바구니의 상품별 금액 = 단가(unitPrice) * 개수(cartCount)
모든 상품별 총금액
모든 상품별 총금액
-배열변수에 사용하는 함수 : map, foreach, filter 등 + reduce
★ reduce => 매개변수의 값을 계속 누적시켜 합또는 차를 구할수 있는 함수
-누적합 알고리즘 : 누적변수 = 누적변수 + 배열값
★ 사용법 : reduce((누적변수, 배열값) => 누적변수 + 배열값);
let totalPrice = this.simpleCart
.map((data)=> data.unitPrice * data.cartCount) // 상품별 금액 배열
// 사용법 : reduce((누적변수, 배열값) => 누적변수 + 배열값);
.reduce((acc, cur) => acc + cur); // 총금액
},
③ 주문상세 객체 정의 => 배열이 되어야함
--------> 정리하기
--> 백엔드
@Entity
@Table(name = "TB_SIMPLE_ORDER")
@SequenceGenerator(
name = "SQ_SIMPLE_ORDER_GENERATOR"
, sequenceName = "SQ_SIMPLE_ORDER"
, initialValue = 1
, allocationSize = 1
)
@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DynamicInsert
@DynamicUpdate
// soft delete
@Where(clause = "DELETE_YN = 'N'")
@SQLDelete(sql = "UPDATE TB_SIMPLE_ORDER SET DELETE_YN = 'Y', DELETE_TIME=TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') WHERE SONO = ?")
public class SimpleOrder extends BaseTimeEntity2 {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE
, generator = "SQ_SIMPLE_ORDER_GENERATOR"
)
private Integer sono; // 주문번호, 기본키, 시퀀스
private String orderDate; // 주문일자
private String orderStatus; // 주문상태(50001: 주문완료, 50002: 결재완료, 50011: 결재취소)
private Integer productAmount; // 총 상품금액
private Integer deliveryAmount; // 배송비
private Integer orderAmount; // 주문금액 = 총 상품금액 + 배송비
private String deliveryAddr; // 배송지 주소
private String deliveryMsg; // 배송지 메모
}
@Entity
@Table(name = "TB_SIMPLE_ORDER_DETAIL")
@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
@DynamicInsert
@DynamicUpdate
// 복합키 사용클래스 정의
@IdClass(SonoSpnoPk.class)
public class SimpleOrderDetail {
@Id
private Integer sono; // 주문번호(PK:복합키), FK
@Id
private Integer spno; // 상품번호(pk2:복합키), fk
private Integer productCount; // 상품수량
}
복합키 정의 : 컬럼 2개이상을 묶어서 기본키로 사용하는 것
기본키는 유일성을 보장해야하므로 복합키 또한 유일성을 보장해야함
예) 주문상세 : 주문번호 + 상품번호 => 유일성 보장
샤프(2) => 2개 컬럼 합치면 유일성 보장됨(복합키)
1 연필(3)
2 샤프(2)
2 지우개(4)
~> DB 사용법 : primary key(컬럼명, 컬럼명2)
2) 자바에서 복합키 사용법 :
2-1) 복합키로 사용할 클래스의 속성(필드)들에 @Id 붙임
2-2) 그 속성명(필드)으로 복합키 정의 클래스를 만듬
2-3) 복합키를 사용하는 클래스 위에 @IdClass(복합키 정의 클래스.class) 추가
=> 사용법 : @IdClass(복합키클래스.class)
public class 클래스명{
@Id
private 자료형 복합키속성1;
@Id
private 자료형 복합키속성2;
}
=> 복합키 클래스 정의 사용법 : 롬북 6개 어노테이션 사용
public class 복합키클래스 implements Serializable {
private 자료형 복합키속성1;
private 자료형 복합키속성2;
}
@Repository
public interface SimpleOrderRepository extends JpaRepository<SimpleOrder, Integer> {
}
@Repository
public interface SimpleOrderDetailRepository extends JpaRepository<SimpleOrderDetail, SonoSpnoPk> {
}
@Setter
@Getter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class SimpleOrderDto {
private Integer sono; // 기본키, 시퀀스
private List<SimpleOrderDetail> simpleOrderDetailList; // 주문상세 객체배열
private String orderDate; // 주문날짜
private Integer orderStatus; // 주문상태(50001: 주문완료, 50002: 결재완료, 50011:결재취소)
private Integer productAmount; // 상품 총금액
private Integer deliveryAmount; // 배달비(3000 : 하드코딩)
private Integer orderAmount; // 주문금액 = 총금액 + 배달비
private String deliveryAddr; // 배달 주소
private String deliveryMsg; // 배달 메세지
}
1) DTO -> Entity 변환
▶ 사용법 : modelMapper.map(DTO클래스, 엔티티명.class);
@Service
public class SimpleOrderService {
@Autowired
SimpleOrderRepository simpleOrderRepository; // DI
@Autowired
SimpleOrderDetailRepository simpleOrderDetailRepository; // DI
// DTO 변환 패키지
ModelMapper modelMapper = new ModelMapper();
// TODO: 저장함수 : 주문 테이블 insert + 주문상세(배열) insert(반복문)
// => 주문 객체 DTO 정의 : (주문상세 객체배열(List), 주문상태 등)
@Transactional
public SimpleOrder insert(SimpleOrderDto simpleOrderDto) {
// 1) insert 할때는 DTO -> Entity 변환해서 insert
// => DTO -> Entity : 1) 직접 변환로직 코딩 : 숙련자에게 추천
// 2) 자동 변환 패키지 : 초보자 추천
// (ModelMapper 패키지 => 단점 : 성능저하)
// TODO: 1) DTO -> Entity 변환
// 사용법 : modelMapper.map(DTO클래스, 엔티티명.class);
SimpleOrder simpleOrder
= modelMapper.map(simpleOrderDto, SimpleOrder.class);
// TODO: 2) 부모테이블 저장 (부모저장 -> 자식저장)
SimpleOrder simpleOrder2
= simpleOrderRepository.save(simpleOrder); // 부모 테이블 저장
// TODO: 3) 자식테이블도 저장 : 주문상세 테이블 (반복문)
// DB 트랜잭션(transaction, 거래) :
// 1) CUD 작업에 대해 여러개가 있을경우 중간에 에러가 발생하면 모두 롤백함
// 2) 위의 있는 기능을 사용하려면 : @Transactional 함수위에 붙임
for (int i = 0; i < simpleOrderDto.getSimpleOrderDetailList().size(); i++) {
// 자식테이블(SimpleOrderDetail) insert : 기본키(부모쪽 insert 할때 시퀀스로 생성되어 있음)
// 생성된 주문번호 -> 주문상세객체에 저장
SimpleOrderDetail tmpSimpleOrderDetail = simpleOrderDto.getSimpleOrderDetailList().get(i);
tmpSimpleOrderDetail.setSono(simpleOrder2.getSono());
// DB 저장
simpleOrderDetailRepository.save(tmpSimpleOrderDetail);
}
return simpleOrder2; // 저장된 주문 객체
}
}
@Slf4j
@RestController
@RequestMapping("/api/shop")
public class SimpleOrderController {
@Autowired
SimpleOrderService simpleOrderService; // DI
// TODO: 저장 함수
@PostMapping("/simple-order")
// 저장(insert) -> post 방식 -> @PostMapping
public ResponseEntity<Object> create(
@RequestBody SimpleOrderDto simpleOrderDto
) {
try {
// 저장 서비스 실행
SimpleOrder simpleOrder = simpleOrderService.insert(simpleOrderDto);
return new ResponseEntity<>(simpleOrder, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
