hyeonga_code

reProject_44_관리자 쿠폰 페이지 기능, 추가, 수정, 스케줄러에 추가, 쿠폰 발급 구현 본문

Project_WEATHERWEAR

reProject_44_관리자 쿠폰 페이지 기능, 추가, 수정, 스케줄러에 추가, 쿠폰 발급 구현

hyeonga 2024. 2. 8. 05:59
반응형

 

reProject_43_팀플 회의, 작업 일지

2024.02.05 팀플 회의 -- 관리자 쿠폰 관리 -- 취소 / 환불 / 교환 / 리뷰 작성 기능 -- 스케줄러 기능 추가 (쿠키만료, 쿠폰 만료, 날씨업데이트) -- 날씨 정보 -- 통계(대부분 chart.js를 사용하는 것 같음)

hyeonga493.tistory.com

2024.02.07

-- 관리자 쿠폰페이지 작업

-- 쿠폰 등록 기능

-- 쿠폰 삭제 기능(삭제되지 않도록 해야하나 일단은 기능을 구현해 둠)

-- 쿠폰 목록 조회

-- 쿠폰 검색 기능 작업

-- 쿠폰 배부

-- 쿠폰 만료 기간 체크

 

couponList.jsp 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WeatherWear 관리자</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<!-- Font Awesome -->
<link href="resources/admin/AdminLTE/plugins/fontawesome-free/css/all.min.css" rel="stylesheet">
<!-- Theme style -->
<link href="resources/admin/AdminLTE/dist/css/adminlte.min.css" rel="stylesheet">
<!-- Swiper -->
<link href="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css" rel="stylesheet"/>
<style>
    .checkbox{ width:20px; height: 20px;}
    .checkboxDiv{ display: flex; align-items: center; justify-content: space-around;}
    .checkDiv{ display:flex; align-items: stretch;}
</style>
</head>
<body class="hold-transition sidebar-collapse layout-top-nav">
    <div class="wrapper">
        <%@ include file="../header.jsp" %>
    
        <div class="content-header">
            <section class="content-header">
                <div class="container">
                    <div class="row mb-2">
                        <div class="col-sm-6">
                            <h1>쿠폰 관리</h1>
                        </div>
                        <div class="col-sm-6">
                            <ol class="breadcrumb float-sm-right">
                                <li class="breadcrumb-item"><a href="main.mdo">메인</a></li>
                                <li class="breadcrumb-item active">쿠폰 관리</li>
                            </ol>
                        </div>
                    </div>
                </div>
            </section>
            
            <section class="content">
                <div class="container">
                    <div class="row">
                        <div class="col-12">
                            <div class="card">
                                <div class="card-header">
                                    <div class="card-title">
                                        <div class="orderby_btn">
                                            <button type="button" class="btn btn-sm btn-outline-primary" onclick="newCoupon()">+추가</button>
                                        </div>
                                    </div>
                                    <div class="card-tools">
                                        <!-- Search -->
                                        <div class="input-group input-group-sm">
                                            <select id="searchType" class="form-control">
                                                <option value="couponId">번호</option>
                                                <option value="couponName">이름</option>
                                            </select>
                                            <input type="text" id="keyword" class="form-control float-right" placeholder="Search">
                                            <div class="input-group-append">
                                                <button type="button" class="btn btn-default" id="btnSearch">
                                                    <i class="fas fa-search"></i>
                                                </button>
                                            </div>
                                        </div>
                                        <!-- End Search -->
                                    </div>
                                </div>
                                <div class="card-body table-responsive p-0">
                                    <form id="listForm" name="clientForm" method="post">
                                        <table class="table table-hover text-nowrap" style="table-layout: fixed;">
                                            <colgroup>
                                                <col width="50px"/><!-- # -->
                                                <col width="200px"/><!-- 쿠폰번호 -->
                                                <col width="270px"/><!-- 쿠폰이름 -->
                                                <col width="90px"/><!-- 쿠폰금액 -->
                                                <col width="90px"/><!-- 쿠폰 적용 최소 금액 -->
                                                <col width="310px"/><!-- 사용기간 -->
                                                <col width="100px"/><!-- 버튼 -->
                                            </colgroup>
                                            <thead>
                                                <tr>
                                                    <th>#</th>
                                                    <th>쿠폰번호</th>
                                                    <th>쿠폰이름</th>
                                                    <th>쿠폰금액</th>
                                                    <th>최소 금액</th>
                                                    <th>사용기간</th>
                                                </tr>
                                            </thead>
                                            <tbody>
                                                <c:forEach var="coupon" items="${couponList}" varStatus="status">
                                                    <tr class="${coupon.couponId}">
                                                        <td>${ status.index+1 }</td>
                                                        <td id="couponId_${coupon.couponId}">${coupon.couponId}</td>
                                                        <td id="couponName_${coupon.couponId}">${coupon.couponName}</td>
                                                        <td id="couponPrice_${coupon.couponId}"><fmt:formatNumber pattern="#,###,###" value="${coupon.couponPrice}"/></td>
                                                        <td id="couponMinPrice_${coupon.couponId}"><fmt:formatNumber pattern="#,###,###" value="${coupon.minPrice}"/></td>
                                                        <td id="couponDate_${coupon.couponId}">
                                                            <fmt:formatDate pattern="YYYY-MM-DD HH:mm" value="${coupon.couponStDate}"/> / <fmt:formatDate pattern="YYYY-MM-DD HH:mm" value="${coupon.couponEndDate}"/>
                                                        </td>
                                                        <td id="couponBtn_${coupon.couponId}"><input type="button" value="삭제" class="btn btn-sm btn-outline-danger" onclick="deleteCoupon(this)"></td>
                                                    </tr>
                                                </c:forEach>
                                            </tbody>
                                        </table>
                                    </form>
                                </div>
                                <!-- Modal -->
                                <div class="modal fade show" id="modal-default" style="display: none; padding-right: 17px;" aria-modal="true" role="dialog">
                                </div>
                                <!-- pagination -->
                                <div class="card-footer">        
                                    <div class="card-title input-group-sm">
                                        <select name="searchType" class="form-control" id="listSize" onchange="page(1)">
                                            <option value="5" <c:if test="${pagination.getListSize() == 5}">selected="selected"</c:if>>5개</option>
                                            <option value="10" <c:if test="${pagination.getListSize() == 10}">selected="selected"</c:if>>10개</option>
                                            <option value="15" <c:if test="${pagination.getListSize() == 15}">selected="selected"</c:if>>15개</option>
                                            <option value="30" <c:if test="${pagination.getListSize() == 30}">selected="selected"</c:if>>30개</option>
                                        </select>
                                    </div>
                                    
                                    <ul class="pagination pagination-sm m-0 float-right">
                                        <c:if test="${pagination.prev}">
                                            <li class="page-item">
                                                <a class="page-link" href="#" onclick="fn_prev('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}', '${search.searchType}', '${search.keyword}')">&laquo;</a>
                                            </li>
                                        </c:if>
                                        <c:forEach begin="${pagination.startPage}" end="${pagination.endPage}" var="pageId">
                                            <li class="page-item <c:out value="${pagination.page == pageId ? 'active':''}"/>">
                                                <a class="page-link" href="#" onclick="fn_pagination('${pageId}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}', '${search.searchType}', '${search.keyword}')">${pageId}</a>
                                            </li>
                                        </c:forEach>                                        
                                        <c:if test="${pagination.next}">
                                            <li class="page-item">
                                                <a class="page-link" href="#" onclick="fn_next('${pagination.page}', '${pagination.range}', '${pagination.rangeSize}', '${pagination.listSize}', '${search.searchType}', '${search.keyword}')">&raquo;</a>
                                            </li>
                                        </c:if>
                                    </ul>
                                </div>
                                
                            </div>
                        </div>
                    </div>
                    
                </div>
            </section>
        </div>    
            
        <%@ include file="../footer.jsp" %>
    </div>
    <div class="modal-backdrop fade" style="display:none"></div>
<!-- jQuery -->
<script src="resources/admin/AdminLTE/plugins/jquery/jquery.min.js"></script>
<script    src="resources/util/plugins/sweetalert/jquery-lates.min.js"></script>
<script src="resources/util/plugins/sweetalert/sweetalert2.js"></script>
<!-- Bootstrap 4 -->
<script src="resources/admin/AdminLTE/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- Modal -->
<script src="resources/admin/AdminLTE/plugins/sweetalert2/sweetalert2.min.js"></script>
<script src="resources/admin/AdminLTE/dist/js/adminlte.min.js?v=3.2.0"></script>
<!-- sweetAlert (alert/confirm/toast) -->
<script src="resources/util/js/sweetalert.js"></script>
 
<script src="resources/util/js/pagingNoOrderBy.js"></script>
<script src="resources/util/js/modal.js"></script>
<script src="resources/util/js/checkbox.js"></script>
<script src="resources/admin/js/manageCoupon.js"></script>
</body>
</html>

 

 

CouponController.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package com.w2.admin.controller;
 
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
 
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.w2.coupon.CouponVO;
import com.w2.coupon.service.CouponService;
import com.w2.util.RandomString;
import com.w2.util.ResponseDTO;
import com.w2.util.Search;
 
@Controller
public class CouponController {
    @Autowired
    private CouponService couponService;
    
    /**
     * 쿠폰 목록 가져오기
     * @param model
     * @return
     */
    @RequestMapping("couponList.mdo")
    public String couponList(Model model, @RequestParam(required = false, defaultValue = "1"int page,
            @RequestParam(required = false, defaultValue = "1"int range, @RequestParam(required = false, defaultValue = "couponId"String searchType,
            @RequestParam(required = falseString keyword, @ModelAttribute("search") Search search) {
        
        // 검색
        model.addAttribute("search", search);
        search.setSearchType(searchType);
        search.setKeyword(keyword);
        
        // 전체 게시글 개수
        int listCnt = couponService.getCouponListCnt(search);
        
        // 검색 페이지 정보
        search.pageInfo(page, range, listCnt);
        // 페이징
        model.addAttribute("pagination", search);
        // 화면 출력
        model.addAttribute("couponList", couponService.getCouponListAll(search));
        
        return "coupon/couponList";
    }
    
    /**
     * 쿠폰 등록
     * @return
     * @throws ParseException 
     */
    @ResponseBody
    @RequestMapping("couponInsert.mdo")
    public ResponseDTO<CouponVO> couponInsert(String couponName, int couponPrice, int minPrice, String couponStDate, String couponEndDate, String couponStTime, String couponEndTime, HttpServletRequest request, String gradeList) throws ParseException {
        Integer statusCode = HttpStatus.OK.value();
        int code;
        String resultCode;
        String message;
        
        CouponVO coupon = new CouponVO();
        coupon.setCouponId("CP" + RandomString.createFileName() + RandomString.setRandomString(4,"number"));
        coupon.setCouponName(couponName);
        coupon.setCouponPrice(couponPrice);
        coupon.setMinPrice(minPrice);
        coupon.setGradeList(gradeList);
        coupon.setCouponEndDate(RandomString.setTime(couponEndDate, couponEndTime));
        coupon.setCouponStDate(RandomString.setTime(couponStDate, couponStTime));
        try {
            int result = couponService.insertCoupon(coupon);
            
            if(result > 0) {
                code = 1;
                resultCode = "success";
                message = "등록이 완료되었습니다.";
            } else if (result == -2){
                code = -2;
                resultCode = "fail";
                message = "쿠폰번호가 이미 존재합니다.";
            } else {
                code = -1;
                resultCode = "fail";
                message = "오류가 발생했습니다. 다시 시도해주세요";
            }
        } catch (Exception e) {
            e.printStackTrace();
            code = -1;
            resultCode = "fail";
            message = "오류가 발생했습니다. 다시 시도해주세요";
        }
        return new ResponseDTO<CouponVO>(statusCode, code, resultCode, message, coupon);
    }
 
    /**
     * 쿠폰 수정
     * @return
     */
    @ResponseBody
    @RequestMapping("couponUpdate.mdo")
    public ResponseDTO<CouponVO> couponUpdate(CouponVO coupon) {
        Integer statusCode = HttpStatus.OK.value();
        int code;
        String resultCode;
        String message;
 
        try {
            int result = couponService.updateCoupon(coupon);
            
            if(result > 0) {
                code = 1;
                resultCode = "success";
                message = "수정되었습니다.";
            } else {
                code = -1;
                resultCode = "fail";
                message = "오류가 발생했습니다. 다시 시도해주세요";
            }
        } catch (Exception e) {
            e.printStackTrace();
            code = -1;
            resultCode = "fail";
            message = "오류가 발생했습니다. 다시 시도해주세요";
        }
        
        return new ResponseDTO<CouponVO>(statusCode, code, resultCode, message, coupon);
    }
 
    /**
     * 쿠폰 삭제
     * @return
     */
    @ResponseBody
    @RequestMapping("couponDelete.mdo")
    public ResponseDTO<String> deletecoupon(@Param("couponId"String couponId) {
        Integer statusCode = HttpStatus.OK.value();
        int code;
        String resultCode;
        String message;
 
        System.err.println("couponId : " + couponId);
        try {
            int result = couponService.deleteCoupon(couponId);
            
            if(result > 0) {
                code = 1;
                resultCode = "success";
                message = "삭제되었습니다.";
            } else {
                code = -1;
                resultCode = "fail";
                message = "오류가 발생했습니다. 다시 시도해주세요";
            }
        } catch (Exception e) {
            e.printStackTrace();
            code = -1;
            resultCode = "fail";
            message = "오류가 발생했습니다. 다시 시도해주세요";
        }
        
        return new ResponseDTO<String>(statusCode, code, resultCode, message, couponId);
    }
}
 

 

 

CouponService.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.w2.coupon.service;
 
import java.util.List;
 
import com.w2.coupon.CouponVO;
import com.w2.util.Search;
 
public interface CouponService {
    // 관리자
    List<CouponVO> getCouponListAll(Search search);     // 쿠폰 목록 가져오기
    int getCouponListCnt(Search search);                // 쿠폰 목록 개수 가져오기
    int insertCoupon(CouponVO coupon);                  // 쿠폰 등록
    int updateCoupon(CouponVO coupon);                  // 쿠폰 수정
    int deleteCoupon(String couponId);                  // 쿠폰 삭제
    int setCoupon();                                    // 쿠폰 배부
    void setCouponLimit();                              // 쿠폰 기간 만료 체크
    
    // 사용자
    List<CouponVO> getCouponList(String clientId);
}
 

 

 

CouponServiceImpl.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.w2.coupon.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import com.w2.coupon.CouponDAO;
import com.w2.coupon.CouponVO;
import com.w2.util.Search;
 
@Transactional
@Service("couponService")
public class CouponServiceImpl implements CouponService {
 
    @Autowired
    CouponDAO couponDAO;
 
    @Override
    public List<CouponVO> getCouponListAll(Search search) {
        return couponDAO.getCouponListAll(search);
    }
 
    @Override
    public int getCouponListCnt(Search search) {
        return couponDAO.getCouponListCnt(search);
    }
 
    @Override
    public int insertCoupon(CouponVO coupon) {
        return couponDAO.insertCoupon(coupon);
    }
 
    @Override
    public int updateCoupon(CouponVO coupon) {
        return couponDAO.updateCoupon(coupon);
    }
 
    @Override
    public int deleteCoupon(String couponId) {
        couponDAO.deleteCouponList(couponId);
        return couponDAO.deleteCouponInfo(couponId);
    }
 
    @Override
    public List<CouponVO> getCouponList(String clientId) {
        return couponDAO.getCouponList(clientId);
    }
 
    @Override
    public int setCoupon() {
        return couponDAO.setCoupon();
    }
 
    @Override
    public void setCouponLimit() {
        couponDAO.setCouponLimit();
    }
}
 

 

 

CouponDAO.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.w2.coupon;
 
import java.util.List;
 
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
 
import com.w2.util.Search;
 
@Repository
public class CouponDAO {
    
    @Autowired
    SqlSessionTemplate sqlSessionTemplate;
    public List<CouponVO> getCouponListAll(Search search) {
        return sqlSessionTemplate.selectList("CouponDAO.getCouponListAll", search);
    }
 
    public int getCouponListCnt(Search search) {
        return sqlSessionTemplate.selectOne("CouponDAO.getCouponListCnt", search);
    }
 
    public int insertCoupon(CouponVO coupon) {
        return sqlSessionTemplate.insert("CouponDAO.insertCoupon", coupon);
    }
 
    public int updateCoupon(CouponVO coupon) {
        return sqlSessionTemplate.update("CouponDAO.updateCoupon", coupon);
    }
 
    public int deleteCouponInfo(String couponId) {
        return sqlSessionTemplate.delete("CouponDAO.deleteCouponInfo", couponId);
    }
 
    public int deleteCouponList(String couponId) {
        return sqlSessionTemplate.delete("CouponDAO.deleteCouponList", couponId);
    }
 
    public List<CouponVO> getCouponList(String clientId) {
        return sqlSessionTemplate.selectList("CouponDAO.getCouponList", clientId);
    }
 
    public int setCoupon() {
        return sqlSessionTemplate.insert("CouponDAO.setCoupon");
    }
 
    public void setCouponLimit() {
        sqlSessionTemplate.update("CouponDAO.setCouponLimit");
    }
 
    
}
 

 

 

coupon-mapping.xml 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
                 
<mapper namespace="CouponDAO">
    <select id="getCouponListAll" resultType="coupon">
        SELECT * 
        FROM coupon_info
        <trim prefix="WHERE" prefixOverrides="AND|OR">
            <if test="keyword != null and keyword != ''">
                <if test="searchType == 'couponId'">
                    AND couponId like CONCAT('%', #{keyword}, '%')
                </if>
                <if test="searchType == 'couponName'">
                    AND couponName like CONCAT('%', #{keyword}, '%')
                </if>
            </if>
        </trim>
        ORDER BY couponId DESC
        LIMIT #{startList}, #{listSize};
    </select>
 
    <select id="getCouponListCnt" resultType="int">
        SELECT COUNT(*
        FROM coupon_info
        <trim prefix="WHERE" prefixOverrides="AND|OR">
            <if test="keyword != null and keyword != ''">
                <if test="searchType == 'couponId'">
                    AND couponId like CONCAT('%', #{keyword}, '%')
                </if>
                <if test="searchType == 'couponName'">
                    AND couponName like CONCAT('%', #{keyword}, '%')
                </if>
            </if>
        </trim>
    </select>
 
    <insert id="insertCoupon" parameterType="coupon">
        INSERT INTO coupon_info(couponId, couponName, couponPrice, couponStDate, couponEndDate, minPrice, gradeList)
        VALUES(#{ couponId } , #{ couponName }, #{ couponPrice }, #{ couponStDate } , #{ couponEndDate }, #{ minPrice }, #{ gradeList });
    </insert>
 
<!-- 하루전부터 현재 시간까지의 쿠폰 배부 -->
    <insert id="setCoupon" parameterType="coupon">
        INSERT INTO coupon_list (couponId, clientId, couponStatus)
        SELECT ci.couponId, c.clientId, '사용가능'
        FROM coupon_info AS ci
        JOIN client AS c ON FIND_IN_SET(c.gradeId, ci.gradeList) > 0
        WHERE ci.couponStDate BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND now()
        AND NOT EXISTS(
            SELECT 1
            FROM coupon_list cl
            WHERE cl.couponId = ci.couponId 
            AND cl.clientId = c.clientId
        );
    </insert>
 
<!-- 현재 시간 이전의 기간 만료 쿠폰 만료 -->
    <update id="setCouponLimit" parameterType="coupon">
        <![CDATA[UPDATE coupon_list cl SET cl.couponStatus='기간만료'
        WHERE cl.couponStatus="사용가능"
        AND EXISTS(
            SELECT 1 
            FROM coupon_info ci
            WHERE ci.couponId = cl.couponId
            AND ci.couponEndDate < NOW());]]>
    </update>
 
    <update id="updateCoupon" parameterType="coupon">
        UPDATE FROM coupon_list WHERE couponStatus=#{ couponStatus }
    </update>
 
    <delete id="deleteCouponInfo" parameterType="String">
        DELETE FROM coupon_info WHERE couponId=#{ couponId }
    </delete>
    
    <delete id="deleteCouponList" parameterType="String">
        DELETE FROM coupon_list WHERE couponId=#{ couponId }
    </delete>
 
    <select id="getCouponList" parameterType="String" resultType="coupon">
        SELECT *
        FROM coupon_info ci
        LEFT JOIN coupon_list cl ON (ci.couponId = cl.couponId AND cl.couponStatus='사용가능')
        WHERE cl.clientId=#{ clientId }
    </select>
</mapper>

 

 

SchedulingService.java 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.w2.util;
 
import java.io.IOException;
 
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
 
import com.w2.cart.CartDAO;
import com.w2.coupon.service.CouponService;
import com.w2.weather.service.WeatherService;
 
@Service(value="schedulerService")
public class SchedulingService {
 
    @Autowired
    private CartDAO cartDAO;
 
    @Autowired
    private WeatherService weatherService;
 
    @Autowired
    private CouponService couponService;
    
    /*
         cron 표현식
          초         | 분     | 시     | 일     | 월     | 요일     | 연도
          0-59      0-59     0-23     1-31     1-12     1-12    (생략가능)
     */
    //@Scheduled(cron="0 0 0 * * *")
//    @Scheduled(cron="*/30 * * * * *")
    @Scheduled(cron="0 0 17 * * *")
    public void scheduleRun() throws IOException, ParseException {
        checkCookieLimit();
        weatherService.saveWeather();
        couponService.setCouponLimit();
        couponService.setCoupon();
    }
    
    // 만료된 쿠키 확인
    public void checkCookieLimit() {
        cartDAO.checkCookieLimit();
    }
}
 

 

 

applicationContext.xml 추가

1
2
3
4
5
    
    <!-- 의존성 주입을 위해 빈 등록 대신 -->
        <context:component-scan base-package="com.w2.util" />
        <context:component-scan base-package="com.w2.weather" />
        <context:component-scan base-package="com.w2.coupon" />

 

 

manageProduct.js 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
 * 
 */
 
//삭제
function deleteCoupon(target){
    let id = target.parentElement.id;
    let couponId = id.split("_")[1];
    
    playConfirm("쿠폰 정보를 삭제하시겠습니까?""이미 발급된 쿠폰은 삭제되지 않습니다.""question""삭제하기""취소하기""deleteCouponAjax('" + couponId + "')""return");
}
 
function deleteCouponAjax(couponId){
    $.ajax({
        type: "post",
        url: "couponDelete.mdo?couponId=" + couponId,
        dataType: "json",
        success: function(res) {
            if(res.code == -1) {
                playToast(res.message, 'error');
                return;
            } 
            
            if(res.code == 1) {
                playToast(res.message, 'success');
                window.location.reload();
            }
        },
        error: function(request, status, error) {
            console.log("code: " + request.status + "\n" + "message: " + request.responseText + "\n" + "error: " + error);
        }
    });
}
 
// 정보 입력
    let couponName = '';
    let couponPrice = '';
    let minPrice = '';
    let couponStDate;
    let couponEndDate;
    let couponStTime;
    let couponEndTime;
    let gradeList = '';
    
    function getInfo(){
        gradeList = '';
        couponName = $("input[name='couponName']").val();
        couponPrice = $("input[name='couponPrice']").val();
        minPrice = $("input[name='minPrice']").val();
        couponStDate = $("input[name='couponStDate']").val();
        couponEndDate = $("input[name='couponEndDate']").val();
        couponStTime = $("input[name='couponStTime']").val();
        couponEndTime = $("input[name='couponEndTime']").val();
        
        let grade = document.querySelectorAll("input[type='checkbox']:checked");
        for(let i=0; i<grade.length; i++){
            gradeList += grade[i].value;
            if(i <grade.length-1){
                gradeList += ",";
            }
        }
    }
 
// 신규 등록
function insertCoupon(){
    getInfo();
    
    if(couponName == '' || couponName == null){
        playToast("쿠폰 이름은 필수 정보입니다.""warning");
        $("input[name='couponName']").focus();
        return;
    } else if (couponPrice == '' || couponPrice == null ){
        playToast("쿠폰 가격은 필수 정보입니다.""warning");
        $("input[name='couponPrice']").focus();
        return;
    } else if (minPrice == '' || minPrice == null ){
        playToast("쿠폰 최소 금엑은 필수 정보입니다.""warning");
        $("input[name='minPrice']").focus();
        return;
    } else if (couponStDate == '' || couponStDate == null ){
        playToast("시작 일자를 선택해주세요""warning");
        $("input[name='couponStDate']").focus();
        return;
    } else if (couponEndDate == '' || couponEndDate == null ){
        playToast("종료 일자를 선텍헤주세요""warning");
        $("input[name='couponEndDate']").focus();
        return;
    } else if( gradeList =='' || gradeList == null){
        playToast("적용 등급을 선택해주세요""warning");
        return;
    } 
    
    if(couponEndTime == "" || couponEndTime == null){
        couponEndTime = "00:00";
    } 
    
    if(couponStTime == "" || couponStTime == null){
        couponStTime = "00:00";
    } 
    
    console.log("couponStDate : " + couponStDate);
    console.log("couponStTime : " + couponStTime);
    console.log("couponEndDate : " + couponEndDate);
    console.log("couponEndTime : " + couponEndTime);
    
    $.ajax({
        type: "post",
        url: "couponInsert.mdo",
        dataType: "json",
        data: {
            couponName: couponName,
            couponPrice: parseInt(couponPrice),
            minPrice: parseInt(minPrice),
            couponStDate: couponStDate,
            couponStTime: couponStTime,
            couponEndDate: couponEndDate,
            couponEndTime: couponEndTime,
            gradeList: gradeList
        },
        success: function(res) {
            if(res.code == -1) {
                playToast(res.message, 'error');
                return;
            } 
            
            if(res.code == 1) {
                playToast(res.message, 'success');
                window.location.reload();
            }
            
            if(res.code == -2) {
                playToast(res.message, 'warning');
                $("input[name='couponId']").val("");
                $("input[name='couponId']").focus();
                return;
            }
        },
        error: function(request, status, error) {
            console.log("code: " + request.status + "\n" + "message: " + request.responseText + "\n" + "error: " + error);
        }
    });
}
 
// 신규 등록
function newCoupon(){
    let newcoupon = "";
    newcoupon += "<div class='modal-dialog'><div class='modal-content'><div class='modal-header'><h4 class='modal-title'>신규 등록</h4>";
    newcoupon += "<button type='button' class='close' data-dismiss='modal' aria-label='Close' onclick='closeModal()'><span aria-hidden='true'>×</span></button></div>";
    newcoupon += "<div class='modal-body'><div class='form-group'><label for='couponName'>쿠폰 이름<code></code></label>";
    newcoupon += "<input type='text' name='couponName' class='form-control form-control-border border-width-2' id='couponName' placeholder='쿠폰 이름'>";
    newcoupon += "</div><div class='form-group'><label for='couponPrice'>쿠폰 금액<code></code></label>";
    newcoupon += "<input type='number' name='couponPrice' class='form-control form-control-border border-width-2' id='couponPrice' placeholder='쿠폰 금액'>";
    newcoupon += "</div><div class='form-group'><label for='minPrice'>쿠폰 적용 최소 금액<code></code></label>";
    newcoupon += "<input type='number' name='minPrice' class='form-control form-control-border border-width-2' id='minPrice' placeholder='쿠폰 적용 최소 금액'>";
    newcoupon += "</div><div class='form-group'><label for='gradeList'>쿠폰 적용 등급<code></code></label>";
    newcoupon += "<div class='row checkboxDiv'><div class='checkDiv'><input type='checkbox' value='S' name='gradeList' class='checkbox' id='grade_S'>&nbsp;<label for='grade_S'>&nbsp;Silver&nbsp;</label>&nbsp;</div>";
    newcoupon += "<div class='checkDiv'><input type='checkbox' value='G' name='gradeList' class='checkbox' id='grade_G'>&nbsp;<label for='grade_G'>&nbsp;Gold&nbsp;</label>&nbsp;</div>";
    newcoupon += "<div class='checkDiv'><input type='checkbox' value='B' name='gradeList' class='checkbox' id='grade_B'>&nbsp;<label for='grade_B'>&nbsp;Black&nbsp;</label>&nbsp;</div></div>";
    newcoupon += "</div><div class='form-group'><label for='couponStDate'>쿠폰 시작 일자<code></code></label><div class='row'>";
    newcoupon += "<input type='date' name='couponStDate' class='form-control form-control-border border-width-2' id='couponStDate' style='width:50%;'>";
    newcoupon += "<input type='time' name='couponStTime' class='form-control form-control-border border-width-2' id='couponStTime' style='width:50%;'>";
    newcoupon += "</div></div><div class='form-group'><label for='couponEndDate'>쿠폰 만료 일자<code></code></label><div class='row'>";
    newcoupon += "<input type='date' name='couponEndDate' class='form-control form-control-border border-width-2' id='couponEndDate' style='width:50%;'>";
    newcoupon += "<input type='time' name='couponEndTime' class='form-control form-control-border border-width-2' id='couponEndTime' style='width:50%;'>";
    newcoupon += "</div></div></div><div class='modal-footer justify-content-between'><button type='button' class='btn btn-default' data-dismiss='modal' onclick='closeModal()'>취소하기</button>";
    newcoupon += "<button type='button' class='btn btn-primary' onclick='insertCoupon()'>등록하기</button></div></div></div>";
    openModel(newcoupon);
    
    let today = new Date();
    document.getElementById("couponStDate").min = today.toISOString().split("T")[0];
    document.getElementById("couponStTime").min = today.toISOString().split("T")[1];
    document.getElementById("couponStDate").value = today.toISOString().split("T")[0];
    document.getElementById("couponStTime").value = today.toISOString().split("T")[1];
    
    document.getElementById("couponStDate").addEventListener("change"function() {
        var startDate = new Date(this.value);
        startDate.setHours(0000);
        document.getElementById("couponStDate").min = startDate.toISOString().split("T")[0];
        document.getElementById("couponStTime").min = startDate.toISOString().split("T")[1];
    });
      
    document.getElementById("couponStTime").addEventListener("change"function() {
        var startDate = new Date(document.getElementById("couponStDate").value);
        startDate.setHours(this.value.split(":")[0], this.value.split(":")[1], 0);
        document.getElementById("couponEndDate").min = startDate.toISOString().split("T")[0];
        document.getElementById("couponEndTime").min = startDate.toISOString().split("T")[0];
    });
    
    document.getElementById("couponEndTime").addEventListener("change"function() {
        var startDate = new Date(document.getElementById("couponStDate").value);
        startDate.setHours(document.getElementById("couponStTime").value.split(":")[0], document.getElementById("couponStTime").value.split(":")[1], 0);
        var endDate = new Date(document.getElementById("couponEndDate").value);
        endDate.setHours(this.value.split(":")[0], this.value.split(":")[1], 0);
        console.log("sratDate : " + startDate);
        console.log("endDate : " + endDate);
        if (startDate > endDate) {
            this.value = "";
            playToast("시작일보다 이전 시간을 선택할 수 없습니다""error");
        }
    });
}
 

 

 

>> 실행 (couponList.mdo)

 

 

>> 쿠폰 삭제 > 한 번 더 확인

 

 

>> 쿠폰 등록

 

 

>>> 쿠폰 만료일자는 쿠폰 시작일 이후로만 선택 가능

-- 같은 일자 선택 후 시간 선택시, 시작 시간보다 이전 시간 선택시 초기화됩니다.

 

 

>>> 등록 성공시 페이지 리로드

 

>>> 현재 스케줄링은 오후 5시로 되어 있으나 추후 배포전에 변경할 예정

-- 현재 쿠폰 일자에 시간이 분단위까지 쪼개 설정되도록 되어있는데 이렇게 설정하는 경우 스케줄링을 분단위로 작업해야 할 수 있어 추후 팀원들과 상의후 변경할 예정

반응형