From 9a1a1a02c9c689751f5d2184f6feb33f489e94ce Mon Sep 17 00:00:00 2001 From: sdw086 Date: Thu, 25 Jun 2026 17:42:41 +0900 Subject: [PATCH] [api] admin/notice/~ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 공지사항 api 추가 --- .../admin/notice/AdminNoticeController.java | 139 +++++++++++ .../admin/notice/dto/AdminNoticeAddDto.java | 24 ++ .../notice/dto/AdminNoticeCampusDto.java | 12 + .../notice/dto/AdminNoticeDeleteDto.java | 11 + .../admin/notice/dto/AdminNoticeFileDto.java | 18 ++ .../admin/notice/dto/AdminNoticeListDto.java | 16 ++ .../notice/dto/AdminNoticeModifyDto.java | 24 ++ .../admin/notice/form/AdminNoticeAddForm.java | 72 ++++++ .../notice/form/AdminNoticeDeleteForm.java | 22 ++ .../notice/form/AdminNoticeFileForm.java | 52 ++++ .../notice/form/AdminNoticeListForm.java | 43 ++++ .../notice/form/AdminNoticeModifyForm.java | 82 +++++++ .../notice/mapper/AdminNoticeMapper.java | 48 ++++ .../notice/service/AdminNoticeService.java | 213 ++++++++++++++++ .../admin/notice/vo/AdminNoticeAddVo.java | 21 ++ .../admin/notice/vo/AdminNoticeDeleteVo.java | 18 ++ .../admin/notice/vo/AdminNoticeFileVo.java | 39 +++ .../admin/notice/vo/AdminNoticeListVo.java | 16 ++ .../admin/notice/vo/AdminNoticeModifyVo.java | 18 ++ .../admin/notice/vo/AdminNoticeViewVo.java | 64 +++++ .../admin/notice/vo/AdminNoticeVo.java | 45 ++++ .../mapper/admin/notice/AdminNoticeMapper.xml | 229 ++++++++++++++++++ 22 files changed, 1226 insertions(+) create mode 100644 src/main/java/com/alist/api/modules/admin/notice/AdminNoticeController.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeAddDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeCampusDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeDeleteDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeFileDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeListDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeModifyDto.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeAddForm.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeDeleteForm.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeFileForm.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeListForm.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeModifyForm.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/mapper/AdminNoticeMapper.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/service/AdminNoticeService.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeAddVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeDeleteVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeFileVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeListVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeModifyVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeViewVo.java create mode 100644 src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeVo.java create mode 100644 src/main/resources/mapper/admin/notice/AdminNoticeMapper.xml diff --git a/src/main/java/com/alist/api/modules/admin/notice/AdminNoticeController.java b/src/main/java/com/alist/api/modules/admin/notice/AdminNoticeController.java new file mode 100644 index 0000000..53acfa5 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/AdminNoticeController.java @@ -0,0 +1,139 @@ +package com.alist.api.modules.admin.notice; + +import com.alist.api.common.response.ApiResponse; +import com.alist.api.common.response.ApiResponseCode; +import com.alist.api.modules.admin.notice.form.AdminNoticeAddForm; +import com.alist.api.modules.admin.notice.form.AdminNoticeDeleteForm; +import com.alist.api.modules.admin.notice.form.AdminNoticeListForm; +import com.alist.api.modules.admin.notice.form.AdminNoticeModifyForm; +import com.alist.api.modules.admin.notice.service.AdminNoticeService; +import com.alist.api.modules.admin.notice.vo.AdminNoticeAddVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeDeleteVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeListVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeModifyVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeViewVo; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "505. 공지사항 관리", description = "관리자 공지사항 관리 API") +@RestController +@RequestMapping("/admin/notice") +public class AdminNoticeController { + private final AdminNoticeService adminNoticeService; + + public AdminNoticeController(AdminNoticeService adminNoticeService) { + this.adminNoticeService = adminNoticeService; + } + + @Operation( + summary = "공지사항 목록 조회" + , description = "관리자가 공지사항 목록을 검색 조건과 페이징으로 조회합니다." + ) + @GetMapping("/list") + public ResponseEntity> adminNoticeList( + @ModelAttribute AdminNoticeListForm adminNoticeListForm + ) { + AdminNoticeListVo adminNoticeListVo = adminNoticeService.selectAdminNoticeList(adminNoticeListForm.toDto()); + + if (adminNoticeListVo.getNoticeList() == null || adminNoticeListVo.getNoticeList().isEmpty()) { + return ApiResponse.entity(adminNoticeListVo, ApiResponseCode.CODE_2003); + } + + return ApiResponse.entity(adminNoticeListVo, ApiResponseCode.CODE_2001, "공지사항"); + } + + @Operation( + summary = "공지사항 상세 조회" + , description = "관리자가 공지사항 PK 기준으로 상세 정보를 조회합니다." + ) + @GetMapping("/view") + public ResponseEntity> adminNoticeView( + @RequestParam Long noticeIdx + ) { + AdminNoticeViewVo adminNoticeViewVo = adminNoticeService.selectAdminNoticeView(noticeIdx); + + if (adminNoticeViewVo == null) { + return ApiResponse.entity((AdminNoticeViewVo) null, ApiResponseCode.CODE_2003); + } + + return ApiResponse.entity(adminNoticeViewVo, ApiResponseCode.CODE_2001, "공지사항"); + } + + @Operation( + summary = "공지사항 등록" + , description = "관리자가 공지사항을 등록합니다. 캠퍼스 대상 공지는 campusIdxList를 함께 저장합니다." + ) + @PostMapping("/add") + public ResponseEntity> adminNoticeAdd( + @Valid @RequestBody AdminNoticeAddForm adminNoticeAddForm + ) { + AdminNoticeAddVo adminNoticeAddVo = adminNoticeService.insertAdminNoticeAdd(adminNoticeAddForm.toDto()); + + if (adminNoticeAddVo.getResultCode() == 401) { + return ApiResponse.entity(adminNoticeAddVo, ApiResponseCode.CODE_401); + } + + if (adminNoticeAddVo.getResultCode() == 4001) { + return ApiResponse.entity(adminNoticeAddVo, ApiResponseCode.CODE_4001); + } + + return ApiResponse.entity(adminNoticeAddVo, ApiResponseCode.CODE_2002, "공지사항"); + } + + @Operation( + summary = "공지사항 수정" + , description = "관리자가 공지사항 PK 기준으로 제목, 내용, 노출 범위, 첨부파일 정보를 수정합니다." + ) + @PutMapping("/modify") + public ResponseEntity> adminNoticeModify( + @Valid @RequestBody AdminNoticeModifyForm adminNoticeModifyForm + ) { + AdminNoticeModifyVo adminNoticeModifyVo = adminNoticeService.updateAdminNoticeModify(adminNoticeModifyForm.toDto()); + + if (adminNoticeModifyVo.getResultCode() == 401) { + return ApiResponse.entity(adminNoticeModifyVo, ApiResponseCode.CODE_401); + } + + if (adminNoticeModifyVo.getResultCode() == 4001) { + return ApiResponse.entity(adminNoticeModifyVo, ApiResponseCode.CODE_4001); + } + + if (!adminNoticeModifyVo.isProcessed()) { + return ApiResponse.entity(adminNoticeModifyVo, ApiResponseCode.CODE_2003); + } + + return ApiResponse.entity(adminNoticeModifyVo, ApiResponseCode.CODE_2005, "공지사항 수정"); + } + + @Operation( + summary = "공지사항 삭제" + , description = "관리자가 공지사항 PK 기준으로 삭제 처리합니다. 실제 삭제가 아닌 DEL_YN 변경 방식입니다." + ) + @PatchMapping("/delete") + public ResponseEntity> adminNoticeDelete( + @Valid @RequestBody AdminNoticeDeleteForm adminNoticeDeleteForm + ) { + AdminNoticeDeleteVo adminNoticeDeleteVo = adminNoticeService.updateAdminNoticeDelete(adminNoticeDeleteForm.toDto()); + + if (adminNoticeDeleteVo.getResultCode() == 401) { + return ApiResponse.entity(adminNoticeDeleteVo, ApiResponseCode.CODE_401); + } + + if (!adminNoticeDeleteVo.isProcessed()) { + return ApiResponse.entity(adminNoticeDeleteVo, ApiResponseCode.CODE_2003); + } + + return ApiResponse.entity(adminNoticeDeleteVo, ApiResponseCode.CODE_2005, "공지사항 삭제"); + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeAddDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeAddDto.java new file mode 100644 index 0000000..f5ab286 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeAddDto.java @@ -0,0 +1,24 @@ +package com.alist.api.modules.admin.notice.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class AdminNoticeAddDto { + private Long noticeIdx; + private String noticeType; + private String targetScope; + private List campusIdxList; + private String title; + private String content; + private String pinYn; + private String startDate; + private String endDate; + private String useYn; + private List fileList; + private Integer createMember; + private Integer updateMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeCampusDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeCampusDto.java new file mode 100644 index 0000000..9819ac0 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeCampusDto.java @@ -0,0 +1,12 @@ +package com.alist.api.modules.admin.notice.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class AdminNoticeCampusDto { + private Long noticeIdx; + private Long campusIdx; + private Integer createMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeDeleteDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeDeleteDto.java new file mode 100644 index 0000000..96b731e --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeDeleteDto.java @@ -0,0 +1,11 @@ +package com.alist.api.modules.admin.notice.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class AdminNoticeDeleteDto { + private Long noticeIdx; + private Integer updateMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeFileDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeFileDto.java new file mode 100644 index 0000000..1e6bd46 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeFileDto.java @@ -0,0 +1,18 @@ +package com.alist.api.modules.admin.notice.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class AdminNoticeFileDto { + private Long noticeIdx; + private String fileOriginalName; + private String fileSaveName; + private String filePath; + private Long fileSize; + private String fileExt; + private Integer sortOrder; + private Integer createMember; + private Integer updateMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeListDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeListDto.java new file mode 100644 index 0000000..0e69579 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeListDto.java @@ -0,0 +1,16 @@ +package com.alist.api.modules.admin.notice.dto; + +import com.alist.api.common.paging.PageRequest; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class AdminNoticeListDto extends PageRequest { + private String keyword; + private String noticeType; + private String targetScope; + private Long campusIdx; + private String pinYn; + private String useYn; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeModifyDto.java b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeModifyDto.java new file mode 100644 index 0000000..903c05d --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/dto/AdminNoticeModifyDto.java @@ -0,0 +1,24 @@ +package com.alist.api.modules.admin.notice.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class AdminNoticeModifyDto { + private Long noticeIdx; + private String noticeType; + private String targetScope; + private List campusIdxList; + private String title; + private String content; + private String pinYn; + private String startDate; + private String endDate; + private String useYn; + private List fileList; + private List deleteFileIdxList; + private Integer updateMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeAddForm.java b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeAddForm.java new file mode 100644 index 0000000..ab950ed --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeAddForm.java @@ -0,0 +1,72 @@ +package com.alist.api.modules.admin.notice.form; + +import com.alist.api.modules.admin.notice.dto.AdminNoticeAddDto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Schema(description = "관리자 공지사항 등록 요청") +@Getter +@Setter +public class AdminNoticeAddForm { + @NotBlank + @Size(max = 30) + @Schema(description = "공지 유형. GENERAL 일반, SYSTEM 시스템, EVENT 이벤트", example = "GENERAL", requiredMode = Schema.RequiredMode.REQUIRED) + private String noticeType; + + @NotBlank + @Size(max = 30) + @Schema(description = "노출 범위. ALL 전체, ADMIN 관리자, TEACHER 교사, STUDENT 학생, CAMPUS 캠퍼스", example = "CAMPUS", requiredMode = Schema.RequiredMode.REQUIRED) + private String targetScope; + + @Schema(description = "캠퍼스 IDX 목록. targetScope가 CAMPUS일 때 사용", example = "[1, 2, 3]") + private List campusIdxList; + + @NotBlank + @Size(max = 200) + @Schema(description = "제목", example = "서비스 점검 안내", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + + @NotBlank + @Schema(description = "내용", example = "서비스 점검이 예정되어 있습니다.", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Pattern(regexp = "Y|N") + @Schema(description = "상단 고정 여부. Y: 고정, N: 미고정. 미입력 시 N", example = "N") + private String pinYn; + + @Schema(description = "노출 시작일", example = "2026-07-01 00:00:00") + private String startDate; + + @Schema(description = "노출 종료일", example = "2026-07-31 23:59:59") + private String endDate; + + @Pattern(regexp = "Y|N") + @Schema(description = "사용 여부. Y: 사용, N: 미사용. 미입력 시 Y", example = "Y") + private String useYn; + + @Valid + @Schema(description = "첨부파일 목록") + private List fileList; + + public AdminNoticeAddDto toDto() { + AdminNoticeAddDto adminNoticeAddDto = new AdminNoticeAddDto(); + adminNoticeAddDto.setNoticeType(noticeType.trim()); + adminNoticeAddDto.setTargetScope(targetScope.trim()); + adminNoticeAddDto.setCampusIdxList(campusIdxList); + adminNoticeAddDto.setTitle(title.trim()); + adminNoticeAddDto.setContent(content.trim()); + adminNoticeAddDto.setPinYn(pinYn == null || pinYn.trim().isEmpty() ? "N" : pinYn.trim()); + adminNoticeAddDto.setStartDate(startDate == null || startDate.trim().isEmpty() ? null : startDate.trim()); + adminNoticeAddDto.setEndDate(endDate == null || endDate.trim().isEmpty() ? null : endDate.trim()); + adminNoticeAddDto.setUseYn(useYn == null || useYn.trim().isEmpty() ? "Y" : useYn.trim()); + adminNoticeAddDto.setFileList(fileList == null ? null : fileList.stream().map(AdminNoticeFileForm::toDto).toList()); + return adminNoticeAddDto; + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeDeleteForm.java b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeDeleteForm.java new file mode 100644 index 0000000..1818be5 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeDeleteForm.java @@ -0,0 +1,22 @@ +package com.alist.api.modules.admin.notice.form; + +import com.alist.api.modules.admin.notice.dto.AdminNoticeDeleteDto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 삭제 요청") +@Getter +@Setter +public class AdminNoticeDeleteForm { + @NotNull + @Schema(description = "공지사항 PK", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) + private Long noticeIdx; + + public AdminNoticeDeleteDto toDto() { + AdminNoticeDeleteDto adminNoticeDeleteDto = new AdminNoticeDeleteDto(); + adminNoticeDeleteDto.setNoticeIdx(noticeIdx); + return adminNoticeDeleteDto; + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeFileForm.java b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeFileForm.java new file mode 100644 index 0000000..11ff224 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeFileForm.java @@ -0,0 +1,52 @@ +package com.alist.api.modules.admin.notice.form; + +import com.alist.api.modules.admin.notice.dto.AdminNoticeFileDto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 첨부파일 요청") +@Getter +@Setter +public class AdminNoticeFileForm { + @NotBlank + @Size(max = 255) + @Schema(description = "원본 파일명", example = "notice.pdf", requiredMode = Schema.RequiredMode.REQUIRED) + private String fileOriginalName; + + @NotBlank + @Size(max = 255) + @Schema(description = "저장 파일명", example = "20260701120000_notice.pdf", requiredMode = Schema.RequiredMode.REQUIRED) + private String fileSaveName; + + @NotBlank + @Size(max = 500) + @Schema(description = "파일 경로", example = "/uploads/notice/2026/07/01/20260701120000_notice.pdf", requiredMode = Schema.RequiredMode.REQUIRED) + private String filePath; + + @Min(0) + @Schema(description = "파일 크기", example = "2048") + private Long fileSize; + + @Size(max = 20) + @Schema(description = "파일 확장자", example = "pdf") + private String fileExt; + + @Min(0) + @Schema(description = "정렬 순서. 미입력 시 0", example = "0") + private Integer sortOrder; + + public AdminNoticeFileDto toDto() { + AdminNoticeFileDto adminNoticeFileDto = new AdminNoticeFileDto(); + adminNoticeFileDto.setFileOriginalName(fileOriginalName.trim()); + adminNoticeFileDto.setFileSaveName(fileSaveName.trim()); + adminNoticeFileDto.setFilePath(filePath.trim()); + adminNoticeFileDto.setFileSize(fileSize); + adminNoticeFileDto.setFileExt(fileExt == null ? null : fileExt.trim()); + adminNoticeFileDto.setSortOrder(sortOrder == null ? 0 : sortOrder); + return adminNoticeFileDto; + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeListForm.java b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeListForm.java new file mode 100644 index 0000000..bf5d33b --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeListForm.java @@ -0,0 +1,43 @@ +package com.alist.api.modules.admin.notice.form; + +import com.alist.api.common.paging.PageRequest; +import com.alist.api.modules.admin.notice.dto.AdminNoticeListDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 목록 검색 조건") +@Getter +@Setter +public class AdminNoticeListForm extends PageRequest { + @Schema(description = "검색어. 제목, 내용을 대상으로 검색합니다.", example = "점검") + private String keyword; + + @Schema(description = "공지 유형. GENERAL 일반, SYSTEM 시스템, EVENT 이벤트", example = "GENERAL") + private String noticeType; + + @Schema(description = "노출 범위. ALL 전체, ADMIN 관리자, TEACHER 교사, STUDENT 학생, CAMPUS 캠퍼스", example = "CAMPUS") + private String targetScope; + + @Schema(description = "캠퍼스 IDX. 특정 캠퍼스 대상 공지를 검색할 때 사용", example = "1") + private Long campusIdx; + + @Schema(description = "상단 고정 여부. Y: 고정, N: 미고정", example = "Y") + private String pinYn; + + @Schema(description = "사용 여부. Y: 사용, N: 미사용", example = "Y") + private String useYn; + + public AdminNoticeListDto toDto() { + AdminNoticeListDto adminNoticeListDto = new AdminNoticeListDto(); + adminNoticeListDto.setPage(getPage()); + adminNoticeListDto.setSize(getSize()); + adminNoticeListDto.setKeyword(keyword == null ? null : keyword.trim()); + adminNoticeListDto.setNoticeType(noticeType == null ? null : noticeType.trim()); + adminNoticeListDto.setTargetScope(targetScope == null ? null : targetScope.trim()); + adminNoticeListDto.setCampusIdx(campusIdx); + adminNoticeListDto.setPinYn(pinYn == null ? null : pinYn.trim()); + adminNoticeListDto.setUseYn(useYn == null ? null : useYn.trim()); + return adminNoticeListDto; + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeModifyForm.java b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeModifyForm.java new file mode 100644 index 0000000..d986dcd --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/form/AdminNoticeModifyForm.java @@ -0,0 +1,82 @@ +package com.alist.api.modules.admin.notice.form; + +import com.alist.api.modules.admin.notice.dto.AdminNoticeModifyDto; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Schema(description = "관리자 공지사항 수정 요청") +@Getter +@Setter +public class AdminNoticeModifyForm { + @NotNull + @Schema(description = "공지사항 PK", example = "1", requiredMode = Schema.RequiredMode.REQUIRED) + private Long noticeIdx; + + @NotBlank + @Size(max = 30) + @Schema(description = "공지 유형. GENERAL 일반, SYSTEM 시스템, EVENT 이벤트", example = "GENERAL", requiredMode = Schema.RequiredMode.REQUIRED) + private String noticeType; + + @NotBlank + @Size(max = 30) + @Schema(description = "노출 범위. ALL 전체, ADMIN 관리자, TEACHER 교사, STUDENT 학생, CAMPUS 캠퍼스", example = "CAMPUS", requiredMode = Schema.RequiredMode.REQUIRED) + private String targetScope; + + @Schema(description = "캠퍼스 IDX 목록. targetScope가 CAMPUS일 때 사용", example = "[1, 2, 3]") + private List campusIdxList; + + @NotBlank + @Size(max = 200) + @Schema(description = "제목", example = "서비스 점검 안내", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + + @NotBlank + @Schema(description = "내용", example = "서비스 점검이 예정되어 있습니다.", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Pattern(regexp = "Y|N") + @Schema(description = "상단 고정 여부. Y: 고정, N: 미고정. 미입력 시 N", example = "N") + private String pinYn; + + @Schema(description = "노출 시작일", example = "2026-07-01 00:00:00") + private String startDate; + + @Schema(description = "노출 종료일", example = "2026-07-31 23:59:59") + private String endDate; + + @Pattern(regexp = "Y|N") + @Schema(description = "사용 여부. Y: 사용, N: 미사용. 미입력 시 Y", example = "Y") + private String useYn; + + @Valid + @Schema(description = "신규 첨부파일 목록. 기존 첨부파일은 유지되고 전달된 파일만 추가됩니다.") + private List fileList; + + @Schema(description = "삭제할 기존 첨부파일 PK 목록", example = "[1, 2]") + private List deleteFileIdxList; + + public AdminNoticeModifyDto toDto() { + AdminNoticeModifyDto adminNoticeModifyDto = new AdminNoticeModifyDto(); + adminNoticeModifyDto.setNoticeIdx(noticeIdx); + adminNoticeModifyDto.setNoticeType(noticeType.trim()); + adminNoticeModifyDto.setTargetScope(targetScope.trim()); + adminNoticeModifyDto.setCampusIdxList(campusIdxList); + adminNoticeModifyDto.setTitle(title.trim()); + adminNoticeModifyDto.setContent(content.trim()); + adminNoticeModifyDto.setPinYn(pinYn == null || pinYn.trim().isEmpty() ? "N" : pinYn.trim()); + adminNoticeModifyDto.setStartDate(startDate == null || startDate.trim().isEmpty() ? null : startDate.trim()); + adminNoticeModifyDto.setEndDate(endDate == null || endDate.trim().isEmpty() ? null : endDate.trim()); + adminNoticeModifyDto.setUseYn(useYn == null || useYn.trim().isEmpty() ? "Y" : useYn.trim()); + adminNoticeModifyDto.setFileList(fileList == null ? null : fileList.stream().map(AdminNoticeFileForm::toDto).toList()); + adminNoticeModifyDto.setDeleteFileIdxList(deleteFileIdxList); + return adminNoticeModifyDto; + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/mapper/AdminNoticeMapper.java b/src/main/java/com/alist/api/modules/admin/notice/mapper/AdminNoticeMapper.java new file mode 100644 index 0000000..6f4d45c --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/mapper/AdminNoticeMapper.java @@ -0,0 +1,48 @@ +package com.alist.api.modules.admin.notice.mapper; + +import com.alist.api.modules.admin.notice.dto.AdminNoticeAddDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeCampusDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeDeleteDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeFileDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeListDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeModifyDto; +import com.alist.api.modules.admin.notice.vo.AdminNoticeFileVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeViewVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface AdminNoticeMapper { + int selectAdminNoticeCount(AdminNoticeListDto adminNoticeListDto); + + List selectAdminNoticeList(AdminNoticeListDto adminNoticeListDto); + + AdminNoticeViewVo selectAdminNoticeView(Long noticeIdx); + + List selectAdminNoticeCampusIdxList(Long noticeIdx); + + List selectAdminNoticeFileList(Long noticeIdx); + + int insertAdminNoticeAdd(AdminNoticeAddDto adminNoticeAddDto); + + int insertAdminNoticeCampusAdd(AdminNoticeCampusDto adminNoticeCampusDto); + + int insertAdminNoticeFileAdd(AdminNoticeFileDto adminNoticeFileDto); + + int updateAdminNoticeModify(AdminNoticeModifyDto adminNoticeModifyDto); + + int updateAdminNoticeDelete(AdminNoticeDeleteDto adminNoticeDeleteDto); + + int deleteAdminNoticeCampusByNoticeIdx(Long noticeIdx); + + int updateAdminNoticeFileDeleteByNoticeIdx(@Param("noticeIdx") Long noticeIdx, @Param("updateMember") Integer updateMember); + + int updateAdminNoticeFileDeleteByNoticeFileIdxList( + @Param("noticeIdx") Long noticeIdx + , @Param("noticeFileIdxList") List noticeFileIdxList + , @Param("updateMember") Integer updateMember + ); +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/service/AdminNoticeService.java b/src/main/java/com/alist/api/modules/admin/notice/service/AdminNoticeService.java new file mode 100644 index 0000000..8d71a5a --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/service/AdminNoticeService.java @@ -0,0 +1,213 @@ +package com.alist.api.modules.admin.notice.service; + +import com.alist.api.common.utils.SecurityUtil; +import com.alist.api.modules.admin.auth.mapper.AdminAuthMapper; +import com.alist.api.modules.admin.auth.vo.AdminAuthLoginVo; +import com.alist.api.modules.admin.notice.dto.AdminNoticeAddDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeCampusDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeDeleteDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeFileDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeListDto; +import com.alist.api.modules.admin.notice.dto.AdminNoticeModifyDto; +import com.alist.api.modules.admin.notice.mapper.AdminNoticeMapper; +import com.alist.api.modules.admin.notice.vo.AdminNoticeAddVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeDeleteVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeFileVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeListVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeModifyVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeViewVo; +import com.alist.api.modules.admin.notice.vo.AdminNoticeVo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class AdminNoticeService { + private final AdminNoticeMapper adminNoticeMapper; + private final AdminAuthMapper adminAuthMapper; + + public AdminNoticeService(AdminNoticeMapper adminNoticeMapper, AdminAuthMapper adminAuthMapper) { + this.adminNoticeMapper = adminNoticeMapper; + this.adminAuthMapper = adminAuthMapper; + } + + @Transactional(readOnly = true) + public AdminNoticeListVo selectAdminNoticeList(AdminNoticeListDto adminNoticeListDto) { + int totalCount = adminNoticeMapper.selectAdminNoticeCount(adminNoticeListDto); + List noticeList = adminNoticeMapper.selectAdminNoticeList(adminNoticeListDto); + + AdminNoticeListVo adminNoticeListVo = new AdminNoticeListVo(); + adminNoticeListVo.setNoticeList(noticeList); + adminNoticeListVo.setPaging(adminNoticeListDto, totalCount); + + return adminNoticeListVo; + } + + @Transactional(readOnly = true) + public AdminNoticeViewVo selectAdminNoticeView(Long noticeIdx) { + AdminNoticeViewVo adminNoticeViewVo = adminNoticeMapper.selectAdminNoticeView(noticeIdx); + + if (adminNoticeViewVo == null) { + return null; + } + + List campusIdxList = adminNoticeMapper.selectAdminNoticeCampusIdxList(noticeIdx); + List fileList = adminNoticeMapper.selectAdminNoticeFileList(noticeIdx); + adminNoticeViewVo.setCampusIdxList(campusIdxList); + adminNoticeViewVo.setFileList(fileList); + + return adminNoticeViewVo; + } + + @Transactional + public AdminNoticeAddVo insertAdminNoticeAdd(AdminNoticeAddDto adminNoticeAddDto) { + AdminNoticeAddVo adminNoticeAddVo = new AdminNoticeAddVo(); + Integer adminUserIdx = getLoginAdminUserIdx(); + + if (adminUserIdx == null) { + adminNoticeAddVo.setResultCode(401); + adminNoticeAddVo.setProcessed(false); + return adminNoticeAddVo; + } + + if (!isValidCampusScope(adminNoticeAddDto.getTargetScope(), adminNoticeAddDto.getCampusIdxList())) { + adminNoticeAddVo.setResultCode(4001); + adminNoticeAddVo.setProcessed(false); + return adminNoticeAddVo; + } + + adminNoticeAddDto.setCreateMember(adminUserIdx); + adminNoticeAddDto.setUpdateMember(adminUserIdx); + + int insertCount = adminNoticeMapper.insertAdminNoticeAdd(adminNoticeAddDto); + + insertCampusList(adminNoticeAddDto.getNoticeIdx(), adminNoticeAddDto.getTargetScope(), adminNoticeAddDto.getCampusIdxList(), adminUserIdx); + insertFileList(adminNoticeAddDto.getNoticeIdx(), adminNoticeAddDto.getFileList(), adminUserIdx); + + adminNoticeAddVo.setResultCode(2002); + adminNoticeAddVo.setProcessed(insertCount > 0); + adminNoticeAddVo.setNoticeIdx(adminNoticeAddDto.getNoticeIdx()); + + return adminNoticeAddVo; + } + + @Transactional + public AdminNoticeModifyVo updateAdminNoticeModify(AdminNoticeModifyDto adminNoticeModifyDto) { + AdminNoticeModifyVo adminNoticeModifyVo = new AdminNoticeModifyVo(); + Integer adminUserIdx = getLoginAdminUserIdx(); + + if (adminUserIdx == null) { + adminNoticeModifyVo.setResultCode(401); + adminNoticeModifyVo.setProcessed(false); + return adminNoticeModifyVo; + } + + if (!isValidCampusScope(adminNoticeModifyDto.getTargetScope(), adminNoticeModifyDto.getCampusIdxList())) { + adminNoticeModifyVo.setResultCode(4001); + adminNoticeModifyVo.setProcessed(false); + return adminNoticeModifyVo; + } + + adminNoticeModifyDto.setUpdateMember(adminUserIdx); + + int updateCount = adminNoticeMapper.updateAdminNoticeModify(adminNoticeModifyDto); + + if (updateCount > 0) { + adminNoticeMapper.deleteAdminNoticeCampusByNoticeIdx(adminNoticeModifyDto.getNoticeIdx()); + deleteFileList(adminNoticeModifyDto.getNoticeIdx(), adminNoticeModifyDto.getDeleteFileIdxList(), adminUserIdx); + + insertCampusList(adminNoticeModifyDto.getNoticeIdx(), adminNoticeModifyDto.getTargetScope(), adminNoticeModifyDto.getCampusIdxList(), adminUserIdx); + insertFileList(adminNoticeModifyDto.getNoticeIdx(), adminNoticeModifyDto.getFileList(), adminUserIdx); + } + + adminNoticeModifyVo.setResultCode(2005); + adminNoticeModifyVo.setProcessed(updateCount > 0); + + return adminNoticeModifyVo; + } + + @Transactional + public AdminNoticeDeleteVo updateAdminNoticeDelete(AdminNoticeDeleteDto adminNoticeDeleteDto) { + AdminNoticeDeleteVo adminNoticeDeleteVo = new AdminNoticeDeleteVo(); + Integer adminUserIdx = getLoginAdminUserIdx(); + + if (adminUserIdx == null) { + adminNoticeDeleteVo.setResultCode(401); + adminNoticeDeleteVo.setProcessed(false); + return adminNoticeDeleteVo; + } + + adminNoticeDeleteDto.setUpdateMember(adminUserIdx); + + int updateCount = adminNoticeMapper.updateAdminNoticeDelete(adminNoticeDeleteDto); + + if (updateCount > 0) { + adminNoticeMapper.updateAdminNoticeFileDeleteByNoticeIdx(adminNoticeDeleteDto.getNoticeIdx(), adminUserIdx); + } + + adminNoticeDeleteVo.setResultCode(2005); + adminNoticeDeleteVo.setProcessed(updateCount > 0); + + return adminNoticeDeleteVo; + } + + private Integer getLoginAdminUserIdx() { + Integer loginUserTokenIdx = SecurityUtil.getLoginUserTokenIdx(); + + if (loginUserTokenIdx == null) { + return null; + } + + AdminAuthLoginVo adminAuthLoginVo = adminAuthMapper.selectAdminTokenByUserTokenIdx(loginUserTokenIdx); + + if (adminAuthLoginVo == null || adminAuthLoginVo.getUserIdx() == null) { + return null; + } + + return adminAuthLoginVo.getUserIdx(); + } + + private boolean isValidCampusScope(String targetScope, List campusIdxList) { + if (!"CAMPUS".equals(targetScope)) { + return true; + } + + return campusIdxList != null && !campusIdxList.isEmpty(); + } + + private void insertCampusList(Long noticeIdx, String targetScope, List campusIdxList, Integer adminUserIdx) { + if (!"CAMPUS".equals(targetScope) || campusIdxList == null) { + return; + } + + for (Long campusIdx : campusIdxList) { + AdminNoticeCampusDto adminNoticeCampusDto = new AdminNoticeCampusDto(); + adminNoticeCampusDto.setNoticeIdx(noticeIdx); + adminNoticeCampusDto.setCampusIdx(campusIdx); + adminNoticeCampusDto.setCreateMember(adminUserIdx); + adminNoticeMapper.insertAdminNoticeCampusAdd(adminNoticeCampusDto); + } + } + + private void insertFileList(Long noticeIdx, List fileList, Integer adminUserIdx) { + if (fileList == null || fileList.isEmpty()) { + return; + } + + for (AdminNoticeFileDto adminNoticeFileDto : fileList) { + adminNoticeFileDto.setNoticeIdx(noticeIdx); + adminNoticeFileDto.setCreateMember(adminUserIdx); + adminNoticeFileDto.setUpdateMember(adminUserIdx); + adminNoticeMapper.insertAdminNoticeFileAdd(adminNoticeFileDto); + } + } + + private void deleteFileList(Long noticeIdx, List deleteFileIdxList, Integer adminUserIdx) { + if (deleteFileIdxList == null || deleteFileIdxList.isEmpty()) { + return; + } + + adminNoticeMapper.updateAdminNoticeFileDeleteByNoticeFileIdxList(noticeIdx, deleteFileIdxList, adminUserIdx); + } +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeAddVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeAddVo.java new file mode 100644 index 0000000..2398d4e --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeAddVo.java @@ -0,0 +1,21 @@ +package com.alist.api.modules.admin.notice.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 등록 응답") +@Getter +@Setter +public class AdminNoticeAddVo { + @Schema(description = "공지사항 등록 여부", example = "true") + private boolean processed; + + @Schema(description = "등록된 공지사항 PK", example = "1") + private Long noticeIdx; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeDeleteVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeDeleteVo.java new file mode 100644 index 0000000..2d3c7dd --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeDeleteVo.java @@ -0,0 +1,18 @@ +package com.alist.api.modules.admin.notice.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 삭제 응답") +@Getter +@Setter +public class AdminNoticeDeleteVo { + @Schema(description = "공지사항 삭제 처리 여부", example = "true") + private boolean processed; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeFileVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeFileVo.java new file mode 100644 index 0000000..8ed2ac0 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeFileVo.java @@ -0,0 +1,39 @@ +package com.alist.api.modules.admin.notice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Schema(description = "관리자 공지사항 첨부파일 응답") +@Getter +@Setter +public class AdminNoticeFileVo { + @Schema(description = "공지사항 첨부파일 PK", example = "1") + private Long noticeFileIdx; + + @Schema(description = "공지사항 PK", example = "1") + private Long noticeIdx; + + @Schema(description = "원본 파일명", example = "notice.pdf") + private String fileOriginalName; + + @Schema(description = "저장 파일명", example = "20260701120000_notice.pdf") + private String fileSaveName; + + @Schema(description = "파일 경로", example = "/uploads/notice/2026/07/01/20260701120000_notice.pdf") + private String filePath; + + @Schema(description = "파일 크기", example = "2048") + private Long fileSize; + + @Schema(description = "파일 확장자", example = "pdf") + private String fileExt; + + @Schema(description = "정렬 순서", example = "0") + private Integer sortOrder; + + @Schema(description = "생성일", example = "2026-07-01 10:00:00") + private LocalDateTime createDate; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeListVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeListVo.java new file mode 100644 index 0000000..96d10a9 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeListVo.java @@ -0,0 +1,16 @@ +package com.alist.api.modules.admin.notice.vo; + +import com.alist.api.common.paging.PageResponse; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Schema(description = "관리자 공지사항 목록 조회 응답") +@Getter +@Setter +public class AdminNoticeListVo extends PageResponse { + @Schema(description = "공지사항 목록") + private List noticeList; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeModifyVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeModifyVo.java new file mode 100644 index 0000000..5abe84d --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeModifyVo.java @@ -0,0 +1,18 @@ +package com.alist.api.modules.admin.notice.vo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Schema(description = "관리자 공지사항 수정 응답") +@Getter +@Setter +public class AdminNoticeModifyVo { + @Schema(description = "공지사항 수정 여부", example = "true") + private boolean processed; + + @JsonIgnore + @Schema(hidden = true) + private int resultCode; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeViewVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeViewVo.java new file mode 100644 index 0000000..b245fd3 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeViewVo.java @@ -0,0 +1,64 @@ +package com.alist.api.modules.admin.notice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "관리자 공지사항 상세 조회 응답") +@Getter +@Setter +public class AdminNoticeViewVo { + @Schema(description = "공지사항 PK", example = "1") + private Long noticeIdx; + + @Schema(description = "공지 유형", example = "GENERAL") + private String noticeType; + + @Schema(description = "노출 범위", example = "CAMPUS") + private String targetScope; + + @Schema(description = "캠퍼스 IDX 목록", example = "[1, 2, 3]") + private List campusIdxList; + + @Schema(description = "제목", example = "서비스 점검 안내") + private String title; + + @Schema(description = "내용", example = "서비스 점검이 예정되어 있습니다.") + private String content; + + @Schema(description = "상단 고정 여부", example = "N") + private String pinYn; + + @Schema(description = "노출 시작일", example = "2026-07-01 00:00:00") + private LocalDateTime startDate; + + @Schema(description = "노출 종료일", example = "2026-07-31 23:59:59") + private LocalDateTime endDate; + + @Schema(description = "조회수", example = "0") + private Integer viewCount; + + @Schema(description = "사용 여부", example = "Y") + private String useYn; + + @Schema(description = "삭제 여부", example = "N") + private String delYn; + + @Schema(description = "첨부파일 목록") + private List fileList; + + @Schema(description = "생성일", example = "2026-07-01 10:00:00") + private LocalDateTime createDate; + + @Schema(description = "생성자 회원 PK", example = "1") + private Integer createMember; + + @Schema(description = "수정일", example = "2026-07-01 10:00:00") + private LocalDateTime updateDate; + + @Schema(description = "수정자 회원 PK", example = "1") + private Integer updateMember; +} diff --git a/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeVo.java b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeVo.java new file mode 100644 index 0000000..0063c54 --- /dev/null +++ b/src/main/java/com/alist/api/modules/admin/notice/vo/AdminNoticeVo.java @@ -0,0 +1,45 @@ +package com.alist.api.modules.admin.notice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Schema(description = "관리자 공지사항 목록 항목") +@Getter +@Setter +public class AdminNoticeVo { + @Schema(description = "공지사항 PK", example = "1") + private Long noticeIdx; + + @Schema(description = "공지 유형", example = "GENERAL") + private String noticeType; + + @Schema(description = "노출 범위", example = "CAMPUS") + private String targetScope; + + @Schema(description = "제목", example = "서비스 점검 안내") + private String title; + + @Schema(description = "상단 고정 여부", example = "N") + private String pinYn; + + @Schema(description = "노출 시작일", example = "2026-07-01 00:00:00") + private LocalDateTime startDate; + + @Schema(description = "노출 종료일", example = "2026-07-31 23:59:59") + private LocalDateTime endDate; + + @Schema(description = "조회수", example = "0") + private Integer viewCount; + + @Schema(description = "사용 여부", example = "Y") + private String useYn; + + @Schema(description = "생성일", example = "2026-07-01 10:00:00") + private LocalDateTime createDate; + + @Schema(description = "수정일", example = "2026-07-01 10:00:00") + private LocalDateTime updateDate; +} diff --git a/src/main/resources/mapper/admin/notice/AdminNoticeMapper.xml b/src/main/resources/mapper/admin/notice/AdminNoticeMapper.xml new file mode 100644 index 0000000..fc8a9f1 --- /dev/null +++ b/src/main/resources/mapper/admin/notice/AdminNoticeMapper.xml @@ -0,0 +1,229 @@ + + + + + + FROM ALISTLMS.NOTICE N + WHERE N.DEL_YN = 'N' + + AND ( + N.TITLE LIKE CONCAT('%', #{keyword}, '%') + OR N.CONTENT LIKE CONCAT('%', #{keyword}, '%') + ) + + + AND N.NOTICE_TYPE = #{noticeType} + + + AND N.TARGET_SCOPE = #{targetScope} + + + AND EXISTS ( + SELECT 1 + FROM ALISTLMS.NOTICE_CAMPUS NC + WHERE NC.NOTICE_IDX = N.NOTICE_IDX + AND NC.CAMPUS_IDX = #{campusIdx} + ) + + + AND N.PIN_YN = #{pinYn} + + + AND N.USE_YN = #{useYn} + + + + + + + + + + + + + + + /*AdminNoticeMapper.insertAdminNoticeAdd*/ + INSERT INTO ALISTLMS.NOTICE ( + NOTICE_TYPE + , TARGET_SCOPE + , TITLE + , CONTENT + , PIN_YN + , START_DATE + , END_DATE + , USE_YN + , DEL_YN + , CREATE_MEMBER + , UPDATE_MEMBER + ) VALUES ( + #{noticeType} + , #{targetScope} + , #{title} + , #{content} + , #{pinYn} + , #{startDate} + , #{endDate} + , #{useYn} + , 'N' + , #{createMember} + , #{updateMember} + ) + + + + /*AdminNoticeMapper.insertAdminNoticeCampusAdd*/ + INSERT INTO ALISTLMS.NOTICE_CAMPUS ( + NOTICE_IDX + , CAMPUS_IDX + , CREATE_MEMBER + ) VALUES ( + #{noticeIdx} + , #{campusIdx} + , #{createMember} + ) + + + + /*AdminNoticeMapper.insertAdminNoticeFileAdd*/ + INSERT INTO ALISTLMS.NOTICE_FILE ( + NOTICE_IDX + , FILE_ORIGINAL_NAME + , FILE_SAVE_NAME + , FILE_PATH + , FILE_SIZE + , FILE_EXT + , SORT_ORDER + , DEL_YN + , CREATE_MEMBER + , UPDATE_MEMBER + ) VALUES ( + #{noticeIdx} + , #{fileOriginalName} + , #{fileSaveName} + , #{filePath} + , #{fileSize} + , #{fileExt} + , #{sortOrder} + , 'N' + , #{createMember} + , #{updateMember} + ) + + + + /*AdminNoticeMapper.updateAdminNoticeModify*/ + UPDATE ALISTLMS.NOTICE + SET NOTICE_TYPE = #{noticeType} + , TARGET_SCOPE = #{targetScope} + , TITLE = #{title} + , CONTENT = #{content} + , PIN_YN = #{pinYn} + , START_DATE = #{startDate} + , END_DATE = #{endDate} + , USE_YN = #{useYn} + , UPDATE_MEMBER = #{updateMember} + WHERE NOTICE_IDX = #{noticeIdx} + AND DEL_YN = 'N' + + + + /*AdminNoticeMapper.updateAdminNoticeDelete*/ + UPDATE ALISTLMS.NOTICE + SET DEL_YN = 'Y' + , UPDATE_MEMBER = #{updateMember} + WHERE NOTICE_IDX = #{noticeIdx} + AND DEL_YN = 'N' + + + + /*AdminNoticeMapper.deleteAdminNoticeCampusByNoticeIdx*/ + DELETE FROM ALISTLMS.NOTICE_CAMPUS + WHERE NOTICE_IDX = #{noticeIdx} + + + + /*AdminNoticeMapper.updateAdminNoticeFileDeleteByNoticeIdx*/ + UPDATE ALISTLMS.NOTICE_FILE + SET DEL_YN = 'Y' + , UPDATE_MEMBER = #{updateMember} + WHERE NOTICE_IDX = #{noticeIdx} + AND DEL_YN = 'N' + + + + /*AdminNoticeMapper.updateAdminNoticeFileDeleteByNoticeFileIdxList*/ + UPDATE ALISTLMS.NOTICE_FILE + SET DEL_YN = 'Y' + , UPDATE_MEMBER = #{updateMember} + WHERE NOTICE_IDX = #{noticeIdx} + AND DEL_YN = 'N' + AND NOTICE_FILE_IDX IN + + #{noticeFileIdx} + + +