diff --git a/src/main/java/com/swp/PodBookingSystem/controller/OrderDetailAmenityController.java b/src/main/java/com/swp/PodBookingSystem/controller/OrderDetailAmenityController.java index f93cd559..c695b08a 100644 --- a/src/main/java/com/swp/PodBookingSystem/controller/OrderDetailAmenityController.java +++ b/src/main/java/com/swp/PodBookingSystem/controller/OrderDetailAmenityController.java @@ -1,25 +1,51 @@ package com.swp.PodBookingSystem.controller; -import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityCreationRequest; +import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityRequest; +import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityUpdateReq; import com.swp.PodBookingSystem.dto.respone.ApiResponse; +import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityCreationRequest; +import com.swp.PodBookingSystem.dto.respone.OrderDetail.OrderDetailAmenityListResponse; import com.swp.PodBookingSystem.dto.respone.OrderDetailAmenity.OrderDetailAmenityResponse; -import com.swp.PodBookingSystem.entity.OrderDetailAmenity; +import com.swp.PodBookingSystem.dto.respone.PaginationResponse; +import com.swp.PodBookingSystem.entity.Account; import com.swp.PodBookingSystem.service.AccountService; import com.swp.PodBookingSystem.service.OrderDetailAmenityService; +import com.swp.PodBookingSystem.service.OrderDetailService; +import com.swp.PodBookingSystem.service.OrderService; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.*; +import java.time.LocalDateTime; +import java.util.List; + @RestController @RequestMapping("/order-detail-amenity") @RequiredArgsConstructor @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class OrderDetailAmenityController { OrderDetailAmenityService orderDetailAmenityService; + OrderDetailService orderDetailService; + private final AccountService accountService; + private final OrderService orderService; + + @GetMapping("/page") + public ApiResponse>> getOrderDetailAndAmenity( + @RequestHeader("Authorization") String token, + @RequestParam String startDate, + @RequestParam String endDate, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + String accountId = accountService.extractAccountIdFromToken(token); + Account user = accountService.getAccountById(accountId); + LocalDateTime startDateTime = orderService.parseDateTime(startDate); + LocalDateTime endDateTime = orderService.parseDateTime(endDate); + return ApiResponse.>>builder() + .data(orderDetailService.getPagedOrderDetails(user, startDateTime, endDateTime, page, size)) + .message("get paging order detail successfully") + .build(); + } @PostMapping public ApiResponse createOrderDetailAmenity(@RequestBody OrderDetailAmenityCreationRequest request) { @@ -28,4 +54,32 @@ public ApiResponse createOrderDetailAmenity(@Request .message("Tạo đơn hàng tiện ích thành công") .build(); } + + @PostMapping("/create") + public ApiResponse createOrderDetailAmenity (@RequestBody OrderDetailAmenityRequest orderDetailAmenityRequest) { + try{ + orderDetailAmenityService.createOrderDetailAmenity(orderDetailAmenityRequest); + return ApiResponse.builder() + .message("Create order detail amenity successfully") + .build(); + } catch (Exception e) { + return ApiResponse.builder() + .message("Failed to create order detail amenity: " + e.getMessage()) + .build(); + } + } + + @PutMapping + public ApiResponse updateOrderDetailAmenity(@RequestBody OrderDetailAmenityUpdateReq request) { + try { + orderDetailAmenityService.updateOrderDetailAmenityStatus(request); + return ApiResponse.builder() + .message("Update order detail amenity successfully") + .build(); + } catch (Exception e) { + return ApiResponse.builder() + .message("Failed to update order detail amenity: " + e.getMessage()) + .build(); + } + } } diff --git a/src/main/java/com/swp/PodBookingSystem/dto/request/OrderDetailAmenity/OrderDetailAmenityUpdateReq.java b/src/main/java/com/swp/PodBookingSystem/dto/request/OrderDetailAmenity/OrderDetailAmenityUpdateReq.java new file mode 100644 index 00000000..6548e7fc --- /dev/null +++ b/src/main/java/com/swp/PodBookingSystem/dto/request/OrderDetailAmenity/OrderDetailAmenityUpdateReq.java @@ -0,0 +1,14 @@ +package com.swp.PodBookingSystem.dto.request.OrderDetailAmenity; +import com.swp.PodBookingSystem.enums.OrderDetailAmenityStatus; +import lombok.*; +import lombok.experimental.FieldDefaults; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class OrderDetailAmenityUpdateReq { + String id; + OrderDetailAmenityStatus status; +} diff --git a/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetail/OrderDetailAmenityListResponse.java b/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetail/OrderDetailAmenityListResponse.java index 62345cb7..1729507b 100644 --- a/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetail/OrderDetailAmenityListResponse.java +++ b/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetail/OrderDetailAmenityListResponse.java @@ -1,8 +1,6 @@ package com.swp.PodBookingSystem.dto.respone.OrderDetail; -import com.swp.PodBookingSystem.entity.OrderDetail; -import com.swp.PodBookingSystem.entity.OrderDetailAmenity; -import com.swp.PodBookingSystem.entity.Room; +import com.swp.PodBookingSystem.dto.respone.OrderDetailAmenity.OrderDetailAmenityResponseDTO; import com.swp.PodBookingSystem.enums.OrderStatus; import lombok.*; @@ -21,7 +19,7 @@ public class OrderDetailAmenityListResponse { int roomId; String roomName; String orderId; - private List amenities; + private List orderDetailAmenities; int servicePackageId; String orderHandledId; double priceRoom; diff --git a/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetailAmenity/OrderDetailAmenityResponseDTO.java b/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetailAmenity/OrderDetailAmenityResponseDTO.java new file mode 100644 index 00000000..9628f459 --- /dev/null +++ b/src/main/java/com/swp/PodBookingSystem/dto/respone/OrderDetailAmenity/OrderDetailAmenityResponseDTO.java @@ -0,0 +1,29 @@ +package com.swp.PodBookingSystem.dto.respone.OrderDetailAmenity; + +import com.swp.PodBookingSystem.entity.Amenity; +import com.swp.PodBookingSystem.enums.AmenityType; +import com.swp.PodBookingSystem.enums.OrderDetailAmenityStatus; +import lombok.*; +import lombok.experimental.FieldDefaults; + +import java.time.LocalDateTime; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@FieldDefaults(level = AccessLevel.PRIVATE) +public class OrderDetailAmenityResponseDTO { + String id; + int quantity; + double price; + String orderDetailId; + int amenityId; + String amenityName; + AmenityType amenityType; + OrderDetailAmenityStatus status; + String statusDescription; + LocalDateTime createdAt; + LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/src/main/java/com/swp/PodBookingSystem/entity/OrderDetailAmenity.java b/src/main/java/com/swp/PodBookingSystem/entity/OrderDetailAmenity.java index 7f569861..956651aa 100644 --- a/src/main/java/com/swp/PodBookingSystem/entity/OrderDetailAmenity.java +++ b/src/main/java/com/swp/PodBookingSystem/entity/OrderDetailAmenity.java @@ -1,10 +1,13 @@ package com.swp.PodBookingSystem.entity; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.swp.PodBookingSystem.enums.OrderDetailAmenityStatus; import jakarta.persistence.*; import lombok.*; import lombok.experimental.FieldDefaults; +import java.time.LocalDateTime; + @Getter @Setter @Builder @@ -31,4 +34,25 @@ public class OrderDetailAmenity { @JsonIgnore @JoinColumn(name = "amenityId", nullable = false) Amenity amenity; + + @Enumerated(EnumType.STRING) + @Column(name = "status") + private OrderDetailAmenityStatus status; + + @Column(name = "createdAt") + LocalDateTime createdAt; + + @Column(name = "updatedAt") + LocalDateTime updatedAt; + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + this.updatedAt = LocalDateTime.now(); + } + + @PreUpdate + protected void onUpdate() { + this.updatedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/swp/PodBookingSystem/enums/OrderDetailAmenityStatus.java b/src/main/java/com/swp/PodBookingSystem/enums/OrderDetailAmenityStatus.java new file mode 100644 index 00000000..2a95098a --- /dev/null +++ b/src/main/java/com/swp/PodBookingSystem/enums/OrderDetailAmenityStatus.java @@ -0,0 +1,15 @@ +package com.swp.PodBookingSystem.enums; +import lombok.Getter; + +@Getter +public enum OrderDetailAmenityStatus { + Booked("Đã đặt"), + Delivered("Đã giao"), + Canceled("Đã xóa"); + + private final String description; + + OrderDetailAmenityStatus(String description) { + this.description = description; + } +} diff --git a/src/main/java/com/swp/PodBookingSystem/repository/OrderDetailRepository.java b/src/main/java/com/swp/PodBookingSystem/repository/OrderDetailRepository.java index 92ea1b52..3e1681c9 100644 --- a/src/main/java/com/swp/PodBookingSystem/repository/OrderDetailRepository.java +++ b/src/main/java/com/swp/PodBookingSystem/repository/OrderDetailRepository.java @@ -23,6 +23,20 @@ public interface OrderDetailRepository extends JpaRepository findByEndTime(LocalDateTime endTime); + @Query(value = "SELECT od FROM OrderDetail od WHERE od.createdAt BETWEEN :startTime AND :endTime ORDER BY od.createdAt DESC") + Page findAllWithTimeRange(@Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + Pageable pageable); + + @Query(value = "SELECT od FROM OrderDetail od WHERE od.createdAt BETWEEN :startTime AND :endTime AND od.building.id = :buildingNumber ORDER BY od.createdAt DESC") + Page findOrdersByBuildingNumberAndTimeRange( + @Param("buildingNumber") int buildingNumber, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + Pageable pageable); + + Page findAll(Pageable pageable); + @Query("SELECT o FROM OrderDetail o WHERE FUNCTION('DATE', o.startTime) BETWEEN FUNCTION('DATE', :startOfDay) AND FUNCTION('DATE', :endOfDay)") List findAllOrderDetailsByDay(@Param("startOfDay") LocalDateTime startOfDay, @Param("endOfDay") LocalDateTime endOfDay); diff --git a/src/main/java/com/swp/PodBookingSystem/service/OrderDetailAmenityService.java b/src/main/java/com/swp/PodBookingSystem/service/OrderDetailAmenityService.java index db5adeac..48e3c0e5 100644 --- a/src/main/java/com/swp/PodBookingSystem/service/OrderDetailAmenityService.java +++ b/src/main/java/com/swp/PodBookingSystem/service/OrderDetailAmenityService.java @@ -1,12 +1,15 @@ package com.swp.PodBookingSystem.service; +import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityRequest; import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityCreationRequest; +import com.swp.PodBookingSystem.dto.request.OrderDetailAmenity.OrderDetailAmenityUpdateReq; import com.swp.PodBookingSystem.dto.respone.Amenity.AmenityManagementResponse; import com.swp.PodBookingSystem.dto.respone.OrderDetailAmenity.OrderDetailAmenityResponse; import com.swp.PodBookingSystem.entity.Amenity; import com.swp.PodBookingSystem.entity.OrderDetail; import com.swp.PodBookingSystem.entity.OrderDetailAmenity; import com.swp.PodBookingSystem.enums.AmenityType; +import com.swp.PodBookingSystem.enums.OrderDetailAmenityStatus; import com.swp.PodBookingSystem.mapper.AmenityMapper; import com.swp.PodBookingSystem.mapper.OrderDetailAmenityMapper; import com.swp.PodBookingSystem.repository.AmenityRepository; @@ -15,11 +18,13 @@ import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.experimental.FieldDefaults; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; @Service @@ -42,6 +47,40 @@ public List getOrderDetailAmenitiesByOrderDetailId(St .build()).collect(Collectors.toList()); } + public List getOrderDetailAmenitiesAllInfoByOrderDetailId(String orderDetailId) { + return orderDetailAmenityRepository.findByOrderDetailId(orderDetailId); + } + + //CREATE: + public void createOrderDetailAmenity(OrderDetailAmenityRequest request) { + Optional orderDetail = orderDetailRepository.findById(request.getOrderDetailId()); + Optional amenity = amenityRepository.findById(request.getAmenityId()); + if(orderDetail.isEmpty() || amenity.isEmpty()) { + throw new RuntimeException("Order detail or amenity not found"); + } + OrderDetailAmenity orderDetailAmenity = new OrderDetailAmenity(); + orderDetailAmenity.setStatus(OrderDetailAmenityStatus.Booked); + orderDetailAmenity.setCreatedAt(LocalDateTime.now()); + orderDetailAmenity.setUpdatedAt(LocalDateTime.now()); + orderDetailAmenity.setId(UUID.randomUUID().toString()); + orderDetailAmenity.setQuantity(request.getQuantity()); + orderDetailAmenity.setPrice(amenity.get().getPrice()); + orderDetailAmenity.setOrderDetail(orderDetail.get()); + orderDetailAmenity.setAmenity(amenity.get()); + + updateAmenityQuantityAfterCreateODA(orderDetailAmenity); + } + + public void updateAmenityQuantityAfterCreateODA(OrderDetailAmenity orderDetailAmenity) { + Amenity amenity = orderDetailAmenity.getAmenity(); + if(amenity.getQuantity() < orderDetailAmenity.getQuantity()) { + throw new RuntimeException("Not enough quantity"); + } + amenity.setQuantity(amenity.getQuantity() - orderDetailAmenity.getQuantity()); + amenityRepository.save(amenity); + orderDetailAmenityRepository.save(orderDetailAmenity); + } + /* [POST]: /order-detail-amenity */ @@ -79,20 +118,15 @@ public OrderDetailAmenityResponse createOrderDetailAmenityApi(OrderDetailAmenity .build(); } - //CREATE in orderDetail - public void createOrderDetailAmenity(OrderDetailAmenity orderDetailAmenity){ - Optional amenity = amenityRepository.findById(orderDetailAmenity.getAmenity().getId()); - if (amenity.isEmpty()) { - throw new RuntimeException("Amenity not found"); + //UPDATE: + public void updateOrderDetailAmenityStatus(OrderDetailAmenityUpdateReq request) { + Optional orderDetailAmenity = orderDetailAmenityRepository.findById(request.getId()); + if (orderDetailAmenity.isEmpty()) { + throw new RuntimeException("Order detail amenity not found"); } - Amenity updatedAmenity = amenity.get(); - if(updatedAmenity.getQuantity() < orderDetailAmenity.getQuantity()){ - throw new RuntimeException("Not enough quantity"); - } - updatedAmenity.setQuantity(updatedAmenity.getQuantity() - orderDetailAmenity.getQuantity()); - amenityRepository.save(updatedAmenity); - - orderDetailAmenityRepository.save(orderDetailAmenity); + OrderDetailAmenity updateOrderDetailAmenity = orderDetailAmenity.get(); + updateOrderDetailAmenity.setStatus(request.getStatus()); + orderDetailAmenityRepository.save(updateOrderDetailAmenity); } //DELETE: diff --git a/src/main/java/com/swp/PodBookingSystem/service/OrderDetailService.java b/src/main/java/com/swp/PodBookingSystem/service/OrderDetailService.java index 1eabf9c4..f3c8bb22 100644 --- a/src/main/java/com/swp/PodBookingSystem/service/OrderDetailService.java +++ b/src/main/java/com/swp/PodBookingSystem/service/OrderDetailService.java @@ -5,10 +5,14 @@ import com.swp.PodBookingSystem.dto.request.OrderDetail.OrderDetailUpdateRoomRequest; import com.swp.PodBookingSystem.dto.request.Room.RoomWithAmenitiesDTO; import com.swp.PodBookingSystem.dto.respone.Amenity.AmenityManagementResponse; +import com.swp.PodBookingSystem.dto.respone.OrderDetail.OrderDetailAmenityListResponse; import com.swp.PodBookingSystem.dto.respone.OrderDetail.OrderDetailManagementResponse; import com.swp.PodBookingSystem.dto.respone.OrderDetail.OrderDetailResponse; +import com.swp.PodBookingSystem.dto.respone.OrderDetailAmenity.OrderDetailAmenityResponseDTO; +import com.swp.PodBookingSystem.dto.respone.PaginationResponse; import com.swp.PodBookingSystem.entity.*; import com.swp.PodBookingSystem.enums.AccountRole; +import com.swp.PodBookingSystem.enums.OrderDetailAmenityStatus; import com.swp.PodBookingSystem.enums.OrderStatus; import com.swp.PodBookingSystem.exception.AppException; import com.swp.PodBookingSystem.exception.ErrorCode; @@ -98,6 +102,69 @@ public Page getOrdersByCustomerId(String customerId, int pa }); } + public PaginationResponse> getPagedOrderDetails(Account user, LocalDateTime startDate, LocalDateTime endDate, int page, int size) { + Page orderDetailPage; + if (user.getRole() == AccountRole.Admin) { + orderDetailPage = orderDetailRepository.findAllWithTimeRange(startDate, endDate, PageRequest.of(page, size)); + } else if (user.getRole() == AccountRole.Staff || user.getRole() == AccountRole.Manager) { + orderDetailPage = orderDetailRepository.findOrdersByBuildingNumberAndTimeRange(user.getBuildingNumber(), startDate, endDate, PageRequest.of(page, size)); + } else { + throw new RuntimeException("Only admin, staff and manager can access this API"); + } + + List orderDetailResponses = orderDetailPage.getContent().stream() + .map(orderDetail -> { + List amenities = + orderDetailAmenityService.getOrderDetailAmenitiesAllInfoByOrderDetailId(orderDetail.getId()).stream() + .map(oda -> OrderDetailAmenityResponseDTO.builder() + .id(oda.getId()) + .quantity(oda.getQuantity()) + .price(oda.getPrice()) + .orderDetailId(oda.getOrderDetail().getId()) + .amenityId(oda.getAmenity().getId()) + .amenityName(oda.getAmenity().getName()) + .amenityType(oda.getAmenity().getType()) + .status(Optional.ofNullable(oda.getStatus()) + .orElse(null)) + .statusDescription(Optional.ofNullable(oda.getStatus()) + .map(OrderDetailAmenityStatus::getDescription) + .orElse(null)) + .createdAt(oda.getCreatedAt()) + .updatedAt(oda.getUpdatedAt()) + .build()) + .collect(Collectors.toList()); + return OrderDetailAmenityListResponse.builder() + .id(orderDetail.getId()) + .customerId(Optional.ofNullable(orderDetail.getCustomer()) + .map(Account::getId) + .orElse(null)) + .buildingId(orderDetail.getBuilding().getId()) + .roomId(orderDetail.getRoom().getId()) + .roomName(orderDetail.getRoom().getName()) + .orderId(orderDetail.getOrder().getId()) + .orderDetailAmenities(amenities) + .servicePackageId(orderDetail.getServicePackage().getId()) + .orderHandledId(Optional.ofNullable(orderDetail.getOrderHandler()) + .map(Account::getId) + .orElse(null)) + .priceRoom(orderDetail.getPriceRoom()) + .status(orderDetail.getStatus()) + .startTime(orderDetail.getStartTime()) + .endTime(orderDetail.getEndTime()) + .createdAt(orderDetail.getCreatedAt()) + .build(); + }) + .collect(Collectors.toList()); + + return PaginationResponse.>builder() + .data(orderDetailResponses) + .currentPage(orderDetailPage.getNumber()) + .totalPage(orderDetailPage.getTotalPages()) + .recordPerPage(orderDetailPage.getSize()) + .totalRecord((int) orderDetailPage.getTotalElements()) + .build(); + } + //CREATE: public boolean processOrderDetails(OrderDetailCreationRequest request, Order order, Account account) { if (account.getRole() != AccountRole.Customer) { @@ -182,11 +249,11 @@ private void createOrderDetailAmenities(OrderDetail orderDetail, List a OrderDetailAmenity orderDetailAmenity = new OrderDetailAmenity(); orderDetailAmenity.setId(UUID.randomUUID().toString()); orderDetailAmenity.setQuantity(amenity.getQuantity()); - orderDetailAmenity.setPrice(amenity.getPrice() * amenity.getQuantity()); + orderDetailAmenity.setPrice(amenity.getPrice()); orderDetailAmenity.setOrderDetail(orderDetail); orderDetailAmenity.setAmenity(amenity); - orderDetailAmenityService.createOrderDetailAmenity(orderDetailAmenity); + orderDetailAmenityService.updateAmenityQuantityAfterCreateODA(orderDetailAmenity); } }