[api] admin/notice/~
공지사항 api 추가
This commit is contained in:
@@ -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<ApiResponse<AdminNoticeListVo>> 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<ApiResponse<AdminNoticeViewVo>> 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<ApiResponse<AdminNoticeAddVo>> 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<ApiResponse<AdminNoticeModifyVo>> 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<ApiResponse<AdminNoticeDeleteVo>> 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, "공지사항 삭제");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Long> campusIdxList;
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
private String pinYn;
|
||||||
|
private String startDate;
|
||||||
|
private String endDate;
|
||||||
|
private String useYn;
|
||||||
|
private List<AdminNoticeFileDto> fileList;
|
||||||
|
private Integer createMember;
|
||||||
|
private Integer updateMember;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<Long> campusIdxList;
|
||||||
|
private String title;
|
||||||
|
private String content;
|
||||||
|
private String pinYn;
|
||||||
|
private String startDate;
|
||||||
|
private String endDate;
|
||||||
|
private String useYn;
|
||||||
|
private List<AdminNoticeFileDto> fileList;
|
||||||
|
private List<Long> deleteFileIdxList;
|
||||||
|
private Integer updateMember;
|
||||||
|
}
|
||||||
@@ -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<Long> 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<AdminNoticeFileForm> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Long> 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<AdminNoticeFileForm> fileList;
|
||||||
|
|
||||||
|
@Schema(description = "삭제할 기존 첨부파일 PK 목록", example = "[1, 2]")
|
||||||
|
private List<Long> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<AdminNoticeVo> selectAdminNoticeList(AdminNoticeListDto adminNoticeListDto);
|
||||||
|
|
||||||
|
AdminNoticeViewVo selectAdminNoticeView(Long noticeIdx);
|
||||||
|
|
||||||
|
List<Long> selectAdminNoticeCampusIdxList(Long noticeIdx);
|
||||||
|
|
||||||
|
List<AdminNoticeFileVo> 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<Long> noticeFileIdxList
|
||||||
|
, @Param("updateMember") Integer updateMember
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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<AdminNoticeVo> 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<Long> campusIdxList = adminNoticeMapper.selectAdminNoticeCampusIdxList(noticeIdx);
|
||||||
|
List<AdminNoticeFileVo> 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<Long> campusIdxList) {
|
||||||
|
if (!"CAMPUS".equals(targetScope)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return campusIdxList != null && !campusIdxList.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertCampusList(Long noticeIdx, String targetScope, List<Long> 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<AdminNoticeFileDto> 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<Long> deleteFileIdxList, Integer adminUserIdx) {
|
||||||
|
if (deleteFileIdxList == null || deleteFileIdxList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
adminNoticeMapper.updateAdminNoticeFileDeleteByNoticeFileIdxList(noticeIdx, deleteFileIdxList, adminUserIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<AdminNoticeVo> noticeList;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<Long> 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<AdminNoticeFileVo> 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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
<?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.alist.api.modules.admin.notice.mapper.AdminNoticeMapper">
|
||||||
|
<sql id="adminNoticeWhere">
|
||||||
|
FROM ALISTLMS.NOTICE N
|
||||||
|
WHERE N.DEL_YN = 'N'
|
||||||
|
<if test="keyword != null and keyword != ''">
|
||||||
|
AND (
|
||||||
|
N.TITLE LIKE CONCAT('%', #{keyword}, '%')
|
||||||
|
OR N.CONTENT LIKE CONCAT('%', #{keyword}, '%')
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
<if test="noticeType != null and noticeType != ''">
|
||||||
|
AND N.NOTICE_TYPE = #{noticeType}
|
||||||
|
</if>
|
||||||
|
<if test="targetScope != null and targetScope != ''">
|
||||||
|
AND N.TARGET_SCOPE = #{targetScope}
|
||||||
|
</if>
|
||||||
|
<if test="campusIdx != null">
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM ALISTLMS.NOTICE_CAMPUS NC
|
||||||
|
WHERE NC.NOTICE_IDX = N.NOTICE_IDX
|
||||||
|
AND NC.CAMPUS_IDX = #{campusIdx}
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
<if test="pinYn != null and pinYn != ''">
|
||||||
|
AND N.PIN_YN = #{pinYn}
|
||||||
|
</if>
|
||||||
|
<if test="useYn != null and useYn != ''">
|
||||||
|
AND N.USE_YN = #{useYn}
|
||||||
|
</if>
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectAdminNoticeCount" resultType="int">
|
||||||
|
/*AdminNoticeMapper.selectAdminNoticeCount*/
|
||||||
|
SELECT COUNT(*)
|
||||||
|
<include refid="adminNoticeWhere"/>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAdminNoticeList" resultType="com.alist.api.modules.admin.notice.vo.AdminNoticeVo">
|
||||||
|
/*AdminNoticeMapper.selectAdminNoticeList*/
|
||||||
|
SELECT N.NOTICE_IDX
|
||||||
|
, N.NOTICE_TYPE
|
||||||
|
, N.TARGET_SCOPE
|
||||||
|
, N.TITLE
|
||||||
|
, N.PIN_YN
|
||||||
|
, N.START_DATE
|
||||||
|
, N.END_DATE
|
||||||
|
, N.VIEW_COUNT
|
||||||
|
, N.USE_YN
|
||||||
|
, N.CREATE_DATE
|
||||||
|
, N.UPDATE_DATE
|
||||||
|
<include refid="adminNoticeWhere"/>
|
||||||
|
ORDER BY N.PIN_YN DESC, N.NOTICE_IDX DESC
|
||||||
|
LIMIT #{limit}
|
||||||
|
OFFSET #{offset}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAdminNoticeView" resultType="com.alist.api.modules.admin.notice.vo.AdminNoticeViewVo">
|
||||||
|
/*AdminNoticeMapper.selectAdminNoticeView*/
|
||||||
|
SELECT N.NOTICE_IDX
|
||||||
|
, N.NOTICE_TYPE
|
||||||
|
, N.TARGET_SCOPE
|
||||||
|
, N.TITLE
|
||||||
|
, N.CONTENT
|
||||||
|
, N.PIN_YN
|
||||||
|
, N.START_DATE
|
||||||
|
, N.END_DATE
|
||||||
|
, N.VIEW_COUNT
|
||||||
|
, N.USE_YN
|
||||||
|
, N.DEL_YN
|
||||||
|
, N.CREATE_DATE
|
||||||
|
, N.CREATE_MEMBER
|
||||||
|
, N.UPDATE_DATE
|
||||||
|
, N.UPDATE_MEMBER
|
||||||
|
FROM ALISTLMS.NOTICE N
|
||||||
|
WHERE N.NOTICE_IDX = #{noticeIdx}
|
||||||
|
AND N.DEL_YN = 'N'
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAdminNoticeCampusIdxList" resultType="long">
|
||||||
|
/*AdminNoticeMapper.selectAdminNoticeCampusIdxList*/
|
||||||
|
SELECT NC.CAMPUS_IDX
|
||||||
|
FROM ALISTLMS.NOTICE_CAMPUS NC
|
||||||
|
WHERE NC.NOTICE_IDX = #{noticeIdx}
|
||||||
|
ORDER BY NC.CAMPUS_IDX
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAdminNoticeFileList" resultType="com.alist.api.modules.admin.notice.vo.AdminNoticeFileVo">
|
||||||
|
/*AdminNoticeMapper.selectAdminNoticeFileList*/
|
||||||
|
SELECT NF.NOTICE_FILE_IDX
|
||||||
|
, NF.NOTICE_IDX
|
||||||
|
, NF.FILE_ORIGINAL_NAME
|
||||||
|
, NF.FILE_SAVE_NAME
|
||||||
|
, NF.FILE_PATH
|
||||||
|
, NF.FILE_SIZE
|
||||||
|
, NF.FILE_EXT
|
||||||
|
, NF.SORT_ORDER
|
||||||
|
, NF.CREATE_DATE
|
||||||
|
FROM ALISTLMS.NOTICE_FILE NF
|
||||||
|
WHERE NF.NOTICE_IDX = #{noticeIdx}
|
||||||
|
AND NF.DEL_YN = 'N'
|
||||||
|
ORDER BY NF.SORT_ORDER ASC, NF.NOTICE_FILE_IDX ASC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertAdminNoticeAdd" parameterType="com.alist.api.modules.admin.notice.dto.AdminNoticeAddDto" useGeneratedKeys="true" keyProperty="noticeIdx">
|
||||||
|
/*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}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insertAdminNoticeCampusAdd" parameterType="com.alist.api.modules.admin.notice.dto.AdminNoticeCampusDto">
|
||||||
|
/*AdminNoticeMapper.insertAdminNoticeCampusAdd*/
|
||||||
|
INSERT INTO ALISTLMS.NOTICE_CAMPUS (
|
||||||
|
NOTICE_IDX
|
||||||
|
, CAMPUS_IDX
|
||||||
|
, CREATE_MEMBER
|
||||||
|
) VALUES (
|
||||||
|
#{noticeIdx}
|
||||||
|
, #{campusIdx}
|
||||||
|
, #{createMember}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<insert id="insertAdminNoticeFileAdd" parameterType="com.alist.api.modules.admin.notice.dto.AdminNoticeFileDto">
|
||||||
|
/*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}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateAdminNoticeModify" parameterType="com.alist.api.modules.admin.notice.dto.AdminNoticeModifyDto">
|
||||||
|
/*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'
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateAdminNoticeDelete" parameterType="com.alist.api.modules.admin.notice.dto.AdminNoticeDeleteDto">
|
||||||
|
/*AdminNoticeMapper.updateAdminNoticeDelete*/
|
||||||
|
UPDATE ALISTLMS.NOTICE
|
||||||
|
SET DEL_YN = 'Y'
|
||||||
|
, UPDATE_MEMBER = #{updateMember}
|
||||||
|
WHERE NOTICE_IDX = #{noticeIdx}
|
||||||
|
AND DEL_YN = 'N'
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteAdminNoticeCampusByNoticeIdx">
|
||||||
|
/*AdminNoticeMapper.deleteAdminNoticeCampusByNoticeIdx*/
|
||||||
|
DELETE FROM ALISTLMS.NOTICE_CAMPUS
|
||||||
|
WHERE NOTICE_IDX = #{noticeIdx}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<update id="updateAdminNoticeFileDeleteByNoticeIdx">
|
||||||
|
/*AdminNoticeMapper.updateAdminNoticeFileDeleteByNoticeIdx*/
|
||||||
|
UPDATE ALISTLMS.NOTICE_FILE
|
||||||
|
SET DEL_YN = 'Y'
|
||||||
|
, UPDATE_MEMBER = #{updateMember}
|
||||||
|
WHERE NOTICE_IDX = #{noticeIdx}
|
||||||
|
AND DEL_YN = 'N'
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateAdminNoticeFileDeleteByNoticeFileIdxList">
|
||||||
|
/*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
|
||||||
|
<foreach collection="noticeFileIdxList" item="noticeFileIdx" open="(" separator="," close=")">
|
||||||
|
#{noticeFileIdx}
|
||||||
|
</foreach>
|
||||||
|
</update>
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user