store
This commit is contained in:
commit
8ef8fa9e95
@ -1,91 +0,0 @@
|
||||
package com.ktds.hi.member.service;
|
||||
|
||||
import com.ktds.hi.member.dto.PreferenceRequest;
|
||||
import com.ktds.hi.member.dto.TasteTagResponse;
|
||||
import com.ktds.hi.member.domain.TagType;
|
||||
import com.ktds.hi.member.repository.entity.PreferenceEntity;
|
||||
import com.ktds.hi.member.repository.entity.TasteTagEntity;
|
||||
import com.ktds.hi.member.repository.jpa.PreferenceRepository;
|
||||
import com.ktds.hi.member.repository.jpa.TasteTagRepository;
|
||||
import com.ktds.hi.common.exception.BusinessException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 취향 관리 서비스 구현체
|
||||
* 취향 정보 등록/수정 및 태그 관리 기능을 구현
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Transactional
|
||||
public class PreferenceServiceImpl implements PreferenceService {
|
||||
|
||||
private final PreferenceRepository preferenceRepository;
|
||||
private final TasteTagRepository tasteTagRepository;
|
||||
|
||||
@Override
|
||||
public void savePreference(Long memberId, PreferenceRequest request) {
|
||||
// 태그 유효성 검증
|
||||
List<TasteTagEntity> existingTags = tasteTagRepository.findByTagNameIn(request.getTags());
|
||||
if (existingTags.size() != request.getTags().size()) {
|
||||
throw new BusinessException("유효하지 않은 태그가 포함되어 있습니다");
|
||||
}
|
||||
|
||||
// 기존 취향 정보 조회
|
||||
PreferenceEntity preference = preferenceRepository.findByMemberId(memberId)
|
||||
.orElse(null);
|
||||
|
||||
if (preference != null) {
|
||||
// 기존 정보 업데이트
|
||||
preference.updatePreference(request.getTags(), request.getHealthInfo(), request.getSpicyLevel());
|
||||
} else {
|
||||
// 새로운 취향 정보 생성
|
||||
preference = PreferenceEntity.builder()
|
||||
.memberId(memberId)
|
||||
.tags(request.getTags())
|
||||
.healthInfo(request.getHealthInfo())
|
||||
.spicyLevel(request.getSpicyLevel())
|
||||
.build();
|
||||
}
|
||||
|
||||
preferenceRepository.save(preference);
|
||||
|
||||
log.info("취향 정보 저장 완료: memberId={}, tags={}", memberId, request.getTags());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<TasteTagResponse> getAvailableTags() {
|
||||
List<TasteTagEntity> tags = tasteTagRepository.findByIsActiveTrue();
|
||||
|
||||
return tags.stream()
|
||||
.map(tag -> TasteTagResponse.builder()
|
||||
.id(tag.getId())
|
||||
.tagName(tag.getTagName())
|
||||
.tagType(tag.getTagType())
|
||||
.description(tag.getDescription())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<TasteTagResponse> getTagsByType(TagType tagType) {
|
||||
List<TasteTagEntity> tags = tasteTagRepository.findByTagTypeAndIsActiveTrue(tagType);
|
||||
|
||||
return tags.stream()
|
||||
.map(tag -> TasteTagResponse.builder()
|
||||
.id(tag.getId())
|
||||
.tagName(tag.getTagName())
|
||||
.tagType(tag.getTagType())
|
||||
.description(tag.getDescription())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.ktds.hi.store.biz.service;
|
||||
|
||||
import com.ktds.hi.store.biz.usecase.in.OrderUseCase;
|
||||
import com.ktds.hi.store.biz.usecase.out.OrderRepositoryPort;
|
||||
import com.ktds.hi.store.domain.Order;
|
||||
import com.ktds.hi.store.infra.dto.OrderListResponse;
|
||||
import com.ktds.hi.store.infra.dto.OrderResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(readOnly = true)
|
||||
public class OrderService implements OrderUseCase {
|
||||
|
||||
private final OrderRepositoryPort orderRepositoryPort;
|
||||
|
||||
@Override
|
||||
public OrderListResponse getOrdersByStore(Long storeId) {
|
||||
log.info("가게 {} 의 주문 목록 조회", storeId);
|
||||
|
||||
List<Order> orders = orderRepositoryPort.findOrdersByStoreId(storeId);
|
||||
List<OrderResponse> orderResponses = orders.stream()
|
||||
.map(this::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return OrderListResponse.builder()
|
||||
.storeId(storeId)
|
||||
.totalCount(orderResponses.size())
|
||||
.orders(orderResponses)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderListResponse getOrdersByStoreAndPeriod(Long storeId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
log.info("가게 {} 의 기간별 주문 목록 조회: {} ~ {}", storeId, startDate, endDate);
|
||||
|
||||
List<Order> orders = orderRepositoryPort.findOrdersByStoreIdAndPeriod(storeId, startDate, endDate);
|
||||
List<OrderResponse> orderResponses = orders.stream()
|
||||
.map(this::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return OrderListResponse.builder()
|
||||
.storeId(storeId)
|
||||
.totalCount(orderResponses.size())
|
||||
.orders(orderResponses)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderResponse getOrder(Long orderId) {
|
||||
log.info("주문 {} 조회", orderId);
|
||||
|
||||
Order order = orderRepositoryPort.findOrderById(orderId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("주문을 찾을 수 없습니다: " + orderId));
|
||||
|
||||
return toResponse(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderResponse> getAllOrders() {
|
||||
log.info("전체 주문 목록 조회");
|
||||
|
||||
return orderRepositoryPort.findAllOrders().stream()
|
||||
.map(this::toResponse)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private OrderResponse toResponse(Order order) {
|
||||
return OrderResponse.builder()
|
||||
.id(order.getId())
|
||||
.storeId(order.getStoreId())
|
||||
.menuId(order.getMenuId())
|
||||
.customerAge(order.getCustomerAge())
|
||||
.customerGender(order.getCustomerGender())
|
||||
.orderAmount(order.getOrderAmount())
|
||||
.orderDate(order.getOrderDate())
|
||||
.createdAt(order.getCreatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ktds.hi.store.biz.usecase.in;
|
||||
|
||||
import com.ktds.hi.store.infra.dto.OrderListResponse;
|
||||
import com.ktds.hi.store.infra.dto.OrderResponse;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public interface OrderUseCase {
|
||||
|
||||
OrderListResponse getOrdersByStore(Long storeId);
|
||||
|
||||
OrderListResponse getOrdersByStoreAndPeriod(Long storeId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
|
||||
OrderResponse getOrder(Long orderId);
|
||||
|
||||
List<OrderResponse> getAllOrders();
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.ktds.hi.store.biz.usecase.out;
|
||||
|
||||
import com.ktds.hi.store.domain.Order;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface OrderRepositoryPort {
|
||||
|
||||
List<Order> findOrdersByStoreId(Long storeId);
|
||||
|
||||
List<Order> findOrdersByStoreIdAndPeriod(Long storeId, LocalDateTime startDate, LocalDateTime endDate);
|
||||
|
||||
Optional<Order> findOrderById(Long orderId);
|
||||
|
||||
List<Order> findAllOrders();
|
||||
|
||||
Order saveOrder(Order order);
|
||||
}
|
||||
22
store/src/main/java/com/ktds/hi/store/domain/Order.java
Normal file
22
store/src/main/java/com/ktds/hi/store/domain/Order.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.ktds.hi.store.domain;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Order {
|
||||
private Long id;
|
||||
private Long storeId;
|
||||
private Long menuId;
|
||||
private Integer customerAge;
|
||||
private String customerGender;
|
||||
private BigDecimal orderAmount;
|
||||
private LocalDateTime orderDate;
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.ktds.hi.store.infra.controller;
|
||||
|
||||
import com.ktds.hi.common.dto.SuccessResponse;
|
||||
import com.ktds.hi.store.biz.usecase.in.OrderUseCase;
|
||||
import com.ktds.hi.store.infra.dto.OrderListResponse;
|
||||
import com.ktds.hi.store.infra.dto.OrderResponse;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/stores/orders")
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "주문 데이터", description = "주문 데이터 조회 API")
|
||||
public class OrderController {
|
||||
|
||||
private final OrderUseCase orderUseCase;
|
||||
|
||||
@GetMapping("/store/{storeId}")
|
||||
@Operation(summary = "가게별 주문 조회", description = "특정 가게의 모든 주문을 조회합니다")
|
||||
public ResponseEntity<SuccessResponse<OrderListResponse>> getOrdersByStore(
|
||||
@PathVariable Long storeId) {
|
||||
|
||||
OrderListResponse response = orderUseCase.getOrdersByStore(storeId);
|
||||
return ResponseEntity.ok(SuccessResponse.of(response));
|
||||
}
|
||||
|
||||
@GetMapping("/store/{storeId}/period")
|
||||
@Operation(summary = "가게별 기간 주문 조회", description = "특정 가게의 기간별 주문을 조회합니다")
|
||||
public ResponseEntity<SuccessResponse<OrderListResponse>> getOrdersByStoreAndPeriod(
|
||||
@PathVariable Long storeId,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate) {
|
||||
|
||||
OrderListResponse response = orderUseCase.getOrdersByStoreAndPeriod(storeId, startDate, endDate);
|
||||
return ResponseEntity.ok(SuccessResponse.of(response));
|
||||
}
|
||||
|
||||
@GetMapping("/{orderId}")
|
||||
@Operation(summary = "단일 주문 조회", description = "특정 주문 하나를 조회합니다 (테스트용)")
|
||||
public ResponseEntity<SuccessResponse<OrderResponse>> getOrder(@PathVariable Long orderId) {
|
||||
|
||||
OrderResponse response = orderUseCase.getOrder(orderId);
|
||||
return ResponseEntity.ok(SuccessResponse.of(response));
|
||||
}
|
||||
|
||||
@GetMapping("/all")
|
||||
@Operation(summary = "전체 주문 조회", description = "모든 주문을 조회합니다 (Analytics 서비스용)")
|
||||
public ResponseEntity<SuccessResponse<List<OrderResponse>>> getAllOrders() {
|
||||
|
||||
List<OrderResponse> response = orderUseCase.getAllOrders();
|
||||
return ResponseEntity.ok(SuccessResponse.of(response));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.ktds.hi.store.infra.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OrderListResponse {
|
||||
private Long storeId;
|
||||
private Integer totalCount;
|
||||
private List<OrderResponse> orders;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package com.ktds.hi.store.infra.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OrderResponse {
|
||||
private Long id;
|
||||
private Long storeId;
|
||||
private Long menuId;
|
||||
private Integer customerAge;
|
||||
private String customerGender;
|
||||
private BigDecimal orderAmount;
|
||||
private LocalDateTime orderDate;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
// Entity를 Response로 변환
|
||||
public static OrderResponse from(com.ktds.hi.store.infra.gateway.entity.OrderEntity entity) {
|
||||
return OrderResponse.builder()
|
||||
.id(entity.getId())
|
||||
.storeId(entity.getStoreId())
|
||||
.menuId(entity.getMenuId())
|
||||
.customerAge(entity.getCustomerAge())
|
||||
.customerGender(entity.getCustomerGender())
|
||||
.orderAmount(entity.getOrderAmount())
|
||||
.orderDate(entity.getOrderDate())
|
||||
.createdAt(entity.getCreatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.ktds.hi.store.infra.gateway;
|
||||
|
||||
import com.ktds.hi.store.biz.usecase.out.OrderRepositoryPort;
|
||||
import com.ktds.hi.store.domain.Order;
|
||||
import com.ktds.hi.store.infra.gateway.entity.OrderEntity;
|
||||
import com.ktds.hi.store.infra.gateway.repository.OrderJpaRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OrderRepositoryAdapter implements OrderRepositoryPort {
|
||||
|
||||
private final OrderJpaRepository orderJpaRepository;
|
||||
|
||||
@Override
|
||||
public List<Order> findOrdersByStoreId(Long storeId) {
|
||||
return orderJpaRepository.findByStoreId(storeId)
|
||||
.stream()
|
||||
.map(this::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Order> findOrdersByStoreIdAndPeriod(Long storeId, LocalDateTime startDate, LocalDateTime endDate) {
|
||||
return orderJpaRepository.findByStoreIdAndOrderDateBetween(storeId, startDate, endDate)
|
||||
.stream()
|
||||
.map(this::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Order> findOrderById(Long orderId) {
|
||||
return orderJpaRepository.findById(orderId)
|
||||
.map(this::toDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Order> findAllOrders() {
|
||||
return orderJpaRepository.findAll()
|
||||
.stream()
|
||||
.map(this::toDomain)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Order saveOrder(Order order) {
|
||||
OrderEntity entity = toEntity(order);
|
||||
OrderEntity saved = orderJpaRepository.save(entity);
|
||||
return toDomain(saved);
|
||||
}
|
||||
|
||||
private Order toDomain(OrderEntity entity) {
|
||||
return Order.builder()
|
||||
.id(entity.getId())
|
||||
.storeId(entity.getStoreId())
|
||||
.menuId(entity.getMenuId())
|
||||
.customerAge(entity.getCustomerAge())
|
||||
.customerGender(entity.getCustomerGender())
|
||||
.orderAmount(entity.getOrderAmount())
|
||||
.orderDate(entity.getOrderDate())
|
||||
.createdAt(entity.getCreatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
private OrderEntity toEntity(Order domain) {
|
||||
return OrderEntity.builder()
|
||||
.id(domain.getId())
|
||||
.storeId(domain.getStoreId())
|
||||
.menuId(domain.getMenuId())
|
||||
.customerAge(domain.getCustomerAge())
|
||||
.customerGender(domain.getCustomerGender())
|
||||
.orderAmount(domain.getOrderAmount())
|
||||
.orderDate(domain.getOrderDate())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package com.ktds.hi.store.infra.gateway.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "orders")
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class OrderEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "store_id", nullable = false)
|
||||
private Long storeId;
|
||||
|
||||
@Column(name = "menu_id", nullable = false)
|
||||
private Long menuId;
|
||||
|
||||
@Column(name = "customer_age", nullable = false)
|
||||
private Integer customerAge;
|
||||
|
||||
@Column(name = "customer_gender", nullable = false)
|
||||
private String customerGender;
|
||||
|
||||
@Column(name = "order_amount", nullable = false, precision = 10, scale = 2)
|
||||
private BigDecimal orderAmount;
|
||||
|
||||
@Column(name = "order_date", nullable = false)
|
||||
private LocalDateTime orderDate;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_at", nullable = false, updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.ktds.hi.store.infra.gateway.repository;
|
||||
|
||||
import com.ktds.hi.store.infra.gateway.entity.OrderEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface OrderJpaRepository extends JpaRepository<OrderEntity, Long> {
|
||||
|
||||
List<OrderEntity> findByStoreId(Long storeId);
|
||||
|
||||
List<OrderEntity> findByStoreIdAndOrderDateBetween(
|
||||
Long storeId,
|
||||
LocalDateTime startDate,
|
||||
LocalDateTime endDate
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user