Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/point details 회원 포인트 사용/적립 내역 기능 #95

Merged
merged 5 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.t3t.frontserver.pointdetail.client;

import com.t3t.frontserver.model.response.BaseResponse;
import com.t3t.frontserver.pointdetail.model.response.PointDetailResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* 포인트 사용/적립 내역 API 호출을 위한 Feign Client
* @author hydraitonn(박수화)
*/
@FeignClient(name = "UserPointDetailApiClient", url = "${t3t.feignClient.url}")
public interface UserPointDetailApiClient {

/**
* 회원의 포인트 타입에 따른 포인트 사용/적립 내역 조회 API 호출
* @param pointDetailType 조회할 포인트 타입(사용/적립)
* @author hydrationn(박수화)
*/
@GetMapping("/t3t/bookstore/members/point-details")
public ResponseEntity<BaseResponse<List<PointDetailResponse>>> getPointDetailByPointDetailType(@RequestParam(name = "pointDetailType", required = false) String pointDetailType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.t3t.frontserver.pointdetail.controller;

import com.t3t.frontserver.auth.util.SecurityContextUtils;
import com.t3t.frontserver.model.response.BaseResponse;
import com.t3t.frontserver.pointdetail.client.UserPointDetailApiClient;
import com.t3t.frontserver.pointdetail.model.response.PointDetailResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Controller
@RequiredArgsConstructor
public class UserPointDetailController {
private final UserPointDetailApiClient userPointDetailApiClient;

/**
* 회원 포인트 사용/적립 내역 페이지 뷰 반환
* @return 포인트 사용/적립 내역 뷰
* @author hydrationn(박수화)
*/
@GetMapping("/member/point-details")
public String pointDetailView(Model model, @Valid @RequestParam(value = "pointDetailType", required = false) String pointDetailType) {

// 로그인 정보가 없으면 로그인 페이지로 이동
if(!SecurityContextUtils.isLoggedIn()){
return "redirect:/login";
}

ResponseEntity<BaseResponse<List<PointDetailResponse>>> response = userPointDetailApiClient.getPointDetailByPointDetailType(pointDetailType); // 모든 내역을 가져오는 API 호출

List<PointDetailResponse> pointDetails;

if (pointDetailType == null) {
// parameter가 null인 경우 모든 내역 반환
pointDetails = Objects.requireNonNull(response.getBody()).getData();
} else {
// pointDetailType(used, saved)에 해당하는 내역만 반환
pointDetails = Objects.requireNonNull(response.getBody()).getData()
.stream()
.filter(pointDetail -> pointDetail.getPointDetailType().equals(pointDetailType))
.collect(Collectors.toList());
}

model.addAttribute("pointDetails", pointDetails);

return "main/pointdetails/pointdetail";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.t3t.frontserver.pointdetail.model.dto;

import com.t3t.frontserver.member.model.dto.MemberDto;
import lombok.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* PointDetail Entity에 대한 DTO 클래스
* @author hydrationn(박수화)
*/
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PointDetailDto {
private Long pointDetailId;
private MemberDto member;
private String content;
private String pointDetailType;
private LocalDateTime pointDetailDate;
private BigDecimal pointAmount;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.t3t.frontserver.pointdetail.model.request;

import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* 포인트 사용/정립 내역 생성 정보를 담기 위한 클래스
* @author hydrationn(박수화)
*/
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Setter
public class CreatePointDetailRequest {

// 포인트 상세 내용
@NotBlank(message = "포인트 상세 내용이 누락되었습니다.")
private String content;

// 포인트 사용/적립 구분
@NotBlank(message = "포인트 사용/적립 구분이 명시되지 않았습니다.")
@Pattern(regexp = "^(사용|적립)$", message = "포인트 상세 유형은'사용' 또는'적립'만 가능합니다.")
private String pointDetailType;

// 사용/적립 내역 일자
@NotNull(message = "포인트 사용/적립 일자가 누락되었습니다.")
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime pointDetailDate;

// 포인트 양
@NotNull(message = "포인트 양이 누락되었습니다.")
private BigDecimal pointAmount;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.t3t.frontserver.pointdetail.model.response;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
* 회원 포인트 사용/적립 내역 조회 요청을 성공적으로 처리한 경우 응답 정보를 담기 위한 클래스
* @author hydrationn(박수화)
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PointDetailResponse {

private String content;

private String pointDetailType;

private LocalDateTime pointDetailDate;

private BigDecimal pointAmount;
}
50 changes: 50 additions & 0 deletions src/main/resources/templates/main/pointdetails/pointdetail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout(categoryList)"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"
layout:decorate="main/layout/layout">

<th:block layout:fragment="content">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-10">
<h2 class="text-center mb-5">회원 포인트 내역 조회</h2>
<div class="d-flex justify-content-end mb-3">
<a href="/member/point-details" class="btn btn-primary mx-1">전체</a>
<a href="/member/point-details?pointDetailType=used" class="btn btn-primary mx-1">사용</a>
<a href="/member/point-details?pointDetailType=saved" class="btn btn-primary mx-1">적립</a>
</div>
<div class="text-center mb-5">
<table id="pointDetailTable" class="table table-bordered table-striped centered-table">
<thread>
<tr>
<td>No</td>
<td>날짜 및 시간</td>
<td>포인트</td>
<td>구분</td>
<td>내용</td>
</tr>
</thread>
<tbody>
<!-- Thymeleaf를 사용하여 반복문 처리 -->
<tr th:each="pointDetail, no : ${pointDetails}">
<td th:text="${no.index + 1}"></td>
<td th:text="${#temporals.format(pointDetail.pointDetailDate, 'yyyy-MM-dd HH:mm:ss')}"></td>
<td th:text="${pointDetail.pointAmount}"></td>
<td th:switch="${pointDetail.pointDetailType}">
<span th:case="used" th:text="사용"></span>
<span th:case="saved" th:text="적립"></span>
</td>
<td th:text="${pointDetail.content}"></td>
</tr>
</tbody>

</table>
<a href="/" class="btn btn-secondary">메인 화면 바로가기</a>
<p></p>
</div>
</div>
</div>
</div>
</th:block>
</html>
Loading