diff --git a/sql/MU_CTI_LOG_DDL.sql b/sql/MU_CTI_LOG_DDL.sql new file mode 100644 index 0000000..4402684 --- /dev/null +++ b/sql/MU_CTI_LOG_DDL.sql @@ -0,0 +1,54 @@ +-- ============================================ +-- CTI 통화 로그 테이블 (MariaDB) +-- ============================================ + +-- CTI 통화 로그 메인 테이블 +CREATE TABLE IF NOT EXISTS MU_CTI_LOG ( + MU_CTI_LOG_ID VARCHAR(20) NOT NULL COMMENT 'CTI 로그 ID (PK)', + RECORD_NO VARCHAR(50) NULL COMMENT 'CTI 레코드 번호', + CID VARCHAR(20) NULL COMMENT '발신자 전화번호', + FULLDNIS VARCHAR(20) NULL COMMENT '매장 수신번호 (ARS 대표번호)', + BOUND VARCHAR(10) NULL COMMENT '통화방향 (IN/OUT)', + MENU_NO VARCHAR(10) NULL COMMENT 'ARS 메뉴 번호', + STATE_TYPE VARCHAR(20) NULL COMMENT '상태유형 (start/ringout/link/callback/lms/local)', + CTI_STEP VARCHAR(5) NULL COMMENT '통화단계 (1=수신, 2=ring, 3=link, 4=linkend, 5=bend, 98=callback)', + LOGINCID VARCHAR(20) NULL COMMENT '상담원 전화번호', + C_TYPE1 VARCHAR(20) NULL COMMENT '구분2 (초진/재진)', + C_TYPE2 VARCHAR(20) NULL COMMENT '구분3 (상담/상담후예약/회차예약)', + CRM_MB_PID VARCHAR(20) NULL COMMENT 'CRM 회원 PID', + STORE_PID VARCHAR(20) NULL COMMENT '매장 PID', + INCALL_SEL VARCHAR(500) NULL COMMENT 'In Call 선택값 (파이프 구분)', + CALL_BACK_CHK CHAR(1) NULL DEFAULT 'N' COMMENT '콜백 확인 여부 (Y/N)', + USE_YN CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부', + CUD_FLAG CHAR(1) NULL DEFAULT 'C' COMMENT 'CUD 플래그', + REG_ID VARCHAR(20) NULL COMMENT '등록자 ID', + REG_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록일시', + MOD_ID VARCHAR(20) NULL COMMENT '수정자 ID', + MOD_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정일시', + PRIMARY KEY (MU_CTI_LOG_ID) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='CTI 통화 로그'; + +-- 인덱스 +CREATE INDEX IDX_MU_CTI_LOG_RECORD_NO ON MU_CTI_LOG (RECORD_NO); +CREATE INDEX IDX_MU_CTI_LOG_REG_DATE ON MU_CTI_LOG (REG_DATE); +CREATE INDEX IDX_MU_CTI_LOG_CID ON MU_CTI_LOG (CID); +CREATE INDEX IDX_MU_CTI_LOG_FULLDNIS ON MU_CTI_LOG (FULLDNIS); +CREATE INDEX IDX_MU_CTI_LOG_STORE_PID ON MU_CTI_LOG (STORE_PID); + + +-- CTI 통화 메모 테이블 +CREATE TABLE IF NOT EXISTS MU_CTI_TEXT ( + MU_CTI_TEXT_ID VARCHAR(20) NOT NULL COMMENT 'CTI 메모 ID (PK)', + RECORD_NO VARCHAR(50) NULL COMMENT 'CTI 레코드 번호', + CALL_MSG TEXT NULL COMMENT '통화 메모 내용', + USE_YN CHAR(1) NOT NULL DEFAULT 'Y' COMMENT '사용여부', + CUD_FLAG CHAR(1) NULL DEFAULT 'C' COMMENT 'CUD 플래그', + REG_ID VARCHAR(20) NULL COMMENT '등록자 ID', + REG_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '등록일시', + MOD_ID VARCHAR(20) NULL COMMENT '수정자 ID', + MOD_DATE DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정일시', + PRIMARY KEY (MU_CTI_TEXT_ID) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='CTI 통화 메모'; + +-- 인덱스 +CREATE INDEX IDX_MU_CTI_TEXT_RECORD_NO ON MU_CTI_TEXT (RECORD_NO); diff --git a/src/main/java/com/madeu/crm/contentsBbs/ctrl/ContentsBbsController.java b/src/main/java/com/madeu/crm/contentsBbs/ctrl/ContentsBbsController.java index 518ca1d..c2a73b6 100644 --- a/src/main/java/com/madeu/crm/contentsBbs/ctrl/ContentsBbsController.java +++ b/src/main/java/com/madeu/crm/contentsBbs/ctrl/ContentsBbsController.java @@ -442,6 +442,76 @@ public class ContentsBbsController extends ManagerDraftAction { return HttpUtil.makeHashToJsonModelAndView(map); } + /** + * 출력순서 일괄 업데이트 + * + * @param paramMap + * @param session + * @param request + * @param response + * @return + */ + @PostMapping(value = "/contentsBbs/updateOrdNo.do") + public ModelAndView updateOrdNo(@RequestBody HashMap paramMap, HttpSession session, + HttpServletRequest request, HttpServletResponse response) { + log.debug("ContentsBbsController updateOrdNo START"); + + HashMap map = new HashMap(); + + StringBuffer errorMsg = new StringBuffer(); + + try { + if (!webCheckLogin(session)) { + return null; + } else { + paramMap.put("loginMemberId", String.valueOf(session.getAttribute("loginMemberId"))); + paramMap.put("modId", String.valueOf(session.getAttribute("loginMemberId"))); + map = contentsBbsService.updateContentsBbsOrdNo(paramMap); + } + } catch (Exception e) { + e.printStackTrace(); + errorMsg.append(e); + } finally { + if (Constants.OK == map.get("msgCode")) { + + } else { + map.put("msgCode", Constants.FAIL); + map.put("success", false); + if (null == map.get("msgDesc") || ("").equals(map.get("msgDesc"))) { + map.put("msgDesc", "정상적으로 수행되지 않았습니다. 관리자에게 문의하시기 바랍니다."); + } + } + + try { + HashMap visitLogParamMap = RequestLogUtil.getVisitLogParameterMap(request); + HashMap insertMap = new HashMap(); + + insertMap.put("url", "/contentsBbs/updateOrdNo.do"); + insertMap.put("func", "updateOrdNo"); + insertMap.put("funcName", "출력순서 변경"); + insertMap.put("service", "contentsBbsService"); + insertMap.put("serviceName", "출력순서 변경"); + insertMap.put("requestValue", String.valueOf(paramMap)); + insertMap.put("responseValue", String.valueOf(map)); + insertMap.put("tId", map.get("tId")); + if ((String.valueOf(errorMsg)).equals("") || (String.valueOf(errorMsg) == null) + || String.valueOf(errorMsg).length() == 0) { + insertMap.put("resultCode", "SUCCESS"); + } else { + insertMap.put("resultCode", "ERROR"); + } + insertMap.put("resultMsg", String.valueOf(errorMsg)); + insertMap.put("muMemberId", paramMap.get("loginMemberId")); + + webLogHistoryService.insertLogHistory(insertMap, visitLogParamMap); + } catch (Exception e) { + e.printStackTrace(); + } + } + log.debug("ContentsBbsController updateOrdNo END"); + return HttpUtil.makeHashToJsonModelAndView(map); + } + /** * 시술 정보 리스트 조회 (option) * 시술등록 팝업 diff --git a/src/main/java/com/madeu/crm/contentsBbs/service/ContentsBbsService.java b/src/main/java/com/madeu/crm/contentsBbs/service/ContentsBbsService.java index d48c18d..b95bcc9 100644 --- a/src/main/java/com/madeu/crm/contentsBbs/service/ContentsBbsService.java +++ b/src/main/java/com/madeu/crm/contentsBbs/service/ContentsBbsService.java @@ -6,14 +6,24 @@ import java.util.HashMap; public interface ContentsBbsService { public HashMap selectListWebTreatmentPetitIntro(HashMap paramMap) throws Exception; + public HashMap getContentsBbsList(HashMap paramMap) throws Exception; + public HashMap getContentsBbs(HashMap paramMap) throws Exception; public HashMap insertWebTreatmentPetitIntro(HashMap paramMap) throws Exception; - public HashMap putContentsBbs(HashMap paramMap, MultipartFile file, MultipartFile content_file) throws Exception; - + + public HashMap putContentsBbs(HashMap paramMap, MultipartFile file, + MultipartFile content_file) throws Exception; + public HashMap moveContentsBbs(HashMap paramMap) throws Exception; - public HashMap modContentsBbs(HashMap paramMap, MultipartFile file, MultipartFile content_file) throws Exception; + + public HashMap modContentsBbs(HashMap paramMap, MultipartFile file, + MultipartFile content_file) throws Exception; + public HashMap delContentsBbs(HashMap paramMap) throws Exception; + public HashMap selectListTreatmentOption(HashMap paramMap) throws Exception; + + public HashMap updateContentsBbsOrdNo(HashMap paramMap) throws Exception; } diff --git a/src/main/java/com/madeu/crm/contentsBbs/service/impl/ContentsBbsServiceImpl.java b/src/main/java/com/madeu/crm/contentsBbs/service/impl/ContentsBbsServiceImpl.java index 624a871..8e1448d 100644 --- a/src/main/java/com/madeu/crm/contentsBbs/service/impl/ContentsBbsServiceImpl.java +++ b/src/main/java/com/madeu/crm/contentsBbs/service/impl/ContentsBbsServiceImpl.java @@ -930,4 +930,86 @@ public class ContentsBbsServiceImpl implements ContentsBbsService { log.debug("WebTreatmentPetitServiceImpl selectListTreatmentOption END"); return map; } + + /** + * 출력순서 일괄 업데이트 + * + * @param paramMap + * @return + * @throws Exception + */ + @Override + @Transactional(rollbackFor = { Exception.class }, propagation = Propagation.REQUIRES_NEW) + public HashMap updateContentsBbsOrdNo( + HashMap paramMap) throws Exception { + log.debug("ContentsBbsServiceImpl updateContentsBbsOrdNo START"); + + HashMap map = new HashMap(); + + try { + boolean check = true; + + if (true == check) { + // 사용자 확인 + List> userListMap = webMemberSqlMapDAO.checkMember(paramMap); + int userListMapSize = userListMap.size(); + + if (1 == userListMapSize) { + paramMap.put("menuClassAuthId", userListMap.get(0).get("muAuthId")); + } else { + check = false; + map.put("msgCode", Constants.FAIL); + map.put("msgDesc", "사용자 정보가 올바르지 않습니다."); + } + } + + if (true == check) { + // 권한 조회 + HashMap authCheckParamMap = new HashMap(); + authCheckParamMap.put("menuClass", paramMap.get("menuClass")); + authCheckParamMap.put("muAuthId", paramMap.get("menuClassAuthId")); + List> authMenuRelationlistMap = webAuthMenuRelationSqlMapDAO + .selectAuthMenuRelation(authCheckParamMap); + int authMenuRelationlistMapSize = authMenuRelationlistMap.size(); + + if (1 == authMenuRelationlistMapSize) { + if (("Y").equals(authMenuRelationlistMap.get(0).get("updateUseYn"))) { + + } else { + check = false; + map.put("msgCode", Constants.FAIL); + map.put("msgDesc", "수정 권한 정보가 없습니다."); + } + } else { + check = false; + map.put("msgCode", Constants.FAIL); + map.put("msgDesc", "권한 정보가 없습니다."); + } + } + + if (true == check) { + List> orderList = (List>) paramMap.get("orderList"); + int updCnt = 0; + for (Map item : orderList) { + HashMap updateParam = new HashMap(); + updateParam.put("categoryDivCd", paramMap.get("categoryDivCd")); + updateParam.put("categoryNo", item.get("categoryNo")); + updateParam.put("postNo", item.get("postNo")); + updateParam.put("ordNo", item.get("ordNo")); + updateParam.put("modId", paramMap.get("loginMemberId")); + cmmnDAO.update("ContentsBbsSql.updateContentsBbsOrdNo", updateParam); + updCnt++; + } + map.put("msgCode", Constants.OK); + map.put("msgDesc", updCnt + "건 순서가 변경되었습니다."); + } + + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + + log.debug("ContentsBbsServiceImpl updateContentsBbsOrdNo END"); + return map; + } } diff --git a/src/main/resources/mappers/crm/contentsBbs/ContentsBbsSql.xml b/src/main/resources/mappers/crm/contentsBbs/ContentsBbsSql.xml index 09c093e..f0624a1 100644 --- a/src/main/resources/mappers/crm/contentsBbs/ContentsBbsSql.xml +++ b/src/main/resources/mappers/crm/contentsBbs/ContentsBbsSql.xml @@ -38,6 +38,7 @@ ,HC.CATEGORY_NO ,HCB.THUMBNAIL_BOTTOM_TXT ,HCB.HASHTAG + ,HCB.ORD_NO ,DATE_FORMAT(HCB.REG_DATE, '%Y-%m-%d') as REG_DT ,MM.NAME as REG_NM ,DATE_FORMAT(HCB.EVENT_START_DT, '%Y-%m-%d') as START_DT @@ -65,7 +66,7 @@ ORDER BY ${webTreatmentPetitSort} - ORDER BY CATEGORY_NO, POST_NO ASC + ORDER BY HCB.ORD_NO DESC LIMIT 18446744073709551615 @@ -315,4 +316,16 @@ AND HC.CATEGORY_DIV_CD = #{categoryDivCd} ORDER BY HC.CATEGORY_NO ASC + + + /** ContentsBbsSql.updateContentsBbsOrdNo **/ + UPDATE HP_CONTENTS_BBS + SET ORD_NO = #{ordNo} + ,MOD_ID = #{modId} + ,MOD_DATE = NOW() + WHERE USE_YN = 'Y' + AND CATEGORY_DIV_CD = #{categoryDivCd} + AND CATEGORY_NO = #{categoryNo} + AND POST_NO = #{postNo} + \ No newline at end of file diff --git a/src/main/resources/static/js/web/contentsBbs/ContentsBbsSelectList.js b/src/main/resources/static/js/web/contentsBbs/ContentsBbsSelectList.js index 9192544..b4342e2 100644 --- a/src/main/resources/static/js/web/contentsBbs/ContentsBbsSelectList.js +++ b/src/main/resources/static/js/web/contentsBbs/ContentsBbsSelectList.js @@ -391,6 +391,58 @@ function fn_deleteWebTreatmentPetit() { }); } +/**************************************************************************** + * 출력순서 저장 + ****************************************************************************/ +function fn_saveOrdNo() { + if ("Y" != updateUseYn) { + modalEvent.warning("", "수정 권한이 없습니다."); + return false; + } + + let orderList = []; + let totalRows = webTreatmentPetitGridOptions.api.getDisplayedRowCount(); + + for (let i = 0; i < totalRows; i++) { + let rowNode = webTreatmentPetitGridOptions.api.getDisplayedRowAtIndex(i); + orderList.push({ + categoryNo: rowNode.data.categoryNo, + postNo: rowNode.data.postNo, + ordNo: totalRows - i // 상단이 큰 값 (DESC 정렬) + }); + } + + modalEvent.info("순서저장", "변경된 출력순서를 저장하시겠습니까?", function () { + let data = { + menuClass: menuClass, + categoryDivCd: categoryDivCd, + orderList: orderList + }; + + $.ajax({ + url: encodeURI('/contentsBbs/updateOrdNo.do'), + data: JSON.stringify(data), + dataType: "json", + contentType: 'application/json; charset=utf-8', + type: 'POST', + async: true, + success: function (data) { + if ('0' == data.msgCode) { + modalEvent.success("순서저장 성공", data.msgDesc, function () { + $("#btnSaveOrdNo").prop("disabled", true).css("opacity", "0.5"); + fn_selectListWebTreatmentPetitJson(); + }); + } else { + modalEvent.danger("순서저장 오류", data.msgDesc); + } + }, + error: function (xhr, status, error) { + modalEvent.danger("순서저장 오류", "순서 저장 중 오류가 발생하였습니다. 잠시후 다시시도하십시오."); + } + }); + }); +} + /**************************************************************************** * 검색 엔터 이벤트 ****************************************************************************/ @@ -504,7 +556,7 @@ function fn_updateWebTreatmentPetitIntro(postNo, categoryNo) { let webTreatmentPetitColumnDefs = [ - { field: "checkbox", headerName: "", minWidth: 55, maxWidth: 55, headerCheckboxSelection: true, checkboxSelection: true }, + { field: "checkbox", headerName: "", minWidth: 55, maxWidth: 55, rowDrag: true, headerCheckboxSelection: true, checkboxSelection: true }, { field: "rowNum", headerName: "번호", minWidth: 60, maxWidth: 60, sortable: false, cellStyle: { textAlign: 'center' } }, { field: "categoryNm", headerName: "카테고리", minWidth: 120, maxWidth: 130, cellStyle: { textAlign: 'center' } }, { field: "title", headerName: "제목", minWidth: 150, cellStyle: { cursor: 'pointer', color: '#3985EA' } }, @@ -517,7 +569,7 @@ let webTreatmentPetitColumnDefs = [ console.log('Current categoryDivCd:', categoryDivCd); if (categoryDivCd === '02' || categoryDivCd === '04') { webTreatmentPetitColumnDefs = [ - { field: "checkbox", headerName: "", minWidth: 55, maxWidth: 55, headerCheckboxSelection: true, checkboxSelection: true }, + { field: "checkbox", headerName: "", minWidth: 55, maxWidth: 55, rowDrag: true, headerCheckboxSelection: true, checkboxSelection: true }, { field: "rowNum", headerName: "번호", minWidth: 60, maxWidth: 60, sortable: false, cellStyle: { textAlign: 'center' } }, { field: "categoryNm", headerName: "카테고리", minWidth: 120, maxWidth: 130, cellStyle: { textAlign: 'center' } }, { field: "title", headerName: "제목", minWidth: 150, cellStyle: { cursor: 'pointer', color: '#3985EA' } }, @@ -533,6 +585,8 @@ if (categoryDivCd === '02' || categoryDivCd === '04') { // let the grid know which columns and what data to use let webTreatmentPetitGridOptions = { suppressRowTransform: true, + rowDragManaged: true, + animateRows: true, columnDefs: webTreatmentPetitColumnDefs, defaultColDef: { // 리스트 기본 설정 flex: 1, @@ -562,6 +616,10 @@ let webTreatmentPetitGridOptions = { fn_updateWebTreatmentPetitIntro(cell.data.postNo, cell.data.categoryNo); } }, + onRowDragEnd: function (event) { + // 드래그 완료 시 순서저장 버튼 활성화 + $("#btnSaveOrdNo").prop("disabled", false).css("opacity", "1"); + }, onSelectionChanged: function (treatmentpetit) { //체크박스 선택 delList = treatmentpetit.api.getSelectedRows(); console.log(delList); @@ -679,6 +737,11 @@ function fn_pageTreatmentPetit() { fn_deleteWebTreatmentPetit(); }); + // 순서저장 버튼 + $("#btnSaveOrdNo").click(function () { + fn_saveOrdNo(); + }); + // 기간 선택 콤보 이벤트 const target = $("#webTreatmentPetitSearchDateType").siblings("ul.select_option_list"); target.find("li.option_list_item").click(function () { diff --git a/src/main/resources/templates/web/contentsBbs/ContentsBbsSelectList.html b/src/main/resources/templates/web/contentsBbs/ContentsBbsSelectList.html index 3a3331e..c80d152 100644 --- a/src/main/resources/templates/web/contentsBbs/ContentsBbsSelectList.html +++ b/src/main/resources/templates/web/contentsBbs/ContentsBbsSelectList.html @@ -73,6 +73,10 @@
+ @@ -98,7 +102,7 @@ - + \ No newline at end of file