연차변경원 진행중
This commit is contained in:
parent
e8e10c48c0
commit
05dc5b5d76
@ -5,6 +5,7 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@ -18,6 +19,8 @@ public class LeaveChangeRequestVO {
|
|||||||
private String userName;
|
private String userName;
|
||||||
private LocalDate originalLeaveDate;
|
private LocalDate originalLeaveDate;
|
||||||
private LocalDate requestedLeaveDate;
|
private LocalDate requestedLeaveDate;
|
||||||
|
private BigDecimal originalLeaveDays; // 추가
|
||||||
|
private BigDecimal requestedLeaveDays; // 추가
|
||||||
private String requestReason;
|
private String requestReason;
|
||||||
private String requestStatus;
|
private String requestStatus;
|
||||||
private String requestStatusName; // 추가
|
private String requestStatusName; // 추가
|
||||||
|
|||||||
@ -32,4 +32,6 @@ public class LeavePlanVO {
|
|||||||
private String requestStatus; // 변경 상태
|
private String requestStatus; // 변경 상태
|
||||||
private String requestStatusName; // 변경 상태 코드 name
|
private String requestStatusName; // 변경 상태 코드 name
|
||||||
private String changeCount; // 변경 카운트
|
private String changeCount; // 변경 카운트
|
||||||
|
private BigDecimal originalLeaveDays; // 변경 전 일수
|
||||||
|
private BigDecimal requestedLeaveDays; // 변경 후 일수
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ public interface ItnLeaveService {
|
|||||||
|
|
||||||
boolean rejectLeavePlan(Long planId, String approverId, String rejectReason);
|
boolean rejectLeavePlan(Long planId, String approverId, String rejectReason);
|
||||||
|
|
||||||
boolean requestLeaveChange(LeaveChangeRequestVO leaveChangeRequestVO);
|
RestResponse requestLeaveChange(LeaveChangeRequestVO leaveChangeRequestVO);
|
||||||
|
|
||||||
LeaveChangeRequestVO getLeaveChangeRequestDetail(Long changeRequestId);
|
LeaveChangeRequestVO getLeaveChangeRequestDetail(Long changeRequestId);
|
||||||
|
|
||||||
|
|||||||
@ -71,6 +71,8 @@ public class ItnLeaveServiceImpl implements ItnLeaveService {
|
|||||||
LeaveChangeRequestVO leaveChangeRequestVO = itnLeaveMapper.selectItnLeaveChangeRequestById(changeRequestId);
|
LeaveChangeRequestVO leaveChangeRequestVO = itnLeaveMapper.selectItnLeaveChangeRequestById(changeRequestId);
|
||||||
if (leaveChangeRequestVO != null) {
|
if (leaveChangeRequestVO != null) {
|
||||||
leaveChangeRequestVO.setUserName(tCodeUtils.getUserName(leaveChangeRequestVO.getUniqId()));
|
leaveChangeRequestVO.setUserName(tCodeUtils.getUserName(leaveChangeRequestVO.getUniqId()));
|
||||||
|
log.info("originalLeaveDays: {}", leaveChangeRequestVO.getOriginalLeaveDays());
|
||||||
|
log.info("requestedLeaveDays: {}", leaveChangeRequestVO.getRequestedLeaveDays());
|
||||||
}
|
}
|
||||||
return leaveChangeRequestVO;
|
return leaveChangeRequestVO;
|
||||||
}
|
}
|
||||||
@ -79,6 +81,30 @@ public class ItnLeaveServiceImpl implements ItnLeaveService {
|
|||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean saveLeavePlan(LeavePlanVO leavePlanVO) {
|
public boolean saveLeavePlan(LeavePlanVO leavePlanVO) {
|
||||||
|
// ==================== [검증 로직 시작] ====================
|
||||||
|
|
||||||
|
// 1. 사용자의 촉진 연차 목표치 조회 (itn_leave_status.promoted_leave)
|
||||||
|
LeaveStatusVO leaveStatus = itnLeaveMapper.selectLeaveStatusByUserIdAndYear(leavePlanVO.getUniqId(), leavePlanVO.getYear());
|
||||||
|
BigDecimal promotedLeaveGoal = leaveStatus.getPromotedLeave();
|
||||||
|
|
||||||
|
// 2. 현재 DB에 저장된 '승인' 및 '대기' 상태의 모든 연차 계획 총합을 계산
|
||||||
|
List<LeavePlanVO> existingPlans = itnLeaveMapper.selectLeavePlansByUserIdAndYear(leavePlanVO.getUniqId(), leavePlanVO.getYear());
|
||||||
|
BigDecimal currentPledgedDays = existingPlans.stream()
|
||||||
|
.filter(p -> "10".equals(p.getStatus()) || "20".equals(p.getStatus())) // 10: 대기, 20: 승인
|
||||||
|
.map(LeavePlanVO::getLeaveDays)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
// 3. 이번에 새로 신청한 연차 일수
|
||||||
|
BigDecimal newRequestDays = leavePlanVO.getLeaveDays();
|
||||||
|
|
||||||
|
// 4. 예상 총합(기존 총합 + 신규 신청)이 목표치를 초과하는지 검증
|
||||||
|
if (currentPledgedDays.add(newRequestDays).compareTo(promotedLeaveGoal) > 0) {
|
||||||
|
// 초과할 경우, 예외를 발생시켜 저장을 막고 사용자에게 에러 메시지 전달
|
||||||
|
throw new IllegalArgumentException("신청 가능한 촉진 연차 일수를 초과했습니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== [검증 로직 종료] ====================
|
||||||
|
|
||||||
if (leavePlanVO.getPlanId() == null) {
|
if (leavePlanVO.getPlanId() == null) {
|
||||||
// 신규 신청
|
// 신규 신청
|
||||||
leavePlanVO.setStatus(LEAVE_STATUS_PENDING); // 초기 상태는 PENDING
|
leavePlanVO.setStatus(LEAVE_STATUS_PENDING); // 초기 상태는 PENDING
|
||||||
@ -173,18 +199,37 @@ public class ItnLeaveServiceImpl implements ItnLeaveService {
|
|||||||
// 연차 변경 요청
|
// 연차 변경 요청
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean requestLeaveChange(LeaveChangeRequestVO leaveChangeRequestVO) {
|
public RestResponse requestLeaveChange(LeaveChangeRequestVO leaveChangeRequestVO) {
|
||||||
// 기존 연차 계획의 변경 요청 상태를 10으로 업데이트
|
// ==================== [검증 로직 시작] ====================
|
||||||
// LeavePlanVO originalLeavePlan = itnLeaveMapper.selectLeavePlanById(leaveChangeRequestVO.getPlanId());
|
|
||||||
// if (originalLeavePlan == null) {
|
|
||||||
// return false; // 원본 연차 계획이 없음
|
|
||||||
// }
|
|
||||||
// leaveChangeRequestVO.setUniqId(originalLeavePlan.getUniqId());
|
|
||||||
|
|
||||||
|
// 1. 사용자의 촉진 연차 목표치 조회 (itn_leave_status.promoted_leave)
|
||||||
|
LeaveStatusVO leaveStatus = itnLeaveMapper.selectLeaveStatusByUserIdAndYear(leaveChangeRequestVO.getUniqId(), String.valueOf(leaveChangeRequestVO.getOriginalLeaveDate().getYear()));
|
||||||
|
BigDecimal promotedLeaveGoal = leaveStatus.getPromotedLeave();
|
||||||
|
|
||||||
// 연차 변경 요청 이력 저장
|
// 2. 현재 DB에 저장된 '승인' 및 '대기' 상태의 모든 연차 계획 총합을 계산
|
||||||
|
List<LeavePlanVO> existingPlans = itnLeaveMapper.selectLeavePlansByUserIdAndYear(leaveChangeRequestVO.getUniqId(), String.valueOf(leaveChangeRequestVO.getOriginalLeaveDate().getYear()));
|
||||||
|
BigDecimal currentPledgedDays = existingPlans.stream()
|
||||||
|
.filter(p -> "10".equals(p.getStatus()) || "20".equals(p.getStatus())) // 10: 대기, 20: 승인
|
||||||
|
.map(LeavePlanVO::getLeaveDays)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
|
// 3. 이번 '변경'으로 인해 발생하는 연차 변동량 계산
|
||||||
|
// (예: 1.0일 -> 0.5일 변경 시 -0.5 / 0.5일 -> 1.0일 변경 시 +0.5)
|
||||||
|
BigDecimal changeInDays = leaveChangeRequestVO.getRequestedLeaveDays().subtract(leaveChangeRequestVO.getOriginalLeaveDays());
|
||||||
|
|
||||||
|
// 4. 예상 총합(기존 총합 + 변동량)이 목표치를 초과하는지 검증
|
||||||
|
if (currentPledgedDays.add(changeInDays).compareTo(promotedLeaveGoal) > 0) {
|
||||||
|
// 초과할 경우, 예외를 발생시켜 저장을 막음
|
||||||
|
return new RestResponse(HttpStatus.BAD_REQUEST, "변경 후 총 연차 일수가 촉진 연차 한도를 초과합니다.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== [검증 로직 종료] ====================
|
||||||
|
|
||||||
|
// 5. 검증 통과 시, 기존 로직 수행
|
||||||
leaveChangeRequestVO.setRequestStatus(LEAVE_CHANGE_REQUEST_STATUS_PENDING);
|
leaveChangeRequestVO.setRequestStatus(LEAVE_CHANGE_REQUEST_STATUS_PENDING);
|
||||||
return itnLeaveMapper.insertLeaveChangeRequest(leaveChangeRequestVO) > 0;
|
itnLeaveMapper.insertLeaveChangeRequest(leaveChangeRequestVO);
|
||||||
|
|
||||||
|
return new RestResponse(HttpStatus.OK, "연차 변경 요청이 성공적으로 제출되었습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,11 +247,21 @@ public class ItnLeaveServiceImpl implements ItnLeaveService {
|
|||||||
changeRequest.setApproverId(approverId);
|
changeRequest.setApproverId(approverId);
|
||||||
itnLeaveMapper.updateLeaveChangeRequestStatus(changeRequest);
|
itnLeaveMapper.updateLeaveChangeRequestStatus(changeRequest);
|
||||||
|
|
||||||
// 원본 연차 계획 업데이트 (날짜 변경)
|
// 원본 연차 계획 업데이트 (날짜 및 일수 변경)
|
||||||
LeavePlanVO originalLeavePlan = itnLeaveMapper.selectLeavePlanById(changeRequest.getPlanId());
|
LeavePlanVO originalLeavePlan = itnLeaveMapper.selectLeavePlanById(changeRequest.getPlanId());
|
||||||
if (originalLeavePlan != null) {
|
if (originalLeavePlan != null) {
|
||||||
originalLeavePlan.setLeaveDate(changeRequest.getRequestedLeaveDate());
|
originalLeavePlan.setLeaveDate(changeRequest.getRequestedLeaveDate());
|
||||||
|
originalLeavePlan.setLeaveDays(changeRequest.getRequestedLeaveDays()); // 일수 변경 반영
|
||||||
itnLeaveMapper.updateLeavePlan(originalLeavePlan); // 기존 updateLeavePlan 사용
|
itnLeaveMapper.updateLeavePlan(originalLeavePlan); // 기존 updateLeavePlan 사용
|
||||||
|
|
||||||
|
// 사용된 연차 재계산 및 업데이트 (used_leave는 고정값이므로 수정하지 않음)
|
||||||
|
// LeaveStatusVO leaveStatus = itnLeaveMapper.selectLeaveStatusByUserIdAndYear(originalLeavePlan.getUniqId(), originalLeavePlan.getYear());
|
||||||
|
// if (leaveStatus != null) {
|
||||||
|
// BigDecimal oldUsedLeave = leaveStatus.getUsedLeave();
|
||||||
|
// BigDecimal changedAmount = changeRequest.getOriginalLeaveDays().subtract(changeRequest.getRequestedLeaveDays());
|
||||||
|
// leaveStatus.setUsedLeave(oldUsedLeave.subtract(changedAmount));
|
||||||
|
// itnLeaveMapper.updateLeaveStatus(leaveStatus);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -89,12 +89,16 @@ public class ItnLeaveRestController {
|
|||||||
public ResponseEntity<RestResponse> submitLeaveChangeRequest(@RequestBody LeaveChangeRequestVO leaveChangeRequestVO
|
public ResponseEntity<RestResponse> submitLeaveChangeRequest(@RequestBody LeaveChangeRequestVO leaveChangeRequestVO
|
||||||
, @AuthenticationPrincipal CustomUserDetails loginUser) {
|
, @AuthenticationPrincipal CustomUserDetails loginUser) {
|
||||||
leaveChangeRequestVO.setUniqId(loginUser.getUser().getUniqId());
|
leaveChangeRequestVO.setUniqId(loginUser.getUser().getUniqId());
|
||||||
boolean result = itnLeaveService.requestLeaveChange(leaveChangeRequestVO);
|
// boolean result = itnLeaveService.requestLeaveChange(leaveChangeRequestVO);
|
||||||
if (result) {
|
|
||||||
return ResponseEntity.ok().body(new RestResponse(HttpStatus.OK, "연차 변경 요청이 성공적으로 제출되었습니다."));
|
|
||||||
} else {
|
|
||||||
return ResponseEntity.badRequest().body(new RestResponse(HttpStatus.BAD_REQUEST, "연차 변경 요청 제출에 실패했습니다."));
|
return ResponseEntity.ok().body(itnLeaveService.requestLeaveChange(leaveChangeRequestVO));
|
||||||
}
|
// if (result) {
|
||||||
|
// return ResponseEntity.ok().body(new RestResponse(HttpStatus.OK, "연차 변경 요청이 성공적으로 제출되었습니다."));
|
||||||
|
// } else {
|
||||||
|
// return ResponseEntity.badRequest().body(new RestResponse(HttpStatus.BAD_REQUEST, "연차 변경 요청 제출에 실패했습니다."));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 연차 변경 요청 상세 조회
|
// 연차 변경 요청 상세 조회
|
||||||
|
|||||||
@ -53,6 +53,8 @@
|
|||||||
c.change_request_id,
|
c.change_request_id,
|
||||||
c.original_leave_date,
|
c.original_leave_date,
|
||||||
c.requested_leave_date,
|
c.requested_leave_date,
|
||||||
|
c.original_leave_days,
|
||||||
|
c.requested_leave_days,
|
||||||
c.request_reason,
|
c.request_reason,
|
||||||
c.request_status,
|
c.request_status,
|
||||||
c.request_dt,
|
c.request_dt,
|
||||||
@ -143,6 +145,8 @@
|
|||||||
UNIQ_ID,
|
UNIQ_ID,
|
||||||
ORIGINAL_LEAVE_DATE,
|
ORIGINAL_LEAVE_DATE,
|
||||||
REQUESTED_LEAVE_DATE,
|
REQUESTED_LEAVE_DATE,
|
||||||
|
ORIGINAL_LEAVE_DAYS,
|
||||||
|
REQUESTED_LEAVE_DAYS,
|
||||||
REQUEST_REASON,
|
REQUEST_REASON,
|
||||||
REQUEST_STATUS,
|
REQUEST_STATUS,
|
||||||
REQUEST_DT
|
REQUEST_DT
|
||||||
@ -151,6 +155,8 @@
|
|||||||
#{uniqId},
|
#{uniqId},
|
||||||
#{originalLeaveDate},
|
#{originalLeaveDate},
|
||||||
#{requestedLeaveDate},
|
#{requestedLeaveDate},
|
||||||
|
#{originalLeaveDays},
|
||||||
|
#{requestedLeaveDays},
|
||||||
#{requestReason},
|
#{requestReason},
|
||||||
#{requestStatus},
|
#{requestStatus},
|
||||||
NOW()
|
NOW()
|
||||||
@ -167,6 +173,8 @@
|
|||||||
T1.UNIQ_ID,
|
T1.UNIQ_ID,
|
||||||
T1.ORIGINAL_LEAVE_DATE,
|
T1.ORIGINAL_LEAVE_DATE,
|
||||||
T1.REQUESTED_LEAVE_DATE,
|
T1.REQUESTED_LEAVE_DATE,
|
||||||
|
T1.ORIGINAL_LEAVE_DAYS,
|
||||||
|
T1.REQUESTED_LEAVE_DAYS,
|
||||||
T1.REQUEST_REASON,
|
T1.REQUEST_REASON,
|
||||||
T1.REQUEST_STATUS,
|
T1.REQUEST_STATUS,
|
||||||
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
||||||
@ -195,6 +203,8 @@
|
|||||||
T1.UNIQ_ID,
|
T1.UNIQ_ID,
|
||||||
T1.ORIGINAL_LEAVE_DATE,
|
T1.ORIGINAL_LEAVE_DATE,
|
||||||
T1.REQUESTED_LEAVE_DATE,
|
T1.REQUESTED_LEAVE_DATE,
|
||||||
|
T1.ORIGINAL_LEAVE_DAYS,
|
||||||
|
T1.REQUESTED_LEAVE_DAYS,
|
||||||
T1.REQUEST_REASON,
|
T1.REQUEST_REASON,
|
||||||
T1.REQUEST_STATUS,
|
T1.REQUEST_STATUS,
|
||||||
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
||||||
@ -211,11 +221,11 @@
|
|||||||
SELECT
|
SELECT
|
||||||
T1.CHANGE_REQUEST_ID,
|
T1.CHANGE_REQUEST_ID,
|
||||||
T1.PLAN_ID,
|
T1.PLAN_ID,
|
||||||
ilp.YEAR ,
|
|
||||||
ilp.LEAVE_DAYS ,
|
|
||||||
T1.UNIQ_ID,
|
T1.UNIQ_ID,
|
||||||
T1.ORIGINAL_LEAVE_DATE,
|
T1.ORIGINAL_LEAVE_DATE,
|
||||||
T1.REQUESTED_LEAVE_DATE,
|
T1.REQUESTED_LEAVE_DATE,
|
||||||
|
T1.ORIGINAL_LEAVE_DAYS,
|
||||||
|
T1.REQUESTED_LEAVE_DAYS,
|
||||||
T1.REQUEST_REASON,
|
T1.REQUEST_REASON,
|
||||||
T1.REQUEST_STATUS,
|
T1.REQUEST_STATUS,
|
||||||
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
||||||
@ -224,8 +234,6 @@
|
|||||||
T1.REQUEST_DT,
|
T1.REQUEST_DT,
|
||||||
T1.APPROVAL_DT
|
T1.APPROVAL_DT
|
||||||
FROM ITN_LEAVE_CHANGE_REQUEST T1
|
FROM ITN_LEAVE_CHANGE_REQUEST T1
|
||||||
left join itn_leave_plan ilp
|
|
||||||
on T1.plan_id = ilp.PLAN_ID
|
|
||||||
WHERE T1.CHANGE_REQUEST_ID = #{changeRequestId}
|
WHERE T1.CHANGE_REQUEST_ID = #{changeRequestId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@ -238,6 +246,8 @@
|
|||||||
T1.UNIQ_ID,
|
T1.UNIQ_ID,
|
||||||
T1.ORIGINAL_LEAVE_DATE,
|
T1.ORIGINAL_LEAVE_DATE,
|
||||||
T1.REQUESTED_LEAVE_DATE,
|
T1.REQUESTED_LEAVE_DATE,
|
||||||
|
T1.ORIGINAL_LEAVE_DAYS,
|
||||||
|
T1.REQUESTED_LEAVE_DAYS,
|
||||||
T1.REQUEST_REASON,
|
T1.REQUEST_REASON,
|
||||||
T1.REQUEST_STATUS,
|
T1.REQUEST_STATUS,
|
||||||
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
(SELECT CODE_NAME FROM COMMON_CODE_DETAIL WHERE CODE_GROUP_ID = 'CHANGE_REQUEST_STATUS' AND CODE_ID = T1.REQUEST_STATUS) AS requestStatusName,
|
||||||
|
|||||||
@ -53,6 +53,7 @@
|
|||||||
<th>신청자</th>
|
<th>신청자</th>
|
||||||
<th>기존 연차 일자</th>
|
<th>기존 연차 일자</th>
|
||||||
<th>요청 변경 일자</th>
|
<th>요청 변경 일자</th>
|
||||||
|
<th>변경일수</th>
|
||||||
<th>요청 사유</th>
|
<th>요청 사유</th>
|
||||||
<th>요청 일시</th>
|
<th>요청 일시</th>
|
||||||
<th>상태</th>
|
<th>상태</th>
|
||||||
@ -64,6 +65,10 @@
|
|||||||
<td th:text="${@TCodeUtils.getUserName(changeRequest.uniqId)}"></td>
|
<td th:text="${@TCodeUtils.getUserName(changeRequest.uniqId)}"></td>
|
||||||
<td th:text="${changeRequest.originalLeaveDate}"></td>
|
<td th:text="${changeRequest.originalLeaveDate}"></td>
|
||||||
<td th:text="${changeRequest.requestedLeaveDate}"></td>
|
<td th:text="${changeRequest.requestedLeaveDate}"></td>
|
||||||
|
<td>
|
||||||
|
<span th:if="${changeRequest.originalLeaveDays != null and changeRequest.requestedLeaveDays != null}"
|
||||||
|
th:text="|${changeRequest.originalLeaveDays} → ${changeRequest.requestedLeaveDays}|"></span>
|
||||||
|
</td>
|
||||||
<td th:text="${changeRequest.requestReason}"></td>
|
<td th:text="${changeRequest.requestReason}"></td>
|
||||||
<td th:text="${#temporals.format(changeRequest.requestDt, 'yyyy-MM-dd HH:mm')}"></td>
|
<td th:text="${#temporals.format(changeRequest.requestDt, 'yyyy-MM-dd HH:mm')}"></td>
|
||||||
<td th:text="${changeRequest.requestStatusName}"></td>
|
<td th:text="${changeRequest.requestStatusName}"></td>
|
||||||
@ -179,6 +184,11 @@
|
|||||||
$('#leaveChangeRequestDetailModal #detailChangeRequestUserId').val(data.userName);
|
$('#leaveChangeRequestDetailModal #detailChangeRequestUserId').val(data.userName);
|
||||||
$('#leaveChangeRequestDetailModal #detailOriginalLeaveDate').val(data.originalLeaveDate);
|
$('#leaveChangeRequestDetailModal #detailOriginalLeaveDate').val(data.originalLeaveDate);
|
||||||
$('#leaveChangeRequestDetailModal #detailRequestedLeaveDate').val(data.requestedLeaveDate);
|
$('#leaveChangeRequestDetailModal #detailRequestedLeaveDate').val(data.requestedLeaveDate);
|
||||||
|
if (data.originalLeaveDays != null && data.requestedLeaveDays != null) {
|
||||||
|
$('#leaveChangeRequestDetailModal #detailLeaveDaysChange').val(`${data.originalLeaveDays} → ${data.requestedLeaveDays}`);
|
||||||
|
} else {
|
||||||
|
$('#leaveChangeRequestDetailModal #detailLeaveDaysChange').val('-');
|
||||||
|
}
|
||||||
$('#leaveChangeRequestDetailModal #detailRequestReason').val(data.requestReason);
|
$('#leaveChangeRequestDetailModal #detailRequestReason').val(data.requestReason);
|
||||||
$('#leaveChangeRequestDetailModal #detailChangeRequestRequestDt').val(data.requestDt);
|
$('#leaveChangeRequestDetailModal #detailChangeRequestRequestDt').val(data.requestDt);
|
||||||
$('#leaveChangeRequestDetailModal #changeRequestApprovalStatus').val('20'); // 기본값 설정 : 승인
|
$('#leaveChangeRequestDetailModal #changeRequestApprovalStatus').val('20'); // 기본값 설정 : 승인
|
||||||
@ -237,6 +247,10 @@
|
|||||||
<label>요청 변경 일자</label>
|
<label>요청 변경 일자</label>
|
||||||
<input type="text" class="form-control" id="detailRequestedLeaveDate" readonly>
|
<input type="text" class="form-control" id="detailRequestedLeaveDate" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>변경 일수</label>
|
||||||
|
<input type="text" class="form-control" id="detailLeaveDaysChange" readonly>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>요청 사유</label>
|
<label>요청 사유</label>
|
||||||
<textarea class="form-control" id="detailRequestReason" rows="3" readonly></textarea>
|
<textarea class="form-control" id="detailRequestReason" rows="3" readonly></textarea>
|
||||||
|
|||||||
@ -112,6 +112,56 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 촉진 연차 현황 요약 섹션 추가 -->
|
||||||
|
<div class="mb-4" th:with="
|
||||||
|
promotedLeaveVal=${leaveStatus != null ? leaveStatus.promotedLeave : T(java.math.BigDecimal).ZERO},
|
||||||
|
filteredLeavePlans=${leavePlans != null ? leavePlans.?[status == '10' or status == '20'] : T(java.util.Collections).emptyList()},
|
||||||
|
plannedTotal=${#aggregates.sum(filteredLeavePlans.![leaveDays != null ? leaveDays : T(java.math.BigDecimal).ZERO])},
|
||||||
|
remainingPlanDays=${T(java.util.Optional).ofNullable(promotedLeaveVal).orElse(T(java.math.BigDecimal).ZERO).subtract(T(java.util.Optional).ofNullable(plannedTotal).orElse(T(java.math.BigDecimal).ZERO))}">
|
||||||
|
<h5 class="mb-3"><i class="fas fa-chart-pie text-info mr-1"></i> 촉진 연차 현황</h5>
|
||||||
|
<table class="table table-bordered table-hover align-middle" style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 200px; background-color: #f8f9fa;">촉진 연차 목표</th>
|
||||||
|
<td th:text="${leaveStatus.promotedLeave} + '일'">10.0일</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="background-color: #f8f9fa;">현재 계획된 연차 총합</th>
|
||||||
|
<td th:text="${plannedTotal} + '일'">8.0일</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="background-color: #f8f9fa;">추가 계획 가능 연차</th>
|
||||||
|
<td th:text="${remainingPlanDays} + '일'">2.0일</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- 디버깅 정보 (임시) -->
|
||||||
|
<div style="background-color: #f0f0f0; padding: 10px; margin-top: 20px; border-radius: 5px;">
|
||||||
|
<p><strong>디버깅 정보:</strong></p>
|
||||||
|
<p>촉진 연차 목표 (promotedLeave): <span th:text="${leaveStatus.promotedLeave}"></span></p>
|
||||||
|
<p>현재 계획된 연차 총합 (plannedTotal): <span th:text="${plannedTotal}"></span></p>
|
||||||
|
<p>추가 계획 가능 연차 (remainingPlanDays): <span th:text="${remainingPlanDays}"></span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 사용자 안내 메시지 -->
|
||||||
|
<div>
|
||||||
|
<div th:if="${remainingPlanDays.compareTo(T(java.math.BigDecimal).ZERO) > 0}" class="alert alert-info mt-3" role="alert">
|
||||||
|
<i class="fas fa-info-circle mr-1"></i> 촉진 연차를 모두 사용하려면 <strong th:text="${remainingPlanDays}">2.0</strong>일의 연차를 더 신청해야 합니다.
|
||||||
|
</div>
|
||||||
|
<div th:if="${remainingPlanDays.compareTo(T(java.math.BigDecimal).ZERO) <= 0}" class="alert alert-success mt-3" role="alert">
|
||||||
|
<i class="fas fa-check-circle mr-1"></i> 촉진 연차 목표를 달성했거나 초과했습니다.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 추가된 버튼 -->
|
||||||
|
<div th:if="${remainingPlanDays.compareTo(T(java.math.BigDecimal).ZERO) > 0}" class="text-center mt-3">
|
||||||
|
<a th:href="@{/itn/leave/request}" class="btn btn-primary btn-lg">
|
||||||
|
<i class="fas fa-plus-circle mr-2"></i> 연차 사용 계획 신청하기
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 연차 사용 계획 -->
|
<!-- 연차 사용 계획 -->
|
||||||
<div>
|
<div>
|
||||||
<h5>📅 연차 사용 계획</h5>
|
<h5>📅 연차 사용 계획</h5>
|
||||||
@ -122,6 +172,7 @@
|
|||||||
<th style="width: 200px;">일자</th>
|
<th style="width: 200px;">일자</th>
|
||||||
<th style="width: 200px;">일수</th>
|
<th style="width: 200px;">일수</th>
|
||||||
<th style="width: 200px;">변경 횟수</th>
|
<th style="width: 200px;">변경 횟수</th>
|
||||||
|
<th style="width: 200px;">변경일수</th>
|
||||||
<th style="width: 200px;">요청 상태</th>
|
<th style="width: 200px;">요청 상태</th>
|
||||||
<th>반려 사유</th>
|
<th>반려 사유</th>
|
||||||
<th style="width: 100px;" class="text-center">관리</th>
|
<th style="width: 100px;" class="text-center">관리</th>
|
||||||
@ -141,6 +192,10 @@
|
|||||||
style="cursor: pointer;">
|
style="cursor: pointer;">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<span th:if="${plan.originalLeaveDays != null and plan.requestedLeaveDays != null}"
|
||||||
|
th:text="|${plan.originalLeaveDays} → ${plan.requestedLeaveDays}|"></span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -158,7 +213,7 @@
|
|||||||
<td th:text="${plan.rejectionReason}"></td>
|
<td th:text="${plan.rejectionReason}"></td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#"
|
<a href="#"
|
||||||
th:onclick="openLeaveChangeRequestModal([[${plan.planId}]], [[${plan.leaveDate}]])"
|
th:onclick="openLeaveChangeRequestModal([[${plan.planId}]], [[${plan.leaveDate}]], [[${plan.leaveDays}]])"
|
||||||
th:if="${plan.requestStatus != '10'} and ${plan.leaveDate > T(java.time.LocalDate).now()}"
|
th:if="${plan.requestStatus != '10'} and ${plan.leaveDate > T(java.time.LocalDate).now()}"
|
||||||
class="btn btn-info btn-sm">
|
class="btn btn-info btn-sm">
|
||||||
변경 요청
|
변경 요청
|
||||||
@ -172,6 +227,14 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</th:block>
|
</th:block>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="table-active font-weight-bold text-center">
|
||||||
|
<td>합계</td>
|
||||||
|
<td th:text="${#aggregates.sum(leavePlans.![leaveDays])}"></td>
|
||||||
|
<td th:text="${#aggregates.sum(leavePlans.![T(java.lang.Integer).parseInt(changeCount)])}"></td>
|
||||||
|
<td colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -220,7 +283,7 @@
|
|||||||
$body.empty(); // 기존 내용 제거
|
$body.empty(); // 기존 내용 제거
|
||||||
|
|
||||||
if (historyList.length === 0) {
|
if (historyList.length === 0) {
|
||||||
$body.append('<tr><td colspan="5">변경 이력이 없습니다.</td></tr>');
|
$body.append('<tr><td colspan="6">변경 이력이 없습니다.</td></tr>');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +293,9 @@
|
|||||||
: item.requestStatus === '40' ? 'badge-success'
|
: item.requestStatus === '40' ? 'badge-success'
|
||||||
: 'badge-light';
|
: 'badge-light';
|
||||||
|
|
||||||
|
const leaveDaysChangeHtml = (item.originalLeaveDays != null && item.requestedLeaveDays != null) ?
|
||||||
|
`<td>${item.originalLeaveDays} → ${item.requestedLeaveDays}</td>` : '<td>-</td>';
|
||||||
|
|
||||||
const row = `
|
const row = `
|
||||||
<tr>
|
<tr>
|
||||||
<td class="bg-secondary text-white font-monospace rounded px-2 py-1">
|
<td class="bg-secondary text-white font-monospace rounded px-2 py-1">
|
||||||
@ -237,6 +303,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>${item.originalLeaveDate}</td>
|
<td>${item.originalLeaveDate}</td>
|
||||||
<td>${item.requestedLeaveDate}</td>
|
<td>${item.requestedLeaveDate}</td>
|
||||||
|
${leaveDaysChangeHtml}
|
||||||
<td>${item.requestReason}</td>
|
<td>${item.requestReason}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge ${badgeClass} px-3 py-2">${item.requestStatusName}</span>
|
<span class="badge ${badgeClass} px-3 py-2">${item.requestStatusName}</span>
|
||||||
@ -254,11 +321,13 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
window.openLeaveChangeRequestModal = function (planId, originalLeaveDate) {
|
window.openLeaveChangeRequestModal = function (planId, originalLeaveDate, originalLeaveDays) {
|
||||||
console.log(' openLeaveChangeRequestModal ');
|
console.log(' openLeaveChangeRequestModal ');
|
||||||
$('#leaveChangeRequestModal #planId').val(planId);
|
$('#leaveChangeRequestModal #planId').val(planId);
|
||||||
$('#leaveChangeRequestModal #originalLeaveDate').val(originalLeaveDate);
|
$('#leaveChangeRequestModal #originalLeaveDate').val(originalLeaveDate);
|
||||||
|
$('#leaveChangeRequestModal #originalLeaveDays').val(originalLeaveDays);
|
||||||
$('#leaveChangeRequestModal #requestedLeaveDate').val('');
|
$('#leaveChangeRequestModal #requestedLeaveDate').val('');
|
||||||
|
$('#leaveChangeRequestModal #requestedLeaveDays').val('1.0');
|
||||||
$('#leaveChangeRequestModal #requestReason').val('');
|
$('#leaveChangeRequestModal #requestReason').val('');
|
||||||
$('#leaveChangeRequestModal').modal('show');
|
$('#leaveChangeRequestModal').modal('show');
|
||||||
}
|
}
|
||||||
@ -266,7 +335,9 @@
|
|||||||
function submitLeaveChangeRequest() {
|
function submitLeaveChangeRequest() {
|
||||||
const planId = $('#leaveChangeRequestModal #planId').val();
|
const planId = $('#leaveChangeRequestModal #planId').val();
|
||||||
const originalLeaveDate = $('#leaveChangeRequestModal #originalLeaveDate').val();
|
const originalLeaveDate = $('#leaveChangeRequestModal #originalLeaveDate').val();
|
||||||
|
const originalLeaveDays = $('#leaveChangeRequestModal #originalLeaveDays').val();
|
||||||
const requestedLeaveDate = $('#leaveChangeRequestModal #requestedLeaveDate').val();
|
const requestedLeaveDate = $('#leaveChangeRequestModal #requestedLeaveDate').val();
|
||||||
|
const requestedLeaveDays = $('#leaveChangeRequestModal #requestedLeaveDays').val();
|
||||||
const requestReason = $('#leaveChangeRequestModal #requestReason').val();
|
const requestReason = $('#leaveChangeRequestModal #requestReason').val();
|
||||||
|
|
||||||
if (!requestedLeaveDate) {
|
if (!requestedLeaveDate) {
|
||||||
@ -283,7 +354,9 @@
|
|||||||
const data = {
|
const data = {
|
||||||
planId: planId,
|
planId: planId,
|
||||||
originalLeaveDate: originalLeaveDate,
|
originalLeaveDate: originalLeaveDate,
|
||||||
|
originalLeaveDays: originalLeaveDays,
|
||||||
requestedLeaveDate: requestedLeaveDate,
|
requestedLeaveDate: requestedLeaveDate,
|
||||||
|
requestedLeaveDays: requestedLeaveDays,
|
||||||
requestReason: requestReason
|
requestReason: requestReason
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -295,9 +368,15 @@
|
|||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
fn_successAlert(response.msg);
|
if(response.status == 'BAD_REQUEST'){
|
||||||
$('#leaveChangeRequestModal').modal('hide');
|
|
||||||
location.reload();
|
fn_failedAlert(response.msg);
|
||||||
|
}else{
|
||||||
|
|
||||||
|
fn_successAlert(response.msg);
|
||||||
|
$('#leaveChangeRequestModal').modal('hide');
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
error: function (xhr, status, error) {
|
error: function (xhr, status, error) {
|
||||||
const errorResponse = JSON.parse(xhr.responseText);
|
const errorResponse = JSON.parse(xhr.responseText);
|
||||||
@ -321,6 +400,7 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="leaveChangeRequestForm">
|
<form id="leaveChangeRequestForm">
|
||||||
<input type="hidden" id="planId" name="planId">
|
<input type="hidden" id="planId" name="planId">
|
||||||
|
<input type="hidden" id="originalLeaveDays" name="originalLeaveDays">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="originalLeaveDate">기존 연차 일자</label>
|
<label for="originalLeaveDate">기존 연차 일자</label>
|
||||||
<input type="text" class="form-control" id="originalLeaveDate" readonly>
|
<input type="text" class="form-control" id="originalLeaveDate" readonly>
|
||||||
@ -334,6 +414,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="requestedLeaveDays">변경 요청 일수</label>
|
||||||
|
<select class="form-control" id="requestedLeaveDays" name="requestedLeaveDays">
|
||||||
|
<option value="1.0">연차 (1.0일)</option>
|
||||||
|
<option value="0.5">반차 (0.5일)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="requestReason">변경 요청 사유</label>
|
<label for="requestReason">변경 요청 사유</label>
|
||||||
<textarea class="form-control" id="requestReason" name="requestReason" rows="3" required></textarea>
|
<textarea class="form-control" id="requestReason" name="requestReason" rows="3" required></textarea>
|
||||||
@ -351,7 +438,7 @@
|
|||||||
<!-- 변경 이력 모달 -->
|
<!-- 변경 이력 모달 -->
|
||||||
<!-- 변경 이력 모달 -->
|
<!-- 변경 이력 모달 -->
|
||||||
<div class="modal fade" id="changeHistoryModal" tabindex="-1" role="dialog" aria-labelledby="changeHistoryModalLabel" aria-hidden="true">
|
<div class="modal fade" id="changeHistoryModal" tabindex="-1" role="dialog" aria-labelledby="changeHistoryModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-xl" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="changeHistoryModalLabel">변경 이력</h5>
|
<h5 class="modal-title" id="changeHistoryModalLabel">변경 이력</h5>
|
||||||
@ -367,23 +454,40 @@
|
|||||||
<th style="width: 20%;">변경 일시</th>
|
<th style="width: 20%;">변경 일시</th>
|
||||||
<th style="width: 15%;">기존 날짜</th>
|
<th style="width: 15%;">기존 날짜</th>
|
||||||
<th style="width: 15%;">요청 날짜</th>
|
<th style="width: 15%;">요청 날짜</th>
|
||||||
|
<th style="width: 10%;">변경일수</th>
|
||||||
<th style="width: 30%;">요청 사유</th>
|
<th style="width: 30%;">요청 사유</th>
|
||||||
<th style="width: 20%;">처리 상태</th>
|
<th style="width: 30%;">처리 상태</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="changeHistoryBody">
|
<tbody id="changeHistoryBody">
|
||||||
<tr>
|
<th:block th:if="${not #lists.isEmpty(historyList)}">
|
||||||
<td class="bg-secondary text-white font-monospace rounded px-2 py-1">
|
<tr th:each="item : ${historyList}">
|
||||||
2025-07-15 09:32
|
<td class="bg-secondary text-white font-monospace rounded px-2 py-1">
|
||||||
</td>
|
<span th:text="${#temporals.format(item.requestDt, 'yyyy-MM-dd HH:mm')}"></span>
|
||||||
<td>2025-07-22</td>
|
</td>
|
||||||
<td>2025-07-24</td>
|
<td th:text="${item.originalLeaveDate}"></td>
|
||||||
<td>개인 일정 조정</td>
|
<td th:text="${item.requestedLeaveDate}"></td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-secondary px-3 py-2">대기</span>
|
<span th:if="${item.originalLeaveDays != null and item.requestedLeaveDays != null}"
|
||||||
</td>
|
th:text="|${item.originalLeaveDays} → ${item.requestedLeaveDays}|"></span>
|
||||||
</tr>
|
<span th:unless="${item.originalLeaveDays != null and item.requestedLeaveDays != null}">-</span>
|
||||||
<!-- 추가 row 가능 -->
|
</td>
|
||||||
|
<td th:text="${item.requestReason}"></td>
|
||||||
|
<td>
|
||||||
|
<span th:class="'badge px-3 py-2 fs-6 ' +
|
||||||
|
(${item.requestStatus} == '20' ? 'badge-secondary' :
|
||||||
|
(${item.requestStatus} == '30' ? 'badge-warning' :
|
||||||
|
(${item.requestStatus} == '40' ? 'badge-success' : 'badge-light')))"
|
||||||
|
th:text="${item.requestStatusName}">
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</th:block>
|
||||||
|
<th:block th:if="${#lists.isEmpty(historyList)}">
|
||||||
|
<tr>
|
||||||
|
<td colspan="6">변경 이력이 없습니다.</td>
|
||||||
|
</tr>
|
||||||
|
</th:block>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user