feat: 게시판 관리 반영

dev
minuk926 3 years ago
parent 483ae3580a
commit 44ad4143a3

@ -2,7 +2,6 @@ package com.xit.biz.ctgy.auth.service;
import com.xit.biz.cmm.entity.CmmUser;
import com.xit.biz.ctgy.dto.LoginMinRequestDto;
import com.xit.core.oauth2.api.dto.LoginRequestDto;
import com.xit.core.oauth2.api.dto.TokenDto;
import com.xit.core.oauth2.api.dto.TokenRequestDto;

@ -1,7 +1,6 @@
package com.xit.biz.ctgy.controller;
import com.xit.biz.ctgy.dto.MinCivBoard680Dto;
import com.xit.biz.ctgy.dto.struct.MinCivBoard680Mapstruct;
import com.xit.biz.ctgy.dto.BoardDto;
import com.xit.biz.ctgy.service.IBoardService;
import com.xit.core.api.IRestResponse;
import com.xit.core.api.RestResponse;
@ -11,14 +10,12 @@ import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.mapstruct.factory.Mappers;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Tag(name = "BoardController", description = "게시글 관리")
@RestController
@ -29,7 +26,6 @@ public class BoardController {
private final IBoardService service;
private final MinCivBoard680Mapstruct mapstruct = Mappers.getMapper(MinCivBoard680Mapstruct.class);
// TODO :: 파라메터 정의 필요
@Operation(summary = "게시글 목록 조회" , description = "게시글 목록 조회")
@ -42,10 +38,25 @@ public class BoardController {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<? extends IRestResponse> findMinCivBoard680s(
@Parameter(hidden = true)
final MinCivBoard680Dto dto,
final BoardDto dto,
@Parameter(hidden = true)
final Pageable pageable) {
return RestResponse.of(service.findAll(mapstruct.toEntity(dto), pageable));
return RestResponse.of(service.findAll(dto, pageable));
}
@Operation(summary = "게시글 조회수 증가" , description = "게시글 조회수 증가")
@Parameters({
@Parameter(in = ParameterIn.PATH, name = "ciCode", description = "게시글번호", required = true, example = "18"),
})
@PutMapping(value = "/hit/{ciCode}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<? extends IRestResponse> modifyByCiCode(@PathVariable final Long ciCode) {
return RestResponse.of(service.modifyByCiCode(ciCode));
}
@Operation(summary = "게시글 등록" , description = "게시글 등록")
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<? extends IRestResponse> saveBoard(BoardDto dto) {
service.saveBoard(dto);
return RestResponse.of(HttpStatus.OK);
}
}

@ -3,19 +3,14 @@ package com.xit.biz.ctgy.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Schema(name = "MinCivBoard680Dto", description = "게시판")
@Schema(name = "BoardDto", description = "게시판")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class MinCivBoard680Dto implements Serializable {
private static final long SerialVersionUID = 1L;
public class BoardDto {
@Schema(title = "게시판코드", example = " ", description = "Input Description...")
private Long ciCode;
@ -61,4 +56,7 @@ public class MinCivBoard680Dto implements Serializable {
@Schema(required = false, title = "내용", example = " ", description = "Input Description...")
private String ciContents;
@Schema(required = false, title = "IP", example = " ", description = "")
private String ciIp;
}

@ -1,12 +1,12 @@
package com.xit.biz.ctgy.dto.struct;
import com.xit.biz.ctgy.dto.MinCivBoard680Dto;
import com.xit.biz.ctgy.dto.BoardDto;
import com.xit.biz.ctgy.entity.MinCivBoard680;
import com.xit.core.support.jpa.mapstruct.IMapstruct;
import com.xit.core.support.jpa.mapstruct.MapStructMapperConfig;
import org.mapstruct.Mapper;
@Mapper(config = MapStructMapperConfig.class)
public interface MinCivBoard680Mapstruct extends IMapstruct<MinCivBoard680Dto, MinCivBoard680> {
public interface MinCivBoard680Mapstruct extends IMapstruct<BoardDto, MinCivBoard680> {
}

@ -1,5 +1,7 @@
package com.xit.biz.ctgy.entity;
import com.xit.biz.ctgy.CtgyConstants;
import com.xit.core.oauth2.utils.HeaderUtil;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.hibernate.annotations.DynamicInsert;
@ -8,6 +10,8 @@ import org.springframework.data.domain.Persistable;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Schema(name = "MinCivBoard680", description = "게시판")
@Table(name = "min_civ_board680", schema = "", catalog = "")
@ -31,6 +35,7 @@ public class MinCivBoard680 implements Persistable<Long> {
@Schema(required = false, title = "제목", example = " ", description = "Input Description...")
@Column(name = "ci_title", nullable = true)
@Setter
private String ciTitle;
@Schema(required = false, title = "사용자아이디", example = " ", description = "Input Description...")
@ -79,12 +84,33 @@ public class MinCivBoard680 implements Persistable<Long> {
@Schema(required = false, title = "내용", example = " ", description = "Input Description...")
@Column(name = "ci_contents", nullable = true)
@Setter
private String ciContents;
@Schema(required = false, title = "IP", example = " ", description = "Input Description...")
@Column(name = "ci_ip", nullable = true)
private String ciIp;
@PrePersist
public void onPrePersist(){
LocalDateTime localDateTime = LocalDateTime.now();
this.ciNalja = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
this.ciTime = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
this.ciId = HeaderUtil.getUserId();
this.ciPwd = this.ciId;
this.ciName = HeaderUtil.getUserName();
this.ciHit = 0L;
}
@PreUpdate
public void onPreUpdate(){
// LocalDateTime localDateTime = LocalDateTime.now();
// this.inNalja = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// this.inTime = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
// this.inName = HeaderUtil.getUserName();
// this.inHit = this.inHit + 1;
}
@Override
public Long getId() {
return this.ciCode;

@ -6,6 +6,14 @@ import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface IBoardRepository extends JpaRepository<MinCivBoard680, Long>, IBoardRepositoryCustom {
@Query(value = "SELECT max(e.ci_code) + 1 FROM min_civ_board680 e", nativeQuery = true)
Long getCiCode();
@Modifying(clearAutomatically = true)
@Query("UPDATE MinCivBoard680 m SET m.ciHit = m.ciHit + 1 WHERE m.ciCode = :ciCode")
int updateInHitForMinCivBoard680(Long ciCode);
}

@ -1,10 +1,10 @@
package com.xit.biz.ctgy.repository;
import com.xit.biz.ctgy.entity.MinCivBoard680;
import com.xit.biz.ctgy.dto.BoardDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface IBoardRepositoryCustom {
Page<MinCivBoard680> findAll2(final MinCivBoard680 entity, Pageable pageable);
Page<BoardDto> findAll(final BoardDto dto, Pageable pageable);
}

@ -1,35 +1,78 @@
package com.xit.biz.ctgy.repository;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xit.biz.ctgy.entity.MinCivBoard680;
import com.xit.biz.ctgy.dto.BoardDto;
import com.xit.core.util.Checks;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import java.util.ArrayList;
import java.util.List;
import static com.xit.biz.ctgy.entity.QMinCivBoard680.minCivBoard680;
import static com.xit.biz.ctgy.entity.QMinUserinfo.minUserinfo;
@AllArgsConstructor
public class IBoardRepositoryImpl implements IBoardRepositoryCustom{
private final JPAQueryFactory queryFactory;
@Override
public Page<MinCivBoard680> findAll2(final MinCivBoard680 entity, Pageable pageable){
/*
SELECT Ci_code,
Ci_name,
ci_contentNo,
Ci_title,
Ci_nalja,
Ci_step,
Ci_revel,
Ci_ref,
ci_hit
FROM MIN_CIV_BOARD680
WHERE Ci_code IN (SELECT Ci_code
FROM (SELECT Ci_code, rownum RCNT
FROM MIN_CIV_BOARD680 "& strSearchSQL1 &"
ORDER BY Ci_ref DESC, ci_step ASC, Ci_code DESC))
*/
return null;
public Page<BoardDto> findAll(final BoardDto dto, Pageable pageable){
// 커버링 인덱스로 대상 조회
QueryResults<Long> ciCodes = queryFactory
.select(minCivBoard680.ciCode)
.from(minCivBoard680)
.where(ciTitleLike(dto.getCiTitle()), ciNameLike(dto.getCiName()))
.orderBy(minCivBoard680.ciRef.desc(), minCivBoard680.ciStep.asc(), minCivBoard680.ciCode.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetchResults();
if (Checks.isEmpty(ciCodes)) {
new PageImpl<>(new ArrayList<>(), pageable, 0);
}
List<BoardDto> rslt = queryFactory
.select(Projections.fields(
BoardDto.class,
minCivBoard680.ciCode,
minUserinfo.name.as("ciName"),
minCivBoard680.ciContentno,
minCivBoard680.ciTitle,
minCivBoard680.ciContents,
minCivBoard680.ciNalja,
minCivBoard680.ciStep,
minCivBoard680.ciRevel,
minCivBoard680.ciRef,
minCivBoard680.ciHit,
minCivBoard680.ciPass,
minCivBoard680.ciId
))
.from(minCivBoard680)
.leftJoin(minUserinfo)
.on(minCivBoard680.ciId.eq(minUserinfo.userid))
.where(minCivBoard680.ciCode.in(ciCodes.getResults()))
.orderBy(minCivBoard680.ciRef.desc(), minCivBoard680.ciStep.asc(), minCivBoard680.ciCode.desc())
.fetch();
return new PageImpl<>(rslt, pageable, ciCodes.getTotal());
}
private BooleanExpression ciTitleLike(String ciTitle){
if(Checks.isEmpty(ciTitle)) return null;
return minCivBoard680.ciTitle.contains(ciTitle);
}
private BooleanExpression ciNameLike(String ciName){
if(Checks.isEmpty(ciName)) return null;
return minCivBoard680.ciName.contains(ciName);
}
}

@ -42,7 +42,7 @@ public class IResidentAndDisabledRepositoryImpl implements IResidentAndDisabledR
public Page<GnRecallScDto> findJudgeDatas(@NotNull final String scDatagb, Pageable pageable) {
// 커버링 인덱스로 대상 조회
QueryResults<Long> scCodeList = queryFactory
QueryResults<Long> scCodes = queryFactory
.select(gnRecallSc.scCode)
.from(gnRecallSc)
.where(gnRecallSc.scDatagb.eq(scDatagb))
@ -52,7 +52,7 @@ public class IResidentAndDisabledRepositoryImpl implements IResidentAndDisabledR
.fetchResults();
// 대상이 없을 경우 추가 쿼리 수행 할 필요 없이 바로 반환
if (Checks.isEmpty(scCodeList)) {
if (Checks.isEmpty(scCodes)) {
new PageImpl<>(new ArrayList<>(), pageable, 0);
}
@ -92,11 +92,11 @@ public class IResidentAndDisabledRepositoryImpl implements IResidentAndDisabledR
"scStateNm")
))
.from(gnRecallSc)
.where(gnRecallSc.scCode.in(scCodeList.getResults()))
.where(gnRecallSc.scCode.in(scCodes.getResults()))
.orderBy(gnRecallSc.scCode.desc())
.fetch();
return new PageImpl<>(rslt, pageable, scCodeList.getTotal());
return new PageImpl<>(rslt, pageable, scCodes.getTotal());
}
@Override

@ -1,11 +1,16 @@
package com.xit.biz.ctgy.service;
import com.xit.biz.ctgy.dto.BoardDto;
import com.xit.biz.ctgy.entity.MinCivBoard680;
import com.xit.core.support.jpa.IJpaOperation;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface IBoardService {
Page<MinCivBoard680> findAll(final MinCivBoard680 minCivBoard680, Pageable pageable);
Page<BoardDto> findAll(final BoardDto dto, Pageable pageable);
Page<MinCivBoard680> findAll2(final MinCivBoard680 entity, Pageable pageable);
int modifyByCiCode(Long ciCode);
void saveBoard(BoardDto dto);
}

@ -1,14 +1,22 @@
package com.xit.biz.ctgy.service.impl;
import com.xit.biz.ctgy.dto.BoardDto;
import com.xit.biz.ctgy.dto.struct.MinCivBoard680Mapstruct;
import com.xit.biz.ctgy.entity.MinCivBoard680;
import com.xit.biz.ctgy.repository.IBoardRepository;
import com.xit.biz.ctgy.service.IBoardService;
import com.xit.core.constant.ErrorCode;
import com.xit.core.exception.CustomBaseException;
import com.xit.core.support.jpa.JpaUtil;
import com.xit.core.util.Checks;
import com.xit.core.util.CommUtil;
import lombok.AllArgsConstructor;
import org.mapstruct.factory.Mappers;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -19,17 +27,56 @@ import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatc
public class BoardService implements IBoardService {
private final IBoardRepository repository;
private final PasswordEncoder passwordEncoder;
private final MinCivBoard680Mapstruct mapstruct = Mappers.getMapper(MinCivBoard680Mapstruct.class);
@Transactional(readOnly = true)
public Page<MinCivBoard680> findAll(final MinCivBoard680 entity, Pageable pageable) {
//Sort sort = Sort.by(Sort.Direction.ASC, "codeOrdr");
public Page<BoardDto> findAll(final BoardDto dto, Pageable pageable) {
pageable = JpaUtil.getPagingInfo(pageable);
return repository.findAll(dto, pageable);
}
@Transactional(readOnly = true)
public Page<MinCivBoard680> findAll2(final MinCivBoard680 entity, Pageable pageable) {
pageable = JpaUtil.getPagingInfo(pageable);
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAll()
.withMatcher("ciTitle", contains())
.withMatcher("ciName", contains());
Example<MinCivBoard680> example = Example.of(entity, exampleMatcher);
Page<MinCivBoard680> page = repository.findAll(example, pageable);
// List<CmmUser> userList = page.getContent();
return page;
return repository.findAll(example, pageable);
}
@Override
@Transactional
public int modifyByCiCode(Long ciCode) {
return repository.updateInHitForMinCivBoard680(ciCode);
}
@Override
@Transactional
public void saveBoard(BoardDto dto) {
MinCivBoard680 entity = null;
// update 인 경우
if(Checks.isNotEmpty(dto.getCiCode())) {
entity = repository.findById(dto.getCiCode()).orElseThrow(() -> new CustomBaseException(ErrorCode.DATA_NOT_FOUND));
if(!entity.getCiPass().equals(passwordEncoder.encode(dto.getCiPass()))){
throw new CustomBaseException(ErrorCode.MISMATCH_PASSWORD);
}
entity.setCiTitle(dto.getCiTitle());
entity.setCiContents(dto.getCiContents());
}else {
dto.setCiCode(repository.getCiCode());
dto.setCiContentno(dto.getCiCode());
if (Checks.isEmpty(dto.getCiRef()) || dto.getCiRef() == 0L) {
dto.setCiRef(dto.getCiCode());
dto.setCiStep(0L);
dto.setCiRevel(0L);
}
dto.setCiPass(passwordEncoder.encode(dto.getCiPass()));
dto.setCiIp(CommUtil.getDeviceInfo().getIp());
entity = mapstruct.toEntity(dto);
}
repository.save(entity);
}
}

@ -77,6 +77,8 @@ public enum ErrorCode {
FORBIDDEN(HttpStatus.FORBIDDEN, "FORBIDDEN"),
INVALID_CODE(HttpStatus.BAD_REQUEST, "유효하지 않은 HttpStatus 상태 코드 입니다"),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "INTERNAL_SERVER_ERROR"),
MISMATCH_PASSWORD(HttpStatus.BAD_REQUEST, "비밀 번호가 일치하지 않습니다.")
;

@ -8,6 +8,8 @@ import org.mozilla.universalchardet.UniversalDetector;
import org.springframework.http.ResponseCookie;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -392,6 +394,10 @@ public class CommUtil {
return Long.toHexString(lDec).toUpperCase();
}
public static DeviceInfo getDeviceInfo() {
return getDeviceInfo(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest());
}
/**
*
* @param request HttpServletRequest

Loading…
Cancel
Save