share job
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package com.company.gw;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableCaching
|
||||
public class GwBackendApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GwBackendApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.company.gw.board.controller;
|
||||
|
||||
import com.company.gw.board.service.BoardService;
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/board")
|
||||
@RequiredArgsConstructor
|
||||
public class BoardController {
|
||||
|
||||
private final BoardService boardService;
|
||||
|
||||
/** 게시물 목록 */
|
||||
@GetMapping("/{untyBbsCd}")
|
||||
public ApiResponse<Map<String, Object>> getPostList(
|
||||
@PathVariable String untyBbsCd,
|
||||
@RequestParam(defaultValue = "") String searchText,
|
||||
@RequestParam(defaultValue = "1") int pageNo,
|
||||
@RequestParam(defaultValue = "20") int pageSize,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(
|
||||
boardService.getPostList(currentUser.getCorpNo(), untyBbsCd, searchText, pageNo, pageSize));
|
||||
}
|
||||
|
||||
/** 게시물 상세 (조회수 증가) */
|
||||
@GetMapping("/{untyBbsCd}/{untyBbsSno}")
|
||||
public ApiResponse<Map<String, Object>> getPostInfo(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(
|
||||
boardService.getPostInfoForView(currentUser.getCorpNo(), untyBbsCd, untyBbsSno));
|
||||
}
|
||||
|
||||
/** 게시물 상세 (수정용, 조회수 미증가) */
|
||||
@GetMapping("/{untyBbsCd}/{untyBbsSno}/edit")
|
||||
public ApiResponse<Map<String, Object>> getPostInfoForEdit(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(
|
||||
boardService.getPostInfoForEdit(currentUser.getCorpNo(), untyBbsCd, untyBbsSno));
|
||||
}
|
||||
|
||||
/** 게시물 등록 */
|
||||
@PostMapping("/{untyBbsCd}")
|
||||
public ApiResponse<Map<String, Object>> insertPost(
|
||||
@PathVariable String untyBbsCd,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
body.put("untyBbsCd", untyBbsCd);
|
||||
return ApiResponse.ok(boardService.insertPost(currentUser.getCorpNo(), body));
|
||||
}
|
||||
|
||||
/** 게시물 수정 */
|
||||
@PutMapping("/{untyBbsCd}/{untyBbsSno}")
|
||||
public ApiResponse<Void> updatePost(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
body.put("untyBbsCd", untyBbsCd);
|
||||
boardService.updatePost(currentUser.getCorpNo(), untyBbsSno, body);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 게시물 삭제 */
|
||||
@DeleteMapping("/{untyBbsCd}/{untyBbsSno}")
|
||||
public ApiResponse<Void> deletePost(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
boardService.deletePost(currentUser.getCorpNo(), untyBbsCd, untyBbsSno);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 댓글 목록 */
|
||||
@GetMapping("/{untyBbsCd}/{untyBbsSno}/comments")
|
||||
public ApiResponse<List<Map<String, Object>>> getCommentList(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(
|
||||
boardService.getCommentList(currentUser.getCorpNo(), untyBbsCd, untyBbsSno));
|
||||
}
|
||||
|
||||
/** 댓글 등록 */
|
||||
@PostMapping("/{untyBbsCd}/{untyBbsSno}/comments")
|
||||
public ApiResponse<Void> insertComment(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@RequestBody Map<String, String> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
boardService.insertComment(currentUser.getCorpNo(), untyBbsCd, untyBbsSno, body.get("cmmtCn"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 댓글 삭제 */
|
||||
@DeleteMapping("/{untyBbsCd}/{untyBbsSno}/comments/{cmmtSno}")
|
||||
public ApiResponse<Void> deleteComment(
|
||||
@PathVariable String untyBbsCd,
|
||||
@PathVariable Long untyBbsSno,
|
||||
@PathVariable Long cmmtSno,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
boardService.deleteComment(currentUser.getCorpNo(), untyBbsCd, untyBbsSno, cmmtSno);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.company.gw.board.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface BoardMapper {
|
||||
|
||||
List<Map<String, Object>> getPostList(Map<String, Object> param);
|
||||
|
||||
long getPostListCount(Map<String, Object> param);
|
||||
|
||||
Map<String, Object> getPostInfo(Map<String, Object> param);
|
||||
|
||||
void insertPost(Map<String, Object> param);
|
||||
|
||||
void updatePost(Map<String, Object> param);
|
||||
|
||||
void increaseInqrCnt(Map<String, Object> param);
|
||||
|
||||
void updateEtcAtchNo(Map<String, Object> param);
|
||||
|
||||
void updatePhotoAtchNo(Map<String, Object> param);
|
||||
|
||||
void updateCmmtCnt(Map<String, Object> param);
|
||||
|
||||
void deletePost(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> getCommentList(Map<String, Object> param);
|
||||
|
||||
Map<String, Object> getCommentInfo(Map<String, Object> param);
|
||||
|
||||
void insertComment(Map<String, Object> param);
|
||||
|
||||
void deleteComment(Map<String, Object> param);
|
||||
|
||||
void deleteCommentsByPost(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.company.gw.board.service;
|
||||
|
||||
import com.company.gw.board.mapper.BoardMapper;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.service.AttachService;
|
||||
import com.company.gw.common.service.SequenceService;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BoardService {
|
||||
|
||||
private final BoardMapper boardMapper;
|
||||
private final SequenceService sequenceService;
|
||||
private final AttachService attachService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 게시물 목록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
public Map<String, Object> getPostList(String corpNo, String untyBbsCd,
|
||||
String searchText, int pageNo, int pageSize) {
|
||||
if (pageSize > 200) pageSize = 200;
|
||||
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("untyBbsCd", untyBbsCd);
|
||||
param.put("searchText", searchText);
|
||||
param.put("pageNo", pageNo);
|
||||
param.put("pageSize", pageSize);
|
||||
|
||||
List<Map<String, Object>> list = boardMapper.getPostList(param);
|
||||
long total = boardMapper.getPostListCount(param);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
result.put("pageNo", pageNo);
|
||||
result.put("pageSize", pageSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 게시물 상세 (조회수 증가 포함)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public Map<String, Object> getPostInfoForView(String corpNo, String untyBbsCd, Long untyBbsSno) {
|
||||
Map<String, Object> param = buildPostParam(corpNo, untyBbsCd, untyBbsSno);
|
||||
|
||||
boardMapper.increaseInqrCnt(param);
|
||||
|
||||
Map<String, Object> info = boardMapper.getPostInfo(param);
|
||||
if (info == null) throw new BizException("게시물이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
|
||||
// 첨부파일 목록 조회
|
||||
String etcAtchNo = (String) info.get("ETC_ATCH_NO");
|
||||
String photoAtchNo = (String) info.get("PHOTO_ATCH_NO");
|
||||
if (etcAtchNo != null) info.put("etcFileList", attachService.getFileList(etcAtchNo));
|
||||
if (photoAtchNo != null) info.put("photoFileList", attachService.getFileList(photoAtchNo));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// 수정화면용 (조회수 증가 없음)
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getPostInfoForEdit(String corpNo, String untyBbsCd, Long untyBbsSno) {
|
||||
Map<String, Object> info = boardMapper.getPostInfo(buildPostParam(corpNo, untyBbsCd, untyBbsSno));
|
||||
if (info == null) throw new BizException("게시물이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
|
||||
String etcAtchNo = (String) info.get("ETC_ATCH_NO");
|
||||
String photoAtchNo = (String) info.get("PHOTO_ATCH_NO");
|
||||
if (etcAtchNo != null) info.put("etcFileList", attachService.getFileList(etcAtchNo));
|
||||
if (photoAtchNo != null) info.put("photoFileList", attachService.getFileList(photoAtchNo));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 게시물 등록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public Map<String, Object> insertPost(String corpNo, Map<String, Object> body) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Integer sno = Integer.parseInt(
|
||||
sequenceService.getNextSeqString("SX_GW0020.UNTY_BBS_SNO", 10));
|
||||
|
||||
Map<String, Object> param = new HashMap<>(body);
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
param.put("untyBbsSno", sno);
|
||||
|
||||
boardMapper.insertPost(param);
|
||||
|
||||
// 첨부 확정
|
||||
String etcAtchNo = (String) body.get("etcAtchNo");
|
||||
String photoAtchNo = (String) body.get("photoAtchNo");
|
||||
if (etcAtchNo != null) {
|
||||
param.put("etcAtchNo", etcAtchNo);
|
||||
boardMapper.updateEtcAtchNo(param);
|
||||
attachService.confirmAtchNo(etcAtchNo, "SX_GW0020.ETC_ATCH_NO");
|
||||
}
|
||||
if (photoAtchNo != null) {
|
||||
param.put("photoAtchNo", photoAtchNo);
|
||||
boardMapper.updatePhotoAtchNo(param);
|
||||
attachService.confirmAtchNo(photoAtchNo, "SX_GW0020.PHOTO_ATCH_NO");
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("untyBbsSno", sno);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 게시물 수정
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void updatePost(String corpNo, Long untyBbsSno, Map<String, Object> body) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> param = buildPostParam(corpNo, (String) body.get("untyBbsCd"), untyBbsSno);
|
||||
|
||||
Map<String, Object> existing = boardMapper.getPostInfo(param);
|
||||
if (existing == null) throw new BizException("게시물이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
if (!usrId.equals(existing.get("CTUSR_ID"))) {
|
||||
throw new BizException("작성자만 수정할 수 있습니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
param.putAll(body);
|
||||
param.put("usrId", usrId);
|
||||
boardMapper.updatePost(param);
|
||||
|
||||
// 첨부 처리 (새 파일이 업로드된 경우)
|
||||
String etcAtchNo = (String) body.get("etcAtchNo");
|
||||
if (etcAtchNo != null) {
|
||||
param.put("etcAtchNo", etcAtchNo);
|
||||
boardMapper.updateEtcAtchNo(param);
|
||||
attachService.confirmAtchNo(etcAtchNo, "SX_GW0020.ETC_ATCH_NO");
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 게시물 삭제
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void deletePost(String corpNo, String untyBbsCd, Long untyBbsSno) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> param = buildPostParam(corpNo, untyBbsCd, untyBbsSno);
|
||||
|
||||
Map<String, Object> info = boardMapper.getPostInfo(param);
|
||||
if (info == null) throw new BizException("게시물이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
if (!usrId.equals(info.get("CTUSR_ID"))) {
|
||||
throw new BizException("작성자만 삭제할 수 있습니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
boardMapper.deleteCommentsByPost(param);
|
||||
boardMapper.deletePost(param);
|
||||
|
||||
// 첨부파일 삭제
|
||||
String etcAtchNo = (String) info.get("ETC_ATCH_NO");
|
||||
String photoAtchNo = (String) info.get("PHOTO_ATCH_NO");
|
||||
if (etcAtchNo != null) attachService.deleteFilesByAtchNo(etcAtchNo, true);
|
||||
if (photoAtchNo != null) attachService.deleteFilesByAtchNo(photoAtchNo, true);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 댓글
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getCommentList(String corpNo, String untyBbsCd, Long untyBbsSno) {
|
||||
return boardMapper.getCommentList(buildPostParam(corpNo, untyBbsCd, untyBbsSno));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void insertComment(String corpNo, String untyBbsCd, Long untyBbsSno, String cmmtCn) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Integer cmmtSno = Integer.parseInt(
|
||||
sequenceService.getNextSeqString("SX_GW0030.CMMT_SNO", 10));
|
||||
|
||||
Map<String, Object> param = buildPostParam(corpNo, untyBbsCd, untyBbsSno);
|
||||
param.put("cmmtSno", cmmtSno);
|
||||
param.put("cmmtCn", cmmtCn);
|
||||
param.put("usrId", usrId);
|
||||
|
||||
boardMapper.insertComment(param);
|
||||
boardMapper.updateCmmtCnt(param);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteComment(String corpNo, String untyBbsCd, Long untyBbsSno, Long cmmtSno) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> param = buildPostParam(corpNo, untyBbsCd, untyBbsSno);
|
||||
param.put("cmmtSno", cmmtSno);
|
||||
param.put("usrId", usrId);
|
||||
|
||||
Map<String, Object> info = boardMapper.getCommentInfo(param);
|
||||
if (info == null) throw new BizException("댓글이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
if (!usrId.equals(info.get("CMMT_CTUSR_ID"))) {
|
||||
throw new BizException("작성자만 삭제할 수 있습니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
boardMapper.deleteComment(param);
|
||||
boardMapper.updateCmmtCnt(param);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 내부 유틸
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
private Map<String, Object> buildPostParam(String corpNo, String untyBbsCd, Long untyBbsSno) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("untyBbsCd", untyBbsCd);
|
||||
p.put("untyBbsSno", untyBbsSno);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.company.gw.common.config;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MyBatis resultType="map" 은 DB 컬럼명을 그대로 Map 키로 반환합니다 (e.g. WORK_START_DT).
|
||||
* 프론트엔드는 camelCase(e.g. workStartDt)를 기대하므로, JSON 직렬화 시 변환합니다.
|
||||
* UPPER_CASE_SNAKE 패턴만 변환하고, 이미 camelCase인 키는 그대로 유지합니다.
|
||||
*/
|
||||
@Configuration
|
||||
public class JacksonConfig {
|
||||
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer mapKeyCamelCaseCustomizer() {
|
||||
return builder -> {
|
||||
SimpleModule module = new SimpleModule();
|
||||
module.addSerializer(Map.class, new MapCamelCaseSerializer());
|
||||
builder.modules(module);
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
static class MapCamelCaseSerializer extends JsonSerializer<Map> {
|
||||
@Override
|
||||
public void serialize(Map map, JsonGenerator gen, SerializerProvider serializers) throws IOException {
|
||||
gen.writeStartObject();
|
||||
for (Object obj : map.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) obj;
|
||||
String key = entry.getKey() != null ? convertKey(entry.getKey().toString()) : "null";
|
||||
gen.writeFieldName(key);
|
||||
serializers.defaultSerializeValue(entry.getValue(), gen);
|
||||
}
|
||||
gen.writeEndObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* UPPER_CASE_SNAKE 패턴인 경우에만 camelCase로 변환.
|
||||
* 이미 camelCase 이거나 소문자인 키는 그대로 반환.
|
||||
*/
|
||||
private String convertKey(String key) {
|
||||
// 모두 대문자+언더스코어 패턴인 경우만 변환
|
||||
if (!key.matches("[A-Z][A-Z0-9_]*")) return key;
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean nextUpper = false;
|
||||
for (int i = 0; i < key.length(); i++) {
|
||||
char c = key.charAt(i);
|
||||
if (c == '_') {
|
||||
nextUpper = true;
|
||||
} else if (nextUpper) {
|
||||
result.append(Character.toUpperCase(c));
|
||||
nextUpper = false;
|
||||
} else {
|
||||
result.append(Character.toLowerCase(c));
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.company.gw.common.config;
|
||||
|
||||
import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@MapperScan("com.company.gw.**.mapper")
|
||||
public class MyBatisConfig {
|
||||
|
||||
@Bean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
|
||||
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
|
||||
factoryBean.setDataSource(dataSource);
|
||||
factoryBean.setMapperLocations(
|
||||
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/**/*.xml")
|
||||
);
|
||||
|
||||
// databaseId 벤더 매핑
|
||||
// SQL Server → "mssql" (기본 구문은 databaseId 없거나 "mssql")
|
||||
// MySQL → "mariadb" (MariaDB JDBC 2.x가 MySQL로 리포트)
|
||||
// MariaDB → "mariadb" (MariaDB JDBC 3.x+)
|
||||
VendorDatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
|
||||
Properties vendorProps = new Properties();
|
||||
vendorProps.setProperty("SQL Server", "mssql");
|
||||
vendorProps.setProperty("MySQL", "mariadb");
|
||||
vendorProps.setProperty("MariaDB", "mariadb");
|
||||
databaseIdProvider.setProperties(vendorProps);
|
||||
factoryBean.setDatabaseIdProvider(databaseIdProvider);
|
||||
|
||||
// application.yml의 mybatis.configuration이 수동 Bean 생성 시 무시되므로 직접 설정
|
||||
org.apache.ibatis.session.Configuration mybatisConfig = new org.apache.ibatis.session.Configuration();
|
||||
mybatisConfig.setMapUnderscoreToCamelCase(true);
|
||||
mybatisConfig.setDefaultFetchSize(100);
|
||||
mybatisConfig.setDefaultStatementTimeout(30);
|
||||
factoryBean.setConfiguration(mybatisConfig);
|
||||
|
||||
return factoryBean.getObject();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
|
||||
return new SqlSessionTemplate(sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.company.gw.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, String> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(new StringRedisSerializer());
|
||||
return template;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
|
||||
try {
|
||||
// Redis 연결 가능 여부 확인
|
||||
connectionFactory.getConnection().ping();
|
||||
|
||||
RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig()
|
||||
.entryTtl(Duration.ofHours(1))
|
||||
.serializeKeysWith(RedisSerializationContext.SerializationPair
|
||||
.fromSerializer(new StringRedisSerializer()))
|
||||
.serializeValuesWith(RedisSerializationContext.SerializationPair
|
||||
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
|
||||
|
||||
Map<String, RedisCacheConfiguration> cacheConfigs = Map.of(
|
||||
"code", defaultConfig.entryTtl(Duration.ofHours(6)),
|
||||
"workCd", defaultConfig.entryTtl(Duration.ofHours(6))
|
||||
);
|
||||
|
||||
log.info("CacheManager: Redis 사용");
|
||||
return RedisCacheManager.builder(connectionFactory)
|
||||
.cacheDefaults(defaultConfig)
|
||||
.withInitialCacheConfigurations(cacheConfigs)
|
||||
.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warn("Redis 연결 실패 → In-Memory CacheManager 사용 ({})", e.getMessage());
|
||||
return new ConcurrentMapCacheManager("code", "workCd");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.company.gw.common.config;
|
||||
|
||||
import com.company.gw.common.filter.JwtAuthenticationFilter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityConfig {
|
||||
|
||||
private final JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
|
||||
.sessionManagement(session ->
|
||||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/auth/**").permitAll()
|
||||
.requestMatchers("/actuator/health").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.exceptionHandling(ex -> ex
|
||||
// 인증 안 된 요청 → 401 (프론트 interceptor가 refresh 시도)
|
||||
.authenticationEntryPoint((request, response, authException) -> {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getWriter().write("{\"message\":\"Unauthorized\"}");
|
||||
})
|
||||
// 인증은 됐지만 권한 없음 → 403
|
||||
.accessDeniedHandler((request, response, accessDeniedException) -> {
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
response.getWriter().write("{\"message\":\"Forbidden\"}");
|
||||
})
|
||||
)
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowedOriginPatterns(List.of("*"));
|
||||
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
config.setAllowedHeaders(List.of("*"));
|
||||
config.setAllowCredentials(true);
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/api/**", config);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package com.company.gw.common.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.AttachDto;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.service.AttachService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/attach")
|
||||
@RequiredArgsConstructor
|
||||
public class AttachController {
|
||||
|
||||
private final AttachService attachService;
|
||||
|
||||
/** 단일 파일 업로드 */
|
||||
@PostMapping("/upload")
|
||||
public ApiResponse<AttachDto> upload(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "atchNo", required = false) String atchNo,
|
||||
@RequestParam(value = "division", required = false) String division) {
|
||||
return ApiResponse.ok(attachService.uploadFile(file, atchNo, division));
|
||||
}
|
||||
|
||||
/** 다중 파일 업로드 */
|
||||
@PostMapping("/upload/multi")
|
||||
public ApiResponse<List<AttachDto>> uploadMulti(
|
||||
@RequestParam("files") List<MultipartFile> files,
|
||||
@RequestParam(value = "atchNo", required = false) String atchNo,
|
||||
@RequestParam(value = "division", required = false) String division) {
|
||||
return ApiResponse.ok(attachService.uploadFiles(files, atchNo, division));
|
||||
}
|
||||
|
||||
/** 에디터 이미지 업로드 */
|
||||
@PostMapping("/upload/image")
|
||||
public ApiResponse<Map<String, String>> uploadImage(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "division", required = false) String division) {
|
||||
return ApiResponse.ok(attachService.uploadEditorImage(file, division));
|
||||
}
|
||||
|
||||
/** 첨부번호로 파일 목록 조회 */
|
||||
@GetMapping("/list/{atchNo}")
|
||||
public ApiResponse<List<Map<String, Object>>> getFileList(@PathVariable String atchNo) {
|
||||
return ApiResponse.ok(attachService.getFileList(atchNo));
|
||||
}
|
||||
|
||||
/** 단일 파일 다운로드 */
|
||||
@GetMapping("/download/{atchfileNo}")
|
||||
public ResponseEntity<Resource> download(@PathVariable String atchfileNo) {
|
||||
Map<String, Object> info = attachService.getFileInfo(atchfileNo);
|
||||
File file = attachService.getPhysicalFile(atchfileNo);
|
||||
|
||||
String fileName = (String) info.get("ATCH_FILE_NM");
|
||||
String encodedName;
|
||||
try {
|
||||
encodedName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name())
|
||||
.replace("+", "%20");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
encodedName = fileName;
|
||||
}
|
||||
|
||||
String contentType = (String) info.getOrDefault("ATCH_TYPE_NM",
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename*=UTF-8''" + encodedName)
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.contentLength(file.length())
|
||||
.body(new FileSystemResource(file));
|
||||
}
|
||||
|
||||
/** 전체 파일 ZIP 다운로드 */
|
||||
@GetMapping("/download-all/{atchNo}")
|
||||
public ResponseEntity<byte[]> downloadAll(@PathVariable String atchNo) throws IOException {
|
||||
List<Map<String, Object>> fileList = attachService.getFileList(atchNo);
|
||||
if (fileList == null || fileList.isEmpty()) {
|
||||
throw new BizException("다운로드할 파일이 없습니다.", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos, StandardCharsets.UTF_8)) {
|
||||
for (Map<String, Object> info : fileList) {
|
||||
String atchfileNo = (String) info.get("ATCHFILE_NO");
|
||||
String fileName = (String) info.get("ATCH_FILE_NM");
|
||||
try {
|
||||
File physicalFile = attachService.getPhysicalFile(atchfileNo);
|
||||
zos.putNextEntry(new ZipEntry(fileName != null ? fileName : atchfileNo));
|
||||
try (FileInputStream fis = new FileInputStream(physicalFile)) {
|
||||
fis.transferTo(zos);
|
||||
}
|
||||
zos.closeEntry();
|
||||
} catch (Exception e) {
|
||||
// 개별 파일 오류 시 건너뜀
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String encodedName = URLEncoder.encode("첨부파일.zip", StandardCharsets.UTF_8)
|
||||
.replace("+", "%20");
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename*=UTF-8''" + encodedName)
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(baos.toByteArray());
|
||||
}
|
||||
|
||||
/** 파일 삭제 */
|
||||
@DeleteMapping("/{atchfileNo}")
|
||||
public ApiResponse<Void> delete(@PathVariable String atchfileNo) {
|
||||
attachService.deleteFile(atchfileNo, false);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.company.gw.common.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.dto.LoginRequestDto;
|
||||
import com.company.gw.common.dto.LoginResponseDto;
|
||||
import com.company.gw.common.dto.RefreshRequestDto;
|
||||
import com.company.gw.common.service.AuthService;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
@RequiredArgsConstructor
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
/**
|
||||
* 로그인
|
||||
* POST /api/auth/login
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<ApiResponse<LoginResponseDto>> login(
|
||||
@Valid @RequestBody LoginRequestDto req) {
|
||||
LoginResponseDto result = authService.login(req);
|
||||
return ResponseEntity.ok(ApiResponse.ok(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃
|
||||
* POST /api/auth/logout
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<ApiResponse<Void>> logout(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
authService.logout(userDetails.getUsername());
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Access Token 재발급
|
||||
* POST /api/auth/refresh
|
||||
*/
|
||||
@PostMapping("/refresh")
|
||||
public ResponseEntity<ApiResponse<String>> refresh(
|
||||
@Valid @RequestBody RefreshRequestDto req) {
|
||||
LoginResponseDto.UserInfo userInfo = authService.refreshToken(req.getRefreshToken());
|
||||
String roleCode = (userInfo.getRoles() != null && !userInfo.getRoles().isEmpty())
|
||||
? userInfo.getRoles().get(0) : "USER";
|
||||
String newAccessToken = jwtUtil.generateAccessToken(userInfo.getUsrId(), userInfo.getCorpNo(), roleCode);
|
||||
return ResponseEntity.ok(ApiResponse.ok(newAccessToken));
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자 정보
|
||||
* GET /api/auth/me
|
||||
*/
|
||||
@GetMapping("/me")
|
||||
public ResponseEntity<ApiResponse<String>> me(
|
||||
@AuthenticationPrincipal UserDetails userDetails) {
|
||||
return ResponseEntity.ok(ApiResponse.ok(userDetails.getUsername()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 변경
|
||||
* POST /api/auth/change-pw
|
||||
*/
|
||||
@PostMapping("/change-pw")
|
||||
public ResponseEntity<ApiResponse<Void>> changePassword(
|
||||
@AuthenticationPrincipal CurrentUser currentUser,
|
||||
@RequestBody Map<String, String> body) {
|
||||
authService.changePassword(
|
||||
currentUser.getUsrId(),
|
||||
body.get("oldPw"),
|
||||
body.get("newPw")
|
||||
);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.company.gw.common.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.service.CodeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/code")
|
||||
@RequiredArgsConstructor
|
||||
public class CodeController {
|
||||
|
||||
private final CodeService codeService;
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 공통코드 목록 조회
|
||||
* GET /api/code?commClCd=SX001&useYn=Y
|
||||
*/
|
||||
@GetMapping
|
||||
public ApiResponse<List<Map<String, Object>>> getCodeList(
|
||||
@RequestParam String commClCd,
|
||||
@RequestParam(defaultValue = "") String useYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(codeService.getCodeList(currentUser.getCorpNo(), commClCd, useYn));
|
||||
}
|
||||
|
||||
/**
|
||||
* 공통코드 전체 정보 조회 (PROP_CD 포함)
|
||||
*/
|
||||
@GetMapping("/full")
|
||||
public ApiResponse<List<Map<String, Object>>> getCodeListFull(
|
||||
@RequestParam String commClCd,
|
||||
@RequestParam(defaultValue = "") String useYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(codeService.getCodeListFull(currentUser.getCorpNo(), commClCd, useYn));
|
||||
}
|
||||
|
||||
/**
|
||||
* 직원 검색 (결재자 팝업 등)
|
||||
* GET /api/code/users?searchText=홍&apprOnly=Y
|
||||
*/
|
||||
@GetMapping("/users")
|
||||
public ApiResponse<List<Map<String, Object>>> searchUser(
|
||||
@RequestParam(defaultValue = "") String searchText,
|
||||
@RequestParam(defaultValue = "N") String apprOnly,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(codeService.searchUser(
|
||||
currentUser.getCorpNo(), searchText, "Y".equals(apprOnly)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 근무코드 목록 조회
|
||||
*/
|
||||
@GetMapping("/workcd")
|
||||
public ApiResponse<List<Map<String, Object>>> getWorkCdList(
|
||||
@RequestParam(defaultValue = "") String useYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(codeService.getWorkCdList(currentUser.getCorpNo(), useYn));
|
||||
}
|
||||
|
||||
/**
|
||||
* 캐시 초기화 (코드 변경 후 호출)
|
||||
*/
|
||||
@PostMapping("/cache/evict")
|
||||
public ApiResponse<Void> evictCache() {
|
||||
Objects.requireNonNull(cacheManager.getCache("code")).clear();
|
||||
Objects.requireNonNull(cacheManager.getCache("workCd")).clear();
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.company.gw.common.controller;
|
||||
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.ExcelUtil;
|
||||
import com.company.gw.tam.mapper.TamMapper;
|
||||
import com.company.gw.wtime.mapper.WtimeMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Excel 내보내기 공통 컨트롤러
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/excel")
|
||||
@RequiredArgsConstructor
|
||||
public class ExcelController {
|
||||
|
||||
private final WtimeMapper wtimeMapper;
|
||||
private final TamMapper tamMapper;
|
||||
|
||||
/** 근무시간 목록 엑셀 */
|
||||
@GetMapping("/wtime")
|
||||
public ResponseEntity<byte[]> wtimeExcel(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser cu) throws IOException {
|
||||
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
setDefault(params, "staYmd", "00000000");
|
||||
setDefault(params, "endYmd", "99999999");
|
||||
setDefault(params, "includeRetireYn", "N");
|
||||
setDefault(params, "includeWorkYn", "N");
|
||||
|
||||
List<Map<String, Object>> data = wtimeMapper.getWtimeList(params);
|
||||
|
||||
return ExcelUtil.toExcel("근무시간",
|
||||
new String[]{"날짜", "이름", "팀", "직위", "근무코드", "출근", "퇴근", "총근무(분)", "지각(분)", "OT(분)", "결근"},
|
||||
new String[]{"WORK_PLAN_YYMMDD", "USR_NM", "TEAM_CD", "DUTY_CD",
|
||||
"REAL_WORK_CD", "WORK_START_DT", "WORK_END_DT",
|
||||
"TOT_WORK_MIN", "LATE_MIN", "OT_WORK_MIN", "ABTI_YN"},
|
||||
data);
|
||||
}
|
||||
|
||||
/** 월별 근무통계 엑셀 */
|
||||
@GetMapping("/wstat")
|
||||
public ResponseEntity<byte[]> wstatExcel(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser cu) throws IOException {
|
||||
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
setDefault(params, "staYmd", "00000000");
|
||||
setDefault(params, "endYmd", "99999999");
|
||||
setDefault(params, "includeRetireYn", "N");
|
||||
|
||||
List<Map<String, Object>> data = wtimeMapper.getWstatList(params);
|
||||
|
||||
return ExcelUtil.toExcel("근무통계",
|
||||
new String[]{"이름", "팀", "직위", "연차", "근무일", "결근", "지각일", "조퇴일", "총근무(분)", "지각(분)", "OT(분)"},
|
||||
new String[]{"USR_NM", "TEAM_CD", "DUTY_CD", "YYVCT_CNT",
|
||||
"WORK_DCNT", "ABTI_DCNT", "LATE_DCNT", "SKIPOFF_DCNT",
|
||||
"TOT_WORK_MIN", "LATE_MIN", "OT_WORK_MIN"},
|
||||
data);
|
||||
}
|
||||
|
||||
/** 결재 신청 목록 엑셀 (TAM0020) */
|
||||
@GetMapping("/tam-apvreq")
|
||||
public ResponseEntity<byte[]> tamApvreqExcel(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser cu) throws IOException {
|
||||
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
params.put("usrId", cu.getUsrId());
|
||||
setDefault(params, "staYmd", "00000000");
|
||||
setDefault(params, "endYmd", "99999999");
|
||||
setDefault(params, "pageNo", 1);
|
||||
setDefault(params, "pageSize", 10000);
|
||||
|
||||
List<Map<String, Object>> data = tamMapper.getApvreqList(params);
|
||||
|
||||
return ExcelUtil.toExcel("결재신청목록",
|
||||
new String[]{"문서ID", "상태", "종류", "상신일", "완료일"},
|
||||
new String[]{"APRVL_DOC_ID", "APRVL_STUS_CD", "APRVL_KIND_CD", "OFFER_DT", "CMPL_DT"},
|
||||
data);
|
||||
}
|
||||
|
||||
/** 근태 현황 엑셀 (TAM0040) */
|
||||
@GetMapping("/tam-status")
|
||||
public ResponseEntity<byte[]> tamStatusExcel(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser cu) throws IOException {
|
||||
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
setDefault(params, "staYmd", "00000000");
|
||||
setDefault(params, "endYmd", "99999999");
|
||||
setDefault(params, "includeRetireYn", "N");
|
||||
|
||||
List<Map<String, Object>> data = tamMapper.getTamStatusList(params);
|
||||
|
||||
return ExcelUtil.toExcel("근태현황",
|
||||
new String[]{"이름", "팀", "직위", "연차", "결재건수"},
|
||||
new String[]{"USR_NM", "TEAM_CD", "DUTY_CD", "YYVCT_CNT", "APRVL_CNT"},
|
||||
data);
|
||||
}
|
||||
|
||||
private void setDefault(Map<String, Object> params, String key, Object defaultVal) {
|
||||
if (!params.containsKey(key) || params.get(key) == null) {
|
||||
params.put(key, defaultVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ApiResponse<T> {
|
||||
|
||||
private boolean success;
|
||||
private T data;
|
||||
private String message;
|
||||
private PaginationInfo pagination;
|
||||
|
||||
public static <T> ApiResponse<T> ok(T data) {
|
||||
return ApiResponse.<T>builder()
|
||||
.success(true)
|
||||
.data(data)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> ok(T data, PaginationInfo pagination) {
|
||||
return ApiResponse.<T>builder()
|
||||
.success(true)
|
||||
.data(data)
|
||||
.pagination(pagination)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> fail(String message) {
|
||||
return ApiResponse.<T>builder()
|
||||
.success(false)
|
||||
.message(message)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public static class PaginationInfo {
|
||||
private int page;
|
||||
private int size;
|
||||
private long total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class AttachDto {
|
||||
private String atchfileNo;
|
||||
private String atchNo;
|
||||
private String atchFilePathNm;
|
||||
private String atchFileNm;
|
||||
private String atchTypeNm;
|
||||
private Long atchFileMg;
|
||||
private String tblColNm;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class ControllerRoleDto {
|
||||
private String controller;
|
||||
private String role;
|
||||
private String funcAuthCn;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* 기존 Grails의 SS_CORP_NO, SS_USER_ID, ROLE_CD를 대체하는 현재 로그인 사용자 정보.
|
||||
* JWT 클레임에서 추출하여 컨트롤러/서비스에서 사용.
|
||||
* Principal 구현 → auth.getName()이 usrId를 반환하도록 보장.
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
public class CurrentUser implements Principal {
|
||||
private final String usrId;
|
||||
private final String corpNo;
|
||||
private final String roleCode;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return usrId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class LoginRequestDto {
|
||||
|
||||
@NotBlank(message = "로그인 아이디를 입력하세요.")
|
||||
private String loginId;
|
||||
|
||||
@NotBlank(message = "비밀번호를 입력하세요.")
|
||||
private String loginPw;
|
||||
|
||||
@NotBlank(message = "권한을 선택하세요.")
|
||||
private String menuAuthCd;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class LoginResponseDto {
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
private UserInfo userInfo;
|
||||
private List<MenuDto> menuList;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public static class UserInfo {
|
||||
private String usrId;
|
||||
private String usrNm;
|
||||
private String loginId;
|
||||
private String corpNo;
|
||||
private String dutyCd;
|
||||
private String roleCode; // 선택한 MENU_AUTH_CD
|
||||
private List<String> roles; // 보유 전체 role 목록
|
||||
}
|
||||
}
|
||||
18
backend/src/main/java/com/company/gw/common/dto/MenuDto.java
Normal file
18
backend/src/main/java/com/company/gw/common/dto/MenuDto.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class MenuDto {
|
||||
private String menuNo;
|
||||
private String upperMenuNo;
|
||||
private String menuNm;
|
||||
private String url;
|
||||
private String rm;
|
||||
private String menuProp;
|
||||
private Integer menuOrdr;
|
||||
private String menuUseYn;
|
||||
private Integer lvl;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class RefreshRequestDto {
|
||||
|
||||
@NotBlank(message = "refreshToken이 필요합니다.")
|
||||
private String refreshToken;
|
||||
}
|
||||
19
backend/src/main/java/com/company/gw/common/dto/UserDto.java
Normal file
19
backend/src/main/java/com/company/gw/common/dto/UserDto.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.company.gw.common.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class UserDto {
|
||||
private String corpNo;
|
||||
private String usrId;
|
||||
private String usrNm;
|
||||
private String loginId;
|
||||
@JsonIgnore
|
||||
private String pw;
|
||||
private String dutyCd;
|
||||
@JsonIgnore
|
||||
private String retirementDate;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.company.gw.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@Getter
|
||||
public class BizException extends RuntimeException {
|
||||
|
||||
private final HttpStatus status;
|
||||
|
||||
public BizException(String message) {
|
||||
super(message);
|
||||
this.status = HttpStatus.BAD_REQUEST;
|
||||
}
|
||||
|
||||
public BizException(String message, HttpStatus status) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.company.gw.common.exception;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BizException.class)
|
||||
public ResponseEntity<ApiResponse<Void>> handleBizException(BizException e) {
|
||||
log.warn("BizException: {}", e.getMessage());
|
||||
return ResponseEntity
|
||||
.status(e.getStatus())
|
||||
.body(ApiResponse.fail(e.getMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
|
||||
public ResponseEntity<ApiResponse<Void>> handleValidationException(BindException e) {
|
||||
String message = e.getBindingResult().getFieldErrors().stream()
|
||||
.map(fe -> fe.getField() + ": " + fe.getDefaultMessage())
|
||||
.findFirst()
|
||||
.orElse("입력값이 올바르지 않습니다.");
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.BAD_REQUEST)
|
||||
.body(ApiResponse.fail(message));
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<ApiResponse<Void>> handleException(Exception e) {
|
||||
log.error("Unhandled exception", e);
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(ApiResponse.fail("서버 오류가 발생했습니다."));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.company.gw.common.filter;
|
||||
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
String token = resolveToken(request);
|
||||
|
||||
if (StringUtils.hasText(token) && jwtUtil.isValid(token)) {
|
||||
try {
|
||||
String usrId = jwtUtil.getUserId(token);
|
||||
String corpNo = jwtUtil.getCorpNo(token);
|
||||
String roleCode = jwtUtil.getRoleCode(token);
|
||||
|
||||
if (StringUtils.hasText(usrId)) {
|
||||
CurrentUser currentUser = CurrentUser.builder()
|
||||
.usrId(usrId)
|
||||
.corpNo(corpNo)
|
||||
.roleCode(roleCode)
|
||||
.build();
|
||||
|
||||
var authorities = StringUtils.hasText(roleCode)
|
||||
? List.of(new SimpleGrantedAuthority("ROLE_" + roleCode))
|
||||
: List.<SimpleGrantedAuthority>of();
|
||||
|
||||
var authentication = new UsernamePasswordAuthenticationToken(
|
||||
currentUser, null, authorities);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("JWT 인증 실패 - 인증 없이 계속 진행: {}", e.getMessage());
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
||||
return bearerToken.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface AttachMapper {
|
||||
|
||||
Map<String, Object> getFileInfo(String atchfileNo);
|
||||
|
||||
List<Map<String, Object>> getFileInfoListByAtchNo(String atchNo);
|
||||
|
||||
void insertFileInfo(Map<String, Object> param);
|
||||
|
||||
void deleteFileInfo(String atchfileNo);
|
||||
|
||||
void updateTblColNmByAtchNo(Map<String, Object> param);
|
||||
|
||||
void updateTblColNmByAtchfileNo(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> getNeedDeleteFileList();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface CodeMapper {
|
||||
|
||||
List<Map<String, Object>> getCodeList(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> getCodeListFull(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> searchUser(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> getWorkCdList(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@Mapper
|
||||
public interface CommonMapper {
|
||||
|
||||
void increaseSequence(@Param("sequenceNm") String sequenceNm);
|
||||
|
||||
Long getSequenceVal(@Param("sequenceNm") String sequenceNm);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import com.company.gw.common.dto.ControllerRoleDto;
|
||||
import com.company.gw.common.dto.MenuDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface MenuMapper {
|
||||
|
||||
List<MenuDto> getMenuList(@Param("corpNo") String corpNo,
|
||||
@Param("menuAuthCd") String menuAuthCd);
|
||||
|
||||
List<ControllerRoleDto> getControllerRoleList(@Param("corpNo") String corpNo);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SecurityMapper {
|
||||
|
||||
List<String> getUserRoleList(@Param("corpNo") String corpNo,
|
||||
@Param("usrId") String usrId);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.company.gw.common.mapper;
|
||||
|
||||
import com.company.gw.common.dto.UserDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper {
|
||||
|
||||
UserDto getUserInfo(@Param("usrId") String usrId);
|
||||
|
||||
UserDto getUserInfoWithPwd(@Param("loginId") String loginId);
|
||||
|
||||
int updatePassword(@Param("usrId") String usrId, @Param("newPw") String newPw);
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package com.company.gw.common.service;
|
||||
|
||||
import com.company.gw.common.dto.AttachDto;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.mapper.AttachMapper;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AttachService {
|
||||
|
||||
private static final List<String> NOT_ALLOWED_EXT =
|
||||
Arrays.asList("php", "jsp", "asp", "gsp", "sh", "exe", "bat");
|
||||
|
||||
private static final List<String> IMAGE_EXT =
|
||||
Arrays.asList("jpg", "jpeg", "png", "gif", "tif", "tiff", "bmp", "webp");
|
||||
|
||||
private static final long MAX_FILE_SIZE = 30L * 1024 * 1024; // 30MB
|
||||
|
||||
private final AttachMapper attachMapper;
|
||||
|
||||
@Value("${file.upload-path}")
|
||||
private String uploadPath;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 업로드
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public AttachDto uploadFile(MultipartFile file, String atchNo, String division) {
|
||||
validateFile(file);
|
||||
|
||||
if (!org.springframework.util.StringUtils.hasText(atchNo)) {
|
||||
atchNo = UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
String ext = FilenameUtils.getExtension(file.getOriginalFilename()).toLowerCase();
|
||||
String atchfileNo = UUID.randomUUID().toString().replace("-", "");
|
||||
String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
String relativePath = (division != null ? division : "common") + "/" + today + "/" + atchfileNo + "." + ext;
|
||||
|
||||
File dest = new File(uploadPath, relativePath);
|
||||
dest.getParentFile().mkdirs();
|
||||
try {
|
||||
file.transferTo(dest);
|
||||
} catch (IOException e) {
|
||||
throw new BizException("파일 저장 중 오류가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("atchfileNo", atchfileNo);
|
||||
param.put("atchNo", atchNo);
|
||||
param.put("atchFilePathNm", relativePath);
|
||||
param.put("atchFileNm", file.getOriginalFilename());
|
||||
param.put("atchTypeNm", file.getContentType());
|
||||
param.put("atchFileMg", file.getSize());
|
||||
param.put("tblColNm", null);
|
||||
param.put("rgstrId", SecurityUtil.getUsrId());
|
||||
|
||||
attachMapper.insertFileInfo(param);
|
||||
|
||||
return AttachDto.builder()
|
||||
.atchfileNo(atchfileNo)
|
||||
.atchNo(atchNo)
|
||||
.atchFilePathNm(relativePath)
|
||||
.atchFileNm(file.getOriginalFilename())
|
||||
.atchTypeNm(file.getContentType())
|
||||
.atchFileMg(file.getSize())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<AttachDto> uploadFiles(List<MultipartFile> files, String atchNo, String division) {
|
||||
if (!org.springframework.util.StringUtils.hasText(atchNo)) {
|
||||
atchNo = UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
List<AttachDto> result = new ArrayList<>();
|
||||
for (MultipartFile file : files) {
|
||||
if (file != null && !file.isEmpty()) {
|
||||
result.add(uploadFile(file, atchNo, division));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 이미지 에디터용 업로드 (DB 저장 없이 파일만 저장)
|
||||
public Map<String, String> uploadEditorImage(MultipartFile file, String division) {
|
||||
String ext = FilenameUtils.getExtension(
|
||||
Objects.requireNonNull(file.getOriginalFilename())).toLowerCase();
|
||||
if (!IMAGE_EXT.contains(ext)) {
|
||||
throw new BizException("이미지 파일만 업로드할 수 있습니다.");
|
||||
}
|
||||
if (file.getSize() > MAX_FILE_SIZE) {
|
||||
throw new BizException("파일 크기가 초과되었습니다. (최대 30MB)");
|
||||
}
|
||||
|
||||
String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
String fileId = UUID.randomUUID().toString().replace("-", "");
|
||||
String relativePath = (division != null ? division : "editor") + "/" + today + "/" + fileId + "." + ext;
|
||||
|
||||
File dest = new File(uploadPath + "/images", relativePath);
|
||||
dest.getParentFile().mkdirs();
|
||||
try {
|
||||
file.transferTo(dest);
|
||||
} catch (IOException e) {
|
||||
throw new BizException("이미지 저장 중 오류가 발생했습니다.", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("url", "/api/attach/image/" + relativePath.replace("/", "_") + "." + ext);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 조회
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
public Map<String, Object> getFileInfo(String atchfileNo) {
|
||||
Map<String, Object> info = attachMapper.getFileInfo(atchfileNo);
|
||||
if (info == null) {
|
||||
throw new BizException("파일 정보가 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getFileList(String atchNo) {
|
||||
return attachMapper.getFileInfoListByAtchNo(atchNo);
|
||||
}
|
||||
|
||||
public File getPhysicalFile(String atchfileNo) {
|
||||
Map<String, Object> info = getFileInfo(atchfileNo);
|
||||
File file = new File(uploadPath, (String) info.get("ATCH_FILE_PATH_NM"));
|
||||
if (!file.exists()) {
|
||||
throw new BizException("파일이 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 삭제
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void deleteFile(String atchfileNo, boolean forceDelete) {
|
||||
Map<String, Object> info = getFileInfo(atchfileNo);
|
||||
if (!forceDelete) {
|
||||
String rgstrId = (String) info.get("RGSTR_ID");
|
||||
if (!SecurityUtil.getUsrId().equals(rgstrId)) {
|
||||
throw new BizException("등록자만 삭제할 수 있습니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
}
|
||||
attachMapper.deleteFileInfo(atchfileNo);
|
||||
// 물리 파일 삭제 (DB 성공 후)
|
||||
new File(uploadPath, (String) info.get("ATCH_FILE_PATH_NM")).delete();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteFilesByAtchNo(String atchNo, boolean forceDelete) {
|
||||
List<Map<String, Object>> list = attachMapper.getFileInfoListByAtchNo(atchNo);
|
||||
for (Map<String, Object> info : list) {
|
||||
deleteFile((String) info.get("ATCHFILE_NO"), forceDelete);
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TBL_COL_NM 확정 처리 (게시판/결재 저장 완료 후 호출)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void confirmAtchNo(String atchNo, String tblColNm) {
|
||||
if (!org.springframework.util.StringUtils.hasText(atchNo)) return;
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("atchNo", atchNo);
|
||||
param.put("tblColNm", tblColNm);
|
||||
attachMapper.updateTblColNmByAtchNo(param);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 미확정 파일 정기 삭제 (6시간 이상 TBL_COL_NM 없는 파일)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Scheduled(cron = "0 0 3 * * *") // 매일 새벽 3시
|
||||
@Transactional
|
||||
public void cleanUpUnnecessaryFiles() {
|
||||
List<Map<String, Object>> list = attachMapper.getNeedDeleteFileList();
|
||||
for (Map<String, Object> item : list) {
|
||||
try {
|
||||
attachMapper.deleteFileInfo((String) item.get("ATCHFILE_NO"));
|
||||
new File(uploadPath, (String) item.get("ATCH_FILE_PATH_NM")).delete();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 검증
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
private void validateFile(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new BizException("파일이 없습니다.");
|
||||
}
|
||||
String ext = FilenameUtils.getExtension(
|
||||
Objects.requireNonNull(file.getOriginalFilename())).toLowerCase();
|
||||
if (NOT_ALLOWED_EXT.contains(ext)) {
|
||||
throw new BizException("업로드할 수 없는 확장자입니다. (" + ext + ")");
|
||||
}
|
||||
if (file.getSize() > MAX_FILE_SIZE) {
|
||||
throw new BizException("파일 크기가 초과되었습니다. (최대 30MB)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.company.gw.common.service;
|
||||
|
||||
import com.company.gw.common.dto.*;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.mapper.MenuMapper;
|
||||
import com.company.gw.common.mapper.SecurityMapper;
|
||||
import com.company.gw.common.mapper.UserMapper;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import com.company.gw.common.util.PasswordUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AuthService {
|
||||
|
||||
private static final String ROLE_ADMIN = "BIDS_0001";
|
||||
private static final String ROLE_FEDEX = "FEDE";
|
||||
private static final String ROLE_USER = "USER";
|
||||
private static final String REFRESH_TOKEN_PREFIX = "refresh:";
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final SecurityMapper securityMapper;
|
||||
private final MenuMapper menuMapper;
|
||||
private final JwtUtil jwtUtil;
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
/**
|
||||
* 로그인
|
||||
* 기존 IndexController.do_login() 로직과 동일
|
||||
*/
|
||||
public LoginResponseDto login(LoginRequestDto req) {
|
||||
|
||||
// 1. 사용자 조회 (PW 포함)
|
||||
UserDto user = userMapper.getUserInfoWithPwd(req.getLoginId());
|
||||
if (user == null) {
|
||||
throw new BizException("로그인 아이디 또는 비밀번호를 확인하세요.");
|
||||
}
|
||||
|
||||
// 2. 비밀번호 검증 (SHA-256 + Base64)
|
||||
if (!PasswordUtil.matches(req.getLoginPw(), user.getPw())) {
|
||||
throw new BizException("로그인 아이디 또는 비밀번호를 확인하세요.");
|
||||
}
|
||||
|
||||
// 3. 퇴직자 체크
|
||||
if (StringUtils.hasText(user.getRetirementDate())) {
|
||||
throw new BizException("로그인 아이디 또는 비밀번호를 확인하세요.");
|
||||
}
|
||||
|
||||
// 4. 보유 롤 조회
|
||||
List<String> roles = securityMapper.getUserRoleList(user.getCorpNo(), user.getUsrId());
|
||||
|
||||
// 5. 선택한 MENU_AUTH_CD 보유 여부 검증
|
||||
// 구 시스템(SecurityService.groovy) 로직과 동일:
|
||||
// - FEDE 사용자이거나, USER 이외의 권한을 선택한 경우에만 DB 체크
|
||||
// - USER 권한은 FEDE 사용자가 아니면 누구나 사용 가능 (기본값)
|
||||
boolean isFedexUser = roles.contains(ROLE_FEDEX);
|
||||
String menuAuthCd = req.getMenuAuthCd();
|
||||
if (isFedexUser || !ROLE_USER.equals(menuAuthCd)) {
|
||||
if (!roles.contains(menuAuthCd)) {
|
||||
throw new BizException("해당 메뉴 권한이 없습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
// 6. JWT 발급 (usrId + corpNo + roleCode 포함)
|
||||
String accessToken = jwtUtil.generateAccessToken(user.getUsrId(), user.getCorpNo(), menuAuthCd);
|
||||
String refreshToken = jwtUtil.generateRefreshToken(user.getUsrId());
|
||||
|
||||
// 7. Redis에 Refresh Token 저장 (7일) — Redis 미사용 환경에서는 건너뜀
|
||||
try {
|
||||
redisTemplate.opsForValue().set(
|
||||
REFRESH_TOKEN_PREFIX + user.getUsrId(),
|
||||
refreshToken,
|
||||
7, TimeUnit.DAYS
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.warn("Redis 미사용 환경: Refresh Token 저장 건너뜀 ({})", e.getMessage());
|
||||
}
|
||||
|
||||
// 8. 메뉴 조회 - 선택한 역할 코드로 SX_CO0090 기반 필터링
|
||||
List<MenuDto> menuList = menuMapper.getMenuList(user.getCorpNo(), menuAuthCd);
|
||||
|
||||
return LoginResponseDto.builder()
|
||||
.accessToken(accessToken)
|
||||
.refreshToken(refreshToken)
|
||||
.userInfo(LoginResponseDto.UserInfo.builder()
|
||||
.usrId(user.getUsrId())
|
||||
.usrNm(user.getUsrNm())
|
||||
.loginId(user.getLoginId())
|
||||
.corpNo(user.getCorpNo())
|
||||
.dutyCd(user.getDutyCd())
|
||||
.roleCode(menuAuthCd)
|
||||
.roles(roles)
|
||||
.build())
|
||||
.menuList(menuList)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Access Token 재발급 (Refresh Token 검증)
|
||||
*/
|
||||
public LoginResponseDto.UserInfo refreshToken(String refreshToken) {
|
||||
if (!jwtUtil.isValid(refreshToken)) {
|
||||
throw new BizException("유효하지 않은 토큰입니다.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
String usrId = jwtUtil.getUserId(refreshToken);
|
||||
try {
|
||||
String stored = redisTemplate.opsForValue().get(REFRESH_TOKEN_PREFIX + usrId);
|
||||
if (stored != null && !refreshToken.equals(stored)) {
|
||||
throw new BizException("만료된 토큰입니다. 다시 로그인하세요.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
// stored == null: Redis 미사용 환경 → JWT 유효성만으로 통과
|
||||
} catch (BizException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.warn("Redis 미사용 환경: Refresh Token 검증 건너뜀 ({})", e.getMessage());
|
||||
}
|
||||
|
||||
// 사용자 정보 재조회
|
||||
UserDto user = userMapper.getUserInfo(usrId);
|
||||
if (user == null) {
|
||||
throw new BizException("사용자 정보를 찾을 수 없습니다.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
List<String> roles = securityMapper.getUserRoleList(user.getCorpNo(), usrId);
|
||||
|
||||
return LoginResponseDto.UserInfo.builder()
|
||||
.usrId(user.getUsrId())
|
||||
.usrNm(user.getUsrNm())
|
||||
.loginId(user.getLoginId())
|
||||
.corpNo(user.getCorpNo())
|
||||
.dutyCd(user.getDutyCd())
|
||||
.roles(roles)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃 - Redis에서 Refresh Token 삭제
|
||||
*/
|
||||
public void logout(String usrId) {
|
||||
try {
|
||||
redisTemplate.delete(REFRESH_TOKEN_PREFIX + usrId);
|
||||
} catch (Exception e) {
|
||||
log.warn("Redis 미사용 환경: 로그아웃 토큰 삭제 건너뜀 ({})", e.getMessage());
|
||||
}
|
||||
log.debug("로그아웃 처리 완료: {}", usrId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 변경
|
||||
*/
|
||||
@org.springframework.transaction.annotation.Transactional
|
||||
public void changePassword(String usrId, String oldPw, String newPw) {
|
||||
UserDto user = userMapper.getUserInfo(usrId);
|
||||
if (user == null) {
|
||||
throw new BizException("사용자 정보를 찾을 수 없습니다.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
// 현재 비밀번호 확인 (loginId로 재조회하여 PW 포함)
|
||||
UserDto userWithPw = userMapper.getUserInfoWithPwd(user.getLoginId());
|
||||
if (userWithPw == null || !PasswordUtil.matches(oldPw, userWithPw.getPw())) {
|
||||
throw new BizException("현재 비밀번호가 올바르지 않습니다.");
|
||||
}
|
||||
if (!StringUtils.hasText(newPw) || newPw.length() < 4) {
|
||||
throw new BizException("새 비밀번호는 4자 이상이어야 합니다.");
|
||||
}
|
||||
userMapper.updatePassword(usrId, PasswordUtil.encode(newPw));
|
||||
try {
|
||||
redisTemplate.delete(REFRESH_TOKEN_PREFIX + usrId);
|
||||
} catch (Exception e) {
|
||||
log.warn("Redis 미사용 환경: 비밀번호 변경 후 토큰 삭제 건너뜀 ({})", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 여부
|
||||
*/
|
||||
public boolean isAdmin(List<String> roles) {
|
||||
return roles.contains(ROLE_ADMIN);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.company.gw.common.service;
|
||||
|
||||
import com.company.gw.common.mapper.CodeMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 공통코드 조회 서비스
|
||||
* - @Cacheable("code") 로 Redis 캐시 적용 (기본 TTL은 RedisConfig에서 설정)
|
||||
* - 공통코드 변경 시 /api/code/cache/evict 호출로 캐시 초기화
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CodeService {
|
||||
|
||||
private final CodeMapper codeMapper;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 공통코드 목록 (드롭다운용)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Cacheable(value = "code", key = "#corpNo + ':' + #commClCd + ':' + #useYn")
|
||||
public List<Map<String, Object>> getCodeList(String corpNo, String commClCd, String useYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("commClCd", commClCd);
|
||||
p.put("useYn", useYn);
|
||||
return codeMapper.getCodeList(p);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getCodeListFull(String corpNo, String commClCd, String useYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("commClCd", commClCd);
|
||||
p.put("useYn", useYn);
|
||||
return codeMapper.getCodeListFull(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 직원 검색 (결재자 선택 팝업 등)
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> searchUser(String corpNo, String searchText, boolean apprOnly) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("searchText", searchText);
|
||||
p.put("apprOnly", apprOnly ? "Y" : "N");
|
||||
return codeMapper.searchUser(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 근무코드 목록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Cacheable(value = "workCd", key = "#corpNo + ':' + #useYn")
|
||||
public List<Map<String, Object>> getWorkCdList(String corpNo, String useYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("useYn", useYn);
|
||||
return codeMapper.getWorkCdList(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.company.gw.common.service;
|
||||
|
||||
import com.company.gw.common.dto.UserDto;
|
||||
import com.company.gw.common.mapper.SecurityMapper;
|
||||
import com.company.gw.common.mapper.UserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final SecurityMapper securityMapper;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String usrId) throws UsernameNotFoundException {
|
||||
UserDto user = userMapper.getUserInfo(usrId);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("사용자를 찾을 수 없습니다: " + usrId);
|
||||
}
|
||||
|
||||
List<String> roles = securityMapper.getUserRoleList(user.getCorpNo(), usrId);
|
||||
List<SimpleGrantedAuthority> authorities = roles.stream()
|
||||
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
|
||||
.toList();
|
||||
|
||||
return User.builder()
|
||||
.username(usrId)
|
||||
.password("") // JWT 방식이므로 password 불필요
|
||||
.authorities(authorities)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.company.gw.common.service;
|
||||
|
||||
import com.company.gw.common.mapper.CommonMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 기존 CommonService.getNextSeqString() 대체.
|
||||
* SX_CO0060 테이블의 MERGE 기반 시퀀스.
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SequenceService {
|
||||
|
||||
private final CommonMapper commonMapper;
|
||||
|
||||
@Transactional
|
||||
public String getNextSeqString(String sequenceNm, int padLength) {
|
||||
commonMapper.increaseSequence(sequenceNm);
|
||||
Long val = commonMapper.getSequenceVal(sequenceNm);
|
||||
return String.format("%0" + padLength + "d", val);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.company.gw.common.util;
|
||||
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Excel 내보내기 유틸리티
|
||||
*/
|
||||
public class ExcelUtil {
|
||||
|
||||
private ExcelUtil() {}
|
||||
|
||||
/**
|
||||
* Map 리스트를 Excel로 변환하여 ResponseEntity 반환
|
||||
* @param fileName 다운로드 파일명 (확장자 없이)
|
||||
* @param headers 컬럼 헤더 배열
|
||||
* @param keys Map에서 읽을 키 배열 (headers와 1:1 대응)
|
||||
* @param data 데이터 리스트
|
||||
*/
|
||||
public static ResponseEntity<byte[]> toExcel(String fileName,
|
||||
String[] headers,
|
||||
String[] keys,
|
||||
List<Map<String, Object>> data) throws IOException {
|
||||
try (Workbook wb = new XSSFWorkbook()) {
|
||||
Sheet sheet = wb.createSheet("Sheet1");
|
||||
|
||||
// 헤더 스타일
|
||||
CellStyle headerStyle = wb.createCellStyle();
|
||||
Font headerFont = wb.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
headerStyle.setBorderBottom(BorderStyle.THIN);
|
||||
|
||||
// 헤더 행
|
||||
Row headerRow = sheet.createRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
cell.setCellStyle(headerStyle);
|
||||
sheet.setColumnWidth(i, 4000);
|
||||
}
|
||||
|
||||
// 데이터 행
|
||||
int rowIdx = 1;
|
||||
for (Map<String, Object> row : data) {
|
||||
Row dataRow = sheet.createRow(rowIdx++);
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
Cell cell = dataRow.createCell(i);
|
||||
Object val = row.get(keys[i]);
|
||||
if (val == null) {
|
||||
cell.setCellValue("");
|
||||
} else if (val instanceof Number) {
|
||||
cell.setCellValue(((Number) val).doubleValue());
|
||||
} else {
|
||||
cell.setCellValue(val.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
wb.write(baos);
|
||||
|
||||
String encodedName = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8)
|
||||
.replace("+", "%20");
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename*=UTF-8''" + encodedName)
|
||||
.contentType(MediaType.parseMediaType(
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(baos.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.company.gw.common.util;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JwtUtil {
|
||||
|
||||
private static final String CLAIM_CORP_NO = "corpNo";
|
||||
private static final String CLAIM_ROLE_CODE = "roleCode";
|
||||
|
||||
private final SecretKey secretKey;
|
||||
private final long accessTokenExpiry;
|
||||
private final long refreshTokenExpiry;
|
||||
|
||||
public JwtUtil(
|
||||
@Value("${jwt.secret}") String secret,
|
||||
@Value("${jwt.access-token-expiry}") long accessTokenExpiry,
|
||||
@Value("${jwt.refresh-token-expiry}") long refreshTokenExpiry) {
|
||||
this.secretKey = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||
this.accessTokenExpiry = accessTokenExpiry;
|
||||
this.refreshTokenExpiry = refreshTokenExpiry;
|
||||
}
|
||||
|
||||
public String generateAccessToken(String usrId, String corpNo, String roleCode) {
|
||||
return Jwts.builder()
|
||||
.subject(usrId)
|
||||
.claim(CLAIM_CORP_NO, corpNo)
|
||||
.claim(CLAIM_ROLE_CODE, roleCode)
|
||||
.issuedAt(new Date())
|
||||
.expiration(new Date(System.currentTimeMillis() + accessTokenExpiry))
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public String generateRefreshToken(String usrId) {
|
||||
return Jwts.builder()
|
||||
.subject(usrId)
|
||||
.issuedAt(new Date())
|
||||
.expiration(new Date(System.currentTimeMillis() + refreshTokenExpiry))
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public String getUserId(String token) {
|
||||
return getClaims(token).getSubject();
|
||||
}
|
||||
|
||||
public String getCorpNo(String token) {
|
||||
return (String) getClaims(token).get(CLAIM_CORP_NO);
|
||||
}
|
||||
|
||||
public String getRoleCode(String token) {
|
||||
return (String) getClaims(token).get(CLAIM_ROLE_CODE);
|
||||
}
|
||||
|
||||
public boolean isValid(String token) {
|
||||
try {
|
||||
getClaims(token);
|
||||
return true;
|
||||
} catch (JwtException | IllegalArgumentException e) {
|
||||
log.debug("Invalid JWT token: {}", e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Claims getClaims(String token) {
|
||||
return Jwts.parser()
|
||||
.verifyWith(secretKey)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.company.gw.common.util;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 기존 Grails EncryptUtil.get_enc_password() 와 동일한 방식
|
||||
* SHA-256 → Base64 인코딩
|
||||
* 기존 Oracle DB의 PW 컬럼 값과 호환 필수
|
||||
*/
|
||||
public class PasswordUtil {
|
||||
|
||||
private PasswordUtil() {}
|
||||
|
||||
public static String encode(String rawPassword) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = digest.digest(rawPassword.getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.getEncoder().encodeToString(hash);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("SHA-256 알고리즘을 찾을 수 없습니다.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean matches(String rawPassword, String encodedPassword) {
|
||||
return encode(rawPassword).equals(encodedPassword);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.company.gw.common.util;
|
||||
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
/**
|
||||
* JWT에서 현재 사용자 정보를 추출하는 유틸.
|
||||
* 기존 CommonUtil.getLoginCorpNo(), getLoginUserID() 역할.
|
||||
*/
|
||||
public class SecurityUtil {
|
||||
|
||||
private SecurityUtil() {}
|
||||
|
||||
public static CurrentUser getCurrentUser(JwtUtil jwtUtil) {
|
||||
String token = resolveToken();
|
||||
if (!StringUtils.hasText(token) || !jwtUtil.isValid(token)) {
|
||||
throw new BizException("인증 정보가 없습니다.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
return CurrentUser.builder()
|
||||
.usrId(jwtUtil.getUserId(token))
|
||||
.corpNo(jwtUtil.getCorpNo(token))
|
||||
.roleCode(jwtUtil.getRoleCode(token))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static String getUsrId() {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth == null || !auth.isAuthenticated()) {
|
||||
throw new BizException("인증 정보가 없습니다.", HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
return auth.getName();
|
||||
}
|
||||
|
||||
private static String resolveToken() {
|
||||
ServletRequestAttributes attrs =
|
||||
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs == null) return null;
|
||||
HttpServletRequest request = attrs.getRequest();
|
||||
String bearer = request.getHeader("Authorization");
|
||||
if (StringUtils.hasText(bearer) && bearer.startsWith("Bearer ")) {
|
||||
return bearer.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.company.gw.envset.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.envset.dto.CodeDto;
|
||||
import com.company.gw.envset.dto.CodeIndexDto;
|
||||
import com.company.gw.envset.service.CodeManageService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 환경설정 > 공통코드 관리 (Envset0020/0030)
|
||||
* GET /api/envset/codes 코드인덱스 목록
|
||||
* POST /api/envset/codes 코드인덱스 배치 저장
|
||||
* GET /api/envset/codes/{commClCd} 코드 목록
|
||||
* POST /api/envset/codes/{commClCd} 코드 배치 저장
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/envset/codes")
|
||||
@RequiredArgsConstructor
|
||||
public class CodeManageController {
|
||||
|
||||
private final CodeManageService codeManageService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<ApiResponse<List<CodeIndexDto>>> getCdidxList(
|
||||
@RequestParam(required = false) String searchText) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(codeManageService.getCdidxList(cu, searchText)));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<ApiResponse<Void>> saveCdidxList(@RequestBody List<CodeIndexDto> list) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
codeManageService.saveCdidxList(cu, list);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@GetMapping("/{commClCd}")
|
||||
public ResponseEntity<ApiResponse<List<CodeDto>>> getCodeList(
|
||||
@PathVariable String commClCd,
|
||||
@RequestParam(required = false) String searchText) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(
|
||||
codeManageService.getCodeList(cu, commClCd, searchText)));
|
||||
}
|
||||
|
||||
@PostMapping("/{commClCd}")
|
||||
public ResponseEntity<ApiResponse<Void>> saveCodeList(
|
||||
@PathVariable String commClCd,
|
||||
@RequestBody List<CodeDto> list) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
codeManageService.saveCodeList(cu, commClCd, list);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.company.gw.envset.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.envset.dto.AuthMenuDto;
|
||||
import com.company.gw.envset.dto.MenuManageDto;
|
||||
import com.company.gw.envset.dto.UserAuthDto;
|
||||
import com.company.gw.envset.service.MenuManageService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 환경설정 > 메뉴관리 / 사용자권한 (Envset0050)
|
||||
*
|
||||
* GET /api/envset/menus 메뉴 목록
|
||||
* POST /api/envset/menus 메뉴 배치 저장
|
||||
* GET /api/envset/menus/auth?menuAuthCd= 권한별 메뉴 목록
|
||||
* POST /api/envset/menus/auth?menuAuthCd= 권한-메뉴 배치 저장
|
||||
* GET /api/envset/menus/user-auth 사용자-권한 목록
|
||||
* POST /api/envset/menus/user-auth 사용자-권한 배치 저장
|
||||
* GET /api/envset/menus/search-user 사용자 검색 (autocomplete)
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/envset/menus")
|
||||
@RequiredArgsConstructor
|
||||
public class MenuManageController {
|
||||
|
||||
private final MenuManageService menuManageService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<ApiResponse<List<MenuManageDto>>> getMenuList() {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(menuManageService.getMenuList(cu)));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<ApiResponse<Void>> saveMenuList(@RequestBody List<MenuManageDto> list) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
menuManageService.saveMenuList(cu, list);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@GetMapping("/auth")
|
||||
public ResponseEntity<ApiResponse<List<AuthMenuDto>>> getAuthMenuList(
|
||||
@RequestParam String menuAuthCd) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(
|
||||
menuManageService.getAuthMenuList(cu, menuAuthCd)));
|
||||
}
|
||||
|
||||
@PostMapping("/auth")
|
||||
public ResponseEntity<ApiResponse<Void>> saveAuthMenuList(
|
||||
@RequestParam String menuAuthCd,
|
||||
@RequestBody List<AuthMenuDto> list) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
menuManageService.saveAuthMenuList(cu, menuAuthCd, list);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@GetMapping("/user-auth")
|
||||
public ResponseEntity<ApiResponse<List<UserAuthDto>>> getUserMauthList(
|
||||
@RequestParam(required = false) String menuAuthCd,
|
||||
@RequestParam(required = false) String usrNm) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(
|
||||
menuManageService.getUserMauthList(cu, menuAuthCd, usrNm)));
|
||||
}
|
||||
|
||||
@PostMapping("/user-auth")
|
||||
public ResponseEntity<ApiResponse<Void>> saveUserMauthList(@RequestBody List<UserAuthDto> list) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
menuManageService.saveUserMauthList(cu, list);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@GetMapping("/search-user")
|
||||
public ResponseEntity<ApiResponse<List<Map<String, Object>>>> searchUser(
|
||||
@RequestParam(required = false) String keyword) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(menuManageService.searchUser(cu, keyword)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.company.gw.envset.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.envset.dto.UserDetailDto;
|
||||
import com.company.gw.envset.dto.UserSaveDto;
|
||||
import com.company.gw.envset.service.UserManageService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 환경설정 > 직원정보 (Envset0010)
|
||||
* GET /api/envset/users 직원 목록 (페이징)
|
||||
* GET /api/envset/users/{usrId} 직원 상세
|
||||
* POST /api/envset/users 직원 등록
|
||||
* PUT /api/envset/users/{usrId} 직원 수정
|
||||
* DELETE /api/envset/users/{usrId} 직원 삭제
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/envset/users")
|
||||
@RequiredArgsConstructor
|
||||
public class UserManageController {
|
||||
|
||||
private final UserManageService userManageService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<ApiResponse<Map<String, Object>>> getUserList(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "100") int size,
|
||||
@RequestParam(required = false) String usrNm,
|
||||
@RequestParam(required = false) String teamCd,
|
||||
@RequestParam(required = false) String dutyCd,
|
||||
@RequestParam(required = false) String apprYn,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@RequestParam(defaultValue = "USR_ID") String userOrderBy) {
|
||||
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("page", page);
|
||||
params.put("size", size);
|
||||
params.put("usrNm", usrNm);
|
||||
params.put("teamCd", teamCd);
|
||||
params.put("dutyCd", dutyCd);
|
||||
params.put("apprYn", apprYn);
|
||||
params.put("includeRetireYn", includeRetireYn);
|
||||
params.put("userOrderBy", userOrderBy);
|
||||
|
||||
Map<String, Object> result = userManageService.getUserList(cu, params);
|
||||
long total = (long) result.get("total");
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.ok(
|
||||
result,
|
||||
ApiResponse.PaginationInfo.builder().page(page).size(size).total(total).build()
|
||||
));
|
||||
}
|
||||
|
||||
@GetMapping("/{usrId}")
|
||||
public ResponseEntity<ApiResponse<UserDetailDto>> getUserDetail(@PathVariable String usrId) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ResponseEntity.ok(ApiResponse.ok(userManageService.getUserDetail(cu, usrId)));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<ApiResponse<Void>> insertUser(@Valid @RequestBody UserSaveDto dto) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
userManageService.insertUser(cu, dto);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@PutMapping("/{usrId}")
|
||||
public ResponseEntity<ApiResponse<Void>> updateUser(
|
||||
@PathVariable String usrId,
|
||||
@Valid @RequestBody UserSaveDto dto) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
dto.setUsrId(usrId);
|
||||
userManageService.updateUser(cu, dto);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{usrId}")
|
||||
public ResponseEntity<ApiResponse<Void>> deleteUser(@PathVariable String usrId) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
userManageService.deleteUser(cu, usrId);
|
||||
return ResponseEntity.ok(ApiResponse.ok(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.company.gw.envset.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.util.JwtUtil;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.envset.service.WorkCdService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 환경설정 > 근무코드 관리 (Envset0040, SX_CO0070)
|
||||
* GET /api/envset/workcd 목록
|
||||
* POST /api/envset/workcd 등록
|
||||
* PUT /api/envset/workcd/{workCd} 수정
|
||||
* DELETE /api/envset/workcd/{workCd} 삭제
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/envset/workcd")
|
||||
@RequiredArgsConstructor
|
||||
public class WorkCdController {
|
||||
|
||||
private final WorkCdService workCdService;
|
||||
private final JwtUtil jwtUtil;
|
||||
|
||||
@GetMapping
|
||||
public ApiResponse<List<Map<String, Object>>> getWorkCdList(
|
||||
@RequestParam(defaultValue = "") String searchText) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
return ApiResponse.ok(workCdService.getWorkCdList(cu.getCorpNo(), searchText));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<Void> insertWorkCd(@RequestBody Map<String, Object> body) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
workCdService.insertWorkCd(cu.getCorpNo(), cu.getUsrId(), body);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@PutMapping("/{workCd}")
|
||||
public ApiResponse<Void> updateWorkCd(
|
||||
@PathVariable String workCd,
|
||||
@RequestBody Map<String, Object> body) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
workCdService.updateWorkCd(cu.getCorpNo(), cu.getUsrId(), workCd, body);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{workCd}")
|
||||
public ApiResponse<Void> deleteWorkCd(@PathVariable String workCd) {
|
||||
CurrentUser cu = SecurityUtil.getCurrentUser(jwtUtil);
|
||||
workCdService.deleteWorkCd(cu.getCorpNo(), workCd);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class AuthMenuDto {
|
||||
private String corpNo;
|
||||
private String menuNo;
|
||||
private String upperMenuNo;
|
||||
private String menuNm;
|
||||
private String url;
|
||||
private String menuProp;
|
||||
private Integer menuOrdr;
|
||||
private String menuUseYn;
|
||||
private Integer lvl;
|
||||
private String menuAuthYn; // Y/N
|
||||
private String menuAuthCd;
|
||||
private String funcAuthCn;
|
||||
private String rgstrId;
|
||||
private String modId;
|
||||
private String rowStatus; // U만 존재 (Y이면 merge, N이면 delete)
|
||||
}
|
||||
18
backend/src/main/java/com/company/gw/envset/dto/CodeDto.java
Normal file
18
backend/src/main/java/com/company/gw/envset/dto/CodeDto.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class CodeDto {
|
||||
private String corpNo;
|
||||
private String commClCd;
|
||||
private String commCd;
|
||||
private String commCdNm;
|
||||
private String commCdUseYn;
|
||||
private String commCdDscrpt;
|
||||
private Integer commCdDsplyOrdr;
|
||||
private String rgstrId;
|
||||
private String modId;
|
||||
private String rowStatus; // I/U/D
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class CodeIndexDto {
|
||||
private String corpNo;
|
||||
private String commClCd;
|
||||
private String commClCdNm;
|
||||
private String commClCdUseYn;
|
||||
private String commClCdDscrpt;
|
||||
private Integer dsplyOrdr;
|
||||
private String rgstrId;
|
||||
private String modId;
|
||||
// 배치 저장용 상태 플래그
|
||||
private String rowStatus; // I/U/D
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class MenuManageDto {
|
||||
private String corpNo;
|
||||
private String menuNo;
|
||||
private String upperMenuNo;
|
||||
private String menuNm;
|
||||
private String url;
|
||||
private String rm;
|
||||
private String menuProp;
|
||||
private Integer menuOrdr;
|
||||
private String menuUseYn;
|
||||
private String controller;
|
||||
private Integer menuLvl;
|
||||
private String rgstrId;
|
||||
private String modId;
|
||||
private String rowStatus; // I/U/D
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class UserAuthDto {
|
||||
private String corpNo;
|
||||
private String usrId;
|
||||
private String usrNm;
|
||||
private String menuAuthCd;
|
||||
private String teamCd;
|
||||
private String dutyCd;
|
||||
private String retirementDate;
|
||||
private String rgstrId;
|
||||
private String rowStatus; // I/D
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class UserDetailDto {
|
||||
private String corpNo;
|
||||
private String usrId;
|
||||
private String usrSortOrdr;
|
||||
private String usrNm;
|
||||
private String loginId;
|
||||
private String dutyCd;
|
||||
private String brthDyDate;
|
||||
private String usrTelno;
|
||||
private String mtelNo;
|
||||
private String email;
|
||||
private String baseAdrs;
|
||||
private String gusoAdrs;
|
||||
private String gusoTelno;
|
||||
private String joinCpDate;
|
||||
private String teamCd;
|
||||
private String dismlDate;
|
||||
private String retirementDate;
|
||||
private String spkltArtcCn;
|
||||
private String photoAtchfileNo;
|
||||
private String spmtEmail;
|
||||
private String spmtMtelNo;
|
||||
private String apprYn;
|
||||
private String finalSchspNm;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class UserListDto {
|
||||
private String usrId;
|
||||
private String usrNm;
|
||||
private String teamCd;
|
||||
private String dutyCd;
|
||||
private String usrTelno;
|
||||
private String mtelNo;
|
||||
private String retirementDate;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.company.gw.envset.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter @Setter
|
||||
public class UserSaveDto {
|
||||
// 공통 (insert/update 구분용)
|
||||
private String corpNo;
|
||||
private String usrId;
|
||||
private String rgstrId;
|
||||
private String modId;
|
||||
|
||||
@NotBlank(message = "직원명은 필수입니다.")
|
||||
private String usrNm;
|
||||
|
||||
private String loginId;
|
||||
private String pw; // 평문 → 서비스에서 암호화
|
||||
private String usrSortOrdr;
|
||||
private String dutyCd;
|
||||
private String brthDyDate;
|
||||
private String usrTelno;
|
||||
private String mtelNo;
|
||||
private String email;
|
||||
private String baseAdrs;
|
||||
private String gusoAdrs;
|
||||
private String gusoTelno;
|
||||
private String joinCpDate;
|
||||
private String teamCd;
|
||||
private String dismlDate;
|
||||
private String retirementDate;
|
||||
private String spkltArtcCn;
|
||||
private String spmtEmail;
|
||||
private String spmtMtelNo;
|
||||
private String rrno;
|
||||
private String apprYn;
|
||||
private String finalSchspNm;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.company.gw.envset.mapper;
|
||||
|
||||
import com.company.gw.envset.dto.CodeDto;
|
||||
import com.company.gw.envset.dto.CodeIndexDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface CodeManageMapper {
|
||||
List<CodeIndexDto> getCdidxList(Map<String, Object> params);
|
||||
CodeIndexDto getCdidxInfo(Map<String, Object> params);
|
||||
void insertCdidx(CodeIndexDto dto);
|
||||
void updateCdidx(CodeIndexDto dto);
|
||||
void deleteCdidx(@Param("corpNo") String corpNo, @Param("commClCd") String commClCd);
|
||||
|
||||
List<CodeDto> getCodeList(Map<String, Object> params);
|
||||
void insertCode(CodeDto dto);
|
||||
void updateCode(CodeDto dto);
|
||||
void deleteCode(@Param("corpNo") String corpNo,
|
||||
@Param("commClCd") String commClCd,
|
||||
@Param("commCd") String commCd);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.company.gw.envset.mapper;
|
||||
|
||||
import com.company.gw.envset.dto.AuthMenuDto;
|
||||
import com.company.gw.envset.dto.MenuManageDto;
|
||||
import com.company.gw.envset.dto.UserAuthDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface MenuManageMapper {
|
||||
List<MenuManageDto> getMenuList(@Param("corpNo") String corpNo);
|
||||
void insertMenu(MenuManageDto dto);
|
||||
void updateMenu(MenuManageDto dto);
|
||||
void deleteMauthByMenu(@Param("corpNo") String corpNo, @Param("menuNo") String menuNo);
|
||||
void deleteMenu(@Param("corpNo") String corpNo, @Param("menuNo") String menuNo);
|
||||
|
||||
List<AuthMenuDto> getAuthMenuList(Map<String, Object> params);
|
||||
void mergeMenuAuth(AuthMenuDto dto);
|
||||
void deleteMenuAuth(@Param("corpNo") String corpNo,
|
||||
@Param("menuNo") String menuNo,
|
||||
@Param("menuAuthCd") String menuAuthCd);
|
||||
|
||||
List<UserAuthDto> getUserMauthList(Map<String, Object> params);
|
||||
void insertUserMauth(UserAuthDto dto);
|
||||
void deleteUserMauth(@Param("corpNo") String corpNo,
|
||||
@Param("usrId") String usrId,
|
||||
@Param("menuAuthCd") String menuAuthCd);
|
||||
|
||||
List<Map<String, Object>> searchUser(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.company.gw.envset.mapper;
|
||||
|
||||
import com.company.gw.envset.dto.UserDetailDto;
|
||||
import com.company.gw.envset.dto.UserListDto;
|
||||
import com.company.gw.envset.dto.UserSaveDto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface UserManageMapper {
|
||||
List<UserListDto> getUserList(Map<String, Object> params);
|
||||
long getUserListCount(Map<String, Object> params);
|
||||
UserDetailDto getUserDetail(Map<String, Object> params);
|
||||
int getLoginIdCount(Map<String, Object> params);
|
||||
void insertUser(UserSaveDto dto);
|
||||
void updateUser(UserSaveDto dto);
|
||||
void updateUserPw(@Param("corpNo") String corpNo,
|
||||
@Param("usrId") String usrId,
|
||||
@Param("pw") String pw,
|
||||
@Param("modId") String modId);
|
||||
void deleteUser(@Param("corpNo") String corpNo, @Param("usrId") String usrId);
|
||||
void updateUserPhoto(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.company.gw.envset.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface WorkCdMapper {
|
||||
List<Map<String, Object>> getWorkCdList(Map<String, Object> param);
|
||||
void insertWorkCd(Map<String, Object> param);
|
||||
void updateWorkCd(Map<String, Object> param);
|
||||
void deleteWorkCd(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.company.gw.envset.service;
|
||||
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.envset.dto.CodeDto;
|
||||
import com.company.gw.envset.dto.CodeIndexDto;
|
||||
import com.company.gw.envset.mapper.CodeManageMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CodeManageService {
|
||||
|
||||
private final CodeManageMapper codeManageMapper;
|
||||
|
||||
public List<CodeIndexDto> getCdidxList(CurrentUser cu, String searchText) {
|
||||
return codeManageMapper.getCdidxList(Map.of(
|
||||
"corpNo", cu.getCorpNo(),
|
||||
"searchText", searchText != null ? searchText : ""
|
||||
));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveCdidxList(CurrentUser cu, List<CodeIndexDto> list) {
|
||||
for (CodeIndexDto item : list) {
|
||||
item.setCorpNo(cu.getCorpNo());
|
||||
item.setRgstrId(cu.getUsrId());
|
||||
item.setModId(cu.getUsrId());
|
||||
|
||||
switch (item.getRowStatus()) {
|
||||
case "I" -> codeManageMapper.insertCdidx(item);
|
||||
case "U" -> codeManageMapper.updateCdidx(item);
|
||||
case "D" -> codeManageMapper.deleteCdidx(cu.getCorpNo(), item.getCommClCd());
|
||||
default -> throw new BizException("잘못된 rowStatus: " + item.getRowStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<CodeDto> getCodeList(CurrentUser cu, String commClCd, String searchText) {
|
||||
if (!StringUtils.hasText(commClCd)) throw new BizException("코드분류가 필요합니다.");
|
||||
return codeManageMapper.getCodeList(Map.of(
|
||||
"corpNo", cu.getCorpNo(),
|
||||
"commClCd", commClCd,
|
||||
"searchText", searchText != null ? searchText : ""
|
||||
));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveCodeList(CurrentUser cu, String commClCd, List<CodeDto> list) {
|
||||
if (!StringUtils.hasText(commClCd)) throw new BizException("코드분류가 필요합니다.");
|
||||
for (CodeDto item : list) {
|
||||
item.setCorpNo(cu.getCorpNo());
|
||||
item.setCommClCd(commClCd);
|
||||
item.setRgstrId(cu.getUsrId());
|
||||
item.setModId(cu.getUsrId());
|
||||
|
||||
switch (item.getRowStatus()) {
|
||||
case "I" -> codeManageMapper.insertCode(item);
|
||||
case "U" -> codeManageMapper.updateCode(item);
|
||||
case "D" -> codeManageMapper.deleteCode(cu.getCorpNo(), commClCd, item.getCommCd());
|
||||
default -> throw new BizException("잘못된 rowStatus: " + item.getRowStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.company.gw.envset.service;
|
||||
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.envset.dto.AuthMenuDto;
|
||||
import com.company.gw.envset.dto.MenuManageDto;
|
||||
import com.company.gw.envset.dto.UserAuthDto;
|
||||
import com.company.gw.envset.mapper.MenuManageMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MenuManageService {
|
||||
|
||||
private final MenuManageMapper menuManageMapper;
|
||||
|
||||
public List<MenuManageDto> getMenuList(CurrentUser cu) {
|
||||
return menuManageMapper.getMenuList(cu.getCorpNo());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveMenuList(CurrentUser cu, List<MenuManageDto> list) {
|
||||
for (MenuManageDto item : list) {
|
||||
item.setCorpNo(cu.getCorpNo());
|
||||
item.setRgstrId(cu.getUsrId());
|
||||
item.setModId(cu.getUsrId());
|
||||
|
||||
switch (item.getRowStatus()) {
|
||||
case "I" -> menuManageMapper.insertMenu(item);
|
||||
case "U" -> menuManageMapper.updateMenu(item);
|
||||
case "D" -> {
|
||||
menuManageMapper.deleteMauthByMenu(cu.getCorpNo(), item.getMenuNo());
|
||||
menuManageMapper.deleteMenu(cu.getCorpNo(), item.getMenuNo());
|
||||
}
|
||||
default -> throw new BizException("잘못된 rowStatus: " + item.getRowStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<AuthMenuDto> getAuthMenuList(CurrentUser cu, String menuAuthCd) {
|
||||
if (!StringUtils.hasText(menuAuthCd)) throw new BizException("권한코드가 필요합니다.");
|
||||
return menuManageMapper.getAuthMenuList(Map.of(
|
||||
"corpNo", cu.getCorpNo(),
|
||||
"menuAuthCd", menuAuthCd
|
||||
));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveAuthMenuList(CurrentUser cu, String menuAuthCd, List<AuthMenuDto> list) {
|
||||
if (!StringUtils.hasText(menuAuthCd)) throw new BizException("권한코드가 필요합니다.");
|
||||
for (AuthMenuDto item : list) {
|
||||
if (!"U".equals(item.getRowStatus())) continue;
|
||||
item.setCorpNo(cu.getCorpNo());
|
||||
item.setMenuAuthCd(menuAuthCd);
|
||||
item.setRgstrId(cu.getUsrId());
|
||||
item.setModId(cu.getUsrId());
|
||||
|
||||
if ("Y".equals(item.getMenuAuthYn())) {
|
||||
menuManageMapper.mergeMenuAuth(item);
|
||||
} else {
|
||||
menuManageMapper.deleteMenuAuth(cu.getCorpNo(), item.getMenuNo(), menuAuthCd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<UserAuthDto> getUserMauthList(CurrentUser cu, String menuAuthCd, String usrNm) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
params.put("menuAuthCd", StringUtils.hasText(menuAuthCd) ? menuAuthCd : null);
|
||||
params.put("usrNm", StringUtils.hasText(usrNm) ? usrNm : null);
|
||||
return menuManageMapper.getUserMauthList(params);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveUserMauthList(CurrentUser cu, List<UserAuthDto> list) {
|
||||
for (UserAuthDto item : list) {
|
||||
item.setCorpNo(cu.getCorpNo());
|
||||
item.setRgstrId(cu.getUsrId());
|
||||
|
||||
switch (item.getRowStatus()) {
|
||||
case "I" -> menuManageMapper.insertUserMauth(item);
|
||||
case "D" -> menuManageMapper.deleteUserMauth(
|
||||
cu.getCorpNo(), item.getUsrId(), item.getMenuAuthCd());
|
||||
default -> throw new BizException("잘못된 rowStatus: " + item.getRowStatus());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> searchUser(CurrentUser cu, String keyword) {
|
||||
return menuManageMapper.searchUser(Map.of(
|
||||
"corpNo", cu.getCorpNo(),
|
||||
"keyword", keyword != null ? keyword : ""
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.company.gw.envset.service;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.service.SequenceService;
|
||||
import com.company.gw.common.util.PasswordUtil;
|
||||
import com.company.gw.envset.dto.UserDetailDto;
|
||||
import com.company.gw.envset.dto.UserListDto;
|
||||
import com.company.gw.envset.dto.UserSaveDto;
|
||||
import com.company.gw.envset.mapper.UserManageMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserManageService {
|
||||
|
||||
private static final List<String> ALLOWED_ORDER_BY =
|
||||
List.of("USR_ID", "USR_NM", "TEAM_CD", "DUTY_CD");
|
||||
|
||||
private final UserManageMapper userManageMapper;
|
||||
private final SequenceService sequenceService;
|
||||
|
||||
public Map<String, Object> getUserList(CurrentUser cu, Map<String, Object> params) {
|
||||
String orderBy = (String) params.getOrDefault("userOrderBy", "USR_ID");
|
||||
if (!ALLOWED_ORDER_BY.contains(orderBy)) {
|
||||
throw new BizException("정렬 조건이 올바르지 않습니다.");
|
||||
}
|
||||
params.put("corpNo", cu.getCorpNo());
|
||||
params.put("userOrderBy", orderBy);
|
||||
|
||||
long total = userManageMapper.getUserListCount(params);
|
||||
List<UserListDto> list = userManageMapper.getUserList(params);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
public UserDetailDto getUserDetail(CurrentUser cu, String usrId) {
|
||||
Map<String, Object> params = Map.of("corpNo", cu.getCorpNo(), "usrId", usrId);
|
||||
UserDetailDto detail = userManageMapper.getUserDetail(params);
|
||||
if (detail == null) {
|
||||
throw new BizException("사용자 정보가 없습니다.");
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void insertUser(CurrentUser cu, UserSaveDto dto) {
|
||||
if (!StringUtils.hasText(dto.getPw())) {
|
||||
throw new BizException("비밀번호는 필수입니다.");
|
||||
}
|
||||
dto.setCorpNo(cu.getCorpNo());
|
||||
dto.setRgstrId(cu.getUsrId());
|
||||
|
||||
// 시퀀스로 USR_ID 생성 (기존 getNextSeqString('SX_GW0010.USR_ID', 5))
|
||||
String usrId = sequenceService.getNextSeqString("SX_GW0010.USR_ID", 5);
|
||||
dto.setUsrId(usrId);
|
||||
|
||||
// 로그인ID 중복 체크
|
||||
checkLoginIdDuplicate(cu.getCorpNo(), dto.getLoginId(), usrId);
|
||||
|
||||
// 비밀번호 암호화 (SHA-256 + Base64)
|
||||
dto.setPw(PasswordUtil.encode(dto.getPw()));
|
||||
|
||||
userManageMapper.insertUser(dto);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateUser(CurrentUser cu, UserSaveDto dto) {
|
||||
if (!StringUtils.hasText(dto.getUsrId())) {
|
||||
throw new BizException("USR_ID는 필수입니다.");
|
||||
}
|
||||
dto.setCorpNo(cu.getCorpNo());
|
||||
dto.setModId(cu.getUsrId());
|
||||
|
||||
// 로그인ID 중복 체크 (본인 제외)
|
||||
checkLoginIdDuplicate(cu.getCorpNo(), dto.getLoginId(), dto.getUsrId());
|
||||
|
||||
userManageMapper.updateUser(dto);
|
||||
|
||||
// 비밀번호 입력 시에만 변경
|
||||
if (StringUtils.hasText(dto.getPw())) {
|
||||
userManageMapper.updateUserPw(
|
||||
cu.getCorpNo(), dto.getUsrId(),
|
||||
PasswordUtil.encode(dto.getPw()), cu.getUsrId());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteUser(CurrentUser cu, String usrId) {
|
||||
// 사용자 존재 확인
|
||||
getUserDetail(cu, usrId);
|
||||
userManageMapper.deleteUser(cu.getCorpNo(), usrId);
|
||||
}
|
||||
|
||||
private void checkLoginIdDuplicate(String corpNo, String loginId, String usrId) {
|
||||
if (!StringUtils.hasText(loginId)) return;
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("corpNo", corpNo);
|
||||
params.put("loginId", loginId);
|
||||
params.put("usrId", usrId != null ? usrId : "");
|
||||
int cnt = userManageMapper.getLoginIdCount(params);
|
||||
if (cnt > 0) {
|
||||
throw new BizException("이미 사용 중인 로그인 아이디입니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.company.gw.envset.service;
|
||||
|
||||
import com.company.gw.envset.mapper.WorkCdMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WorkCdService {
|
||||
|
||||
private final WorkCdMapper workCdMapper;
|
||||
|
||||
public List<Map<String, Object>> getWorkCdList(String corpNo, String searchText) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("searchText", searchText);
|
||||
return workCdMapper.getWorkCdList(param);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void insertWorkCd(String corpNo, String regUsrId, Map<String, Object> data) {
|
||||
data.put("corpNo", corpNo);
|
||||
data.put("regUsrId", regUsrId);
|
||||
workCdMapper.insertWorkCd(data);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateWorkCd(String corpNo, String regUsrId, String workCd, Map<String, Object> data) {
|
||||
data.put("corpNo", corpNo);
|
||||
data.put("regUsrId", regUsrId);
|
||||
data.put("workCd", workCd);
|
||||
workCdMapper.updateWorkCd(data);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteWorkCd(String corpNo, String workCd) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("workCd", workCd);
|
||||
workCdMapper.deleteWorkCd(param);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.company.gw.fedex.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.fedex.service.FedexService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/fedex")
|
||||
@RequiredArgsConstructor
|
||||
public class FedexController {
|
||||
|
||||
private final FedexService fedexService;
|
||||
|
||||
/** 목록 */
|
||||
@GetMapping("/0010")
|
||||
public ApiResponse<Map<String, Object>> getFedexList(
|
||||
@RequestParam(defaultValue = "") String searchText,
|
||||
@RequestParam(defaultValue = "1") int pageNo,
|
||||
@RequestParam(defaultValue = "100") int pageSize) {
|
||||
return ApiResponse.ok(fedexService.getFedexList(searchText, pageNo, pageSize));
|
||||
}
|
||||
|
||||
/** 상세 */
|
||||
@GetMapping("/0010/{sq}")
|
||||
public ApiResponse<Map<String, Object>> getFedexDetail(@PathVariable long sq) {
|
||||
return ApiResponse.ok(fedexService.getFedexDetail(sq));
|
||||
}
|
||||
|
||||
/** 등록 */
|
||||
@PostMapping("/0010")
|
||||
public ApiResponse<Long> insertFedex(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser cu) {
|
||||
body.put("regUserId", cu.getUsrId());
|
||||
long sq = fedexService.insertFedex(body);
|
||||
return ApiResponse.ok(sq);
|
||||
}
|
||||
|
||||
/** 첨부파일 번호 업데이트 */
|
||||
@PatchMapping("/0010/{sq}/attach")
|
||||
public ApiResponse<Void> updateFedexAttach(
|
||||
@PathVariable long sq,
|
||||
@RequestBody Map<String, Object> body) {
|
||||
fedexService.updateFedexAttach(sq, (String) body.get("attachNo"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 코드 목록 */
|
||||
@GetMapping("/codes")
|
||||
public ApiResponse<Map<String, Object>> getCodes() {
|
||||
return ApiResponse.ok(fedexService.getCodes());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.company.gw.fedex.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface FedexMapper {
|
||||
int countFedexList(Map<String, Object> param);
|
||||
List<Map<String, Object>> getFedexList(Map<String, Object> param);
|
||||
Map<String, Object> getFedexDetail(Map<String, Object> param);
|
||||
void insertFedex(Map<String, Object> param);
|
||||
void updateFedexAttach(Map<String, Object> param);
|
||||
List<Map<String, Object>> getFstList();
|
||||
List<Map<String, Object>> getGwiList();
|
||||
List<Map<String, Object>> getFjjList();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.company.gw.fedex.service;
|
||||
|
||||
import com.company.gw.fedex.mapper.FedexMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FedexService {
|
||||
|
||||
private final FedexMapper fedexMapper;
|
||||
|
||||
public Map<String, Object> getFedexList(String searchText, int pageNo, int pageSize) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("searchText", searchText);
|
||||
param.put("pageSize", pageSize);
|
||||
param.put("offset", (pageNo - 1) * pageSize);
|
||||
|
||||
int total = fedexMapper.countFedexList(param);
|
||||
List<Map<String, Object>> list = fedexMapper.getFedexList(param);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, Object> getFedexDetail(long sq) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("sq", sq);
|
||||
return fedexMapper.getFedexDetail(param);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public long insertFedex(Map<String, Object> param) {
|
||||
fedexMapper.insertFedex(param);
|
||||
return ((Number) param.get("sq")).longValue();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateFedexAttach(long sq, String attachNo) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("sq", sq);
|
||||
param.put("attachNo", attachNo);
|
||||
fedexMapper.updateFedexAttach(param);
|
||||
}
|
||||
|
||||
public Map<String, Object> getCodes() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("fstList", fedexMapper.getFstList());
|
||||
result.put("gwiList", fedexMapper.getGwiList());
|
||||
result.put("fjjList", fedexMapper.getFjjList());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.company.gw.main.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.main.service.MainService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/main")
|
||||
@RequiredArgsConstructor
|
||||
public class MainController {
|
||||
|
||||
private final MainService mainService;
|
||||
|
||||
/** 대시보드 전체 데이터 */
|
||||
@GetMapping("/dashboard")
|
||||
public ApiResponse<Map<String, Object>> getDashboard(
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(mainService.getDashboard(
|
||||
currentUser.getCorpNo(), currentUser.getUsrId()));
|
||||
}
|
||||
|
||||
/** 출근 */
|
||||
@PostMapping("/workstart")
|
||||
public ApiResponse<Map<String, Object>> clockIn(
|
||||
@AuthenticationPrincipal CurrentUser currentUser,
|
||||
@RequestBody Map<String, String> body,
|
||||
HttpServletRequest request) {
|
||||
String date = body.get("workPlanYymmdd");
|
||||
String ip = getClientIp(request);
|
||||
return ApiResponse.ok(mainService.clockIn(
|
||||
currentUser.getCorpNo(), currentUser.getUsrId(), date, ip));
|
||||
}
|
||||
|
||||
/** 퇴근 */
|
||||
@PostMapping("/workend")
|
||||
public ApiResponse<Map<String, Object>> clockOut(
|
||||
@AuthenticationPrincipal CurrentUser currentUser,
|
||||
@RequestBody Map<String, String> body,
|
||||
HttpServletRequest request) {
|
||||
String date = body.get("workPlanYymmdd");
|
||||
String ip = getClientIp(request);
|
||||
return ApiResponse.ok(mainService.clockOut(
|
||||
currentUser.getCorpNo(), currentUser.getUsrId(), date, ip));
|
||||
}
|
||||
|
||||
/** 오늘 지각자 목록 (관리자용) */
|
||||
@GetMapping("/late-list")
|
||||
public ApiResponse<List<Map<String, Object>>> getLateList(
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(mainService.getTodayLateList(currentUser.getCorpNo()));
|
||||
}
|
||||
|
||||
/** X-Forwarded-For → remoteAddr 순으로 클라이언트 IP 추출 */
|
||||
private String getClientIp(HttpServletRequest request) {
|
||||
String xff = request.getHeader("X-Forwarded-For");
|
||||
if (StringUtils.hasText(xff)) {
|
||||
return xff.split(",")[0].trim();
|
||||
}
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.company.gw.main.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface MainMapper {
|
||||
List<Map<String, Object>> getTopPostList(Map<String, Object> param);
|
||||
List<Map<String, Object>> getWorkRangeList(Map<String, Object> param);
|
||||
Map<String, Object> getTodayWorkRecord(Map<String, Object> param);
|
||||
Map<String, Object> getPendingApprCount(Map<String, Object> param);
|
||||
List<Map<String, Object>> getMyDocSentSummary(Map<String, Object> param);
|
||||
List<Map<String, Object>> getMyDocReceivedSummary(Map<String, Object> param);
|
||||
List<Map<String, Object>> getTodayWorkSummary(Map<String, Object> param);
|
||||
|
||||
// 출퇴근
|
||||
Map<String, Object> getWorkplanInfo(Map<String, Object> param);
|
||||
List<String> getAllowedIpList(Map<String, Object> param);
|
||||
int updateWorkStart(Map<String, Object> param);
|
||||
int updateWorkEnd(Map<String, Object> param);
|
||||
List<Map<String, Object>> getTodayLateList(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
package com.company.gw.main.service;
|
||||
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.main.mapper.MainMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MainService {
|
||||
|
||||
private final MainMapper mainMapper;
|
||||
private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
|
||||
/** 대시보드 전체 데이터 */
|
||||
public Map<String, Object> getDashboard(String corpNo, String usrId) {
|
||||
LocalDate today = LocalDate.now();
|
||||
String todayStr = today.format(FMT);
|
||||
String fromDate = today.minusDays(4).format(FMT);
|
||||
String toDate = today.plusDays(4).format(FMT);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
// 공지사항 최신 5건 (UNTY_BBS_CD='0002')
|
||||
result.put("noticeList", getTopPostList(corpNo, "0002", 5));
|
||||
// 자유게시판 최신 5건 (UNTY_BBS_CD='0001')
|
||||
result.put("boardList", getTopPostList(corpNo, "0001", 5));
|
||||
// 업무메뉴얼 최신 5건 (UNTY_BBS_CD='0004')
|
||||
result.put("manualList", getTopPostList(corpNo, "0004", 5));
|
||||
|
||||
// 9일 근무 범위 (오늘±4일)
|
||||
Map<String, Object> wp = new HashMap<>();
|
||||
wp.put("corpNo", corpNo);
|
||||
wp.put("usrId", usrId);
|
||||
wp.put("fromDate", fromDate);
|
||||
wp.put("toDate", toDate);
|
||||
result.put("workRangeList", mainMapper.getWorkRangeList(wp));
|
||||
|
||||
// 오늘 근무 기록
|
||||
result.put("todayWork", getTodayWorkRecord(corpNo, usrId, todayStr));
|
||||
|
||||
// 결재 대기 건수
|
||||
result.put("pendingAppr", getPendingApprCount(corpNo, usrId));
|
||||
|
||||
// 내가 올린 결재 문서 상태별 카운트
|
||||
Map<String, Object> sp = new HashMap<>();
|
||||
sp.put("corpNo", corpNo);
|
||||
sp.put("usrId", usrId);
|
||||
result.put("myDocSent", mainMapper.getMyDocSentSummary(sp));
|
||||
|
||||
// 내가 받은 결재 문서 상태별 카운트
|
||||
result.put("myDocReceived", mainMapper.getMyDocReceivedSummary(sp));
|
||||
|
||||
// 오늘 전체 근무 현황 (근무코드별 그룹)
|
||||
Map<String, Object> ts = new HashMap<>();
|
||||
ts.put("corpNo", corpNo);
|
||||
ts.put("today", todayStr);
|
||||
result.put("todayWorkSummary", mainMapper.getTodayWorkSummary(ts));
|
||||
|
||||
// 오늘 지각자
|
||||
result.put("todayLateList", getTodayLateList(corpNo));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getTopPostList(String corpNo, String bbsCd, int top) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("bbsCd", bbsCd);
|
||||
param.put("top", top);
|
||||
return mainMapper.getTopPostList(param);
|
||||
}
|
||||
|
||||
private Map<String, Object> getTodayWorkRecord(String corpNo, String usrId, String today) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
param.put("today", today);
|
||||
return mainMapper.getTodayWorkRecord(param);
|
||||
}
|
||||
|
||||
private Map<String, Object> getPendingApprCount(String corpNo, String usrId) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
return mainMapper.getPendingApprCount(param);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────
|
||||
// 출퇴근
|
||||
// ─────────────────────────────────────────────────────
|
||||
|
||||
/** 근무계획 단건 조회 */
|
||||
public Map<String, Object> getWorkplanInfo(String corpNo, String usrId, String workPlanYymmdd) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
param.put("workPlanYymmdd", workPlanYymmdd);
|
||||
return mainMapper.getWorkplanInfo(param);
|
||||
}
|
||||
|
||||
/** IP 허용 여부 검사 (SX014 코드에 IP 등록 없으면 전체 허용) */
|
||||
public void checkAllowedIp(String corpNo, String clientIp) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
List<String> ipList = mainMapper.getAllowedIpList(param);
|
||||
if (ipList == null || ipList.isEmpty()) return; // 설정 없으면 전체 허용
|
||||
for (String allowed : ipList) {
|
||||
if (StringUtils.hasText(allowed) && clientIp.startsWith(allowed.trim())) return;
|
||||
}
|
||||
throw new BizException("접속 IP(" + clientIp + ")가 허용 IP가 아닙니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
/** 출근 처리 */
|
||||
@Transactional
|
||||
public Map<String, Object> clockIn(String corpNo, String usrId, String workPlanYymmdd, String clientIp) {
|
||||
checkAllowedIp(corpNo, clientIp);
|
||||
|
||||
Map<String, Object> wp = getWorkplanInfo(corpNo, usrId, workPlanYymmdd);
|
||||
if (wp == null || !StringUtils.hasText((String) wp.get("REAL_WORK_CD"))) {
|
||||
throw new BizException(workPlanYymmdd + " 일의 근무 계획이 없습니다.");
|
||||
}
|
||||
if (StringUtils.hasText((String) wp.get("WORK_START_DT"))) {
|
||||
throw new BizException(workPlanYymmdd + " 에 이미 출근 기록이 있습니다.");
|
||||
}
|
||||
|
||||
// 지각 여부 계산
|
||||
int lateMin = calcLateMin((String) wp.get("GOTOWORK_TM_NM"));
|
||||
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
param.put("workPlanYymmdd", workPlanYymmdd);
|
||||
mainMapper.updateWorkStart(param);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("lateMin", lateMin);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 퇴근 처리 */
|
||||
@Transactional
|
||||
public Map<String, Object> clockOut(String corpNo, String usrId, String workPlanYymmdd, String clientIp) {
|
||||
checkAllowedIp(corpNo, clientIp);
|
||||
|
||||
Map<String, Object> wp = getWorkplanInfo(corpNo, usrId, workPlanYymmdd);
|
||||
if (wp == null || !StringUtils.hasText((String) wp.get("REAL_WORK_CD"))) {
|
||||
throw new BizException(workPlanYymmdd + " 일의 근무 계획이 없습니다.");
|
||||
}
|
||||
if (!StringUtils.hasText((String) wp.get("WORK_START_DT"))) {
|
||||
throw new BizException(workPlanYymmdd + " 에 출근 기록이 없습니다.");
|
||||
}
|
||||
if (StringUtils.hasText((String) wp.get("WORK_END_DT"))) {
|
||||
throw new BizException(workPlanYymmdd + " 에 이미 퇴근 기록이 있습니다.");
|
||||
}
|
||||
|
||||
// 조퇴 여부 계산
|
||||
int earlyMin = calcEarlyMin((String) wp.get("GETOFFWORK_TM_NM"));
|
||||
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("usrId", usrId);
|
||||
param.put("workPlanYymmdd", workPlanYymmdd);
|
||||
mainMapper.updateWorkEnd(param);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("earlyMin", earlyMin);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 오늘 지각자 목록 */
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getTodayLateList(String corpNo) {
|
||||
String today = LocalDate.now().format(FMT);
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("corpNo", corpNo);
|
||||
param.put("today", today);
|
||||
return mainMapper.getTodayLateList(param);
|
||||
}
|
||||
|
||||
/** 지각 분 계산 (GOTOWORK_TM_NM 예: "0900") */
|
||||
private int calcLateMin(String gotoworkTmNm) {
|
||||
if (!StringUtils.hasText(gotoworkTmNm) || gotoworkTmNm.length() < 4) return 0;
|
||||
try {
|
||||
LocalTime scheduled = LocalTime.of(
|
||||
Integer.parseInt(gotoworkTmNm.substring(0, 2)),
|
||||
Integer.parseInt(gotoworkTmNm.substring(2, 4))
|
||||
);
|
||||
LocalTime now = LocalTime.now();
|
||||
if (now.isAfter(scheduled)) {
|
||||
return (int) java.time.Duration.between(scheduled, now).toMinutes();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** 조퇴 분 계산 (GETOFFWORK_TM_NM 예: "1800") */
|
||||
private int calcEarlyMin(String getoffworkTmNm) {
|
||||
if (!StringUtils.hasText(getoffworkTmNm) || getoffworkTmNm.length() < 4) return 0;
|
||||
try {
|
||||
LocalTime scheduled = LocalTime.of(
|
||||
Integer.parseInt(getoffworkTmNm.substring(0, 2)),
|
||||
Integer.parseInt(getoffworkTmNm.substring(2, 4))
|
||||
);
|
||||
LocalTime now = LocalTime.now();
|
||||
if (now.isBefore(scheduled)) {
|
||||
return (int) java.time.Duration.between(now, scheduled).toMinutes();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package com.company.gw.tam.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.tam.service.TamService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/tam")
|
||||
@RequiredArgsConstructor
|
||||
public class TamController {
|
||||
|
||||
private final TamService tamService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0010 - 연차 관리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/yyvct")
|
||||
public ApiResponse<List<Map<String, Object>>> getYyvctList(
|
||||
@RequestParam String yyvctYy,
|
||||
@RequestParam(defaultValue = "") String usrNm,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getYyvctList(
|
||||
currentUser.getCorpNo(), yyvctYy, usrNm, teamCd, includeRetireYn));
|
||||
}
|
||||
|
||||
@PostMapping("/yyvct")
|
||||
public ApiResponse<Void> saveYyvct(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.saveYyvct(
|
||||
currentUser.getCorpNo(),
|
||||
(String) body.get("yyvctYy"),
|
||||
(String) body.get("usrId"),
|
||||
Integer.parseInt(body.get("yyvctCnt").toString()));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@DeleteMapping("/yyvct")
|
||||
public ApiResponse<Void> deleteYyvct(
|
||||
@RequestParam String yyvctYy,
|
||||
@RequestParam String usrId,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.deleteYyvct(currentUser.getCorpNo(), yyvctYy, usrId);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0020 - 결재 신청
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/apvreq")
|
||||
public ApiResponse<Map<String, Object>> getApvreqList(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getApvreqList(currentUser.getCorpNo(), params));
|
||||
}
|
||||
|
||||
@GetMapping("/apvreq/{aprvlDocId}")
|
||||
public ApiResponse<Map<String, Object>> getApvreqDetail(
|
||||
@PathVariable String aprvlDocId,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getApvreqDetail(currentUser.getCorpNo(), aprvlDocId));
|
||||
}
|
||||
|
||||
@PostMapping("/apvreq")
|
||||
public ApiResponse<Map<String, String>> createApvreq(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
String aprvlDocId = tamService.createApvreq(currentUser.getCorpNo(), body);
|
||||
return ApiResponse.ok(Map.of("aprvlDocId", aprvlDocId));
|
||||
}
|
||||
|
||||
@PutMapping("/apvreq/{aprvlDocId}")
|
||||
public ApiResponse<Void> updateApvreq(
|
||||
@PathVariable String aprvlDocId,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.updateApvreq(currentUser.getCorpNo(), aprvlDocId, body);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/apvreq/{aprvlDocId}/request")
|
||||
public ApiResponse<Void> requestApvreq(
|
||||
@PathVariable String aprvlDocId,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> apprList = (List<Map<String, Object>>) body.get("apprList");
|
||||
tamService.requestApvreq(currentUser.getCorpNo(), aprvlDocId, apprList);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@DeleteMapping("/apvreq/{aprvlDocId}")
|
||||
public ApiResponse<Void> deleteApvreq(
|
||||
@PathVariable String aprvlDocId,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.deleteApvreq(currentUser.getCorpNo(), aprvlDocId);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@GetMapping("/apvreq/latest-appr")
|
||||
public ApiResponse<List<Map<String, Object>>> getLatestApprList(
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getLatestApprList(currentUser.getCorpNo()));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0030 - 결재 처리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/apvapp")
|
||||
public ApiResponse<Map<String, Object>> getApvappList(
|
||||
@RequestParam Map<String, Object> params,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getApvappList(currentUser.getCorpNo(), params));
|
||||
}
|
||||
|
||||
@GetMapping("/apvapp/{aprvlDocId}")
|
||||
public ApiResponse<Map<String, Object>> getApvappDetail(
|
||||
@PathVariable String aprvlDocId,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getApvappDetail(currentUser.getCorpNo(), aprvlDocId));
|
||||
}
|
||||
|
||||
@PostMapping("/apvapp/{aprvlDocId}/approve")
|
||||
public ApiResponse<Void> approve(
|
||||
@PathVariable String aprvlDocId,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.approveApvdoc(currentUser.getCorpNo(), aprvlDocId,
|
||||
Integer.parseInt(body.get("aprvlSno").toString()),
|
||||
(String) body.get("apprCn"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/apvapp/{aprvlDocId}/reject")
|
||||
public ApiResponse<Void> reject(
|
||||
@PathVariable String aprvlDocId,
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
tamService.rejectApvdoc(currentUser.getCorpNo(), aprvlDocId,
|
||||
Integer.parseInt(body.get("aprvlSno").toString()),
|
||||
(String) body.get("apprCn"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 일괄 승인 */
|
||||
@PostMapping("/apvapp/multi-approve")
|
||||
public ApiResponse<Void> multiApprove(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> items = (List<Map<String, Object>>) body.get("items");
|
||||
tamService.multiApprove(currentUser.getCorpNo(), items, (String) body.get("apprCn"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
/** 일괄 반려 */
|
||||
@PostMapping("/apvapp/multi-reject")
|
||||
public ApiResponse<Void> multiReject(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> items = (List<Map<String, Object>>) body.get("items");
|
||||
tamService.multiReject(currentUser.getCorpNo(), items, (String) body.get("apprCn"));
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0040 - 근태 현황
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/status")
|
||||
public ApiResponse<List<Map<String, Object>>> getTamStatusList(
|
||||
@RequestParam String yyvctYy,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "00000000") String staYmd,
|
||||
@RequestParam(defaultValue = "99999999") String endYmd,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(tamService.getTamStatusList(
|
||||
currentUser.getCorpNo(), yyvctYy, teamCd, staYmd, endYmd, includeRetireYn));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.company.gw.tam.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface ApvdocMapper {
|
||||
|
||||
Map<String, Object> getApvdocInfo(Map<String, Object> param);
|
||||
|
||||
List<Map<String, Object>> getApprList(Map<String, Object> param);
|
||||
|
||||
Map<String, Object> getApprInfo(Map<String, Object> param);
|
||||
|
||||
void insertApvdoc(Map<String, Object> param);
|
||||
|
||||
void updateApvdocContent(Map<String, Object> param);
|
||||
|
||||
void updateApvdocAtchNo(Map<String, Object> param);
|
||||
|
||||
void updateApvdocStatusRequest(Map<String, Object> param);
|
||||
|
||||
void updateApvdocStatusApprove(Map<String, Object> param);
|
||||
|
||||
void updateApvdocStatusReject(Map<String, Object> param);
|
||||
|
||||
void updateFinalAprvlSno(Map<String, Object> param);
|
||||
|
||||
void updateAprvlCmplSno(Map<String, Object> param);
|
||||
|
||||
void deleteApprAll(Map<String, Object> param);
|
||||
|
||||
void insertAppr(Map<String, Object> param);
|
||||
|
||||
void updateApprStatus(Map<String, Object> param);
|
||||
|
||||
void apprApproveOrReject(Map<String, Object> param);
|
||||
|
||||
void updateNextApprStatusAppring(Map<String, Object> param);
|
||||
|
||||
void deleteApvdocSx0080(Map<String, Object> param);
|
||||
|
||||
void deleteApvdocSx0110(Map<String, Object> param);
|
||||
|
||||
void deleteApvdocSx0090(Map<String, Object> param);
|
||||
|
||||
void updateApvdocDocFlagAplnt(Map<String, Object> param);
|
||||
|
||||
void resetWorkEndDt(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.company.gw.tam.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface TamMapper {
|
||||
|
||||
// TAM0010 - 연차
|
||||
List<Map<String, Object>> getYyvctList(Map<String, Object> param);
|
||||
void upsertYyvct(Map<String, Object> param);
|
||||
void deleteYyvct(Map<String, Object> param);
|
||||
|
||||
// TAM0020 - 결재 신청
|
||||
List<Map<String, Object>> getApvreqList(Map<String, Object> param);
|
||||
long getApvreqListCount(Map<String, Object> param);
|
||||
List<Map<String, Object>> getWorkChangeList(Map<String, Object> param);
|
||||
Map<String, Object> getOtInfo(Map<String, Object> param);
|
||||
void insertSxGw0110(Map<String, Object> param);
|
||||
void insertSxGw0080(Map<String, Object> param);
|
||||
void deleteSxGw0110(Map<String, Object> param);
|
||||
void deleteSxGw0080(Map<String, Object> param);
|
||||
List<Map<String, Object>> getLatestApprList(Map<String, Object> param);
|
||||
void updateDocFlagAplnt(Map<String, Object> param);
|
||||
|
||||
// TAM0030 - 결재 처리
|
||||
List<Map<String, Object>> getApvappList(Map<String, Object> param);
|
||||
long getApvappListCount(Map<String, Object> param);
|
||||
void updateDocFlagAppr(Map<String, Object> param);
|
||||
void updateOutingTime(Map<String, Object> param);
|
||||
|
||||
// TAM0040 - 현황/통계
|
||||
List<Map<String, Object>> getTamStatusList(Map<String, Object> param);
|
||||
|
||||
// 결재 후처리
|
||||
int afterProcessOt(Map<String, Object> param);
|
||||
int afterProcessLate(Map<String, Object> param);
|
||||
int afterProcessEarlyDep(Map<String, Object> param);
|
||||
int afterProcessAbsence(Map<String, Object> param);
|
||||
int afterProcessWorkChange(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package com.company.gw.tam.service;
|
||||
|
||||
import com.company.gw.common.exception.BizException;
|
||||
import com.company.gw.common.service.AttachService;
|
||||
import com.company.gw.common.service.SequenceService;
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.tam.mapper.ApvdocMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 결재 공통 서비스
|
||||
* 결재 상태코드: 0001=작성중, 0002=결재중, 0003=결재완료, 0004=반려
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ApvdocService {
|
||||
|
||||
public static final String STATUS_WRITING = "0001";
|
||||
public static final String STATUS_APPRING = "0002";
|
||||
public static final String STATUS_APPROVED = "0003";
|
||||
public static final String STATUS_REJECTED = "0004";
|
||||
|
||||
private final ApvdocMapper apvdocMapper;
|
||||
private final AttachService attachService;
|
||||
private final SequenceService sequenceService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 결재문서 조회
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
public Map<String, Object> getApvdocInfo(String corpNo, String aprvlDocId) {
|
||||
Map<String, Object> info = apvdocMapper.getApvdocInfo(param(corpNo, aprvlDocId));
|
||||
if (info == null) throw new BizException("결재문서가 존재하지 않습니다.", HttpStatus.NOT_FOUND);
|
||||
return info;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getApprList(String corpNo, String aprvlDocId) {
|
||||
return apvdocMapper.getApprList(param(corpNo, aprvlDocId));
|
||||
}
|
||||
|
||||
/** 결재문서 + 결재자목록 + 첨부파일 통합 조회 */
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getApvdocInfoAll(String corpNo, String aprvlDocId) {
|
||||
Map<String, Object> info = getApvdocInfo(corpNo, aprvlDocId);
|
||||
info.put("apprList", getApprList(corpNo, aprvlDocId));
|
||||
String atchNo = (String) info.get("ATCH_NO");
|
||||
if (atchNo != null) {
|
||||
info.put("attachFileList", attachService.getFileList(atchNo));
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 결재문서 생성
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public String createApvdoc(String corpNo, String aprvlKindCd,
|
||||
String aplntCn, String bzCn, String offerCn, String bzDeputyId,
|
||||
String atchNo) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
String aprvlDocId = sequenceService.getNextSeqString("SX_GW0090.APRVL_DOC_ID", 10);
|
||||
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
p.put("aprvlKindCd", aprvlKindCd);
|
||||
p.put("aplntCn", aplntCn);
|
||||
p.put("bzCn", bzCn);
|
||||
p.put("offerCn", offerCn);
|
||||
p.put("bzDeputyId", bzDeputyId);
|
||||
p.put("atchNo", atchNo);
|
||||
p.put("usrId", usrId);
|
||||
|
||||
apvdocMapper.insertApvdoc(p);
|
||||
|
||||
if (org.springframework.util.StringUtils.hasText(atchNo)) {
|
||||
attachService.confirmAtchNo(atchNo, "SX_GW0090.ATCH_NO");
|
||||
}
|
||||
|
||||
return aprvlDocId;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateApvdocContent(String corpNo, String aprvlDocId,
|
||||
String aplntCn, String bzCn, String offerCn, String bzDeputyId,
|
||||
String atchNo) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> info = getApvdocInfo(corpNo, aprvlDocId);
|
||||
checkAplnt(info);
|
||||
checkBeforeRequest(info);
|
||||
|
||||
Map<String, Object> p = param(corpNo, aprvlDocId);
|
||||
p.put("aplntCn", aplntCn);
|
||||
p.put("bzCn", bzCn);
|
||||
p.put("offerCn", offerCn);
|
||||
p.put("bzDeputyId", bzDeputyId);
|
||||
p.put("usrId", usrId);
|
||||
apvdocMapper.updateApvdocContent(p);
|
||||
|
||||
if (org.springframework.util.StringUtils.hasText(atchNo)) {
|
||||
Map<String, Object> ap = param(corpNo, aprvlDocId);
|
||||
ap.put("atchNo", atchNo);
|
||||
apvdocMapper.updateApvdocAtchNo(ap);
|
||||
attachService.confirmAtchNo(atchNo, "SX_GW0090.ATCH_NO");
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 결재자 등록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void insertApprList(String corpNo, String aprvlDocId, List<Map<String, Object>> apprList) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> info = getApvdocInfo(corpNo, aprvlDocId);
|
||||
checkBeforeRequest(info);
|
||||
|
||||
apvdocMapper.deleteApprAll(param(corpNo, aprvlDocId));
|
||||
|
||||
int sno = 1;
|
||||
for (Map<String, Object> appr : apprList) {
|
||||
String apprId = (String) appr.get("apprId");
|
||||
if (apprId == null || apprId.isEmpty()) {
|
||||
throw new BizException("결재자가 지정되지 않았습니다.");
|
||||
}
|
||||
Map<String, Object> p = param(corpNo, aprvlDocId);
|
||||
p.put("aprvlSno", sno++);
|
||||
p.put("apprId", apprId);
|
||||
p.put("usrId", usrId);
|
||||
apvdocMapper.insertAppr(p);
|
||||
}
|
||||
apvdocMapper.updateFinalAprvlSno(param(corpNo, aprvlDocId));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 결재 상신
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void requestApvdoc(String corpNo, String aprvlDocId) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
Map<String, Object> info = getApvdocInfo(corpNo, aprvlDocId);
|
||||
checkBeforeRequest(info);
|
||||
|
||||
List<Map<String, Object>> apprList = getApprList(corpNo, aprvlDocId);
|
||||
if (apprList.isEmpty()) throw new BizException("결재자가 지정되지 않았습니다.");
|
||||
|
||||
// 1차 결재자 → 결재중
|
||||
Map<String, Object> p1 = param(corpNo, aprvlDocId);
|
||||
p1.put("aprvlSno", 1);
|
||||
p1.put("apprStusCd", STATUS_APPRING);
|
||||
p1.put("usrId", usrId);
|
||||
apvdocMapper.updateApprStatus(p1);
|
||||
|
||||
// 문서 → 결재중
|
||||
apvdocMapper.updateApvdocStatusRequest(param(corpNo, aprvlDocId));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 승인 / 반려
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void approveApvdoc(String corpNo, String aprvlDocId, int aprvlSno, String apprCn) {
|
||||
processApproveOrReject(corpNo, aprvlDocId, aprvlSno, apprCn, true);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void rejectApvdoc(String corpNo, String aprvlDocId, int aprvlSno, String apprCn) {
|
||||
processApproveOrReject(corpNo, aprvlDocId, aprvlSno, apprCn, false);
|
||||
}
|
||||
|
||||
private void processApproveOrReject(String corpNo, String aprvlDocId,
|
||||
int aprvlSno, String apprCn, boolean isApprove) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
|
||||
Map<String, Object> docInfo = getApvdocInfo(corpNo, aprvlDocId);
|
||||
if (!STATUS_APPRING.equals(docInfo.get("APRVL_STUS_CD"))) {
|
||||
throw new BizException("결재중 상태가 아닙니다.");
|
||||
}
|
||||
|
||||
Map<String, Object> apprParam = param(corpNo, aprvlDocId);
|
||||
apprParam.put("aprvlSno", aprvlSno);
|
||||
Map<String, Object> apprInfo = apvdocMapper.getApprInfo(apprParam);
|
||||
|
||||
if (apprInfo == null) throw new BizException("결재자 정보가 없습니다. (" + aprvlSno + "차)");
|
||||
if (!STATUS_APPRING.equals(apprInfo.get("APPR_STUS_CD"))) throw new BizException("결재중인 상태가 아닙니다.");
|
||||
if (!usrId.equals(apprInfo.get("APPR_ID"))) throw new BizException("결재자가 아닙니다.");
|
||||
|
||||
String apprStusCd = isApprove ? STATUS_APPROVED : STATUS_REJECTED;
|
||||
Map<String, Object> p = param(corpNo, aprvlDocId);
|
||||
p.put("aprvlSno", aprvlSno);
|
||||
p.put("apprStusCd", apprStusCd);
|
||||
p.put("apprCn", apprCn);
|
||||
p.put("usrId", usrId);
|
||||
apvdocMapper.apprApproveOrReject(p);
|
||||
|
||||
if (isApprove) {
|
||||
if ("Y".equals(apprInfo.get("FINAL_APPR_YN"))) {
|
||||
apvdocMapper.updateApvdocStatusApprove(param(corpNo, aprvlDocId));
|
||||
} else {
|
||||
Map<String, Object> nextP = param(corpNo, aprvlDocId);
|
||||
nextP.put("aprvlSno", aprvlSno);
|
||||
nextP.put("usrId", usrId);
|
||||
apvdocMapper.updateNextApprStatusAppring(nextP);
|
||||
}
|
||||
} else {
|
||||
apvdocMapper.updateApvdocStatusReject(param(corpNo, aprvlDocId));
|
||||
apvdocMapper.resetWorkEndDt(param(corpNo, aprvlDocId));
|
||||
}
|
||||
apvdocMapper.updateAprvlCmplSno(param(corpNo, aprvlDocId));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 결재문서 삭제
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional
|
||||
public void deleteApvdoc(String corpNo, String aprvlDocId) {
|
||||
Map<String, Object> info = getApvdocInfo(corpNo, aprvlDocId);
|
||||
checkAplnt(info);
|
||||
Map<String, Object> p = param(corpNo, aprvlDocId);
|
||||
apvdocMapper.deleteApvdocSx0080(p);
|
||||
apvdocMapper.deleteApvdocSx0110(p);
|
||||
apvdocMapper.deleteApvdocSx0090(p);
|
||||
|
||||
String atchNo = (String) info.get("ATCH_NO");
|
||||
if (atchNo != null) attachService.deleteFilesByAtchNo(atchNo, true);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 내부 유틸
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
private Map<String, Object> param(String corpNo, String aprvlDocId) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
return p;
|
||||
}
|
||||
|
||||
private void checkBeforeRequest(Map<String, Object> docInfo) {
|
||||
if (!STATUS_WRITING.equals(docInfo.get("APRVL_STUS_CD"))) {
|
||||
throw new BizException("작성중 상태가 아닙니다.");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAplnt(Map<String, Object> docInfo) {
|
||||
String usrId = SecurityUtil.getUsrId();
|
||||
if (!usrId.equals(docInfo.get("APLNT_ID"))) {
|
||||
throw new BizException("신청자가 아닙니다.", HttpStatus.FORBIDDEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
315
backend/src/main/java/com/company/gw/tam/service/TamService.java
Normal file
315
backend/src/main/java/com/company/gw/tam/service/TamService.java
Normal file
@@ -0,0 +1,315 @@
|
||||
package com.company.gw.tam.service;
|
||||
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.tam.mapper.TamMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TamService {
|
||||
|
||||
private final TamMapper tamMapper;
|
||||
private final ApvdocService apvdocService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0010 - 연차 관리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getYyvctList(String corpNo, String yyvctYy,
|
||||
String usrNm, String teamCd,
|
||||
String includeRetireYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("yyvctYy", yyvctYy);
|
||||
p.put("usrNm", usrNm);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("includeRetireYn", includeRetireYn != null ? includeRetireYn : "N");
|
||||
return tamMapper.getYyvctList(p);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void saveYyvct(String corpNo, String yyvctYy, String usrId, int yyvctCnt) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("yyvctYy", yyvctYy);
|
||||
p.put("usrId", usrId);
|
||||
p.put("yyvctCnt", yyvctCnt);
|
||||
p.put("loginUsrId", SecurityUtil.getUsrId());
|
||||
tamMapper.upsertYyvct(p);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteYyvct(String corpNo, String yyvctYy, String usrId) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("yyvctYy", yyvctYy);
|
||||
p.put("usrId", usrId);
|
||||
tamMapper.deleteYyvct(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0020 - 결재 신청 목록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getApvreqList(String corpNo, Map<String, Object> filter) {
|
||||
filter.put("corpNo", corpNo);
|
||||
filter.put("usrId", SecurityUtil.getUsrId());
|
||||
filter.put("pageNo", Integer.parseInt(filter.getOrDefault("pageNo", "1").toString()));
|
||||
filter.put("pageSize", Integer.parseInt(filter.getOrDefault("pageSize", "20").toString()));
|
||||
if (!filter.containsKey("staYmd") || filter.get("staYmd") == null || filter.get("staYmd").toString().isEmpty())
|
||||
filter.put("staYmd", "00000000");
|
||||
if (!filter.containsKey("endYmd") || filter.get("endYmd") == null || filter.get("endYmd").toString().isEmpty())
|
||||
filter.put("endYmd", "99999999");
|
||||
|
||||
List<Map<String, Object>> list = tamMapper.getApvreqList(filter);
|
||||
long total = tamMapper.getApvreqListCount(filter);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 결재 신청 상세 (문서 + 결재자 + 첨부 + 세부항목) */
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getApvreqDetail(String corpNo, String aprvlDocId) {
|
||||
Map<String, Object> info = apvdocService.getApvdocInfoAll(corpNo, aprvlDocId);
|
||||
|
||||
// 변경근무 목록
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
info.put("workChangeList", tamMapper.getWorkChangeList(p));
|
||||
info.put("otInfo", tamMapper.getOtInfo(p));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/** 결재 신청 생성 */
|
||||
@Transactional
|
||||
public String createApvreq(String corpNo, Map<String, Object> body) {
|
||||
String aprvlDocId = apvdocService.createApvdoc(
|
||||
corpNo,
|
||||
(String) body.get("aprvlKindCd"),
|
||||
(String) body.get("aplntCn"),
|
||||
(String) body.get("bzCn"),
|
||||
(String) body.get("offerCn"),
|
||||
(String) body.get("bzDeputyId"),
|
||||
(String) body.get("atchNo")
|
||||
);
|
||||
|
||||
// 세부 항목 등록
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
p.put("usrId", SecurityUtil.getUsrId());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> workChangeList = (List<Map<String, Object>>) body.get("workChangeList");
|
||||
if (workChangeList != null) {
|
||||
for (Map<String, Object> item : workChangeList) {
|
||||
Map<String, Object> ip = new HashMap<>(p);
|
||||
ip.putAll(item);
|
||||
tamMapper.insertSxGw0110(ip);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> otInfo = (Map<String, Object>) body.get("otInfo");
|
||||
if (otInfo != null) {
|
||||
Map<String, Object> ip = new HashMap<>(p);
|
||||
ip.putAll(otInfo);
|
||||
tamMapper.insertSxGw0080(ip);
|
||||
}
|
||||
|
||||
return aprvlDocId;
|
||||
}
|
||||
|
||||
/** 결재 신청 수정 */
|
||||
@Transactional
|
||||
public void updateApvreq(String corpNo, String aprvlDocId, Map<String, Object> body) {
|
||||
apvdocService.updateApvdocContent(corpNo, aprvlDocId,
|
||||
(String) body.get("aplntCn"), (String) body.get("bzCn"),
|
||||
(String) body.get("offerCn"), (String) body.get("bzDeputyId"),
|
||||
(String) body.get("atchNo"));
|
||||
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
p.put("usrId", SecurityUtil.getUsrId());
|
||||
|
||||
tamMapper.deleteSxGw0110(p);
|
||||
tamMapper.deleteSxGw0080(p);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> workChangeList = (List<Map<String, Object>>) body.get("workChangeList");
|
||||
if (workChangeList != null) {
|
||||
for (Map<String, Object> item : workChangeList) {
|
||||
Map<String, Object> ip = new HashMap<>(p);
|
||||
ip.putAll(item);
|
||||
tamMapper.insertSxGw0110(ip);
|
||||
}
|
||||
}
|
||||
Map<String, Object> otInfo = (Map<String, Object>) body.get("otInfo");
|
||||
if (otInfo != null) {
|
||||
Map<String, Object> ip = new HashMap<>(p);
|
||||
ip.putAll(otInfo);
|
||||
tamMapper.insertSxGw0080(ip);
|
||||
}
|
||||
}
|
||||
|
||||
/** 결재 상신 (결재자 등록 + 상신) */
|
||||
@Transactional
|
||||
public void requestApvreq(String corpNo, String aprvlDocId, List<Map<String, Object>> apprList) {
|
||||
apvdocService.insertApprList(corpNo, aprvlDocId, apprList);
|
||||
apvdocService.requestApvdoc(corpNo, aprvlDocId);
|
||||
}
|
||||
|
||||
/** 결재문서 삭제 */
|
||||
@Transactional
|
||||
public void deleteApvreq(String corpNo, String aprvlDocId) {
|
||||
apvdocService.deleteApvdoc(corpNo, aprvlDocId);
|
||||
}
|
||||
|
||||
/** 최근 결재자 목록 조회 */
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getLatestApprList(String corpNo) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("usrId", SecurityUtil.getUsrId());
|
||||
return tamMapper.getLatestApprList(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0030 - 결재 처리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getApvappList(String corpNo, Map<String, Object> filter) {
|
||||
filter.put("corpNo", corpNo);
|
||||
filter.put("usrId", SecurityUtil.getUsrId());
|
||||
filter.put("pageNo", Integer.parseInt(filter.getOrDefault("pageNo", "1").toString()));
|
||||
filter.put("pageSize", Integer.parseInt(filter.getOrDefault("pageSize", "20").toString()));
|
||||
|
||||
List<Map<String, Object>> list = tamMapper.getApvappList(filter);
|
||||
long total = tamMapper.getApvappListCount(filter);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("list", list);
|
||||
result.put("total", total);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 결재 처리 상세 */
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getApvappDetail(String corpNo, String aprvlDocId) {
|
||||
return apvdocService.getApvdocInfoAll(corpNo, aprvlDocId);
|
||||
}
|
||||
|
||||
/** 승인 처리 (최종 승인 시 executeAfterProcess 호출) */
|
||||
@Transactional
|
||||
public void approveApvdoc(String corpNo, String aprvlDocId, int aprvlSno, String apprCn) {
|
||||
// 승인 전 문서 정보 (aplntId, aprvlKindCd 필요)
|
||||
Map<String, Object> docBefore = apvdocService.getApvdocInfo(corpNo, aprvlDocId);
|
||||
apvdocService.approveApvdoc(corpNo, aprvlDocId, aprvlSno, apprCn);
|
||||
// 최종 승인 여부 확인
|
||||
Map<String, Object> docAfter = apvdocService.getApvdocInfo(corpNo, aprvlDocId);
|
||||
if (ApvdocService.STATUS_APPROVED.equals(docAfter.get("APRVL_STUS_CD"))) {
|
||||
executeAfterProcess(corpNo, aprvlDocId,
|
||||
(String) docBefore.get("APRVL_KIND_CD"),
|
||||
(String) docBefore.get("APLNT_ID"));
|
||||
}
|
||||
}
|
||||
|
||||
/** 반려 처리 */
|
||||
@Transactional
|
||||
public void rejectApvdoc(String corpNo, String aprvlDocId, int aprvlSno, String apprCn) {
|
||||
apvdocService.rejectApvdoc(corpNo, aprvlDocId, aprvlSno, apprCn);
|
||||
}
|
||||
|
||||
/** 일괄 승인 */
|
||||
@Transactional
|
||||
public void multiApprove(String corpNo, List<Map<String, Object>> items, String apprCn) {
|
||||
for (Map<String, Object> item : items) {
|
||||
String aprvlDocId = (String) item.get("aprvlDocId");
|
||||
int aprvlSno = Integer.parseInt(item.get("aprvlSno").toString());
|
||||
try {
|
||||
approveApvdoc(corpNo, aprvlDocId, aprvlSno, apprCn);
|
||||
} catch (Exception e) {
|
||||
// 일괄 처리 중 개별 실패는 무시하고 계속 진행
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 일괄 반려 */
|
||||
@Transactional
|
||||
public void multiReject(String corpNo, List<Map<String, Object>> items, String apprCn) {
|
||||
for (Map<String, Object> item : items) {
|
||||
String aprvlDocId = (String) item.get("aprvlDocId");
|
||||
int aprvlSno = Integer.parseInt(item.get("aprvlSno").toString());
|
||||
try {
|
||||
rejectApvdoc(corpNo, aprvlDocId, aprvlSno, apprCn);
|
||||
} catch (Exception e) {
|
||||
// 일괄 처리 중 개별 실패는 무시하고 계속 진행
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 최종 승인 후처리 - 결재 종류별 근무 데이터 업데이트 */
|
||||
private void executeAfterProcess(String corpNo, String aprvlDocId,
|
||||
String aprvlKindCd, String aplntId) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("aprvlDocId", aprvlDocId);
|
||||
p.put("aplntId", aplntId);
|
||||
|
||||
switch (aprvlKindCd != null ? aprvlKindCd : "") {
|
||||
case "0001": // 시간외 → OT_RCTN_YN='Y'
|
||||
tamMapper.afterProcessOt(p);
|
||||
break;
|
||||
case "0002": // 지각 → WORK_START_DT 보정
|
||||
tamMapper.afterProcessLate(p);
|
||||
break;
|
||||
case "0003": // 조퇴 → WORK_END_DT 보정 + EL_RCTN_YN='Y'
|
||||
tamMapper.afterProcessEarlyDep(p);
|
||||
break;
|
||||
case "0004": // 결근 → 출퇴근 모두 보정
|
||||
tamMapper.afterProcessAbsence(p);
|
||||
break;
|
||||
case "0005": // 연차 → WORK_CD 변경
|
||||
case "0006": // 근무변경 → WORK_CD 변경
|
||||
tamMapper.afterProcessWorkChange(p);
|
||||
break;
|
||||
case "0008": // 외출 → OUTING_MIN/CNT 업데이트
|
||||
tamMapper.updateOutingTime(p);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// TAM0040 - 근태 현황
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getTamStatusList(String corpNo, String yyvctYy,
|
||||
String teamCd, String staYmd,
|
||||
String endYmd, String includeRetireYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("yyvctYy", yyvctYy);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("staYmd", staYmd);
|
||||
p.put("endYmd", endYmd);
|
||||
p.put("includeRetireYn", includeRetireYn != null ? includeRetireYn : "N");
|
||||
return tamMapper.getTamStatusList(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.company.gw.wplan.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.wplan.service.WplanService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/wplan")
|
||||
@RequiredArgsConstructor
|
||||
public class WplanController {
|
||||
|
||||
private final WplanService wplanService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 근무코드 목록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/workcode")
|
||||
public ApiResponse<List<Map<String, Object>>> getWorkCodeList(
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wplanService.getWorkCodeList(currentUser.getCorpNo()));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0010 - 근무계획관리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/0010")
|
||||
public ApiResponse<List<Map<String, Object>>> getWplanList(
|
||||
@RequestParam String workPlanYymm,
|
||||
@RequestParam(defaultValue = "") String searchText,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wplanService.getWplanList(
|
||||
currentUser.getCorpNo(), workPlanYymm, searchText, teamCd, includeRetireYn));
|
||||
}
|
||||
|
||||
@PostMapping("/0010")
|
||||
public ApiResponse<Void> saveWplanList(
|
||||
@RequestBody Map<String, Object> body,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> saveList = (List<Map<String, Object>>) body.get("saveList");
|
||||
wplanService.saveWplanList(currentUser.getCorpNo(), saveList);
|
||||
return ApiResponse.ok(null);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0020 - 나의 근무계획
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/0020")
|
||||
public ApiResponse<List<Map<String, Object>>> getMyWplanList(
|
||||
@RequestParam String workPlanYymm,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wplanService.getMyWplanList(currentUser.getCorpNo(), workPlanYymm));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0030 - 전체 근무계획
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/0030")
|
||||
public ApiResponse<List<Map<String, Object>>> getAllWplanList(
|
||||
@RequestParam String workPlanYymm,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "") String dutyCd,
|
||||
@RequestParam(defaultValue = "") String workCd,
|
||||
@RequestParam(defaultValue = "WORK_CD") String workCdType,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wplanService.getAllWplanList(
|
||||
currentUser.getCorpNo(), workPlanYymm, teamCd, dutyCd, workCd, workCdType));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.company.gw.wplan.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface WplanMapper {
|
||||
|
||||
// 근무코드 목록
|
||||
List<Map<String, Object>> getWorkCodeList(Map<String, Object> param);
|
||||
|
||||
// Wplan0010 - 근무계획관리
|
||||
List<Map<String, Object>> getWplanList(Map<String, Object> param);
|
||||
|
||||
// Wplan0020 - 나의 근무계획
|
||||
List<Map<String, Object>> getMyWplanList(Map<String, Object> param);
|
||||
|
||||
// Wplan0030 - 전체 근무계획
|
||||
List<Map<String, Object>> getAllWplanList(Map<String, Object> param);
|
||||
|
||||
// 저장/삭제
|
||||
void upsertWorkplan(Map<String, Object> param);
|
||||
void deleteWorkplan(Map<String, Object> param);
|
||||
void deleteWorkplanMonth(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.company.gw.wplan.service;
|
||||
|
||||
import com.company.gw.common.util.SecurityUtil;
|
||||
import com.company.gw.wplan.mapper.WplanMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WplanService {
|
||||
|
||||
private final WplanMapper wplanMapper;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// 근무코드 목록
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getWorkCodeList(String corpNo) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
return wplanMapper.getWorkCodeList(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0010 - 근무계획관리
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getWplanList(String corpNo, String workPlanYymm,
|
||||
String searchText, String teamCd,
|
||||
String includeRetireYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("workPlanYymm", workPlanYymm);
|
||||
p.put("searchText", searchText);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("includeRetireYn", includeRetireYn != null ? includeRetireYn : "N");
|
||||
return wplanMapper.getWplanList(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* 근무계획 일괄 저장
|
||||
* saveList: [{usrId, workPlanYymmdd, planWorkCd, sortOdr}]
|
||||
*/
|
||||
@Transactional
|
||||
public void saveWplanList(String corpNo, List<Map<String, Object>> saveList) {
|
||||
String loginUsrId = SecurityUtil.getUsrId();
|
||||
for (Map<String, Object> item : saveList) {
|
||||
Map<String, Object> p = new HashMap<>(item);
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("loginUsrId", loginUsrId);
|
||||
String planWorkCd = (String) p.get("planWorkCd");
|
||||
if (planWorkCd == null || planWorkCd.isEmpty()) {
|
||||
wplanMapper.deleteWorkplan(p);
|
||||
} else {
|
||||
wplanMapper.upsertWorkplan(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0020 - 나의 근무계획
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getMyWplanList(String corpNo, String workPlanYymm) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("usrId", SecurityUtil.getUsrId());
|
||||
p.put("workPlanYymm", workPlanYymm);
|
||||
return wplanMapper.getMyWplanList(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wplan0030 - 전체 근무계획
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getAllWplanList(String corpNo, String workPlanYymm,
|
||||
String teamCd, String dutyCd,
|
||||
String workCd, String workCdType) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("workPlanYymm", workPlanYymm);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("dutyCd", dutyCd);
|
||||
p.put("workCd", workCd);
|
||||
p.put("workCdType", workCdType != null ? workCdType : "WORK_CD");
|
||||
return wplanMapper.getAllWplanList(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.company.gw.wtime.controller;
|
||||
|
||||
import com.company.gw.common.dto.ApiResponse;
|
||||
import com.company.gw.common.dto.CurrentUser;
|
||||
import com.company.gw.wtime.service.WtimeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/wtime")
|
||||
@RequiredArgsConstructor
|
||||
public class WtimeController {
|
||||
|
||||
private final WtimeService wtimeService;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wtime0010 - 개인별 근무시간
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/0010")
|
||||
public ApiResponse<List<Map<String, Object>>> getWtimeList(
|
||||
@RequestParam String staYmd,
|
||||
@RequestParam String endYmd,
|
||||
@RequestParam(defaultValue = "") String usrId,
|
||||
@RequestParam(defaultValue = "") String usrNm,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "") String dutyCd,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@RequestParam(defaultValue = "") String includeWorkYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wtimeService.getWtimeList(
|
||||
currentUser.getCorpNo(), staYmd, endYmd,
|
||||
usrId, usrNm, teamCd, dutyCd, includeRetireYn, includeWorkYn));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wtime0030 - 월별 근무시간 집계
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/0030")
|
||||
public ApiResponse<List<Map<String, Object>>> getWstatList(
|
||||
@RequestParam String staYmd,
|
||||
@RequestParam String endYmd,
|
||||
@RequestParam(defaultValue = "") String usrId,
|
||||
@RequestParam(defaultValue = "") String usrNm,
|
||||
@RequestParam(defaultValue = "") String teamCd,
|
||||
@RequestParam(defaultValue = "") String dutyCd,
|
||||
@RequestParam(defaultValue = "N") String includeRetireYn,
|
||||
@AuthenticationPrincipal CurrentUser currentUser) {
|
||||
return ApiResponse.ok(wtimeService.getWstatList(
|
||||
currentUser.getCorpNo(), staYmd, endYmd,
|
||||
usrId, usrNm, teamCd, dutyCd, includeRetireYn));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.company.gw.wtime.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface WtimeMapper {
|
||||
|
||||
// Wtime0010 - 개인별 근무시간
|
||||
List<Map<String, Object>> getWtimeList(Map<String, Object> param);
|
||||
|
||||
// Wtime0030 - 월별 근무시간 집계
|
||||
List<Map<String, Object>> getWstatList(Map<String, Object> param);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.company.gw.wtime.service;
|
||||
|
||||
import com.company.gw.wtime.mapper.WtimeMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WtimeService {
|
||||
|
||||
private final WtimeMapper wtimeMapper;
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wtime0010 - 개인별 근무시간
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getWtimeList(String corpNo, String staYmd, String endYmd,
|
||||
String usrId, String usrNm, String teamCd,
|
||||
String dutyCd, String includeRetireYn,
|
||||
String includeWorkYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("staYmd", staYmd);
|
||||
p.put("endYmd", endYmd);
|
||||
p.put("usrId", usrId);
|
||||
p.put("usrNm", usrNm);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("dutyCd", dutyCd);
|
||||
p.put("includeRetireYn", includeRetireYn != null ? includeRetireYn : "N");
|
||||
p.put("includeWorkYn", includeWorkYn);
|
||||
return wtimeMapper.getWtimeList(p);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────
|
||||
// Wtime0030 - 월별 근무시간 집계
|
||||
// ──────────────────────────────────────────────
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Map<String, Object>> getWstatList(String corpNo, String staYmd, String endYmd,
|
||||
String usrId, String usrNm, String teamCd,
|
||||
String dutyCd, String includeRetireYn) {
|
||||
Map<String, Object> p = new HashMap<>();
|
||||
p.put("corpNo", corpNo);
|
||||
p.put("staYmd", staYmd);
|
||||
p.put("endYmd", endYmd);
|
||||
p.put("usrId", usrId);
|
||||
p.put("usrNm", usrNm);
|
||||
p.put("teamCd", teamCd);
|
||||
p.put("dutyCd", dutyCd);
|
||||
p.put("includeRetireYn", includeRetireYn != null ? includeRetireYn : "N");
|
||||
return wtimeMapper.getWstatList(p);
|
||||
}
|
||||
}
|
||||
17
backend/src/main/resources/application-mariadb.yml
Normal file
17
backend/src/main/resources/application-mariadb.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# MariaDB 설정 (추후 전환용)
|
||||
spring:
|
||||
datasource:
|
||||
url: ${DB_URL:jdbc:mariadb://localhost:3306/gw}
|
||||
username: ${DB_USERNAME:}
|
||||
password: ${DB_PASSWORD:}
|
||||
driver-class-name: org.mariadb.jdbc.Driver
|
||||
hikari:
|
||||
maximum-pool-size: 20
|
||||
minimum-idle: 5
|
||||
connection-timeout: 30000
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
mybatis:
|
||||
configuration:
|
||||
database-id: mariadb
|
||||
13
backend/src/main/resources/application-mssql.yml
Normal file
13
backend/src/main/resources/application-mssql.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
# MS SQL Server 설정 (현재 운영)
|
||||
spring:
|
||||
datasource:
|
||||
url: ${DB_URL:jdbc:sqlserver://121.156.116.136:52785;databaseName=logins_test;encrypt=false;trustServerCertificate=true;sendStringParametersAsUnicode=false}
|
||||
username: ${DB_USERNAME:logins}
|
||||
password: ${DB_PASSWORD:ghkfkdahrfh40-8}
|
||||
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
hikari:
|
||||
maximum-pool-size: 20
|
||||
minimum-idle: 5
|
||||
connection-timeout: 30000
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
17
backend/src/main/resources/application-oracle.yml
Normal file
17
backend/src/main/resources/application-oracle.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# Oracle DB 설정 (현재 운영)
|
||||
spring:
|
||||
datasource:
|
||||
url: ${DB_URL:jdbc:oracle:thin:@localhost:1521:ORCL}
|
||||
username: ${DB_USERNAME:}
|
||||
password: ${DB_PASSWORD:}
|
||||
driver-class-name: oracle.jdbc.OracleDriver
|
||||
hikari:
|
||||
maximum-pool-size: 20
|
||||
minimum-idle: 5
|
||||
connection-timeout: 30000
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
mybatis:
|
||||
configuration:
|
||||
database-id: oracle
|
||||
62
backend/src/main/resources/application.yml
Normal file
62
backend/src/main/resources/application.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
spring:
|
||||
application:
|
||||
name: gw-backend
|
||||
|
||||
# Active Profile: mssql | mariadb
|
||||
profiles:
|
||||
active: mssql
|
||||
|
||||
# Redis
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
|
||||
# RabbitMQ
|
||||
rabbitmq:
|
||||
host: ${RABBITMQ_HOST:localhost}
|
||||
port: ${RABBITMQ_PORT:5672}
|
||||
username: ${RABBITMQ_USER:guest}
|
||||
password: ${RABBITMQ_PASSWORD:guest}
|
||||
|
||||
# File Upload
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 50MB
|
||||
max-request-size: 100MB
|
||||
|
||||
# MyBatis
|
||||
mybatis:
|
||||
mapper-locations: classpath:mapper/**/*.xml
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
default-fetch-size: 100
|
||||
default-statement-timeout: 30
|
||||
|
||||
# JWT
|
||||
jwt:
|
||||
secret: ${JWT_SECRET:your-secret-key-must-be-at-least-256-bits-long-for-hs256}
|
||||
access-token-expiry: 1800000 # 30분 (ms)
|
||||
refresh-token-expiry: 604800000 # 7일 (ms)
|
||||
|
||||
# File Storage
|
||||
file:
|
||||
upload-path: ${FILE_UPLOAD_PATH:/data/uploads}
|
||||
|
||||
# Actuator
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info
|
||||
base-path: /actuator
|
||||
endpoint:
|
||||
health:
|
||||
show-details: when-authorized
|
||||
|
||||
# Logging
|
||||
logging:
|
||||
level:
|
||||
com.company.gw: DEBUG
|
||||
org.mybatis: DEBUG
|
||||
85
backend/src/main/resources/logback-spring.xml
Normal file
85
backend/src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="gw-backend"/>
|
||||
|
||||
<!-- ── 패턴 ── -->
|
||||
<property name="LOG_PATTERN"
|
||||
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- ── 콘솔 ── -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- ── 파일 (Rolling) ── -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/var/log/${APP_NAME}/app.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 날짜별 롤링, 최대 30일 보관 -->
|
||||
<fileNamePattern>/var/log/${APP_NAME}/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<timeBasedFileNamingAndTriggeringPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>3GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- ── 에러 전용 파일 ── -->
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/var/log/${APP_NAME}/error.log</file>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>ERROR</level>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>/var/log/${APP_NAME}/error.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- ── 레벨 설정 ── -->
|
||||
|
||||
<!-- 로컬 개발: 콘솔만, DEBUG (mssql/mariadb는 DB 프로파일이므로 local 여부로 판단) -->
|
||||
<springProfile name="local">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
<logger name="com.company.gw" level="DEBUG"/>
|
||||
<logger name="org.mybatis" level="DEBUG"/>
|
||||
<logger name="jdbc.sqltiming" level="DEBUG"/>
|
||||
</springProfile>
|
||||
|
||||
<!-- 운영: 파일 + 콘솔, INFO -->
|
||||
<springProfile name="prod">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="ERROR_FILE"/>
|
||||
</root>
|
||||
<logger name="com.company.gw" level="INFO"/>
|
||||
<logger name="org.mybatis" level="WARN"/>
|
||||
<logger name="org.apache.ibatis" level="WARN"/>
|
||||
</springProfile>
|
||||
|
||||
<!-- 기본 (local/prod 아닐 때) -->
|
||||
<springProfile name="!local && !prod">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
<logger name="com.company.gw" level="INFO"/>
|
||||
</springProfile>
|
||||
|
||||
</configuration>
|
||||
339
backend/src/main/resources/mapper/board/board_sql.xml
Normal file
339
backend/src/main/resources/mapper/board/board_sql.xml
Normal file
@@ -0,0 +1,339 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/biz/board/board0010_sql.xml
|
||||
테이블: SX_GW0020(게시물), SX_GW0030(댓글), SX_GW0010(사용자) -->
|
||||
<mapper namespace="com.company.gw.board.mapper.BoardMapper">
|
||||
|
||||
<!-- ===================== MSSQL (default) ===================== -->
|
||||
|
||||
<!-- 게시물 목록 (페이징) -->
|
||||
<select id="getPostList" parameterType="map" resultType="map">
|
||||
SELECT A.UNTY_BBS_SNO,
|
||||
A.BBS_TITLE_NM,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
A.CTUSR_ID,
|
||||
B.USR_NM AS CTUSR_NM,
|
||||
CONVERT(VARCHAR, A.RGST_DT, 112) AS RGST_DT
|
||||
FROM SX_GW0020 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND (#{searchText} IS NULL OR #{searchText} = ''
|
||||
OR A.BBS_TITLE_NM LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR CAST(A.BBS_CN AS VARCHAR(MAX)) LIKE CONCAT('%', #{searchText}, '%'))
|
||||
ORDER BY A.RGST_DT DESC, A.UNTY_BBS_SNO DESC
|
||||
OFFSET (#{pageNo} - 1) * #{pageSize} ROWS
|
||||
FETCH NEXT #{pageSize} ROWS ONLY
|
||||
</select>
|
||||
|
||||
<!-- 게시물 목록 건수 -->
|
||||
<select id="getPostListCount" parameterType="map" resultType="long">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0020 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND (#{searchText} IS NULL OR #{searchText} = ''
|
||||
OR A.BBS_TITLE_NM LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR CAST(A.BBS_CN AS VARCHAR(MAX)) LIKE CONCAT('%', #{searchText}, '%'))
|
||||
</select>
|
||||
|
||||
<!-- 게시물 상세 -->
|
||||
<select id="getPostInfo" parameterType="map" resultType="map">
|
||||
SELECT A.UNTY_BBS_CD,
|
||||
A.UNTY_BBS_SNO,
|
||||
A.BBS_TITLE_NM,
|
||||
A.BBS_CN,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
A.CTUSR_ID,
|
||||
A.ETC_ATCH_NO,
|
||||
A.PHOTO_ATCH_NO,
|
||||
A.RGSTR_ID,
|
||||
CONVERT(VARCHAR, A.RGST_DT, 120) AS RGST_DATE,
|
||||
CONVERT(VARCHAR, A.UPD_DT, 120) AS UPD_DATE,
|
||||
B.USR_NM AS CTUSR_NM
|
||||
FROM SX_GW0020 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND A.UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</select>
|
||||
|
||||
<!-- 게시물 등록 -->
|
||||
<insert id="insertPost" parameterType="map">
|
||||
INSERT INTO SX_GW0020 (
|
||||
CORP_NO, UNTY_BBS_CD, UNTY_BBS_SNO,
|
||||
BBS_TITLE_NM, BBS_CN, INQR_CNT,
|
||||
CTUSR_ID, RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{untyBbsCd}, #{untyBbsSno},
|
||||
#{bbsTitleNm}, #{bbsCn}, 0,
|
||||
#{usrId}, #{usrId}, GETDATE(), #{usrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 게시물 수정 -->
|
||||
<update id="updatePost" parameterType="map">
|
||||
UPDATE SX_GW0020
|
||||
SET BBS_TITLE_NM = #{bbsTitleNm},
|
||||
BBS_CN = #{bbsCn},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<!-- 조회수 증가 -->
|
||||
<update id="increaseInqrCnt" parameterType="map">
|
||||
UPDATE SX_GW0020
|
||||
SET INQR_CNT = ISNULL(INQR_CNT, 0) + 1
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<!-- 기타첨부 번호 업데이트 -->
|
||||
<update id="updateEtcAtchNo" parameterType="map">
|
||||
UPDATE SX_GW0020
|
||||
SET ETC_ATCH_NO = #{etcAtchNo},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<!-- 사진첨부 번호 업데이트 -->
|
||||
<update id="updatePhotoAtchNo" parameterType="map">
|
||||
UPDATE SX_GW0020
|
||||
SET PHOTO_ATCH_NO = #{photoAtchNo},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<!-- 댓글수 재계산 -->
|
||||
<update id="updateCmmtCnt" parameterType="map">
|
||||
UPDATE SX_GW0020
|
||||
SET CMMT_CNT = (
|
||||
SELECT COUNT(1) FROM SX_GW0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
),
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<!-- 게시물 삭제 -->
|
||||
<delete id="deletePost" parameterType="map">
|
||||
DELETE FROM SX_GW0020
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</delete>
|
||||
|
||||
<!-- 댓글 목록 -->
|
||||
<select id="getCommentList" parameterType="map" resultType="map">
|
||||
SELECT A.CMMT_SNO,
|
||||
A.CMMT_CN,
|
||||
A.CMMT_CTUSR_ID,
|
||||
B.USR_NM AS CMMT_CTUSR_NM,
|
||||
CONVERT(VARCHAR, A.RGST_DT, 120) AS RGST_DATE
|
||||
FROM SX_GW0030 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CMMT_CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND A.UNTY_BBS_SNO = #{untyBbsSno}
|
||||
ORDER BY A.RGST_DT, A.CMMT_SNO
|
||||
</select>
|
||||
|
||||
<!-- 댓글 상세 -->
|
||||
<select id="getCommentInfo" parameterType="map" resultType="map">
|
||||
SELECT A.CMMT_SNO, A.CMMT_CN, A.CMMT_CTUSR_ID
|
||||
FROM SX_GW0030 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND A.UNTY_BBS_SNO = #{untyBbsSno}
|
||||
AND A.CMMT_SNO = #{cmmtSno}
|
||||
</select>
|
||||
|
||||
<!-- 댓글 등록 -->
|
||||
<insert id="insertComment" parameterType="map">
|
||||
INSERT INTO SX_GW0030 (
|
||||
CORP_NO, UNTY_BBS_CD, UNTY_BBS_SNO, CMMT_SNO,
|
||||
CMMT_CN, CMMT_CTUSR_ID, RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{untyBbsCd}, #{untyBbsSno}, #{cmmtSno},
|
||||
#{cmmtCn}, #{usrId}, #{usrId}, GETDATE(), #{usrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 댓글 삭제 -->
|
||||
<delete id="deleteComment" parameterType="map">
|
||||
DELETE FROM SX_GW0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
AND CMMT_SNO = #{cmmtSno}
|
||||
</delete>
|
||||
|
||||
<!-- 게시물 전체 댓글 삭제 (게시물 삭제시) -->
|
||||
<delete id="deleteCommentsByPost" parameterType="map">
|
||||
DELETE FROM SX_GW0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</delete>
|
||||
|
||||
<!-- ===================== MariaDB ===================== -->
|
||||
|
||||
<select id="getPostList" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.UNTY_BBS_SNO,
|
||||
A.BBS_TITLE_NM,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
A.CTUSR_ID,
|
||||
B.USR_NM AS CTUSR_NM,
|
||||
DATE_FORMAT(A.RGST_DT, '%Y%m%d') AS RGST_DT
|
||||
FROM SX_GW0020 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND (#{searchText} IS NULL OR #{searchText} = ''
|
||||
OR A.BBS_TITLE_NM LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR CAST(A.BBS_CN AS CHAR) LIKE CONCAT('%', #{searchText}, '%'))
|
||||
ORDER BY A.RGST_DT DESC, A.UNTY_BBS_SNO DESC
|
||||
LIMIT #{pageSize} OFFSET (#{pageNo} - 1) * #{pageSize}
|
||||
</select>
|
||||
|
||||
<select id="getPostListCount" parameterType="map" resultType="long" databaseId="mariadb">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0020 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND (#{searchText} IS NULL OR #{searchText} = ''
|
||||
OR A.BBS_TITLE_NM LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR CAST(A.BBS_CN AS CHAR) LIKE CONCAT('%', #{searchText}, '%'))
|
||||
</select>
|
||||
|
||||
<select id="getPostInfo" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.UNTY_BBS_CD,
|
||||
A.UNTY_BBS_SNO,
|
||||
A.BBS_TITLE_NM,
|
||||
A.BBS_CN,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
A.CTUSR_ID,
|
||||
A.ETC_ATCH_NO,
|
||||
A.PHOTO_ATCH_NO,
|
||||
A.RGSTR_ID,
|
||||
DATE_FORMAT(A.RGST_DT, '%Y-%m-%d %H:%i:%s') AS RGST_DATE,
|
||||
DATE_FORMAT(A.UPD_DT, '%Y-%m-%d %H:%i:%s') AS UPD_DATE,
|
||||
B.USR_NM AS CTUSR_NM
|
||||
FROM SX_GW0020 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND A.UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</select>
|
||||
|
||||
<insert id="insertPost" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0020 (
|
||||
CORP_NO, UNTY_BBS_CD, UNTY_BBS_SNO,
|
||||
BBS_TITLE_NM, BBS_CN, INQR_CNT,
|
||||
CTUSR_ID, RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{untyBbsCd}, #{untyBbsSno},
|
||||
#{bbsTitleNm}, #{bbsCn}, 0,
|
||||
#{usrId}, #{usrId}, NOW(), #{usrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updatePost" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0020
|
||||
SET BBS_TITLE_NM = #{bbsTitleNm},
|
||||
BBS_CN = #{bbsCn},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<update id="increaseInqrCnt" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0020
|
||||
SET INQR_CNT = IFNULL(INQR_CNT, 0) + 1
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<update id="updateEtcAtchNo" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0020
|
||||
SET ETC_ATCH_NO = #{etcAtchNo},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<update id="updatePhotoAtchNo" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0020
|
||||
SET PHOTO_ATCH_NO = #{photoAtchNo},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<update id="updateCmmtCnt" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0020
|
||||
SET CMMT_CNT = (
|
||||
SELECT COUNT(1) FROM SX_GW0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
),
|
||||
MODID = #{usrId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND UNTY_BBS_SNO = #{untyBbsSno}
|
||||
</update>
|
||||
|
||||
<insert id="insertComment" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0030 (
|
||||
CORP_NO, UNTY_BBS_CD, UNTY_BBS_SNO, CMMT_SNO,
|
||||
CMMT_CN, CMMT_CTUSR_ID, RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{untyBbsCd}, #{untyBbsSno}, #{cmmtSno},
|
||||
#{cmmtCn}, #{usrId}, #{usrId}, NOW(), #{usrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<select id="getCommentList" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.CMMT_SNO,
|
||||
A.CMMT_CN,
|
||||
A.CMMT_CTUSR_ID,
|
||||
B.USR_NM AS CMMT_CTUSR_NM,
|
||||
DATE_FORMAT(A.RGST_DT, '%Y-%m-%d %H:%i:%s') AS RGST_DATE
|
||||
FROM SX_GW0030 A
|
||||
LEFT JOIN SX_GW0010 B ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.CMMT_CTUSR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{untyBbsCd}
|
||||
AND A.UNTY_BBS_SNO = #{untyBbsSno}
|
||||
ORDER BY A.RGST_DT, A.CMMT_SNO
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
111
backend/src/main/resources/mapper/common/attach_sql.xml
Normal file
111
backend/src/main/resources/mapper/common/attach_sql.xml
Normal file
@@ -0,0 +1,111 @@
|
||||
<?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="com.company.gw.common.mapper.AttachMapper">
|
||||
|
||||
<!-- ===================== MSSQL (default) ===================== -->
|
||||
|
||||
<select id="getFileInfo" parameterType="string" resultType="map">
|
||||
SELECT ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, TBL_COL_NM, RGSTR_ID
|
||||
FROM SX_CO0050
|
||||
WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</select>
|
||||
|
||||
<select id="getFileInfoListByAtchNo" parameterType="string" resultType="map">
|
||||
SELECT ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, TBL_COL_NM
|
||||
FROM SX_CO0050
|
||||
WHERE ATCH_NO = #{atchNo}
|
||||
AND DEL_DT IS NULL
|
||||
ORDER BY RGST_DT
|
||||
</select>
|
||||
|
||||
<insert id="insertFileInfo" parameterType="map">
|
||||
INSERT INTO SX_CO0050 (
|
||||
ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, DEL_DT, TBL_COL_NM,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{atchfileNo}, #{atchNo}, #{atchFilePathNm}, #{atchFileNm},
|
||||
#{atchTypeNm}, #{atchFileMg}, NULL, #{tblColNm},
|
||||
#{rgstrId}, GETDATE(), #{rgstrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<delete id="deleteFileInfo" parameterType="string">
|
||||
DELETE FROM SX_CO0050 WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</delete>
|
||||
|
||||
<update id="updateTblColNmByAtchNo" parameterType="map">
|
||||
UPDATE SX_CO0050
|
||||
SET TBL_COL_NM = #{tblColNm}
|
||||
WHERE ATCH_NO = #{atchNo}
|
||||
</update>
|
||||
|
||||
<update id="updateTblColNmByAtchfileNo" parameterType="map">
|
||||
UPDATE SX_CO0050
|
||||
SET TBL_COL_NM = #{tblColNm}
|
||||
WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</update>
|
||||
|
||||
<select id="getNeedDeleteFileList" resultType="map">
|
||||
SELECT ATCHFILE_NO, ATCH_FILE_PATH_NM
|
||||
FROM SX_CO0050
|
||||
WHERE NULLIF(TBL_COL_NM, '') IS NULL
|
||||
AND RGST_DT < DATEADD(HOUR, -6, GETDATE())
|
||||
</select>
|
||||
|
||||
<!-- ===================== MariaDB ===================== -->
|
||||
|
||||
<select id="getFileInfo" parameterType="string" resultType="map" databaseId="mariadb">
|
||||
SELECT ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, TBL_COL_NM, RGSTR_ID
|
||||
FROM SX_CO0050
|
||||
WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</select>
|
||||
|
||||
<select id="getFileInfoListByAtchNo" parameterType="string" resultType="map" databaseId="mariadb">
|
||||
SELECT ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, TBL_COL_NM
|
||||
FROM SX_CO0050
|
||||
WHERE ATCH_NO = #{atchNo}
|
||||
AND DEL_DT IS NULL
|
||||
ORDER BY RGST_DT
|
||||
</select>
|
||||
|
||||
<insert id="insertFileInfo" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0050 (
|
||||
ATCHFILE_NO, ATCH_NO, ATCH_FILE_PATH_NM, ATCH_FILE_NM,
|
||||
ATCH_TYPE_NM, ATCH_FILE_MG, DEL_DT, TBL_COL_NM,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{atchfileNo}, #{atchNo}, #{atchFilePathNm}, #{atchFileNm},
|
||||
#{atchTypeNm}, #{atchFileMg}, NULL, #{tblColNm},
|
||||
#{rgstrId}, NOW(), #{rgstrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<delete id="deleteFileInfo" parameterType="string" databaseId="mariadb">
|
||||
DELETE FROM SX_CO0050 WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</delete>
|
||||
|
||||
<update id="updateTblColNmByAtchNo" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_CO0050
|
||||
SET TBL_COL_NM = #{tblColNm}
|
||||
WHERE ATCH_NO = #{atchNo}
|
||||
</update>
|
||||
|
||||
<update id="updateTblColNmByAtchfileNo" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_CO0050
|
||||
SET TBL_COL_NM = #{tblColNm}
|
||||
WHERE ATCHFILE_NO = #{atchfileNo}
|
||||
</update>
|
||||
|
||||
<select id="getNeedDeleteFileList" resultType="map" databaseId="mariadb">
|
||||
SELECT ATCHFILE_NO, ATCH_FILE_PATH_NM
|
||||
FROM SX_CO0050
|
||||
WHERE (TBL_COL_NM IS NULL OR TBL_COL_NM = '')
|
||||
AND RGST_DT < DATE_SUB(NOW(), INTERVAL 6 HOUR)
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
145
backend/src/main/resources/mapper/common/code_sql.xml
Normal file
145
backend/src/main/resources/mapper/common/code_sql.xml
Normal file
@@ -0,0 +1,145 @@
|
||||
<?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">
|
||||
<!--
|
||||
공통코드 조회 SQL
|
||||
테이블: SX_CO0040 (공통코드), SX_GW0010 (직원), SX_CO0070 (근무코드)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.common.mapper.CodeMapper">
|
||||
|
||||
<!-- ──────────────────────────────────────────────
|
||||
공통코드 목록 (드롭다운용 간략버전)
|
||||
────────────────────────────────────────────── -->
|
||||
<select id="getCodeList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.COMM_CD AS code,
|
||||
A.COMM_CD_NM AS name,
|
||||
A.COMM_CD_USE_YN AS useYn
|
||||
FROM SX_CO0040 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.COMM_CL_CD = #{commClCd}
|
||||
AND (ISNULL(#{useYn}, '') = '' OR A.COMM_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.COMM_CD_DSPLY_ORDR, A.COMM_CD
|
||||
]]></select>
|
||||
|
||||
<select id="getCodeList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.COMM_CD AS code,
|
||||
A.COMM_CD_NM AS name,
|
||||
A.COMM_CD_USE_YN AS useYn
|
||||
FROM SX_CO0040 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.COMM_CL_CD = #{commClCd}
|
||||
AND (IFNULL(#{useYn}, '') = '' OR A.COMM_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.COMM_CD_DSPLY_ORDR, A.COMM_CD
|
||||
]]></select>
|
||||
|
||||
<!-- ──────────────────────────────────────────────
|
||||
공통코드 전체 정보
|
||||
────────────────────────────────────────────── -->
|
||||
<select id="getCodeListFull" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.COMM_CD AS code,
|
||||
A.COMM_CD_NM AS name,
|
||||
A.COMM_CL_CD,
|
||||
A.COMM_CD_DSPLY_ORDR,
|
||||
A.COMM_CD_USE_YN,
|
||||
A.COMM_CD_TYPE_VAL,
|
||||
A.COMM_CD_DSCRPT,
|
||||
A.PROP_CD1,
|
||||
A.PROP_CD2,
|
||||
A.PROP_CD3,
|
||||
A.PROP_CD4,
|
||||
A.PROP_CD5
|
||||
FROM SX_CO0040 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.COMM_CL_CD = #{commClCd}
|
||||
AND (ISNULL(#{useYn}, '') = '' OR A.COMM_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.COMM_CD_DSPLY_ORDR, A.COMM_CD
|
||||
]]></select>
|
||||
|
||||
<select id="getCodeListFull" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.COMM_CD AS code,
|
||||
A.COMM_CD_NM AS name,
|
||||
A.COMM_CL_CD,
|
||||
A.COMM_CD_DSPLY_ORDR,
|
||||
A.COMM_CD_USE_YN,
|
||||
A.COMM_CD_TYPE_VAL,
|
||||
A.COMM_CD_DSCRPT,
|
||||
A.PROP_CD1,
|
||||
A.PROP_CD2,
|
||||
A.PROP_CD3,
|
||||
A.PROP_CD4,
|
||||
A.PROP_CD5
|
||||
FROM SX_CO0040 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.COMM_CL_CD = #{commClCd}
|
||||
AND (IFNULL(#{useYn}, '') = '' OR A.COMM_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.COMM_CD_DSPLY_ORDR, A.COMM_CD
|
||||
]]></select>
|
||||
|
||||
<!-- ──────────────────────────────────────────────
|
||||
직원 목록 (결재자 선택 등 팝업용)
|
||||
────────────────────────────────────────────── -->
|
||||
<select id="searchUser" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT TOP 100
|
||||
A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.DUTY_CD,
|
||||
A.TEAM_CD,
|
||||
A.APPR_YN
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND ISNULL(A.RETIREMENT_DATE, '') = ''
|
||||
AND (ISNULL(#{searchText}, '') = '' OR (
|
||||
A.USR_ID LIKE CONCAT('%', #{searchText}, '%') OR
|
||||
A.USR_NM LIKE CONCAT('%', #{searchText}, '%')))
|
||||
AND (#{apprOnly} != 'Y' OR A.APPR_YN = 'Y')
|
||||
ORDER BY A.USR_NM
|
||||
]]></select>
|
||||
|
||||
<select id="searchUser" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.DUTY_CD,
|
||||
A.TEAM_CD,
|
||||
A.APPR_YN
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND IFNULL(A.RETIREMENT_DATE, '') = ''
|
||||
AND (IFNULL(#{searchText}, '') = '' OR (
|
||||
A.USR_ID LIKE CONCAT('%', #{searchText}, '%') OR
|
||||
A.USR_NM LIKE CONCAT('%', #{searchText}, '%')))
|
||||
AND (#{apprOnly} != 'Y' OR A.APPR_YN = 'Y')
|
||||
ORDER BY A.USR_NM
|
||||
LIMIT 100
|
||||
]]></select>
|
||||
|
||||
<!-- ──────────────────────────────────────────────
|
||||
근무코드 목록
|
||||
────────────────────────────────────────────── -->
|
||||
<select id="getWorkCdList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_CD AS code,
|
||||
A.WORK_CD_TITLE_NM AS name,
|
||||
A.WORK_CD,
|
||||
A.WORK_CD_TITLE_NM,
|
||||
A.GOTOWORK_TM_NM,
|
||||
A.GETOFFWORK_TM_NM,
|
||||
A.WORK_CD_USE_YN
|
||||
FROM SX_CO0070 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (ISNULL(#{useYn}, '') = '' OR A.WORK_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.WORK_CD
|
||||
]]></select>
|
||||
|
||||
<select id="getWorkCdList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_CD AS code,
|
||||
A.WORK_CD_TITLE_NM AS name,
|
||||
A.WORK_CD,
|
||||
A.WORK_CD_TITLE_NM,
|
||||
A.GOTOWORK_TM_NM,
|
||||
A.GETOFFWORK_TM_NM,
|
||||
A.WORK_CD_USE_YN
|
||||
FROM SX_CO0070 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (IFNULL(#{useYn}, '') = '' OR A.WORK_CD_USE_YN = #{useYn})
|
||||
ORDER BY A.WORK_CD
|
||||
]]></select>
|
||||
|
||||
</mapper>
|
||||
28
backend/src/main/resources/mapper/common/common_sql.xml
Normal file
28
backend/src/main/resources/mapper/common/common_sql.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/common/common_sql.xml -->
|
||||
<mapper namespace="com.company.gw.common.mapper.CommonMapper">
|
||||
|
||||
<!-- 시퀀스 증가 (MERGE = SQL Server / MariaDB INSERT ON DUPLICATE KEY) -->
|
||||
<update id="increaseSequence" parameterType="String">
|
||||
MERGE INTO SX_CO0060 T
|
||||
USING (SELECT 1 AS DUMMY) S
|
||||
ON (T.SEQUENCE_NM = #{sequenceNm})
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (SEQUENCE_NM, SEQUENCE_VAL) VALUES (#{sequenceNm}, 1)
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET SEQUENCE_VAL = SEQUENCE_VAL + 1;
|
||||
</update>
|
||||
|
||||
<update id="increaseSequence" parameterType="String" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0060 (SEQUENCE_NM, SEQUENCE_VAL)
|
||||
VALUES (#{sequenceNm}, 1)
|
||||
ON DUPLICATE KEY UPDATE SEQUENCE_VAL = SEQUENCE_VAL + 1
|
||||
</update>
|
||||
|
||||
<select id="getSequenceVal" parameterType="String" resultType="Long">
|
||||
SELECT SEQUENCE_VAL FROM SX_CO0060 WHERE SEQUENCE_NM = #{sequenceNm}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
146
backend/src/main/resources/mapper/common/menu_sql.xml
Normal file
146
backend/src/main/resources/mapper/common/menu_sql.xml
Normal file
@@ -0,0 +1,146 @@
|
||||
<?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">
|
||||
<!--
|
||||
원본: src/java/sql/common/menu_sql.xml (SX_CO0080, SX_CO0090)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.common.mapper.MenuMapper">
|
||||
|
||||
<!-- 사용자 권한 기반 메뉴 트리 조회 (재귀 CTE) -->
|
||||
<select id="getMenuList" parameterType="map" resultType="com.company.gw.common.dto.MenuDto">
|
||||
WITH MENU_TREE AS (
|
||||
SELECT A.MENU_NO AS upMenuNo,
|
||||
A.CORP_NO,
|
||||
A.MENU_NO,
|
||||
A.UPPER_MENU_NO,
|
||||
A.MENU_NM,
|
||||
A.URL,
|
||||
A.RM,
|
||||
A.MENU_PROP,
|
||||
A.MENU_ORDR,
|
||||
A.MENU_USE_YN,
|
||||
1 AS lvl,
|
||||
CAST('/' + RIGHT('00000' + CONVERT(VARCHAR, A.MENU_ORDR), 5) AS VARCHAR(MAX)) AS sortPath
|
||||
FROM SX_CO0080 A
|
||||
JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO
|
||||
AND B.MENU_NO = A.MENU_NO
|
||||
AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.MENU_USE_YN = 'Y'
|
||||
AND NULLIF(A.UPPER_MENU_NO, '') IS NULL
|
||||
UNION ALL
|
||||
SELECT PARENT.upMenuNo,
|
||||
A.CORP_NO,
|
||||
A.MENU_NO,
|
||||
A.UPPER_MENU_NO,
|
||||
A.MENU_NM,
|
||||
A.URL,
|
||||
A.RM,
|
||||
A.MENU_PROP,
|
||||
A.MENU_ORDR,
|
||||
A.MENU_USE_YN,
|
||||
PARENT.lvl + 1 AS lvl,
|
||||
PARENT.sortPath + CAST('/' + RIGHT('00000' + CONVERT(VARCHAR, A.MENU_ORDR), 5) AS VARCHAR(MAX)) AS sortPath
|
||||
FROM SX_CO0080 A
|
||||
JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO
|
||||
AND B.MENU_NO = A.MENU_NO
|
||||
AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
JOIN MENU_TREE PARENT
|
||||
ON PARENT.CORP_NO = A.CORP_NO
|
||||
AND PARENT.MENU_NO = A.UPPER_MENU_NO
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.MENU_USE_YN = 'Y'
|
||||
)
|
||||
SELECT MENU_NO AS menuNo,
|
||||
UPPER_MENU_NO AS upperMenuNo,
|
||||
MENU_NM AS menuNm,
|
||||
URL,
|
||||
RM,
|
||||
MENU_PROP AS menuProp,
|
||||
MENU_ORDR AS menuOrdr,
|
||||
MENU_USE_YN AS menuUseYn,
|
||||
lvl
|
||||
FROM MENU_TREE
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
ORDER BY sortPath
|
||||
</select>
|
||||
|
||||
<select id="getMenuList" parameterType="map" resultType="com.company.gw.common.dto.MenuDto" databaseId="mariadb">
|
||||
WITH MENU_TREE AS (
|
||||
SELECT A.MENU_NO AS upMenuNo,
|
||||
A.CORP_NO,
|
||||
A.MENU_NO,
|
||||
A.UPPER_MENU_NO,
|
||||
A.MENU_NM,
|
||||
A.URL,
|
||||
A.RM,
|
||||
A.MENU_PROP,
|
||||
A.MENU_ORDR,
|
||||
A.MENU_USE_YN,
|
||||
1 AS lvl,
|
||||
CONCAT('/', LPAD(A.MENU_ORDR, 5, '0')) AS sortPath
|
||||
FROM SX_CO0080 A
|
||||
JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO
|
||||
AND B.MENU_NO = A.MENU_NO
|
||||
AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.MENU_USE_YN = 'Y'
|
||||
AND NULLIF(A.UPPER_MENU_NO, '') IS NULL
|
||||
UNION ALL
|
||||
SELECT PARENT.upMenuNo,
|
||||
A.CORP_NO,
|
||||
A.MENU_NO,
|
||||
A.UPPER_MENU_NO,
|
||||
A.MENU_NM,
|
||||
A.URL,
|
||||
A.RM,
|
||||
A.MENU_PROP,
|
||||
A.MENU_ORDR,
|
||||
A.MENU_USE_YN,
|
||||
PARENT.lvl + 1 AS lvl,
|
||||
CONCAT(PARENT.sortPath, '/', LPAD(A.MENU_ORDR, 5, '0')) AS sortPath
|
||||
FROM SX_CO0080 A
|
||||
JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO
|
||||
AND B.MENU_NO = A.MENU_NO
|
||||
AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
JOIN MENU_TREE PARENT
|
||||
ON PARENT.CORP_NO = A.CORP_NO
|
||||
AND PARENT.MENU_NO = A.UPPER_MENU_NO
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.MENU_USE_YN = 'Y'
|
||||
)
|
||||
SELECT MENU_NO AS menuNo,
|
||||
UPPER_MENU_NO AS upperMenuNo,
|
||||
MENU_NM AS menuNm,
|
||||
URL,
|
||||
RM,
|
||||
MENU_PROP AS menuProp,
|
||||
MENU_ORDR AS menuOrdr,
|
||||
MENU_USE_YN AS menuUseYn,
|
||||
lvl
|
||||
FROM MENU_TREE
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
ORDER BY sortPath
|
||||
</select>
|
||||
|
||||
<!-- 컨트롤러-롤 매핑 목록 (접근 권한 체크용) -->
|
||||
<select id="getControllerRoleList" parameterType="map" resultType="com.company.gw.common.dto.ControllerRoleDto">
|
||||
SELECT DISTINCT
|
||||
A.CONTROLLER AS controller,
|
||||
B.MENU_AUTH_CD AS role,
|
||||
B.FUNC_AUTH_CN AS funcAuthCn
|
||||
FROM SX_CO0080 A
|
||||
JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO
|
||||
AND B.MENU_NO = A.MENU_NO
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.MENU_USE_YN = 'Y'
|
||||
AND NULLIF(A.CONTROLLER, '') IS NOT NULL
|
||||
ORDER BY A.CONTROLLER
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
18
backend/src/main/resources/mapper/common/security_sql.xml
Normal file
18
backend/src/main/resources/mapper/common/security_sql.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?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">
|
||||
<!--
|
||||
원본: src/java/sql/common/security_sql.xml (SX_GW0130)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.common.mapper.SecurityMapper">
|
||||
|
||||
<!-- 사용자 보유 ROLE 목록 -->
|
||||
<select id="getUserRoleList" parameterType="map" resultType="String">
|
||||
SELECT MENU_AUTH_CD AS roleCode
|
||||
FROM SX_GW0130
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
ORDER BY MENU_AUTH_CD
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
41
backend/src/main/resources/mapper/common/user_sql.xml
Normal file
41
backend/src/main/resources/mapper/common/user_sql.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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">
|
||||
<!--
|
||||
원본: src/java/sql/common/user_sql.xml (SX_GW0010)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.common.mapper.UserMapper">
|
||||
|
||||
<!-- 사용자 정보 by USR_ID -->
|
||||
<select id="getUserInfo" parameterType="String" resultType="com.company.gw.common.dto.UserDto">
|
||||
SELECT CORP_NO,
|
||||
USR_ID,
|
||||
USR_NM,
|
||||
LOGIN_ID,
|
||||
DUTY_CD
|
||||
FROM SX_GW0010
|
||||
WHERE USR_ID = #{usrId}
|
||||
</select>
|
||||
|
||||
<!-- 사용자 정보 by LOGIN_ID (비밀번호 포함) - 로그인용 -->
|
||||
<select id="getUserInfoWithPwd" parameterType="String" resultType="com.company.gw.common.dto.UserDto">
|
||||
SELECT CORP_NO,
|
||||
USR_ID,
|
||||
USR_NM,
|
||||
LOGIN_ID,
|
||||
PW,
|
||||
DUTY_CD,
|
||||
RETIREMENT_DATE
|
||||
FROM SX_GW0010
|
||||
WHERE LOGIN_ID = #{loginId}
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 비밀번호 변경 -->
|
||||
<update id="updatePassword">
|
||||
UPDATE SX_GW0010
|
||||
SET PW = #{newPw}
|
||||
WHERE USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
246
backend/src/main/resources/mapper/envset/envset0010_sql.xml
Normal file
246
backend/src/main/resources/mapper/envset/envset0010_sql.xml
Normal file
@@ -0,0 +1,246 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/biz/envset/envset0010_sql.xml (SX_GW0010) -->
|
||||
<mapper namespace="com.company.gw.envset.mapper.UserManageMapper">
|
||||
|
||||
<!-- 직원 목록 (페이징) -->
|
||||
<select id="getUserList" parameterType="map" resultType="com.company.gw.envset.dto.UserListDto">
|
||||
SELECT A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.TEAM_CD,
|
||||
A.DUTY_CD,
|
||||
A.USR_TELNO,
|
||||
A.MTEL_NO,
|
||||
A.RETIREMENT_DATE
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
<if test="usrNm != null and usrNm != ''">AND A.USR_NM LIKE CONCAT('%', #{usrNm}, '%')</if>
|
||||
<if test="teamCd != null and teamCd != ''">AND A.TEAM_CD = #{teamCd}</if>
|
||||
<if test="dutyCd != null and dutyCd != ''">AND A.DUTY_CD = #{dutyCd}</if>
|
||||
<if test="apprYn != null and apprYn != ''">AND A.APPR_YN = #{apprYn}</if>
|
||||
AND A.USR_ID != '00001'
|
||||
AND (#{includeRetireYn} = 'Y' OR NULLIF(A.RETIREMENT_DATE, '') IS NULL)
|
||||
ORDER BY A.${userOrderBy}, A.USR_ID
|
||||
OFFSET (#{page} - 1) * #{size} ROWS
|
||||
FETCH NEXT #{size} ROWS ONLY
|
||||
</select>
|
||||
|
||||
<select id="getUserList" parameterType="map" resultType="com.company.gw.envset.dto.UserListDto" databaseId="mariadb">
|
||||
SELECT A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.TEAM_CD,
|
||||
A.DUTY_CD,
|
||||
A.USR_TELNO,
|
||||
A.MTEL_NO,
|
||||
A.RETIREMENT_DATE
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
<if test="usrNm != null and usrNm != ''">AND A.USR_NM LIKE CONCAT('%', #{usrNm}, '%')</if>
|
||||
<if test="teamCd != null and teamCd != ''">AND A.TEAM_CD = #{teamCd}</if>
|
||||
<if test="dutyCd != null and dutyCd != ''">AND A.DUTY_CD = #{dutyCd}</if>
|
||||
<if test="apprYn != null and apprYn != ''">AND A.APPR_YN = #{apprYn}</if>
|
||||
AND A.USR_ID != '00001'
|
||||
AND (#{includeRetireYn} = 'Y' OR NULLIF(A.RETIREMENT_DATE, '') IS NULL)
|
||||
ORDER BY A.${userOrderBy}, A.USR_ID
|
||||
LIMIT #{size} OFFSET (#{page} - 1) * #{size}
|
||||
</select>
|
||||
|
||||
<!-- 직원 목록 건수 -->
|
||||
<select id="getUserListCount" parameterType="map" resultType="long">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
<if test="usrNm != null and usrNm != ''">AND A.USR_NM LIKE CONCAT('%', #{usrNm}, '%')</if>
|
||||
<if test="teamCd != null and teamCd != ''">AND A.TEAM_CD = #{teamCd}</if>
|
||||
<if test="dutyCd != null and dutyCd != ''">AND A.DUTY_CD = #{dutyCd}</if>
|
||||
<if test="apprYn != null and apprYn != ''">AND A.APPR_YN = #{apprYn}</if>
|
||||
AND A.USR_ID != '00001'
|
||||
AND (#{includeRetireYn} = 'Y' OR NULLIF(A.RETIREMENT_DATE, '') IS NULL)
|
||||
</select>
|
||||
|
||||
<!-- 직원 상세 -->
|
||||
<select id="getUserDetail" parameterType="map" resultType="com.company.gw.envset.dto.UserDetailDto">
|
||||
SELECT A.CORP_NO,
|
||||
A.USR_ID,
|
||||
A.USR_SORT_ORDR,
|
||||
A.USR_NM,
|
||||
A.LOGIN_ID,
|
||||
A.DUTY_CD,
|
||||
A.BRTHDY_DATE,
|
||||
A.USR_TELNO,
|
||||
A.MTEL_NO,
|
||||
A.EMAIL,
|
||||
A.BASE_ADRS,
|
||||
A.GUSO_ADRS,
|
||||
A.GUSO_TELNO,
|
||||
A.JOINCP_DATE,
|
||||
A.TEAM_CD,
|
||||
A.DISML_DATE,
|
||||
A.RETIREMENT_DATE,
|
||||
A.SPCLT_ARTC_CN,
|
||||
A.PHOTO_ATCHFILE_NO,
|
||||
A.SPMT_EMAIL,
|
||||
A.SPMT_MTEL_NO,
|
||||
A.APPR_YN,
|
||||
A.FINAL_SCHSP_NM
|
||||
FROM SX_GW0010 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
</select>
|
||||
|
||||
<!-- 로그인ID 중복 체크 -->
|
||||
<select id="getLoginIdCount" parameterType="map" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0010
|
||||
WHERE LOGIN_ID = #{loginId}
|
||||
AND CORP_NO != #{corpNo}
|
||||
AND USR_ID != #{usrId}
|
||||
</select>
|
||||
|
||||
<!-- 직원 등록 -->
|
||||
<insert id="insertUser" parameterType="com.company.gw.envset.dto.UserSaveDto">
|
||||
INSERT INTO SX_GW0010 (
|
||||
CORP_NO, USR_ID, USR_SORT_ORDR, USR_NM, PW,
|
||||
DUTY_CD, BRTHDY_DATE, USR_TELNO, MTEL_NO, EMAIL,
|
||||
BASE_ADRS, GUSO_ADRS, GUSO_TELNO, JOINCP_DATE, TEAM_CD,
|
||||
DISML_DATE, RETIREMENT_DATE, SPCLT_ARTC_CN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT,
|
||||
LOGIN_ID, SPMT_EMAIL, SPMT_MTEL_NO, RRNO,
|
||||
APPR_YN, FINAL_SCHSP_NM
|
||||
) VALUES (
|
||||
#{corpNo}, #{usrId}, #{usrSortOrdr}, #{usrNm}, #{pw},
|
||||
#{dutyCd}, #{brthDyDate}, #{usrTelno}, #{mtelNo}, #{email},
|
||||
#{baseAdrs}, #{gusoAdrs}, #{gusoTelno}, #{joinCpDate}, #{teamCd},
|
||||
#{dismlDate}, #{retirementDate}, #{spkltArtcCn},
|
||||
#{rgstrId}, GETDATE(), #{rgstrId}, GETDATE(),
|
||||
#{loginId}, #{spmtEmail}, #{spmtMtelNo}, #{rrno},
|
||||
ISNULL(NULLIF(#{apprYn}, ''), 'N'), #{finalSchspNm}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertUser" parameterType="com.company.gw.envset.dto.UserSaveDto" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0010 (
|
||||
CORP_NO, USR_ID, USR_SORT_ORDR, USR_NM, PW,
|
||||
DUTY_CD, BRTHDY_DATE, USR_TELNO, MTEL_NO, EMAIL,
|
||||
BASE_ADRS, GUSO_ADRS, GUSO_TELNO, JOINCP_DATE, TEAM_CD,
|
||||
DISML_DATE, RETIREMENT_DATE, SPCLT_ARTC_CN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT,
|
||||
LOGIN_ID, SPMT_EMAIL, SPMT_MTEL_NO, RRNO,
|
||||
APPR_YN, FINAL_SCHSP_NM
|
||||
) VALUES (
|
||||
#{corpNo}, #{usrId}, #{usrSortOrdr}, #{usrNm}, #{pw},
|
||||
#{dutyCd}, #{brthDyDate}, #{usrTelno}, #{mtelNo}, #{email},
|
||||
#{baseAdrs}, #{gusoAdrs}, #{gusoTelno}, #{joinCpDate}, #{teamCd},
|
||||
#{dismlDate}, #{retirementDate}, #{spkltArtcCn},
|
||||
#{rgstrId}, NOW(), #{rgstrId}, NOW(),
|
||||
#{loginId}, #{spmtEmail}, #{spmtMtelNo}, #{rrno},
|
||||
IFNULL(NULLIF(#{apprYn}, ''), 'N'), #{finalSchspNm}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 직원 수정 -->
|
||||
<update id="updateUser" parameterType="com.company.gw.envset.dto.UserSaveDto">
|
||||
UPDATE SX_GW0010
|
||||
SET USR_SORT_ORDR = #{usrSortOrdr},
|
||||
USR_NM = #{usrNm},
|
||||
DUTY_CD = #{dutyCd},
|
||||
BRTHDY_DATE = #{brthDyDate},
|
||||
USR_TELNO = #{usrTelno},
|
||||
MTEL_NO = #{mtelNo},
|
||||
EMAIL = #{email},
|
||||
BASE_ADRS = #{baseAdrs},
|
||||
GUSO_ADRS = #{gusoAdrs},
|
||||
GUSO_TELNO = #{gusoTelno},
|
||||
JOINCP_DATE = #{joinCpDate},
|
||||
TEAM_CD = #{teamCd},
|
||||
DISML_DATE = #{dismlDate},
|
||||
RETIREMENT_DATE = #{retirementDate},
|
||||
SPCLT_ARTC_CN = #{spkltArtcCn},
|
||||
LOGIN_ID = #{loginId},
|
||||
SPMT_EMAIL = #{spmtEmail},
|
||||
SPMT_MTEL_NO = #{spmtMtelNo},
|
||||
RRNO = #{rrno},
|
||||
APPR_YN = ISNULL(NULLIF(#{apprYn}, ''), 'N'),
|
||||
FINAL_SCHSP_NM = #{finalSchspNm},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
<update id="updateUser" parameterType="com.company.gw.envset.dto.UserSaveDto" databaseId="mariadb">
|
||||
UPDATE SX_GW0010
|
||||
SET USR_SORT_ORDR = #{usrSortOrdr},
|
||||
USR_NM = #{usrNm},
|
||||
DUTY_CD = #{dutyCd},
|
||||
BRTHDY_DATE = #{brthDyDate},
|
||||
USR_TELNO = #{usrTelno},
|
||||
MTEL_NO = #{mtelNo},
|
||||
EMAIL = #{email},
|
||||
BASE_ADRS = #{baseAdrs},
|
||||
GUSO_ADRS = #{gusoAdrs},
|
||||
GUSO_TELNO = #{gusoTelno},
|
||||
JOINCP_DATE = #{joinCpDate},
|
||||
TEAM_CD = #{teamCd},
|
||||
DISML_DATE = #{dismlDate},
|
||||
RETIREMENT_DATE = #{retirementDate},
|
||||
SPCLT_ARTC_CN = #{spkltArtcCn},
|
||||
LOGIN_ID = #{loginId},
|
||||
SPMT_EMAIL = #{spmtEmail},
|
||||
SPMT_MTEL_NO = #{spmtMtelNo},
|
||||
RRNO = #{rrno},
|
||||
APPR_YN = IFNULL(NULLIF(#{apprYn}, ''), 'N'),
|
||||
FINAL_SCHSP_NM = #{finalSchspNm},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
<!-- 비밀번호 변경 -->
|
||||
<update id="updateUserPw" parameterType="map">
|
||||
UPDATE SX_GW0010
|
||||
SET PW = #{pw},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
<update id="updateUserPw" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0010
|
||||
SET PW = #{pw},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
<!-- 직원 삭제 -->
|
||||
<delete id="deleteUser" parameterType="map">
|
||||
DELETE FROM SX_GW0010
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</delete>
|
||||
|
||||
<!-- 사진 파일번호 업데이트 -->
|
||||
<update id="updateUserPhoto" parameterType="map">
|
||||
UPDATE SX_GW0010
|
||||
SET PHOTO_ATCHFILE_NO = #{photoAtchfileNo},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
<update id="updateUserPhoto" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0010
|
||||
SET PHOTO_ATCHFILE_NO = #{photoAtchfileNo},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
158
backend/src/main/resources/mapper/envset/envset0020_sql.xml
Normal file
158
backend/src/main/resources/mapper/envset/envset0020_sql.xml
Normal file
@@ -0,0 +1,158 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/biz/envset/envset0020_sql.xml (SX_CO0030, SX_CO0040) -->
|
||||
<mapper namespace="com.company.gw.envset.mapper.CodeManageMapper">
|
||||
|
||||
<!-- ===== 코드인덱스 (SX_CO0030) ===== -->
|
||||
|
||||
<select id="getCdidxList" parameterType="map" resultType="com.company.gw.envset.dto.CodeIndexDto">
|
||||
SELECT COMM_CL_CD,
|
||||
COMM_CL_CD_NM,
|
||||
COMM_CL_CD_USE_YN,
|
||||
COMM_CL_CD_DSCRPT,
|
||||
DSPLY_ORDR
|
||||
FROM SX_CO0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND (#{searchText} IS NULL
|
||||
OR COMM_CL_CD LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR COMM_CL_CD_NM LIKE CONCAT('%', #{searchText}, '%'))
|
||||
ORDER BY DSPLY_ORDR, COMM_CL_CD
|
||||
</select>
|
||||
|
||||
<select id="getCdidxInfo" parameterType="map" resultType="com.company.gw.envset.dto.CodeIndexDto">
|
||||
SELECT COMM_CL_CD, COMM_CL_CD_NM, COMM_CL_CD_USE_YN, COMM_CL_CD_DSCRPT, DSPLY_ORDR
|
||||
FROM SX_CO0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
</select>
|
||||
|
||||
<insert id="insertCdidx" parameterType="com.company.gw.envset.dto.CodeIndexDto">
|
||||
INSERT INTO SX_CO0030 (
|
||||
CORP_NO, COMM_CL_CD, COMM_CL_CD_NM, COMM_CL_CD_USE_YN,
|
||||
COMM_CL_CD_DSCRPT, DSPLY_ORDR, PROP_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{commClCd}, #{commClCdNm}, #{commClCdUseYn},
|
||||
#{commClCdDscrpt}, #{dsplyOrdr}, 'N',
|
||||
#{rgstrId}, GETDATE(), #{rgstrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertCdidx" parameterType="com.company.gw.envset.dto.CodeIndexDto" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0030 (
|
||||
CORP_NO, COMM_CL_CD, COMM_CL_CD_NM, COMM_CL_CD_USE_YN,
|
||||
COMM_CL_CD_DSCRPT, DSPLY_ORDR, PROP_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{commClCd}, #{commClCdNm}, #{commClCdUseYn},
|
||||
#{commClCdDscrpt}, #{dsplyOrdr}, 'N',
|
||||
#{rgstrId}, NOW(), #{rgstrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateCdidx" parameterType="com.company.gw.envset.dto.CodeIndexDto">
|
||||
UPDATE SX_CO0030
|
||||
SET COMM_CL_CD_NM = #{commClCdNm},
|
||||
COMM_CL_CD_USE_YN = #{commClCdUseYn},
|
||||
COMM_CL_CD_DSCRPT = #{commClCdDscrpt},
|
||||
DSPLY_ORDR = #{dsplyOrdr},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
</update>
|
||||
|
||||
<update id="updateCdidx" parameterType="com.company.gw.envset.dto.CodeIndexDto" databaseId="mariadb">
|
||||
UPDATE SX_CO0030
|
||||
SET COMM_CL_CD_NM = #{commClCdNm},
|
||||
COMM_CL_CD_USE_YN = #{commClCdUseYn},
|
||||
COMM_CL_CD_DSCRPT = #{commClCdDscrpt},
|
||||
DSPLY_ORDR = #{dsplyOrdr},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
</update>
|
||||
|
||||
<delete id="deleteCdidx" parameterType="map">
|
||||
DELETE FROM SX_CO0030
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
</delete>
|
||||
|
||||
<!-- ===== 코드 (SX_CO0040) ===== -->
|
||||
|
||||
<select id="getCodeList" parameterType="map" resultType="com.company.gw.envset.dto.CodeDto">
|
||||
SELECT COMM_CD,
|
||||
COMM_CD_NM,
|
||||
COMM_CD_USE_YN,
|
||||
COMM_CD_DSCRPT,
|
||||
COMM_CD_DSPLY_ORDR
|
||||
FROM SX_CO0040
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
AND (#{searchText} IS NULL
|
||||
OR COMM_CD LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR COMM_CD_NM LIKE CONCAT('%', #{searchText}, '%'))
|
||||
ORDER BY COMM_CD_DSPLY_ORDR, COMM_CD
|
||||
</select>
|
||||
|
||||
<insert id="insertCode" parameterType="com.company.gw.envset.dto.CodeDto">
|
||||
INSERT INTO SX_CO0040 (
|
||||
CORP_NO, COMM_CL_CD, COMM_CD, COMM_CD_NM,
|
||||
COMM_CD_USE_YN, COMM_CD_DSCRPT, COMM_CD_DSPLY_ORDR,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{commClCd}, #{commCd}, #{commCdNm},
|
||||
#{commCdUseYn}, #{commCdDscrpt}, #{commCdDsplyOrdr},
|
||||
#{rgstrId}, GETDATE(), #{rgstrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertCode" parameterType="com.company.gw.envset.dto.CodeDto" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0040 (
|
||||
CORP_NO, COMM_CL_CD, COMM_CD, COMM_CD_NM,
|
||||
COMM_CD_USE_YN, COMM_CD_DSCRPT, COMM_CD_DSPLY_ORDR,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{commClCd}, #{commCd}, #{commCdNm},
|
||||
#{commCdUseYn}, #{commCdDscrpt}, #{commCdDsplyOrdr},
|
||||
#{rgstrId}, NOW(), #{rgstrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateCode" parameterType="com.company.gw.envset.dto.CodeDto">
|
||||
UPDATE SX_CO0040
|
||||
SET COMM_CD_NM = #{commCdNm},
|
||||
COMM_CD_USE_YN = #{commCdUseYn},
|
||||
COMM_CD_DSCRPT = #{commCdDscrpt},
|
||||
COMM_CD_DSPLY_ORDR = #{commCdDsplyOrdr},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
AND COMM_CD = #{commCd}
|
||||
</update>
|
||||
|
||||
<update id="updateCode" parameterType="com.company.gw.envset.dto.CodeDto" databaseId="mariadb">
|
||||
UPDATE SX_CO0040
|
||||
SET COMM_CD_NM = #{commCdNm},
|
||||
COMM_CD_USE_YN = #{commCdUseYn},
|
||||
COMM_CD_DSCRPT = #{commCdDscrpt},
|
||||
COMM_CD_DSPLY_ORDR = #{commCdDsplyOrdr},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
AND COMM_CD = #{commCd}
|
||||
</update>
|
||||
|
||||
<delete id="deleteCode" parameterType="map">
|
||||
DELETE FROM SX_CO0040
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND COMM_CL_CD = #{commClCd}
|
||||
AND COMM_CD = #{commCd}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
167
backend/src/main/resources/mapper/envset/envset0040_sql.xml
Normal file
167
backend/src/main/resources/mapper/envset/envset0040_sql.xml
Normal file
@@ -0,0 +1,167 @@
|
||||
<?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">
|
||||
<!--
|
||||
환경설정 > 근무코드관리 (SX_CO0070)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.envset.mapper.WorkCdMapper">
|
||||
|
||||
<!-- 근무코드 목록 -->
|
||||
<select id="getWorkCdList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
A.WORK_CD,
|
||||
A.WORK_CD_TITLE_NM,
|
||||
A.GOTOWORK_TM_NM,
|
||||
A.GETOFFWORK_TM_NM,
|
||||
A.PAY_DIV_NM,
|
||||
A.REGULAR_WORK_TM,
|
||||
A.REST_TM,
|
||||
A.INCLU_WORK_NM,
|
||||
A.INCLU_WORK_START_TM,
|
||||
A.INCLU_WORK_END_TM,
|
||||
A.INCLU_WORK_TM,
|
||||
A.CALC_LOCA_NM,
|
||||
A.OT_START_TM,
|
||||
A.NGT_ALLW_NM,
|
||||
A.NGT_START_TM,
|
||||
A.NGT_END_TM,
|
||||
A.WORK_ALLW_NM,
|
||||
A.WORK_CD_USE_YN,
|
||||
A.WORK_CN,
|
||||
A.OT_BSCRT,
|
||||
A.NGT_BSCRT,
|
||||
A.APLY_WORK_DAY,
|
||||
A.YYCT_DEDU_DAY,
|
||||
A.MEAL_START_TM,
|
||||
A.MEAL_END_TM,
|
||||
A.HOLIDAY_YN
|
||||
FROM SX_CO0070 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
<if test="searchText != null and searchText != ''">
|
||||
AND (A.WORK_CD LIKE CONCAT('%', #{searchText}, '%')
|
||||
OR A.WORK_CD_TITLE_NM LIKE CONCAT('%', #{searchText}, '%'))
|
||||
</if>
|
||||
ORDER BY A.WORK_CD
|
||||
</select>
|
||||
|
||||
<!-- 근무코드 등록 MSSQL -->
|
||||
<insert id="insertWorkCd" parameterType="map">
|
||||
INSERT INTO SX_CO0070 (
|
||||
CORP_NO, WORK_CD, WORK_CD_TITLE_NM, GOTOWORK_TM_NM, GETOFFWORK_TM_NM,
|
||||
PAY_DIV_NM, REGULAR_WORK_TM, REST_TM,
|
||||
INCLU_WORK_NM, INCLU_WORK_START_TM, INCLU_WORK_END_TM, INCLU_WORK_TM,
|
||||
CALC_LOCA_NM, OT_START_TM, NGT_ALLW_NM, NGT_START_TM, NGT_END_TM,
|
||||
WORK_ALLW_NM, WORK_CD_USE_YN, WORK_CN,
|
||||
OT_BSCRT, NGT_BSCRT, APLY_WORK_DAY, YYCT_DEDU_DAY,
|
||||
MEAL_START_TM, MEAL_END_TM, HOLIDAY_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{workCd}, #{workCdTitleNm}, #{gotoworkTmNm}, #{getoffworkTmNm},
|
||||
#{payDivNm}, #{regularWorkTm}, #{restTm},
|
||||
#{incluWorkNm}, #{incluWorkStartTm}, #{incluWorkEndTm}, #{incluWorkTm},
|
||||
#{calcLocaNm}, #{otStartTm}, #{ngtAllwNm}, #{ngtStartTm}, #{ngtEndTm},
|
||||
#{workAllwNm}, #{workCdUseYn}, #{workCn},
|
||||
#{otBscrt}, #{ngtBscrt}, #{aplyWorkDay}, #{yyctDeduDay},
|
||||
#{mealStartTm}, #{mealEndTm}, #{holidayYn},
|
||||
#{regUsrId}, GETDATE(), #{regUsrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 근무코드 등록 MariaDB -->
|
||||
<insert id="insertWorkCd" databaseId="mariadb" parameterType="map">
|
||||
INSERT INTO SX_CO0070 (
|
||||
CORP_NO, WORK_CD, WORK_CD_TITLE_NM, GOTOWORK_TM_NM, GETOFFWORK_TM_NM,
|
||||
PAY_DIV_NM, REGULAR_WORK_TM, REST_TM,
|
||||
INCLU_WORK_NM, INCLU_WORK_START_TM, INCLU_WORK_END_TM, INCLU_WORK_TM,
|
||||
CALC_LOCA_NM, OT_START_TM, NGT_ALLW_NM, NGT_START_TM, NGT_END_TM,
|
||||
WORK_ALLW_NM, WORK_CD_USE_YN, WORK_CN,
|
||||
OT_BSCRT, NGT_BSCRT, APLY_WORK_DAY, YYCT_DEDU_DAY,
|
||||
MEAL_START_TM, MEAL_END_TM, HOLIDAY_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{workCd}, #{workCdTitleNm}, #{gotoworkTmNm}, #{getoffworkTmNm},
|
||||
#{payDivNm}, #{regularWorkTm}, #{restTm},
|
||||
#{incluWorkNm}, #{incluWorkStartTm}, #{incluWorkEndTm}, #{incluWorkTm},
|
||||
#{calcLocaNm}, #{otStartTm}, #{ngtAllwNm}, #{ngtStartTm}, #{ngtEndTm},
|
||||
#{workAllwNm}, #{workCdUseYn}, #{workCn},
|
||||
#{otBscrt}, #{ngtBscrt}, #{aplyWorkDay}, #{yyctDeduDay},
|
||||
#{mealStartTm}, #{mealEndTm}, #{holidayYn},
|
||||
#{regUsrId}, NOW(), #{regUsrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 근무코드 수정 MSSQL -->
|
||||
<update id="updateWorkCd" parameterType="map">
|
||||
UPDATE SX_CO0070 SET
|
||||
WORK_CD_TITLE_NM = #{workCdTitleNm},
|
||||
GOTOWORK_TM_NM = #{gotoworkTmNm},
|
||||
GETOFFWORK_TM_NM = #{getoffworkTmNm},
|
||||
PAY_DIV_NM = #{payDivNm},
|
||||
REGULAR_WORK_TM = #{regularWorkTm},
|
||||
REST_TM = #{restTm},
|
||||
INCLU_WORK_NM = #{incluWorkNm},
|
||||
INCLU_WORK_START_TM = #{incluWorkStartTm},
|
||||
INCLU_WORK_END_TM = #{incluWorkEndTm},
|
||||
INCLU_WORK_TM = #{incluWorkTm},
|
||||
CALC_LOCA_NM = #{calcLocaNm},
|
||||
OT_START_TM = #{otStartTm},
|
||||
NGT_ALLW_NM = #{ngtAllwNm},
|
||||
NGT_START_TM = #{ngtStartTm},
|
||||
NGT_END_TM = #{ngtEndTm},
|
||||
WORK_ALLW_NM = #{workAllwNm},
|
||||
WORK_CD_USE_YN = #{workCdUseYn},
|
||||
WORK_CN = #{workCn},
|
||||
OT_BSCRT = #{otBscrt},
|
||||
NGT_BSCRT = #{ngtBscrt},
|
||||
APLY_WORK_DAY = #{aplyWorkDay},
|
||||
YYCT_DEDU_DAY = #{yyctDeduDay},
|
||||
MEAL_START_TM = #{mealStartTm},
|
||||
MEAL_END_TM = #{mealEndTm},
|
||||
HOLIDAY_YN = #{holidayYn},
|
||||
MODID = #{regUsrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND WORK_CD = #{workCd}
|
||||
</update>
|
||||
|
||||
<!-- 근무코드 수정 MariaDB -->
|
||||
<update id="updateWorkCd" databaseId="mariadb" parameterType="map">
|
||||
UPDATE SX_CO0070 SET
|
||||
WORK_CD_TITLE_NM = #{workCdTitleNm},
|
||||
GOTOWORK_TM_NM = #{gotoworkTmNm},
|
||||
GETOFFWORK_TM_NM = #{getoffworkTmNm},
|
||||
PAY_DIV_NM = #{payDivNm},
|
||||
REGULAR_WORK_TM = #{regularWorkTm},
|
||||
REST_TM = #{restTm},
|
||||
INCLU_WORK_NM = #{incluWorkNm},
|
||||
INCLU_WORK_START_TM = #{incluWorkStartTm},
|
||||
INCLU_WORK_END_TM = #{incluWorkEndTm},
|
||||
INCLU_WORK_TM = #{incluWorkTm},
|
||||
CALC_LOCA_NM = #{calcLocaNm},
|
||||
OT_START_TM = #{otStartTm},
|
||||
NGT_ALLW_NM = #{ngtAllwNm},
|
||||
NGT_START_TM = #{ngtStartTm},
|
||||
NGT_END_TM = #{ngtEndTm},
|
||||
WORK_ALLW_NM = #{workAllwNm},
|
||||
WORK_CD_USE_YN = #{workCdUseYn},
|
||||
WORK_CN = #{workCn},
|
||||
OT_BSCRT = #{otBscrt},
|
||||
NGT_BSCRT = #{ngtBscrt},
|
||||
APLY_WORK_DAY = #{aplyWorkDay},
|
||||
YYCT_DEDU_DAY = #{yyctDeduDay},
|
||||
MEAL_START_TM = #{mealStartTm},
|
||||
MEAL_END_TM = #{mealEndTm},
|
||||
HOLIDAY_YN = #{holidayYn},
|
||||
MODID = #{regUsrId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND WORK_CD = #{workCd}
|
||||
</update>
|
||||
|
||||
<!-- 근무코드 삭제 -->
|
||||
<delete id="deleteWorkCd" parameterType="map">
|
||||
DELETE FROM SX_CO0070
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND WORK_CD = #{workCd}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
213
backend/src/main/resources/mapper/envset/envset0050_sql.xml
Normal file
213
backend/src/main/resources/mapper/envset/envset0050_sql.xml
Normal file
@@ -0,0 +1,213 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/biz/envset/envset0050_sql.xml (SX_CO0080, SX_CO0090, SX_GW0130) -->
|
||||
<mapper namespace="com.company.gw.envset.mapper.MenuManageMapper">
|
||||
|
||||
<!-- ===== 메뉴 (SX_CO0080) ===== -->
|
||||
|
||||
<select id="getMenuList" parameterType="String" resultType="com.company.gw.envset.dto.MenuManageDto">
|
||||
SELECT MENU_NO, UPPER_MENU_NO, MENU_NM, URL, RM,
|
||||
MENU_PROP, MENU_ORDR, MENU_USE_YN, CONTROLLER, MENU_LVL
|
||||
FROM SX_CO0080
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
ORDER BY MENU_ORDR
|
||||
</select>
|
||||
|
||||
<insert id="insertMenu" parameterType="com.company.gw.envset.dto.MenuManageDto">
|
||||
INSERT INTO SX_CO0080 (
|
||||
CORP_NO, MENU_NO, UPPER_MENU_NO, MENU_NM, URL, RM,
|
||||
MENU_PROP, MENU_ORDR, MENU_USE_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT, CONTROLLER, MENU_LVL
|
||||
) VALUES (
|
||||
#{corpNo}, #{menuNo}, NULLIF(#{upperMenuNo}, ''), #{menuNm}, #{url}, #{rm},
|
||||
#{menuProp}, #{menuOrdr}, #{menuUseYn},
|
||||
#{rgstrId}, GETDATE(), #{rgstrId}, GETDATE(), #{controller}, #{menuLvl}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertMenu" parameterType="com.company.gw.envset.dto.MenuManageDto" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0080 (
|
||||
CORP_NO, MENU_NO, UPPER_MENU_NO, MENU_NM, URL, RM,
|
||||
MENU_PROP, MENU_ORDR, MENU_USE_YN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT, CONTROLLER, MENU_LVL
|
||||
) VALUES (
|
||||
#{corpNo}, #{menuNo}, NULLIF(#{upperMenuNo}, ''), #{menuNm}, #{url}, #{rm},
|
||||
#{menuProp}, #{menuOrdr}, #{menuUseYn},
|
||||
#{rgstrId}, NOW(), #{rgstrId}, NOW(), #{controller}, #{menuLvl}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateMenu" parameterType="com.company.gw.envset.dto.MenuManageDto">
|
||||
UPDATE SX_CO0080
|
||||
SET UPPER_MENU_NO = NULLIF(#{upperMenuNo}, ''),
|
||||
MENU_NM = #{menuNm},
|
||||
URL = #{url},
|
||||
RM = #{rm},
|
||||
MENU_PROP = #{menuProp},
|
||||
MENU_ORDR = #{menuOrdr},
|
||||
MENU_USE_YN = #{menuUseYn},
|
||||
CONTROLLER = #{controller},
|
||||
MENU_LVL = #{menuLvl},
|
||||
MODID = #{modId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND MENU_NO = #{menuNo}
|
||||
</update>
|
||||
|
||||
<update id="updateMenu" parameterType="com.company.gw.envset.dto.MenuManageDto" databaseId="mariadb">
|
||||
UPDATE SX_CO0080
|
||||
SET UPPER_MENU_NO = NULLIF(#{upperMenuNo}, ''),
|
||||
MENU_NM = #{menuNm},
|
||||
URL = #{url},
|
||||
RM = #{rm},
|
||||
MENU_PROP = #{menuProp},
|
||||
MENU_ORDR = #{menuOrdr},
|
||||
MENU_USE_YN = #{menuUseYn},
|
||||
CONTROLLER = #{controller},
|
||||
MENU_LVL = #{menuLvl},
|
||||
MODID = #{modId},
|
||||
UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND MENU_NO = #{menuNo}
|
||||
</update>
|
||||
|
||||
<delete id="deleteMauthByMenu" parameterType="map">
|
||||
DELETE FROM SX_CO0090 WHERE CORP_NO = #{corpNo} AND MENU_NO = #{menuNo}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteMenu" parameterType="map">
|
||||
DELETE FROM SX_CO0080 WHERE CORP_NO = #{corpNo} AND MENU_NO = #{menuNo}
|
||||
</delete>
|
||||
|
||||
<!-- ===== 권한-메뉴 (SX_CO0090) ===== -->
|
||||
|
||||
<select id="getAuthMenuList" parameterType="map" resultType="com.company.gw.envset.dto.AuthMenuDto">
|
||||
WITH MENU_TREE AS (
|
||||
SELECT A.MENU_NO AS UP_MENU_NO, A.CORP_NO, A.MENU_NO, A.UPPER_MENU_NO,
|
||||
A.MENU_NM, A.URL, A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN,
|
||||
1 AS LVL,
|
||||
CAST('/' + RIGHT('00000' + CONVERT(VARCHAR, A.MENU_ORDR), 5) AS VARCHAR(MAX)) AS SORT_PATH
|
||||
FROM SX_CO0080 A
|
||||
WHERE A.CORP_NO = #{corpNo} AND NULLIF(A.UPPER_MENU_NO, '') IS NULL
|
||||
UNION ALL
|
||||
SELECT PARENT.UP_MENU_NO, A.CORP_NO, A.MENU_NO, A.UPPER_MENU_NO,
|
||||
A.MENU_NM, A.URL, A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN,
|
||||
PARENT.LVL + 1,
|
||||
PARENT.SORT_PATH + CAST('/' + RIGHT('00000' + CONVERT(VARCHAR, A.MENU_ORDR), 5) AS VARCHAR(MAX))
|
||||
FROM SX_CO0080 A
|
||||
JOIN MENU_TREE PARENT ON PARENT.CORP_NO = A.CORP_NO AND PARENT.MENU_NO = A.UPPER_MENU_NO
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
)
|
||||
SELECT A.MENU_NO, A.UPPER_MENU_NO, A.MENU_NM, A.URL,
|
||||
A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN, A.LVL,
|
||||
CASE WHEN B.MENU_NO IS NOT NULL THEN 'Y' ELSE 'N' END AS MENU_AUTH_YN,
|
||||
B.FUNC_AUTH_CN,
|
||||
#{menuAuthCd} AS MENU_AUTH_CD
|
||||
FROM MENU_TREE A
|
||||
LEFT JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO AND B.MENU_NO = A.MENU_NO AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
ORDER BY A.SORT_PATH
|
||||
</select>
|
||||
|
||||
<select id="getAuthMenuList" parameterType="map" resultType="com.company.gw.envset.dto.AuthMenuDto" databaseId="mariadb">
|
||||
WITH MENU_TREE AS (
|
||||
SELECT A.MENU_NO AS UP_MENU_NO, A.CORP_NO, A.MENU_NO, A.UPPER_MENU_NO,
|
||||
A.MENU_NM, A.URL, A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN,
|
||||
1 AS LVL,
|
||||
CONCAT('/', LPAD(A.MENU_ORDR, 5, '0')) AS SORT_PATH
|
||||
FROM SX_CO0080 A
|
||||
WHERE A.CORP_NO = #{corpNo} AND NULLIF(A.UPPER_MENU_NO, '') IS NULL
|
||||
UNION ALL
|
||||
SELECT PARENT.UP_MENU_NO, A.CORP_NO, A.MENU_NO, A.UPPER_MENU_NO,
|
||||
A.MENU_NM, A.URL, A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN,
|
||||
PARENT.LVL + 1,
|
||||
CONCAT(PARENT.SORT_PATH, '/', LPAD(A.MENU_ORDR, 5, '0'))
|
||||
FROM SX_CO0080 A
|
||||
JOIN MENU_TREE PARENT ON PARENT.CORP_NO = A.CORP_NO AND PARENT.MENU_NO = A.UPPER_MENU_NO
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
)
|
||||
SELECT A.MENU_NO, A.UPPER_MENU_NO, A.MENU_NM, A.URL,
|
||||
A.MENU_PROP, A.MENU_ORDR, A.MENU_USE_YN, A.LVL,
|
||||
CASE WHEN B.MENU_NO IS NOT NULL THEN 'Y' ELSE 'N' END AS MENU_AUTH_YN,
|
||||
B.FUNC_AUTH_CN,
|
||||
#{menuAuthCd} AS MENU_AUTH_CD
|
||||
FROM MENU_TREE A
|
||||
LEFT JOIN SX_CO0090 B
|
||||
ON B.CORP_NO = A.CORP_NO AND B.MENU_NO = A.MENU_NO AND B.MENU_AUTH_CD = #{menuAuthCd}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
ORDER BY A.SORT_PATH
|
||||
</select>
|
||||
|
||||
<insert id="mergeMenuAuth" parameterType="com.company.gw.envset.dto.AuthMenuDto">
|
||||
MERGE INTO SX_CO0090 T
|
||||
USING (SELECT 1 X) S
|
||||
ON (T.CORP_NO = #{corpNo} AND T.MENU_NO = #{menuNo} AND T.MENU_AUTH_CD = #{menuAuthCd})
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (CORP_NO, MENU_NO, MENU_AUTH_CD, FUNC_AUTH_CN, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{menuNo}, #{menuAuthCd}, #{funcAuthCn}, #{rgstrId}, GETDATE(), #{rgstrId}, GETDATE())
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET FUNC_AUTH_CN = #{funcAuthCn}, MODID = #{modId}, UPD_DT = GETDATE();
|
||||
</insert>
|
||||
|
||||
<insert id="mergeMenuAuth" parameterType="com.company.gw.envset.dto.AuthMenuDto" databaseId="mariadb">
|
||||
INSERT INTO SX_CO0090 (CORP_NO, MENU_NO, MENU_AUTH_CD, FUNC_AUTH_CN, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{menuNo}, #{menuAuthCd}, #{funcAuthCn}, #{rgstrId}, NOW(), #{rgstrId}, NOW())
|
||||
ON DUPLICATE KEY UPDATE FUNC_AUTH_CN = #{funcAuthCn}, MODID = #{modId}, UPD_DT = NOW()
|
||||
</insert>
|
||||
|
||||
<delete id="deleteMenuAuth" parameterType="map">
|
||||
DELETE FROM SX_CO0090
|
||||
WHERE CORP_NO = #{corpNo} AND MENU_NO = #{menuNo} AND MENU_AUTH_CD = #{menuAuthCd}
|
||||
</delete>
|
||||
|
||||
<!-- ===== 사용자-메뉴권한 (SX_GW0130) ===== -->
|
||||
|
||||
<select id="getUserMauthList" parameterType="map" resultType="com.company.gw.envset.dto.UserAuthDto">
|
||||
SELECT A.USR_ID, A.MENU_AUTH_CD,
|
||||
U.USR_NM, U.TEAM_CD, U.DUTY_CD, U.RETIREMENT_DATE
|
||||
FROM SX_GW0130 A
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.USR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (#{menuAuthCd} IS NULL OR A.MENU_AUTH_CD = #{menuAuthCd})
|
||||
AND (#{usrNm} IS NULL OR U.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
ORDER BY A.MENU_AUTH_CD, U.USR_SORT_ORDR, A.USR_ID
|
||||
</select>
|
||||
|
||||
<insert id="insertUserMauth" parameterType="com.company.gw.envset.dto.UserAuthDto">
|
||||
INSERT INTO SX_GW0130 (CORP_NO, USR_ID, MENU_AUTH_CD, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{menuAuthCd}, #{rgstrId}, GETDATE(), #{rgstrId}, GETDATE())
|
||||
</insert>
|
||||
|
||||
<insert id="insertUserMauth" parameterType="com.company.gw.envset.dto.UserAuthDto" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0130 (CORP_NO, USR_ID, MENU_AUTH_CD, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{menuAuthCd}, #{rgstrId}, NOW(), #{rgstrId}, NOW())
|
||||
</insert>
|
||||
|
||||
<delete id="deleteUserMauth" parameterType="map">
|
||||
DELETE FROM SX_GW0130
|
||||
WHERE CORP_NO = #{corpNo} AND USR_ID = #{usrId} AND MENU_AUTH_CD = #{menuAuthCd}
|
||||
</delete>
|
||||
|
||||
<!-- 사용자 검색 (autocomplete) -->
|
||||
<select id="searchUser" parameterType="map" resultType="map">
|
||||
SELECT TOP 20 USR_ID, USR_NM, TEAM_CD, DUTY_CD
|
||||
FROM SX_GW0010
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_NM LIKE CONCAT('%', #{keyword}, '%')
|
||||
AND NULLIF(RETIREMENT_DATE, '') IS NULL
|
||||
ORDER BY USR_SORT_ORDR, USR_ID
|
||||
</select>
|
||||
|
||||
<select id="searchUser" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT USR_ID, USR_NM, TEAM_CD, DUTY_CD
|
||||
FROM SX_GW0010
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_NM LIKE CONCAT('%', #{keyword}, '%')
|
||||
AND NULLIF(RETIREMENT_DATE, '') IS NULL
|
||||
ORDER BY USR_SORT_ORDR, USR_ID
|
||||
LIMIT 20
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
125
backend/src/main/resources/mapper/fedex/fedex_sql.xml
Normal file
125
backend/src/main/resources/mapper/fedex/fedex_sql.xml
Normal file
@@ -0,0 +1,125 @@
|
||||
<?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="com.company.gw.fedex.mapper.FedexMapper">
|
||||
|
||||
<!-- 목록 건수 -->
|
||||
<select id="countFedexList" parameterType="map" resultType="int">
|
||||
SELECT COUNT(*) FROM errorMng
|
||||
<where>
|
||||
<if test="searchText != null and searchText != ''">
|
||||
AND com_nm LIKE CONCAT('%', #{searchText}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 목록 조회 MSSQL -->
|
||||
<select id="getFedexList" parameterType="map" resultType="map">
|
||||
SELECT sq, e.ie_gbn, e.s_code, e.s_year, e.s_jechl,
|
||||
(e.s_code +'-'+ e.s_year +'-'+ e.s_jechl) AS singoNo,
|
||||
e.com_nm, e.j_singo_dt, e.s_singo_dt,
|
||||
e.reg_user_id, e.f_st_cd, e.f_jj_cd, e.f_jj_contents,
|
||||
e.f_jj_nm, e.f_jj_reg_dt, e.f_jj_reg_gbn,
|
||||
e.ATTACH_NO,
|
||||
fst.f_st_des, gw.j_gwi_des, fgb.f_jj_des1
|
||||
FROM errorMng e
|
||||
LEFT JOIN f_jj_st fst ON e.f_st_cd = fst.f_st_cd
|
||||
LEFT JOIN gwi_gbn gw ON e.j_gwi_cd = gw.j_gwi_cd
|
||||
LEFT JOIN f_jj_gbn fgb ON e.f_jj_cd = fgb.f_jj_cd
|
||||
<where>
|
||||
<if test="searchText != null and searchText != ''">
|
||||
AND e.com_nm LIKE CONCAT('%', #{searchText}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY e.s_singo_dt DESC
|
||||
OFFSET #{offset} ROWS FETCH NEXT #{pageSize} ROWS ONLY
|
||||
</select>
|
||||
|
||||
<!-- 목록 조회 MariaDB -->
|
||||
<select id="getFedexList" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT sq, e.ie_gbn, e.s_code, e.s_year, e.s_jechl,
|
||||
CONCAT(e.s_code, '-', e.s_year, '-', e.s_jechl) AS singoNo,
|
||||
e.com_nm, e.j_singo_dt, e.s_singo_dt,
|
||||
e.reg_user_id, e.f_st_cd, e.f_jj_cd, e.f_jj_contents,
|
||||
e.f_jj_nm, e.f_jj_reg_dt, e.f_jj_reg_gbn,
|
||||
e.ATTACH_NO,
|
||||
fst.f_st_des, gw.j_gwi_des, fgb.f_jj_des1
|
||||
FROM errorMng e
|
||||
LEFT JOIN f_jj_st fst ON e.f_st_cd = fst.f_st_cd
|
||||
LEFT JOIN gwi_gbn gw ON e.j_gwi_cd = gw.j_gwi_cd
|
||||
LEFT JOIN f_jj_gbn fgb ON e.f_jj_cd = fgb.f_jj_cd
|
||||
<where>
|
||||
<if test="searchText != null and searchText != ''">
|
||||
AND e.com_nm LIKE CONCAT('%', #{searchText}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY e.s_singo_dt DESC
|
||||
LIMIT #{pageSize} OFFSET #{offset}
|
||||
</select>
|
||||
|
||||
<!-- 상세 조회 -->
|
||||
<select id="getFedexDetail" parameterType="map" resultType="map">
|
||||
SELECT sq, e.ie_gbn, e.s_code, e.s_year, e.s_jechl,
|
||||
(e.s_code +'-'+ e.s_year +'-'+ e.s_jechl) AS singoNo,
|
||||
e.com_nm, e.j_singo_dt, e.s_singo_dt,
|
||||
e.j_gwi_cd, e.reg_user_id, e.f_st_cd, e.f_jj_cd,
|
||||
e.f_jj_contents, e.f_jj_nm, e.f_jj_reg_dt, e.f_jj_reg_gbn,
|
||||
e.u_title, e.u_res, e.u_reg_dt, e.ATTACH_NO,
|
||||
fst.f_st_des, gw.j_gwi_des, fgb.f_jj_des1
|
||||
FROM errorMng e
|
||||
LEFT JOIN f_jj_st fst ON e.f_st_cd = fst.f_st_cd
|
||||
LEFT JOIN gwi_gbn gw ON e.j_gwi_cd = gw.j_gwi_cd
|
||||
LEFT JOIN f_jj_gbn fgb ON e.f_jj_cd = fgb.f_jj_cd
|
||||
WHERE e.sq = #{sq}
|
||||
</select>
|
||||
|
||||
<!-- 상세 조회 MariaDB -->
|
||||
<select id="getFedexDetail" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT sq, e.ie_gbn, e.s_code, e.s_year, e.s_jechl,
|
||||
CONCAT(e.s_code, '-', e.s_year, '-', e.s_jechl) AS singoNo,
|
||||
e.com_nm, e.j_singo_dt, e.s_singo_dt,
|
||||
e.j_gwi_cd, e.reg_user_id, e.f_st_cd, e.f_jj_cd,
|
||||
e.f_jj_contents, e.f_jj_nm, e.f_jj_reg_dt, e.f_jj_reg_gbn,
|
||||
e.u_title, e.u_res, e.u_reg_dt, e.ATTACH_NO,
|
||||
fst.f_st_des, gw.j_gwi_des, fgb.f_jj_des1
|
||||
FROM errorMng e
|
||||
LEFT JOIN f_jj_st fst ON e.f_st_cd = fst.f_st_cd
|
||||
LEFT JOIN gwi_gbn gw ON e.j_gwi_cd = gw.j_gwi_cd
|
||||
LEFT JOIN f_jj_gbn fgb ON e.f_jj_cd = fgb.f_jj_cd
|
||||
WHERE e.sq = #{sq}
|
||||
</select>
|
||||
|
||||
<!-- 등록 MSSQL -->
|
||||
<insert id="insertFedex" parameterType="map" useGeneratedKeys="true" keyProperty="sq">
|
||||
INSERT INTO errorMng (
|
||||
ie_gbn, s_code, s_year, s_jechl, com_nm, j_singo_dt, s_singo_dt,
|
||||
j_gwi_cd, reg_user_id, f_st_cd, f_jj_cd, f_jj_contents,
|
||||
f_jj_nm, f_jj_reg_dt, f_jj_reg_gbn, ATTACH_NO
|
||||
) VALUES (
|
||||
#{ieGbn}, #{sCode}, #{sYear}, #{sJechl}, #{comNm}, #{jSingoDt}, #{sSingoDt},
|
||||
#{jGwiCd}, #{regUserId}, #{fStCd}, #{fJjCd}, #{fJjContents},
|
||||
#{fJjNm}, #{fJjRegDt}, #{fJjRegGbn},
|
||||
<choose><when test="attachNo != null and attachNo != ''">#{attachNo}</when><otherwise>''</otherwise></choose>
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- ATTACH_NO 업데이트 -->
|
||||
<update id="updateFedexAttach" parameterType="map">
|
||||
UPDATE errorMng SET ATTACH_NO = #{attachNo} WHERE sq = #{sq}
|
||||
</update>
|
||||
|
||||
<!-- f_jj_st 코드 목록 -->
|
||||
<select id="getFstList" resultType="map">
|
||||
SELECT f_st_cd, f_st_des FROM f_jj_st ORDER BY f_st_cd
|
||||
</select>
|
||||
|
||||
<!-- gwi_gbn 코드 목록 -->
|
||||
<select id="getGwiList" resultType="map">
|
||||
SELECT j_gwi_cd, j_gwi_des FROM gwi_gbn ORDER BY j_gwi_cd
|
||||
</select>
|
||||
|
||||
<!-- f_jj_gbn 코드 목록 -->
|
||||
<select id="getFjjList" resultType="map">
|
||||
SELECT f_jj_cd, f_jj_des1 FROM f_jj_gbn ORDER BY f_jj_cd
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
340
backend/src/main/resources/mapper/main/main_sql.xml
Normal file
340
backend/src/main/resources/mapper/main/main_sql.xml
Normal file
@@ -0,0 +1,340 @@
|
||||
<?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">
|
||||
<!--
|
||||
메인/대시보드
|
||||
결재상태: 0001=작성중, 0002=결재중, 0003=결재완료, 0004=반려
|
||||
-->
|
||||
<mapper namespace="com.company.gw.main.mapper.MainMapper">
|
||||
|
||||
<!-- 최신 게시물 (게시판 유형별 TOP N) MSSQL -->
|
||||
<select id="getTopPostList" parameterType="map" resultType="map">
|
||||
SELECT TOP(#{top})
|
||||
A.UNTY_BBS_SNO,
|
||||
A.UNTY_BBS_CD,
|
||||
A.BBS_TITLE_NM,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
CONVERT(VARCHAR, A.RGST_DT, 120) AS RGST_DT,
|
||||
U.USR_NM AS RGSTR_NM,
|
||||
CASE WHEN DATEDIFF(DD, A.RGST_DT, GETDATE()) < 8 THEN 'Y' ELSE 'N' END AS IS_NEW
|
||||
FROM SX_GW0020 A
|
||||
JOIN SX_GW0010 U
|
||||
ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.RGSTR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{bbsCd}
|
||||
ORDER BY A.RGST_DT DESC
|
||||
</select>
|
||||
|
||||
<!-- 최신 게시물 MariaDB -->
|
||||
<select id="getTopPostList" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT A.UNTY_BBS_SNO,
|
||||
A.UNTY_BBS_CD,
|
||||
A.BBS_TITLE_NM,
|
||||
A.INQR_CNT,
|
||||
A.CMMT_CNT,
|
||||
DATE_FORMAT(A.RGST_DT, '%Y-%m-%d %H:%i:%s') AS RGST_DT,
|
||||
U.USR_NM AS RGSTR_NM,
|
||||
CASE WHEN DATEDIFF(CURDATE(), DATE(A.RGST_DT)) < 8 THEN 'Y' ELSE 'N' END AS IS_NEW
|
||||
FROM SX_GW0020 A
|
||||
JOIN SX_GW0010 U
|
||||
ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.RGSTR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.UNTY_BBS_CD = #{bbsCd}
|
||||
ORDER BY A.RGST_DT DESC
|
||||
LIMIT #{top}
|
||||
</select>
|
||||
|
||||
<!-- 9일 범위 근무 기록 (오늘±4일, 미래=근무계획 포함) MSSQL -->
|
||||
<select id="getWorkRangeList" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
CONVERT(VARCHAR, A.WORK_START_DT, 120) AS WORK_START_DT,
|
||||
CONVERT(VARCHAR, A.WORK_END_DT, 120) AS WORK_END_DT,
|
||||
A.TOT_WORK_MIN,
|
||||
A.LATE_MIN,
|
||||
A.OT_WORK_MIN,
|
||||
ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD >= #{fromDate}
|
||||
AND A.WORK_PLAN_YYMMDD <= #{toDate}
|
||||
ORDER BY A.WORK_PLAN_YYMMDD
|
||||
</select>
|
||||
|
||||
<!-- 9일 범위 근무 기록 MariaDB -->
|
||||
<select id="getWorkRangeList" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
DATE_FORMAT(A.WORK_START_DT, '%Y-%m-%d %H:%i:%s') AS WORK_START_DT,
|
||||
DATE_FORMAT(A.WORK_END_DT, '%Y-%m-%d %H:%i:%s') AS WORK_END_DT,
|
||||
A.TOT_WORK_MIN,
|
||||
A.LATE_MIN,
|
||||
A.OT_WORK_MIN,
|
||||
IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD >= #{fromDate}
|
||||
AND A.WORK_PLAN_YYMMDD <= #{toDate}
|
||||
ORDER BY A.WORK_PLAN_YYMMDD
|
||||
</select>
|
||||
|
||||
<!-- 오늘 근무 기록 (현재 일자) MSSQL -->
|
||||
<select id="getTodayWorkRecord" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
CONVERT(VARCHAR, A.WORK_START_DT, 120) AS WORK_START_DT,
|
||||
CONVERT(VARCHAR, A.WORK_END_DT, 120) AS WORK_END_DT,
|
||||
A.TOT_WORK_MIN,
|
||||
A.LATE_MIN,
|
||||
A.OT_WORK_MIN,
|
||||
A.PLAN_WORK_CD,
|
||||
ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD
|
||||
FROM SX_GW0050 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
</select>
|
||||
|
||||
<!-- 오늘 근무 기록 MariaDB -->
|
||||
<select id="getTodayWorkRecord" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
DATE_FORMAT(A.WORK_START_DT, '%Y-%m-%d %H:%i:%s') AS WORK_START_DT,
|
||||
DATE_FORMAT(A.WORK_END_DT, '%Y-%m-%d %H:%i:%s') AS WORK_END_DT,
|
||||
A.TOT_WORK_MIN,
|
||||
A.LATE_MIN,
|
||||
A.OT_WORK_MIN,
|
||||
A.PLAN_WORK_CD,
|
||||
IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD
|
||||
FROM SX_GW0050 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
</select>
|
||||
|
||||
<!-- 결재 대기 건수 (내가 결재해야 할 차례, APPR_STUS_CD=0002) MSSQL -->
|
||||
<select id="getPendingApprCount" parameterType="map" resultType="map">
|
||||
SELECT COUNT(1) AS PENDING_CNT
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0090 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APPR_ID = #{usrId}
|
||||
AND A.APPR_STUS_CD = '0002'
|
||||
AND B.APRVL_STUS_CD = '0002'
|
||||
</select>
|
||||
|
||||
<!-- 내가 올린 결재 문서 현황 (상태별 카운트) MSSQL -->
|
||||
<select id="getMyDocSentSummary" parameterType="map" resultType="map">
|
||||
SELECT APRVL_STUS_CD, COUNT(1) AS CNT
|
||||
FROM SX_GW0090
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APLNT_ID = #{usrId}
|
||||
GROUP BY APRVL_STUS_CD
|
||||
</select>
|
||||
|
||||
<!-- 내가 올린 결재 문서 현황 MariaDB -->
|
||||
<select id="getMyDocSentSummary" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT APRVL_STUS_CD, COUNT(1) AS CNT
|
||||
FROM SX_GW0090
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APLNT_ID = #{usrId}
|
||||
GROUP BY APRVL_STUS_CD
|
||||
</select>
|
||||
|
||||
<!-- 내가 받은 결재 문서 현황 (상태별 카운트, 제출된 문서만) MSSQL -->
|
||||
<select id="getMyDocReceivedSummary" parameterType="map" resultType="map">
|
||||
SELECT ISNULL(A.APPR_STUS_CD, 'WAIT') AS APPR_STUS_CD, COUNT(1) AS CNT
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0090 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APPR_ID = #{usrId}
|
||||
AND B.APRVL_STUS_CD IN ('0002', '0003', '0004')
|
||||
GROUP BY ISNULL(A.APPR_STUS_CD, 'WAIT')
|
||||
</select>
|
||||
|
||||
<!-- 내가 받은 결재 문서 현황 MariaDB -->
|
||||
<select id="getMyDocReceivedSummary" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT IFNULL(A.APPR_STUS_CD, 'WAIT') AS APPR_STUS_CD, COUNT(1) AS CNT
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0090 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APPR_ID = #{usrId}
|
||||
AND B.APRVL_STUS_CD IN ('0002', '0003', '0004')
|
||||
GROUP BY IFNULL(A.APPR_STUS_CD, 'WAIT')
|
||||
</select>
|
||||
|
||||
<!-- 오늘 전체 근무 현황 (근무코드별 그룹) MSSQL -->
|
||||
<select id="getTodayWorkSummary" parameterType="map" resultType="map">
|
||||
SELECT ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM,
|
||||
COUNT(*) AS TOTAL_CNT,
|
||||
SUM(CASE WHEN A.WORK_START_DT IS NOT NULL THEN 1 ELSE 0 END) AS IN_CNT,
|
||||
SUM(CASE WHEN A.WORK_END_DT IS NOT NULL THEN 1 ELSE 0 END) AS OUT_CNT
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
GROUP BY ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD),
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
ORDER BY REAL_WORK_CD
|
||||
</select>
|
||||
|
||||
<!-- 오늘 전체 근무 현황 MariaDB -->
|
||||
<select id="getTodayWorkSummary" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM,
|
||||
COUNT(*) AS TOTAL_CNT,
|
||||
SUM(CASE WHEN A.WORK_START_DT IS NOT NULL THEN 1 ELSE 0 END) AS IN_CNT,
|
||||
SUM(CASE WHEN A.WORK_END_DT IS NOT NULL THEN 1 ELSE 0 END) AS OUT_CNT
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
GROUP BY IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD),
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
ORDER BY REAL_WORK_CD
|
||||
</select>
|
||||
|
||||
<!-- ─────────────────────────────────────────────
|
||||
출퇴근 - 근무계획 단건 조회 (MSSQL)
|
||||
───────────────────────────────────────────── -->
|
||||
<select id="getWorkplanInfo" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
CONVERT(VARCHAR, A.WORK_START_DT, 120) AS WORK_START_DT,
|
||||
CONVERT(VARCHAR, A.WORK_END_DT, 120) AS WORK_END_DT,
|
||||
A.PLAN_WORK_CD,
|
||||
ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</select>
|
||||
|
||||
<!-- 출퇴근 - 근무계획 단건 조회 (MariaDB) -->
|
||||
<select id="getWorkplanInfo" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
DATE_FORMAT(A.WORK_START_DT, '%Y-%m-%d %H:%i:%s') AS WORK_START_DT,
|
||||
DATE_FORMAT(A.WORK_END_DT, '%Y-%m-%d %H:%i:%s') AS WORK_END_DT,
|
||||
A.PLAN_WORK_CD,
|
||||
IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</select>
|
||||
|
||||
<!-- 허용 IP 목록 조회 -->
|
||||
<select id="getAllowedIpList" parameterType="map" resultType="string">
|
||||
SELECT A.COMM_CD_NM
|
||||
FROM SX_CO0040 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.COMM_CL_CD = 'SX014'
|
||||
AND A.COMM_CD_USE_YN = 'Y'
|
||||
ORDER BY A.COMM_CD_DSPLY_ORDR
|
||||
</select>
|
||||
|
||||
<!-- 출근 시간 업데이트 (MSSQL) -->
|
||||
<update id="updateWorkStart" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET WORK_START_DT = GETDATE(),
|
||||
REAL_START_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</update>
|
||||
|
||||
<!-- 출근 시간 업데이트 (MariaDB) -->
|
||||
<update id="updateWorkStart" databaseId="mariadb" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET WORK_START_DT = NOW(),
|
||||
REAL_START_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</update>
|
||||
|
||||
<!-- 퇴근 시간 업데이트 (MSSQL) -->
|
||||
<update id="updateWorkEnd" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET WORK_END_DT = GETDATE(),
|
||||
REAL_END_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</update>
|
||||
|
||||
<!-- 퇴근 시간 업데이트 (MariaDB) -->
|
||||
<update id="updateWorkEnd" databaseId="mariadb" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET WORK_END_DT = NOW(),
|
||||
REAL_END_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
</update>
|
||||
|
||||
<!-- 오늘 지각자 목록 (MSSQL) -->
|
||||
<select id="getTodayLateList" parameterType="map" resultType="map">
|
||||
SELECT U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD,
|
||||
A.LATE_MIN,
|
||||
CONVERT(VARCHAR, A.WORK_START_DT, 120) AS WORK_START_DT
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 U
|
||||
ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.USR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
AND A.LATE_MIN > 0
|
||||
AND A.WORK_START_DT IS NOT NULL
|
||||
ORDER BY A.LATE_MIN DESC
|
||||
</select>
|
||||
|
||||
<!-- 오늘 지각자 목록 (MariaDB) -->
|
||||
<select id="getTodayLateList" databaseId="mariadb" parameterType="map" resultType="map">
|
||||
SELECT U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD,
|
||||
A.LATE_MIN,
|
||||
DATE_FORMAT(A.WORK_START_DT, '%Y-%m-%d %H:%i:%s') AS WORK_START_DT
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 U
|
||||
ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.USR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD = #{today}
|
||||
AND A.LATE_MIN > 0
|
||||
AND A.WORK_START_DT IS NOT NULL
|
||||
ORDER BY A.LATE_MIN DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
321
backend/src/main/resources/mapper/tam/apvdoc_sql.xml
Normal file
321
backend/src/main/resources/mapper/tam/apvdoc_sql.xml
Normal file
@@ -0,0 +1,321 @@
|
||||
<?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">
|
||||
<!-- 원본: src/java/sql/biz/common/apvdoc_sql.xml
|
||||
테이블: SX_GW0090(결재문서), SX_GW0100(결재자), SX_GW0010(사용자)
|
||||
결재상태: 0001=작성중, 0002=결재중, 0003=결재완료, 0004=반려 -->
|
||||
<mapper namespace="com.company.gw.tam.mapper.ApvdocMapper">
|
||||
|
||||
<!-- ===================== MSSQL (default) ===================== -->
|
||||
|
||||
<!-- 결재문서 상세 -->
|
||||
<select id="getApvdocInfo" parameterType="map" resultType="map">
|
||||
SELECT A.CORP_NO,
|
||||
ISNULL(A.DOC_FLAG, '') AS DOC_FLAG,
|
||||
A.APRVL_DOC_ID, A.APRVL_STUS_CD, A.APRVL_KIND_CD,
|
||||
A.APLNT_ID, A.APLNT_CN, A.BZ_CN, A.ATCH_NO, A.OFFER_CN,
|
||||
A.APRVL_CMPL_SNO, A.FINAL_APRVL_SNO, A.RGSTR_ID, A.BZ_DEPUTY_ID,
|
||||
CONVERT(VARCHAR, A.OFFER_DT, 120) AS OFFER_DT,
|
||||
CONVERT(VARCHAR, A.CMPL_DT, 120) AS CMPL_DT,
|
||||
U.USR_NM AS APLNT_NM, U.TEAM_CD AS APLNT_TEAM_CD, U.DUTY_CD AS APLNT_DUTY_CD,
|
||||
U2.USR_NM AS BZ_DEPUTY_NM, U2.TEAM_CD AS BZ_DEPUTY_TEAM_CD, U2.DUTY_CD AS BZ_DEPUTY_DUTY_CD
|
||||
FROM SX_GW0090 A
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.APLNT_ID
|
||||
LEFT JOIN SX_GW0010 U2 ON U2.CORP_NO = A.CORP_NO AND U2.USR_ID = A.BZ_DEPUTY_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
</select>
|
||||
|
||||
<!-- 결재자 목록 -->
|
||||
<select id="getApprList" parameterType="map" resultType="map">
|
||||
SELECT A.APRVL_DOC_ID, A.APRVL_SNO, A.APPR_ID,
|
||||
A.APPR_STUS_CD, A.APPR_CN, A.DOC_FLAG,
|
||||
CONVERT(VARCHAR, A.APRVL_DT, 120) AS APRVL_DT,
|
||||
U.USR_NM AS APPR_NM, U.TEAM_CD AS APPR_TEAM_CD, U.DUTY_CD AS APPR_DUTY_CD
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.APPR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
ORDER BY A.APRVL_SNO
|
||||
</select>
|
||||
|
||||
<!-- 특정 결재자 정보 (최종 결재자 여부 포함) -->
|
||||
<select id="getApprInfo" parameterType="map" resultType="map">
|
||||
SELECT A.APRVL_SNO, A.APPR_ID, A.APPR_STUS_CD, A.APPR_CN,
|
||||
CASE WHEN NOT EXISTS (
|
||||
SELECT 1 FROM SX_GW0100 AA
|
||||
WHERE AA.CORP_NO = A.CORP_NO AND AA.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
AND AA.APRVL_SNO > A.APRVL_SNO
|
||||
) THEN 'Y' ELSE 'N' END AS FINAL_APPR_YN
|
||||
FROM SX_GW0100 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND A.APRVL_SNO = #{aprvlSno}
|
||||
</select>
|
||||
|
||||
<!-- 결재문서 생성 (작성중 0001) -->
|
||||
<insert id="insertApvdoc" parameterType="map">
|
||||
INSERT INTO SX_GW0090 (
|
||||
CORP_NO, APRVL_DOC_ID, APRVL_STUS_CD, APRVL_KIND_CD,
|
||||
APLNT_ID, APLNT_CN, BZ_CN, OFFER_CN, BZ_DEPUTY_ID,
|
||||
OFFER_DT, CMPL_DT, ATCH_NO, APRVL_CMPL_SNO, FINAL_APRVL_SNO,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{aprvlDocId}, '0001', #{aprvlKindCd},
|
||||
#{usrId}, #{aplntCn}, #{bzCn}, #{offerCn}, #{bzDeputyId},
|
||||
NULL, NULL, #{atchNo}, NULL, NULL,
|
||||
#{usrId}, GETDATE(), #{usrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 결재문서 내용 수정 -->
|
||||
<update id="updateApvdocContent" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET APLNT_CN = #{aplntCn},
|
||||
BZ_CN = #{bzCn},
|
||||
OFFER_CN = #{offerCn},
|
||||
BZ_DEPUTY_ID= #{bzDeputyId},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 첨부번호 업데이트 -->
|
||||
<update id="updateApvdocAtchNo" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET ATCH_NO = #{atchNo}
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 상신 → 결재중(0002) -->
|
||||
<update id="updateApvdocStatusRequest" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0002',
|
||||
OFFER_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 결재완료(0003) -->
|
||||
<update id="updateApvdocStatusApprove" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0003',
|
||||
CMPL_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 반려(0004) -->
|
||||
<update id="updateApvdocStatusReject" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0004',
|
||||
CMPL_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 결재완료 최고 순번 업데이트 (DECLARE 제거 → 서브쿼리) -->
|
||||
<update id="updateFinalAprvlSno" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET FINAL_APRVL_SNO = (
|
||||
SELECT MAX(AA.APRVL_SNO) FROM SX_GW0100 AA
|
||||
WHERE AA.CORP_NO = #{corpNo} AND AA.APRVL_DOC_ID = #{aprvlDocId}
|
||||
)
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 현재 결재 완료 순번 업데이트 -->
|
||||
<update id="updateAprvlCmplSno" parameterType="map">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_CMPL_SNO = (
|
||||
SELECT MAX(CASE WHEN AA.APRVL_DT IS NOT NULL THEN AA.APRVL_SNO END)
|
||||
FROM SX_GW0100 AA
|
||||
WHERE AA.CORP_NO = #{corpNo} AND AA.APRVL_DOC_ID = #{aprvlDocId}
|
||||
)
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 결재자 전체 삭제 (재등록 전) -->
|
||||
<delete id="deleteApprAll" parameterType="map">
|
||||
DELETE FROM SX_GW0100
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
|
||||
<!-- 결재자 등록 -->
|
||||
<insert id="insertAppr" parameterType="map">
|
||||
INSERT INTO SX_GW0100 (
|
||||
CORP_NO, APRVL_DOC_ID, APRVL_SNO, APPR_ID,
|
||||
APPR_STUS_CD, APRVL_DT, APPR_CN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{aprvlDocId}, #{aprvlSno}, #{apprId},
|
||||
NULL, NULL, NULL,
|
||||
#{usrId}, GETDATE(), #{usrId}, GETDATE()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 결재자 상태 변경 -->
|
||||
<update id="updateApprStatus" parameterType="map">
|
||||
UPDATE SX_GW0100
|
||||
SET APPR_STUS_CD = #{apprStusCd},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND APRVL_SNO = #{aprvlSno}
|
||||
</update>
|
||||
|
||||
<!-- 결재자 승인/반려 처리 -->
|
||||
<update id="apprApproveOrReject" parameterType="map">
|
||||
UPDATE SX_GW0100
|
||||
SET APPR_STUS_CD = #{apprStusCd},
|
||||
APRVL_DT = GETDATE(),
|
||||
APPR_CN = #{apprCn},
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND APRVL_SNO = #{aprvlSno}
|
||||
</update>
|
||||
|
||||
<!-- 다음 결재자 결재중(0002)으로 변경 -->
|
||||
<update id="updateNextApprStatusAppring" parameterType="map">
|
||||
UPDATE SX_GW0100
|
||||
SET APPR_STUS_CD = '0002',
|
||||
MODID = #{usrId},
|
||||
UPD_DT = GETDATE()
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND APRVL_SNO = (
|
||||
SELECT MIN(AA.APRVL_SNO) FROM SX_GW0100 AA
|
||||
WHERE AA.CORP_NO = #{corpNo}
|
||||
AND AA.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND AA.APRVL_SNO > #{aprvlSno}
|
||||
)
|
||||
</update>
|
||||
|
||||
<!-- 결재문서 삭제 (하위 데이터 포함) -->
|
||||
<delete id="deleteApvdocSx0080" parameterType="map">
|
||||
DELETE FROM SX_GW0080 WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
<delete id="deleteApvdocSx0110" parameterType="map">
|
||||
DELETE FROM SX_GW0110 WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
<delete id="deleteApvdocSx0090" parameterType="map">
|
||||
DELETE FROM SX_GW0090 WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
|
||||
<!-- 신청자 반려 확인 처리 -->
|
||||
<update id="updateApvdocDocFlagAplnt" parameterType="map">
|
||||
UPDATE SX_GW0090 SET DOC_FLAG = 'A'
|
||||
WHERE CORP_NO = #{corpNo} AND APLNT_ID = #{usrId} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 반려 시 근무 종료시간 초기화 -->
|
||||
<update id="resetWorkEndDt" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET WORK_END_DT = NULL
|
||||
FROM SX_GW0050 g
|
||||
LEFT JOIN SX_GW0090 d9 ON g.USR_ID = d9.APLNT_ID AND g.CORP_NO = d9.CORP_NO
|
||||
LEFT JOIN SX_GW0080 d8 ON d9.APRVL_DOC_ID = d8.APRVL_DOC_ID AND d9.CORP_NO = d8.CORP_NO
|
||||
WHERE g.CORP_NO = #{corpNo}
|
||||
AND d9.APRVL_KIND_CD = '0003'
|
||||
AND d9.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND d8.APRVL_DOC_ID IS NOT NULL
|
||||
AND g.WORK_PLAN_YYMMDD = d8.LATE_SKIPOFF_ABTI_OT_DATE
|
||||
</update>
|
||||
|
||||
<!-- ===================== MariaDB ===================== -->
|
||||
|
||||
<select id="getApvdocInfo" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.CORP_NO,
|
||||
IFNULL(A.DOC_FLAG, '') AS DOC_FLAG,
|
||||
A.APRVL_DOC_ID, A.APRVL_STUS_CD, A.APRVL_KIND_CD,
|
||||
A.APLNT_ID, A.APLNT_CN, A.BZ_CN, A.ATCH_NO, A.OFFER_CN,
|
||||
A.APRVL_CMPL_SNO, A.FINAL_APRVL_SNO, A.RGSTR_ID, A.BZ_DEPUTY_ID,
|
||||
DATE_FORMAT(A.OFFER_DT, '%Y-%m-%d %H:%i:%s') AS OFFER_DT,
|
||||
DATE_FORMAT(A.CMPL_DT, '%Y-%m-%d %H:%i:%s') AS CMPL_DT,
|
||||
U.USR_NM AS APLNT_NM, U.TEAM_CD AS APLNT_TEAM_CD, U.DUTY_CD AS APLNT_DUTY_CD,
|
||||
U2.USR_NM AS BZ_DEPUTY_NM, U2.TEAM_CD AS BZ_DEPUTY_TEAM_CD, U2.DUTY_CD AS BZ_DEPUTY_DUTY_CD
|
||||
FROM SX_GW0090 A
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.APLNT_ID
|
||||
LEFT JOIN SX_GW0010 U2 ON U2.CORP_NO = A.CORP_NO AND U2.USR_ID = A.BZ_DEPUTY_ID
|
||||
WHERE A.CORP_NO = #{corpNo} AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
</select>
|
||||
|
||||
<select id="getApprList" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.APRVL_DOC_ID, A.APRVL_SNO, A.APPR_ID,
|
||||
A.APPR_STUS_CD, A.APPR_CN, A.DOC_FLAG,
|
||||
DATE_FORMAT(A.APRVL_DT, '%Y-%m-%d %H:%i:%s') AS APRVL_DT,
|
||||
U.USR_NM AS APPR_NM, U.TEAM_CD AS APPR_TEAM_CD, U.DUTY_CD AS APPR_DUTY_CD
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = A.CORP_NO AND U.USR_ID = A.APPR_ID
|
||||
WHERE A.CORP_NO = #{corpNo} AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
ORDER BY A.APRVL_SNO
|
||||
</select>
|
||||
|
||||
<insert id="insertApvdoc" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0090 (
|
||||
CORP_NO, APRVL_DOC_ID, APRVL_STUS_CD, APRVL_KIND_CD,
|
||||
APLNT_ID, APLNT_CN, BZ_CN, OFFER_CN, BZ_DEPUTY_ID,
|
||||
OFFER_DT, CMPL_DT, ATCH_NO, APRVL_CMPL_SNO, FINAL_APRVL_SNO,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{aprvlDocId}, '0001', #{aprvlKindCd},
|
||||
#{usrId}, #{aplntCn}, #{bzCn}, #{offerCn}, #{bzDeputyId},
|
||||
NULL, NULL, #{atchNo}, NULL, NULL,
|
||||
#{usrId}, NOW(), #{usrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="updateApvdocContent" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0090
|
||||
SET APLNT_CN = #{aplntCn}, BZ_CN = #{bzCn},
|
||||
OFFER_CN = #{offerCn}, BZ_DEPUTY_ID = #{bzDeputyId},
|
||||
MODID = #{usrId}, UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<update id="updateApvdocStatusRequest" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0002', OFFER_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<update id="updateApvdocStatusApprove" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0003', CMPL_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<update id="updateApvdocStatusReject" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0090
|
||||
SET APRVL_STUS_CD = '0004', CMPL_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<insert id="insertAppr" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0100 (
|
||||
CORP_NO, APRVL_DOC_ID, APRVL_SNO, APPR_ID,
|
||||
APPR_STUS_CD, APRVL_DT, APPR_CN,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT
|
||||
) VALUES (
|
||||
#{corpNo}, #{aprvlDocId}, #{aprvlSno}, #{apprId},
|
||||
NULL, NULL, NULL,
|
||||
#{usrId}, NOW(), #{usrId}, NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<update id="apprApproveOrReject" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0100
|
||||
SET APPR_STUS_CD = #{apprStusCd}, APRVL_DT = NOW(),
|
||||
APPR_CN = #{apprCn}, MODID = #{usrId}, UPD_DT = NOW()
|
||||
WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId} AND APRVL_SNO = #{aprvlSno}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
417
backend/src/main/resources/mapper/tam/tam_sql.xml
Normal file
417
backend/src/main/resources/mapper/tam/tam_sql.xml
Normal file
@@ -0,0 +1,417 @@
|
||||
<?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">
|
||||
<!-- 원본: tam0010~0040_sql.xml 통합
|
||||
테이블: SX_GW0060(연차), SX_GW0080(시간외/지각/조퇴), SX_GW0090(결재문서),
|
||||
SX_GW0100(결재자), SX_GW0110(변경근무) -->
|
||||
<mapper namespace="com.company.gw.tam.mapper.TamMapper">
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- TAM0010 - 연차 관리 -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<!-- 연차 목록 (직원별) -->
|
||||
<select id="getYyvctList" parameterType="map" resultType="map">
|
||||
SELECT A.USR_ID, A.USR_NM, A.BZ_CD, A.TEAM_CD, A.DUTY_CD,
|
||||
#{yyvctYy} AS YYVCT_YY,
|
||||
B.YYVCT_CNT
|
||||
FROM SX_GW0010 A
|
||||
LEFT JOIN SX_GW0060 B
|
||||
ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.USR_ID AND B.YYVCT_YY = #{yyvctYy}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (#{usrNm} IS NULL OR #{usrNm} = '' OR A.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
AND (#{teamCd} IS NULL OR #{teamCd} = '' OR A.TEAM_CD = #{teamCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR A.RETIREMENT_DATE IS NULL OR A.RETIREMENT_DATE = '')
|
||||
ORDER BY A.USR_NM
|
||||
</select>
|
||||
|
||||
<!-- 연차 저장 (MERGE) -->
|
||||
<update id="upsertYyvct" parameterType="map">
|
||||
MERGE INTO SX_GW0060 T
|
||||
USING (SELECT 1 AS DUMMY) S
|
||||
ON (T.CORP_NO = #{corpNo} AND T.USR_ID = #{usrId} AND T.YYVCT_YY = #{yyvctYy})
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (CORP_NO, USR_ID, YYVCT_YY, YYVCT_CNT, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{yyvctYy}, #{yyvctCnt}, #{loginUsrId}, GETDATE(), #{loginUsrId}, GETDATE())
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET YYVCT_CNT = #{yyvctCnt}, MODID = #{loginUsrId}, UPD_DT = GETDATE();
|
||||
</update>
|
||||
|
||||
<!-- 연차 삭제 -->
|
||||
<delete id="deleteYyvct" parameterType="map">
|
||||
DELETE FROM SX_GW0060
|
||||
WHERE CORP_NO = #{corpNo} AND USR_ID = #{usrId} AND YYVCT_YY = #{yyvctYy}
|
||||
</delete>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- TAM0020 - 결재 신청 목록 -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<select id="getApvreqList" parameterType="map" resultType="map">
|
||||
SELECT A.APRVL_DOC_ID, A.APRVL_STUS_CD, A.APRVL_KIND_CD,
|
||||
A.APRVL_CMPL_SNO, A.FINAL_APRVL_SNO,
|
||||
A.APLNT_ID,
|
||||
CONVERT(VARCHAR, ISNULL(A.OFFER_DT, A.RGST_DT), 120) AS OFFER_DT,
|
||||
CONVERT(VARCHAR, A.CMPL_DT, 120) AS CMPL_DT
|
||||
FROM SX_GW0090 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APLNT_ID = #{usrId}
|
||||
AND (#{aprvlStusCd} IS NULL OR #{aprvlStusCd} = '' OR A.APRVL_STUS_CD = #{aprvlStusCd})
|
||||
AND (#{aprvlKindCd} IS NULL OR #{aprvlKindCd} = '' OR A.APRVL_KIND_CD = #{aprvlKindCd})
|
||||
AND CONVERT(VARCHAR, ISNULL(A.OFFER_DT, A.RGST_DT), 112) BETWEEN #{staYmd} AND #{endYmd}
|
||||
ORDER BY ISNULL(A.OFFER_DT, A.RGST_DT) DESC
|
||||
OFFSET (#{pageNo} - 1) * #{pageSize} ROWS
|
||||
FETCH NEXT #{pageSize} ROWS ONLY
|
||||
</select>
|
||||
|
||||
<select id="getApvreqListCount" parameterType="map" resultType="long">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0090 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APLNT_ID = #{usrId}
|
||||
AND (#{aprvlStusCd} IS NULL OR #{aprvlStusCd} = '' OR A.APRVL_STUS_CD = #{aprvlStusCd})
|
||||
AND (#{aprvlKindCd} IS NULL OR #{aprvlKindCd} = '' OR A.APRVL_KIND_CD = #{aprvlKindCd})
|
||||
AND CONVERT(VARCHAR, ISNULL(A.OFFER_DT, A.RGST_DT), 112) BETWEEN #{staYmd} AND #{endYmd}
|
||||
</select>
|
||||
|
||||
<!-- 변경근무 상세 목록 (SX_GW0110) -->
|
||||
<select id="getWorkChangeList" parameterType="map" resultType="map">
|
||||
SELECT TOT.*,
|
||||
BF.WORK_CD_TITLE_NM AS BF_TITLE,
|
||||
ISNULL(BF.GOTOWORK_TM_NM, '') AS BF_START,
|
||||
ISNULL(BF.GETOFFWORK_TM_NM, '') AS BF_END,
|
||||
AF.WORK_CD_TITLE_NM AS AF_TITLE,
|
||||
ISNULL(AF.GOTOWORK_TM_NM, '') AS AF_START,
|
||||
ISNULL(AF.GETOFFWORK_TM_NM, '') AS AF_END
|
||||
FROM (
|
||||
SELECT A.UPD_DATE, A.UPD_BF_WORK_CD, A.UPD_WORK_CD,
|
||||
CASE WHEN ISNULL(D.WORK_CD,'') NOT IN ('', A.UPD_WORK_CD)
|
||||
THEN D.WORK_CD ELSE ISNULL(D.PLAN_WORK_CD,'') END AS ORI_WORK_CD
|
||||
FROM SX_GW0110 A
|
||||
LEFT JOIN SX_GW0050 D
|
||||
ON D.CORP_NO = A.CORP_NO AND D.WORK_PLAN_YYMMDD = A.UPD_DATE AND D.USR_ID = A.RGSTR_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
) TOT
|
||||
LEFT JOIN SX_CO0070 BF ON TOT.ORI_WORK_CD = BF.WORK_CD
|
||||
LEFT JOIN SX_CO0070 AF ON TOT.UPD_WORK_CD = AF.WORK_CD
|
||||
</select>
|
||||
|
||||
<!-- 시간외/지각/조퇴 상세 (SX_GW0080) -->
|
||||
<select id="getOtInfo" parameterType="map" resultType="map">
|
||||
SELECT A.LATE_SKIPOFF_ABTI_OT_DATE,
|
||||
CONVERT(VARCHAR, A.LATE_SKIPOFF_OT_DT, 120) AS LATE_SKIPOFF_OT_DT,
|
||||
CONVERT(VARCHAR, A.LATE_SKIPOFF_OT_DT2, 120) AS LATE_SKIPOFF_OT_DT2,
|
||||
A.LATE_SKIPOFF_OT_MIN, A.NML_WORK_RCNTN_YN,
|
||||
CONVERT(VARCHAR, A.REQUEST_DT, 24) AS REQUEST_DT,
|
||||
CONVERT(VARCHAR, A.REQUEST_DT2, 24) AS REQUEST_DT2,
|
||||
ISNULL(B.WORK_CD, B.PLAN_WORK_CD) AS OT_WORK_CD,
|
||||
C.GOTOWORK_TM_NM AS OT_WORK_START_DT, C.GETOFFWORK_TM_NM AS OT_WORK_END_DT,
|
||||
C.WORK_CD_TITLE_NM
|
||||
FROM SX_GW0080 A
|
||||
LEFT JOIN SX_GW0050 B
|
||||
ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.RGSTR_ID
|
||||
AND B.WORK_PLAN_YYMMDD = A.LATE_SKIPOFF_ABTI_OT_DATE
|
||||
LEFT JOIN SX_CO0070 C
|
||||
ON C.CORP_NO = B.CORP_NO AND C.WORK_CD = ISNULL(B.WORK_CD, B.PLAN_WORK_CD)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
</select>
|
||||
|
||||
<!-- 변경근무/연차 등록 (SX_GW0110) -->
|
||||
<insert id="insertSxGw0110" parameterType="map">
|
||||
INSERT INTO SX_GW0110 (CORP_NO, APRVL_DOC_ID, UPD_DATE, UPD_BF_WORK_CD, UPD_WORK_CD,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{aprvlDocId}, #{updDate}, #{updBfWorkCd}, #{updWorkCd},
|
||||
#{usrId}, GETDATE(), #{usrId}, GETDATE())
|
||||
</insert>
|
||||
|
||||
<!-- 시간외/지각/조퇴 등록 (SX_GW0080) -->
|
||||
<insert id="insertSxGw0080" parameterType="map">
|
||||
INSERT INTO SX_GW0080 (
|
||||
CORP_NO, APRVL_DOC_ID, LATE_SKIPOFF_ABTI_OT_DATE,
|
||||
LATE_SKIPOFF_OT_DT, LATE_SKIPOFF_OT_DT2, LATE_SKIPOFF_OT_MIN,
|
||||
NML_WORK_RCNTN_YN, RGSTR_ID, RGST_DT, MODID, UPD_DT, REQUEST_DT, REQUEST_DT2
|
||||
) VALUES (
|
||||
#{corpNo}, #{aprvlDocId}, #{lateSkipoffAbtiOtDate},
|
||||
CONVERT(DATETIME, NULLIF(#{lateSkipoffOtDt}, ''), 120),
|
||||
CONVERT(DATETIME, NULLIF(#{lateSkipoffOtDt2}, ''), 120),
|
||||
#{lateSkipoffOtMin}, ISNULL(#{nmlWorkRcntnYn}, 'N'),
|
||||
#{usrId}, GETDATE(), #{usrId}, GETDATE(), #{requestDt}, #{requestDt2}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- SX_GW0110 삭제 -->
|
||||
<delete id="deleteSxGw0110" parameterType="map">
|
||||
DELETE FROM SX_GW0110 WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
|
||||
<!-- SX_GW0080 삭제 -->
|
||||
<delete id="deleteSxGw0080" parameterType="map">
|
||||
DELETE FROM SX_GW0080 WHERE CORP_NO = #{corpNo} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</delete>
|
||||
|
||||
<!-- 최근 결재자 목록 조회 (이전 신청 기반) -->
|
||||
<select id="getLatestApprList" parameterType="map" resultType="map">
|
||||
SELECT B.APRVL_SNO, U.USR_ID, U.USR_NM, U.TEAM_CD, U.DUTY_CD
|
||||
FROM (
|
||||
SELECT TOP 1 A.CORP_NO, A.APRVL_DOC_ID
|
||||
FROM SX_GW0090 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APLNT_ID = #{usrId}
|
||||
AND A.APRVL_STUS_CD IN ('0002', '0003', '0004')
|
||||
ORDER BY OFFER_DT DESC
|
||||
) A
|
||||
JOIN SX_GW0100 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
JOIN SX_GW0010 U ON U.CORP_NO = B.CORP_NO AND U.USR_ID = B.APPR_ID
|
||||
ORDER BY B.APRVL_SNO
|
||||
</select>
|
||||
|
||||
<!-- 신청자 DOC_FLAG 확인 처리 -->
|
||||
<update id="updateDocFlagAplnt" parameterType="map">
|
||||
UPDATE SX_GW0090 SET DOC_FLAG = 'A'
|
||||
WHERE CORP_NO = #{corpNo} AND APLNT_ID = #{usrId} AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- TAM0030 - 결재 처리 목록 (결재자 입장) -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<select id="getApvappList" parameterType="map" resultType="map">
|
||||
SELECT A.APRVL_SNO,
|
||||
CONVERT(VARCHAR, A.APRVL_DT, 120) AS APRVL_DT,
|
||||
A.APPR_STUS_CD,
|
||||
B.APRVL_DOC_ID, B.APRVL_STUS_CD, B.APRVL_KIND_CD,
|
||||
B.APRVL_CMPL_SNO, B.FINAL_APRVL_SNO,
|
||||
B.APLNT_ID,
|
||||
U1.USR_NM AS APLNT_NM,
|
||||
CONVERT(VARCHAR, B.OFFER_DT, 120) AS OFFER_DT,
|
||||
CONVERT(VARCHAR, B.CMPL_DT, 120) AS CMPL_DT
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0090 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
LEFT JOIN SX_GW0010 U1 ON U1.CORP_NO = B.CORP_NO AND U1.USR_ID = B.APLNT_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APPR_ID = #{usrId}
|
||||
AND (#{apprStusCd} IS NULL OR #{apprStusCd} = '' OR A.APPR_STUS_CD = #{apprStusCd})
|
||||
AND (#{aprvlStusCd} IS NULL OR #{aprvlStusCd} = '' OR B.APRVL_STUS_CD = #{aprvlStusCd})
|
||||
AND (#{aprvlKindCd} IS NULL OR #{aprvlKindCd} = '' OR B.APRVL_KIND_CD = #{aprvlKindCd})
|
||||
AND (#{staYmd} IS NULL OR #{staYmd} = '' OR CONVERT(VARCHAR, B.OFFER_DT, 112) >= #{staYmd})
|
||||
AND (#{endYmd} IS NULL OR #{endYmd} = '' OR CONVERT(VARCHAR, B.OFFER_DT, 112) <= #{endYmd})
|
||||
ORDER BY B.OFFER_DT DESC, A.APRVL_SNO DESC
|
||||
OFFSET (#{pageNo} - 1) * #{pageSize} ROWS
|
||||
FETCH NEXT #{pageSize} ROWS ONLY
|
||||
</select>
|
||||
|
||||
<select id="getApvappListCount" parameterType="map" resultType="long">
|
||||
SELECT COUNT(1)
|
||||
FROM SX_GW0100 A
|
||||
JOIN SX_GW0090 B ON B.CORP_NO = A.CORP_NO AND B.APRVL_DOC_ID = A.APRVL_DOC_ID
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APPR_ID = #{usrId}
|
||||
AND (#{apprStusCd} IS NULL OR #{apprStusCd} = '' OR A.APPR_STUS_CD = #{apprStusCd})
|
||||
AND (#{aprvlStusCd} IS NULL OR #{aprvlStusCd} = '' OR B.APRVL_STUS_CD = #{aprvlStusCd})
|
||||
AND (#{aprvlKindCd} IS NULL OR #{aprvlKindCd} = '' OR B.APRVL_KIND_CD = #{aprvlKindCd})
|
||||
</select>
|
||||
|
||||
<!-- 1차결재자 DOC_FLAG 확인 처리 -->
|
||||
<update id="updateDocFlagAppr" parameterType="map">
|
||||
UPDATE SX_GW0100 SET DOC_FLAG = 'A'
|
||||
WHERE CORP_NO = #{corpNo} AND APPR_ID = #{usrId}
|
||||
AND APRVL_SNO = 1 AND APRVL_DOC_ID = #{aprvlDocId}
|
||||
</update>
|
||||
|
||||
<!-- 외출 시간 업데이트 -->
|
||||
<update id="updateOutingTime" parameterType="map">
|
||||
UPDATE SX_GW0050
|
||||
SET OUTING_MIN = ISNULL(OUTING_MIN, 0) + DATEDIFF(MI, A.LATE_SKIPOFF_OT_DT, A.LATE_SKIPOFF_OT_DT2),
|
||||
OUTING_CNT = ISNULL(OUTING_CNT, 0) + 1
|
||||
FROM SX_GW0080 A
|
||||
WHERE USR_ID = #{aplntId}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND WORK_PLAN_YYMMDD = A.LATE_SKIPOFF_ABTI_OT_DATE
|
||||
</update>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- TAM0040 - 근태 현황/통계 -->
|
||||
<!-- ===================================================== -->
|
||||
<select id="getTamStatusList" parameterType="map" resultType="map">
|
||||
SELECT A.USR_ID, A.USR_NM, A.BZ_CD, A.TEAM_CD, A.DUTY_CD,
|
||||
B.YYVCT_CNT,
|
||||
(SELECT COUNT(1) FROM SX_GW0090 D
|
||||
WHERE D.CORP_NO = A.CORP_NO AND D.APLNT_ID = A.USR_ID
|
||||
AND D.APRVL_STUS_CD IN ('0002', '0003')
|
||||
AND CONVERT(VARCHAR, ISNULL(D.OFFER_DT, D.RGST_DT), 112)
|
||||
BETWEEN #{staYmd} AND #{endYmd}
|
||||
) AS APRVL_CNT
|
||||
FROM SX_GW0010 A
|
||||
LEFT JOIN SX_GW0060 B
|
||||
ON B.CORP_NO = A.CORP_NO AND B.USR_ID = A.USR_ID AND B.YYVCT_YY = #{yyvctYy}
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (#{teamCd} IS NULL OR #{teamCd} = '' OR A.TEAM_CD = #{teamCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR A.RETIREMENT_DATE IS NULL OR A.RETIREMENT_DATE = '')
|
||||
ORDER BY A.USR_NM
|
||||
</select>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- 결재 후처리 (최종 승인 시) -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<!-- 0001 시간외: OT_RCTN_YN='Y' 설정 -->
|
||||
<update id="afterProcessOt" parameterType="map">
|
||||
UPDATE W
|
||||
SET W.OT_RCTN_YN = 'Y'
|
||||
FROM SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- 0002 지각: WORK_START_DT를 신청시간으로 보정 -->
|
||||
<update id="afterProcessLate" parameterType="map">
|
||||
UPDATE W
|
||||
SET W.WORK_START_DT = A.REQUEST_DT
|
||||
FROM SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- 0003 조퇴: WORK_END_DT 보정 + EL_RCTN_YN='Y' -->
|
||||
<update id="afterProcessEarlyDep" parameterType="map">
|
||||
UPDATE W
|
||||
SET W.WORK_END_DT = A.REQUEST_DT,
|
||||
W.EL_RCTN_YN = 'Y'
|
||||
FROM SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- 0004 결근: 출퇴근 시간 모두 보정 -->
|
||||
<update id="afterProcessAbsence" parameterType="map">
|
||||
UPDATE W
|
||||
SET W.WORK_START_DT = A.REQUEST_DT,
|
||||
W.WORK_END_DT = A.REQUEST_DT2
|
||||
FROM SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- 0005 연차 / 0006 근무변경: WORK_CD 변경 -->
|
||||
<update id="afterProcessWorkChange" parameterType="map">
|
||||
UPDATE W
|
||||
SET W.WORK_CD = A.UPD_WORK_CD
|
||||
FROM SX_GW0050 W
|
||||
JOIN SX_GW0110 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.UPD_DATE = W.WORK_PLAN_YYMMDD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- MariaDB 후처리 버전 -->
|
||||
<update id="afterProcessOt" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
SET W.OT_RCTN_YN = 'Y'
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<update id="afterProcessLate" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
SET W.WORK_START_DT = A.REQUEST_DT
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<update id="afterProcessEarlyDep" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
SET W.WORK_END_DT = A.REQUEST_DT,
|
||||
W.EL_RCTN_YN = 'Y'
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<update id="afterProcessAbsence" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0050 W
|
||||
JOIN SX_GW0080 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.LATE_SKIPOFF_ABTI_OT_DATE = W.WORK_PLAN_YYMMDD
|
||||
SET W.WORK_START_DT = A.REQUEST_DT,
|
||||
W.WORK_END_DT = A.REQUEST_DT2
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<update id="afterProcessWorkChange" parameterType="map" databaseId="mariadb">
|
||||
UPDATE SX_GW0050 W
|
||||
JOIN SX_GW0110 A
|
||||
ON A.CORP_NO = W.CORP_NO
|
||||
AND A.UPD_DATE = W.WORK_PLAN_YYMMDD
|
||||
SET W.WORK_CD = A.UPD_WORK_CD
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APRVL_DOC_ID = #{aprvlDocId}
|
||||
AND W.USR_ID = #{aplntId}
|
||||
</update>
|
||||
|
||||
<!-- ===================================================== -->
|
||||
<!-- MariaDB 버전 -->
|
||||
<!-- ===================================================== -->
|
||||
|
||||
<select id="getApvreqList" parameterType="map" resultType="map" databaseId="mariadb">
|
||||
SELECT A.APRVL_DOC_ID, A.APRVL_STUS_CD, A.APRVL_KIND_CD,
|
||||
A.APRVL_CMPL_SNO, A.FINAL_APRVL_SNO, A.APLNT_ID,
|
||||
DATE_FORMAT(IFNULL(A.OFFER_DT, A.RGST_DT), '%Y-%m-%d %H:%i:%s') AS OFFER_DT,
|
||||
DATE_FORMAT(A.CMPL_DT, '%Y-%m-%d %H:%i:%s') AS CMPL_DT
|
||||
FROM SX_GW0090 A
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.APLNT_ID = #{usrId}
|
||||
AND (#{aprvlStusCd} IS NULL OR #{aprvlStusCd} = '' OR A.APRVL_STUS_CD = #{aprvlStusCd})
|
||||
AND (#{aprvlKindCd} IS NULL OR #{aprvlKindCd} = '' OR A.APRVL_KIND_CD = #{aprvlKindCd})
|
||||
AND DATE_FORMAT(IFNULL(A.OFFER_DT, A.RGST_DT), '%Y%m%d') BETWEEN #{staYmd} AND #{endYmd}
|
||||
ORDER BY IFNULL(A.OFFER_DT, A.RGST_DT) DESC
|
||||
LIMIT #{pageSize} OFFSET (#{pageNo} - 1) * #{pageSize}
|
||||
</select>
|
||||
|
||||
<update id="upsertYyvct" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0060 (CORP_NO, USR_ID, YYVCT_YY, YYVCT_CNT, RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{yyvctYy}, #{yyvctCnt}, #{loginUsrId}, NOW(), #{loginUsrId}, NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
YYVCT_CNT = #{yyvctCnt}, MODID = #{loginUsrId}, UPD_DT = NOW()
|
||||
</update>
|
||||
|
||||
<insert id="insertSxGw0110" parameterType="map" databaseId="mariadb">
|
||||
INSERT INTO SX_GW0110 (CORP_NO, APRVL_DOC_ID, UPD_DATE, UPD_BF_WORK_CD, UPD_WORK_CD,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{aprvlDocId}, #{updDate}, #{updBfWorkCd}, #{updWorkCd},
|
||||
#{usrId}, NOW(), #{usrId}, NOW())
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
287
backend/src/main/resources/mapper/wplan/wplan_sql.xml
Normal file
287
backend/src/main/resources/mapper/wplan/wplan_sql.xml
Normal file
@@ -0,0 +1,287 @@
|
||||
<?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">
|
||||
<!--
|
||||
근무계획 SQL (MSSQL 기본 + MariaDB databaseId="mariadb")
|
||||
테이블: SX_GW0050 (근무계획), SX_GW0010 (직원), SX_CO0070 (근무코드)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.wplan.mapper.WplanMapper">
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
근무코드 목록 (드롭다운)
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getWorkCodeList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT WORK_CD,
|
||||
WORK_CD_TITLE_NM,
|
||||
GOTOWORK_TM_NM,
|
||||
GETOFFWORK_TM_NM,
|
||||
HOLIDAY_YN,
|
||||
WORK_CD_USE_YN
|
||||
FROM SX_CO0070
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND ISNULL(WORK_CD_USE_YN, 'Y') = 'Y'
|
||||
ORDER BY WORK_CD
|
||||
]]></select>
|
||||
|
||||
<select id="getWorkCodeList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT WORK_CD,
|
||||
WORK_CD_TITLE_NM,
|
||||
GOTOWORK_TM_NM,
|
||||
GETOFFWORK_TM_NM,
|
||||
HOLIDAY_YN,
|
||||
WORK_CD_USE_YN
|
||||
FROM SX_CO0070
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND IFNULL(WORK_CD_USE_YN, 'Y') = 'Y'
|
||||
ORDER BY WORK_CD
|
||||
]]></select>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
Wplan0010 - 근무계획관리 목록
|
||||
개인별 월간 근무계획을 행으로 조회 (피벗은 프론트에서 처리)
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getWplanList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.TEAM_CD,
|
||||
A.DUTY_CD,
|
||||
A.USR_SORT_ORDR,
|
||||
B.WORK_PLAN_YYMMDD,
|
||||
B.PLAN_WORK_CD,
|
||||
ISNULL(NULLIF(B.WORK_CD, ''), B.PLAN_WORK_CD) AS WORK_CD,
|
||||
ISNULL(B.SORT_ODR, 9999) AS SORT_ODR
|
||||
FROM SX_GW0010 A
|
||||
LEFT OUTER JOIN SX_GW0050 B
|
||||
ON (B.CORP_NO = A.CORP_NO
|
||||
AND B.USR_ID = A.USR_ID
|
||||
AND B.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%'))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (#{includeRetireYn} = 'Y' OR ISNULL(A.RETIREMENT_DATE, '') = '')
|
||||
AND (ISNULL(#{searchText}, '') = '' OR A.USR_NM LIKE CONCAT('%', #{searchText}, '%'))
|
||||
AND (ISNULL(#{teamCd}, '') = '' OR A.TEAM_CD = #{teamCd})
|
||||
ORDER BY
|
||||
ISNULL(B.SORT_ODR, 9999),
|
||||
A.USR_ID
|
||||
]]></select>
|
||||
|
||||
<select id="getWplanList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.USR_ID,
|
||||
A.USR_NM,
|
||||
A.TEAM_CD,
|
||||
A.DUTY_CD,
|
||||
A.USR_SORT_ORDR,
|
||||
B.WORK_PLAN_YYMMDD,
|
||||
B.PLAN_WORK_CD,
|
||||
IFNULL(NULLIF(B.WORK_CD, ''), B.PLAN_WORK_CD) AS WORK_CD,
|
||||
IFNULL(B.SORT_ODR, 9999) AS SORT_ODR
|
||||
FROM SX_GW0010 A
|
||||
LEFT OUTER JOIN SX_GW0050 B
|
||||
ON (B.CORP_NO = A.CORP_NO
|
||||
AND B.USR_ID = A.USR_ID
|
||||
AND B.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%'))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND (#{includeRetireYn} = 'Y' OR IFNULL(A.RETIREMENT_DATE, '') = '')
|
||||
AND (IFNULL(#{searchText}, '') = '' OR A.USR_NM LIKE CONCAT('%', #{searchText}, '%'))
|
||||
AND (IFNULL(#{teamCd}, '') = '' OR A.TEAM_CD = #{teamCd})
|
||||
ORDER BY
|
||||
IFNULL(B.SORT_ODR, 9999),
|
||||
A.USR_ID
|
||||
]]></select>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
Wplan0020 - 나의 근무계획 목록
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getMyWplanList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS WORK_CD,
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%')
|
||||
ORDER BY A.WORK_PLAN_YYMMDD
|
||||
]]></select>
|
||||
|
||||
<select id="getMyWplanList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS WORK_CD,
|
||||
C.WORK_CD_TITLE_NM,
|
||||
C.GOTOWORK_TM_NM,
|
||||
C.GETOFFWORK_TM_NM
|
||||
FROM SX_GW0050 A
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.USR_ID = #{usrId}
|
||||
AND A.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%')
|
||||
ORDER BY A.WORK_PLAN_YYMMDD
|
||||
]]></select>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
Wplan0030 - 전체 근무계획 목록 (근무코드 포함)
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getAllWplanList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.USR_ID,
|
||||
B.USR_NM,
|
||||
B.TEAM_CD,
|
||||
B.DUTY_CD,
|
||||
A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
CASE
|
||||
WHEN ISNULL(A.WORK_CD, '') != '' THEN A.WORK_CD
|
||||
WHEN ISNULL(A.PLAN_WORK_CD, '') != '' THEN A.PLAN_WORK_CD
|
||||
ELSE ''
|
||||
END AS WORK_CD,
|
||||
C.WORK_CD_TITLE_NM AS PLAN_WORK_NM,
|
||||
D.WORK_CD_TITLE_NM AS WORK_NM,
|
||||
CASE
|
||||
WHEN LEN(ISNULL(C.GOTOWORK_TM_NM, '')) = 5
|
||||
THEN SUBSTRING(C.GOTOWORK_TM_NM, 1, 3) + ':' + SUBSTRING(C.GOTOWORK_TM_NM, 4, 2)
|
||||
WHEN LEN(ISNULL(C.GOTOWORK_TM_NM, '')) = 4
|
||||
THEN SUBSTRING(C.GOTOWORK_TM_NM, 1, 2) + ':' + SUBSTRING(C.GOTOWORK_TM_NM, 3, 2)
|
||||
ELSE '' END AS PLAN_GOTOWORK_TM,
|
||||
CASE
|
||||
WHEN LEN(ISNULL(C.GETOFFWORK_TM_NM, '')) = 5
|
||||
THEN SUBSTRING(C.GETOFFWORK_TM_NM, 1, 3) + ':' + SUBSTRING(C.GETOFFWORK_TM_NM, 4, 2)
|
||||
WHEN LEN(ISNULL(C.GETOFFWORK_TM_NM, '')) = 4
|
||||
THEN SUBSTRING(C.GETOFFWORK_TM_NM, 1, 2) + ':' + SUBSTRING(C.GETOFFWORK_TM_NM, 3, 2)
|
||||
ELSE '' END AS PLAN_GETOFFWORK_TM
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 B
|
||||
ON (B.CORP_NO = A.CORP_NO
|
||||
AND B.USR_ID = A.USR_ID
|
||||
AND (ISNULL(#{teamCd}, '') = '' OR B.TEAM_CD = #{teamCd})
|
||||
AND (ISNULL(#{dutyCd}, '') = '' OR B.DUTY_CD = #{dutyCd}))
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.WORK_CD = A.PLAN_WORK_CD AND C.CORP_NO = A.CORP_NO)
|
||||
LEFT OUTER JOIN SX_CO0070 D
|
||||
ON (D.WORK_CD = A.WORK_CD AND D.CORP_NO = A.CORP_NO)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%')
|
||||
AND (ISNULL(#{workCd}, '') = '' OR
|
||||
CASE WHEN #{workCdType} = 'PLAN_WORK_CD'
|
||||
THEN A.PLAN_WORK_CD
|
||||
ELSE ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
END = #{workCd})
|
||||
ORDER BY
|
||||
A.WORK_PLAN_YYMMDD,
|
||||
CASE WHEN #{workCdType} = 'PLAN_WORK_CD'
|
||||
THEN A.PLAN_WORK_CD
|
||||
ELSE ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
END,
|
||||
B.USR_NM
|
||||
]]></select>
|
||||
|
||||
<select id="getAllWplanList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.USR_ID,
|
||||
B.USR_NM,
|
||||
B.TEAM_CD,
|
||||
B.DUTY_CD,
|
||||
A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
CASE
|
||||
WHEN IFNULL(A.WORK_CD, '') != '' THEN A.WORK_CD
|
||||
WHEN IFNULL(A.PLAN_WORK_CD, '') != '' THEN A.PLAN_WORK_CD
|
||||
ELSE ''
|
||||
END AS WORK_CD,
|
||||
C.WORK_CD_TITLE_NM AS PLAN_WORK_NM,
|
||||
D.WORK_CD_TITLE_NM AS WORK_NM,
|
||||
CASE
|
||||
WHEN CHAR_LENGTH(IFNULL(C.GOTOWORK_TM_NM, '')) = 5
|
||||
THEN CONCAT(SUBSTRING(C.GOTOWORK_TM_NM, 1, 3), ':', SUBSTRING(C.GOTOWORK_TM_NM, 4, 2))
|
||||
WHEN CHAR_LENGTH(IFNULL(C.GOTOWORK_TM_NM, '')) = 4
|
||||
THEN CONCAT(SUBSTRING(C.GOTOWORK_TM_NM, 1, 2), ':', SUBSTRING(C.GOTOWORK_TM_NM, 3, 2))
|
||||
ELSE '' END AS PLAN_GOTOWORK_TM,
|
||||
CASE
|
||||
WHEN CHAR_LENGTH(IFNULL(C.GETOFFWORK_TM_NM, '')) = 5
|
||||
THEN CONCAT(SUBSTRING(C.GETOFFWORK_TM_NM, 1, 3), ':', SUBSTRING(C.GETOFFWORK_TM_NM, 4, 2))
|
||||
WHEN CHAR_LENGTH(IFNULL(C.GETOFFWORK_TM_NM, '')) = 4
|
||||
THEN CONCAT(SUBSTRING(C.GETOFFWORK_TM_NM, 1, 2), ':', SUBSTRING(C.GETOFFWORK_TM_NM, 3, 2))
|
||||
ELSE '' END AS PLAN_GETOFFWORK_TM
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 B
|
||||
ON (B.CORP_NO = A.CORP_NO
|
||||
AND B.USR_ID = A.USR_ID
|
||||
AND (IFNULL(#{teamCd}, '') = '' OR B.TEAM_CD = #{teamCd})
|
||||
AND (IFNULL(#{dutyCd}, '') = '' OR B.DUTY_CD = #{dutyCd}))
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.WORK_CD = A.PLAN_WORK_CD AND C.CORP_NO = A.CORP_NO)
|
||||
LEFT OUTER JOIN SX_CO0070 D
|
||||
ON (D.WORK_CD = A.WORK_CD AND D.CORP_NO = A.CORP_NO)
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%')
|
||||
AND (IFNULL(#{workCd}, '') = '' OR
|
||||
CASE WHEN #{workCdType} = 'PLAN_WORK_CD'
|
||||
THEN A.PLAN_WORK_CD
|
||||
ELSE IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
END = #{workCd})
|
||||
ORDER BY
|
||||
A.WORK_PLAN_YYMMDD,
|
||||
CASE WHEN #{workCdType} = 'PLAN_WORK_CD'
|
||||
THEN A.PLAN_WORK_CD
|
||||
ELSE IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD)
|
||||
END,
|
||||
B.USR_NM
|
||||
]]></select>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
근무계획 저장 (MERGE / UPSERT)
|
||||
단건: 특정 직원의 특정 날짜 근무계획 저장
|
||||
─────────────────────────────────────────── -->
|
||||
<update id="upsertWorkplan" parameterType="map"><![CDATA[
|
||||
MERGE INTO SX_GW0050 T
|
||||
USING (SELECT 1 AS DUMMY) S
|
||||
ON (T.CORP_NO = #{corpNo}
|
||||
AND T.USR_ID = #{usrId}
|
||||
AND T.WORK_PLAN_YYMMDD = #{workPlanYymmdd})
|
||||
WHEN NOT MATCHED THEN
|
||||
INSERT (CORP_NO, USR_ID, WORK_PLAN_YYMMDD, PLAN_WORK_CD, SORT_ODR,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{workPlanYymmdd}, #{planWorkCd}, #{sortOdr},
|
||||
#{loginUsrId}, GETDATE(), #{loginUsrId}, GETDATE())
|
||||
WHEN MATCHED THEN
|
||||
UPDATE SET
|
||||
PLAN_WORK_CD = #{planWorkCd},
|
||||
SORT_ODR = #{sortOdr},
|
||||
MODID = #{loginUsrId},
|
||||
UPD_DT = GETDATE()
|
||||
;
|
||||
]]></update>
|
||||
|
||||
<update id="upsertWorkplan" databaseId="mariadb" parameterType="map"><![CDATA[
|
||||
INSERT INTO SX_GW0050 (CORP_NO, USR_ID, WORK_PLAN_YYMMDD, PLAN_WORK_CD, SORT_ODR,
|
||||
RGSTR_ID, RGST_DT, MODID, UPD_DT)
|
||||
VALUES (#{corpNo}, #{usrId}, #{workPlanYymmdd}, #{planWorkCd}, #{sortOdr},
|
||||
#{loginUsrId}, NOW(), #{loginUsrId}, NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
PLAN_WORK_CD = #{planWorkCd},
|
||||
SORT_ODR = #{sortOdr},
|
||||
MODID = #{loginUsrId},
|
||||
UPD_DT = NOW()
|
||||
]]></update>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
근무계획 삭제 (특정 날짜 또는 월 전체)
|
||||
─────────────────────────────────────────── -->
|
||||
<delete id="deleteWorkplan" parameterType="map"><![CDATA[
|
||||
DELETE FROM SX_GW0050
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD = #{workPlanYymmdd}
|
||||
]]></delete>
|
||||
|
||||
<delete id="deleteWorkplanMonth" parameterType="map"><![CDATA[
|
||||
DELETE FROM SX_GW0050
|
||||
WHERE CORP_NO = #{corpNo}
|
||||
AND USR_ID = #{usrId}
|
||||
AND WORK_PLAN_YYMMDD LIKE CONCAT(#{workPlanYymm}, '%')
|
||||
]]></delete>
|
||||
|
||||
</mapper>
|
||||
247
backend/src/main/resources/mapper/wtime/wtime_sql.xml
Normal file
247
backend/src/main/resources/mapper/wtime/wtime_sql.xml
Normal file
@@ -0,0 +1,247 @@
|
||||
<?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">
|
||||
<!--
|
||||
근무시간 SQL (MSSQL 기본 + MariaDB databaseId="mariadb")
|
||||
테이블: SX_GW0050 (근무계획/시간), SX_GW0010 (직원), SX_CO0070 (근무코드), SX_GW0060 (연차)
|
||||
-->
|
||||
<mapper namespace="com.company.gw.wtime.mapper.WtimeMapper">
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
Wtime0010 - 개인별 근무시간 목록
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getWtimeList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
A.WORK_CD,
|
||||
ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
SUBSTRING(CONVERT(VARCHAR, A.WORK_START_DT, 120), 1, 16) AS WORK_START_DT,
|
||||
SUBSTRING(CONVERT(VARCHAR, A.WORK_END_DT, 120), 1, 16) AS WORK_END_DT,
|
||||
(CASE WHEN (A.WORK_START_DT IS NULL
|
||||
AND A.WORK_PLAN_YYMMDD <= CONVERT(VARCHAR, GETDATE(), 112)
|
||||
AND ISNULL(A.WORK_CD, A.PLAN_WORK_CD) >= 'A'
|
||||
AND ISNULL(A.WORK_CD, A.PLAN_WORK_CD) <= 'T')
|
||||
THEN 'Y' ELSE 'N' END) AS ABTI_YN,
|
||||
A.OT_RCTN_YN,
|
||||
A.EL_RCTN_YN,
|
||||
ISNULL(A.TOT_WORK_MIN, 0) AS TOT_WORK_MIN,
|
||||
ISNULL(A.LATE_MIN, 0) AS LATE_MIN,
|
||||
ISNULL(A.SKIPOFF_REMN_BZ_MIN, 0) AS SKIPOFF_REMN_BZ_MIN,
|
||||
ISNULL(A.INCLU_WORK_OT_MIN, 0) AS INCLU_WORK_OT_MIN,
|
||||
ISNULL(A.OT_WORK_MIN, 0) AS OT_WORK_MIN,
|
||||
ISNULL(A.NGT_OT_MIN, 0) AS NGT_OT_MIN,
|
||||
ISNULL(A.OUTING_MIN, 0) AS OUTING_MIN,
|
||||
ISNULL(A.HOLIDAY_LATE_MIN, 0) AS HOLIDAY_LATE_MIN,
|
||||
SUBSTRING(CONVERT(VARCHAR, A.REAL_START_DT, 120), 1, 16) AS REAL_START_DT,
|
||||
SUBSTRING(CONVERT(VARCHAR, A.REAL_END_DT, 120), 1, 16) AS REAL_END_DT,
|
||||
ISNULL(C.GETOFFWORK_TM_NM, '') AS GETOFFWORK_TM_NM,
|
||||
U.USR_ID,
|
||||
U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 U
|
||||
ON (U.CORP_NO = A.CORP_NO
|
||||
AND U.USR_ID = A.USR_ID
|
||||
AND (ISNULL(#{usrId}, '') = '' OR U.USR_ID = #{usrId})
|
||||
AND (ISNULL(#{usrNm}, '') = '' OR U.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
AND (ISNULL(#{teamCd}, '') = '' OR U.TEAM_CD = #{teamCd})
|
||||
AND (ISNULL(#{dutyCd}, '') = '' OR U.DUTY_CD = #{dutyCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR ISNULL(U.RETIREMENT_DATE, '') = ''))
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = ISNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
AND (ISNULL(#{includeWorkYn}, '') != 'Y'
|
||||
OR (#{includeWorkYn} = 'Y'
|
||||
AND (A.WORK_START_DT IS NOT NULL OR A.REAL_START_DT IS NOT NULL)))
|
||||
ORDER BY U.USR_NM, U.USR_ID, A.WORK_PLAN_YYMMDD
|
||||
]]></select>
|
||||
|
||||
<select id="getWtimeList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT A.WORK_PLAN_YYMMDD,
|
||||
A.PLAN_WORK_CD,
|
||||
A.WORK_CD,
|
||||
IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD) AS REAL_WORK_CD,
|
||||
DATE_FORMAT(A.WORK_START_DT, '%Y-%m-%d %H:%i') AS WORK_START_DT,
|
||||
DATE_FORMAT(A.WORK_END_DT, '%Y-%m-%d %H:%i') AS WORK_END_DT,
|
||||
(CASE WHEN (A.WORK_START_DT IS NULL
|
||||
AND A.WORK_PLAN_YYMMDD <= DATE_FORMAT(NOW(), '%Y%m%d')
|
||||
AND IFNULL(A.WORK_CD, A.PLAN_WORK_CD) >= 'A'
|
||||
AND IFNULL(A.WORK_CD, A.PLAN_WORK_CD) <= 'T')
|
||||
THEN 'Y' ELSE 'N' END) AS ABTI_YN,
|
||||
A.OT_RCTN_YN,
|
||||
A.EL_RCTN_YN,
|
||||
IFNULL(A.TOT_WORK_MIN, 0) AS TOT_WORK_MIN,
|
||||
IFNULL(A.LATE_MIN, 0) AS LATE_MIN,
|
||||
IFNULL(A.SKIPOFF_REMN_BZ_MIN, 0) AS SKIPOFF_REMN_BZ_MIN,
|
||||
IFNULL(A.INCLU_WORK_OT_MIN, 0) AS INCLU_WORK_OT_MIN,
|
||||
IFNULL(A.OT_WORK_MIN, 0) AS OT_WORK_MIN,
|
||||
IFNULL(A.NGT_OT_MIN, 0) AS NGT_OT_MIN,
|
||||
IFNULL(A.OUTING_MIN, 0) AS OUTING_MIN,
|
||||
IFNULL(A.HOLIDAY_LATE_MIN, 0) AS HOLIDAY_LATE_MIN,
|
||||
DATE_FORMAT(A.REAL_START_DT, '%Y-%m-%d %H:%i') AS REAL_START_DT,
|
||||
DATE_FORMAT(A.REAL_END_DT, '%Y-%m-%d %H:%i') AS REAL_END_DT,
|
||||
IFNULL(C.GETOFFWORK_TM_NM, '') AS GETOFFWORK_TM_NM,
|
||||
U.USR_ID,
|
||||
U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD
|
||||
FROM SX_GW0050 A
|
||||
JOIN SX_GW0010 U
|
||||
ON (U.CORP_NO = A.CORP_NO
|
||||
AND U.USR_ID = A.USR_ID
|
||||
AND (IFNULL(#{usrId}, '') = '' OR U.USR_ID = #{usrId})
|
||||
AND (IFNULL(#{usrNm}, '') = '' OR U.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
AND (IFNULL(#{teamCd}, '') = '' OR U.TEAM_CD = #{teamCd})
|
||||
AND (IFNULL(#{dutyCd}, '') = '' OR U.DUTY_CD = #{dutyCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR IFNULL(U.RETIREMENT_DATE, '') = ''))
|
||||
LEFT OUTER JOIN SX_CO0070 C
|
||||
ON (C.CORP_NO = A.CORP_NO
|
||||
AND C.WORK_CD = IFNULL(NULLIF(A.WORK_CD, ''), A.PLAN_WORK_CD))
|
||||
WHERE A.CORP_NO = #{corpNo}
|
||||
AND A.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
AND (IFNULL(#{includeWorkYn}, '') != 'Y'
|
||||
OR (#{includeWorkYn} = 'Y'
|
||||
AND (A.WORK_START_DT IS NOT NULL OR A.REAL_START_DT IS NOT NULL)))
|
||||
ORDER BY U.USR_NM, U.USR_ID, A.WORK_PLAN_YYMMDD
|
||||
]]></select>
|
||||
|
||||
<!-- ───────────────────────────────────────────
|
||||
Wtime0030 - 월별 근무시간 집계 (개인별 합산)
|
||||
─────────────────────────────────────────── -->
|
||||
<select id="getWstatList" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT U.USR_ID,
|
||||
U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD,
|
||||
ISNULL(A.WORK_DCNT, 0) AS WORK_DCNT,
|
||||
(SELECT COUNT('A')
|
||||
FROM SX_GW0050 AT
|
||||
WHERE AT.CORP_NO = U.CORP_NO
|
||||
AND AT.USR_ID = U.USR_ID
|
||||
AND AT.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
AND AT.WORK_START_DT IS NULL
|
||||
AND ISNULL(AT.WORK_CD, AT.PLAN_WORK_CD) >= 'A'
|
||||
AND ISNULL(AT.WORK_CD, AT.PLAN_WORK_CD) <= 'T') AS ABTI_DCNT,
|
||||
ISNULL(A.YYCT_DEDU_DCNT, 0) AS YYCT_DEDU_DCNT,
|
||||
ISNULL(A.LATE_DCNT, 0) AS LATE_DCNT,
|
||||
ISNULL(A.SKIPOFF_DCNT, 0) AS SKIPOFF_DCNT,
|
||||
ISNULL(A.SICKLEAVE_DCNT, 0) AS SICKLEAVE_DCNT,
|
||||
ISNULL(A.TOT_WORK_MIN, 0) AS TOT_WORK_MIN,
|
||||
ISNULL(A.LATE_MIN, 0) AS LATE_MIN,
|
||||
ISNULL(A.SKIPOFF_REMN_BZ_MIN, 0) AS SKIPOFF_REMN_BZ_MIN,
|
||||
ISNULL(A.INCLU_WORK_OT_MIN, 0) AS INCLU_WORK_OT_MIN,
|
||||
ISNULL(A.OT_WORK_MIN, 0) AS OT_WORK_MIN,
|
||||
ISNULL(A.NGT_OT_MIN, 0) AS NGT_OT_MIN,
|
||||
ISNULL(A.OUTING_DCNT, 0) AS OUTING_DCNT,
|
||||
ISNULL(A.OUTING_MIN, 0) AS OUTING_MIN,
|
||||
ISNULL(B.YYVCT_CNT, 0) AS YYVCT_CNT
|
||||
FROM SX_GW0010 U
|
||||
LEFT JOIN (
|
||||
SELECT A2.CORP_NO,
|
||||
A2.USR_ID,
|
||||
SUM(CASE WHEN ISNULL(NULLIF(A2.ABTI_YN, ''), 'N') != 'Y'
|
||||
THEN C2.APLY_WORK_DAY END) AS WORK_DCNT,
|
||||
SUM(C2.YYCT_DEDU_DAY) AS YYCT_DEDU_DCNT,
|
||||
COUNT(CASE WHEN A2.LATE_MIN > 0 THEN 1 END) AS LATE_DCNT,
|
||||
COUNT(CASE WHEN A2.SKIPOFF_REMN_BZ_MIN > 0 THEN 1 END) AS SKIPOFF_DCNT,
|
||||
COUNT(CASE WHEN ISNULL(NULLIF(A2.WORK_CD, ''), A2.PLAN_WORK_CD) = '병'
|
||||
THEN 1 END) AS SICKLEAVE_DCNT,
|
||||
SUM(ISNULL(A2.TOT_WORK_MIN, 0)) AS TOT_WORK_MIN,
|
||||
SUM(ISNULL(A2.LATE_MIN, 0)) AS LATE_MIN,
|
||||
SUM(ISNULL(A2.SKIPOFF_REMN_BZ_MIN, 0)) AS SKIPOFF_REMN_BZ_MIN,
|
||||
SUM(ISNULL(A2.INCLU_WORK_OT_MIN, 0)) AS INCLU_WORK_OT_MIN,
|
||||
SUM(ISNULL(A2.OT_WORK_MIN, 0)) AS OT_WORK_MIN,
|
||||
SUM(ISNULL(A2.NGT_OT_MIN, 0)) AS NGT_OT_MIN,
|
||||
SUM(ISNULL(A2.OUTING_CNT, 0)) AS OUTING_DCNT,
|
||||
SUM(ISNULL(A2.OUTING_MIN, 0)) AS OUTING_MIN
|
||||
FROM SX_GW0050 A2
|
||||
LEFT JOIN SX_CO0070 C2
|
||||
ON (C2.CORP_NO = A2.CORP_NO
|
||||
AND C2.WORK_CD = ISNULL(NULLIF(A2.WORK_CD, ''), A2.PLAN_WORK_CD))
|
||||
WHERE A2.CORP_NO = #{corpNo}
|
||||
AND A2.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
GROUP BY A2.CORP_NO, A2.USR_ID
|
||||
) A ON (A.CORP_NO = U.CORP_NO AND A.USR_ID = U.USR_ID)
|
||||
LEFT JOIN SX_GW0060 B
|
||||
ON (B.CORP_NO = U.CORP_NO
|
||||
AND B.USR_ID = U.USR_ID
|
||||
AND B.YYVCT_YY = SUBSTRING(#{staYmd}, 1, 4))
|
||||
WHERE U.CORP_NO = #{corpNo}
|
||||
AND (ISNULL(#{usrId}, '') = '' OR U.USR_ID = #{usrId})
|
||||
AND (ISNULL(#{usrNm}, '') = '' OR U.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
AND (ISNULL(#{teamCd}, '') = '' OR U.TEAM_CD = #{teamCd})
|
||||
AND (ISNULL(#{dutyCd}, '') = '' OR U.DUTY_CD = #{dutyCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR ISNULL(U.RETIREMENT_DATE, '') = '')
|
||||
ORDER BY U.USR_NM, U.USR_ID
|
||||
]]></select>
|
||||
|
||||
<select id="getWstatList" databaseId="mariadb" parameterType="map" resultType="map"><![CDATA[
|
||||
SELECT U.USR_ID,
|
||||
U.USR_NM,
|
||||
U.TEAM_CD,
|
||||
U.DUTY_CD,
|
||||
IFNULL(A.WORK_DCNT, 0) AS WORK_DCNT,
|
||||
(SELECT COUNT('A')
|
||||
FROM SX_GW0050 AT
|
||||
WHERE AT.CORP_NO = U.CORP_NO
|
||||
AND AT.USR_ID = U.USR_ID
|
||||
AND AT.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
AND AT.WORK_START_DT IS NULL
|
||||
AND IFNULL(AT.WORK_CD, AT.PLAN_WORK_CD) >= 'A'
|
||||
AND IFNULL(AT.WORK_CD, AT.PLAN_WORK_CD) <= 'T') AS ABTI_DCNT,
|
||||
IFNULL(A.YYCT_DEDU_DCNT, 0) AS YYCT_DEDU_DCNT,
|
||||
IFNULL(A.LATE_DCNT, 0) AS LATE_DCNT,
|
||||
IFNULL(A.SKIPOFF_DCNT, 0) AS SKIPOFF_DCNT,
|
||||
IFNULL(A.SICKLEAVE_DCNT, 0) AS SICKLEAVE_DCNT,
|
||||
IFNULL(A.TOT_WORK_MIN, 0) AS TOT_WORK_MIN,
|
||||
IFNULL(A.LATE_MIN, 0) AS LATE_MIN,
|
||||
IFNULL(A.SKIPOFF_REMN_BZ_MIN, 0) AS SKIPOFF_REMN_BZ_MIN,
|
||||
IFNULL(A.INCLU_WORK_OT_MIN, 0) AS INCLU_WORK_OT_MIN,
|
||||
IFNULL(A.OT_WORK_MIN, 0) AS OT_WORK_MIN,
|
||||
IFNULL(A.NGT_OT_MIN, 0) AS NGT_OT_MIN,
|
||||
IFNULL(A.OUTING_DCNT, 0) AS OUTING_DCNT,
|
||||
IFNULL(A.OUTING_MIN, 0) AS OUTING_MIN,
|
||||
IFNULL(B.YYVCT_CNT, 0) AS YYVCT_CNT
|
||||
FROM SX_GW0010 U
|
||||
LEFT JOIN (
|
||||
SELECT A2.CORP_NO,
|
||||
A2.USR_ID,
|
||||
SUM(CASE WHEN IFNULL(NULLIF(A2.ABTI_YN, ''), 'N') != 'Y'
|
||||
THEN C2.APLY_WORK_DAY END) AS WORK_DCNT,
|
||||
SUM(C2.YYCT_DEDU_DAY) AS YYCT_DEDU_DCNT,
|
||||
COUNT(CASE WHEN A2.LATE_MIN > 0 THEN 1 END) AS LATE_DCNT,
|
||||
COUNT(CASE WHEN A2.SKIPOFF_REMN_BZ_MIN > 0 THEN 1 END) AS SKIPOFF_DCNT,
|
||||
COUNT(CASE WHEN IFNULL(NULLIF(A2.WORK_CD, ''), A2.PLAN_WORK_CD) = '병'
|
||||
THEN 1 END) AS SICKLEAVE_DCNT,
|
||||
SUM(IFNULL(A2.TOT_WORK_MIN, 0)) AS TOT_WORK_MIN,
|
||||
SUM(IFNULL(A2.LATE_MIN, 0)) AS LATE_MIN,
|
||||
SUM(IFNULL(A2.SKIPOFF_REMN_BZ_MIN, 0)) AS SKIPOFF_REMN_BZ_MIN,
|
||||
SUM(IFNULL(A2.INCLU_WORK_OT_MIN, 0)) AS INCLU_WORK_OT_MIN,
|
||||
SUM(IFNULL(A2.OT_WORK_MIN, 0)) AS OT_WORK_MIN,
|
||||
SUM(IFNULL(A2.NGT_OT_MIN, 0)) AS NGT_OT_MIN,
|
||||
SUM(IFNULL(A2.OUTING_CNT, 0)) AS OUTING_DCNT,
|
||||
SUM(IFNULL(A2.OUTING_MIN, 0)) AS OUTING_MIN
|
||||
FROM SX_GW0050 A2
|
||||
LEFT JOIN SX_CO0070 C2
|
||||
ON (C2.CORP_NO = A2.CORP_NO
|
||||
AND C2.WORK_CD = IFNULL(NULLIF(A2.WORK_CD, ''), A2.PLAN_WORK_CD))
|
||||
WHERE A2.CORP_NO = #{corpNo}
|
||||
AND A2.WORK_PLAN_YYMMDD BETWEEN #{staYmd} AND #{endYmd}
|
||||
GROUP BY A2.CORP_NO, A2.USR_ID
|
||||
) A ON (A.CORP_NO = U.CORP_NO AND A.USR_ID = U.USR_ID)
|
||||
LEFT JOIN SX_GW0060 B
|
||||
ON (B.CORP_NO = U.CORP_NO
|
||||
AND B.USR_ID = U.USR_ID
|
||||
AND B.YYVCT_YY = SUBSTRING(#{staYmd}, 1, 4))
|
||||
WHERE U.CORP_NO = #{corpNo}
|
||||
AND (IFNULL(#{usrId}, '') = '' OR U.USR_ID = #{usrId})
|
||||
AND (IFNULL(#{usrNm}, '') = '' OR U.USR_NM LIKE CONCAT('%', #{usrNm}, '%'))
|
||||
AND (IFNULL(#{teamCd}, '') = '' OR U.TEAM_CD = #{teamCd})
|
||||
AND (IFNULL(#{dutyCd}, '') = '' OR U.DUTY_CD = #{dutyCd})
|
||||
AND (#{includeRetireYn} = 'Y' OR IFNULL(U.RETIREMENT_DATE, '') = '')
|
||||
ORDER BY U.USR_NM, U.USR_ID
|
||||
]]></select>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user