본문 바로가기

개인프로젝트(수강프로그램)

백오피스 - 강좌신청 처리구현

관리자 페이지에서 수강신청 목록을 보는 로직 구현

수강내역을 확인하고 승인 구현

 

+) 트러블슈팅

 

- ApiCourseController

 

강좌신청시 유저정보를 위해 Principal을 사용하여 로그인한 유저정보를 가져왔는데 id값을 가져오는 것이 아닌 username을 받아오는 에러가 발생

 

왜 이 오류에 직면했나?

관리자모드에서 수강관리에 대한 정보를 가져올때 member에 있는 userId와 takecourse에 있는 userId가 같은 것을 조회했는데

아래의 코드처럼 Principal을 사용해서 로그인정보를 가져왔는데 Db에 username이 저장되는 문제가 발생

@PostMapping("/api/course/req.api")
public ResponseEntity<?> courseRequest(Model model,
                                       @RequestBody TakeCourseInput param,
                                       Principal principal){

    // 유저정보 가져오는 코드
    param.setUserId(principal.getName());

    ServiceResult result = courseService.request(param);

    if (!result.isResult()){

        ResponseResult responseResult = new ResponseResult(false, result.getMessage());

        return ResponseEntity.ok().body(responseResult);
    }

    // 내리는 값자체를 param이 아닌 response 값 자체를 내릴것
    ResponseResult responseResult = new ResponseResult(true);
    return ResponseEntity.ok().body(param);
}

 

문제를 해결하기 위해 구글링을 한 결과 스프링 시큐리티에서 값을 가져올때 문제가 있다고 판단했고 실제 memberServiceImpl을 보니 username으로 받아오고 있었다...

이를 id로 바꿔주니 해결!

 

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    Optional<Member> optionalMember = memberRepository.findById(username);
    if(!optionalMember.isPresent()){
        throw new UsernameNotFoundException("회원정보가 존재하지 않습니다");
    }
    Member member = optionalMember.get();

    // 이메일 인증절차에 관한 로직
    // true가 아닐때 예외처리
    if(Member.MEMBER_STATUS_REQ.equals(member.getUserStatus())){
        throw new MemberNotEmailAuthException("이메일 활성화 이후에 로그인 진행해주세요");
    }

    if(Member.MEMBER_STATUS_STOP.equals(member.getUserStatus())){
        throw new MemberStopUserlAuthException("정지된 회원입니다");
    }

    // return 객체의 파라미터가 이름, 비밀번호 , role인데 role은 직접 설정해야함
    List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));

    // 유저과 관리자일때 관리자 역할 부여
    if(member.isAdminYn()){
        grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    }
	
    // !!!!!!!!!!  여기가 문제 username으로 받아옴
    return new User(member.getUserName(), member.getPassword(),grantedAuthorities);
}

 

  • 수강관리메뉴

 

어떤 강좌에 대해서 사용자 정보가 나오도록 쿼리를 작성해야 한다

 

- AdminTakeCourseController

 

기존 강좌 리스트와 비슷한 구조이며 후에 들어갈 쿼리빼고 대부분 비슷함

@RequiredArgsConstructor
@Controller
public class AdminTakeCourseController extends BaseController{

    private final TakeCourseService takeCourseService;

    @GetMapping("/admin/takecourse/list")
    public String list(Model model, TakeCourseParam param){

        param.init();

        List<TakeCourseDto> courseList = takeCourseService.list(param);


        long totalCount = 0;
        if(courseList != null && courseList.size() > 0){
            totalCount = courseList.get(0).getTotalCount();
        }

        String queryString = param.getQueryString();
        String pagerHtml = getPapaerHtml(totalCount, param.getPageSize(), param.getPageIndex(), queryString);

        model.addAttribute("list", courseList);
        model.addAttribute("pager", pagerHtml);
        model.addAttribute("totalCount", totalCount);

        return "admin/takecourse/list";
    }

}

 

- TakeCourseService

 

public interface TakeCourseService {


    // 수강목록
    List<TakeCourseDto> list(TakeCourseParam param);


}

 

- TakeCourseParam

 

@Data
public class TakeCourseParam extends CommonParam {


}

 

- TakeCourseDto

 

TakeCourse 엔티티에 있는 내용을 가져올 거임

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TakeCourseDto {


    long id;

    long courseId;
    String userId;

    long payPrice;
    String status;

    LocalDateTime regDt;

    // 조인컬럼
    String userName;
    String phone;
    String subject;

    // 페이징 카운트트
    long totalCount;
    long seq;

}

 

 

- TakeCourseServiceImpl

 

@RequiredArgsConstructor
@Service
public class TakeCourseServiceImpl implements TakeCourseService{


    private final TakeCourseMapper takeCourseMapper;


    @Override
    public List<TakeCourseDto> list(TakeCourseParam param) {

        long totalCount = takeCourseMapper.selectListCount(param);

        List<TakeCourseDto> list = takeCourseMapper.selectList(param);

        // 각 칼럼에 totalCount를 넣어주는 식
        if(!CollectionUtils.isEmpty(list)){
            int i = 0;
            for (TakeCourseDto m : list){
                m.setTotalCount(totalCount);
                m.setSeq(totalCount - param.getPageStart() - i);
                i++;
            }
        }

        return list;
    }
}

 

- TakeCourseMapper

 

@Mapper
public interface TakeCourseMapper {

    long selectListCount(TakeCourseParam param);

    List<TakeCourseDto> selectList(TakeCourseParam param);
}

 

- TakeCourseMapper.xml

 

<?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.zerobase.fastlms.course.mapper.TakeCourseMapper">

<!--    공통인 부분 처리, 중복 쿼리를 줄이기 위해 사용-->
    <sql id="selectListWhere">
    </sql>


    <select id="selectListCount"
            parameterType="com.zerobase.fastlms.course.model.TakeCourseParam"
            resultType="long">
        select count(*)
        from take_course
        where 1 = 1
            <include refid="selectListWhere" />
    </select>


    <select id="selectList"
            resultType="com.zerobase.fastlms.course.dto.TakeCourseDto">

        select tc.*
        , c.subject
        , m.user_name
        , m.phone
        from take_course tc
            join course c on tc.course_id = c.id
            join member m on tc.user_id = m.user_id
        where 1 = 1
            <include refid="selectListWhere" />
            order by reg_dt desc
        limit #{pageStart}, #{pageEnd}
    </select>

</mapper>

 

- detail.html

 

<div class="list">

    <div class="buttons">
        <p class="total-count">전체 <span th:text="${totalCount}"></span>개</p>

    </div>

    <table>
        <thead>
        <tr>
            <th>
                <input id="selectAll" type="checkbox" />
            </th>
            <th> NO </th>
            <th>
                등록일
            </th>
            <th>
                강좌명
            </th>
            <th colspan="3">
                신청인
            </th>
            <th>
                상태
            </th>



        </tr>
        </thead>
        <tbody id="dataLIst">
        <tr th:each="x : ${list}">
            <td>
                <input type="checkbox" th:value="${x.id}" />
            </td>
            <td th:text="${x.seq}">1</td>
            <td>
                <p th:text="${x.regDt}">2021.01.01</p>
            </td>
            <td>
                <p th:href="'edit?id=' + ${x.id}" th:text="${x.subject}">강좌명</p>
            </td>
            <td>
                <p th:text="${x.userName}"></p>
            </td>
            <td>
                <p th:text="${x.userId}"></p>
            </td>
            <td>
                <p th:text="${x.phone}"></p>
            </td>
            <td>
                <p th:if="${x.status eq 'REQ'}">수강신청</p>
                <p th:if="${x.status eq 'COM'}">결제완료</p>
                <p th:if="${x.status eq 'CANCEL'}">수강취소</p>
            </td>

        </tr>
        </tbody>
    </table>


    <div class="pager" th:utext="${pager}">
    </div>



</div>

<form name="deleteForm" method="post" action="/admin/course/delete">
    <input type="hidden" name="idList"/>
</form>


</body>
</html>

 


상태를 결제완료 처리하는 로직

 

- detail

<tbody id="dataLIst">
        <tr th:each="x : ${list}">
            <td>
                <input type="checkbox" th:value="${x.id}" />
            </td>
            <td th:text="${x.seq}">1</td>
            <td>
                <p th:text="${x.regDt}">2021.01.01</p>
            </td>
            <td>
                <p th:href="'edit?id=' + ${x.id}" th:text="${x.subject}">강좌명</p>
            </td>
            <td>
                <p th:text="${x.userName}"></p>
            </td>
            <td>
                <p th:text="${x.userId}"></p>
            </td>
            <td>
                <p th:text="${x.phone}"></p>
            </td>
            <td>
                <p th:if="${x.status eq 'REQ'}">수강신청</p>
                <p th:if="${x.status eq 'COM'}">결제완료</p>
                <p th:if="${x.status eq 'CANCEL'}">수강취소</p>
            </td>
            <td>
            	// 수강신청일때만 결제완료 , 수강취소 처리가 보이도록 설정
                <p th:if="${x.status eq 'REQ'}">수강신청
                <button type="button">결제완료 처리</button>
                <button type="button">수강취소 처리</button>
                </p>
            </td>

        </tr>
        </tbody>
    </table>


    <div class="pager" th:utext="${pager}">
    </div>



</div>
// 수강상태를 id, status값으로 서버에 ajax처리 후 넘겨준다 
<form name="proForm" method="post" action="/admin/takecourse/status">
    <input type="hidden" name="id"/>
    <input type="hidden" name="status"/>
</form>

 

<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script>
    $(document).ready(function() {

        // 여기서의 button은 수강완료가 될수도 있고 수강취소가 될 수도 있다
        $('.row-buttons button').on('click', function (){

            var status = $(this).val();
            // this = row-buttons, 상위 div로 올라가서 input의 name이 id인것을 find
            var id = $(this).closest('div').find('input[name=id]').val();

            var msg = status == 'COMPLETE' ? '결제완료처리 하시겠습니까?' : '수강처리취소 하시겠습니까';

            if(!confirm(msg)){
                return false;
            }

            // proForm데이터 가져오기
            var $proForm = $('#proForm');
            $proForm.find('input[name=id]').val(id);
            $proForm.find('input[name=status]').val(status);
            $proForm.submit();

        });

    });
</script>

 

- AdminTakeCourseController

 

@PostMapping("/admin/takecourse/status")
public String status(Model model, TakeCourseParam param){

    ServiceResult result = takeCourseService.updateStatus(param.getId(), param.getStatus());

    if(!result.isResult()){
        model.addAttribute("message", result.getMessage());
        return "common/error";
    }



    return "redirect:/admin/takecourse/list";
}

 

- TakeCourseParam

 

html에서 ajax로 넘겨준 id와 status를 

TakeCourseParam으로 받아준다

 

@Data
public class TakeCourseParam extends CommonParam {
    long id;
    String status;

}

 

- TakeCourseService

 

// 수강내용 상태변경
ServiceResult updateStatus(long id, String status);

 

- TakeCourseServiceImpl

 

@Override
public ServiceResult updateStatus(long id, String status) {

    Optional<TakeCourse> optionalTakeCourse = takeCourseRepository.findById(id);

    if (!optionalTakeCourse.isPresent()){
        return new ServiceResult(false, "수강정보가 존재하지 않습니다");
    }

    TakeCourse takeCourse = optionalTakeCourse.get();
    takeCourse.setStatus(status);
    takeCourseRepository.save(takeCourse);

    return  new ServiceResult(true);

}

 

+ ) 등록일 수정

 

- TakeCourseDto

 

public String getRegDtText(){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    return regDt != null ? regDt.format(formatter) : "";
}

 

 

 

 

'개인프로젝트(수강프로그램)' 카테고리의 다른 글

강좌관리  (0) 2022.05.12
회원정보 수정  (0) 2022.05.03
강좌신청  (0) 2022.04.25
강좌 목록 구현  (0) 2022.04.25
강좌 목록 구현, 강좌 신청  (0) 2022.04.22