Skip to content

Commit

Permalink
Merge pull request #16 from hyundai-fruitfruit/HEENDY-43-user-visit-QR
Browse files Browse the repository at this point in the history
[HEENDY-43-user-visit-QR] 유저용 이벤트 참여 API 구현
  • Loading branch information
sangeun99 authored Feb 23, 2024
2 parents 2bebb7d + a8b4b56 commit 58b63e7
Show file tree
Hide file tree
Showing 16 changed files with 276 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.hyundai.app.coupon.controller;

import com.hyundai.app.common.AdventureOfHeendyResponse;
import com.hyundai.app.coupon.domain.Coupon;
import com.hyundai.app.coupon.service.CouponService;
import com.hyundai.app.security.methodparam.MemberId;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.List;

/**
* @author 엄상은
* @since 2024/02/23
* 사용자용 쿠폰 컨트롤러
*/
@Api("사용자용 쿠폰 관련 API")
@RequiredArgsConstructor
@RequestMapping("/api/v1/coupons")
@RestController
public class CouponController {
private final CouponService couponService;

@ApiOperation("사용자용 쿠폰 전체 조회 API")
@GetMapping
public AdventureOfHeendyResponse<List<Coupon>> findCouponList(@ApiIgnore @MemberId Integer memberId) {
return AdventureOfHeendyResponse.success("사용자의 쿠폰 목록을 가져왔습니다.", couponService.findMemberCouponList(memberId));
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/hyundai/app/coupon/domain/MemberCoupon.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.hyundai.app.coupon.domain;

import com.hyundai.app.common.entity.BaseEntity;

import java.time.LocalDate;

/**
* @author 엄상은
* @since 2024/02/22
* 유저가 가지고 있는 쿠폰 엔티티
*/
public class MemberCoupon extends BaseEntity {
private int id;
private int memberId;
private int couponId;
private int isUsed;
private String channelType;
private LocalDate expiredAt;

public MemberCoupon(int memberId, int couponId, String channelType) {
this.memberId = memberId;
this.couponId = couponId;
this.channelType = channelType;
}

public static MemberCoupon of(int memberId, int couponId, String channelType) {
return new MemberCoupon(memberId, couponId, channelType);
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/hyundai/app/coupon/mapper/CouponMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@
@Mapper
public interface CouponMapper {
List<Coupon> findCouponList(int storeId);

Coupon findById(int couponId);

List<Coupon> findMemberCouponList(Integer memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.hyundai.app.coupon.mapper;

import com.hyundai.app.coupon.domain.MemberCoupon;

/**
* @author 엄상은
* @since 2024/02/22
* 쿠폰을 가진 사용자 매퍼
*/
public interface MemberCouponMapper {
void saveMemberCoupon(MemberCoupon memberCoupon);
}
10 changes: 10 additions & 0 deletions src/main/java/com/hyundai/app/coupon/service/CouponService.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,14 @@ public List<Coupon> findCouponList(int storeId) {
}
return couponList;
}

public List<Coupon> findMemberCouponList(Integer memberId) {
List<Coupon> couponList = couponMapper.findMemberCouponList(memberId);
for (Coupon coupon: couponList) {
CouponType couponType = coupon.getCouponType();
String description = couponType.getDescription(coupon);
coupon.updateContent(description);
}
return couponList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import com.hyundai.app.common.AdventureOfHeendyResponse;
import com.hyundai.app.event.dto.EventDetailResDto;
import com.hyundai.app.event.dto.EventParticipateResDto;
import com.hyundai.app.event.enumType.EventType;
import com.hyundai.app.event.service.EventService;
import com.hyundai.app.security.methodparam.MemberId;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.Random;

Expand All @@ -35,6 +35,13 @@ public AdventureOfHeendyResponse<EventDetailResDto> findCurrentEventByEventType(
return AdventureOfHeendyResponse.success("이벤트 목록을 가져왔습니다.", eventService.findCurrentEventByEventType(eventType));
}

@PostMapping("{eventId}/participate")
@ApiOperation("유저용 이벤트 참여 API")
public AdventureOfHeendyResponse<EventParticipateResDto> participateEvent(@ApiIgnore @MemberId Integer memberId,
@PathVariable int eventId){
return AdventureOfHeendyResponse.success("이벤트 참여에 성공했습니다.", eventService.participateEvent(memberId, eventId));
}

/**
* @author 황수영
* @since 2024/02/14
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/hyundai/app/event/domain/MemberEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,13 @@ public class MemberEvent extends BaseEntity {
private int id;
private int eventId;
private int memberId;

public MemberEvent(int eventId, int memberId) {
this.eventId = eventId;
this.memberId = memberId;
}

public static MemberEvent of(int eventId, int memberId) {
return new MemberEvent(eventId, memberId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class EventDetailResDto {
private LocalDate finishedAt;
private int maxCount;
private int visitedCount;
private int couponId;
private List<EventActiveTimeZoneDto> eventActiveTimeZoneDto;

public void setActiveTimeList(List<EventActiveTimeZoneDto> eventActiveTimeZoneDto) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.hyundai.app.event.dto;

import com.hyundai.app.coupon.domain.Coupon;
import lombok.Getter;

/**
* @author 엄상은
* @since 2024/02/22
* 이벤트 참여 응답 DTO
*/
@Getter
public class EventParticipateResDto {
EventDetailResDto eventDetailResDto;
Coupon coupon;

public EventParticipateResDto(EventDetailResDto eventDetailResDto, Coupon coupon) {
this.eventDetailResDto = eventDetailResDto;
this.coupon = coupon;
}

public static EventParticipateResDto from(EventDetailResDto eventDetailResDto, Coupon coupon) {
return new EventParticipateResDto(eventDetailResDto, coupon);
}

public static EventParticipateResDto of(EventDetailResDto eventDetailResDto) {
return new EventParticipateResDto(eventDetailResDto, null);
}

public void updateCoupon(Coupon coupon) {
this.coupon = coupon;
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/hyundai/app/event/mapper/EventMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ public interface EventMapper {
void delete(int eventId);

List<EventDetailResDto> findEventAllByEventType(EventType eventType);

void increaseVisitedCount(int eventId);
}
14 changes: 14 additions & 0 deletions src/main/java/com/hyundai/app/event/mapper/MemberEventMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.hyundai.app.event.mapper;

import com.hyundai.app.event.domain.MemberEvent;
import org.apache.ibatis.annotations.Mapper;

/**
* @author 엄상은
* @since 2024/02/21
* 이벤트에 참여한 회원 Mapper
*/
@Mapper
public interface MemberEventMapper {
void saveMemberEvent(MemberEvent memberEvent);
}
53 changes: 53 additions & 0 deletions src/main/java/com/hyundai/app/event/service/EventService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.hyundai.app.event.service;

import com.hyundai.app.common.entity.IdWithCriteria;
import com.hyundai.app.coupon.domain.Coupon;
import com.hyundai.app.coupon.domain.MemberCoupon;
import com.hyundai.app.coupon.mapper.CouponMapper;
import com.hyundai.app.coupon.mapper.MemberCouponMapper;
import com.hyundai.app.event.domain.MemberEvent;
import com.hyundai.app.event.dto.*;
import com.hyundai.app.event.enumType.EventType;
import com.hyundai.app.event.enumType.RewardType;
import com.hyundai.app.event.mapper.EventActiveTimeMapper;
import com.hyundai.app.event.mapper.EventMapper;
import com.hyundai.app.event.mapper.MemberEventMapper;
import com.hyundai.app.exception.AdventureOfHeendyException;
import com.hyundai.app.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
Expand All @@ -24,6 +31,9 @@
public class EventService {
private final EventMapper eventMapper;
private final EventActiveTimeMapper eventActiveTimeMapper;
private final MemberEventMapper memberEventMapper;
private final MemberCouponMapper memberCouponMapper;
private final CouponMapper couponMapper;

public EventDetailResDto findCurrentEventByEventType(EventType eventType) {
EventDetailResDto eventDetailResDto = eventMapper.findCurrentEventByEventType(eventType);
Expand Down Expand Up @@ -71,6 +81,17 @@ public EventDetailResDto findEventAndValidate(int storeId, int eventId) {
return eventDetailResDto;
}

private EventDetailResDto findAvailableEvent(int eventId) {
EventDetailResDto eventDetailResDto = eventMapper.findById(eventId);
if (eventDetailResDto == null) {
throw new IllegalArgumentException("해당 이벤트가 존재하지 않습니다.");
}
if (eventDetailResDto.getVisitedCount() >= eventDetailResDto.getMaxCount()) {
throw new IllegalArgumentException("이벤트 참여가 마감되었습니다.");
}
return eventDetailResDto;
}

private List<EventActiveTimeZoneDto> findEventActiveTime(int eventId) {
List<EventActiveTimeZoneDto> eventActiveTimeZoneDto = eventActiveTimeMapper.findByEventId(eventId);
return eventActiveTimeZoneDto;
Expand Down Expand Up @@ -110,6 +131,38 @@ public Void delete(int storeId, int eventId) {
return null;
}

public EventParticipateResDto participateEvent(Integer memberId, int eventId) {
EventDetailResDto eventDetailResDto = findAvailableEvent(eventId);
EventParticipateResDto eventVisitResDto = EventParticipateResDto.of(eventDetailResDto);
if (eventDetailResDto.getRewardType() == RewardType.COUPON) {
int couponId = eventDetailResDto.getCouponId();
Coupon coupon = findCoupon(couponId);
eventVisitResDto.updateCoupon(coupon);
saveMemberCoupon(memberId, couponId, "OFFLINE");
}
visitEvent(memberId, eventId);
return eventVisitResDto;
}

private Coupon findCoupon(int couponId) {
Coupon coupon = couponMapper.findById(couponId);
if (coupon == null) {
throw new IllegalArgumentException("해당 쿠폰이 존재하지 않습니다.");
}
return coupon;
}

private void saveMemberCoupon(int memberId, int couponId, String channelType) {
MemberCoupon memberCoupon = MemberCoupon.of(memberId, couponId, channelType);
memberCouponMapper.saveMemberCoupon(memberCoupon);
}

private void visitEvent(int memberId, int eventId) {
MemberEvent memberEvent = MemberEvent.of(eventId, memberId);
memberEventMapper.saveMemberEvent(memberEvent);
eventMapper.increaseVisitedCount(eventId);
}

/**
* @author 황수영
* @since 2024/02/20
Expand Down
26 changes: 26 additions & 0 deletions src/main/resources/mapper/CouponMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,30 @@
FROM coupon
WHERE store_id = #{storeId}
</select>

<select id="findById" parameterType="int" resultType="coupon">
SELECT id
, coupon_type
, discount_rate
, discount_amount
, minimum_amount
, started_at
, finished_at
FROM coupon
WHERE id = #{couponId}
</select>

<select id="findMemberCouponList" parameterType="int" resultType="coupon">
SELECT id
, coupon_type
, discount_rate
, discount_amount
, minimum_amount
, started_at
, finished_at
FROM coupon
WHERE id IN (SELECT coupon_id
FROM member_coupon
WHERE member_id = #{memberId})
</select>
</mapper>
7 changes: 7 additions & 0 deletions src/main/resources/mapper/EventMapper.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
, finished_at
, max_count
, visited_count
, coupon_id
FROM event
WHERE id = #{eventId}
</select>
Expand Down Expand Up @@ -139,4 +140,10 @@
AND max_count >= visited_count
AND is_deleted = 0
</select>

<update id="increaseVisitedCount" parameterType="int">
UPDATE event
SET visited_count = visited_count + 1
WHERE id = #{eventId}
</update>
</mapper>
17 changes: 17 additions & 0 deletions src/main/resources/mapper/MemberCouponMapper.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?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.hyundai.app.coupon.mapper.MemberCouponMapper">
<!-- @author 엄상은 -->
<!-- @since 2024/02/22 -->
<!-- 쿠폰을 가진 멤버 mapper -->
<insert id="saveMemberCoupon" parameterType="membercoupon">
INSERT INTO member_coupon (member_id
, coupon_id
, channel_type)
VALUES (#{memberId}
, #{couponId}
, #{channelType})
</insert>
</mapper>
15 changes: 15 additions & 0 deletions src/main/resources/mapper/MemberEventMapper.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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.hyundai.app.event.mapper.MemberEventMapper">
<!-- @author 엄상은 -->
<!-- @since 2024/02/22 -->
<!-- 이벤트에 참여한 멤버 mapper -->
<insert id="saveMemberEvent" parameterType="memberevent">
INSERT INTO member_event (member_id
, event_id)
VALUES (#{memberId}
, #{eventId})
</insert>
</mapper>

0 comments on commit 58b63e7

Please sign in to comment.