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

feat: 장바구니 비우기 기능 구현 #172

Merged
merged 4 commits into from
Nov 28, 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
52 changes: 40 additions & 12 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,46 @@ jobs:
runs-on: self-hosted

steps:
# 1. 최신 이미지를 풀받습니다
- name: docker pull
run: sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/jangburich2
- uses: actions/checkout@v3

- name: Setup SSH key
uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.EC2_SSH_KEY }}

- name: Add EC2 to known_hosts
run: |
ssh-keyscan -H ip-172-31-3-107 >> ~/.ssh/known_hosts
# 2. 기존의 컨테이너를 중지시킵니다
- name: docker stop container
run: sudo docker stop $(sudo docker ps -q) 2>/dev/null || true
- name: Copy docker-compose.yml to EC2
run: |
scp docker-compose.yml ubuntu@ip-172-31-3-107:/home/ubuntu/
# 3. 최신 이미지를 컨테이너화하여 실행시킵니다
- name: docker run new container
run: sudo docker run --name jangburich2 --rm -d -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/jangburich2
- name: Login to Docker Hub on EC2
run: |
ssh ubuntu@ip-172-31-3-107 '
echo "${{ secrets.DOCKERHUB_PASSWORD }}" | sudo docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
'
# 4. 미사용 이미지를 정리합니다
- name: delete old docker image
run: sudo docker system prune -f
- name: Stop existing Redis process
run: |
if pgrep redis-server; then
sudo systemctl stop redis || echo "Redis service not managed by systemctl"
pkill redis-server || echo "No Redis process to kill"
fi
# 0. 최신 이미지를 풀받습니다
- name: docker pull
run: sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/jangburich2

# 1. docker-compose 종료
- name: docker-compose down
run: sudo docker-compose down

# 2. docker-compose 실행
- name: docker-compose up
run: sudo docker-compose up -d

# 3. 안쓰는 이미지 제거
- name: Remove unused Docker images
run: sudo docker image prune -f
8 changes: 3 additions & 5 deletions compose-prod.yml → docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
services:
api-server:
build:
context: .
dockerfile: ./Dockerfile
app:
image: rookie97/jangburich2:latest
ports:
- 8080:8080
depends_on:
Expand All @@ -15,4 +13,4 @@ services:
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 5s
retries: 10
retries: 10
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ public Message addCart(String userProviderId, AddCartRequest addCartRequest) {
Menu menu = menuRepository.findById(addCartRequest.menuId())
.orElseThrow(() -> new IllegalArgumentException("등록된 메뉴를 찾을 수 없습니다. "));

List<Cart> allByUserAndStatus = cartRepository.findAllByUserAndStatus(user, Status.ACTIVE);
Cart.validateHasAnotherStoreItem(user, addCartRequest, allByUserAndStatus);

Optional<Cart> optionalCart = cartRepository.findByUserIdAndMenuIdAndStatus(user.getUserId(), menu.getId(),
Status.ACTIVE);

Expand Down Expand Up @@ -126,16 +129,6 @@ public OrderResponse order(String userProviderId, OrderRequest orderRequest) {
Team team = teamRepository.findById(orderRequest.teamId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 그룹 id 입니다."));

List<Cart> existingCarts = cartRepository.findAllByUserAndStoreAndStatus(user, store, Status.ACTIVE);

List<Cart> mergedCarts = mergeCarts(existingCarts, orderRequest.items(), user, store);

Orders orders = saveOrder(user, store, team, orderRequest);

associateCartsWithOrder(mergedCarts, orders);

cartRepository.saveAll(mergedCarts);

List<Long> menuIds = orderRequest.items()
.stream()
.map(item -> item.menuId())
Expand Down Expand Up @@ -169,73 +162,70 @@ public OrderResponse order(String userProviderId, OrderRequest orderRequest) {
.store(store)
.build();

System.out.println("totalAmount = " + totalAmount);

pointTransactionRepository.save(pointTransaction);

StoreTeam storeTeam = storeTeamRepository.findByStoreIdAndTeamId(store.getId(), team.getId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 가게 id와 팀 id 입니다."));

storeTeam.useRemainPoint(totalAmount);

return ordersRepository.findTicket(orders.getId());
}
Orders orders = saveOrder(user, store, team, orderRequest);

private List<Cart> mergeCarts(List<Cart> existingCarts, List<OrderRequest.OrderItemRequest> items, User user,
Store store) {
if (existingCarts.isEmpty()) {
for (OrderRequest.OrderItemRequest item : items) {
Cart newCartAfterOrder = createNewCartAfterOrder(item, user, store);
existingCarts.add(newCartAfterOrder);
}
return existingCarts;
}
List<Cart> allByUserAndStatus = cartRepository.findAllByUserAndStatus(user, Status.ACTIVE);
System.out.println("allByUserAndStatus = " + allByUserAndStatus);

for (OrderRequest.OrderItemRequest item : items) {
Optional<Cart> existingCart = findCartByMenuId(existingCarts, item.menuId());
if (existingCart.isPresent()) {
existingCart.get().updateQuantity(item.quantity());
existingCart.get().updateStatus(Status.INACTIVE);
continue;
}
Cart newCart = createNewCart(item, user, store);
existingCarts.add(newCart);
}
return existingCarts;
}
syncCart(orderRequest, allByUserAndStatus, orders, user);
OrderResponse ticket = ordersRepository.findTicket(orders.getId());

private Optional<Cart> findCartByMenuId(List<Cart> carts, Long menuId) {
return carts.stream()
.filter(cart -> cart.getMenu().getId().equals(menuId))
.findFirst();
}
List<Cart> cartsForStatusManage = cartRepository.findAllByUserAndStatus(user, Status.ACTIVE);

private Cart createNewCart(OrderRequest.OrderItemRequest item, User user, Store store) {
Menu menu = menuRepository.findById(item.menuId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 메뉴 ID입니다."));
return Cart.builder()
.quantity(item.quantity())
.menu(menu)
.user(user)
.store(store)
.orders(null)
.build();
}
cartsForStatusManage.stream()
.forEach(cart -> cart.updateStatus(Status.INACTIVE));

private Cart createNewCartAfterOrder(OrderRequest.OrderItemRequest item, User user, Store store) {
Menu menu = menuRepository.findById(item.menuId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 메뉴 ID입니다."));
Cart cart = Cart.builder()
.quantity(item.quantity())
.menu(menu)
.user(user)
.store(store)
.orders(null)
.build();
return ticket;
}

cart.updateStatus(Status.INACTIVE);
private void syncCart(OrderRequest orderRequest, List<Cart> carts, Orders orders, User user) {
if (carts.isEmpty()) {
for (OrderRequest.OrderItemRequest orderItemRequest : orderRequest.items()) {
Menu menu = menuRepository.findById(orderItemRequest.menuId())
.orElseThrow(() -> new IllegalArgumentException("해당 메뉴를 찾을 수 없습니다."));

Cart newCart = Cart.builder()
.quantity(orderItemRequest.quantity())
.orders(orders)
.menu(menu)
.user(user)
.store(orders.getStore())
.build();

cartRepository.save(newCart);
cartRepository.flush();
}
} else {
for (Cart cart : carts) {
for (OrderRequest.OrderItemRequest orderItemRequest : orderRequest.items()) {
if (orderItemRequest.menuId().equals(cart.getMenu().getId())) {
cart.updateQuantity(orderItemRequest.quantity());
cart.updateOrders(orders);
} else {
Menu menu = menuRepository.findById(orderItemRequest.menuId())
.orElseThrow(() -> new IllegalArgumentException("해당 메뉴를 찾을 수 없습니다."));

Cart newCart = Cart.builder()
.quantity(orderItemRequest.quantity())
.orders(orders)
.menu(menu)
.user(user)
.store(cart.getStore())
.build();

cartRepository.save(newCart);
}
}

return cart;
}
}
}

private Orders saveOrder(User user, Store store, Team team, OrderRequest orderRequest) {
Expand All @@ -248,10 +238,6 @@ private Orders saveOrder(User user, Store store, Team team, OrderRequest orderRe
return ordersRepository.save(orders);
}

private void associateCartsWithOrder(List<Cart> carts, Orders orders) {
carts.forEach(cart -> cart.updateOrders(orders));
}

@Transactional
public Message useMealTicket(String userProviderId, Long orderId) {
User user = userRepository.findByProviderId(userProviderId)
Expand Down Expand Up @@ -279,4 +265,18 @@ public Message useMealTicket(String userProviderId, Long orderId) {
.message("식권을 사용했습니다.")
.build();
}

@Transactional
public Message removeCart(String userProviderId) {
User user = userRepository.findByProviderId(userProviderId)
.orElseThrow(() -> new NullPointerException());

List<Cart> allByUserAndStatus = cartRepository.findAllByUserAndStatus(user, Status.ACTIVE);

cartRepository.deleteAll(allByUserAndStatus);

return Message.builder()
.message("장바구니를 비웠습니다.")
.build();
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/jangburich/domain/order/domain/Cart.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.jangburich.domain.common.BaseEntity;
import com.jangburich.domain.menu.domain.Menu;
import com.jangburich.domain.order.dto.request.AddCartRequest;
import com.jangburich.domain.store.domain.Store;
import com.jangburich.domain.user.domain.User;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -57,6 +58,15 @@ public Cart(Integer quantity, Orders orders, Menu menu, User user, Store store)
this.store = store;
}

public static void validateHasAnotherStoreItem(User user, AddCartRequest addCartRequest,
List<Cart> allByUserAndStatus) {
for (Cart cart : allByUserAndStatus) {
if (!cart.getStore().getId().equals(addCartRequest.storeId())) {
throw new IllegalArgumentException("서로 다른 가게의 물건을 장바구니에 함께 담을 수 없습니다.");
}
}
}

public void updateQuantity(int quantity) {
this.quantity = quantity;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,7 @@ public interface CartRepository extends JpaRepository<Cart, Long> {
List<Cart> findAllByUserAndStoreAndStatus(User user, Store store, Status status);

List<Cart> findAllByOrders(Orders orders);

Optional<List<Cart>> findByUser(User user);

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.jangburich.domain.order.domain.QCart.cart;
import static com.jangburich.domain.order.domain.QOrders.orders;

import com.jangburich.domain.common.Status;
import com.jangburich.domain.order.dto.response.OrderItemResponse;
import com.jangburich.domain.order.dto.response.OrderResponse;
import com.jangburich.domain.order.dto.response.QOrderItemResponse;
Expand All @@ -30,7 +31,8 @@ public OrderResponse findTicket(Long ordersId) {
.from(cart)
.leftJoin(orders).on(cart.orders.id.eq(ordersId))
.leftJoin(menu).on(cart.menu.id.eq(menu.id))
.where((cart.orders.id.eq(ordersId)))
.where((cart.orders.id.eq(ordersId)),
cart.status.eq(Status.ACTIVE))
.fetch();

int totalPrice = orderItemResponses.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -36,6 +37,14 @@ public ResponseCustom<Message> addCart(
return ResponseCustom.OK(orderService.addCart(AuthenticationParser.parseUserId(authentication), addCartRequest));
}

@Operation(summary = "장바구니 비우기", description = "장바구니를 완전히 비웁니다.")
@DeleteMapping
public ResponseCustom<Message> removeCart(
Authentication authentication
) {
return ResponseCustom.OK(orderService.removeCart(AuthenticationParser.parseUserId(authentication)));
}

@Operation(summary = "장바구니 조회", description = "장바구니에 담은 상품을 조회합니다.")
@GetMapping("/carts")
public ResponseCustom<CartResponse> getCartItems(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.time.LocalDate;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -44,6 +45,9 @@ public class StoreTeam extends BaseEntity {
@Column(name = "remain_point")
private Integer remainPoint;

@Column(name = "prepaid_expiration_date")
private LocalDate prepaidExpirationDate;

public void updatePersonalAllocatedPoint(Integer point) {
this.personalAllocatedPoint = point;
}
Expand Down Expand Up @@ -71,13 +75,16 @@ public void subRemainPoint(Integer point) {
this.remainPoint -= point;
}


@Builder
public StoreTeam(Store store, Team team, Integer point, Integer personalAllocatedPoint, Integer remainPoint) {
public StoreTeam(Store store, Team team, Integer point, Integer personalAllocatedPoint, Integer remainPoint,
LocalDate prepaidExpirationDate) {
this.store = store;
this.team = team;
this.point = point;
this.personalAllocatedPoint = personalAllocatedPoint;
this.remainPoint = remainPoint;
this.prepaidExpirationDate = prepaidExpirationDate;
}

public static StoreTeam create(Team team, Store store, Integer point) {
Expand Down
Loading
Loading