diff --git a/.gitignore b/.gitignore index 3dae940..25f9002 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,9 @@ Thumbs.db .settings/org.eclipse.jdt.core.prefs .settings/org.eclipse.buildship.core.prefs .classpath + +# Wiki repo (별도 git 리포) +.wiki/ + +# Agent workflows +.agent/ diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs index 7b8f972..a6350f0 100644 --- a/.settings/org.eclipse.buildship.core.prefs +++ b/.settings/org.eclipse.buildship.core.prefs @@ -1,13 +1,13 @@ -arguments= +arguments=--init-script C\:\\Users\\bd091\\AppData\\Roaming\\Antigravity\\User\\globalStorage\\redhat.java\\1.50.0\\config_win\\org.eclipse.osgi\\58\\0\\.cp\\gradle\\init\\init.gradle --init-script C\:\\Users\\bd091\\AppData\\Roaming\\Antigravity\\User\\globalStorage\\redhat.java\\1.50.0\\config_win\\org.eclipse.osgi\\58\\0\\.cp\\gradle\\protobuf\\init.gradle auto.sync=false build.scans.enabled=false connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 gradle.user.home= -java.home= +java.home=C\:/Program Files/Java/jdk-21 jvm.arguments= offline.mode=false -override.workspace.settings=false -show.console.view=false -show.executions.view=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/src/main/java/com/madeu/batch/InsertPublicHolidayBatchExcute.java b/src/main/java/com/madeu/batch/InsertPublicHolidayBatchExcute.java index cc6f5e2..1904a87 100644 --- a/src/main/java/com/madeu/batch/InsertPublicHolidayBatchExcute.java +++ b/src/main/java/com/madeu/batch/InsertPublicHolidayBatchExcute.java @@ -50,7 +50,7 @@ public class InsertPublicHolidayBatchExcute { * [임시 실행용] 서버 시작(또는 리로드) 시 배치를 즉시 1회 실행합니다. * 실행이 완료된 후에는 다시 주석 처리하거나 삭제하세요. */ - @EventListener(ContextRefreshedEvent.class) + // @EventListener(ContextRefreshedEvent.class) public void forceRunBatch() { log.info("============================================================================"); log.info("============== [FORCE START] Public Holiday Batch Execution =============="); diff --git a/src/main/java/com/madeu/controller/web/webhospital/WebHospitalController.java b/src/main/java/com/madeu/controller/web/webhospital/WebHospitalController.java index f6801c2..ef8d0b7 100644 --- a/src/main/java/com/madeu/controller/web/webhospital/WebHospitalController.java +++ b/src/main/java/com/madeu/controller/web/webhospital/WebHospitalController.java @@ -360,4 +360,73 @@ public class WebHospitalController extends ManagerDraftAction { log.debug("WebHospitalController deleteHospitalSchedule END"); return HttpUtil.makeHashToJsonModelAndView(map); } + + /** + * 병원 지정 휴일 개별 저장 (insert or update) + */ + @RequestMapping(value = "/webhospital/saveHospitalHoliday.do") + public ModelAndView saveHospitalHoliday(HttpSession session, HttpServletRequest request, + HttpServletResponse response) { + log.debug("WebHospitalController saveHospitalHoliday START"); + HashMap paramMap = HttpUtil.getParameterMap(request); + HashMap map = new HashMap(); + + try { + if (!webCheckLogin(session)) { + return null; + } else { + paramMap.put("loginMemberId", String.valueOf(session.getAttribute("loginMemberId"))); + paramMap.put("regId", String.valueOf(session.getAttribute("loginMemberId"))); + paramMap.put("modId", String.valueOf(session.getAttribute("loginMemberId"))); + map = webHospitalService.saveHospitalHoliday(paramMap); + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (Constants.OK != map.get("msgCode")) { + map.put("msgCode", Constants.FAIL); + map.put("success", false); + if (null == map.get("msgDesc") || ("").equals(map.get("msgDesc"))) { + map.put("msgDesc", "정상적으로 수행되지 않았습니다. 관리자에게 문의하시기 바랍니다."); + } + } + } + log.debug("WebHospitalController saveHospitalHoliday END"); + return HttpUtil.makeHashToJsonModelAndView(map); + } + + /** + * 병원 지정 휴일 선택 삭제 (체크된 row 일괄 삭제) + */ + @RequestMapping(value = "/webhospital/deleteHospitalHolidays.do") + public ModelAndView deleteHospitalHolidays(HttpSession session, HttpServletRequest request, + HttpServletResponse response) { + log.debug("WebHospitalController deleteHospitalHolidays START"); + HashMap paramMap = HttpUtil.getParameterMap(request); + HashMap map = new HashMap(); + + try { + if (!webCheckLogin(session)) { + return null; + } else { + paramMap.put("loginMemberId", String.valueOf(session.getAttribute("loginMemberId"))); + paramMap.put("modId", String.valueOf(session.getAttribute("loginMemberId"))); + map = webHospitalService.deleteHospitalHolidays(paramMap); + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (Constants.OK != map.get("msgCode")) { + map.put("msgCode", Constants.FAIL); + map.put("success", false); + if (null == map.get("msgDesc") || ("").equals(map.get("msgDesc"))) { + map.put("msgDesc", "정상적으로 수행되지 않았습니다. 관리자에게 문의하시기 바랍니다."); + } + } + } + log.debug("WebHospitalController deleteHospitalHolidays END"); + return HttpUtil.makeHashToJsonModelAndView(map); + } } diff --git a/src/main/java/com/madeu/service/web/webhospital/WebHospitalService.java b/src/main/java/com/madeu/service/web/webhospital/WebHospitalService.java index 5995609..9541b76 100644 --- a/src/main/java/com/madeu/service/web/webhospital/WebHospitalService.java +++ b/src/main/java/com/madeu/service/web/webhospital/WebHospitalService.java @@ -19,4 +19,8 @@ public interface WebHospitalService { public HashMap saveHospitalSchedule(HashMap paramMap) throws Exception; public HashMap deleteHospitalSchedule(HashMap paramMap) throws Exception; + + public HashMap saveHospitalHoliday(HashMap paramMap) throws Exception; + + public HashMap deleteHospitalHolidays(HashMap paramMap) throws Exception; } diff --git a/src/main/java/com/madeu/service/web/webhospital/impl/WebHospitalServiceImpl.java b/src/main/java/com/madeu/service/web/webhospital/impl/WebHospitalServiceImpl.java index bf435c6..ca0c558 100644 --- a/src/main/java/com/madeu/service/web/webhospital/impl/WebHospitalServiceImpl.java +++ b/src/main/java/com/madeu/service/web/webhospital/impl/WebHospitalServiceImpl.java @@ -8,10 +8,6 @@ import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.*; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -715,39 +711,6 @@ public class WebHospitalServiceImpl implements WebHospitalService { webHospitalSqlMapDAO.updateHospital(paramMap); - // 휴일정보 삭제 - webHospitalHolidaySqlMapDAO.deleteHospitalHoliday(paramMap); - - // 휴일정보 등록 - JSONParser jsonParser = new JSONParser(); - JSONObject jsonObject = (JSONObject) jsonParser.parse(String.valueOf(paramMap.get("holidayRows"))); - JSONArray detailArray = (JSONArray) jsonObject.get("data"); - - for (int j = 0; j < detailArray.size(); j++) { - JSONObject detailObject = (JSONObject) detailArray.get(j); - - String hospitalHolidayName = String.valueOf(detailObject.get("hospitalHolidayName")); - String locDate = String.valueOf(detailObject.get("locDate")); - String repeatYn = String.valueOf(detailObject.get("repeatYn")); - - if ((null != hospitalHolidayName && !("").equals(hospitalHolidayName)) - || (null != locDate && !("").equals(locDate)) - || (null != repeatYn && !("").equals(repeatYn))) { - HashMap holidayParamMap = new HashMap(); - String muHospitalHolidayId = ("HH").concat(String.valueOf(System.currentTimeMillis())); - holidayParamMap.put("muHospitalHolidayId", muHospitalHolidayId); - holidayParamMap.put("muHospitalId", paramMap.get("muHospitalId")); - holidayParamMap.put("hospitalHolidayName", hospitalHolidayName); - holidayParamMap.put("locDate", locDate); - holidayParamMap.put("repeatYn", repeatYn); - holidayParamMap.put("useYn", "Y"); - holidayParamMap.put("regId", paramMap.get("regId")); - holidayParamMap.put("modId", paramMap.get("modId")); - holidayParamMap.put("tId", paramMap.get("tId")); - holidayParamMap.put("tDate", paramMap.get("tDate")); - webHospitalHolidaySqlMapDAO.insertHospitalHoliday(holidayParamMap); - } - } map.put("msgCode", Constants.OK); map.put("msgDesc", "수정되었습니다."); } @@ -826,4 +789,62 @@ public class WebHospitalServiceImpl implements WebHospitalService { } return map; } + + /** + * 병원 지정 휴일 개별 저장 (insert or update) + */ + @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class }) + public HashMap saveHospitalHoliday(HashMap paramMap) throws Exception { + log.debug("WebHospitalServiceImpl saveHospitalHoliday START"); + HashMap map = new HashMap<>(); + try { + String muHospitalHolidayId = String.valueOf(paramMap.get("muHospitalHolidayId")); + if (muHospitalHolidayId != null && !muHospitalHolidayId.isEmpty() && !"null".equals(muHospitalHolidayId)) { + // 기존 row 수정 + webHospitalHolidaySqlMapDAO.updateHospitalHoliday(paramMap); + } else { + // 신규 row 등록 + paramMap.put("muHospitalHolidayId", "HH"); + webHospitalHolidaySqlMapDAO.insertHospitalHoliday(paramMap); + } + map.put("msgCode", Constants.OK); + map.put("msgDesc", "저장되었습니다."); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + log.debug("WebHospitalServiceImpl saveHospitalHoliday END"); + return map; + } + + /** + * 병원 지정 휴일 선택 삭제 (체크된 row 일괄 삭제) + */ + @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class }) + public HashMap deleteHospitalHolidays(HashMap paramMap) throws Exception { + log.debug("WebHospitalServiceImpl deleteHospitalHolidays START"); + HashMap map = new HashMap<>(); + try { + String holidayIds = String.valueOf(paramMap.get("holidayIds")); + if (holidayIds != null && !holidayIds.isEmpty() && !"null".equals(holidayIds)) { + String[] ids = holidayIds.split(","); + for (String id : ids) { + HashMap delMap = new HashMap<>(); + delMap.put("muHospitalId", paramMap.get("muHospitalId")); + delMap.put("muHospitalHolidayId", id.trim()); + delMap.put("modId", paramMap.get("modId")); + webHospitalHolidaySqlMapDAO.deleteHospitalHoliday(delMap); + } + } + map.put("msgCode", Constants.OK); + map.put("msgDesc", "삭제되었습니다."); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + log.debug("WebHospitalServiceImpl deleteHospitalHolidays END"); + return map; + } } diff --git a/src/main/resources/mappers/WebHospitalHolidaySqlMap.xml b/src/main/resources/mappers/WebHospitalHolidaySqlMap.xml index ae91519..c2bc216 100644 --- a/src/main/resources/mappers/WebHospitalHolidaySqlMap.xml +++ b/src/main/resources/mappers/WebHospitalHolidaySqlMap.xml @@ -81,6 +81,7 @@ ,USE_YN = 'N' WHERE USE_YN = 'Y' AND MU_HOSPITAL_ID = #{muHospitalId} + AND MU_HOSPITAL_HOLIDAY_ID = #{muHospitalHolidayId} \ No newline at end of file diff --git a/src/main/resources/mappers/WebHospitalSqlMap.xml b/src/main/resources/mappers/WebHospitalSqlMap.xml index 41b3638..72e157c 100644 --- a/src/main/resources/mappers/WebHospitalSqlMap.xml +++ b/src/main/resources/mappers/WebHospitalSqlMap.xml @@ -5,6 +5,7 @@ @@ -71,21 +75,20 @@ ,CASE WHEN EXISTS ( SELECT 1 - FROM MU_HOSPITAL_HOLIDAY MH - WHERE MH.USE_YN = 'Y' + FROM MU_HOSPITAL_HOLIDAY MHH + WHERE MHH.USE_YN = 'Y' + AND MHH.MU_HOSPITAL_ID = MH.MU_HOSPITAL_ID AND ( - (MH.REPEAT_YN = 'Y' AND DATE_FORMAT(MH.LOC_DATE, '%m-%d') = DATE_FORMAT(#{searchDate}, '%m-%d')) + (MHH.REPEAT_YN = 'Y' AND DATE_FORMAT(MHH.LOC_DATE, '%m-%d') = DATE_FORMAT(#{searchDate}, '%m-%d')) OR - (MH.REPEAT_YN = 'N' AND MH.LOC_DATE = #{searchDate}) + (MHH.REPEAT_YN = 'N' AND MHH.LOC_DATE = #{searchDate}) )) OR - EXISTS ( + (MH.PUBLIC_HOLIDAY_USE_YN = 'Y' AND EXISTS ( SELECT 1 FROM MU_PUBLIC_HOLIDAY MPH - JOIN MU_HOSPITAL - ON PUBLIC_HOLIDAY_USE_YN='Y' WHERE MPH.USE_YN = 'Y' AND MPH.LOC_DATE = #{searchDate} - ) + )) THEN 'Y' ELSE 'N' END AS "holidayYn" @@ -147,6 +150,9 @@ AND MHS.SCHEDULE_DATE = #{searchDate} AND MHS.USE_YN = 'Y' WHERE MH.USE_YN = 'Y' + + AND MH.CENTER_DIV_CD = #{centerDivCd} + LIMIT 0, 1 @@ -188,21 +194,20 @@ END AS OPEN_YN ,CASE WHEN EXISTS( - SELECT 1 - FROM MU_HOSPITAL_HOLIDAY AS MH - WHERE MH.USE_YN = 'Y' - AND ((MH.REPEAT_YN = 'Y' AND DATE_FORMAT(MH.LOC_DATE, '%m-%d') = DATE_FORMAT(TTD.RESULT_DATE, '%m-%d')) - OR - (MH.REPEAT_YN = 'N' AND MH.LOC_DATE = TTD.RESULT_DATE)) - ) - OR EXISTS( - SELECT 1 - FROM MU_PUBLIC_HOLIDAY AS MPH - JOIN MU_HOSPITAL - ON PUBLIC_HOLIDAY_USE_YN='Y' - WHERE MPH.USE_YN = 'Y' - AND MPH.LOC_DATE = TTD.RESULT_DATE + SELECT 1 + FROM MU_HOSPITAL_HOLIDAY AS MHH + WHERE MHH.USE_YN = 'Y' + AND MHH.MU_HOSPITAL_ID = MH.MU_HOSPITAL_ID + AND ((MHH.REPEAT_YN = 'Y' AND DATE_FORMAT(MHH.LOC_DATE, '%m-%d') = DATE_FORMAT(TTD.RESULT_DATE, '%m-%d')) + OR + (MHH.REPEAT_YN = 'N' AND MHH.LOC_DATE = TTD.RESULT_DATE)) ) + OR (MH.PUBLIC_HOLIDAY_USE_YN = 'Y' AND EXISTS( + SELECT 1 + FROM MU_PUBLIC_HOLIDAY AS MPH + WHERE MPH.USE_YN = 'Y' + AND MPH.LOC_DATE = TTD.RESULT_DATE + )) THEN 'Y' ELSE 'N' END AS HOLIDAY_YN @@ -213,7 +218,10 @@ ORDER BY TTD.RESULT_DATE ASC ) AS TTD LEFT JOIN MU_HOSPITAL AS MH - ON 1 = 1 + ON MH.USE_YN = 'Y' + + AND MH.CENTER_DIV_CD = #{centerDivCd} + ) AS TTD LEFT JOIN MU_HOSPITAL_SCHEDULE MHS ON MHS.SCHEDULE_DATE = TTD.RESULT_DATE @@ -387,4 +395,5 @@ WHERE USE_YN = 'Y' AND MU_HOSPITAL_ID = #{muHospitalId} + \ No newline at end of file diff --git a/src/main/resources/sql/center_div_migration.sql b/src/main/resources/sql/center_div_migration.sql new file mode 100644 index 0000000..ede2aa0 --- /dev/null +++ b/src/main/resources/sql/center_div_migration.sql @@ -0,0 +1,38 @@ +-- ================================================================ +-- 센터구분(CENTER_DIV_CD) 컬럼 추가 및 쁘띠센터 행 생성 마이그레이션 +-- ================================================================ + +-- 1. 센터구분 컬럼 추가 +ALTER TABLE MU_HOSPITAL ADD COLUMN CENTER_DIV_CD VARCHAR(10) DEFAULT 'DIET' COMMENT '센터구분(DIET/PETIT)' AFTER HOSPITAL_NAME; + +-- 2. 기존 행을 다이어트센터로 설정 +UPDATE MU_HOSPITAL SET CENTER_DIV_CD = 'DIET' WHERE USE_YN = 'Y'; + +-- 3. 쁘띠센터 행 생성 (기존 다이어트 운영시간을 복사, 운영시간은 별도 설정 필요) +INSERT INTO MU_HOSPITAL ( + MU_HOSPITAL_ID, HOSPITAL_NAME, CENTER_DIV_CD, + MON_OPEN_YN, MON_OPEN_START_TIME, MON_OPEN_END_TIME, MON_BREAK_START_TIME, MON_BREAK_END_TIME, + TUE_OPEN_YN, TUE_OPEN_START_TIME, TUE_OPEN_END_TIME, TUE_BREAK_START_TIME, TUE_BREAK_END_TIME, + WED_OPEN_YN, WED_OPEN_START_TIME, WED_OPEN_END_TIME, WED_BREAK_START_TIME, WED_BREAK_END_TIME, + THU_OPEN_YN, THU_OPEN_START_TIME, THU_OPEN_END_TIME, THU_BREAK_START_TIME, THU_BREAK_END_TIME, + FRI_OPEN_YN, FRI_OPEN_START_TIME, FRI_OPEN_END_TIME, FRI_BREAK_START_TIME, FRI_BREAK_END_TIME, + SAT_OPEN_YN, SAT_OPEN_START_TIME, SAT_OPEN_END_TIME, SAT_BREAK_START_TIME, SAT_BREAK_END_TIME, + SUN_OPEN_YN, SUN_OPEN_START_TIME, SUN_OPEN_END_TIME, SUN_BREAK_START_TIME, SUN_BREAK_END_TIME, + PUBLIC_HOLIDAY_USE_YN, MU_MEMBER_ID, + WRITE_DATE, WRITE_TIME, CUD_FLAG, USE_YN, REG_ID, REG_DATE, MOD_ID, MOD_DATE +) +SELECT + CONCAT(LEFT(MU_HOSPITAL_ID, 24), '2'), -- 새 ID 생성 + HOSPITAL_NAME, 'PETIT', + MON_OPEN_YN, MON_OPEN_START_TIME, MON_OPEN_END_TIME, MON_BREAK_START_TIME, MON_BREAK_END_TIME, + TUE_OPEN_YN, TUE_OPEN_START_TIME, TUE_OPEN_END_TIME, TUE_BREAK_START_TIME, TUE_BREAK_END_TIME, + WED_OPEN_YN, WED_OPEN_START_TIME, WED_OPEN_END_TIME, WED_BREAK_START_TIME, WED_BREAK_END_TIME, + THU_OPEN_YN, THU_OPEN_START_TIME, THU_OPEN_END_TIME, THU_BREAK_START_TIME, THU_BREAK_END_TIME, + FRI_OPEN_YN, FRI_OPEN_START_TIME, FRI_OPEN_END_TIME, FRI_BREAK_START_TIME, FRI_BREAK_END_TIME, + SAT_OPEN_YN, SAT_OPEN_START_TIME, SAT_OPEN_END_TIME, SAT_BREAK_START_TIME, SAT_BREAK_END_TIME, + SUN_OPEN_YN, SUN_OPEN_START_TIME, SUN_OPEN_END_TIME, SUN_BREAK_START_TIME, SUN_BREAK_END_TIME, + PUBLIC_HOLIDAY_USE_YN, MU_MEMBER_ID, + CURDATE(), CURTIME(), 'C', 'Y', 'SYSTEM', NOW(), 'SYSTEM', NOW() +FROM MU_HOSPITAL +WHERE USE_YN = 'Y' AND CENTER_DIV_CD = 'DIET' +LIMIT 1; diff --git a/src/main/resources/static/css/web/hospital_info.css b/src/main/resources/static/css/web/hospital_info.css index 1650f03..558b54e 100644 --- a/src/main/resources/static/css/web/hospital_info.css +++ b/src/main/resources/static/css/web/hospital_info.css @@ -121,20 +121,21 @@ background: #fff; border: solid 1px #E9ECF0; border-radius: 5px; - padding: 50px; + padding: 20px 50px 50px 50px; margin-top: 20px; display: flex; - gap: 50px; + flex-wrap: wrap; + gap: 30px; } .project_wrap .content_section .hospital_wrap .center_box .info_box .info_left { - width: 50%; - min-width: 500px; + flex: 1 1 400px; + min-width: 0; } .project_wrap .content_section .hospital_wrap .center_box .info_box .info_right { - width: 50%; - min-width: 500px; + flex: 1 1 400px; + min-width: 0; } .project_wrap .content_section .hospital_wrap .center_box .info_box .info { @@ -176,7 +177,7 @@ } .project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .time_box .time_list { - width: 700px; + width: 100%; float: left; } @@ -233,7 +234,8 @@ } .project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .time_box .time_list li .day_box .day { - width: 70px; + width: 100%; + max-width: 70px; line-height: 36px; border-radius: 16px; font-size: 14px; @@ -470,7 +472,7 @@ } .project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .hospital_box .hospital_list { - width: 700px; + width: 100%; float: left; } @@ -753,10 +755,14 @@ vertical-align: top; } -.project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .hospital_box .hospital_list li button:hover { +.project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .hospital_box .hospital_list li button:not(.save_box button):hover { background: none !important; } +.project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .hospital_box .hospital_list li .save_box button:hover { + background: #2d3748 !important; +} + .project_wrap .content_section .hospital_wrap .center_box .info_box .form_box .admset_box { width: 100%; background: #fff; diff --git a/src/main/resources/static/js/web/hospital/hospitalUpdate.js b/src/main/resources/static/js/web/hospital/hospitalUpdate.js index beb87cf..c6a208e 100644 --- a/src/main/resources/static/js/web/hospital/hospitalUpdate.js +++ b/src/main/resources/static/js/web/hospital/hospitalUpdate.js @@ -5,6 +5,7 @@ function fn_selectHospitalJson(onlyOperatingHours) { let formData = new FormData(); formData.append("menuClass", menuClass); + formData.append("centerDivCd", $("#currentCenterDivCd").val() || 'DIET'); $.ajax({ url: encodeURI('/webhospital/selectHospital.do'), @@ -131,8 +132,12 @@ function fn_selectHospitalJson(onlyOperatingHours) { // 휴일 상세 정보 fn_addRow2(hospitalRows.holidayRows); - // 달력 조회 (병원 ID 확보 후 실행) - fn_selectHospitalHolidayList(); + // 달력: 이미 생성되어 있으면 이벤트만 재조회, 없으면 새로 생성 + if (window.fcCalendar) { + window.fcCalendar.refetchEvents(); + } else { + fn_selectHospitalHolidayList(); + } } } else { @@ -177,10 +182,11 @@ function fn_addRow2(detailList) { let repeatLabel = ('Y' == repeatYn) ? '반복' : '반복 안함'; addRowHtml += '
  • '; + addRowHtml += ''; // Checkbox addRowHtml += '
    '; - addRowHtml += ' '; + addRowHtml += ' '; addRowHtml += '
    '; // Name @@ -258,6 +264,7 @@ function fn_addRow(param) { let addRowHtml = ''; addRowHtml += '
  • '; + addRowHtml += ''; // Checkbox addRowHtml += '
    '; @@ -671,7 +678,6 @@ function fn_updateHospital() { formData.append("sunBreakStartTime", sunBreakStartTime); formData.append("sunBreakEndTime", sunBreakEndTime); formData.append("publicHolidayUseYn", publicHolidayUseYn); - formData.append("holidayRows", JSON.stringify(detailArray)); $.ajax({ url: encodeURI('/webhospital/updateHospital.do'), @@ -684,7 +690,7 @@ function fn_updateHospital() { success: function (data) { if ('0' == data.msgCode) { modalEvent.success("수정 성공", data.msgDesc, function () { - fn_reload(); + fn_selectHospitalJson(true); }); } else { @@ -744,16 +750,38 @@ function fn_pageInit() { // 탭 전환 시 캘린더 리사이즈 (풀캘린더 v6) $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { if (e.target.hash === '#schedule') { - if (window.calendar) { - window.calendar.render(); + if (window.fcCalendar) { + window.fcCalendar.render(); } } }); + // 기본 센터: 다이어트 + $("#currentCenterDivCd").val('DIET'); + // 병원 상세 조회 fn_selectHospitalJson(); } +/**************************************************************************** +* 센터 전환 +****************************************************************************/ +function fn_switchCenter(centerDivCd) { + $("#currentCenterDivCd").val(centerDivCd); + fn_resetOperatingHoursForm(); + fn_selectHospitalJson(); +} + +/**************************************************************************** +* 운영시간 폼 초기화 +****************************************************************************/ +function fn_resetOperatingHoursForm() { + $('#checkMonOpenYn, #checkTueOpenYn, #checkWedOpenYn, #checkThuOpenYn, #checkFriOpenYn, #checkSatOpenYn, #checkSunOpenYn').prop('checked', false).trigger('change'); + $('#checkPublicHolidayUseYn').prop('checked', false); + // 병원휴일 리스트 초기화 + $('#hospitalHolidayList').empty(); +} + /**************************************************************************** * 병원 휴일 정보 조회 (달력용) @@ -822,7 +850,7 @@ function fn_selectHospitalHolidayList() { } }); calendar.render(); - window.calendar = calendar; // 전역 변수로 저장 + window.fcCalendar = calendar; // 전역 변수로 저장 } /**************************************************************************** @@ -962,7 +990,7 @@ function fn_saveSchedule() { success: function (data) { if ('0' == data.msgCode) { fn_closeSchedulePopup(); - window.calendar.refetchEvents(); // 달력 갱신 + window.fcCalendar.refetchEvents(); // 달력 갱신 } else { modalEvent.danger("오류", data.msgDesc); } @@ -991,7 +1019,7 @@ function fn_deleteSchedule() { success: function (data) { if ('0' == data.msgCode) { fn_closeSchedulePopup(); - window.calendar.refetchEvents(); // 달력 갱신 + window.fcCalendar.refetchEvents(); // 달력 갱신 } else { modalEvent.danger("오류", data.msgDesc); } @@ -1089,27 +1117,7 @@ function fn_pageEvent() { // [New] Row Remove Button (Checked items) $("#btnRemoveRow").click(function () { - let checkedRows = $("#hospitalHolidayList input[name='checkHolidayRow']:checked"); - if (checkedRows.length > 0) { - modalEvent.info("삭제", "선택한 " + checkedRows.length + "개의 항목을 삭제하시겠습니까?", function () { - checkedRows.each(function () { - $(this).closest('li').remove(); - }); - - // If no rows left, add one empty row? Or just leave header? - // fn_addRow2 logic adds header if length > 0, else calls fn_addRow. - // If we deleted all data rows, we should check if any data row exists. - // Header is li.list_title_li. Data rows are just li. - if ($("#hospitalHolidayList li").not(".list_title_li").length == 0) { - $('#hospitalHolidayList').append('
  • 지정한 휴일이 없습니다.
  • '); - } - - // Trigger DB update immediately (skip confirmation) - fn_updateHospitalHoliday(true); - }); - } else { - modalEvent.warning("알림", "삭제할 항목을 선택해주세요."); - } + fn_deleteCheckedHolidays(); }); // [New] Check All @@ -1122,115 +1130,33 @@ function fn_pageEvent() { * 병원 휴일 행별 저장 ****************************************************************************/ function fn_saveHospitalHolidayRow(btn) { - // Simply call the bulk update function which gathers all rows and saves them. - // This satisfies the "Save" action while maintaining data integrity with the backend's "Delete All -> Insert All" logic. - fn_updateHospitalHoliday(); -} - -/**************************************************************************** -* 병원 휴일 정보 수정 -****************************************************************************/ -function fn_updateHospitalHoliday() { + let $li = $(btn).closest('li'); let muHospitalId = $("#muHospitalId").val(); + let muHospitalHolidayId = $li.find('input[name="muHospitalHolidayId"]').val(); + let hospitalHolidayName = $li.find('input[name="hospitalHolidayName"]').val(); + let locDate = $li.find('input[name="dateLocDate"]').val(); + let repeatYn = $li.find('input[name="repeatYn"]').val(); - // 법정공휴일 사용 여부 - let publicHolidayUseYn = $("#checkPublicHolidayUseYn").is(":checked") ? "Y" : "N"; - - // 병원 지정 휴일 리스트 - let detailArray = new Object(); - let holidayLi = $("#hospitalHolidayList li"); - let liLength = holidayLi.length; - - let tempArray = new Array(); - for (let i = 1; i < liLength; i++) { - // Skip 'no_data' row - if (holidayLi.eq(i).hasClass('no_data')) continue; - - let hospitalHolidayName = holidayLi.eq(i).find('input[name="hospitalHolidayName"]').val(); - - // Skip empty names to prevent null insertion - if (!hospitalHolidayName || hospitalHolidayName.trim() === "") continue; - - let locDate = holidayLi.eq(i).find('input[name="dateLocDate"]').val(); - let repeatYn = holidayLi.eq(i).find('input[name="repeatYn"]').val(); - - let arr_sub = new Object(); - arr_sub.hospitalHolidayName = hospitalHolidayName; - arr_sub.locDate = locDate; - arr_sub.repeatYn = repeatYn; - tempArray.push(arr_sub); + if (!hospitalHolidayName || hospitalHolidayName.trim() === "") { + modalEvent.danger("오류", "휴일명을 입력해주세요."); + return; + } + if (!locDate) { + modalEvent.danger("오류", "날짜를 선택해주세요."); + return; } - detailArray.data = tempArray; - var updateFunc = function () { + modalEvent.info("저장", "해당 휴일을 저장하시겠습니까?", function () { let formData = new FormData(); - // 기존 병원 정보 수정 로직과 동일한 엔드포인트를 사용하되, 휴일 관련 데이터만 전송 - // 단, 서버 로직상 다른 필드가 필수라면 기존 값을 가져오거나, 별도 API가 필요할 수 있음. - // 현재 updateHospital 로직은 전체 필드를 업데이트하는 것으로 보이므로, - // 안전하게는 전체 데이터를 보내거나, 휴일만 업데이트하는 별도 로직이 권장됨. - // 여기서는 사용자의 요청에 따라 '별도로 저장' 기능을 구현하므로, - // 기존 updateHospital을 호출하되 휴일 데이터 위주로 처리하거나, - // 혹은 updateHospital 수정이 필요할 수 있음. - - // *중요*: 사용자가 '운영시간' 탭의 내용은 '저장' 버튼으로, '운영스케쥴' 탭의 내용은 '휴일 저장' 버튼으로 저장하길 원함. - // 하지만 백엔드(updateHospital)가 하나 통으로 되어 있다면, - // 여기서도 다른 필드 값들을 다 채워서 보내야 에러가 안 날 수 있음 (MyBatis Query 확인 필요). - // 앞서 본 쿼리상 updateHospital은 모든 칼럼을 업데이트함. - // 따라서 여기서도 화면에 있는 모든 입력값을 다 읽어서 보내는 것이 안전함. (부분 업데이트 쿼리가 없다면) - // 하지만 '운영시간' 탭의 데이터 변경사항이 '휴일 저장' 버튼 누를 때 같이 저장되어도 되는지? - // 사용자 의도는 "별도로 저장할 수 있게" 이므로, - // 이상적으로는 휴일만 업데이트하는 API가 있어야 함. - // 현재 API 구조상 updateHospital을 재사용한다면 모든 데이터를 다 보내야 함. - - // 일단 전체 데이터를 다 수집해서 보내되, 성공 메시지 등은 분리 처리. - - // --- 전체 데이터 수집 시작 (fn_updateHospital 내용 복사) --- formData.append("menuClass", menuClass); formData.append("muHospitalId", muHospitalId); - - // 운영시간 데이터도 현재 화면 값 그대로 전송 (null 방지) - formData.append("monOpenYn", $("#checkMonOpenYn").is(":checked") ? "Y" : "N"); - formData.append("monOpenStartTime", $("#monOpenStartTime").val()); - formData.append("monOpenEndTime", $("#monOpenEndTime").val()); - formData.append("monBreakStartTime", $("#monBreakStartTime").val()); - formData.append("monBreakEndTime", $("#monBreakEndTime").val()); - formData.append("tueOpenYn", $("#checkTueOpenYn").is(":checked") ? "Y" : "N"); - formData.append("tueOpenStartTime", $("#tueOpenStartTime").val()); - formData.append("tueOpenEndTime", $("#tueOpenEndTime").val()); - formData.append("tueBreakStartTime", $("#tueBreakStartTime").val()); - formData.append("tueBreakEndTime", $("#tueBreakEndTime").val()); - formData.append("wedOpenYn", $("#checkWedOpenYn").is(":checked") ? "Y" : "N"); - formData.append("wedOpenStartTime", $("#wedOpenStartTime").val()); - formData.append("wedOpenEndTime", $("#wedOpenEndTime").val()); - formData.append("wedBreakStartTime", $("#wedBreakStartTime").val()); - formData.append("wedBreakEndTime", $("#wedBreakEndTime").val()); - formData.append("thuOpenYn", $("#checkThuOpenYn").is(":checked") ? "Y" : "N"); - formData.append("thuOpenStartTime", $("#thuOpenStartTime").val()); - formData.append("thuOpenEndTime", $("#thuOpenEndTime").val()); - formData.append("thuBreakStartTime", $("#thuBreakStartTime").val()); - formData.append("thuBreakEndTime", $("#thuBreakEndTime").val()); - formData.append("friOpenYn", $("#checkFriOpenYn").is(":checked") ? "Y" : "N"); - formData.append("friOpenStartTime", $("#friOpenStartTime").val()); - formData.append("friOpenEndTime", $("#friOpenEndTime").val()); - formData.append("friBreakStartTime", $("#friBreakStartTime").val()); - formData.append("friBreakEndTime", $("#friBreakEndTime").val()); - formData.append("satOpenYn", $("#checkSatOpenYn").is(":checked") ? "Y" : "N"); - formData.append("satOpenStartTime", $("#satOpenStartTime").val()); - formData.append("satOpenEndTime", $("#satOpenEndTime").val()); - formData.append("satBreakStartTime", $("#satBreakStartTime").val()); - formData.append("satBreakEndTime", $("#satBreakEndTime").val()); - formData.append("sunOpenYn", $("#checkSunOpenYn").is(":checked") ? "Y" : "N"); - formData.append("sunOpenStartTime", $("#sunOpenStartTime").val()); - formData.append("sunOpenEndTime", $("#sunOpenEndTime").val()); - formData.append("sunBreakStartTime", $("#sunBreakStartTime").val()); - formData.append("sunBreakEndTime", $("#sunBreakEndTime").val()); - - // 휴일 데이터 - formData.append("publicHolidayUseYn", publicHolidayUseYn); - formData.append("holidayRows", JSON.stringify(detailArray)); + formData.append("muHospitalHolidayId", muHospitalHolidayId || ""); + formData.append("hospitalHolidayName", hospitalHolidayName); + formData.append("locDate", locDate); + formData.append("repeatYn", repeatYn || "N"); $.ajax({ - url: encodeURI('/webhospital/updateHospital.do'), + url: encodeURI('/webhospital/saveHospitalHoliday.do'), data: formData, dataType: "json", processData: false, @@ -1238,29 +1164,93 @@ function fn_updateHospitalHoliday() { type: 'POST', success: function (data) { if ('0' == data.msgCode) { - modalEvent.success("성공", "수정되었습니다.", function () { + modalEvent.success("성공", "저장되었습니다.", function () { // 캘린더 리렌더링 - if (window.calendar) { - window.calendar.refetchEvents(); + if (window.fcCalendar) { + window.fcCalendar.refetchEvents(); } - // 페이지 리로드 대신 필요한 부분만 갱신하거나 유지 - // location.reload(); + // 휴일 목록 새로고침 (저장 후 ID가 변경될 수 있으므로) + fn_selectHospitalJson(); }); } else { modalEvent.danger("오류", data.msgDesc); } }, error: function () { - modalEvent.danger("오류", "수정 중 오류가 발생했습니다."); + modalEvent.danger("오류", "저장 중 오류가 발생했습니다."); } }); - }; + }); +} - if (typeof arguments[0] !== 'undefined' && arguments[0] === true) { - updateFunc(); - } else { - modalEvent.info("수정", "병원 휴일 정보를 수정하시겠습니까?", updateFunc); +/**************************************************************************** +* 병원 지정 휴일 선택 삭제 (체크된 row 삭제) +****************************************************************************/ +function fn_deleteCheckedHolidays() { + let muHospitalId = $("#muHospitalId").val(); + let checkedBoxes = $('input[name="checkHolidayRow"]:checked'); + + if (checkedBoxes.length === 0) { + modalEvent.danger("알림", "삭제할 휴일을 선택해주세요."); + return; } + + // 신규 row (ID가 없는 것)는 DOM에서 바로 제거, 기존 row는 서버에 삭제 요청 + let idsToDelete = []; + let $newRows = $(); + + checkedBoxes.each(function () { + let holidayId = $(this).val(); + if (holidayId && holidayId.trim() !== "") { + idsToDelete.push(holidayId.trim()); + } else { + $newRows = $newRows.add($(this).closest('li')); + } + }); + + modalEvent.info("삭제", "선택한 휴일 " + checkedBoxes.length + "건을 삭제하시겠습니까?", function () { + // 신규 row는 DOM에서 즉시 제거 + $newRows.remove(); + + if (idsToDelete.length > 0) { + // 기존 row는 서버에 삭제 요청 + let formData = new FormData(); + formData.append("menuClass", menuClass); + formData.append("muHospitalId", muHospitalId); + formData.append("holidayIds", idsToDelete.join(",")); + + $.ajax({ + url: encodeURI('/webhospital/deleteHospitalHolidays.do'), + data: formData, + dataType: "json", + processData: false, + contentType: false, + type: 'POST', + success: function (data) { + if ('0' == data.msgCode) { + modalEvent.success("성공", "삭제되었습니다.", function () { + if (window.fcCalendar) { + window.fcCalendar.refetchEvents(); + } + fn_selectHospitalJson(); + }); + } else { + modalEvent.danger("오류", data.msgDesc); + } + }, + error: function () { + modalEvent.danger("오류", "삭제 중 오류가 발생했습니다."); + } + }); + } else { + // 신규 row만 삭제한 경우 + modalEvent.success("성공", "삭제되었습니다."); + // 남은 li가 헤더뿐이면 'no_data' 표시 + if ($("#hospitalHolidayList li").not('.list_title_li').length === 0) { + $('#hospitalHolidayList').append('
  • 지정한 휴일이 없습니다.
  • '); + } + } + }); } $(function () { diff --git a/src/main/resources/templates/web/hospital/hospitalUpdate.html b/src/main/resources/templates/web/hospital/hospitalUpdate.html index 7293ff5..58fc5f1 100644 --- a/src/main/resources/templates/web/hospital/hospitalUpdate.html +++ b/src/main/resources/templates/web/hospital/hospitalUpdate.html @@ -50,11 +50,11 @@
    -