Compare commits

...

135 Commits

Author SHA1 Message Date
aae556a180 연차 로직 변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-07-14 13:57:07 +09:00
7643723f25 로그 path 추가
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-15 15:18:11 +09:00
5516f71bfc f
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-14 13:24:33 +09:00
f1b3f1d953 ee
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-14 10:52:39 +09:00
18cf7d1a62 날씨 메인 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-11 10:18:55 +09:00
a2d57166fc 주석 제거
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-10 23:02:30 +09:00
0d6448bfbf 사원 등록 오류 수정 2025-04-10 23:00:10 +09:00
ac8d637dc2 s
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-10 16:03:38 +09:00
eea2d74c70 d
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-10 16:01:47 +09:00
0850d6d356 사원 등록에서 로그인 세션으로 등록/반려가 아닌 DB의 권한을 가져와서 처리하는 방향으로 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-10 15:22:11 +09:00
163fdb34cb 메인페이지 유저승인 api 변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-10 13:42:05 +09:00
7eaa24e4fc 휴가로직 변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-08 16:16:43 +09:00
71fa90d378 투표쿼리 변경 _메인일때만 2025-04-08 16:03:02 +09:00
0018734679 Merge branch 'khj' into main
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-08 10:52:04 +09:00
8697504d46 용어집 쿼리변경 2025-04-08 10:51:44 +09:00
yoon
aa37231f9b .
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-07 16:48:25 +09:00
yoon
c3cd6b3f5d selectbox 정렬 2025-04-07 16:47:49 +09:00
674ced8c16 사원 등록 쿼리 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-07 11:11:49 +09:00
8c3d5d1310 프로젝트 유저 색상 이름 추가
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-07 09:45:04 +09:00
29d29edaba 메인 페이지 휴가자 조회 쿼리 수정 2025-04-04 23:46:06 +09:00
yoon
8f272ce123 selectbox 2025-04-04 19:22:27 +09:00
yoon
ee1933008f 퇴근 2025-04-04 19:22:18 +09:00
yoon
b6bd7fac4d 승인여부 2025-04-04 15:45:07 +09:00
157eefdb9d 유저인포
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-04 14:19:28 +09:00
abb8a4916a 유저인포 수정 2025-04-04 14:07:44 +09:00
c9a2906e2d Merge branch 'main' of
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
http://192.168.0.251:3000/localnet/localhost-back.git into main
2025-04-04 13:29:07 +09:00
b55d150bc0 사원등록프로세스 추가, 주간 날씨 데이터 전화 프로세스 추가 2025-04-04 13:21:23 +09:00
0a127c35b4 마이페이지
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-04 10:13:56 +09:00
e4956f12b0 Merge branch 'khj' into main
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-04-01 16:18:32 +09:00
eb17f1a14e 투표 용어집 수정 2025-04-01 16:18:08 +09:00
dcb996f50b 메인 게시판 로직 수정 2025-04-01 16:13:04 +09:00
dd31e08c4f 날씨 2025-04-01 14:46:09 +09:00
yoon
a0cac0b987 usercolor 추가
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-31 19:10:05 +09:00
yoon
c73bd6459c NOT_AUTHORIZED 추가 (비인가 계정) 2025-03-31 17:41:06 +09:00
yoon
733a67fffc 따옴표 삭제 2025-03-31 16:35:29 +09:00
66fbd4fdad Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-31 13:14:41 +09:00
92e147a7df 메인 페이지 작업 2025-03-31 13:14:37 +09:00
yoon
a25b751d5e 퇴근위치
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-31 13:03:04 +09:00
yoon
436a4fc49b 출퇴근 로직변경 2025-03-31 12:48:22 +09:00
e45273a9b3 조건변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-28 15:42:18 +09:00
3b0d3b5f44 대체공휴일(~~~~)->대체공휴일
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-28 13:41:42 +09:00
c4e523843e Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-28 13:10:19 +09:00
7b2cab5b95 사용자 좋아요 싫어요 상태 내려주는 로직 추가. 2025-03-28 13:10:14 +09:00
fe3081e859 검색어 페이징 수정 2025-03-28 11:09:41 +09:00
fe7afd1d7f 1 2025-03-27 20:01:09 +09:00
yoon
1e7b380777 출근 퇴근 각각 색상 및 프젝이름 2025-03-27 18:53:19 +09:00
yoon
3ef2d8be18 출퇴근 드래그앤드랍 시 업데이트 x
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-27 18:18:50 +09:00
c1351808df 정렬 변경 2025-03-27 14:04:42 +09:00
8351e7a0d7 Merge branch 'khj' into main 2025-03-27 13:10:14 +09:00
373a8c6a5e 투표 쿼리수정 필터링 추가 2025-03-27 13:09:50 +09:00
6f968effdc 게시판
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-27 11:09:47 +09:00
92119be6fa 게시판 삭제 수정 2025-03-27 10:55:57 +09:00
01f936a407 휴가 삭제 수정 2025-03-27 09:56:17 +09:00
yoon
4fdc97fde5 Merge branch 'main' into yoon
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-25 17:46:36 +09:00
yoon
ec7e53b0b6 정렬 2025-03-25 17:46:14 +09:00
yoon
674aaba0ff 프로젝트 참여인원 포함 조회 2025-03-25 17:46:04 +09:00
b0f77138cd 게시판 검색 수정 2025-03-25 15:38:43 +09:00
4241859180 댓글삭제 로직 수정 2025-03-25 14:59:27 +09:00
e099a65006 Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-25 14:55:32 +09:00
dba1edb701 투표수정 2025-03-25 14:55:26 +09:00
9c1c8621a0 본문에 댓글의 좋아요 싫어요가 반영 안되도록 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-25 11:58:47 +09:00
4ceb2ea128 주석 오타 2025-03-24 23:30:02 +09:00
5991a59e48 용어집 에디터 이미지 파일 매핑 및 삭제 로직 추가
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-24 15:44:28 +09:00
58f7679775 Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-24 13:57:48 +09:00
dc7ab68fc6 게시판 에디터 이미지 삭제 시 파일 삭제 및 데이터 제거 추가 2025-03-24 13:57:43 +09:00
yoon
54bd9869c1 프로젝트 로직 변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-24 09:46:17 +09:00
38d4c401c3 게시글 정보가 없는 파일 삭제 스케쥴러 생성2 2025-03-24 09:40:22 +09:00
f93676081f Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-24 09:25:34 +09:00
f8ebcbd1be 게시글 정보가 없는 파일 삭제 스케쥴러 생성 2025-03-24 09:25:13 +09:00
eb1c4a6961 투표쿼리수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-21 15:08:03 +09:00
59df70ee4c 댓글 삭제시 수정됨 삭제 2025-03-21 13:20:18 +09:00
8568ad84fc 익명 닉네임 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-21 10:53:26 +09:00
fde1520377 Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-20 16:17:18 +09:00
302efa298c 에디터 첨부 이미지 게시글 번호 업데이트 로직 추가 2025-03-20 16:16:52 +09:00
5f2c4f3bd2 게시판 익명 닉네임 추가 2025-03-20 13:02:50 +09:00
f37a281f6c 공휴일 사용자 지정 추가 2025-03-20 10:14:04 +09:00
yoon
1643a5fc7c Merge branch 'main' into yoon 2025-03-20 10:08:40 +09:00
yoon
ed7623c448 프로젝트 수정 2025-03-20 10:08:18 +09:00
42bb0dd244 휴가 저장로직 수정 2025-03-19 17:45:46 +09:00
ea50617980 ErrorCode 변경 2025-03-18 20:34:27 +09:00
b16008c0d1 handler Error 수정 2025-03-18 20:10:45 +09:00
e411a0a567 게시판 통합검색(작성자,내용,제목) 추가 2025-03-18 15:59:07 +09:00
4d208ae802 댓글/ 대댓글 조회 쿼리 > 수정일 기준에서 작성일 기준 순서로 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-18 10:58:53 +09:00
4f14ef5d53 Merge branch 'khj' into main 2025-03-18 10:27:07 +09:00
49024275a4 투표 쿼리수정 2025-03-18 10:26:42 +09:00
yoon
352dc770ee 콘솔에러 안찍히게 2025-03-18 10:24:13 +09:00
09d656ee5b 수정시 멀티파일 업로드 쿼리 원복
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-17 22:04:53 +09:00
b1028b61c7 공지글 수정 권한 변경(관리자 > 작성자) 2025-03-17 21:49:17 +09:00
ea35ea3082 댓글 최신순 2025-03-17 15:52:21 +09:00
b3e3cc7277 게시판 수정 2025-03-17 15:26:22 +09:00
11550daf6f 대댓글 프로필 이미지 조회 쿼리 추가
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-17 13:57:53 +09:00
6affb7dade Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-17 13:06:58 +09:00
31cad333d1 게시글 수정 페이지 접근 시 비밀번호 확인 2025-03-17 13:06:48 +09:00
ada6654edd 휴가쿼리문 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-17 12:32:16 +09:00
e9f4cb2fc5 Admin 권한 2025-03-17 12:06:33 +09:00
yoon
778ffb5edf 필요없는 import 삭제 2025-03-17 12:04:38 +09:00
yoon
2a730cdf0b Merge branch 'main' into yoon 2025-03-17 12:02:50 +09:00
yoon
606c3c586c 개인참여기간 추가 2025-03-17 12:01:39 +09:00
e7d6db5e94 Merge branch 'khj' into main 2025-03-17 11:13:20 +09:00
920af2adfe Merge branch 'khj' into main 2025-03-17 10:55:14 +09:00
dfca1a9ee2 수정 2025-03-17 10:54:42 +09:00
yoon
558e732f62 Merge branch 'main' of
http://192.168.0.251:3000/localnet/localhost-back.git into main
2025-03-17 09:38:21 +09:00
87bf1c37de 관리자권한부여 2025-03-14 13:16:31 +09:00
yoon
1673ddccac get -> select 변경 2025-03-14 12:12:06 +09:00
yoon
214f4ec8a0 Merge branch 'main' into yoon
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-13 12:14:10 +09:00
yoon
d0f9cefa80 출퇴근 2025-03-13 12:13:31 +09:00
d34fdf1fda 응답용 프로세스 변경 2025-03-13 11:00:45 +09:00
c182f749b8 Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main 2025-03-13 10:37:23 +09:00
c277eb1a27 응답 처리 변경 2025-03-13 10:37:16 +09:00
yoon
1c42e51664 주석 수정 2025-03-12 21:39:05 +09:00
cae7928017 휴가 쿼리문 수정 2025-03-11 16:14:09 +09:00
f52b5be47c Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-11 12:46:49 +09:00
a125ad3c25 게시글 및 댓글 이미지 조회 프로세스 추가 2025-03-11 12:45:20 +09:00
3d03663896 댓글 삭제 수정 2025-03-11 10:33:37 +09:00
799945e154 게시판 댓글갯수 수정
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-10 15:49:27 +09:00
yoon
0f2777916e Merge branch 'main' into yoon 2025-03-10 15:46:32 +09:00
yoon
e8ae11250e 출퇴근 2025-03-10 15:45:58 +09:00
yoon
eb7b65aed7 연도 불러오기 쿼리 변경 2025-03-10 15:45:50 +09:00
8f3f5901da 댓글 대댓글 조회쿼리 최신순으로 변경
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-10 11:18:05 +09:00
yoon
b29c2df5e3 사용자가 속한 프로젝트 조회 쿼리 변경 2025-03-10 10:26:39 +09:00
yoon
1326e0e33f Merge branch 'main' into yoon 2025-03-09 20:48:16 +09:00
yoon
fb4c2c2180 사용자가 속한 프로젝트 조회 2025-03-09 20:47:38 +09:00
2a9fc778fb 코드수정 2025-03-07 16:19:11 +09:00
269c80eb95 Merge branch 'khj' into main 2025-03-07 13:33:05 +09:00
yoon
7091e41a18 Merge branch 'main' into yoon 2025-03-07 11:14:06 +09:00
yoon
8419f76386 프로젝트 정렬 및 로그 조회 로직 수정 2025-03-07 11:13:21 +09:00
4490655eab 게시글 수정 관련
All checks were successful
LOCALNET-DEV/pipeline/head This commit looks good
2025-03-07 10:19:32 +09:00
b7435d82f4 Merge branch 'khj' into main 2025-03-06 15:27:10 +09:00
9777553500 용어집 수정 2025-03-06 15:26:35 +09:00
yoon
7caaa0dd81 회원가입 시 색상 체크 2025-03-06 13:14:28 +09:00
yoon
24aea013bc 주석 추가 2025-03-06 13:14:10 +09:00
yoon
963ff1f106 Merge branch 'main' into yoon 2025-03-06 09:29:12 +09:00
278605e5d9 게시판 수정 2025-03-04 17:43:26 +09:00
b906ed74a7 게시판 파일다운 추가 2025-03-04 17:00:28 +09:00
yoon
0e4a9e6716 연도 최신순 정렬 2025-02-28 15:50:21 +09:00
66 changed files with 3783 additions and 565 deletions

19
WEB-INF/web.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>localhost</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -14,20 +14,23 @@
*************************************************************/
package io.company.localhost;
import io.company.localhost.common.config.ComponentScanConfig;
import io.company.localhost.common.context.ApplicationContextProvider;
import lombok.extern.slf4j.Slf4j;
import java.util.Locale;
import java.util.TimeZone;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.Locale;
import java.util.TimeZone;
import io.company.localhost.common.config.ComponentScanConfig;
import io.company.localhost.common.context.ApplicationContextProvider;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@EnableScheduling
@SpringBootApplication(scanBasePackageClasses = { ApplicationContextProvider.class , ComponentScanConfig.class} ,
exclude = {DataSourceTransactionManagerAutoConfiguration.class, TransactionAutoConfiguration.class , JacksonAutoConfiguration.class})
public class LocalhostApplication {

View File

@ -89,7 +89,7 @@ public class TransactionConfig {
// naming 설정
txAttributes.setProperty("select*", readOnlyAttribute.toString());
txAttributes.setProperty("*NewTx*", newTxAttribute.toString());
txAttributes.setProperty("insert*", newTxAttribute.toString());
txAttributes.setProperty("*NestedTx*", nestedTxAttribute.toString());
txAttributes.setProperty("*", writeTxAttribute.toString());

View File

@ -14,11 +14,12 @@
*************************************************************/
package io.company.localhost.common.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class ApiResponse<T> {
private int code;
private HttpStatus status;
@ -47,6 +48,11 @@ public class ApiResponse<T> {
public static <T> ApiResponse<T> error(HttpStatus status, String message) {
return new ApiResponse<>(status, message, null);
}
public static <T> ApiResponse<T> error(int code,HttpStatus status, String message) {
return new ApiResponse<>(code,status, message, null);
}
public static <T> ApiResponse<T> okMessage(String message) {
return new ApiResponse<>(HttpStatus.OK, message, null);
}

View File

@ -79,6 +79,23 @@ public class MapDto extends ListOrderedMap {
return null;
}
/**
* 주어진 키에 해당하는 값을 Long 타입으로 반환합니다.
* 값이 BigInteger인 경우 자동으로 long으로 변환합니다.
*
* @param key Map에서 값을 검색할
* @return 해당 키에 대한 (Long 타입), 값이 없으면 null
*/
public Long getLong(String key) {
Object value = get(key);
if (value instanceof BigInteger) {
return ((BigInteger) value).longValue();
} else if (value instanceof Long) {
return (Long) value;
}
return null;
}
public <T> List<T> getList(String key, Class<T> clazz) {
Object value = this.get(key);
if (value == null) {
@ -97,6 +114,8 @@ public class MapDto extends ListOrderedMap {
result.add(clazz.cast(item));
} else if (clazz.equals(Long.class) && item instanceof Integer) {
result.add(clazz.cast(Long.valueOf((Integer) item)));
} else if (clazz.equals(String.class) && item instanceof Integer) {
result.add(clazz.cast(String.valueOf((Integer) item)));
} else if (item instanceof Map && clazz.equals(MapDto.class)) {
result.add(clazz.cast(new MapDto((Map<String, Object>) item)));
} else {

View File

@ -26,10 +26,10 @@ public enum UserErrorCode implements ErrorCode {
NOT_AUTH_USER(HttpStatus.UNAUTHORIZED ,"로그인이 필요합니다."),
INACTIVE_USER(HttpStatus.FORBIDDEN,"권한이 필요합니다."),
USER_NOT_FOUND(HttpStatus.UNAUTHORIZED,"아이디 혹은 비밀번호가 틀렸습니다."),
NOT_AUTHORIZED(HttpStatus.UNAUTHORIZED,"비인가 계정입니다."),
EXIT_USER(HttpStatus.UNAUTHORIZED,"탈퇴한 계정입니다."),
BAD_CREDENTIAL(HttpStatus.UNAUTHORIZED, "아이디 혹은 비밀번호 문제")
USER_NOT_FOUND(10001,HttpStatus.UNAUTHORIZED,"아이디 혹은 비밀번호가 틀렸습니다."),
NOT_AUTHORIZED(10002,HttpStatus.UNAUTHORIZED,"비인가 계정입니다."),
EXIT_USER(10003,HttpStatus.UNAUTHORIZED,"탈퇴한 계정입니다."),
BAD_CREDENTIAL(10004,HttpStatus.UNAUTHORIZED, "아이디 혹은 비밀번호 문제")
;
private final long code;
@ -43,7 +43,11 @@ public enum UserErrorCode implements ErrorCode {
}
public ApiResponse<?> getApiResponse() {
return ApiResponse.error(this.getHttpStatus() , this.getMessage());
if(this.code > 10000){
return ApiResponse.error((int) this.getCode(),this.getHttpStatus() , this.getMessage());
}else{
return ApiResponse.error(this.getHttpStatus() , this.getMessage());
}
}
public ApiResponse<?> getApiResponse(String message) {

View File

@ -32,16 +32,18 @@ public class MemberAuthFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
ApiResponse<?> res = UserErrorCode.BAD_CREDENTIAL.getApiResponse();
String message = exception.getMessage();
ApiResponse<?> res = UserErrorCode.BAD_CREDENTIAL.getApiResponse();
if (exception instanceof BadCredentialsException || message.startsWith("NOT_FOUND")) {
res = UserErrorCode.USER_NOT_FOUND.getApiResponse();
} else if (message.startsWith("NOT_AUTH_USER")) {
res = UserErrorCode.NOT_AUTH_USER.getApiResponse();
} else if (message.startsWith("NOT_AUTHORIZED")) {
res = UserErrorCode.NOT_AUTHORIZED.getApiResponse();
} else if (message.startsWith("EXIT")) {

View File

@ -30,11 +30,14 @@ public class MapBasedUrlRoleMapper implements UrlRoleMapper{
public Map<String, String> getUrlRoleMappings() {
urlRoleMappings.put("/api/user/**", PERMIT_ALL);
urlRoleMappings.put("/api/project/**", ROLE_MEMBER);
urlRoleMappings.put("/api/vacation/**", PERMIT_ALL);
urlRoleMappings.put("/api/board/**", PERMIT_ALL);
urlRoleMappings.put("/api/vote/**", PERMIT_ALL);
urlRoleMappings.put("/api/worddict/**", PERMIT_ALL);
urlRoleMappings.put("/api/quilleditor/**", PERMIT_ALL);
urlRoleMappings.put("/api/vacation/**", ROLE_MEMBER);
urlRoleMappings.put("/api/board/**", ROLE_MEMBER);
urlRoleMappings.put("/api/vote/**", ROLE_MEMBER);
urlRoleMappings.put("/api/worddict/**", ROLE_MEMBER);
urlRoleMappings.put("/api/quilleditor/**", ROLE_MEMBER);
urlRoleMappings.put("/api/commuters/**", ROLE_MEMBER);
urlRoleMappings.put("/api/weather/**", ROLE_MEMBER);
urlRoleMappings.put("/api/admin/**", PERMIT_ALL);
return new HashMap<>(urlRoleMappings);
}
}

View File

@ -0,0 +1,73 @@
/************************************************************
*
* @packageName : io.company.localhost.controller.api
* @fileName : AdminController.java
* @author : 서지희
* @date : 25.03.14
* @description : 게시판
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25.03.14 서지희 최초 생성
*
*************************************************************/
package io.company.localhost.controller.api;
import java.util.List;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.company.localhost.common.annotation.Member;
import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.NetmemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/api/admin")
@RequiredArgsConstructor
@Slf4j
public class AdminController {
private final NetmemberService netmemberService;
/**
* 사원 리스트
* @return 사원 리스트
*/
@Member
@ParameterCheck
@GetMapping("/users")
public ApiResponse<List<MapDto>> selectallUserList() {
List<MapDto> response = netmemberService.selectallUserList();
return ApiResponse.ok(response);
}
/**
* 관리자 권한 수정
* @ReqMap map 요청 파라미터 (MEMBERROL, MEMBERSEQ)
* @return 결과 메시지
*/
@Member
@ParameterCheck
@PutMapping("/role")
public ApiResponse<String> updateUserRole(@ReqMap MapDto map) {
Long id = Long.valueOf(map.get("id").toString());
String role = map.get("role").toString();
String newRole = role.equalsIgnoreCase("ADMIN") ? "ROLE_ADMIN" : "ROLE_MEMBER";
netmemberService.updateUserRole(id, newRole);
return ApiResponse.ok("관리자 권한이 변경되었습니다.");
}
}

View File

@ -15,14 +15,30 @@
package io.company.localhost.controller.api;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.github.pagehelper.PageInfo;
@ -31,7 +47,6 @@ import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.common.exception.InvalidPasswordException;
import io.company.localhost.common.exception.NotFoundHandler;
import io.company.localhost.service.commoncodService;
import io.company.localhost.service.localbordService;
@ -49,6 +64,7 @@ public class BoardController {
private final commoncodService commoncodService;
private final PasswordEncoder passwordEncoder;
/**
* 공지사항 목록 조회
* @ReqMap map 요청 파라미터 (searchKeyword)
@ -58,6 +74,19 @@ public class BoardController {
@ParameterCheck
@GetMapping("/notices")
public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
// size를 안전하게 Integer로 변환하여 MapDto에 다시 넣기
Object sizeObj = map.get("size");
Integer size = null;
if (sizeObj instanceof String) {
size = Integer.parseInt((String) sizeObj);
}else {
size = null;
}
map.put("size", size);
return ApiResponse.ok(boardService.selectNotices(map));
}
@ -84,7 +113,6 @@ public class BoardController {
@PostMapping
public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) {
if (map.containsKey("LOCBRDPWD") && !map.getString("LOCBRDPWD").trim().isEmpty()) { // 체크
String rawPassword = map.getString("LOCBRDPWD");
String hashedPassword = passwordEncoder.encode(rawPassword);
@ -105,7 +133,9 @@ public class BoardController {
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
MapDto board = boardService.selectBoardDetail(boardId);
if (board == null) {
throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
//throw new NotFoundHandler("게시물 ID " + boardId + "을(를) 찾을 수 없습니다.");
String errMessage = "게시물 ID " + boardId + "을(를) 찾을 수 없습니다.";
return ApiResponse.error(HttpStatus.NOT_FOUND, errMessage);
}
// 📌 첨부파일 목록 추가
List<MapDto> attachments = boardService.selectAttachments(boardId);
@ -114,6 +144,49 @@ public class BoardController {
return ApiResponse.ok(board);
}
/**
* 게시물 수정 조회(익명 게시글은 비밀번호 필수)
*
* @param boardId
* @param map
* @return
*/
@Member
@ParameterCheck
@PostMapping("/{boardId}")
public ApiResponse<MapDto> getBoardDetail2(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("boardId", boardId);
return boardService.selectBoardDetail2(map);
}
/**
* 파일 다운로드 API
* @param path 파일 경로
* @return 파일 데이터 (바이너리 응답)
*/
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam String path) {
try {
Path filePath = Paths.get(path).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (!resource.exists() || !resource.isReadable()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
String contentType = Files.probeContentType(filePath);
String fileName = filePath.getFileName().toString();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
.header(HttpHeaders.CONTENT_TYPE, contentType != null ? contentType : "application/octet-stream")
.body(resource);
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
/**
* 게시물 삭제
* @ReqMap map 수정 데이터 (LOCBRDSEQ)
@ -123,23 +196,25 @@ public class BoardController {
@ParameterCheck
@DeleteMapping("/{boardId}")
public ApiResponse<String> deleteBoard(@ReqMap MapDto map) {
boardService.deleteBoard(map);
return ApiResponse.ok("게시물이 삭제되었습니다.");
return boardService.deleteBoard(map);
}
/**
* 게시물 수정
* @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ)
* @return 수정 결과 메시지
*
* @param map 수정 데이터 (LOCBRDTTL, LOCBRDCON, LOCBRDSEQ, delListInfo)
* @param files 첨부파일 정보
* @return
* @throws IOException
*/
@Member
@ParameterCheck
@PutMapping("/{boardId}")
public ApiResponse<String> updateBoard(@ReqMap MapDto map) {
boardService.updateBoard(map);
return ApiResponse.ok("게시물이 수정되었습니다.");
public ApiResponse<String> updateBoard(@ReqMap MapDto map, @RequestPart(value = "files", required = false) List<MultipartFile> files) throws IOException {
return boardService.updateBoardWithFiles(map, files);
}
/**
* 첨부파일 추가
* @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ)
@ -148,13 +223,20 @@ public class BoardController {
@Member
@ParameterCheck
@PostMapping("/{CMNBRDSEQ}/attachments")
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId();
map.put("CMNFLEREG", userId);
boardService.insertAttachment(map);
return ApiResponse.ok("첨부파일이 저장되었습니다.");
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map, @RequestParam("file") MultipartFile file) {
try {
Long userId = AuthUtil.getUser().getId();
map.put("CMNFLEREG", userId);
boardService.insertAttachment(map, file);
return ApiResponse.ok("첨부파일이 저장되었습니다.");
} catch (Exception e) {
return ApiResponse.ok("첨부파일 저장 실패: " + e.getMessage());
}
}
/**
* 게시물, 댓글 좋아요/싫어요 추가
* @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)
@ -172,7 +254,7 @@ public class BoardController {
/**
* 댓글 조회
* @ReqMap map 수정 데이터 (LOCBRDSEQ)
* @ReqMap map 수정 데이터 (LOCBRDSEQ, page)
* @return 댓글
*/
@Member
@ -188,7 +270,7 @@ public class BoardController {
/**
* 대댓글 조회
* @ReqMap map 수정 데이터 (LOCBRDSEQ)
* @ReqMap map 수정 데이터 (LOCCMTPNT)
* @return 대댓글
*/
@Member
@ -242,9 +324,10 @@ public class BoardController {
@Member
@ParameterCheck
@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();
map.put("LOCCMTSEQ", commentId);
map.put("LOCCMTPNT", parentId);
boardService.deleteComment(map);
return ApiResponse.ok("댓글이 삭제되었습니다.");
@ -274,11 +357,13 @@ public class BoardController {
String storedHashedPassword = boardService.selectBoardPassword(boardId);
if (storedHashedPassword == null) {
throw new NotFoundHandler("해당 게시물이 존재하지 않습니다.");
}
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
if (!isMatch) {
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
//throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다.");
}
return ApiResponse.ok(true);
@ -311,7 +396,8 @@ public class BoardController {
boolean isMatch = passwordEncoder.matches(rawPassword, storedHashedPassword);
if (!isMatch) {
throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
//throw new InvalidPasswordException("비밀번호가 일치하지 않습니다.");
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다.");
}
return ApiResponse.ok(true);
@ -322,7 +408,7 @@ public class BoardController {
* @return 카테고리 리스트
*/
@GetMapping("/categories")
public ApiResponse<List<MapDto>> getCategories() {
public ApiResponse<List<MapDto>> SelectCategories() {
List<MapDto> categories = commoncodService.selectCategoryList();
return ApiResponse.ok(categories);
}

View File

@ -0,0 +1,116 @@
/************************************************************
*
* @packageName : io.company.localhost.controller.api
* @fileName : CommuterController.java
* @author : 박지윤
* @date : 25.03.10
* @description : 출퇴근
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25.03.10 박지윤 최초 생성
*
*************************************************************/
package io.company.localhost.controller.api;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.CommutersService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@RestController
@RequestMapping("/api/commuters")
@RequiredArgsConstructor
@Slf4j
public class CommutersController {
private final CommutersService commutersService;
/**
* 출퇴근 등록
*
* @param map
* @return
*/
@PostMapping("/insert")
public ApiResponse<Integer> insertCommuters(@ReqMap MapDto map) {
int commuters = commutersService.insertCommuters(map);
return ApiResponse.ok(commuters);
}
/**
* 퇴근 업데이트
*
* @param map
* @return
*
*/
@PatchMapping("/updateLve")
public ApiResponse<Boolean> updateLeaveTime(@ReqMap MapDto map) {
boolean isLeaveTime = commutersService.updateLeaveTime(map);
return ApiResponse.ok(isLeaveTime);
}
/**
* 현재 달의 모든 출근 정보 조회
*
* @param map
* @return
*/
@GetMapping("/month")
public ApiResponse<List<MapDto>> selectCommutersByMonth(int year, int month) {
return ApiResponse.ok(commutersService.selectCommutersByMonth(year, month));
}
/**
* 오늘 사용자의 출근 정보 조회
*
* @param map
* @return
*/
@GetMapping("/today/{memberSeq}")
public ApiResponse<List<MapDto>> selectTodayCommuterInfo(@PathVariable Integer memberSeq) {
return ApiResponse.ok(commutersService.selectTodayCommuterInfo(memberSeq));
}
/**
* 오늘 출근 모든 사용자 조회
*
* @param map
* @return
*/
@GetMapping("/todays")
public ApiResponse<List<MapDto>> selectTodayCommuter() {
return ApiResponse.ok(commutersService.selectTodayCommuter());
}
/**
* 출근 프로젝트 업데이트
*
* @param map
* @return
*
*/
/*
* @PatchMapping("/update") public ApiResponse<Boolean>
* updateCommuterProject(@ReqMap MapDto map) { boolean isCommuter =
* commutersService.updateCommuterProject(map); return
* ApiResponse.ok(isCommuter); }
*/
}

View File

@ -0,0 +1,86 @@
package io.company.localhost.controller.api;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.company.localhost.common.annotation.Admin;
import io.company.localhost.common.annotation.Member;
import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.MainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/main")
public class MainController {
private final MainService mainService;
@Member
@ParameterCheck
@GetMapping("/category")
public ApiResponse<List<MapDto>> selectMainMenuCategory() {
return mainService.selectMainMenuCategory();
}
@Member
@ParameterCheck
@GetMapping("/eventList")
public ApiResponse<MapDto> selectEventList(@ReqMap MapDto map) {
return mainService.selectEventList(map);
}
@Member
@ParameterCheck
@PostMapping("/toggleEvent")
public ApiResponse<String> toggleEvent(@ReqMap MapDto map) {
return mainService.toggleEvent(map);
}
@Member
@ParameterCheck
@PostMapping("/inserEvent")
public ApiResponse<String> insertEvent(@ReqMap MapDto map) {
return mainService.insertEvent(map);
}
@Admin
@ParameterCheck
@GetMapping("/registerMemberList")
public ApiResponse<List<MapDto>> registerMemberList() {
return mainService.registerMemberList();
}
@Admin
@ParameterCheck
@PostMapping("/registerMember")
public ApiResponse<String> registerMember(@ReqMap MapDto map) {
long memberSeq = map.getInt("memberSeq");
return mainService.registerMember(memberSeq);
}
@Admin
@ParameterCheck
@PostMapping("/rejectMember")
public ApiResponse<String> rejectMember(@ReqMap MapDto map) {
long memberSeq = map.getInt("memberSeq");
return mainService.rejectMember(memberSeq);
}
@Member
@ParameterCheck
@PostMapping("/getUserLeaveRecord")
public ApiResponse<MapDto> getUserLeaveRecord(@ReqMap MapDto map) {
return mainService.getUserLeaveRecord(map);
}
}

View File

@ -17,7 +17,6 @@ package io.company.localhost.controller.api;
import java.util.List;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -61,9 +60,7 @@ public class ProjectController {
/**
* 프로젝트 목록 조회
*
* @param projectName 프로젝트 이름
* @param participantSeq 참여자 번호
* @param address 주소 정보 (주소, 상세주소, 우편번호)
* @param map
* @return
*
*/
@ -105,7 +102,7 @@ public class ProjectController {
/**
* 비밀번호 재설정
* 프로젝트 멤버 참여 업데이트
*
* @param map
* @return
@ -157,4 +154,37 @@ public class ProjectController {
return ApiResponse.ok(isDelete);
}
/**
* 사용자가 속한 프로젝트 조회
*
* @return
*
*/
@ParameterCheck
@GetMapping("{memberSeq}")
public ApiResponse<List<MapDto>> selectMemberProjects(@PathVariable int memberSeq) {
return ApiResponse.ok(promemberService.selectMemberProjects(memberSeq));
}
/**
* 프로젝트 모든 사용자 참여기간 조회
*
* @return
*
*/
@ParameterCheck
@GetMapping("/period/{projctSeq}")
public ApiResponse<List<MapDto>> selectUserProjectPeriod(@PathVariable int projctSeq) {
return ApiResponse.ok(netprojctService.selectUserProjectPeriod(projctSeq));
}
@ParameterCheck
@GetMapping("/people/{memberSeq}")
public ApiResponse<List<MapDto>> selectUserProjectPeriod2(@PathVariable int memberSeq) {
return ApiResponse.ok(netprojctService.selectUserProjectPeriod2(memberSeq));
}
}

View File

@ -13,6 +13,7 @@
*
*************************************************************/
package io.company.localhost.controller.api;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -54,11 +55,12 @@ public class VacationController {
@PostMapping
public ApiResponse<?> insertVacations(@RequestBody List<MapDto> list) {
Long user = AuthUtil.getUser().getId();
List<MapDto> savedVacations = new ArrayList<>();
for (MapDto request : list) {
String date = request.getString("date");
String type = request.getString("type");
Object receiverId = request.get("receiverId");
request.put("employeeId", user);
if (date == null || type == null) {
throw new IllegalArgumentException("요청 데이터에 누락된 값이 있습니다: " + request);
@ -68,11 +70,21 @@ public class VacationController {
if (count == null || count < 1) {
count = 1;
}
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);
}
/**
@ -88,20 +100,23 @@ public class VacationController {
List<MapDto> addRequests = map.getList("add", MapDto.class);
List<Long> deleteIds = map.getList("delete", Long.class);
if (addRequests != null) {
// 1 삭제 먼저 처리
if (deleteIds != null && !deleteIds.isEmpty()) {
localVacaService.deleteVacation(deleteIds);
}
// 2 추가 또는 업데이트 처리
if (addRequests != null && !addRequests.isEmpty()) {
for (MapDto addRequest : addRequests) {
addRequest.put("employeeId", user);
localVacaService.insertVacation(addRequest);
}
}
if (deleteIds != null) {
for (Long deleteId : deleteIds) {
localVacaService.deleteVacation(deleteId);
localVacaService.upsertVacation(addRequest);
}
}
return ApiResponse.ok("휴가 변경이 성공적으로 처리되었습니다.");
}
/**
* 전체 사원의 휴가 조회
* @param year, month

View File

@ -30,7 +30,7 @@ public class VoteBoardController {
/**
* 투표목록조회
* @param page 페이지번호 , 내가한투표 :0 투표안한것 :1 , 전체:0,투표마감:1,투표중:2
* @param page 페이지번호 , myVote 내가한투표 :1 투표안한것 :0 , 전체:0, voteset 투표마감:1,투표중:2
* @return
*/
@Member

View File

@ -31,6 +31,7 @@ import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.commoncodService;
import io.company.localhost.service.worddictyService;
import io.company.localhost.utils.AuthUtil;
import io.company.localhost.vo.MemberVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -52,10 +53,10 @@ public class worddictController {
@Member
@ParameterCheck
@GetMapping("getWordList")
public ApiResponse<MapDto> getWordList(@ReqMap MapDto map) {
public ApiResponse<MapDto> selectWordList(@ReqMap MapDto map) {
int total = worddictyservice.getTotal(map);
List<MapDto> wordList = worddictyservice.getWordList(map);
List<MapDto> wordList = worddictyservice.selectWordList(map);
MapDto OutData = new MapDto();
OutData.put("total", total);
@ -64,6 +65,18 @@ public class worddictController {
return ApiResponse.ok(OutData);
}
/**
* 용어집 검색정렬 목록
* @param
* @return
*/
@Member
@ParameterCheck
@GetMapping("getWordCategory")
public ApiResponse<List<MapDto>> selectWordCategory() {
List<MapDto> WordCategoryList = commoncodservice.selectWordCategory();
return ApiResponse.ok(WordCategoryList);
}
/**
* 용어집 카테고리 목록
* @param
@ -71,10 +84,10 @@ public class worddictController {
*/
@Member
@ParameterCheck
@GetMapping("getWordCategory")
public ApiResponse<List<MapDto>> getWordCategory() {
List<MapDto> WordCategoryList = commoncodservice.selectWordCategory();
return ApiResponse.ok(WordCategoryList);
@GetMapping("getIndexCategory")
public ApiResponse<List<MapDto>> selectIndexCategory() {
List<MapDto> selectIndexCategory = worddictyservice.selectIndexCategory();
return ApiResponse.ok(selectIndexCategory);
}
/**
* 용어집 상세 조회
@ -84,8 +97,8 @@ public class worddictController {
@Member
@ParameterCheck
@GetMapping("getWordDetail")
public ApiResponse<MapDto> getWordDetail(@ReqMap MapDto map) {
return ApiResponse.ok( worddictyservice.getWordDetail(map));
public ApiResponse<MapDto> selectWordDetail(@ReqMap MapDto map) {
return ApiResponse.ok( worddictyservice.selectWordDetail(map));
}
/**
* 용어 등록 - 카테고리 등록
@ -94,11 +107,9 @@ public class worddictController {
*/
@Member
@PostMapping("insertWord")
public ApiResponse<Long> insertWord(@AuthenticationPrincipal MemberVo memberVo,@ReqMap MapDto map) {
//userId
//Long userId = AuthUtil.getUser().getId();
//임시
int userId = 38;
public ApiResponse<Long> insertWord(@ReqMap MapDto map) {
Long userId = AuthUtil.getUser().getId();
map.put("userId", userId);
Long result = worddictyservice.insertWord(map);
@ -112,12 +123,9 @@ public class worddictController {
@Member
@ParameterCheck
@PatchMapping("updateWord")
public ApiResponse<Long> updateWord(@AuthenticationPrincipal MemberVo memberVo,@ReqMap MapDto map) {
public ApiResponse<Long> updateWord(@ReqMap MapDto map) {
//userId
//Long userId = AuthUtil.getUser().getId();
//임시
int userId = 38;
Long userId = AuthUtil.getUser().getId();
map.put("userId", userId);
Long result = worddictyservice.updateWord(map);

View File

@ -18,10 +18,12 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -29,8 +31,11 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.localbordService;
import io.company.localhost.utils.AuthUtil;
import io.company.localhost.vo.UploadFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -43,6 +48,8 @@ public class ImageUploadController {
@Value("${filePath.boardfile}")
private String boardFilePath;
private final localbordService localbordService;
/**
* quilleditor 안에서 삽입된 이미지를 서버에 저장하는 메소드
* @form-data 서버에 저장된 이미지 경로와 이름
@ -50,7 +57,8 @@ public class ImageUploadController {
*/
@ParameterCheck
@PostMapping("/upload")
public ApiResponse<String> uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
@Transactional
public ApiResponse<MapDto> uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return ApiResponse.error(HttpStatus.BAD_REQUEST, "File is empty");
@ -59,13 +67,47 @@ public class ImageUploadController {
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
String fileName = UUID.randomUUID().toString() + fileExtension;
Path filePath = Paths.get(boardFilePath, fileName);
Long fileSize = file.getSize();
Files.createDirectories(filePath.getParent());
Files.write(filePath, file.getBytes());
String fileUrl = "upload/img/board/" + fileName;
long fileIndex = insertUploadEditorImageInfo(fileName, originalFileName, filePath.toString(), fileExtension, fileSize);
return ApiResponse.ok(fileUrl);
MapDto map = new MapDto();
if(fileIndex != 0) map.put("fileIndex", fileIndex);
map.put("fileUrl", fileUrl);
return ApiResponse.ok(map);
}
/**
* 업로드 파일정보를 DB 적재
*
* @param fileName
* @param originalFileName
* @param filePath
* @param fileExtension
* @param fileSize
* @return success: DB 시퀀스 번호, fail: 0
*
*/
public long insertUploadEditorImageInfo(String fileName, String originalFileName, String filePath, String fileExtension, Long fileSize) {
Long userId = AuthUtil.getUser().getId();
MapDto map = new MapDto();
map.put("CMNFLENAM" , fileName );
map.put("CMNFLEORG" , originalFileName );
map.put("CMNFLEPAT" , filePath );
map.put("CMNFLEEXT" , fileExtension );
map.put("CMNFLESIZ" , fileSize );
map.put("CMNFLEREG" , userId );
int result = localbordService.insertUploadEditorImageInfo(map);
return result == 1 ? map.getLong("id") : 0;
}
}

View File

@ -17,10 +17,12 @@ package io.company.localhost.controller.common;
import static org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@ -28,11 +30,14 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@ -43,6 +48,7 @@ import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.service.FileService;
import io.company.localhost.service.NetmemberService;
import io.company.localhost.service.commoncodService;
import io.company.localhost.utils.AuthUtil;
@ -67,20 +73,33 @@ public class UserController {
/**
* 사용 가능 색상 조회
*
* @return ApiResponse<List<MapDto>>
* @return
*
*/
@ParameterCheck
@GetMapping("/color")
public ApiResponse<List<MapDto>> selectColorList(@RequestParam("type") String type) {
public ApiResponse<List<MapDto>> selectColorList(String type) {
List<MapDto> ColorList = commoncodservice.selectColorList(type);
return ApiResponse.ok(ColorList);
}
/**
* 색상 중복 체크
*
* @return
*
*/
@ParameterCheck
@GetMapping("/checkColor")
public ApiResponse<Boolean> selectMemberColor(String memberCol) {
boolean isDuplicate = netmemberservice.selectMemberColor(memberCol);
return ApiResponse.ok(isDuplicate);
}
/**
* MBTI 목록 조회
*
* @return ApiResponse<List<MapDto>>
* @return
*
*/
@ParameterCheck
@ -93,7 +112,7 @@ public class UserController {
/**
* 비밀번호 힌트 목록 조회
*
* @return ApiResponse<List<MapDto>>
* @return
*
*/
@ParameterCheck
@ -108,7 +127,7 @@ public class UserController {
*
* @param profile
* @param map
* @return ApiResponse<Integer>
* @return
*/
@PostMapping("/join")
public ApiResponse<Integer> register(@RequestParam("memberPrf") MultipartFile memberPrf, @ReqMap MapDto map) {
@ -120,11 +139,11 @@ public class UserController {
* 아이디 중복 체크
*
* @param memberIds
* @return ApiResponse<Boolean>
* @return
*
*/
@GetMapping("/checkId")
public ApiResponse<Boolean> selectCheckId(@RequestParam("memberIds") String memberIds) {
public ApiResponse<Boolean> selectCheckId(String memberIds) {
boolean isDuplicate = netmemberservice.selectCheckId(memberIds);
return ApiResponse.ok(!isDuplicate);
}
@ -133,11 +152,11 @@ public class UserController {
* 전화번호 중복 체크
*
* @param memberTel
* @return ApiResponse<Boolean>
* @return
*
*/
@GetMapping("/checkPhone")
public ApiResponse<Boolean> selectCheckPhone(@RequestParam String memberTel) {
public ApiResponse<Boolean> selectCheckPhone(String memberTel) {
boolean isDuplicate = netmemberservice.selectCheckPhone(memberTel);
return ApiResponse.ok(!isDuplicate);
}
@ -145,7 +164,7 @@ public class UserController {
/**
* 로그인 여부 체크
*
* @return ApiResponse<Boolean>
* @return
*/
@GetMapping("/isLogin")
public ApiResponse<Boolean> checkLogin() {
@ -157,7 +176,7 @@ public class UserController {
* 비밀번호 재설정 member 체크
*
* @param map
* @return ApiResponse<Boolean>
* @return
*
*/
@PostMapping("/pwReset")
@ -170,7 +189,7 @@ public class UserController {
* 기존 비밀번호 체크
*
* @param map
* @return ApiResponse<Boolean>
* @return
*/
@PostMapping("/checkPassword")
public ApiResponse<Boolean> selectPassword(@ReqMap MapDto map) {
@ -182,32 +201,53 @@ public class UserController {
* 비밀번호 재설정
*
* @param map
* @return ApiResponse<Boolean>
* @return
*
*/
@PatchMapping("/pwNew")
public ApiResponse<Boolean> updatePassword(@ReqMap MapDto map) {
System.out.println(map);
boolean isPwNew = netmemberservice.updatePassword(map);
return ApiResponse.ok(isPwNew);
}
// security 인증 체크
// // security 인증 체크
// @GetMapping("userInfo")
// public ApiResponse<MemberVo> getUserInfo(@AuthenticationPrincipal MemberVo memberVo) {
// SecurityContextHolderStrategy contextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
// log.info(">> contextHolderStrategy : {}", contextHolderStrategy);
// SecurityContext context = contextHolderStrategy.getContext();
// log.info(">> context : {}", context);
// Authentication authentication = context.getAuthentication();
// log.info(">> authentication : {}", authentication);
// log.info(">> memberVo : {}", memberVo);
//
// MemberVo user = AuthUtil.getUser();
// log.info(">> AuthUtil : {}", user);
//
// return ApiResponse.ok(memberVo);
// }
@GetMapping("userInfo")
public ApiResponse<MemberVo> getUserInfo(@AuthenticationPrincipal MemberVo memberVo) {
SecurityContextHolderStrategy contextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
log.info(">> contextHolderStrategy : {}", contextHolderStrategy);
SecurityContext context = contextHolderStrategy.getContext();
log.info(">> context : {}", context);
Authentication authentication = context.getAuthentication();
log.info(">> authentication : {}", authentication);
log.info(">> memberVo : {}", memberVo);
public ApiResponse<MemberVo> getUserInfo2(@AuthenticationPrincipal MemberVo memberVo) {
if(AuthUtil.getUser() != null) {
Long memberId = AuthUtil.getUser().getId();
MemberVo user = AuthUtil.getUser();
log.info(">> AuthUtil : {}", user);
log.info("🧩 memberId from AuthUtil: {}", memberId);
MemberVo user = netmemberservice.getUserInfoById(memberId);
log.info("📦 User from DB: {}", user);
return ApiResponse.ok(user);
}
return null;
return ApiResponse.ok(memberVo);
}
// @GetMapping("checkUserSession")
// public
// 유저 세션 체크
@GetMapping(value = "check")
public ApiResponse<?> check() {
@ -223,6 +263,21 @@ public class UserController {
return ApiResponse.ok(sessionData);
}
// 유저 세션 권한 체크
@PostMapping(value = "authCheck")
public ApiResponse<?> authCheck(@ReqMap MapDto map) {
String memberId = map.getString("memberId");
if(!StringUtils.hasText(memberId)) return ApiResponse.error(HttpStatus.BAD_REQUEST, "파라미터 오류");
String userRole = "";
MemberVo vo = AuthUtil.getUser();
if(vo != null && memberId.equals(vo.getLoginId())) {
userRole = vo.getRole();
}
return ApiResponse.ok(userRole);
}
// rememberMe 확인용
@GetMapping(value = "rememberCheck")
public ApiResponse<?> rememberCheck(HttpServletRequest request) {
@ -273,14 +328,11 @@ public class UserController {
/**
* 사원 목록 전체 조회
*
*
*
*/
@ParameterCheck
@GetMapping("/allUserList")
public ApiResponse<MapDto> getallUserList() {
List<MapDto> allUserList = netmemberservice.getallUserList();
public ApiResponse<MapDto> selectallUserList() {
List<MapDto> allUserList = netmemberservice.selectallUserList();
MemberVo user = AuthUtil.getUser();
MapDto outData = new MapDto();
@ -289,6 +341,27 @@ public class UserController {
return ApiResponse.ok(outData);
}
@PatchMapping("/updateInfo")
public ApiResponse<?> updateUserInfo(@ReqMap MapDto map,
@RequestPart(value = "profileFile", required = false) MultipartFile profileFile
) throws IOException {
Long userId = AuthUtil.getUser().getId();
map.put("memberId", userId);
netmemberservice.updateUserInfo(map, profileFile);
return ApiResponse.ok("수정 완료");
}
@PatchMapping("/updateColorYon")
public ApiResponse<Integer> updateColorYon(@ReqMap MapDto map) {
return ApiResponse.ok(commoncodservice.updateColorYon(map));
}
@PatchMapping("/updateColorChange")
public ApiResponse<Integer> updateColorChange(@ReqMap MapDto map) {
return ApiResponse.ok(commoncodservice.updateColorChange(map));
}
@Guest
@GetMapping("get1")
public ApiResponse<?> getAuthTest1() {

View File

@ -0,0 +1,156 @@
package io.company.localhost.controller.common;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.vo.WeatherVo;
import lombok.RequiredArgsConstructor;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/weather")
public class WeatherController {
@Value("${api.weather.key}")
private String weatherApiKey;
private final ObjectMapper objectMapper;
@GetMapping
public ApiResponse<MapDto> getWeather(@RequestParam("lat") double lat,@RequestParam("lon") double lon) throws Exception {
String url = String.format(
"https://api.openweathermap.org/data/2.5/forecast?lat=%f&lon=%f&appid=%s&units=metric&lang=kr",
lat, lon, weatherApiKey
);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
List<WeatherVo> list = this.convertDailyForecast(response);
MapDto map = new MapDto();
map.put("weatherInfo", response);
map.put("dailyWeatherList", list);
return ApiResponse.ok(map);
}
/**
* 일별 데이터 전환
*
* @param jsonData
* @return
* @throws Exception
*/
private List<WeatherVo> convertDailyForecast(String jsonData) throws Exception {
JsonNode nodeData = objectMapper.readTree(jsonData);
JsonNode forecastList = nodeData.get("list");
// 현재 날짜 시간 계산
LocalDate today = LocalDate.now();
LocalDateTime nowTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 날짜별 데이터를 그룹화
Map<String, List<String>> dailyWeathers = new HashMap<>();
Map<String, List<String>> dailyDescriptions = new HashMap<>();
Map<String, List<String>> dailyIcons = new HashMap<>();
// 오늘 예보 가장 가까운 예보 저장 변수
JsonNode closestForecastToday = null;
long minDiff = Long.MAX_VALUE;
// forecastList를 순회하며 데이터를 그룹화하고, 오늘의 경우 가장 가까운 forecast 선택
for (JsonNode forecast : forecastList) {
String dtTxt = forecast.get("dt_txt").asText();
String date = dtTxt.split(" ")[0]; // 날짜 추출 (: "2025-04-04")
JsonNode weather = forecast.get("weather").get(0);
String mainWeather = weather.get("main").asText();
String description = weather.get("description").asText();
String icon = weather.get("icon").asText();
// 해당 날짜의 리스트에 추가 (map이 없으면 생성)
dailyWeathers.computeIfAbsent(date, k -> new ArrayList<>()).add(mainWeather);
dailyDescriptions.computeIfAbsent(date, k -> new ArrayList<>()).add(description);
dailyIcons.computeIfAbsent(date, k -> new ArrayList<>()).add(icon);
// 오늘 날짜의 forecast라면 현재 시간과의 차이 계산
if (date.equals(today.toString())) {
LocalDateTime forecastTime = LocalDateTime.parse(dtTxt, formatter);
long diff = Math.abs(Duration.between(forecastTime, nowTime).toMillis());
if (diff < minDiff) {
minDiff = diff;
closestForecastToday = forecast;
}
}
}
// 최종적으로 날짜의 대표 날씨 결정
List<WeatherVo> dailyWeatherList = new ArrayList<>();
for (String date : dailyWeathers.keySet()) {
String repMainWeather;
String repDescription;
String repIcon;
// 오늘인 경우, 가장 가까운 forecast의 아이콘과 설명 사용
if (date.equals(today.toString()) && closestForecastToday != null) {
JsonNode weather = closestForecastToday.get("weather").get(0);
repMainWeather = weather.get("main").asText();
repDescription = weather.get("description").asText();
repIcon = weather.get("icon").asText();
} else {
// 기타 날짜는 기존 방식대로 가장 빈번한 날씨 상태 선택
List<String> weathers = dailyWeathers.get(date);
List<String> descriptions = dailyDescriptions.get(date);
List<String> icons = dailyIcons.get(date);
Map<String, Integer> weatherCounts = new HashMap<>();
for (String w : weathers) {
weatherCounts.put(w, weatherCounts.getOrDefault(w, 0) + 1);
}
repMainWeather = "";
int maxCount = 0;
for (Map.Entry<String, Integer> entry : weatherCounts.entrySet()) {
if (entry.getValue() > maxCount) {
maxCount = entry.getValue();
repMainWeather = entry.getKey();
}
}
int repIndex = weathers.indexOf(repMainWeather);
repDescription = descriptions.get(repIndex);
repIcon = icons.get(repIndex);
}
dailyWeatherList.add(new WeatherVo(date, repMainWeather, repDescription, repIcon));
}
return dailyWeatherList;
}
}

View File

@ -0,0 +1,42 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : CommutersMapper.java
* @author : 박지윤
* @date : 24.03.10
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.03.10 박지윤 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import io.company.localhost.common.dto.MapDto;
@Mapper
public interface CommutersMapper {
int insertCommuters(MapDto map);
int updateLeaveTime(MapDto map);
List<MapDto> selectCommutersByMonth(int year, int month);
List<MapDto> selectTodayCommuterInfo(Integer memberSeq);
List<MapDto> selectTodayCommuter();
// int updateCommuterProject(MapDto map);
int deleteCommuters(MapDto map);
MapDto selectUserLeaveWorkList(MapDto map);
}

View File

@ -0,0 +1,20 @@
package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import io.company.localhost.common.dto.MapDto;
@Mapper
public interface LocalevntMapper {
int insertEvent(MapDto map);
int selectCheckEvent(MapDto map);
List<MapDto> selectEventList(MapDto map);
int deleteEvent(MapDto map);
}

View File

@ -18,6 +18,7 @@ import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.vo.MemberVo;
@ -34,12 +35,28 @@ public interface NetmemberMapper {
int selectCheckPhone(String memberTel);
int selectMemberColor(String memberCol);
int selectPwReset(MapDto map);
String selectPassword(String id);
int updatePassword(MapDto map);
List<MapDto> getallUserList();
List<MapDto> selectallUserList();
void updateUserRole(Long id, String role);
List<MapDto> selectMemberBirthDay(MapDto map);
List<MapDto> selectRegisterMemberList();
void updateUserInfo(MapDto map);
MemberVo selectUserById(Long memberId);
int updateRegistMember(long memberSeq);
int updateRejectMember(long memberSeq);
}

View File

@ -32,4 +32,9 @@ public interface NetprojctMapper {
List<MapDto> selectProjectLog(int projctSeq);
int deleteProject(MapDto map);
List<MapDto> selectUserProjectPeriod(int projectSeq);
List<MapDto> selectUserProjectPeriod2(int memberSeq);
}

View File

@ -23,7 +23,9 @@ import io.company.localhost.common.dto.MapDto;
@Mapper
public interface PromemberMapper {
int insertProjectMember(Integer projctSeq);
int insertProjectMember(MapDto map);
int updateProjectMembers(MapDto map);
int insertNewMemberToProjects(Integer memberSeq);
@ -31,4 +33,8 @@ public interface PromemberMapper {
List<MapDto> selectProjectMembers(int projctSeq);
List<MapDto> selectMemberProjects(int memberSeq);
int deletePromember(MapDto map);
}

View File

@ -1,3 +1,17 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : VotDetailMapper.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import java.util.List;
@ -11,6 +25,6 @@ public interface VotDetailMapper {
Long insertdetail(MapDto map);
List<MapDto> selectVoteDetails(int locvotSeq);
List<MapDto> selectVoteDetailsResult(MapDto map);
}

View File

@ -1,3 +1,17 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : VotMemberMapper.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import java.util.List;
@ -13,8 +27,4 @@ public interface VotMemberMapper {
List<MapDto> selectVoteMember(Integer locvotSeq);
}

View File

@ -1,3 +1,17 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : VotRecordMapper.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import org.apache.ibatis.annotations.Mapper;
@ -7,8 +21,6 @@ import io.company.localhost.common.dto.MapDto;
@Mapper
public interface VotRecordMapper {
int selectYesVotetotal(MapDto map);
Long insertCheckedNums(MapDto map);
}

View File

@ -1,7 +1,19 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : VotchoiceMapper.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import io.company.localhost.common.dto.MapDto;
@ -11,6 +23,4 @@ public interface VotchoiceMapper {
void insertChoice(MapDto map);
List<MapDto> selectVoteResult(Integer locvotSeq);
}

View File

@ -44,4 +44,6 @@ public interface commoncodMapper {
Long selectcheckCategoryExists(MapDto map);
List<MapDto> selectVacationType();
List<MapDto> selectCodeList(MapDto map);
}

View File

@ -15,8 +15,11 @@
package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.vo.FileVo;
@Mapper
public interface localbordMapper {
@ -42,7 +45,7 @@ public interface localbordMapper {
void deleteCommentsByBoardId(MapDto map);
// 게시물 수정
void updateBoard(MapDto map);
int updateBoard(MapDto map);
// 기존 반응 조회
MapDto selectReaction(MapDto map);
@ -65,20 +68,14 @@ public interface localbordMapper {
// 댓글/대댓글 수정
void updateComment(MapDto map);
// 대댓글인지 확인
int selectIsReply(MapDto map);
// 댓글에 대댓글이 있는지 확인
int selectHasReplies(MapDto map);
int selectReplyCount(Long parentId);
// 댓글 내용만 삭제 처리 (대댓글 유지)
void updateSoftDeleteComment(MapDto map);
void updateSoftDeleteComment(Long commentId);
// 댓글 삭제 (대댓글 없음)
void deleteComment(MapDto map);
// 대댓글 삭제
void deleteReply(MapDto map);
void deleteComment(Long commentId);
// 댓글 비밀번호 조회
String selectCommentPassword(int commentId);
@ -107,6 +104,36 @@ public interface localbordMapper {
//댓글id 확인
MapDto selectCommentById(int commentId);
void insertAttachments(MapDto map);
List<String> selectDelFileInfo(String[] array);
void deleteFileInfo(String[] array);
String selectUserProfileImg(String userId);
MapDto selectBoardDetail2(Long boardId);
int insertUploadEditorImageInfo(MapDto map);
int updateBoardIndexToFile(MapDto map);
List<FileVo> selectFilesInfo(MapDto map);
void deleteFiles(MapDto map);
void deleteGoodOrBadByBoardId(MapDto map);
List<FileVo> selectFilesBoardIndexIsNull();
int deleteTrashFileData(FileVo vo);
void deleteGoodOrBadByCommentId(MapDto map);
MapDto selectMyBoardReaction(MapDto boardDetail);
MapDto selectMyBoardReactions(MapDto param);
}

View File

@ -26,7 +26,7 @@ import io.company.localhost.common.dto.MapDto;
public interface localvacaMapper {
void insertVacation(MapDto map);
void deleteVacation(Long vacationId);
void deleteVacation(@Param("vacationIds") List<Long> vacationIds);
List<MapDto> selectVacations(@Param("year") int year, @Param("month") int month);
@ -37,6 +37,12 @@ public interface localvacaMapper {
List<MapDto> selectEmployeeRemainingVacation();
List<MapDto> selectSentVacationCount(MapDto map);
Long findVacationIdByDate(@Param("userId") Long employeeId, @Param("date") String date);
void updateVacation(MapDto vacation);
List<MapDto> selectMemberVacationsInMain(@Param("year") int year, @Param("month") int month);
}

View File

@ -1,3 +1,17 @@
/************************************************************
*
* @packageName : io.company.localhost.mapper
* @fileName : localvoteMapper.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.mapper;
import java.util.List;
@ -21,5 +35,7 @@ public interface localvoteMapper {
Long updateDeleteData(MapDto map);
List<MapDto> selectVoteListWithDetails(MapDto map);
}

View File

@ -23,22 +23,24 @@ import io.company.localhost.common.dto.MapDto;
@Mapper
public interface worddictyMapper {
List<MapDto> getWordList(MapDto map);
List<MapDto> selectWordList(MapDto map);
Long insertWord(MapDto map);
Long updateWord(MapDto map);
MapDto getWordDetail(MapDto map);
MapDto selectWordDetail(MapDto map);
int getTotal(MapDto map);
Long updateword(MapDto map);
List<MapDto> selectIndexCategory();
int updateBoardIndexToFile(MapDto map);
List<String> selectDelFileInfo(String[] array);
void deleteFileInfo(String[] array);
}

View File

@ -0,0 +1,123 @@
/************************************************************
*
* @packageName : io.company.localhost.CommutersService
* @fileName : CommutersService.java
* @author : 박지윤
* @date : 25.03.10
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25.03.10 박지윤 최초 생성
*
*************************************************************/
package io.company.localhost.service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import org.springframework.stereotype.Service;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.CommutersMapper;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class CommutersService {
private final CommutersMapper commutersMapper;
/**
* 출퇴근 등록
*
* @param map
* @return
*/
public int insertCommuters(MapDto map) {
map.put("commutDay", LocalDateTime.now());
map.put("commutCme", LocalTime.now());
int result = commutersMapper.insertCommuters(map);
return result;
}
/**
* 퇴근 시간 업데이트
* @param map
* @return
*/
public boolean updateLeaveTime(MapDto map) {
if(map.get("commutLve") != null) {
map.put("commutLve", null);
map.put("commutOut", null);
map.put("projctLve", null);
} else {
map.put("commutLve", LocalTime.now());
}
return commutersMapper.updateLeaveTime(map) > 0;
}
/**
* 현재 달의 모든 출근 정보 조회
*
* @param year, month
* @return
*/
public List<MapDto> selectCommutersByMonth(int year, int month) {
return commutersMapper.selectCommutersByMonth(year, month);
}
/**
* 오늘 사용자 출근 정보 조회
*
* @param memberSeq
* @return
*/
public List<MapDto> selectTodayCommuterInfo(Integer memberSeq) {
return commutersMapper.selectTodayCommuterInfo(memberSeq);
}
/**
* 오늘 출근 모든 사용자 조회
*
* @param
* @return
*/
public List<MapDto> selectTodayCommuter() {
return commutersMapper.selectTodayCommuter();
}
/**
* 출근 프로젝트 업데이트
*
* @param map
* @return
*/
/*
* public boolean updateCommuterProject(MapDto map) { return
* commutersMapper.updateCommuterProject(map) > 0; }
*/
/**
* 사용자의 퇴근 기록 조회
*
* @return
*/
public ApiResponse<MapDto> selectUserLeaveWorkList(@ReqMap MapDto map) {
map.put("currentDate", LocalDateTime.now());
return ApiResponse.ok(commutersMapper.selectUserLeaveWorkList(map));
}
}

View File

@ -19,11 +19,15 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.UUID;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import io.company.localhost.utils.FileUtil;
import io.company.localhost.vo.UploadFile;
import lombok.RequiredArgsConstructor;
@Service
@ -34,6 +38,11 @@ public class FileService {
@Value("${filePath.profile}")
private String uploadPath;
@Value("${filePath.boardfile}")
private String boardFilePath;
private final FileUtil fileUtil;
/**
* 파일 업로드
*
@ -65,4 +74,79 @@ public class FileService {
throw new RuntimeException("파일 업로드 실패: " + e.getMessage());
}
}
/**
* 게시판 파일 업로드
*
* @param file
* @return
* @throws RuntimeException
*/
public String boardUploadFile(MultipartFile file) {
try {
System.out.println(file);
// 원본 파일명
String originalFilename = file.getOriginalFilename();
// 파일 확장자
String extension = FilenameUtils.getExtension(originalFilename);
// UUID를 사용하여 고유한 파일명 생성
String newFilename = UUID.randomUUID().toString() + "." + extension;
// 최종 저장 경로 생성 (기본경로 + 파일명)
Path targetPath = Paths.get(boardFilePath, newFilename);
// 저장될 디렉토리가 없는 경우 생성
Files.createDirectories(targetPath.getParent());
// 동일 파일명이 있을 경우 덮어쓰기
Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
// 저장된 파일의 상대 경로 반환
return targetPath.toString();
} catch (IOException e) {
throw new RuntimeException("파일 업로드 실패: " + e.getMessage());
}
}
/**
* 게시판 다중파일 업로드
*
* @param files
* @return
* @throws IOException
*/
public List<UploadFile> boardUploadFiles(List<MultipartFile> files) throws IOException {
return fileUtil.uploadFiles(boardFilePath, files);
}
/**
* 파일 삭제
*
* @param path 경로+파일명
* @return
*/
public boolean removeFile(String path) {
return fileUtil.removeFile(path);
}
/**
* 파일 삭제
*
* @param path
* @param fileName
* @return
*/
public boolean removeFile(String path, String fileName) {
return fileUtil.removeFile(path, fileName);
}
/**
* 게시글 파일 삭제
*
* @param fileName
* @return
*/
public boolean removeBoardFile(String fileName) {
return fileUtil.removeFile(boardFilePath, fileName);
}
}

View File

@ -0,0 +1,53 @@
/************************************************************
*
* @packageName : io.company.localhost.service
* @fileName : LocalbordService.java
* @author : 박성용
* @date : 25.03.30
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25.03.30 박성용 최초 생성
*
*************************************************************/
package io.company.localhost.service;
import java.util.List;
import org.springframework.stereotype.Service;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.LocalevntMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Service
@RequiredArgsConstructor
@Slf4j
public class LocalevntService {
private final LocalevntMapper localevntMapper;
public int insertEvent(MapDto map) {
return localevntMapper.insertEvent(map);
}
public int selectCheckEvent(MapDto map) {
return localevntMapper.selectCheckEvent(map);
}
public List<MapDto> selectEventList(MapDto map) {
return localevntMapper.selectEventList(map);
}
public int deleteEvent(MapDto map) {
return localevntMapper.deleteEvent(map);
}
}

View File

@ -0,0 +1,142 @@
/************************************************************
*
* @packageName : io.company.localhost.CommutersService
* @fileName : MainService.java
* @author : 박성용
* @date : 25.03.17
* @description : 메인페이지 비지니스 로직
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 25.03.17 박성용 최초 생성
*
*************************************************************/
package io.company.localhost.service;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.utils.AuthUtil;
import io.company.localhost.vo.MemberVo;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class MainService {
private final commoncodService commoncodService;
private final NetmemberService netmemberService;
private final localvacaService localvacaService;
private final LocalevntService localevntService;
private final CommutersService commutersService;
/**
* 메인페이지 카테고리 메뉴 조회
*
* @return
*/
public ApiResponse<List<MapDto>> selectMainMenuCategory() {
return ApiResponse.ok(commoncodService.selectCodeList("300", "200"));
}
/**
* 메인페이지 이벤트 리스트
*
* @param map (year, month)
* @return { 생일자, 휴가자, 생일파티, 회식, 티타임, 워크샵 } 일정
*/
public ApiResponse<MapDto> selectEventList(MapDto map) {
int year = Integer.valueOf(map.getString("year"));
int month = Integer.valueOf(map.getString("month"));
map.put("memberBirthdayList", netmemberService.selectMemberBirthDay(map)); //생일자 조회
map.put("memberVacationList", localvacaService.selectMemberVacationsInMain(year, month)); //휴가자 조회
map.put("eventList", localevntService.selectEventList(map));
return ApiResponse.ok(map);
}
/**
* 이벤트 생성/삭제
*
* @param map (code, date)
* @return
*/
public ApiResponse<String> toggleEvent(MapDto map) {
if(localevntService.selectCheckEvent(map) > 0) {
localevntService.deleteEvent(map);
return ApiResponse.okMessage("이벤트 삭제");
} else {
return ApiResponse.error(HttpStatus.CONFLICT, "해당 이벤트가 존재하지 않습니다");
}
}
public ApiResponse<String> insertEvent(MapDto map) {
if(localevntService.selectCheckEvent(map) > 0) {
return ApiResponse.error(HttpStatus.CONFLICT, "이미 동일한 이벤트가 존재합니다");
} else {
localevntService.insertEvent(map);
return ApiResponse.okMessage("이벤트 추가");
}
}
/**
* 사원 등록 대상자 목록 조회
*
* @return
*/
public ApiResponse<List<MapDto>> registerMemberList() {
return ApiResponse.ok(netmemberService.selectRegisterMemberList());
}
/**
* 사원 등록 승인
* @param memberSeq
*
* @return
*/
public ApiResponse<String> registerMember(long memberSeq) {
Long loginUserId = AuthUtil.getUser().getId();
MemberVo user = netmemberService.getUserInfoById(loginUserId);
if(user.getId() != loginUserId || !"ROLE_ADMIN".equals(user.getRole())) {
return ApiResponse.error(HttpStatus.FORBIDDEN, "사용 권한 없음");
}
int result = netmemberService.registerMember(memberSeq);
return result == 1 ? ApiResponse.ok("사원 등록 성공") : ApiResponse.ok("사원 등록 실패");
}
/**
* 사원 등록 거절
*
* @param memberSeq
* @return
*/
public ApiResponse<String> rejectMember(long memberSeq) {
Long loginUserId = AuthUtil.getUser().getId();
MemberVo user = netmemberService.getUserInfoById(loginUserId);
if(user.getId() != loginUserId || !"ROLE_ADMIN".equals(user.getRole())) {
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "사용 권한 없음");
}
int result = netmemberService.rejectMember(memberSeq);
return result == 1 ? ApiResponse.ok("미승인 대상자 등록") : ApiResponse.ok("미승인 대상자 등록 실패");
}
public ApiResponse<MapDto> getUserLeaveRecord(MapDto map) {
return commutersService.selectUserLeaveWorkList(map);
}
}

View File

@ -14,6 +14,7 @@
*************************************************************/
package io.company.localhost.service;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
@ -21,10 +22,12 @@ import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.NetmemberMapper;
import io.company.localhost.mapper.PromemberMapper;
import io.company.localhost.mapper.commoncodMapper;
import io.company.localhost.vo.MemberVo;
import lombok.RequiredArgsConstructor;
@Service
@ -56,7 +59,7 @@ public class NetmemberService {
map.put("memberRol", "ROLE_MEMBER");
map.put("memberPos", 500107);
map.put("memberTkn", "Null");
map.put("memberPrm", "Y");
map.put("memberPrm", "N");
map.put("memberDel", "N");
map.put("memberLea", "N");
map.put("memberRdt", LocalDateTime.now());
@ -102,16 +105,37 @@ public class NetmemberService {
return memberMapper.selectCheckPhone(memberTel) > 0;
}
/**
* 색상 중복 체크
*
* @param memberCol
* @return
*/
public boolean selectMemberColor(String memberCol) {
return memberMapper.selectMemberColor(memberCol) > 0;
}
/**
* 사원 목록 전체 조회
*
* @param
* @return
*/
public List<MapDto> getallUserList() {
return memberMapper.getallUserList();
public List<MapDto> selectallUserList() {
return memberMapper.selectallUserList();
}
/**
* 사원 권한 업데이트
*
* @param
* @return
*/
public void updateUserRole(Long id, String newRole) {
memberMapper.updateUserRole(id, newRole);
}
/**
* 로그인 토큰
*
@ -159,4 +183,50 @@ public class NetmemberService {
return memberMapper.updatePassword(map) > 0;
}
/**
* 멤버 생일 조회
*
* @param map (year, month)
* @return
*/
public List<MapDto> selectMemberBirthDay(MapDto map) {
return memberMapper.selectMemberBirthDay(map);
}
/**
* 등록 대기 멤버 조회
*
* @param map
* @return
*/
public List<MapDto> selectRegisterMemberList() {
return memberMapper.selectRegisterMemberList();
}
public void updateUserInfo(MapDto map, MultipartFile profileFile) throws IOException {
// 프로필 이미지 저장 처리
if (profileFile != null && !profileFile.isEmpty()) {
String savedFilePath = fileService.uploadFile(profileFile);
map.put("memberPrf", savedFilePath); // DB 컬럼에 맞게 추가
}
System.out.println(map);
// DB 업데이트
memberMapper.updateUserInfo(map);
}
public MemberVo getUserInfoById(Long memberId) {
return memberMapper.selectUserById(memberId);
}
public int registerMember(long memberSeq) {
return memberMapper.updateRegistMember(memberSeq);
}
public int rejectMember(long memberSeq) {
return memberMapper.updateRejectMember(memberSeq);
}
}

View File

@ -16,12 +16,12 @@ package io.company.localhost.service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.CommutersMapper;
import io.company.localhost.mapper.NetprojctMapper;
import io.company.localhost.mapper.PromemberMapper;
import io.company.localhost.mapper.commoncodMapper;
@ -33,6 +33,7 @@ public class NetprojctService {
private final commoncodMapper commoncodMapper;
private final NetprojctMapper netprojctMapper;
private final PromemberMapper promemberMapper;
private final CommutersMapper commutersMapper;
/**
@ -55,6 +56,46 @@ public class NetprojctService {
public int insertProject(MapDto map) {
map.put("projctCdt", LocalDateTime.now());
int result = netprojctMapper.insertProject(map);
Integer color = map.getInt("projctCol");
// 컬러 업데이트
MapDto colorMap = new MapDto();
colorMap.put("color", color);
colorMap.put("type", "YNP");
commoncodMapper.updateColorYon(colorMap);
Integer projctSeq = map.getInt("PROJCTSEQ");
// 비활성화된 사용자 목록 받아오기
List<Integer> disabledMembers = (List<Integer>) map.get("disabledMembers");
// 프로젝트 멤버 추가 (비활성화된 사용자 정보 포함)
MapDto paramMap = new MapDto();
paramMap.put("projctSeq", projctSeq);
paramMap.put("disabledMembers", disabledMembers);
promemberMapper.insertProjectMember(paramMap);
return result;
}
/**
* 프로젝트 수정
*
* @param map
* @return
*/
/**
* 프로젝트 수정
*
* @param map
* @return
*/
public boolean updateProject(MapDto map) {
map.put("projctUdt", LocalDateTime.now());
boolean result = netprojctMapper.updateProject(map) > 0;
Integer color = map.getInt("projctCol");
@ -64,45 +105,29 @@ public class NetprojctService {
commoncodMapper.updateColorYon(colorMap);
Integer projctSeq = map.getInt("PROJCTSEQ");
promemberMapper.insertProjectMember(projctSeq);
return result;
}
/**
* 프로젝트 수정
*
* @param map
* @return
*/
public boolean updateProject(MapDto map) {
map.put("projctUdt", LocalDateTime.now());
boolean result = netprojctMapper.updateProject(map) > 0;
Integer color = map.getInt("projctCol");
MapDto colorMap = new MapDto();
colorMap.put("color", color);
colorMap.put("type", "YNP");
commoncodMapper.updateColorYon(colorMap);
Integer originalColor = map.getInt("originalColor");
if(originalColor != null) {
MapDto OldColorMap = new MapDto();
OldColorMap.put("color", originalColor);
OldColorMap.put("type", "YNP");
MapDto OldColorMap = new MapDto();
OldColorMap.put("color", originalColor);
OldColorMap.put("type", "YNP");
commoncodMapper.updateColorChange(OldColorMap);
commoncodMapper.updateColorChange(OldColorMap);
}
// 멤버 상태 업데이트
Integer projctSeq = map.getInt("projctSeq");
List<Integer> disabledMembers = (List<Integer>) map.get("disabledMembers");
if (disabledMembers != null) {
MapDto memberMap = new MapDto();
memberMap.put("projctSeq", projctSeq);
memberMap.put("disabledMembers", disabledMembers);
promemberMapper.updateProjectMembers(memberMap);
}
return result;
}
return result;
}
/**
@ -123,6 +148,10 @@ public class NetprojctService {
*/
public boolean deleteProject(MapDto map) {
promemberMapper.deletePromember(map);
commutersMapper.deleteCommuters(map);
boolean result = netprojctMapper.deleteProject(map) > 0;
Integer color = map.getInt("projctCol");
@ -136,4 +165,18 @@ public class NetprojctService {
return result;
}
/**
* 프로젝트 모든 사용자 참여기간 조회
*
* @param
* @return
*/
public List<MapDto> selectUserProjectPeriod(int projctSeq) {
return netprojctMapper.selectUserProjectPeriod(projctSeq);
}
public List<MapDto> selectUserProjectPeriod2(int memberSeq) {
return netprojctMapper.selectUserProjectPeriod2(memberSeq);
}
}

View File

@ -48,6 +48,16 @@ public class ProMemberService {
return promemberMapper.selectProjectMembers(projctSeq);
}
/**
* 사용자가 속한 프로젝트 조회
*
* @param
* @return
*/
public List<MapDto> selectMemberProjects(int memberSeq) {
return promemberMapper.selectMemberProjects(memberSeq);
}
}

View File

@ -22,6 +22,7 @@ import org.springframework.stereotype.Service;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.common.exception.NotFoundHandler;
import io.company.localhost.mapper.commoncodMapper;
import io.company.localhost.utils.StringUtil;
import lombok.RequiredArgsConstructor;
@Service
@ -60,4 +61,22 @@ public class commoncodService {
// 데이터가 비어있으면 리스트 반환 (null 방지)
return (codeList != null) ? codeList : new ArrayList<>();
}
public List<MapDto> selectCodeList(String code1, String code2) {
if(!StringUtil.isNumeric(code1) || !StringUtil.isNumeric(code2)) throw new IllegalArgumentException("파라미터는 반드시 숫자 타입이여야 함");
MapDto map = new MapDto();
map.put("CMNCODLV1", code1);
map.put("CMNCODLV2", code2.substring(0, 1));
return commoncodmapper.selectCodeList(map);
}
public int updateColorYon(MapDto map) {
return commoncodmapper.updateColorYon(map);
}
public int updateColorChange(MapDto map) {
return commoncodmapper.updateColorChange(map);
}
}

View File

@ -14,38 +14,56 @@
*************************************************************/
package io.company.localhost.service;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import io.company.localhost.utils.BlobUtil;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.localbordMapper;
import io.company.localhost.utils.AuthUtil;
import io.company.localhost.utils.BlobUtil;
import io.company.localhost.utils.PageUtil;
import io.company.localhost.vo.FileVo;
import io.company.localhost.vo.MemberVo;
import io.company.localhost.vo.UploadFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Service
@RequiredArgsConstructor
@Slf4j
public class localbordService {
private final localbordMapper boardMapper;
private final FileService fileService;
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
private final PasswordEncoder passwordEncoder;
public List<MapDto> selectNotices(MapDto map) {
map.put("searchKeyword", null);
List<MapDto> posts = boardMapper.selectNotices(map);
enrichPostsWithAdditionalData(posts);
return posts;
return posts; // 검색 없이 전체 공지사항 리스트 반환
}
public PageInfo<MapDto> selectGeneralPosts(MapDto map) {
System.out.println(map);
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10;
@ -54,19 +72,42 @@ public class localbordService {
map.put("orderBy", "date");
}
PageHelper.startPage(page, size);
String keyword = map.getString("searchKeyword");
boolean hasKeyword = keyword != null && !keyword.trim().isEmpty();
if (hasKeyword) {
// 전체 데이터를 가져와서 필터링
map.put("searchKeyword", null);
List<MapDto> allPosts = boardMapper.selectGeneralPosts(map);
enrichPostsWithAdditionalData(allPosts);
// 검색어 기반 필터링
List<MapDto> filtered = filterPostsByKeyword(allPosts, keyword.trim());
// Java에서 수동 페이징
int fromIndex = (page - 1) * size;
int toIndex = Math.min(fromIndex + size, filtered.size());
List<MapDto> pagedList = fromIndex >= filtered.size() ? new ArrayList<>() : filtered.subList(fromIndex, toIndex);
PageInfo<MapDto> pageInfo = new PageInfo<>(pagedList);
pageInfo.setTotal(filtered.size());
return PageUtil.redefineNavigation(pageInfo);
}
// 키워드 없으면 MyBatis에서 DB 페이징 처리
PageHelper.startPage(page, size);
List<MapDto> result = boardMapper.selectGeneralPosts(map);
enrichPostsWithAdditionalData(result);
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
return PageUtil.redefineNavigation(new PageInfo<>(result));
}
public void updateIncrementViewCount(Long boardId) {
boardMapper.updateIncrementViewCount(boardId);
}
public BigInteger insertBoard(MapDto map) {
@SuppressWarnings("unchecked")
@Transactional
public BigInteger insertBoard(MapDto map) {
// 익명게시판이면 회원 정보를 null로 설정
if ("300102".equals(String.valueOf(map.get("LOCBRDTYP")))) {
map.put("MEMBERSEQ", null);
@ -75,17 +116,33 @@ public class localbordService {
map.put("MEMBERSEQ", userId);
}
boardMapper.insertBoard(map);
//에디터 첨부 이미지 게시글 번호 업데이트
if(map.get("editorUploadedImgList") != null) {
ArrayList<String> editorUploadedImgList = (ArrayList<String>) map.get("editorUploadedImgList");
map.put("editorImgList", editorUploadedImgList);
this.updateBoardIndexToFile(map);
}
// 에디터 수정 업로드 에디터 이미지 삭제
if(map.get("editorDeleteImgList") != null) {
ArrayList<String> editorDeleteImgList = (ArrayList<String>) map.getList("editorDeleteImgList", String.class);
String[] array = editorDeleteImgList.stream().toArray(String[]::new);
this.deleteFileAndData(array);
}
return (BigInteger) map.get("LOCBRDSEQ");
}
public void insertAttachment(MapDto map) {
public void insertAttachment(MapDto map, MultipartFile file) {
String boardSeqStr = (String) map.get("CMNBRDSEQ");
Long boardSeq = Long.parseLong(boardSeqStr);
map.put("CMNBRDSEQ", boardSeq);
String newFilename = UUID.randomUUID().toString();
map.put("CMNFLENAM", newFilename);
String Path = fileService.boardUploadFile(file);
map.put("CMNFLEPAT", Path);
boardMapper.insertAttachment(map);
}
@ -111,13 +168,51 @@ public class localbordService {
return boardMapper.selectAttachments(boardId);
}
public void deleteBoard(MapDto map) {
boardMapper.deleteCommentsByBoardId(map);
boardMapper.deleteBoard(map);
@Transactional
public ApiResponse<String> deleteBoard(MapDto map) {
boardMapper.deleteCommentsByBoardId(map); // 댓글 대댓글
boardMapper.deleteGoodOrBadByBoardId(map); // 좋아요 싫어요 삭제
this.deleteBoardFiles(map); // 파일 삭제
boardMapper.deleteBoard(map); // 게시글 삭제
return ApiResponse.ok("게시물이 삭제되었습니다.");
}
public void updateBoard(MapDto map) {
boardMapper.updateBoard(map);
/**
* 게시글 첨부파일 에디터 이미지 파일 삭제
*
* @param map
*/
private void deleteBoardFiles(MapDto map) {
List<FileVo> list = this.selectFilesInfo(map); // 삭제 파일 정보 조회
for(FileVo vo : list) {
String fileName = vo.getCMNFLEPAT();
//if(!fileName.contains(vo.getCMNFLEEXT())) fileName = fileName + vo.getCMNFLEEXT();
fileService.removeFile(fileName); // 파일 삭제
}
this.deleteFiles(map); // 파일 데이터 삭제
}
/**
* 게시글 파일정보 삭제
* @param map
*/
public void deleteFiles(MapDto map) {
boardMapper.deleteFiles(map);
}
/**
* 게시글 파일 정보 조회
*
* @param map
* @return
*/
public List<FileVo> selectFilesInfo(MapDto map) {
return boardMapper.selectFilesInfo(map);
}
public int updateBoard(MapDto map) {
return boardMapper.updateBoard(map);
}
public void procReactToBoard(MapDto map) {
@ -136,13 +231,13 @@ public class localbordService {
PageHelper.startPage(page, size);
List<MapDto> result = boardMapper.selectComments(map);
enrichCommentsWithAdditionalData(result); // 댓글 데이터 보강
enrichCommentsWithAdditionalData(map, result); // 댓글 데이터 보강
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
}
public List<MapDto> selectReply(MapDto map) {
return boardMapper.selectReply(map);
return boardMapper.selectReply(map);
}
public void insertCommentOrReply(MapDto map) {
@ -166,27 +261,34 @@ public class localbordService {
}
public void deleteComment(MapDto map) {
// 댓글이 대댓글인지 확인
boolean isReply = boardMapper.selectIsReply(map) > 0;
if (isReply) {
// 대댓글이면 바로 삭제
boardMapper.deleteReply(map);
Long commentId = (Long) map.get("LOCCMTSEQ");
// 댓글이 대댓글이 있는지 확인
boolean hasReplies = boardMapper.selectReplyCount(commentId) > 0;
if (hasReplies) {
// 대댓글이 있는 경우, '삭제된 댓글입니다.' 변경 (소프트 삭제)
boardMapper.updateSoftDeleteComment(commentId);
} else {
// 댓글에 대댓글이 있는지 확인
boolean hasReplies = boardMapper.selectHasReplies(map) > 0;
// 대댓글이 없는 경우, 완전 삭제
boardMapper.deleteComment(commentId);
}
checkAndDeleteParentComment(map);
boardMapper.deleteGoodOrBadByCommentId(map);
}
if (hasReplies) {
// 대댓글이 있는 경우, '삭제된 댓글입니다.' 변경 (소프트 삭제)
boardMapper.updateSoftDeleteComment(map);
} else {
// 대댓글이 없는 경우, 완전 삭제
boardMapper.deleteComment(map);
}
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) {
public String selectCommentPassword(int commentId) {
return boardMapper.selectCommentPassword(commentId);
}
@ -215,21 +317,19 @@ public class localbordService {
return boardMapper.selectCountCommentReactions(boardId);
}
private String procFirstImageUrl(String jsonContent) {
public static String procFirstImageUrl(String jsonContent) {
try {
// JSON 유효성 검사
if (!procIsValidJson(jsonContent)) {
throw new IllegalArgumentException("Invalid JSON content: " + jsonContent);
}
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonContent);
// JSON 배열 순회
for (JsonNode node : rootNode) {
JsonNode insertNode = node.get("insert");
if (insertNode != null && insertNode.has("image")) {
return insertNode.get("image").asText(); // 번째 이미지 URL 반환
// "ops" 배열 가져오기
JsonNode opsNode = rootNode.get("ops");
if (opsNode != null && opsNode.isArray()) {
for (JsonNode node : opsNode) {
JsonNode insertNode = node.get("insert");
if (insertNode != null && insertNode.has("image")) {
return insertNode.get("image").asText(); // 번째 이미지 URL 반환
}
}
}
} catch (Exception e) {
@ -239,56 +339,81 @@ public class localbordService {
return null; // 이미지가 없는 경우
}
private boolean procIsValidJson(String json) {
public String extractPlainText(String deltaJson) {
StringBuilder sb = new StringBuilder();
ObjectMapper mapper = new ObjectMapper();
try {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.readTree(json); // JSON 파싱 시도
return true; // JSON이 유효하면 true 반환
} catch (Exception e) {
return false; // 유효하지 않은 경우 false 반환
}
}
JsonNode root = mapper.readTree(deltaJson);
JsonNode ops = root.get("ops");
private String procPlainTextFromJson(String jsonContent) {
StringBuilder plainTextBuilder = new StringBuilder();
try {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonContent);
if (ops != null && ops.isArray()) {
for (JsonNode op : ops) {
JsonNode insertNode = op.get("insert");
// JSON 배열인지 확인
if (!rootNode.isArray()) {
System.err.println("JSON content is not an array");
return "";
}
// JSON 노드 순회
for (JsonNode node : rootNode) {
JsonNode insertNode = node.get("insert");
// insert 노드가 텍스트인지 확인
if (insertNode != null && insertNode.isTextual()) {
String text = insertNode.asText();
// '\n' 제거하고 순수 텍스트만 추가
if (!text.trim().isEmpty() && !text.trim().equals("\n")) {
plainTextBuilder.append(text.trim());
// insert가 문자열일 경우만 추출
if (insertNode != null && insertNode.isTextual()) {
String text = insertNode.asText();
if (!"\n".equals(text.trim())) { // 줄바꿈 제외
sb.append(text).append(" ");
}
}
// insert가 객체면 image일 가능성 제외
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Failed to extract plain text: " + e.getMessage(), e);
e.printStackTrace(); // 실제 운영에서는 로깅 처리
}
return plainTextBuilder.toString();
return sb.toString().trim();
}
/**
* 검색어로 순수 텍스트 기준 게시글 필터링
*/
private List<MapDto> filterPostsByKeyword(List<MapDto> posts, String keyword) {
if (keyword == null || keyword.trim().isEmpty()) return posts;
keyword = keyword.trim();
List<MapDto> filtered = new ArrayList<>();
for (MapDto post : posts) {
String title = post.getString("title");
String author = post.getString("author");
String contentJson = BlobUtil.procBlobToString(post.get("content")); // Blob 처리
String plainText = extractPlainText(contentJson);
// 포함 여부 판단 (title, author, content 순수 텍스트)
if ((title != null && title.contains(keyword)) ||
(author != null && author.contains(keyword)) ||
plainText.contains(keyword)) {
post.put("content", contentJson); // content는 원래대로 복원
filtered.add(post);
}
}
return filtered;
}
private void enrichBoardDetail(MapDto boardDetail) {
if(boardDetail == null) return;
long userId = AuthUtil.getUser().getId();
long boardId = ((Number) boardDetail.get("id")).longValue();
boardDetail.put("userId", userId);
boardDetail.put("hasAttachment", selectIsAttachments(boardId));
boardDetail.put("commentCount", selectCountComments(boardId));
MapDto reactions = selectCountBoardReactions(boardId);
long myReaction = this.selectMyBoardReaction(boardDetail);
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
boardDetail.put("myReaction", myReaction);
// Blob 데이터를 문자열로 변환
Object content = boardDetail.get("content");
@ -298,7 +423,44 @@ public class localbordService {
}
}
private void enrichPostsWithAdditionalData(List<MapDto> posts) {
// 사용자 게시글 좋아요/싫어요 조회
private long selectMyBoardReaction(MapDto boardDetail) {
MapDto map = boardMapper.selectMyBoardReaction(boardDetail);
long result = 3;
if(map == null) {
result = 3;
} else if("T".equals(map.getString("LOCGOBGOD")) && "F".equals(map.getString("LOCGOBBAD"))) {
result = 1;
} else if("F".equals(map.getString("LOCGOBGOD")) && "T".equals(map.getString("LOCGOBBAD"))) {
result = 2;
} else {
result = 3;
}
return result;
}
// 사용자 댓글 좋아요/싫어요 조회
private long selectMyBoardReactions(MapDto param) {
MapDto map = boardMapper.selectMyBoardReactions(param);
long result = 3;
if(map == null) {
result = 3;
} else if("T".equals(map.getString("LOCGOBGOD")) && "F".equals(map.getString("LOCGOBBAD"))) {
result = 1;
} else if("F".equals(map.getString("LOCGOBGOD")) && "T".equals(map.getString("LOCGOBBAD"))) {
result = 2;
} else {
result = 3;
}
return result;
}
private void enrichPostsWithAdditionalData(List<MapDto> posts) {
for (MapDto post : posts) {
Object idObject = post.get("id");
if (idObject instanceof Number) {
@ -316,26 +478,220 @@ public class localbordService {
String firstImageUrl = procFirstImageUrl(contentString);
post.put("firstImageUrl", firstImageUrl);
String plainContent = procPlainTextFromJson(contentString);
post.put("plainContent", plainContent);
}
}
}
private void enrichCommentsWithAdditionalData(List<MapDto> comments) {
private void enrichCommentsWithAdditionalData(MapDto map, List<MapDto> comments) {
for (MapDto comment : comments) {
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) {
long commentId = ((Number) idObject).longValue();
long id = AuthUtil.getUser().getId(); //사용자 아이디
MapDto reactions = boardMapper.selectCountCommentReactions(commentId);
comment.put("likeCount", reactions != null ? reactions.getOrDefault("likeCount", 0) : 0);
comment.put("dislikeCount", reactions != null ? reactions.getOrDefault("dislikeCount", 0) : 0);
map.put("userId", id);
map.put("boardId", map.get("LOCBRDSEQ"));
map.put("commentId", commentId);
comment.put("myReaction", this.selectMyBoardReactions(map));
Object content = comment.get("content");
comment.put("content", content);
}
}
}
/**
* 게시판 수정
*
* @param map
* @param files
* @throws IOException
*/
@Transactional
public ApiResponse<String> updateBoardWithFiles(MapDto map, List<MultipartFile> files) throws IOException {
int result = this.updateBoard(map); // 게시글 수정
Long userId = AuthUtil.getUser().getId();
String[] editorUploadedImgList = null;
// 수정 성공 첨부파일 수정 변경
if(result == 1) {
//에디터 첨부 이미지 게시글 번호 업데이트
if(map.get("editorUploadedImgList") != null) {
editorUploadedImgList = String.valueOf(map.get("editorUploadedImgList")).split(",");
map.put("editorImgList", editorUploadedImgList);
this.updateBoardIndexToFile(map);
}
// 추가 첨부파일 업로드
if(files != null && !files.isEmpty()) {
List<UploadFile> list = fileService.boardUploadFiles(files); // 파일 업로드
map.put("CMNFLEREG", userId);
map.put("list", list);
boardMapper.insertAttachments(map); // 파일 정보 DB 적재
}
// 제거 첨부파일 삭제
if(map.get("delFileIdx") != null) {
String[] array = String.valueOf(map.get("delFileIdx")).split(",");
this.deleteFileAndData(array);
}
// 에디터 수정 업로드 에디터 이미지 삭제
if(map.get("editorDeleteImgList") != null) {
String[] array = String.valueOf(map.get("editorDeleteImgList")).split(",");
this.deleteFileAndData(array);
}
} else {
return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, "게시물이 수정에 실패하였습니다.");
}
return ApiResponse.ok("게시물이 수정되었습니다.");
}
/**
* 첨부파일 데이터 삭제
*
* @param array
*/
private void deleteFileInfo(String[] array) {
boardMapper.deleteFileInfo(array);
}
private int updateBoardIndexToFile(MapDto map) {
return boardMapper.updateBoardIndexToFile(map);
}
/**
* 파일 삭제 db 데이터 제거
*
* @param array
*/
private void deleteFileAndData(String[] array) {
List<String> delListInfo = this.selectDelFileInfo(array); // 삭제할 파일 정보 조회
for(String item : delListInfo) {
fileService.removeFile(item); // 파일 삭제
}
this.deleteFileInfo(array);
}
/**
* 삭제 첨부파일 정보 조회
*
* @param array
* @return
*/
private List<String> selectDelFileInfo(String[] array) {
return boardMapper.selectDelFileInfo(array);
}
/**
* 게시글 수정 조회
*
* @param map
* @return
*/
public ApiResponse<MapDto> selectBoardDetail2(MapDto map) {
String password = map.getString("password"); // 입력한 비밀번호
Long boardId = map.getLong("boardId"); // 조회한 게시글 번호
MemberVo member = AuthUtil.getUser(); // 로그인 정보 조회
MapDto resultMap = boardMapper.selectBoardDetail2(boardId); // 게시글 정보 조회
if(resultMap == null) return ApiResponse.error(HttpStatus.NOT_FOUND, "해당 게시글이 없습니다");
String boardType = resultMap.getString("type"); // 게시글 타입
// 익명 게시글
if("300102".equals(boardType)) {
String hashedPassword = resultMap.getString("password");
if(StringUtils.hasText(password)) {
boolean isMatch = passwordEncoder.matches(password, hashedPassword);
if(!isMatch) return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다");
} else {
return ApiResponse.error(HttpStatus.UNAUTHORIZED, "비밀번호를 입력하세요");
}
// 자유 게시글 && 공지글
} else if("300101".equals(boardType) || "300103".equals(boardType)) {
Long writerId = Long.valueOf(resultMap.getInt("authorId"));
if(member.getId() != writerId) return ApiResponse.error(HttpStatus.UNAUTHORIZED, "권한이 없습니다");
// 공지글
// } else if("300103".equals(boardType)) {
// if(!"ROLE_ADMIN".equals(member.getRole())) return ApiResponse.error(HttpStatus.UNAUTHORIZED, "권한이 없습니다");
//
} else {
log.error("게시글 카테고리 정보 없음");
return ApiResponse.error(HttpStatus.NOT_FOUND, "해당 게시글이 없습니다");
}
this.enrichBoardDetail(resultMap); // 추가정보 세팅
List<MapDto> attachments = this.selectAttachments(boardId); // 📌 첨부파일 목록 추가
resultMap.put("attachments", attachments != null ? attachments : new ArrayList<>());
return ApiResponse.ok(resultMap);
}
/**
* 에디터 업로드 이미지 게시글 번호 업데이트
*
* @param map
* @return
*/
public int insertUploadEditorImageInfo(MapDto map) {
return boardMapper.insertUploadEditorImageInfo(map);
}
/**
* 게시글 정보가 없는 파일 조회
*
* @return
*/
public List<FileVo> selectFilesBoardIndexIsNull() {
return boardMapper.selectFilesBoardIndexIsNull();
}
/**
* 파일 data 제거
*
* @param vo
* @return
*/
public int deleteTrashFileData(FileVo vo) {
return boardMapper.deleteTrashFileData(vo);
}
/**
* Garbage File Collector
*/
@Scheduled(cron = "0 0 2 1 * *", zone = "Asia/Seoul")
public void deleteTrashFiles() {
List<FileVo> list = this.selectFilesBoardIndexIsNull();
for(FileVo file : list) {
String fileName = file.getCMNFLEPAT();
//if(!fileName.contains(file.getCMNFLEEXT())) fileName = fileName + file.getCMNFLEEXT();
boolean deleteResult = fileService.removeFile(fileName);
if(deleteResult) this.deleteTrashFileData(file);
}
}
}

View File

@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
@ -34,6 +35,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.localvacaMapper;
@ -48,45 +50,108 @@ public class localvacaService {
@Value("${api.public-holiday.key}")
private String serviceKey;
private static final List<MapDto> CUSTOM_HOLIDAYS = new ArrayList<>();
// 초기 사용자 지정 공휴일 추가
static {
MapDto customHoliday1 = new MapDto();
customHoliday1.put("monthDay", "05-01");
customHoliday1.put("name", "근로자의 날");
CUSTOM_HOLIDAYS.add(customHoliday1);
// MapDto customHoliday2 = new MapDto();
// customHoliday2.put("date", "2025-03-21");
// customHoliday2.put("name", "사용자 지정 예시");
//
// CUSTOM_HOLIDAYS.add(customHoliday2);
}
public void insertVacation(MapDto vacation) {
// 필요한 경우 데이터 검증/전처리 매퍼 호출
localvacaMapper.insertVacation(vacation);
}
public void deleteVacation(Long vacationId) {
localvacaMapper.deleteVacation(vacationId);
/**
* 여러 개의 휴가를 삭제
*/
@Transactional
public void deleteVacation(List<Long> vacationIds) {
if (vacationIds != null && !vacationIds.isEmpty()) {
localvacaMapper.deleteVacation(vacationIds);
}
}
/**
* 휴가 추가 또는 업데이트 (중복 검사 처리)
*/
@Transactional
public void upsertVacation(MapDto vacation) {
String date = vacation.getString("date");
Long employeeId = vacation.getLong("employeeId");
// 기존 데이터 확인
Long existingId = localvacaMapper.findVacationIdByDate(employeeId, date);
if (existingId != null) {
// 기존 휴가가 존재하면 업데이트
vacation.put("id", existingId);
localvacaMapper.updateVacation(vacation);
} else {
// 기존 휴가가 없으면 새롭게 추가
localvacaMapper.insertVacation(vacation);
}
}
public List<MapDto> selectVacationList(int year, int month) {
return localvacaMapper.selectVacations(year, month);
}
public List<MapDto> selectHolidays(int year, int month) {
// ServiceKey를 디코딩해서 사용
String decodedServiceKey = URLDecoder.decode(serviceKey, StandardCharsets.UTF_8);
System.out.println("📌 디코딩된 ServiceKey: " + decodedServiceKey);
// API에서 공휴일 가져오기
List<MapDto> apiHolidays = fetchHolidaysFromApi(year, month);
// URI를 직접 문자열로 구성하여 ServiceKey가 다시 인코딩되지 않도록
// 사용자 정의 공휴일 추가 (monthDay: 전체 연도 / date: 특정 연도)
List<MapDto> userDefinedHolidays = CUSTOM_HOLIDAYS.stream()
.filter(holiday ->
Optional.ofNullable(holiday.getString("date"))
.map(d -> d.startsWith(year + "-")) // 특정 연도의 공휴일
.orElse(false) // date가 있으면 연도 매칭 포함
|| Optional.ofNullable(holiday.getString("monthDay"))
.map(md -> md.startsWith(String.format("%02d-", month))) // 모든 연도에 적용되는 monthDay
.orElse(false)
)
.map(holiday -> {
MapDto newHoliday = new MapDto();
// 특정 연도 공휴일이면 그대로 사용, 모든 연도 공휴일이면 해당 연도 추가
newHoliday.put("date", holiday.containsKey("date") ? holiday.getString("date") : year + "-" + holiday.getString("monthDay"));
newHoliday.put("name", holiday.getString("name"));
return newHoliday;
})
.collect(Collectors.toList());
// API 공휴일과 사용자 정의 공휴일 합치기
List<MapDto> combinedHolidays = new ArrayList<>();
combinedHolidays.addAll(apiHolidays);
combinedHolidays.addAll(userDefinedHolidays);
return combinedHolidays;
}
private List<MapDto> fetchHolidaysFromApi(int year, int month) {
String decodedServiceKey = URLDecoder.decode(serviceKey, StandardCharsets.UTF_8);
String url = "http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo"
+ "?solYear=" + year
+ "&solMonth=" + String.format("%02d", month)
+ "&ServiceKey=" + decodedServiceKey // 디코딩된 상태로 직접 추가
+ "&ServiceKey=" + decodedServiceKey
+ "&_type=json";
System.out.println("📌 API 요청 URL: " + url);
// API 요청 헤더 추가 (User-Agent 포함)
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
HttpEntity<String> entity = new HttpEntity<>(headers);
// `exchange` 메서드를 사용하여 요청
ResponseEntity<Map> response = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);
System.out.println("📌 API 응답 데이터: " + response.getBody());
return parseResponse(response.getBody());
}
@ -163,7 +228,12 @@ public class localvacaService {
dto.put("date", locdateStr); // 변환 불가능한 경우 원본 저장
}
dto.put("name", item.get("dateName"));
String dateName = String.valueOf(item.get("dateName"));
if (dateName.contains("대체공휴일")) {
dto.put("name", "대체공휴일");
} else {
dto.put("name", dateName);
}
return dto;
}
@ -218,41 +288,39 @@ public class localvacaService {
return emp;
}).collect(Collectors.toList());
}
/**
* 연차 계산 로직
*/
/**
* 연차 계산 로직
*/
public int procCalculateTotalVacation(LocalDate hireDate) {
LocalDate today = LocalDate.now(); // 현재 날짜
int yearsWorked = hireDate.until(today).getYears();
int hireMonth = hireDate.getMonthValue();
LocalDate today = LocalDate.now();
int hireYear = hireDate.getYear();
int currentYear = today.getYear();
// 🔹 1년 미만: 입사한 월을 고려하여 연차 개수 계산
if (yearsWorked < 1) {
return 12 - hireMonth;
} else {
int totalVacation = 12 - hireMonth; // 1년 미만 사용하고 남은 연차 반영
LocalDate nextIncreaseDate = hireDate.plusYears(1).withMonth(hireMonth).withDayOfMonth(1);
// 🔹 매년 입사월에 15개 지급
while (!nextIncreaseDate.isAfter(today)) {
totalVacation += 15;
nextIncreaseDate = nextIncreaseDate.plusYears(1);
}
// 🔹 입사년도 2년마다 입사월에 15개에서 1개씩 추가 지급
LocalDate additionalIncreaseDate = hireDate.plusYears(2).withMonth(hireMonth).withDayOfMonth(1);
int extraIncrease = 1;
while (!additionalIncreaseDate.isAfter(today)) {
totalVacation += extraIncrease;
additionalIncreaseDate = additionalIncreaseDate.plusYears(2);
extraIncrease++; // 2년마다 1개씩 증가
}
return totalVacation;
// 입사년도와 현재년도가 같으면 : (12 - 입사월)
if (hireYear == currentYear) {
return 12 - hireDate.getMonthValue();
}
// 기본 연차 15
int totalVacation = 15;
// 입사년도 기준 3년차 1월부터, 2년마다 1개씩 증가
LocalDate accrualDate = LocalDate.of(hireYear + 3, 1, 1);
while (!accrualDate.isAfter(today)) {
totalVacation++;
accrualDate = accrualDate.plusYears(2);
}
return totalVacation;
}
public List<MapDto> selectSentVacationCount(MapDto map) {
return localvacaMapper.selectSentVacationCount(map);
}
public List<MapDto> selectMemberVacationsInMain(int year, int month) {
return localvacaMapper.selectMemberVacationsInMain(year, month);
}
}

View File

@ -1,3 +1,17 @@
/************************************************************
*
* @packageName : io.company.localhost.service
* @fileName : localvoteService.java
* @author : 공현지
* @date : 25.01.07
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 공현지 최초 생성
*
*************************************************************/
package io.company.localhost.service;
import java.util.ArrayList;
@ -55,35 +69,26 @@ public class localvoteService {
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
PageHelper.startPage(page, 10);
PageInfo<MapDto> localvote = PageUtil.redefineNavigation(new PageInfo<>(localvotemapper.selectVoteList(map),10));
List<MapDto> resultList = new ArrayList<>();
List<MapDto> resultList = new ArrayList<>();
List<MapDto> voteList = localvote.getList();
for (MapDto vote : voteList) {
for (MapDto vote : voteList) {
MapDto voteMap = new MapDto();
voteMap.put("localVote", vote);
Integer locvotSeq = (Integer) vote.get("LOCVOTSEQ");
//투표 항목조회
List<MapDto> voteDetails = votdetailmapper.selectVoteDetails(locvotSeq);
map.put("locvotSeq", locvotSeq);
//투표 항목조회 + 결과 조회 + 투표여부
List<MapDto> voteDetails = votdetailmapper.selectVoteDetailsResult(map);
//투표 가능 멤버 조회
List<MapDto> voteMembers = votmembermapper.selectVoteMember(locvotSeq);
//투표 결과 조회
List<MapDto> voteResult = votchoicemapper.selectVoteResult(locvotSeq);
voteMap.put("voteDetails", voteDetails);
voteMap.put("voteMembers", voteMembers);
voteMap.put("voteResult", voteResult);
map.put("id",locvotSeq);
//투표 여부
int yesVotetotal = votrecordmapper.selectYesVotetotal(map);
voteMap.put("yesVotetotal", yesVotetotal);
resultList.add(voteMap);
}
localvote.setList(resultList);
return localvote;
}

View File

@ -20,6 +20,9 @@ import java.util.List;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.commoncodMapper;
import io.company.localhost.mapper.worddictyMapper;
@ -32,52 +35,184 @@ public class worddictyService {
private final worddictyMapper worddictymapper;
private final commoncodMapper commoncodmapper;
private final FileService fileService;
public List<MapDto> getWordList(MapDto map) {
List<MapDto> wordList = worddictymapper.getWordList(map);
for (MapDto word : wordList) {
Object content = word.get("WRDDICCON");
// BlobUtil.procBlobToString으로 content 변환
String contentString = BlobUtil.procBlobToString(content);
word.put("WRDDICCON", contentString);
}
List<MapDto> processedList = new ArrayList<>();
// 데이터 가공
for (MapDto dto : wordList) {
MapDto author = new MapDto();
author.put("profileImage", dto.remove("REGPRF"));
author.put("name", dto.remove("REGNAME"));
author.put("color", dto.remove("REGCOLOR"));
author.put("createdAt", dto.remove("REGRDT"));
MapDto lastEditor = new MapDto();
lastEditor.put("profileImage", dto.remove("UPDPRF"));
lastEditor.put("name", dto.remove("UPDNAME"));
lastEditor.put("color", dto.remove("UPDCOLOR"));
lastEditor.put("updatedAt", dto.remove("UPDUDT"));
dto.put("author", author);
dto.put("lastEditor", lastEditor);
MapDto processedDto = new MapDto();
processedDto.putAll(dto);
processedList.add(processedDto);
}
return processedList;
}
public Long insertWord(MapDto map) {
if (map.containsKey("CMNCODNAM") && map.get("CMNCODNAM") != null) {
commoncodmapper.insertCategory(map);
public List<MapDto> selectWordList(MapDto map) {
if( map.getString("pageNum") != null) {
String pageNumStr = map.getString("pageNum");
int pageNum = Integer.parseInt(pageNumStr);
map.put("pageNum", pageNum);
}
return worddictymapper.insertWord(map);
List<MapDto> wordList = worddictymapper.selectWordList(map);
String keyword = map.getString("searchKeyword");
List<MapDto> processedList = new ArrayList<>();
// 데이터 가공
for (MapDto dto : wordList) {
MapDto author = new MapDto();
author.put("profileImage", dto.remove("REGPRF"));
author.put("name", dto.remove("REGNAME"));
author.put("color", dto.remove("REGCOLOR"));
author.put("createdAt", dto.remove("REGRDT"));
MapDto lastEditor = new MapDto();
lastEditor.put("profileImage", dto.remove("UPDPRF"));
lastEditor.put("name", dto.remove("UPDNAME"));
lastEditor.put("color", dto.remove("UPDCOLOR"));
lastEditor.put("updatedAt", dto.remove("UPDUDT"));
dto.put("author", author);
dto.put("lastEditor", lastEditor);
MapDto processedDto = new MapDto();
processedDto.putAll(dto);
processedList.add(processedDto);
}
return filterPostsByKeyword(processedList,keyword);
}
/**
* 검색어로 순수 텍스트 기준 게시글 필터링
*/
private List<MapDto> filterPostsByKeyword(List<MapDto> posts, String keyword) {
keyword = keyword.trim();
List<MapDto> filtered = new ArrayList<>();
for (MapDto post : posts) {
String title = post.getString("WRDDICTTL");
Object content = post.get("WRDDICCON");
// BlobUtil.procBlobToString으로 content 변환
String contentString = BlobUtil.procBlobToString(content);
if(keyword != null || !keyword.trim().isEmpty()) {
String plainText = extractPlainText(contentString);
if ((title != null && title.contains(keyword)) ||plainText.contains(keyword)) {
post.put("WRDDICCON", contentString); // content는 원래대로 복원
filtered.add(post);
}
}
}
return filtered;
}
public String extractPlainText(String deltaJson) {
StringBuilder sb = new StringBuilder();
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode root = mapper.readTree(deltaJson);
if (root != null && root.isArray()) {
for (JsonNode op : root) {
JsonNode insertNode = op.get("insert");
// insert가 문자열일 경우만 추출
if (insertNode != null && insertNode.isTextual()) {
String text = insertNode.asText();
if (!"\n".equals(text.trim())) { // 줄바꿈 제외
sb.append(text).append(" ");
}
}
// insert가 객체면 image일 가능성 제외
}
}
} catch (Exception e) {
e.printStackTrace(); // 실제 운영에서는 로깅 처리
}
return sb.toString().trim();
}
public Long insertWord(MapDto map) {
Long result = 1L;
if (map.containsKey("CMNCODNAM") && map.get("CMNCODNAM") != null && map.get("CMNCODNAM") != "") {
commoncodmapper.insertCategory(map);
result = 2L;
}
worddictymapper.insertWord(map);
//에디터 첨부 이미지 게시글 번호 업데이트
if(map.get("editorUploadedImgList") != null) {
ArrayList<String> editorUploadedImgList = (ArrayList<String>) map.getList("editorUploadedImgList", String.class);
map.put("editorImgList", editorUploadedImgList);
this.updateBoardIndexToFile(map);
}
// 에디터 수정 업로드 에디터 이미지 삭제
if(map.get("editorDeleteImgList") != null) {
ArrayList<String> editorDeleteImgList = (ArrayList<String>) map.getList("editorDeleteImgList", String.class);
String[] array = editorDeleteImgList.stream().toArray(String[]::new);
this.deleteFileAndData(array);
}
return result;
}
/**
* 실제 파일 삭제 db 데이터 제거
*
* @param array
*/
private void deleteFileAndData(String[] array) {
List<String> delListInfo = this.selectDelFileInfo(array); // 삭제할 파일 정보 조회
for(String item : delListInfo) {
fileService.removeFile(item); // 파일 삭제
}
this.deleteFileInfo(array);
}
/**
* 삭제 첨부파일 정보 조회
*
* @param array
* @return
*/
private List<String> selectDelFileInfo(String[] array) {
return worddictymapper.selectDelFileInfo(array);
}
/**
* 첨부파일 데이터 삭제
*
* @param array
*/
private void deleteFileInfo(String[] array) {
worddictymapper.deleteFileInfo(array);
}
private int updateBoardIndexToFile(MapDto map) {
return worddictymapper.updateBoardIndexToFile(map);
}
public Long updateWord(MapDto map) {
return worddictymapper.updateWord(map);
Long result = worddictymapper.updateWord(map);
if(result == 1) {
map.put("id", map.get("WRDDICSEQ"));
//에디터 첨부 이미지 게시글 번호 업데이트
if(map.get("editorUploadedImgList") != null) {
ArrayList<String> editorUploadedImgList = (ArrayList<String>) map.getList("editorUploadedImgList", String.class);
map.put("editorImgList", editorUploadedImgList);
this.updateBoardIndexToFile(map);
}
// 에디터 수정 업로드 에디터 이미지 삭제
if(map.get("editorDeleteImgList") != null) {
ArrayList<String> editorDeleteImgList = (ArrayList<String>) map.getList("editorDeleteImgList", String.class);
String[] array = editorDeleteImgList.stream().toArray(String[]::new);
this.deleteFileAndData(array);
}
}
return result;
}
public MapDto getWordDetail(MapDto map) {
return worddictymapper.getWordDetail(map);
public MapDto selectWordDetail(MapDto map) {
return worddictymapper.selectWordDetail(map);
}
public int getTotal(MapDto map) {
return worddictymapper.getTotal(map);
@ -85,4 +220,7 @@ public class worddictyService {
public Long updateword(MapDto map) {
return worddictymapper.updateword(map);
}
public List<MapDto> selectIndexCategory() {
return worddictymapper.selectIndexCategory();
}
}

View File

@ -0,0 +1,147 @@
package io.company.localhost.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import io.company.localhost.vo.UploadFile;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class FileUtil {
/**
* 파일 저장 경로/파일명
* @param savePath
* @param fileName
* @return
*/
public String getFullPath(String savePath, String fileName) {
return Paths.get(savePath, fileName).toString();
}
/**
* DB에 저장될 파일명
* @param originalFilename
* @return
*/
public String createSaveFileName(String originalFilename) {
String uuid = UUID.randomUUID().toString();
String extension = getFileExtension(originalFilename);
return uuid + "." + extension;
}
/**
* 파일 확장자
* @param originalFileName
* @return
*/
public String getFileExtension(String originalFileName) {
int pos = originalFileName.lastIndexOf(".");
return originalFileName.substring(pos + 1);
}
/**
* 파일 확장자 제외
* @param
* @return
*/
public String excludeFileExtension(String withExt) {
int pos = withExt.lastIndexOf(".");
return withExt.substring(0, pos);
}
/**
* 단일 파일 업로드
* @param savePath
* @param multipartFile
* @return
* @throws IOException
*/
public UploadFile uploadFile(String savePath, MultipartFile multipartFile) throws IOException{
File saveDirectory = new File(savePath);
if(!saveDirectory.exists()) saveDirectory.mkdirs();
if(multipartFile.isEmpty()) return null;
String originalFileName = multipartFile.getOriginalFilename(); //원본파일명
String saveFileName = createSaveFileName(originalFileName); //난수명
String ext = getFileExtension(originalFileName); //확장자
Long size = multipartFile.getSize(); //사이즈
String filePath = getFullPath(savePath, saveFileName);
multipartFile.transferTo(new File(filePath));
String orgFileName = this.excludeFileExtension(originalFileName);
String savFileName = this.excludeFileExtension(saveFileName);
return new UploadFile(orgFileName, savFileName, ext, size, filePath);
}
/**
* 다중 파일 업로드
* @param savePath
* @param multipartFiles
* @return
* @throws IOException
*/
public List<UploadFile> uploadFiles(String savePath, List<MultipartFile> multipartFiles) throws IOException{
List<UploadFile> uploadFiles = new ArrayList<>();
for(MultipartFile multipartFile : multipartFiles) {
if(!multipartFile.isEmpty()) {
uploadFiles.add(uploadFile(savePath, multipartFile));
}
}
return uploadFiles;
}
/**
* 업로드된 파일 삭제
* @param path
* @param originalProfile
* @return
*/
public Boolean removeFile(String path, String saveFileName) {
log.debug("========================================");
log.debug("FileUtil.removeFile()");
log.debug("path : {}", path);
log.debug("saveFileName : {}", saveFileName);
File file = new File(path, saveFileName);
System.gc();
boolean result = file.delete();
log.debug("result : {}", result);
log.debug("========================================");
return result;
}
public Boolean removeFile(String path) {
log.debug("========================================");
log.debug("FileUtil.removeFile()");
log.debug("path : {}", path);
File file = new File(path);
System.gc();
boolean result = file.delete();
log.debug("result : {}", result);
log.debug("========================================");
return result;
}
}

View File

@ -18,7 +18,15 @@ import org.springframework.util.StringUtils;
public class StringUtil extends StringUtils {
//String Util 여기서 작성
/**
* 정수타입 확인
*
* @param str
* @return
*/
public static boolean isNumeric(String str) {
return str.matches("\\d+");
}
public StringUtil() {}
}

View File

@ -0,0 +1,18 @@
package io.company.localhost.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class FileVo {
private String CMNFLESEQ;
private String CMNBRDSEQ;
private String CMNFLENAM;
private String CMNFLEORG;
private String CMNFLEPAT;
private String CMNFLEEXT;
private String CMNFLESIZ;
private String CMNFLETYP;
}

View File

@ -47,6 +47,7 @@ public class MemberVo {
private String isLea; // 휴직여부
private int color; // 색상
private int mbit; // MBTI
private String usercolor; // usercolor
private Boolean remember; // 로그인 유지
}

View File

@ -0,0 +1,15 @@
package io.company.localhost.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class UploadFile {
private String originalFileName;
private String saveFileName;
private String extension;
private long fileSize;
private String filePath;
}

View File

@ -0,0 +1,33 @@
/************************************************************
*
* @packageName : io.company.localhost.vo
* @fileName : MemberVo.java
* @author : 조인제
* @date : 24.12.06
* @description :
*
* ===========================================================
* DATE AUTHOR NOTE
* -----------------------------------------------------------
* 24.12.06 조인제 최초 생성
*
*************************************************************/
package io.company.localhost.vo;
import lombok.*;
import java.util.Date;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class WeatherVo {
String date;
String mainWeather;
String description;
String icon;
}

View File

@ -55,7 +55,8 @@ management:
api:
public-holiday:
key: "MugzCRZ7VmR/LJ3BZ1Ehmmg5yiI0GPFt4evLjNkNuwKoiWbKbe/M9U5pLjAxfSP13OOwHi943aMFM9yiI8OADA=="
weather:
key: "3505b3500aacf34c4497bf449996ea09"
server:
shutdown: graceful
@ -94,6 +95,8 @@ logging:
connection: off
io.company: DEBUG
io.company.localhost.mapper: off
file:
path: logs
filePath:

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.company.localhost.mapper.CommutersMapper">
<!-- 출퇴근 등록 -->
<insert id="insertCommuters" useGeneratedKeys="true" keyProperty="COMMUTSEQ">
INSERT INTO commuters (
COMMUTSEQ,
MEMBERSEQ,
PROJCTSEQ,
COMMUTCMT,
COMMUTLVE,
COMMUTDAY,
COMMUTARR,
COMMUTOUT
) VALUES (
#{commutSeq},
#{memberSeq},
#{projctSeq},
#{commutCme},
#{commutLve},
#{commutDay},
#{commutArr},
#{commutOut}
)
</insert>
<!-- 퇴근 시간 업데이트 -->
<update id="updateLeaveTime">
UPDATE commuters
SET COMMUTLVE = #{commutLve},
PROJCTLVE = #{projctLve},
COMMUTOUT = #{commutOut}
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTDAY = CURDATE()
</update>
<!-- 현재 달의 모든 출근 정보 조회 -->
<select id="selectCommutersByMonth" parameterType="map" resultType="map">
SELECT
c.COMMUTSEQ,
c.MEMBERSEQ,
c.PROJCTSEQ,
c.PROJCTLVE,
c.COMMUTCMT,
c.COMMUTLVE,
c.COMMUTDAY,
c.COMMUTARR,
m.MEMBERNAM AS memberName,
m.MEMBERPRF AS profile,
p.PROJCTNAM,
p.PROJCTARR AS projectAddress,
cc.CMNCODNAM AS projctcolor,
p2.PROJCTNAM AS leaveProjectName,
p2.PROJCTARR AS leaveProjectAddress,
cl.CMNCODNAM AS leaveProjectColor
FROM
commuters c
JOIN
netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
JOIN
netprojct p ON c.PROJCTSEQ = p.PROJCTSEQ
LEFT JOIN
commoncod cc ON p.PROJCTCOL = cc.CMNCODVAL AND cc.CMNCODYNP = '1'
LEFT JOIN
netprojct p2 ON c.PROJCTLVE = p2.PROJCTSEQ
LEFT JOIN
commoncod cl ON p2.PROJCTCOL = cl.CMNCODVAL AND cl.CMNCODYNP = '1'
WHERE
YEAR(c.COMMUTDAY) = #{year}
AND MONTH(c.COMMUTDAY) = #{month}
</select>
<!-- 사용자 오늘 출근 정보 조회 -->
<select id="selectTodayCommuterInfo" parameterType="Integer" resultType="map">
SELECT c.COMMUTCMT, c.COMMUTLVE
FROM commuters c
WHERE c.MEMBERSEQ = #{memberSeq}
AND c.COMMUTDAY = CURDATE()
</select>
<!-- 오늘 출근 모든 사용자 조회 -->
<select id="selectTodayCommuter">
SELECT c.COMMUTCMT, c.PROJCTLVE, c.COMMUTLVE, m.MEMBERSEQ, m.MEMBERPRF as profile, p.PROJCTNAM
FROM commuters c
JOIN netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
JOIN netprojct p ON c.PROJCTSEQ = p.PROJCTSEQ
WHERE c.COMMUTDAY = CURDATE()
</select>
<!-- 출근 프로젝트 업데이트 -->
<!-- <update id="updateCommuterProject">
UPDATE commuters
SET PROJCTSEQ = #{projctSeq}
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTDAY = CURDATE()
</update> -->
<delete id="deleteCommuters" parameterType="int">
DELETE FROM commuters WHERE PROJCTSEQ = #{projctSeq}
</delete>
<select id="selectUserLeaveWorkList">
/* 금일 퇴근 조회 */
SELECT * FROM COMMUTERS WHERE MEMBERSEQ = #{memberSeq} AND COMMUTDAY = DATE_FORMAT(#{currentDate}, '%Y-%m-%d')
</select>
</mapper>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.company.localhost.mapper.LocalevntMapper">
<!-- 이벤트 작성 -->
<insert id="insertEvent">
/* 이벤트 작성 */
INSERT INTO LOCALEVNT (
CMNCODVAL,
LOCEVTPLC,
LOCEVTTME,
LOCEVTRDT
) VALUES (
#{code},
<choose>
<when test="place != null">
#{place},
</when>
<otherwise>
null,
</otherwise>
</choose>
#{date},
NOW()
)
</insert>
<select id="selectCheckEvent">
/* 이벤트 확인 */
SELECT
COUNT(*)
FROM
LOCALEVNT
WHERE
CMNCODVAL = #{code} AND DATE(LOCEVTTME) = DATE(#{date})
</select>
<select id="selectEventList">
/* 이벤트 조회 */
SELECT
*
FROM
LOCALEVNT
WHERE
YEAR(LOCEVTTME) = #{year} AND MONTH(LOCEVTTME) = #{month}
</select>
<delete id="deleteEvent">
/* 이벤트 제거 */
DELETE FROM
LOCALEVNT
WHERE
CMNCODVAL = #{code} AND DATE(LOCEVTTME) = DATE(#{date})
</delete>
</mapper>

View File

@ -26,8 +26,13 @@
, MEMBERLEA AS isLea
, MEMBERCOL AS color
, MEMBERMBT AS mbit
, c.CMNCODNAM usercolor
FROM
netmember
netmember m
left join
commoncod c
on
M.MEMBERCOL = C.CMNCODVAL
WHERE
MEMBERIDS = #{id}
</select>
@ -102,6 +107,13 @@
WHERE MEMBERTEL = #{memberTel}
</select>
<!-- 색상 중복체크 -->
<select id="selectMemberColor" resultType="int">
SELECT COUNT(*)
FROM netmember
WHERE MEMBERCOL = #{memberCol}
</select>
<!-- 비밀번호 재설정 member 체크 -->
<select id="selectPwReset" resultType="int">
SELECT COUNT(*)
@ -127,7 +139,7 @@
</update>
<!-- 전체 회원 목록 -->
<select id="getallUserList" resultType="Map">
<select id="selectallUserList" resultType="Map">
SELECT
m.*
,c.CMNCODNAM usercolor
@ -145,4 +157,115 @@
m.MEMBERLEA ="N"
</select>
<update id="updateUserRole">
UPDATE netmember SET MEMBERROL = #{role} WHERE MEMBERSEQ = #{id}
</update>
<select id="selectMemberBirthDay">
SELECT
A.MEMBERSEQ,
A.MEMBERNAM,
A.MEMBERCOL,
A.MEMBERPRF,
A.MEMBERBTH,
B.CMNCODNAM AS usercolor
FROM
NETMEMBER A
LEFT JOIN
COMMONCOD B ON B.CMNCODVAL = A.MEMBERCOL
WHERE
MONTH(MEMBERBTH) = #{month} AND MEMBERPRM = "Y";
</select>
<select id="selectRegisterMemberList">
/* 미등록 멤버 조회 */
SELECT
MEMBERSEQ,
MEMBERIDS,
MEMBERPRF,
MEMBERNAM,
MEMBERTEL,
MEMBERRDT,
MEMBERPRM,
MEMBERMBT,
MEMBERCDT,
B.CMNCODNAM AS MBTI
FROM
NETMEMBER
LEFT JOIN
COMMONCOD B ON B.CMNCODVAL = MEMBERMBT
WHERE
MEMBERPRM = 'N'
</select>
<update id="updateRegistMember">
/* 멤버 승인 */
UPDATE
NETMEMBER
SET
MEMBERPRM = 'Y'
WHERE
MEMBERSEQ = #{memberSeq}
</update>
<update id="updateRejectMember">
/* 멤버 등록 미승인 */
UPDATE
NETMEMBER
SET
MEMBERPRM = 'R'
WHERE
MEMBERSEQ = #{memberSeq}
</update>
<update id="updateUserInfo" parameterType="map">
UPDATE NETMEMBER
<set>
<if test="phone != null"> MEMBERTEL = #{phone}, </if>
<if test="color != null"> MEMBERCOL = #{color}, </if>
<if test="mbti != null"> MEMBERMBT = #{mbti}, </if>
<if test="birth != null"> MEMBERBTH = #{birth}, </if>
<if test="entryDate != null"> MEMBERCDT = #{entryDate}, </if>
<if test="address != null"> MEMBERARR = #{address}, </if>
<if test="detailAddress != null"> MEMBERDTL = #{detailAddress}, </if>
<if test="memberPrf != null"> MEMBERPRF = #{memberPrf}, </if>
</set>
WHERE MEMBERSEQ = #{memberId}
</update>
<select id="selectUserById" resultType="io.company.localhost.vo.MemberVo">
SELECT
MEMBERSEQ AS id
, MEMBERIDS AS loginId
, MEMBERROL AS role
, MEMBERTKN AS token
, MEMBERPRF AS profile
, MEMBERNAM AS name
, MEMBERPWD AS password
, MEMBERPWH AS passwordhint
, MEMBERPWR AS passwordRes
, MEMBERPOS AS position
, MEMBERARR AS address
, MEMBERDTL AS addressDetail
, MEMBERZIP AS zipcode
, MEMBERBTH AS birth
, MEMBERTEL AS phone
, MEMBERRDT AS regist
, MEMBERCDT AS isCdt
, MEMBERPRM AS isUsed
, MEMBERDEL AS isDel
, MEMBERLEA AS isLea
, MEMBERCOL AS color
, MEMBERMBT AS mbit
, c.CMNCODNAM usercolor
FROM
netmember m
left join
commoncod c
on
M.MEMBERCOL = C.CMNCODVAL
WHERE MEMBERSEQ = #{memberId}
</select>
</mapper>

View File

@ -6,22 +6,26 @@
<select id="selectProject" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
SELECT DISTINCT
p.*,
c.CMNCODNAM AS projctcolor
c.CMNCODNAM AS projctcolor,
(SELECT COUNT(*)
FROM promember pm2
WHERE pm2.PROJCTSEQ = p.PROJCTSEQ
AND pm2.PROJCTYON = '1') AS participant_count
FROM netprojct p
LEFT JOIN commoncod c ON p.PROJCTCOL = c.CMNCODVAL AND c.CMNCODYNP = '1'
LEFT JOIN promember pm ON p.PROJCTSEQ = pm.PROJCTSEQ
WHERE 1=1
WHERE 1=1
<if test="searchKeyword != null and searchKeyword != ''">
AND (
p.PROJCTNAM LIKE CONCAT('%', #{searchKeyword}, '%')
OR EXISTS (
SELECT 1
FROM promember pm2
JOIN netmember m ON pm2.MEMBERSEQ = m.MEMBERSEQ
WHERE pm2.PROJCTSEQ = p.PROJCTSEQ
AND pm2.PROJCTYON = '1'
AND m.membernam LIKE CONCAT('%', #{searchKeyword}, '%')
)
SELECT 1
FROM promember pm2
JOIN netmember m ON pm2.MEMBERSEQ = m.MEMBERSEQ
WHERE pm2.PROJCTSEQ = p.PROJCTSEQ
AND pm2.PROJCTYON = '1'
AND m.membernam LIKE CONCAT('%', #{searchKeyword}, '%')
)
OR p.PROJCTARR LIKE CONCAT('%', #{searchKeyword}, '%')
OR p.PROJCTDTL LIKE CONCAT('%', #{searchKeyword}, '%')
OR p.PROJCTZIP LIKE CONCAT('%', #{searchKeyword}, '%')
@ -30,7 +34,10 @@
<if test="category != null and category != ''">
AND SUBSTRING(p.PROJCTSTR, 1, 4) = #{category}
</if>
ORDER BY p.PROJCTSEQ DESC
<if test="excludeEnded != null and excludeEnded == 'true'">
AND (p.PROJCTEND IS NULL OR p.PROJCTEND > CURDATE())
</if>
ORDER BY p.PROJCTSTR DESC
</select>
@ -78,31 +85,96 @@
WHERE PROJCTSEQ = #{projctSeq}
</update>
<!-- 프로젝트 로그 조회 -->
<select id="selectProjectLog" parameterType="int" resultType="map">
SELECT logDate, logMessage
FROM (
SELECT
DATE_FORMAT(PROJCTCDT, '%Y-%m-%d %H:%i') AS logDate,
CONCAT('[', PROJCTCMB, '] 프로젝트 등록') AS logMessage
FROM netprojct
WHERE PROJCTSEQ = #{projctSeq}
<!-- 프로젝트 등록·수정자 조회 -->
<select id="selectProjectLog" parameterType="int" resultType="map">
SELECT logDate, logMessage
FROM (
SELECT
DATE_FORMAT(p.PROJCTCDT, '%Y-%m-%d %H:%i') AS logDate,
CONCAT('[', m.MEMBERNAM, '] 프로젝트 등록') AS logMessage
FROM netprojct p
JOIN netmember m ON p.PROJCTCMB = m.MEMBERSEQ
WHERE p.PROJCTSEQ = #{projctSeq}
UNION ALL
UNION ALL
SELECT
DATE_FORMAT(PROJCTUDT, '%Y-%m-%d %H:%i') AS logDate,
CONCAT('[', PROJCTUMB, '] 프로젝트 수정') AS logMessage
FROM netprojct
WHERE PROJCTSEQ = #{projctSeq} AND PROJCTUDT IS NOT NULL
) AS logs
ORDER BY logDate DESC;
</select>
SELECT
DATE_FORMAT(p.PROJCTUDT, '%Y-%m-%d %H:%i') AS logDate,
CONCAT('[', m.MEMBERNAM, '] 프로젝트 수정') AS logMessage
FROM netprojct p
JOIN netmember m ON p.PROJCTUMB = m.MEMBERSEQ
WHERE p.PROJCTSEQ = #{projctSeq}
AND p.PROJCTUDT IS NOT NULL
) AS logs
ORDER BY logDate DESC;
</select>
<!-- 프로젝트 삭제 -->
<delete id="deleteProject">
DELETE FROM netprojct WHERE PROJCTSEQ = #{projctSeq}
</delete>
<delete id="deleteProject" parameterType="int">
DELETE FROM netprojct WHERE PROJCTSEQ = #{projctSeq}
</delete>
<!-- 프로젝트 모든 사용자 참여기간 조회 -->
<select id="selectUserProjectPeriod" resultType="io.company.localhost.common.dto.MapDto">
SELECT
m.MEMBERSEQ,
m.MEMBERNAM,
p.PROJCTSEQ,
p.PROJCTNAM,
p.PROJCTSTR AS projectStartDate,
p.PROJCTEND AS projectEndDate,
COALESCE((
SELECT MIN(c2.COMMUTDAY)
FROM commuters c2
WHERE c2.PROJCTSEQ = p.PROJCTSEQ
AND c2.MEMBERSEQ = m.MEMBERSEQ
), p.PROJCTSTR) AS userStartDate,
COALESCE((
SELECT MAX(c2.COMMUTDAY)
FROM commuters c2
WHERE c2.PROJCTSEQ = p.PROJCTSEQ
AND c2.MEMBERSEQ = m.MEMBERSEQ
), p.PROJCTEND) AS userEndDate
FROM
netprojct p
LEFT JOIN
commuters c ON p.PROJCTSEQ = c.PROJCTSEQ
LEFT JOIN
netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
WHERE
p.PROJCTSEQ = #{projectSeq}
GROUP BY
m.MEMBERSEQ, m.MEMBERNAM, p.PROJCTSEQ, p.PROJCTNAM, p.PROJCTSTR, p.PROJCTEND
</select>
<select id="selectUserProjectPeriod2" resultType="io.company.localhost.common.dto.MapDto">
SELECT
pm.MEMBERSEQ,
p.PROJCTSEQ,
p.PROJCTNAM,
p.PROJCTSTR AS projectStartDate,
p.PROJCTEND AS projectEndDate,
(
SELECT MIN(c2.COMMUTDAY)
FROM commuters c2
WHERE c2.PROJCTSEQ = p.PROJCTSEQ
AND c2.MEMBERSEQ = pm.MEMBERSEQ
) AS userStartDate,
CASE
WHEN p.PROJCTEND IS NOT NULL THEN (
SELECT MAX(c2.COMMUTDAY)
FROM commuters c2
WHERE c2.PROJCTSEQ = p.PROJCTSEQ
AND c2.MEMBERSEQ = pm.MEMBERSEQ
)
ELSE NULL
END AS userEndDate
FROM promember pm
INNER JOIN netprojct p ON pm.PROJCTSEQ = p.PROJCTSEQ
WHERE pm.MEMBERSEQ = #{memberSeq}
AND pm.PROJCTYON = 1
</select>
</mapper>

View File

@ -2,19 +2,63 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.company.localhost.mapper.PromemberMapper">
<!-- 프로젝트 등록 후 모든 사용자 자동 참여 -->
<!-- 프로젝트 등록 후 모든 사용자 참여 -->
<insert id="insertProjectMember">
INSERT INTO promember (PROJCTSEQ, MEMBERSEQ, PROJCTYON)
SELECT #{projctSeq}, MEMBERSEQ, '1' FROM netmember;
SELECT
#{projctSeq},
MEMBERSEQ,
<choose>
<when test="disabledMembers != null and disabledMembers.size() > 0">
CASE
WHEN MEMBERSEQ IN
<foreach item="member" collection="disabledMembers" open="(" separator="," close=")">
#{member}
</foreach>
THEN '0'
ELSE '1'
END
</when>
<otherwise>
'1'
</otherwise>
</choose>
FROM netmember;
</insert>
<update id="updateProjectMembers">
UPDATE promember
SET PROJCTYON =
<choose>
<when test="disabledMembers != null and disabledMembers.size() > 0">
CASE
WHEN MEMBERSEQ IN
<foreach item="member" collection="disabledMembers" open="(" separator="," close=")">
#{member}
</foreach>
THEN '0'
ELSE '1'
END
</when>
<otherwise>
'1'
</otherwise>
</choose>
WHERE PROJCTSEQ = #{projctSeq}
</update>
<!-- 새로 가입한 회원 모든 프로젝트 멤버에 미참여 상태로 추가 -->
<insert id="insertNewMemberToProjects">
INSERT INTO promember (PROJCTSEQ, MEMBERSEQ, PROJCTYON)
SELECT PROJCTSEQ, #{memberSeq}, '0' FROM netprojct;
SELECT PROJCTSEQ, #{memberSeq},
CASE
WHEN PROJCTSEQ IN (1, 2) THEN '1'
ELSE '0'
END AS PROJCTYON
FROM netprojct;
</insert>
<!-- 프로젝트 참여 미참여 -->
<update id="updateProjectMember">
UPDATE promember
@ -30,10 +74,82 @@
pm.PROJCTYON,
nm.MEMBERNAM,
nm.MEMBERPRF,
nm.MEMBERCOL as usercolor
nm.MEMBERCOL as usercolor,
cc.CMNCODNAM as usercolorName
FROM promember pm
JOIN netmember nm ON pm.MEMBERSEQ = nm.MEMBERSEQ
LEFT JOIN commoncod cc on nm.MEMBERCOL = cc.CMNCODVAL
WHERE pm.PROJCTSEQ = #{projctSeq}
</select>
<!-- 사용자가 속한 프로젝트 조회 -->
<select id="selectMemberProjects" resultType="io.company.localhost.common.dto.MapDto">
SELECT
p.PROJCTSEQ,
p.PROJCTNAM,
c.CMNCODNAM AS projctcolor,
MAX(cm.PROJCTLVE) AS last_worked_project,
MAX(cm.COMMUTLVE) AS last_check_out_time,
MAX(cm.COMMUTCMT) AS last_check_in_time
FROM promember pm
JOIN netprojct p ON pm.PROJCTSEQ = p.PROJCTSEQ
LEFT JOIN commoncod c ON p.PROJCTCOL = c.CMNCODVAL AND c.CMNCODYNP = '1'
LEFT JOIN commuters cm
ON pm.MEMBERSEQ = cm.MEMBERSEQ
AND (pm.PROJCTSEQ = cm.PROJCTSEQ OR pm.PROJCTSEQ = cm.PROJCTLVE)
WHERE pm.MEMBERSEQ = #{memberSeq}
AND pm.PROJCTYON = '1'
AND (p.PROJCTEND IS NULL OR p.PROJCTEND >= CURDATE())
GROUP BY p.PROJCTSEQ, p.PROJCTNAM, c.CMNCODNAM
ORDER BY
/* 오늘 퇴근이 있는 프로젝트를 최우선 */
CASE WHEN EXISTS (
SELECT 1 FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTDAY = CURDATE()
AND COMMUTLVE IS NOT NULL
AND PROJCTLVE = p.PROJCTSEQ
) THEN 0 ELSE 1 END,
/* 오늘 출근이 있는 프로젝트를 두 번째 우선순위 */
CASE WHEN EXISTS (
SELECT 1 FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTDAY = CURDATE()
AND PROJCTSEQ = p.PROJCTSEQ
) THEN 0 ELSE 1 END,
/* 마지막 퇴근 프로젝트를 세 번째 우선순위 - 여기서 정확히 프로젝트별 최신 날짜를 확인 */
CASE WHEN p.PROJCTSEQ IN (
SELECT PROJCTLVE
FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTLVE IS NOT NULL
AND COMMUTDAY = (
SELECT MAX(COMMUTDAY)
FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTLVE IS NOT NULL
)
) THEN 0 ELSE 1 END,
/* 마지막 출근 프로젝트를 네 번째 우선순위 */
CASE WHEN p.PROJCTSEQ IN (
SELECT PROJCTSEQ
FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
AND COMMUTDAY = (
SELECT MAX(COMMUTDAY)
FROM commuters
WHERE MEMBERSEQ = #{memberSeq}
)
) THEN 0 ELSE 1 END,
/* 없으면 최신 날짜 기준 */
MAX(cm.COMMUTDAY) DESC,
MAX(cm.COMMUTLVE) DESC,
MAX(cm.COMMUTCMT) DESC,
p.PROJCTSTR DESC
</select>
<delete id="deletePromember" parameterType="int">
DELETE FROM promember WHERE PROJCTSEQ = #{projctSeq}
</delete>
</mapper>

View File

@ -16,13 +16,23 @@
)
</foreach>
</insert>
<select id="selectVoteDetails" parameterType="int" >
select
*
from
votdetail
where
LOCVOTSEQ = #{LOCVOTSEQ}
<select id="selectVoteDetailsResult" parameterType="map">
SELECT
d.*,
COALESCE(COUNT(c.VOTDETSEQ), 0) AS VOTE_COUNT,
(SELECT COUNT(*)
FROM votrecord
WHERE LOCVOTSEQ = d.LOCVOTSEQ
AND VOTRECMEM = #{userId}) AS yesvote
FROM
votdetail d
LEFT JOIN
votchoice c ON d.LOCVOTSEQ = c.LOCVOTSEQ AND d.VOTDETSEQ = c.VOTDETSEQ
WHERE
d.LOCVOTSEQ = #{locvotSeq}
GROUP BY
d.VOTDETSEQ, d.LOCVOTCON
ORDER BY
VOTDETSEQ ASC
</select>
</mapper>

View File

@ -13,8 +13,10 @@
</insert>
<select id="selectVoteMember" parameterType="int" >
SELECT
a.*,
n.*,
n.MEMBERSEQ,
n.MEMBERNAM,
n.MEMBERCOL,
n.MEMBERPRF,
c.CMNCODNAM AS usercolor,
CASE
WHEN v.LOCVOTSEQ IS NOT NULL THEN 1

View File

@ -1,15 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.company.localhost.mapper.VotRecordMapper">
<select id="selectYesVotetotal" parameterType="map">
select count(*) as yesvote
from
votrecord
where
LOCVOTSEQ = #{id}
and
VOTRECMEM = #{userId}
</select>
<insert id="insertCheckedNums" parameterType="map">
INSERT INTO votrecord
(

View File

@ -15,21 +15,4 @@
)
</foreach>
</insert>
<select id="selectVoteResult" parameterType="int">
SELECT
c.VOTDETSEQ,
v.LOCVOTCON,
COUNT(v.VOTDETSEQ) AS VOTE_COUNT
FROM
votchoice c
LEFT JOIN
votdetail v ON c.LOCVOTSEQ = v.LOCVOTSEQ AND c.VOTDETSEQ = v.VOTDETSEQ
WHERE
c.LOCVOTSEQ = #{LOCVOTSEQ}
GROUP BY
c.LOCVOTSEQ, c.VOTDETSEQ
ORDER BY
VOTE_COUNT DESC
</select>
</mapper>

View File

@ -30,6 +30,7 @@
CMNCODLV1 = 600;
</insert>
<!-- 색상 조회 YON는 user, YNP는 프로젝트-->
<select id="selectColorList" resultType="Map">
SELECT
CMNCODVAL
@ -48,6 +49,7 @@
</if>
</select>
<!-- mbti 조회 -->
<select id="selectMbtiList" resultType="Map">
SELECT
CMNCODVAL
@ -60,6 +62,7 @@
CMNCODODR != 0
</select>
<!-- 비밀번호 힌트 조회 -->
<select id="selectPwhintList" resultType="Map">
SELECT
CMNCODVAL
@ -72,6 +75,7 @@
CMNCODODR != 0
</select>
<!-- 선택한 색상 사용 중으로 업데이트 -->
<update id="updateColorYon" parameterType="Map">
UPDATE commoncod
SET
@ -84,6 +88,7 @@
WHERE CMNCODVAL = #{color};
</update>
<!-- 수정 시 기존 컬러 사용안함으로 업데이트 -->
<update id="updateColorChange" parameterType="Map">
UPDATE commoncod
SET
@ -101,17 +106,31 @@
WHERE CMNCODVAL BETWEEN 300101 AND 300103
</select>
<!-- 연도 -->
<select id="selectYearCategories" resultType="Map">
SELECT
CMNCODVAL
,CMNCODNAM
CMNCODVAL,
CMNCODNAM
FROM
commoncod
commoncod
WHERE
CMNCODLV1 = 900
CMNCODLV1 = 900
AND
CMNCODODR != 0
CMNCODODR != 0
AND
(CMNCODNAM = 'All' OR CMNCODNAM IN (
SELECT DISTINCT
CAST(YEAR(STR_TO_DATE(PROJCTSTR, '%Y-%m-%d')) AS CHAR) AS project_year
FROM
netprojct
WHERE
PROJCTSTR IS NOT NULL
))
ORDER BY
CASE WHEN CMNCODODR = 1 THEN 0 ELSE 1 END ASC,
CMNCODODR DESC
</select>
<select id="selectcheckCategoryExists" parameterType="Map" resultType="Long">
select
count(*) checkCategory
@ -127,4 +146,20 @@
FROM commoncod
WHERE CMNCODVAL IN ('700101', '700102', '700103')
</select>
<select id="selectCodeList" parameterType="Map">
/* 코드 목록 조회 */
SELECT
CMNCODVAL,
CMNCODNAM,
CMNCODODR
FROM
COMMONCOD
WHERE
CMNCODLV1 = #{CMNCODLV1} AND CMNCODLV2 LIKE CONCAT(#{CMNCODLV2}, '%')
AND
CMNCODYON = 1
</select>
</mapper>

View File

@ -14,10 +14,10 @@
FROM localbord b
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
WHERE LOCBRDTYP = '300103'
<if test="searchKeyword != null and searchKeyword != ''">
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if>
ORDER BY LOCBRDUDT DESC
ORDER BY LOCBRDUDT DESC
<if test="size != null">
LIMIT #{size}
</if>
</select>
<!-- 자유/익명 게시판 조회 (작성자 이름 포함) -->
@ -28,13 +28,11 @@
b.LOCBRDCON AS content,
b.LOCBRDUDT AS date,
b.LOCBRDCNT AS cnt,
b.LOCBRDNIC AS nickname,
m.MEMBERNAM AS author
FROM localbord b
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
WHERE b.LOCBRDTYP IN ('300101', '300102')
<if test="searchKeyword != null and searchKeyword != ''">
AND b.LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if>
ORDER BY
<choose>
<when test="orderBy == 'date'"> b.LOCBRDUDT DESC </when>
@ -50,8 +48,8 @@
<!-- 게시물 작성 -->
<insert id="insertBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ">
INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP)
VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP})
INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP, LOCBRDNIC)
VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP}, #{LOCBRDNIC})
</insert>
<!-- 첨부파일 저장 -->
@ -65,6 +63,57 @@
)
</insert>
<!-- 멀티 첨부파일 저장 -->
<insert id="insertAttachments" parameterType="map">
INSERT INTO commonfil (
CMNBRDSEQ,
CMNFLENAM,
CMNFLEORG,
CMNFLEPAT,
CMNFLEEXT,
CMNFLESIZ,
CMNFLEREG,
CMNFLERDT
) VALUES
<foreach collection="list" item="item" index="index" open="(" separator="),(" close=")">
#{LOCBRDSEQ},
#{item.saveFileName},
#{item.originalFileName},
#{item.filePath},
#{item.extension},
#{item.fileSize},
#{CMNFLEREG},
NOW()
</foreach>
</insert>
<!-- 에디터 첨부 이미지 저장 -->
<insert id="insertUploadEditorImageInfo" parameterType="map">
<selectKey keyProperty="id" order="AFTER" resultType="long">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO commonfil (
CMNFLENAM,
CMNFLEORG,
CMNFLEPAT,
CMNFLEEXT,
CMNFLESIZ,
CMNFLEREG,
CMNFLERDT,
CMNFLETYP
) VALUES (
#{CMNFLENAM},
#{CMNFLEORG},
#{CMNFLEPAT},
#{CMNFLEEXT},
#{CMNFLESIZ},
#{CMNFLEREG},
NOW(),
2
)
</insert>
<!-- 게시물 상세정보 조회 -->
<select id="selectBoardDetail" resultType="io.company.localhost.common.dto.MapDto">
SELECT
@ -74,8 +123,29 @@
b.LOCBRDUDT AS date,
b.LOCBRDTYP AS type,
b.LOCBRDCNT AS cnt,
b.LOCBRDNIC AS nickname,
m.MEMBERNAM AS author,
m.MEMBERSEQ AS authorId
m.MEMBERSEQ AS authorId,
m.MEMBERPRF AS profileImg
FROM localbord b
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
WHERE b.LOCBRDSEQ = #{boardId}
</select>
<!-- 게시물 상세정보 조회2 -->
<select id="selectBoardDetail2" resultType="io.company.localhost.common.dto.MapDto">
SELECT
b.LOCBRDSEQ AS id,
b.LOCBRDTTL AS title,
b.LOCBRDCON AS content,
b.LOCBRDUDT AS date,
b.LOCBRDTYP AS type,
b.LOCBRDNIC AS nickname,
b.LOCBRDCNT AS cnt,
b.LOCBRDPWD AS password,
m.MEMBERNAM AS author,
m.MEMBERSEQ AS authorId,
m.MEMBERPRF AS profileImg
FROM localbord b
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
WHERE b.LOCBRDSEQ = #{boardId}
@ -87,10 +157,36 @@
SELECT CMNFLESEQ AS id, CMNFLEORG AS originalName, CMNFLENAM AS fileName, CMNFLEPAT AS path,
CMNFLEEXT AS extension, CMNFLESIZ AS size, CMNFLERDT AS uploadDate
FROM commonfil
WHERE CMNBRDSEQ = #{boardId}
WHERE CMNBRDSEQ = #{boardId} and CMNFLETYP = 1
ORDER BY CMNFLERDT DESC
</select>
<!-- 게시글 삭제 파일 목록 조회 -->
<select id="selectFilesInfo" resultType="io.company.localhost.vo.FileVo">
SELECT
CMNFLESEQ,
CMNBRDSEQ,
CMNFLENAM,
CMNFLEORG,
CMNFLEPAT,
CMNFLEEXT,
CMNFLESIZ,
CMNFLETYP
FROM
COMMONFIL
WHERE
CMNBRDSEQ = #{LOCBRDSEQ}
AND CMNFLETYP IN (1, 2)
</select>
<!-- 파일 목록 조회 -->
<select id="deleteFiles">
DELETE FROM
COMMONFIL
WHERE
CMNBRDSEQ = #{LOCBRDSEQ}
</select>
<!-- 게시물 삭제 -->
<delete id="deleteBoard">
DELETE FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ}
@ -102,6 +198,18 @@
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</delete>
<!-- 게시물 삭제 시 좋아요/싫어요 삭제 -->
<delete id="deleteGoodOrBadByBoardId">
DELETE FROM localgorb
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</delete>
<!-- 댓글 및 대댓글 삭제 시 좋아요/싫어요 삭제 -->
<delete id="deleteGoodOrBadByCommentId">
DELETE FROM localgorb
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
</delete>
<!-- 게시물 수정 -->
<update id="updateBoard">
UPDATE localbord
@ -113,18 +221,46 @@
<select id="selectReaction" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD
FROM localgorb
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
AND MEMBERSEQ = #{MEMBERSEQ}
WHERE
<choose>
<when test="LOCCMTSEQ == null">
LOCBRDSEQ = #{LOCBRDSEQ} AND LOCCMTSEQ IS NULL
</when>
<otherwise>
LOCBRDSEQ = #{LOCBRDSEQ} AND LOCCMTSEQ = #{LOCCMTSEQ}
</otherwise>
</choose>
AND
MEMBERSEQ = #{MEMBERSEQ}
</select>
<!-- 반응 업데이트 -->
<update id="updateReaction">
UPDATE localgorb
SET LOCGOBGOD = #{LOCGOBGOD}, LOCGOBBAD = #{LOCGOBBAD}
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
AND MEMBERSEQ = #{MEMBERSEQ}
WHERE
<choose>
<when test="LOCCMTSEQ == null">
LOCBRDSEQ = #{LOCBRDSEQ} AND LOCCMTSEQ IS NULL
</when>
<otherwise>
LOCBRDSEQ = #{LOCBRDSEQ} AND LOCCMTSEQ = #{LOCCMTSEQ}
</otherwise>
</choose>
AND
MEMBERSEQ = #{MEMBERSEQ}
</update>
<update id="updateBoardIndexToFile">
UPDATE
COMMONFIL
SET
CMNBRDSEQ = #{LOCBRDSEQ}
WHERE
CMNFLESEQ IN
<foreach collection="editorImgList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</update>
<!-- 새 반응 삽입 -->
@ -137,13 +273,14 @@
<select id="selectComments" resultType="io.company.localhost.common.dto.MapDto">
SELECT
c.LOCCMTSEQ,c.LOCBRDSEQ,c.LOCCMTPNT,c.LOCCMTRPY,
c.LOCCMTUDT,c.LOCCMTPWD,c.LOCCMTRDT,c.LOCCMTPNT,
c.LOCCMTUDT,c.LOCCMTPWD,c.LOCCMTRDT,
m.MEMBERNAM AS author,
m.MEMBERSEQ AS authorId
m.MEMBERSEQ AS authorId,
c.LOCCMTNIC
FROM localcomt c
LEFT JOIN netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
WHERE LOCBRDSEQ = #{LOCBRDSEQ} and LOCCMTPNT = 1
ORDER BY LOCCMTPNT ASC, LOCCMTUDT ASC
ORDER BY LOCCMTRDT DESC
</select>
<!-- 대댓글 조회 -->
@ -152,17 +289,19 @@
c.LOCCMTSEQ,c.LOCBRDSEQ,c.LOCCMTPNT,c.LOCCMTRPY,
c.LOCCMTUDT,c.LOCCMTPWD,c.LOCCMTRDT,c.LOCCMTPNT,
m.MEMBERNAM AS author,
m.MEMBERSEQ AS authorId
m.MEMBERSEQ AS authorId,
m.MEMBERPRF AS profileImg,
c.LOCCMTNIC
FROM localcomt c
LEFT JOIN netmember m ON c.MEMBERSEQ = m.MEMBERSEQ
WHERE LOCCMTPNT = #{LOCCMTPNT} and LOCCMTPNT != 1
ORDER BY LOCCMTPNT ASC, LOCCMTUDT ASC
ORDER BY LOCCMTRDT DESC
</select>
<!-- 댓글/대댓글 작성 -->
<insert id="insertCommentOrReply">
INSERT INTO localcomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTUDT, LOCCMTPNT, MEMBERSEQ)
VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), NOW() , #{LOCCMTPNT}, #{MEMBERSEQ})
INSERT INTO localcomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTUDT, LOCCMTPNT, MEMBERSEQ,LOCCMTNIC)
VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), NOW() , #{LOCCMTPNT}, #{MEMBERSEQ},#{LOCCMTNIC})
</insert>
<!-- 댓글/대댓글 수정 -->
@ -176,6 +315,7 @@
<update id="updateSoftDeleteComment">
UPDATE localcomt
SET LOCCMTRPY = '삭제된 댓글입니다'
,LOCCMTUDT = NOW()
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
AND EXISTS (
SELECT 1 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
@ -191,22 +331,12 @@
)
</delete>
<!-- 대댓글 삭제 -->
<delete id="deleteReply">
DELETE FROM localcomt
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
<!-- 특정 댓글에 달린 대댓글 개수 조회 -->
<select id="selectReplyCount" resultType="int">
SELECT COUNT(*)
FROM localcomt
WHERE LOCCMTPNT = #{LOCCMTSEQ}
AND LOCCMTPNT IS NOT NULL
</delete>
<!-- 대댓글인지 확인 -->
<select id="selectIsReply" resultType="int">
SELECT COUNT(1) FROM localcomt
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPNT IS NOT NULL
</select>
<!-- 댓글에 대댓글이 있는지 확인 -->
<select id="selectHasReplies" resultType="int">
SELECT COUNT(1) FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
</select>
<!-- 댓글 비밀번호 조회 -->
@ -234,14 +364,14 @@
<select id="selectCountComments" parameterType="long" resultType="int">
SELECT COUNT(*)
FROM localcomt
WHERE LOCBRDSEQ = #{boardId}
WHERE LOCBRDSEQ = #{boardId} and LOCCMTPNT = 1
</select>
<!-- 첨부파일 유무 -->
<select id="selectIsAttachments" resultType="int">
SELECT COUNT(*)
FROM commonfil
WHERE CMNBRDSEQ = #{boardId}
WHERE CMNBRDSEQ = #{boardId} and CMNFLETYP = 1
</select>
<!-- 게시물 좋아요/싫어요 개수 조회 -->
@ -250,8 +380,33 @@
COALESCE(SUM(CASE WHEN LOCGOBGOD = 'T' THEN 1 ELSE 0 END), 0) AS likeCount,
COALESCE(SUM(CASE WHEN LOCGOBBAD = 'T' THEN 1 ELSE 0 END), 0) AS dislikeCount
FROM localgorb
WHERE LOCBRDSEQ = #{boardId};
WHERE LOCBRDSEQ = #{boardId} AND LOCCMTSEQ IS NULL;
</select>
<!-- 사용자 게시물 좋아요/싫어요 상태 조회 -->
<select id="selectMyBoardReaction">
SELECT
LOCGOBGOD,
LOCGOBBAD
FROM
localgorb
WHERE
LOCBRDSEQ = #{id}
AND LOCCMTSEQ IS NULL
AND MEMBERSEQ = #{userId};
</select>
<!-- 사용자 댓글 게시물 좋아요/싫어요 상태 조회 -->
<select id="selectMyBoardReactions">
SELECT
LOCGOBGOD,
LOCGOBBAD
FROM
localgorb
WHERE
LOCBRDSEQ = #{boardId}
AND LOCCMTSEQ = #{commentId}
AND MEMBERSEQ = #{userId};
</select>
<!-- 댓글별 좋아요/싫어요 개수 조회 -->
@ -265,5 +420,64 @@
LIMIT 1
</select>
<!-- 삭제 파일 정보 조회 -->
<select id="selectDelFileInfo" >
SELECT
CMNFLEPAT
FROM
commonfil
WHERE
CMNFLESEQ in
<foreach collection="array" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</select>
<!-- 파일 정보 삭제 -->
<delete id="deleteFileInfo" >
DELETE FROM
commonfil
WHERE
CMNFLESEQ in
<foreach collection="array" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</delete>
<!-- 프로파일 이미지 조회 -->
<select id="selectUserProfileImg">
SELECT
MEMBERPRF
FROM
NETMEMBER
WHERE
MEMBERSEQ = ${userId}
</select>
<!-- 게시글 정보가 없는 파일 조회-->
<select id="selectFilesBoardIndexIsNull" resultType="io.company.localhost.vo.FileVo">
SELECT
CMNFLESEQ,
CMNBRDSEQ,
CMNFLENAM,
CMNFLEORG,
CMNFLEPAT,
CMNFLEEXT,
CMNFLESIZ,
CMNFLETYP
FROM
COMMONFIL
WHERE
CMNBRDSEQ IS NULL
</select>
<!-- 파일 데이터 삭제 -->
<delete id="deleteTrashFileData">
DELETE FROM
COMMONFIL
WHERE
CMNFLESEQ = #{CMNFLESEQ}
</delete>
</mapper>

View File

@ -8,17 +8,44 @@
VALUES (#{employeeId}, #{date}, #{type}, NOW(), #{receiverId})
</insert>
<!-- 휴가 데이터 삭제 -->
<delete id="deleteVacation" parameterType="long">
<!-- 특정 날짜의 휴가 ID 조회 (존재 여부 확인) -->
<select id="findVacationIdByDate" resultType="Long">
SELECT LOCVACSEQ
FROM localvaca
WHERE MEMBERSEQ = #{userId} AND LOCVACUDT = #{date}
AND LOCVACRMM IS NULL
</select>
<!-- 휴가 수정 (기존 데이터가 존재하는 경우) -->
<update id="updateVacation">
UPDATE localvaca
SET LOCVACTYP = #{type}
WHERE LOCVACSEQ = #{id}
</update>
<!-- 여러 개의 휴가 삭제 -->
<delete id="deleteVacation">
DELETE FROM localvaca
WHERE LOCVACSEQ = #{vacationId}
WHERE LOCVACSEQ IN
<foreach item="id" collection="vacationIds" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!-- 휴가 정보 조회 -->
<select id="selectVacations" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCVACSEQ, MEMBERSEQ, LOCVACUDT, LOCVACTYP, LOCVACRMM
FROM localvaca
WHERE DATE_FORMAT(LOCVACUDT, '%Y-%m') = CONCAT(#{year}, '-', LPAD(#{month}, 2, '0'))
SELECT
A.LOCVACSEQ, A.MEMBERSEQ, A.LOCVACUDT, A.LOCVACTYP, A.LOCVACRMM, B.MEMBERPRF, B.MEMBERNAM, C.CMNCODNAM AS usercolor
FROM
localvaca A
LEFT JOIN
NETMEMBER B ON A.MEMBERSEQ = B.MEMBERSEQ
LEFT JOIN
COMMONCOD C ON C.CMNCODVAL = B.MEMBERCOL
WHERE
DATE_FORMAT(LOCVACUDT, '%Y-%m') = CONCAT(#{year}, '-', LPAD(#{month}, 2, '0'))
ORDER BY
A.LOCVACUDT ASC
</select>
<!-- 사용자가 사용한 연차 목록 조회 -->
@ -33,23 +60,31 @@
FROM localvaca
WHERE MEMBERSEQ = #{userId}
AND YEAR(LOCVACUDT) = #{year}
AND DATE_FORMAT(LOCVACUDT, '%Y') = DATE_FORMAT(CURDATE(), '%Y')
GROUP BY LOCVACUDT, LOCVACTYP, LOCVACRMM
ORDER BY LOCVACUDT DESC
</select>
<!-- 사용자가 받은 연차 목록 조회 -->
<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
WHERE LOCVACRMM = #{userId}
AND YEAR(LOCVACUDT) = #{year}
AND DATE_FORMAT(LOCVACUDT, '%Y') = DATE_FORMAT(CURDATE(), '%Y')
GROUP BY LOCVACUDT, LOCVACTYP, MEMBERSEQ
ORDER BY LOCVACUDT DESC
WHERE LOCVACRMM = #{userId} -- 현재 로그인한 사용자가 받은 연차
AND YEAR(LOCVACUDT) = #{year} -- 해당 연도의 데이터만 가져옴
GROUP BY LOCVACUDT, LOCVACTYP, MEMBERSEQ -- 연차를 보낸 사람별로 그룹화
ORDER BY LOCVACUDT DESC;
</select>
<!-- 전체 직원 남은 연차 조회 -->
<select id="selectEmployeeRemainingVacation" resultType="io.company.localhost.common.dto.MapDto">
<![CDATA[
@ -114,7 +149,33 @@
</select>
<select id="selectSentVacationCount" resultType="io.company.localhost.common.dto.MapDto">
SELECT COUNT(*) as count FROM localvaca WHERE MEMBERSEQ = #{userId} AND LOCVACRMM = #{receiverId}
SELECT COUNT(*) as count FROM localvaca WHERE MEMBERSEQ = #{userId} AND LOCVACRMM = #{receiverId} AND YEAR(LOCVACUDT) = YEAR(NOW())
</select>
<select id="selectMemberVacationsInMain">
/* 메인페이지 휴가자 조회 */
SELECT
A.LOCVACSEQ,
A.MEMBERSEQ,
A.LOCVACUDT,
A.LOCVACTYP,
A.LOCVACRMM,
B.MEMBERPRF,
B.MEMBERNAM,
C.CMNCODNAM as usercolor
FROM
localvaca A
LEFT JOIN
NETMEMBER B on A.MEMBERSEQ = B.MEMBERSEQ
LEFT JOIN
COMMONCOD C on C.CMNCODVAL = B.MEMBERCOL
WHERE
DATE_FORMAT(LOCVACUDT, '%Y-%m') = CONCAT(#{year}, '-', LPAD(${month}, 2, '0'))
AND LOCVACRMM is null
GROUP BY
A.LOCVACUDT, A.MEMBERSEQ
ORDER BY
A.LOCVACUDT ASC;
</select>

View File

@ -35,13 +35,18 @@
)
</insert>
<select id="selectVoteList" parameterType="map">
SELECT * FROM (
SELECT * FROM (
SELECT
a.*,
DATE_FORMAT(a.LOCVOTRDT, '%Y-%m-%d %H:%i') AS formatted_LOCVOTRDT,
DATE_FORMAT(a.LOCVOTEDT, '%Y-%m-%d %H:%i') AS formatted_LOCVOTEDT,
b.*,
b.MEMBERSEQ,
b.MEMBERNAM,
b.MEMBERCOL,
b.MEMBERPRF,
c.CMNCODNAM AS usercolor,
(SELECT COUNT(*) FROM votmember vm WHERE vm.LOCVOTSEQ = a.LOCVOTSEQ) AS total_votable,
(SELECT COUNT(*) FROM votrecord v WHERE v.LOCVOTSEQ = a.LOCVOTSEQ) AS total_voted,
CASE
WHEN EXISTS (
SELECT 1
@ -57,18 +62,36 @@
netmember b ON a.LOCVOTREG = b.MEMBERSEQ
LEFT JOIN
commoncod c ON b.MEMBERCOL = c.CMNCODVAL
WHERE 1=1
WHERE
1=1
<include refid="searchConditions"/>
AND EXISTS (
SELECT 1 FROM votmember vm
WHERE vm.LOCVOTSEQ = a.LOCVOTSEQ
AND vm.MEMBERSEQ = #{userId}
)
) AS subquery
WHERE 1=1
<if test="myVote != null and myVote != ''">
<choose>
<when test='myVote == "1"'>
<when test='myVote == "1"' >
AND myvoted = 'Y'
AND LOCVOTDEL IS NULL
</when>
<when test='myVote == "2"' >
AND myvoted = 'N'
AND LOCVOTDEL IS NULL
</when>
</choose>
</if>
ORDER BY formatted_LOCVOTRDT DESC
<choose>
<when test='myVote == "2"'>
ORDER BY LOCVOTEDT ASC, formatted_LOCVOTRDT DESC
</when>
<otherwise>
ORDER BY formatted_LOCVOTRDT DESC
</otherwise>
</choose>
</select>
<update id="updateEndData" parameterType="map">
UPDATE

View File

@ -5,56 +5,56 @@
<!-- 검색어 조건 -->
<if test="searchKeyword != null and searchKeyword != ''">
and (
REGEXP_REPLACE(w.WRDDICTTL, '\\[\\{.*?"insert":"', '') LIKE CONCAT('%', #{searchKeyword}, '%')
OR REGEXP_REPLACE(w.WRDDICCON, '\\[\\{.*?"insert":"', '') LIKE CONCAT('%', #{searchKeyword}, '%')
w.WRDDICTTL LIKE CONCAT('%', #{searchKeyword}, '%')
OR w.WRDDICCON LIKE CONCAT('%', #{searchKeyword}, '%')
)
</if>
<!-- 색인표 조건 -->
<if test="indexKeyword != null and indexKeyword != ''">
<choose>
<!-- 한글 ㄱ ~ ㅎ에 대한 검색 -->
<when test='indexKeyword == "ㄱ"'>
and w.WRDDICTTL BETWEEN '가' AND '깋'
</when>
<when test='indexKeyword == "ㄴ"'>
and w.WRDDICTTL BETWEEN '나' AND '닣'
</when>
<when test='indexKeyword == "ㄷ"'>
and w.WRDDICTTL BETWEEN '다' AND '딷'
</when>
<when test='indexKeyword == "ㄹ"'>
and w.WRDDICTTL BETWEEN '라' AND '릿'
</when>
<when test='indexKeyword == "ㅁ"'>
and w.WRDDICTTL BETWEEN '마' AND '맇'
</when>
<when test='indexKeyword == "ㅂ"'>
and w.WRDDICTTL BETWEEN '바' AND '빟'
</when>
<when test='indexKeyword == "ㅅ"'>
and w.WRDDICTTL BETWEEN '사' AND '싷'
</when>
<when test='indexKeyword == "ㅇ"'>
and w.WRDDICTTL BETWEEN '아' AND '잏'
</when>
<when test='indexKeyword == "ㅈ"'>
and w.WRDDICTTL BETWEEN '자' AND '짛'
</when>
<when test='indexKeyword == "ㅊ"'>
and w.WRDDICTTL BETWEEN '차' AND '칳'
</when>
<when test='indexKeyword == "ㅋ"'>
and w.WRDDICTTL BETWEEN '카' AND '킿'
</when>
<when test='indexKeyword == "ㅌ"'>
and w.WRDDICTTL BETWEEN '타' AND '틷'
</when>
<when test='indexKeyword == "ㅍ"'>
and w.WRDDICTTL BETWEEN '파' AND '핗'
</when>
<when test='indexKeyword == "ㅎ"'>
and w.WRDDICTTL BETWEEN '하' AND '힣'
</when>
<!-- 한글 ㄱ ~ ㅎ에 대한 검색 (자음만 있는 경우도 포함) -->
<when test='indexKeyword == "ㄱ"'>
AND (w.WRDDICTTL BETWEEN '가' AND '깋' OR w.WRDDICTTL LIKE 'ㄱ%')
</when>
<when test='indexKeyword == "ㄴ"'>
AND (w.WRDDICTTL BETWEEN '나' AND '닣' OR w.WRDDICTTL LIKE 'ㄴ%')
</when>
<when test='indexKeyword == "ㄷ"'>
AND (w.WRDDICTTL BETWEEN '다' AND '딷' OR w.WRDDICTTL LIKE 'ㄷ%')
</when>
<when test='indexKeyword == "ㄹ"'>
AND (w.WRDDICTTL BETWEEN '라' AND '릿' OR w.WRDDICTTL LIKE 'ㄹ%')
</when>
<when test='indexKeyword == "ㅁ"'>
AND (w.WRDDICTTL BETWEEN '마' AND '밓' OR w.WRDDICTTL LIKE 'ㅁ%')
</when>
<when test='indexKeyword == "ㅂ"'>
AND (w.WRDDICTTL BETWEEN '바' AND '빟' OR w.WRDDICTTL LIKE 'ㅂ%')
</when>
<when test='indexKeyword == "ㅅ"'>
AND (w.WRDDICTTL BETWEEN '사' AND '싷' OR w.WRDDICTTL LIKE 'ㅅ%')
</when>
<when test='indexKeyword == "ㅇ"'>
AND (w.WRDDICTTL BETWEEN '아' AND '잏' OR w.WRDDICTTL LIKE 'ㅇ%')
</when>
<when test='indexKeyword == "ㅈ"'>
AND (w.WRDDICTTL BETWEEN '자' AND '짛' OR w.WRDDICTTL LIKE 'ㅈ%')
</when>
<when test='indexKeyword == "ㅊ"'>
AND (w.WRDDICTTL BETWEEN '차' AND '칳' OR w.WRDDICTTL LIKE 'ㅊ%')
</when>
<when test='indexKeyword == "ㅋ"'>
AND (w.WRDDICTTL BETWEEN '카' AND '킿' OR w.WRDDICTTL LIKE 'ㅋ%')
</when>
<when test='indexKeyword == "ㅌ"'>
AND (w.WRDDICTTL BETWEEN '타' AND '틷' OR w.WRDDICTTL LIKE 'ㅌ%')
</when>
<when test='indexKeyword == "ㅍ"'>
AND (w.WRDDICTTL BETWEEN '파' AND '핗' OR w.WRDDICTTL LIKE 'ㅍ%')
</when>
<when test='indexKeyword == "ㅎ"'>
AND (w.WRDDICTTL BETWEEN '하' AND '힣' OR w.WRDDICTTL LIKE 'ㅎ%')
</when>
<!-- 알파벳 a ~ z에 대한 검색 -->
<when test='indexKeyword == "a"'>
and w.WRDDICTTL like "a%"
@ -134,14 +134,17 @@
<when test='indexKeyword == "z"'>
and w.WRDDICTTL like "z%"
</when>
<otherwise>
and w.WRDDICTTL like CONCAT('%', #{indexKeyword}, '%')
</otherwise>
</choose>
</if>
<!-- 카테고리 조건 -->
<if test="category != null and category != ''">
<if test="category != null and category != '' and category != 'all'">
and w.WRDDICCAT = #{category}
</if>
</sql>
<select id="getWordList" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
<select id="selectWordList" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
select
w.WRDDICSEQ,
w.WRDDICCAT,
@ -183,6 +186,9 @@
and w.WRDDICEDT IS NULL
<include refid="searchConditions"/>
order by w.WRDDICRDT desc
<if test="pageNum != null and pageNum != ''">
limit #{pageNum}
</if>
</select>
<select id="getTotal" parameterType="map" >
select count(*) from worddicty w
@ -190,6 +196,9 @@
<include refid="searchConditions"/>
</select>
<insert id="insertWord" parameterType="map">
<selectKey keyProperty="id" order="AFTER" resultType="long">
SELECT LAST_INSERT_ID()
</selectKey>
insert into worddicty
(
WRDDICCAT
@ -217,6 +226,47 @@
</if>
)
</insert>
<!-- 삭제 파일 정보 조회 -->
<select id="selectDelFileInfo" >
SELECT
CMNFLEPAT
FROM
commonfil
WHERE
CMNFLESEQ in
<foreach collection="array" item="item" separator="," open="(" close=")">
#{item}
</foreach>
AND CMNFLETYP = 3
</select>
<!-- 파일 정보 삭제 -->
<delete id="deleteFileInfo" >
DELETE FROM
commonfil
WHERE
CMNFLESEQ in
<foreach collection="array" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</delete>
<insert id="updateBoardIndexToFile">
/* 용어집 인덱스와 에디터 이미지 매핑 */
UPDATE
COMMONFIL
SET
CMNBRDSEQ = #{id},
CMNFLETYP = 3
WHERE
CMNFLESEQ IN
<foreach collection="editorImgList" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</insert>
<update id="updateWord" parameterType="map">
update
worddicty
@ -232,7 +282,7 @@
where
WRDDICSEQ = #{WRDDICSEQ}
</update>
<select id="getWordDetail" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
<select id="selectWordDetail" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
select *
from
worddicty
@ -249,4 +299,111 @@
#{id}
</foreach>
</update>
<select id="selectIndexCategory">
SELECT
CHARACTER_,
COUNT(*) AS COUNT
FROM (
SELECT 'ㄱ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '가' AND '깋' OR WRDDICTTL LIKE 'ㄱ%'
UNION ALL
SELECT 'ㄴ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '나' AND '닣' OR WRDDICTTL LIKE 'ㄴ%'
UNION ALL
SELECT 'ㄷ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '다' AND '딷' OR WRDDICTTL LIKE 'ㄷ%'
UNION ALL
SELECT 'ㄹ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '라' AND '릿' OR WRDDICTTL LIKE 'ㄹ%'
UNION ALL
SELECT 'ㅁ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '마' AND '밓' OR WRDDICTTL LIKE 'ㅁ%'
UNION ALL
SELECT 'ㅂ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '바' AND '빟' OR WRDDICTTL LIKE 'ㅂ%'
UNION ALL
SELECT 'ㅅ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '사' AND '싷' OR WRDDICTTL LIKE 'ㅅ%'
UNION ALL
SELECT 'ㅇ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '아' AND '잏' OR WRDDICTTL LIKE 'ㅇ%'
UNION ALL
SELECT 'ㅈ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '자' AND '짛' OR WRDDICTTL LIKE 'ㅈ%'
UNION ALL
SELECT 'ㅊ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '차' AND '칳' OR WRDDICTTL LIKE 'ㅊ%'
UNION ALL
SELECT 'ㅋ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '카' AND '킿' OR WRDDICTTL LIKE 'ㅋ%'
UNION ALL
SELECT 'ㅌ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '타' AND '틷' OR WRDDICTTL LIKE 'ㅌ%'
UNION ALL
SELECT 'ㅍ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '파' AND '핗' OR WRDDICTTL LIKE 'ㅍ%'
UNION ALL
SELECT 'ㅎ' AS CHARACTER_, WRDDICTTL FROM worddicty
WHERE WRDDICTTL BETWEEN '하' AND '힣' OR WRDDICTTL LIKE 'ㅎ%'
UNION ALL
SELECT 'a' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'a%'
UNION ALL
SELECT 'b' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'b%'
UNION ALL
SELECT 'c' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'c%'
UNION ALL
SELECT 'd' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'd%'
UNION ALL
SELECT 'e' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'e%'
UNION ALL
SELECT 'f' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'f%'
UNION ALL
SELECT 'g' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'g%'
UNION ALL
SELECT 'h' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'h%'
UNION ALL
SELECT 'i' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'i%'
UNION ALL
SELECT 'j' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'j%'
UNION ALL
SELECT 'k' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'k%'
UNION ALL
SELECT 'l' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'l%'
UNION ALL
SELECT 'm' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'm%'
UNION ALL
SELECT 'n' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'n%'
UNION ALL
SELECT 'o' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'o%'
UNION ALL
SELECT 'p' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'p%'
UNION ALL
SELECT 'q' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'q%'
UNION ALL
SELECT 'r' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'r%'
UNION ALL
SELECT 's' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 's%'
UNION ALL
SELECT 't' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 't%'
UNION ALL
SELECT 'u' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'u%'
UNION ALL
SELECT 'v' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'v%'
UNION ALL
SELECT 'w' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'w%'
UNION ALL
SELECT 'x' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'x%'
UNION ALL
SELECT 'y' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'y%'
UNION ALL
SELECT 'z' AS CHARACTER_, WRDDICTTL FROM worddicty WHERE WRDDICTTL LIKE 'z%'
) AS combined
GROUP BY CHARACTER_
ORDER BY
CASE
WHEN CHARACTER_ BETWEEN 'ㄱ' AND 'ㅎ' THEN 1
ELSE 2
END,
CHARACTER_
</select>
</mapper>