접수 저장 및 메시지 처리

This commit is contained in:
pjs
2026-01-28 00:59:29 +09:00
parent 50d2f05404
commit b9f1419e5e
12 changed files with 319 additions and 17 deletions

View File

@@ -0,0 +1,24 @@
package com.madeu.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Configuration;
import com.madeu.util.MessageUtils;
import jakarta.annotation.PostConstruct;
@Configuration
public class MessageConfig {
private final MessageSource messageSource;
public MessageConfig(MessageSource messageSource) {
this.messageSource = messageSource;
}
@PostConstruct
public void init() {
// 여기서 딱 한 번 MessageUtils의 static 필드에 값을 셋팅합니다.
MessageUtils.setMessageSource(messageSource);
}
}

View File

@@ -39,6 +39,8 @@ public interface Constants {
static final public String EBS_ID_UNEQUAL = "410"; // 사용자 정보가 없습니다. static final public String EBS_ID_UNEQUAL = "410"; // 사용자 정보가 없습니다.
static final public String SERVER_ERROR = "서버 오류가 발생했습니다."; //서버 오류가 발생했습니다. static final public String SERVER_ERROR = "서버 오류가 발생했습니다."; //서버 오류가 발생했습니다.
static final public String MSG_0001 = "접수되었습니다! 안내데스크에서 확인 후 바로 안내해 드릴게요. 잠시만 기다려 주세요.";
static final public String MSG_0002 = "오늘 예약은 확인되었습니다만, 현재 방문하신 시간이 예약 시간과 차이가 있어 안내데스크의 확인이 필요합니다. 데스크로 문의해 주시면 친절히 안내해 드리겠습니다.";
} }

View File

@@ -238,11 +238,12 @@ public class KioskController extends ManagerDraftAction {
/** /**
* 고객 등록 * 고객 등록
* @throws Exception
*/ */
@PostMapping("/kiosk/putSubmit.do") @PostMapping("/kiosk/putSubmit.do")
public KioskDTO putSubmit(@RequestBody KioskDTO dto) { public KioskDTO putSubmit(@RequestBody KioskDTO dto) throws Exception {
System.out.println("putSubmit getMuUserId:::: " + dto.getMuUserId());
return null; return kioskService.putSubmit(dto);
} }
/** /**

View File

@@ -8,7 +8,8 @@ import lombok.ToString;
@Setter @Setter
@ToString @ToString
public class KioskDTO { public class KioskDTO {
private String userNumber; // 고객 private String muUserId; // 고객ID
private String userNumber; // 고객번호
private String userName; // 고객명 private String userName; // 고객명
private String birthday; // 생년월일 (YYYYMMDD) private String birthday; // 생년월일 (YYYYMMDD)
private String gender; // 성별 (M/F) private String gender; // 성별 (M/F)

View File

@@ -0,0 +1,80 @@
package com.madeu.crm.kiosk.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
@Getter
@Setter
@ToString
public class ReserveDTO {
private String muReserveId; // 식별자
private String userName; // 고객 이름
private String muUserId; // 고객 식별자
private LocalDate reserveDate; // 예약날짜
private LocalTime reserveTime; // 예약시간
private String reserveCategoryItemId; // 예약처 카테고리 식별자
private String reserveCategoryItemName;// 예약처 카테고리 이름
private String reserveAppYn; // 앱예약 유무 (Y/N)
private String reserveNaverYn; // 네이버 예약 유무 (Y/N)
private String muTreatmentId; // 진료 식별자
private String treatmentName; // 진료명
private String muTreatmentProcedureId; // 진료 시술 식별자
private String treatmentProcedureName; // 진료 시술명
private String reserveMemberId; // 의사, 상담자 식별자
private String muMemberId; // 담당자 식별자
private String etc; // 메모
private String status; // 상태 (T, TN, R, RW, RN, G, Y)
private String status2; // 수납상태 (N, Y, C, P, R)
private String userCheckYn; // 사용자 확인 여부
private LocalDate writeDate; // 작성일자
private LocalTime writeTime; // 작성시간
private String remark; // 비고
private String cudFlag; // 작업타입 (C, U, D)
private String useYn; // 사용여부
private String regId; // 등록자
private LocalDateTime regDate; // 등록일자
private String modId; // 수정자
private LocalDateTime modDate; // 수정일자
private String tId; // T_ID
private LocalDateTime tDate; // T_DATE
private LocalDateTime receptionDate; // 접수시간
private String phoneNumber; // 고객 전화번호
// 네이버 예약 관련 필드
private String naverReservationKey; // 네이버 예약 상품 키값
private String naverBookingKey; // 네이버 예약 키값
private String naverDateTime; // 네이버 예약 일자 및 시간
private String naverName; // 네이버 예약 예약자 이름
private String naverPhone; // 네이버 예약 예약자 전화번호
private String naverState; // 네이버 예약상태
private String naverUserId; // 네이버 예약 사용자 아이디
// 기존 CRM DB 연동 필드
private String crmMemberSchedulePid; // 기존 DB 식별자
private String crmMemberScheduleMbPid; // 기존 DB 고객 식별자
private String crmMemberScheduleMbHp; // 기존 DB 고객 전화번호
private String crmMemberScheduleResPid; // 기존 DB 예약종류 식별자
private String crmMemberScheduleResPid2; // 기존 DB 시술분류 식별자
private String crmMemberScheduleResPid3;
private String crmMemberScheduleResPid4;
private String crmMemberScheduleResPidName; // 기존 DB 예약종류 이름
private String crmMemberScheduleResPid2Name; // 기존 DB 시술분류 이름
private String crmMemberScheduleResPid3Name;
private String crmMemberScheduleResPid4Name;
private String crmMemberScheduleResEtc; // 기존 DB 시술분류 비고
private String crmMemberScheduleRStaff3; // 기존 DB 시술의사 식별자
private String crmMemberScheduleRStaff3Icon;
private String crmMemberScheduleRStaff3Name; // 기존 DB 시술의사 이름
private String crmMemberScheduleResConsult; // 기존 DB 상담자 식별자
private String crmMemberScheduleResConsultName;
private String crmMemberScheduleResAccept; // 기존 DB 담당자 식별자
private String crmMemberScheduleResAcceptName;
private String crmMemberScheduleResState; // 기존 DB 예약상태
private String reserveHomepageYn; // 홈페이지 예약 여부
private String id;
}

View File

@@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Mapper;
import com.madeu.crm.kiosk.dto.ConsentFormDTO; import com.madeu.crm.kiosk.dto.ConsentFormDTO;
import com.madeu.crm.kiosk.dto.KioskDTO; import com.madeu.crm.kiosk.dto.KioskDTO;
import com.madeu.crm.kiosk.dto.ReserveDTO;
import com.madeu.crm.kiosk.dto.UserDTO; import com.madeu.crm.kiosk.dto.UserDTO;
@Mapper @Mapper
@@ -50,4 +51,10 @@ public interface KioskMAP {
int insertUser(UserDTO dto); int insertUser(UserDTO dto);
List<KioskDTO> selectUserByPhoneNumber(KioskDTO dto); List<KioskDTO> selectUserByPhoneNumber(KioskDTO dto);
List<ReserveDTO> selectReserveByMuUserId(KioskDTO dto);
int updateReserveStatus(ReserveDTO dto);
int insertReserve(ReserveDTO dto);
} }

View File

@@ -1,21 +1,27 @@
package com.madeu.crm.kiosk.service; package com.madeu.crm.kiosk.service;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import com.madeu.constants.Constants; import com.madeu.constants.Constants;
import com.madeu.crm.kiosk.dto.ConsentFormDTO; import com.madeu.crm.kiosk.dto.ConsentFormDTO;
import com.madeu.crm.kiosk.dto.KioskDTO; import com.madeu.crm.kiosk.dto.KioskDTO;
import com.madeu.crm.kiosk.dto.ReserveDTO;
import com.madeu.crm.kiosk.dto.UserDTO; import com.madeu.crm.kiosk.dto.UserDTO;
import com.madeu.crm.kiosk.map.KioskMAP; import com.madeu.crm.kiosk.map.KioskMAP;
import com.madeu.dao.web.webuser.WebUserSqlMapDAO; import com.madeu.dao.web.webuser.WebUserSqlMapDAO;
import com.madeu.util.MessageUtils;
import com.madeu.util.ValidationCheckUtil; import com.madeu.util.ValidationCheckUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -29,6 +35,7 @@ public class KioskService {
@Autowired @Autowired
private WebUserSqlMapDAO webUserSqlMapDAO; private WebUserSqlMapDAO webUserSqlMapDAO;
/** /**
* 진료 리스트 조회 (option) * 진료 리스트 조회 (option)
*/ */
@@ -314,6 +321,13 @@ public class KioskService {
return kioskMAP.selectConsentForm(dto); return kioskMAP.selectConsentForm(dto);
} }
/**
* 폰번호로 사용자정보 조회
* @param dto
* @return
* @throws Exception
*/
public HashMap<String, Object> getUserByPhoneNumber(KioskDTO dto) throws Exception { public HashMap<String, Object> getUserByPhoneNumber(KioskDTO dto) throws Exception {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
@@ -333,7 +347,59 @@ public class KioskService {
return map; return map;
} }
public KioskDTO putSubmit(KioskDTO dto) throws Exception {
LocalTime now = LocalTime.now();
/**
* 1. 예약된사람인지 확인 - 예약이 여러건일수도 있음.
* 2. 동의서 1년이 경과했는지 확인
* 3. 예약 > 접수 가능 시간은 예약시간으로 앞뒤 한시간으로 정함
* 4.
*/
// 예약시간으로부터 앞뒤 한시간안에 해당 muUserId로 예약한 건이 있는지 조회
List<ReserveDTO> reserveList = kioskMAP.selectReserveByMuUserId(dto);
if (ObjectUtils.isEmpty(reserveList)) {
String muReserveId = ("R").concat(String.valueOf(System.currentTimeMillis()));
ReserveDTO insertDto = new ReserveDTO();
insertDto.setMuReserveId(muReserveId);
insertDto.setUserName(dto.getUserName());
insertDto.setMuUserId(dto.getMuUserId());
insertDto.setStatus("RW");
insertDto.setRegId("kiosk");;
kioskMAP.insertReserve(insertDto);
dto.setMsgCode(Constants.OK);
dto.setMsgDesc(MessageUtils.getMessage("reserve.checkin.success", dto.getUserName()));
} else {
for (ReserveDTO reserveDTO : reserveList) {
LocalTime reserveTime = reserveDTO.getReserveTime();
// 3. 현재 시간과 예약 시간의 차이 계산 (절댓값)
long minutesBetween = Math.abs(ChronoUnit.MINUTES.between(now, reserveTime));
if (minutesBetween <= 60) {
reserveDTO.setStatus("R"); //접수
kioskMAP.updateReserveStatus(reserveDTO);
dto.setMsgCode(Constants.OK);
dto.setMsgDesc(MessageUtils.getMessage("reserve.checkin.welcome", dto.getUserName()));
} else {
dto.setMsgCode(Constants.OK);
dto.setMsgDesc(MessageUtils.getMessage("reserve.checkin.time-mismatch", dto.getUserName()));
return dto;
}
}
}
return dto;
}

View File

@@ -0,0 +1,19 @@
package com.madeu.util;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
public class MessageUtils {
// static 필드
private static MessageSource messageSource;
// 외부(Config)에서 호출하여 주입할 메서드
public static void setMessageSource(MessageSource messageSource) {
MessageUtils.messageSource = messageSource;
}
public static String getMessage(String code, Object... args) {
if (messageSource == null) return code; // 초기화 전이라면 키값 그대로 반환
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}

View File

@@ -16,6 +16,19 @@ spring:
aop: aop:
proxy-target-class: false proxy-target-class: false
messages:
# 메시지 파일의 경로와 기본 파일명 (src/main/resources 기준)
basename: messages
# 인코딩 설정 (한글 깨짐 방지를 위해 UTF-8 권장)
encoding: UTF-8
# 메시지 파일을 찾지 못했을 때 시스템 언어를 사용할지 여부
fallback-to-system-locale: true
# 설정한 로케일에 해당하는 파일이 없어도 에러를 내지 않고 기본 파일을 사용함
use-code-as-default-message: true
# 메시지 변경 시 새로고침 주기 (초 단위, -1은 캐싱)
cache-duration: 3600
server: server:
encoding: encoding:
charset: UTF-8 charset: UTF-8

View File

@@ -710,4 +710,56 @@
ORDER BY CONSENT_FORM_VERSION DESC ORDER BY CONSENT_FORM_VERSION DESC
LIMIT 1 LIMIT 1
</select> </select>
<select id="selectReserveByMuUserId" parameterType="com.madeu.crm.kiosk.dto.KioskDTO" resultType="com.madeu.crm.kiosk.dto.ReserveDTO">
SELECT MU_RESERVE_ID
,RESERVE_TIME
FROM MU_RESERVE
WHERE MU_USER_ID = #{muUserId} -- 찾으려는 고객 ID
AND RESERVE_DATE = CURDATE() -- 오늘 날짜
AND USE_YN = 'Y' -- 사용 중인 데이터
AND STATUS = 'T'
</select>
<update id="updateReserveStatus" parameterType="com.madeu.crm.kiosk.dto.ReserveDTO">
UPDATE MU_RESERVE
SET STATUS = #{status}
WHERE MU_RESERVE_ID = #{muReserveId} -- 찾으려는 예약 ID
AND USE_YN = 'Y' -- 사용 중인 데이터
AND STATUS = 'T'
</update>
<update id="insertReserve" parameterType="com.madeu.crm.kiosk.dto.ReserveDTO">
<selectKey resultType="string" keyProperty="id" order="BEFORE">
SELECT CONCAT(#{muReserveId},LPAD((SELECT NEXTVAL(MU_RESERVE_SEQ)), 11, 0))
</selectKey>
INSERT INTO MU_RESERVE (
MU_RESERVE_ID,
USER_NAME,
MU_USER_ID,
RESERVE_DATE,
RESERVE_TIME,
STATUS,
WRITE_DATE,
WRITE_TIME,
CUD_FLAG,
USE_YN,
REG_ID,
MOD_ID
) VALUES (
#{id},
#{userName},
#{muUserId},
CURDATE(),
CURTIME(),
#{status},
CURDATE(),
CURTIME(),
'C',
'Y',
#{regId},
#{regId}
)
</update>
</mapper> </mapper>

View File

@@ -0,0 +1,9 @@
# 공통 오류
common.error.server=서버 오류가 발생했습니다.
# 예약/접수 관련 (Reservation)
reserve.checkin.success=접수되었습니다! 안내데스크에서 확인 후 바로 안내해 드릴게요. 잠시만 기다려 주세요.
reserve.checkin.time-mismatch=오늘 예약은 확인되었습니다만, 방문하신 시간이 예약 시간과 차이가 있어 데스크 확인이 필요합니다. 안내데스크로 문의해 주세요.
# 만약 파라미터를 쓴다면 (나중을 위해)
reserve.checkin.welcome={0}님, 접수가 완료되었습니다. 잠시만 기다려 주세요.

View File

@@ -251,7 +251,7 @@
let html = ""; let html = "";
if( res.msgCode == 0 ){ if( res.msgCode == 0 ){
const userList = res.list; const userList = res.list;
console.log(userList);
if (!userList || userList.length === 0) { if (!userList || userList.length === 0) {
alert("조회된 정보가 없습니다."); alert("조회된 정보가 없습니다.");
return; return;
@@ -260,7 +260,7 @@
userList.forEach((user, index) => { userList.forEach((user, index) => {
html += ` html += `
<tr> <tr>
<td><input type="radio" name="selectedUser" class="user-radio" value="${user.userNumber}" ${index === 0 ? 'checked' : ''}></td> <td><input type="radio" name="selectedUser" class="user-radio" value="${user.muUserId}" ${index === 0 ? 'checked' : ''}></td>
<td class="user-name-cell">${user.userName}</td> <td class="user-name-cell">${user.userName}</td>
<td>${user.birthday || '-'}</td> <td>${user.birthday || '-'}</td>
<td>${user.gender === 'M' ? '남' : (user.gender === 'F' ? '여' : '-')}</td> <td>${user.gender === 'M' ? '남' : (user.gender === 'F' ? '여' : '-')}</td>
@@ -284,13 +284,41 @@
function submitBtn() { function submitBtn() {
const selectedUser = $("input[name='selectedUser']:checked"); const selectedUser = $("input[name='selectedUser']:checked");
// 1. 선택 여부 확인
if (selectedUser.length === 0) { if (selectedUser.length === 0) {
alert("접수할 고객을 선택해 주세요."); alert("접수할 고객을 선택해 주세요.");
return; return;
} }
const userName = selectedUser.val();
alert(userName + "님 접수가 완료되었습니다."); // 2. 선택된 사용자의 식별값 (userNumber) 가져오기
const muUserId = selectedUser.val();
const userName = selectedUser.closest('tr').find('.user-name-cell').text();
// 3. 서버로 접수 정보 전송 (AJAX)
$.ajax({
url: '/kiosk/putSubmit.do', // 실제 서버의 접수 처리 URL로 변경하세요
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
muUserId: muUserId,
userName: userName
}),
success: function(res) {
if (res.msgCode == 0) {
alert(res.msgDesc);
$("#customerDialog").dialog("close"); $("#customerDialog").dialog("close");
// 접수 완료 후 메인 페이지로 이동하거나 초기화
location.href = "/kiosk";
} else {
alert(res.msgDesc);
}
},
error: function() {
alert("서버 통신 중 오류가 발생했습니다.");
}
});
} }
function moveKiosk() { function moveKiosk() {