Merge branch 'main' into yoon
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
This commit is contained in:
commit
214f4ec8a0
@ -49,6 +49,7 @@ import io.company.localhost.common.dto.ApiResponse;
|
|||||||
import io.company.localhost.common.dto.MapDto;
|
import io.company.localhost.common.dto.MapDto;
|
||||||
import io.company.localhost.common.exception.InvalidPasswordException;
|
import io.company.localhost.common.exception.InvalidPasswordException;
|
||||||
import io.company.localhost.common.exception.NotFoundHandler;
|
import io.company.localhost.common.exception.NotFoundHandler;
|
||||||
|
import io.company.localhost.common.exception.code.UserErrorCode;
|
||||||
import io.company.localhost.service.commoncodService;
|
import io.company.localhost.service.commoncodService;
|
||||||
import io.company.localhost.service.localbordService;
|
import io.company.localhost.service.localbordService;
|
||||||
import io.company.localhost.utils.AuthUtil;
|
import io.company.localhost.utils.AuthUtil;
|
||||||
@ -121,7 +122,9 @@ public class BoardController {
|
|||||||
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
|
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
|
||||||
MapDto board = boardService.selectBoardDetail(boardId);
|
MapDto board = boardService.selectBoardDetail(boardId);
|
||||||
if (board == null) {
|
if (board == null) {
|
||||||
throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
|
//throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
|
||||||
|
String errMessage = "게시물 ID " + boardId + "을(를) 찾을 수 없습니다.";
|
||||||
|
ApiResponse.error(HttpStatus.NOT_FOUND, errMessage);
|
||||||
}
|
}
|
||||||
// 📌 첨부파일 목록 추가
|
// 📌 첨부파일 목록 추가
|
||||||
List<MapDto> attachments = boardService.selectAttachments(boardId);
|
List<MapDto> attachments = boardService.selectAttachments(boardId);
|
||||||
@ -296,9 +299,10 @@ public class BoardController {
|
|||||||
@Member
|
@Member
|
||||||
@ParameterCheck
|
@ParameterCheck
|
||||||
@DeleteMapping("/comment/{commentId}")
|
@DeleteMapping("/comment/{commentId}")
|
||||||
public ApiResponse<String> deleteComment(@PathVariable("commentId") Long commentId) {
|
public ApiResponse<String> deleteComment(@PathVariable("commentId") Long commentId, @RequestParam(value = "LOCCMTPNT") Long parentId) {
|
||||||
MapDto map = new MapDto();
|
MapDto map = new MapDto();
|
||||||
map.put("LOCCMTSEQ", commentId);
|
map.put("LOCCMTSEQ", commentId);
|
||||||
|
map.put("LOCCMTPNT", parentId);
|
||||||
|
|
||||||
boardService.deleteComment(map);
|
boardService.deleteComment(map);
|
||||||
return ApiResponse.ok("댓글이 삭제되었습니다.");
|
return ApiResponse.ok("댓글이 삭제되었습니다.");
|
||||||
@ -328,11 +332,13 @@ public class BoardController {
|
|||||||
String storedHashedPassword = boardService.selectBoardPassword(boardId);
|
String storedHashedPassword = boardService.selectBoardPassword(boardId);
|
||||||
if (storedHashedPassword == null) {
|
if (storedHashedPassword == null) {
|
||||||
throw new NotFoundHandler("해당 게시물이 존재하지 않습니다.");
|
throw new NotFoundHandler("해당 게시물이 존재하지 않습니다.");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
||||||
if (!isMatch) {
|
if (!isMatch) {
|
||||||
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
//throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
||||||
|
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.ok(true);
|
return ApiResponse.ok(true);
|
||||||
@ -365,7 +371,8 @@ public class BoardController {
|
|||||||
|
|
||||||
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
|
||||||
if (!isMatch) {
|
if (!isMatch) {
|
||||||
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
//throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
|
||||||
|
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiResponse.ok(true);
|
return ApiResponse.ok(true);
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
*
|
*
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
package io.company.localhost.controller.api;
|
package io.company.localhost.controller.api;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -54,11 +55,12 @@ public class VacationController {
|
|||||||
@PostMapping
|
@PostMapping
|
||||||
public ApiResponse<?> insertVacations(@RequestBody List<MapDto> list) {
|
public ApiResponse<?> insertVacations(@RequestBody List<MapDto> list) {
|
||||||
Long user = AuthUtil.getUser().getId();
|
Long user = AuthUtil.getUser().getId();
|
||||||
|
List<MapDto> savedVacations = new ArrayList<>();
|
||||||
|
|
||||||
for (MapDto request : list) {
|
for (MapDto request : list) {
|
||||||
String date = request.getString("date");
|
String date = request.getString("date");
|
||||||
String type = request.getString("type");
|
String type = request.getString("type");
|
||||||
Object receiverId = request.get("receiverId");
|
Object receiverId = request.get("receiverId");
|
||||||
request.put("employeeId", user);
|
|
||||||
|
|
||||||
if (date == null || type == null) {
|
if (date == null || type == null) {
|
||||||
throw new IllegalArgumentException("요청 데이터에 누락된 값이 있습니다: " + request);
|
throw new IllegalArgumentException("요청 데이터에 누락된 값이 있습니다: " + request);
|
||||||
@ -68,11 +70,21 @@ public class VacationController {
|
|||||||
if (count == null || count < 1) {
|
if (count == null || count < 1) {
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
localVacaService.insertVacation(request);
|
MapDto vacationRequest = new MapDto();
|
||||||
|
vacationRequest.put("date", date);
|
||||||
|
vacationRequest.put("type", type);
|
||||||
|
vacationRequest.put("receiverId", receiverId);
|
||||||
|
vacationRequest.put("employeeId", user);
|
||||||
|
|
||||||
|
// 실제 저장
|
||||||
|
localVacaService.insertVacation(vacationRequest);
|
||||||
|
savedVacations.add(vacationRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ApiResponse.ok("모든 휴가가 성공적으로 저장되었습니다.");
|
|
||||||
|
return ApiResponse.ok(savedVacations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -66,13 +66,13 @@ public interface localbordMapper {
|
|||||||
void updateComment(MapDto map);
|
void updateComment(MapDto map);
|
||||||
|
|
||||||
// 댓글에 대댓글이 있는지 확인
|
// 댓글에 대댓글이 있는지 확인
|
||||||
int selectHasReplies(MapDto map);
|
int selectReplyCount(Long parentId);
|
||||||
|
|
||||||
// 댓글 내용만 삭제 처리 (대댓글 유지)
|
// 댓글 내용만 삭제 처리 (대댓글 유지)
|
||||||
void updateSoftDeleteComment(MapDto map);
|
void updateSoftDeleteComment(Long commentId);
|
||||||
|
|
||||||
// 댓글 삭제 (대댓글 없음)
|
// 댓글 삭제 (대댓글 없음)
|
||||||
void deleteComment(MapDto map);
|
void deleteComment(Long commentId);
|
||||||
|
|
||||||
// 댓글 비밀번호 조회
|
// 댓글 비밀번호 조회
|
||||||
String selectCommentPassword(int commentId);
|
String selectCommentPassword(int commentId);
|
||||||
@ -107,6 +107,8 @@ public interface localbordMapper {
|
|||||||
|
|
||||||
void deleteFileInfo(String[] array);
|
void deleteFileInfo(String[] array);
|
||||||
|
|
||||||
|
String selectUserProfileImg(String userId);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,9 +36,11 @@ import io.company.localhost.utils.BlobUtil;
|
|||||||
import io.company.localhost.utils.PageUtil;
|
import io.company.localhost.utils.PageUtil;
|
||||||
import io.company.localhost.vo.UploadFile;
|
import io.company.localhost.vo.UploadFile;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
public class localbordService {
|
public class localbordService {
|
||||||
private final localbordMapper boardMapper;
|
private final localbordMapper boardMapper;
|
||||||
private final FileService fileService;
|
private final FileService fileService;
|
||||||
@ -148,8 +150,7 @@ public class localbordService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<MapDto> selectReply(MapDto map) {
|
public List<MapDto> selectReply(MapDto map) {
|
||||||
|
return boardMapper.selectReply(map);
|
||||||
return boardMapper.selectReply(map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertCommentOrReply(MapDto map) {
|
public void insertCommentOrReply(MapDto map) {
|
||||||
@ -173,20 +174,33 @@ public class localbordService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void deleteComment(MapDto map) {
|
public void deleteComment(MapDto map) {
|
||||||
|
Long commentId = (Long) map.get("LOCCMTSEQ");
|
||||||
// 댓글이 대댓글이 있는지 확인
|
// 댓글이 대댓글이 있는지 확인
|
||||||
boolean hasReplies = boardMapper.selectHasReplies(map) > 0;
|
boolean hasReplies = boardMapper.selectReplyCount(commentId) > 0;
|
||||||
|
|
||||||
if (hasReplies) {
|
if (hasReplies) {
|
||||||
// 대댓글이 있는 경우, '삭제된 댓글입니다.'로 변경 (소프트 삭제)
|
// 대댓글이 있는 경우, '삭제된 댓글입니다.'로 변경 (소프트 삭제)
|
||||||
boardMapper.updateSoftDeleteComment(map);
|
boardMapper.updateSoftDeleteComment(commentId);
|
||||||
} else {
|
} else {
|
||||||
// 대댓글이 없는 경우, 완전 삭제
|
// 대댓글이 없는 경우, 완전 삭제
|
||||||
boardMapper.deleteComment(map);
|
boardMapper.deleteComment(commentId);
|
||||||
}
|
}
|
||||||
|
checkAndDeleteParentComment(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String selectCommentPassword(int commentId) {
|
private void checkAndDeleteParentComment(MapDto map) {
|
||||||
|
Long parentId = (Long) map.get("LOCCMTPNT");
|
||||||
|
if (parentId == null) return; // 부모가 없으면 종료
|
||||||
|
|
||||||
|
// 부모 댓글의 남아있는 대댓글 개수 확인
|
||||||
|
int remainingReplies = boardMapper.selectReplyCount(parentId);
|
||||||
|
|
||||||
|
if (remainingReplies == 0) {
|
||||||
|
// 남은 대댓글이 없으면 부모 댓글도 삭제
|
||||||
|
boardMapper.deleteComment(parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String selectCommentPassword(int commentId) {
|
||||||
return boardMapper.selectCommentPassword(commentId);
|
return boardMapper.selectCommentPassword(commentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,6 +339,16 @@ public class localbordService {
|
|||||||
private void enrichCommentsWithAdditionalData(List<MapDto> comments) {
|
private void enrichCommentsWithAdditionalData(List<MapDto> comments) {
|
||||||
for (MapDto comment : comments) {
|
for (MapDto comment : comments) {
|
||||||
Object idObject = comment.get("LOCCMTSEQ");
|
Object idObject = comment.get("LOCCMTSEQ");
|
||||||
|
String userId = "";
|
||||||
|
|
||||||
|
// 프로필 이미지 추가
|
||||||
|
if(comment.containsKey("authorId")) {
|
||||||
|
userId = String.valueOf(comment.get("authorId"));
|
||||||
|
String profileImg = boardMapper.selectUserProfileImg(userId);
|
||||||
|
comment.put("profileImg", profileImg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (idObject instanceof Number) {
|
if (idObject instanceof Number) {
|
||||||
long commentId = ((Number) idObject).longValue();
|
long commentId = ((Number) idObject).longValue();
|
||||||
|
|
||||||
|
|||||||
@ -99,7 +99,8 @@
|
|||||||
b.LOCBRDTYP AS type,
|
b.LOCBRDTYP AS type,
|
||||||
b.LOCBRDCNT AS cnt,
|
b.LOCBRDCNT AS cnt,
|
||||||
m.MEMBERNAM AS author,
|
m.MEMBERNAM AS author,
|
||||||
m.MEMBERSEQ AS authorId
|
m.MEMBERSEQ AS authorId,
|
||||||
|
m.MEMBERPRF AS profileImg
|
||||||
FROM localbord b
|
FROM localbord b
|
||||||
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
|
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
|
||||||
WHERE b.LOCBRDSEQ = #{boardId}
|
WHERE b.LOCBRDSEQ = #{boardId}
|
||||||
@ -176,7 +177,8 @@
|
|||||||
c.LOCCMTSEQ,c.LOCBRDSEQ,c.LOCCMTPNT,c.LOCCMTRPY,
|
c.LOCCMTSEQ,c.LOCBRDSEQ,c.LOCCMTPNT,c.LOCCMTRPY,
|
||||||
c.LOCCMTUDT,c.LOCCMTPWD,c.LOCCMTRDT,c.LOCCMTPNT,
|
c.LOCCMTUDT,c.LOCCMTPWD,c.LOCCMTRDT,c.LOCCMTPNT,
|
||||||
m.MEMBERNAM AS author,
|
m.MEMBERNAM AS author,
|
||||||
m.MEMBERSEQ AS authorId
|
m.MEMBERSEQ AS authorId,
|
||||||
|
m.MEMBERPRF as profileImg
|
||||||
FROM localcomt c
|
FROM localcomt c
|
||||||
LEFT JOIN netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
|
LEFT JOIN netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
|
||||||
WHERE LOCCMTPNT = #{LOCCMTPNT} and LOCCMTPNT != 1
|
WHERE LOCCMTPNT = #{LOCCMTPNT} and LOCCMTPNT != 1
|
||||||
@ -207,7 +209,6 @@
|
|||||||
)
|
)
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
|
||||||
<!-- 댓글 삭제 (대댓글 없을 경우) -->
|
<!-- 댓글 삭제 (대댓글 없을 경우) -->
|
||||||
<delete id="deleteComment">
|
<delete id="deleteComment">
|
||||||
DELETE FROM localcomt
|
DELETE FROM localcomt
|
||||||
@ -217,9 +218,12 @@
|
|||||||
)
|
)
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<!-- 댓글에 대댓글이 있는지 확인 -->
|
<!-- 특정 댓글에 달린 대댓글 개수 조회 -->
|
||||||
<select id="selectHasReplies" resultType="int">
|
<select id="selectReplyCount" resultType="int">
|
||||||
SELECT COUNT(1) FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
|
SELECT COUNT(*)
|
||||||
|
FROM localcomt
|
||||||
|
WHERE LOCCMTPNT = #{LOCCMTSEQ}
|
||||||
|
AND LOCCMTPNT IS NOT NULL
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 댓글 비밀번호 조회 -->
|
<!-- 댓글 비밀번호 조회 -->
|
||||||
@ -247,7 +251,7 @@
|
|||||||
<select id="selectCountComments" parameterType="long" resultType="int">
|
<select id="selectCountComments" parameterType="long" resultType="int">
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM localcomt
|
FROM localcomt
|
||||||
WHERE LOCBRDSEQ = #{boardId}
|
WHERE LOCBRDSEQ = #{boardId} and LOCCMTPNT = 1
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 첨부파일 유무 -->
|
<!-- 첨부파일 유무 -->
|
||||||
@ -302,4 +306,14 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
<!-- 프로파일 이미지 조회 -->
|
||||||
|
<select id="selectUserProfileImg">
|
||||||
|
SELECT
|
||||||
|
MEMBERPRF
|
||||||
|
FROM
|
||||||
|
NETMEMBER
|
||||||
|
WHERE
|
||||||
|
MEMBERSEQ = ${userId}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@ -33,23 +33,31 @@
|
|||||||
FROM localvaca
|
FROM localvaca
|
||||||
WHERE MEMBERSEQ = #{userId}
|
WHERE MEMBERSEQ = #{userId}
|
||||||
AND YEAR(LOCVACUDT) = #{year}
|
AND YEAR(LOCVACUDT) = #{year}
|
||||||
AND DATE_FORMAT(LOCVACUDT, '%Y') = DATE_FORMAT(CURDATE(), '%Y')
|
|
||||||
GROUP BY LOCVACUDT, LOCVACTYP, LOCVACRMM
|
GROUP BY LOCVACUDT, LOCVACTYP, LOCVACRMM
|
||||||
ORDER BY LOCVACUDT DESC
|
ORDER BY LOCVACUDT DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- 사용자가 받은 연차 목록 조회 -->
|
<!-- 사용자가 받은 연차 목록 조회 -->
|
||||||
<select id="selectReceivedVacations" resultType="io.company.localhost.common.dto.MapDto">
|
<select id="selectReceivedVacations" resultType="io.company.localhost.common.dto.MapDto">
|
||||||
SELECT LOCVACUDT AS date, LOCVACTYP AS type, MEMBERSEQ AS senderId
|
SELECT
|
||||||
|
LOCVACUDT AS date,
|
||||||
|
LOCVACTYP AS type,
|
||||||
|
MEMBERSEQ AS senderId,
|
||||||
|
-- 반차(700101, 700102)는 0.5, 연차(700103)는 1로 계산하여 받은 연차 수량 저장
|
||||||
|
SUM(
|
||||||
|
CASE
|
||||||
|
WHEN LOCVACTYP IN ('700101', '700102') THEN 0.5
|
||||||
|
WHEN LOCVACTYP = '700103' THEN 1
|
||||||
|
ELSE 0
|
||||||
|
END
|
||||||
|
) AS received_quota
|
||||||
FROM localvaca
|
FROM localvaca
|
||||||
WHERE LOCVACRMM = #{userId}
|
WHERE LOCVACRMM = #{userId} -- 현재 로그인한 사용자가 받은 연차
|
||||||
AND YEAR(LOCVACUDT) = #{year}
|
AND YEAR(LOCVACUDT) = #{year} -- 해당 연도의 데이터만 가져옴
|
||||||
AND DATE_FORMAT(LOCVACUDT, '%Y') = DATE_FORMAT(CURDATE(), '%Y')
|
GROUP BY LOCVACUDT, LOCVACTYP, MEMBERSEQ -- 연차를 보낸 사람별로 그룹화
|
||||||
GROUP BY LOCVACUDT, LOCVACTYP, MEMBERSEQ
|
ORDER BY LOCVACUDT DESC;
|
||||||
ORDER BY LOCVACUDT DESC
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
<!-- 전체 직원 남은 연차 조회 -->
|
<!-- 전체 직원 남은 연차 조회 -->
|
||||||
<select id="selectEmployeeRemainingVacation" resultType="io.company.localhost.common.dto.MapDto">
|
<select id="selectEmployeeRemainingVacation" resultType="io.company.localhost.common.dto.MapDto">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user