diff --git a/src/main/java/com/swp/PodBookingSystem/configuration/SecurityConfig.java b/src/main/java/com/swp/PodBookingSystem/configuration/SecurityConfig.java index 27aa8a7f..fe500f69 100644 --- a/src/main/java/com/swp/PodBookingSystem/configuration/SecurityConfig.java +++ b/src/main/java/com/swp/PodBookingSystem/configuration/SecurityConfig.java @@ -28,7 +28,9 @@ @EnableMethodSecurity public class SecurityConfig { private final String[] PUBLIC_ENDPOINTS = {"/accounts", "/accounts/me", - "/auth/login", "/auth/introspect", "/auth/refresh-token", "/auth/logout", "/auth/login/google" + "/auth/login", "/auth/introspect", "/auth/refresh-token", + "/auth/logout", "/auth/login/google", + "/rooms/slots-by-rooms-and-date","/rooms/available-by-type-and-date" }; private final String[] ADMIN_ENDPOINTS = { diff --git a/src/main/java/com/swp/PodBookingSystem/controller/AccountController.java b/src/main/java/com/swp/PodBookingSystem/controller/AccountController.java index d262a980..8c73fe05 100644 --- a/src/main/java/com/swp/PodBookingSystem/controller/AccountController.java +++ b/src/main/java/com/swp/PodBookingSystem/controller/AccountController.java @@ -6,6 +6,7 @@ import com.swp.PodBookingSystem.dto.respone.Account.AccountOrderResponse; import com.swp.PodBookingSystem.dto.respone.ApiResponse; import com.swp.PodBookingSystem.dto.respone.AccountResponse; +import com.swp.PodBookingSystem.dto.respone.Order.OrderManagementResponse; import com.swp.PodBookingSystem.dto.respone.PaginationResponse; import com.swp.PodBookingSystem.entity.Account; import com.swp.PodBookingSystem.enums.AccountRole; @@ -13,6 +14,7 @@ import com.swp.PodBookingSystem.exception.ErrorCode; import com.swp.PodBookingSystem.mapper.AccountMapper; import com.swp.PodBookingSystem.service.AccountService; +import com.swp.PodBookingSystem.service.OrderService; import com.swp.PodBookingSystem.service.SendEmailService; import jakarta.mail.MessagingException; import jakarta.servlet.http.HttpServletRequest; @@ -45,6 +47,7 @@ public class AccountController { AccountMapper accountMapper; SendEmailService sendEmailService; JwtDecoder jwtDecoder; + OrderService orderService; @PostMapping ApiResponse createAccount(@RequestBody @Valid AccountCreationRequest request) { @@ -124,6 +127,16 @@ ApiResponse sendEmail(@RequestBody SendMailRequest request) throws MessagingExce .build(); } + @PostMapping("/send-email-order") + ApiResponse sendEmailOrder(@RequestBody SendMailOrderRequest request) throws MessagingException, IOException { + OrderManagementResponse order = orderService.getInfoOrder(request.getOrderId()); + sendEmailService.sendMailTemplate(request.getEmail(), order, "Hóa đơn tại FlexiPod"); + return ApiResponse.builder() + .message("Gửi lời mời đặt lịch thành công") + .code(200) + .build(); + } + @GetMapping("/staff") public ResponseEntity> getAllStaffAccounts() { return ResponseEntity.status(HttpStatus.OK).body(accountService.getAllStaffAccounts()); diff --git a/src/main/java/com/swp/PodBookingSystem/controller/RoomController.java b/src/main/java/com/swp/PodBookingSystem/controller/RoomController.java index 9890646f..e3bf6a38 100644 --- a/src/main/java/com/swp/PodBookingSystem/controller/RoomController.java +++ b/src/main/java/com/swp/PodBookingSystem/controller/RoomController.java @@ -1,11 +1,10 @@ package com.swp.PodBookingSystem.controller; import com.swp.PodBookingSystem.dto.request.Room.RoomAvailabilityDTO; -import com.swp.PodBookingSystem.dto.request.Slot.SlotCreationRequest; +import com.swp.PodBookingSystem.dto.request.Slot.SlotDTO; import com.swp.PodBookingSystem.dto.respone.ApiResponse; import com.swp.PodBookingSystem.dto.request.Room.RoomCreationRequest; import com.swp.PodBookingSystem.dto.request.Room.RoomPaginationDTO; -import com.swp.PodBookingSystem.dto.respone.Calendar.DateResponse; import com.swp.PodBookingSystem.dto.respone.PaginationResponse; import com.swp.PodBookingSystem.dto.respone.Room.BookedRoomDto; import com.swp.PodBookingSystem.dto.respone.Room.RoomResponse; @@ -87,13 +86,13 @@ PaginationResponse> getFilteredRoom(@RequestParam(required = false) S @GetMapping("/available-rooms") ApiResponse> getAvailableRoomsByRoomTypeId(@RequestParam Integer typeId, @RequestParam(required = false) List slots) { - List slotList = new ArrayList<>(); + List slotList = new ArrayList<>(); if(slots!=null) { for(String slot: slots) { String[] parts = slot.split("_"); LocalDateTime startTime = LocalDateTime.parse(parts[0]); LocalDateTime endTime = LocalDateTime.parse(parts[1]); - slotList.add(new SlotCreationRequest(startTime,endTime)); + slotList.add(new SlotDTO(startTime,endTime)); } } return ApiResponse.>builder() @@ -102,24 +101,13 @@ ApiResponse> getAvailableRoomsByRoomTypeId(@RequestParam Integer typ .build(); } - @GetMapping("/calendar") - ApiResponse> getCalendar(@RequestParam List roomIds, - @RequestParam(required = false) Integer servicePackageId, - @RequestParam LocalDate selectedDate, - @RequestParam List slots - ) { - return ApiResponse.>builder() - .data(roomService.getCalendar(roomIds,servicePackageId,selectedDate,slots)) - .message("Get calendar successfully") - .build(); - } - @GetMapping("/unavailable") - ApiResponse> getUnavailableRooms(@RequestParam LocalDateTime startTime, + ApiResponse> getUnavailableRooms(@RequestParam List roomIds, + @RequestParam LocalDateTime startTime, @RequestParam LocalDateTime endTime ) { return ApiResponse.>builder() - .data(roomService.getUnavailableRooms(startTime,endTime)) + .data(roomService.getUnavailableRooms(roomIds,startTime,endTime)) .message("Get unavailable rooms successfully") .build(); } @@ -164,4 +152,22 @@ ApiResponse countCurrentlyServedRooms() { .data(roomService.countCurrentlyServedRooms()) .build(); } + @GetMapping("/available-by-type-and-date") + ApiResponse> getRoomsByTypeAndDate(@RequestParam Integer typeId, @RequestParam String date) { + LocalDate selectedDate = LocalDate.parse(date); + return ApiResponse.>builder() + .data(roomService.getRoomsByTypeAndDate(typeId, selectedDate)) + .message("Get rooms by typeId and date successfully") + .build(); + } + + @GetMapping("/slots-by-rooms-and-date") + ApiResponse> getSlotsByRoomsAndDate(@RequestParam(required = false) List roomIds, @RequestParam(required = false) String date) { + return ApiResponse.>builder() + .data(roomService.getSlotsByRoomsAndDate(roomIds, date)) + .message("Get slots by rooms and date successfully") + .build(); + } + + } diff --git a/src/main/java/com/swp/PodBookingSystem/dto/request/Account/SendMailOrderRequest.java b/src/main/java/com/swp/PodBookingSystem/dto/request/Account/SendMailOrderRequest.java new file mode 100644 index 00000000..fb744d04 --- /dev/null +++ b/src/main/java/com/swp/PodBookingSystem/dto/request/Account/SendMailOrderRequest.java @@ -0,0 +1,14 @@ +package com.swp.PodBookingSystem.dto.request.Account; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class SendMailOrderRequest { + String email; + String orderId; +} diff --git a/src/main/java/com/swp/PodBookingSystem/dto/request/Room/RoomAvailabilityDTO.java b/src/main/java/com/swp/PodBookingSystem/dto/request/Room/RoomAvailabilityDTO.java index 5cbc836a..373a8a9b 100644 --- a/src/main/java/com/swp/PodBookingSystem/dto/request/Room/RoomAvailabilityDTO.java +++ b/src/main/java/com/swp/PodBookingSystem/dto/request/Room/RoomAvailabilityDTO.java @@ -1,9 +1,10 @@ package com.swp.PodBookingSystem.dto.request.Room; +import com.swp.PodBookingSystem.dto.request.Slot.SlotDTO; import lombok.*; import lombok.experimental.FieldDefaults; -import java.time.LocalDateTime; +import java.util.List; @Data @NoArgsConstructor @@ -13,6 +14,5 @@ public class RoomAvailabilityDTO { Integer roomId; String name; - LocalDateTime startTime; - LocalDateTime endTime; + List slots; } diff --git a/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotDTO.java b/src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotDTO.java similarity index 77% rename from src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotDTO.java rename to src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotDTO.java index 2aeafe17..b106bb1b 100644 --- a/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotDTO.java +++ b/src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotDTO.java @@ -1,10 +1,9 @@ -package com.swp.PodBookingSystem.dto.respone.Calendar; +package com.swp.PodBookingSystem.dto.request.Slot; import lombok.*; import lombok.experimental.FieldDefaults; import java.time.LocalDateTime; - @Data @NoArgsConstructor @AllArgsConstructor @@ -13,5 +12,4 @@ public class SlotDTO { LocalDateTime startTime; LocalDateTime endTime; - boolean available; } diff --git a/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/RoomDTO.java b/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/RoomDTO.java index 29f47162..82a100da 100644 --- a/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/RoomDTO.java +++ b/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/RoomDTO.java @@ -1,6 +1,5 @@ package com.swp.PodBookingSystem.dto.respone.Calendar; -import com.swp.PodBookingSystem.dto.request.Slot.SlotCreationRequest; import lombok.*; import lombok.experimental.FieldDefaults; @@ -14,5 +13,5 @@ public class RoomDTO { int roomId; String roomName; - List slots; + List slots; } diff --git a/src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotCreationRequest.java b/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotCustomDTO.java similarity index 69% rename from src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotCreationRequest.java rename to src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotCustomDTO.java index 5492f624..e898da45 100644 --- a/src/main/java/com/swp/PodBookingSystem/dto/request/Slot/SlotCreationRequest.java +++ b/src/main/java/com/swp/PodBookingSystem/dto/respone/Calendar/SlotCustomDTO.java @@ -1,15 +1,17 @@ -package com.swp.PodBookingSystem.dto.request.Slot; +package com.swp.PodBookingSystem.dto.respone.Calendar; import lombok.*; import lombok.experimental.FieldDefaults; import java.time.LocalDateTime; + @Data @NoArgsConstructor @AllArgsConstructor @Builder @FieldDefaults(level = AccessLevel.PRIVATE) -public class SlotCreationRequest { +public class SlotCustomDTO { LocalDateTime startTime; LocalDateTime endTime; + boolean available; } diff --git a/src/main/java/com/swp/PodBookingSystem/repository/RoomRepository.java b/src/main/java/com/swp/PodBookingSystem/repository/RoomRepository.java index c09cb37b..60038b0e 100644 --- a/src/main/java/com/swp/PodBookingSystem/repository/RoomRepository.java +++ b/src/main/java/com/swp/PodBookingSystem/repository/RoomRepository.java @@ -1,5 +1,6 @@ package com.swp.PodBookingSystem.repository; +import com.swp.PodBookingSystem.dto.request.Slot.SlotDTO; import com.swp.PodBookingSystem.dto.respone.Room.BookedRoomDto; import com.swp.PodBookingSystem.entity.OrderDetail; import com.swp.PodBookingSystem.entity.Room; @@ -62,4 +63,35 @@ List findRoomAvailabilityWithinDateRange( "WHERE :currentTime BETWEEN od.startTime AND od.endTime " + "AND od.status = com.swp.PodBookingSystem.enums.OrderStatus.Successfully") int countCurrentlyServedRooms(@Param("currentTime") LocalDateTime currentTime); + + @Query("SELECT r FROM Room r " + + "JOIN OrderDetail od ON r.id = od.room.id " + + "WHERE r.roomType.id = :typeId " + + "AND r.status = com.swp.PodBookingSystem.enums.RoomStatus.Available " + + "AND od.startTime >= :startTime " + + "AND od.endTime <= :endTime " + + "AND (od.status = com.swp.PodBookingSystem.enums.OrderStatus.Successfully " + + "OR od.status = com.swp.PodBookingSystem.enums.OrderStatus.Pending) " + ) + List getRoomsByTypeAndDate(@Param("typeId") Integer typeId, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + @Query("SELECT DISTINCT NEW com.swp.PodBookingSystem.dto.request.Slot.SlotDTO(od.startTime,od.endTime) " + + "FROM OrderDetail od " + + "WHERE od.room.id = :roomId " + + "AND od.room.status = com.swp.PodBookingSystem.enums.RoomStatus.Available " + + "AND od.startTime >= :startTime " + + "AND od.endTime <= :endTime " + + "AND (od.status = com.swp.PodBookingSystem.enums.OrderStatus.Successfully " + + "OR od.status = com.swp.PodBookingSystem.enums.OrderStatus.Pending) " + ) + List getSlotsByRoomAndDate(@Param("roomId")Integer roomId, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime); + + @Query("SELECT r FROM Room r " + + "JOIN r.roomType rt " + + "WHERE rt.id = :typeId") + List findAllByTypeId(@Param("typeId") Integer typeId); } diff --git a/src/main/java/com/swp/PodBookingSystem/service/RoomService.java b/src/main/java/com/swp/PodBookingSystem/service/RoomService.java index 7e272b45..23d5be73 100644 --- a/src/main/java/com/swp/PodBookingSystem/service/RoomService.java +++ b/src/main/java/com/swp/PodBookingSystem/service/RoomService.java @@ -2,13 +2,9 @@ import com.swp.PodBookingSystem.dto.request.Room.RoomAvailabilityDTO; import com.swp.PodBookingSystem.dto.request.Room.RoomCreationRequest; -import com.swp.PodBookingSystem.dto.request.Slot.SlotCreationRequest; -import com.swp.PodBookingSystem.dto.respone.Calendar.DateResponse; -import com.swp.PodBookingSystem.dto.respone.Calendar.RoomDTO; -import com.swp.PodBookingSystem.dto.respone.Calendar.SlotDTO; +import com.swp.PodBookingSystem.dto.request.Slot.SlotDTO; import com.swp.PodBookingSystem.dto.respone.Room.BookedRoomDto; import com.swp.PodBookingSystem.dto.respone.Room.RoomResponse; -import com.swp.PodBookingSystem.entity.OrderDetail; import com.swp.PodBookingSystem.entity.Room; import com.swp.PodBookingSystem.entity.RoomType; import com.swp.PodBookingSystem.exception.AppException; @@ -29,7 +25,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -86,13 +81,13 @@ public boolean isRoomAvailable(Integer roomId, LocalDateTime startTime, LocalDat return roomRepository.isRoomAvailable(roomId, startTime, endTime); } - public List getRoomByTypeAndSlot(Integer typeId,List slots ) { + public List getRoomByTypeAndSlot(Integer typeId,List slots ) { List roomList = roomRepository.findRoomsByTypeId(typeId); List availableRooms = new ArrayList<>(); for (Room room : roomList) { boolean isAvailableForAllSlots = true; - for (SlotCreationRequest slot : slots) { + for (SlotDTO slot : slots) { if (!isRoomAvailable(room.getId(), slot.getStartTime(), slot.getEndTime())) { isAvailableForAllSlots = false; @@ -144,64 +139,27 @@ public String deleteRoom(int roomId) { return "Delete room " + roomId + " successfully"; } - public List getCalendar(List roomIds, Integer servicePackageId, LocalDate selectedDate, List slots) - { - List response = new ArrayList<>(); - List dates = new ArrayList<>(); - - if(servicePackageId!= null && servicePackageId == 1) { - LocalDateTime currentDate = selectedDate.atStartOfDay(); - int count = 1; - do { - dates.add(currentDate.toLocalDate()); - currentDate.plusDays(7); - } while(count++<=3); - } else if (servicePackageId!= null && servicePackageId == 2) { - LocalDateTime currentDate = selectedDate.atStartOfDay(); - int count = 1; - do { - dates.add(currentDate.toLocalDate()); - currentDate.plusDays(1); - } while(count++<=29); - } else { - LocalDateTime currentDate = selectedDate.atStartOfDay(); - dates.add(currentDate.toLocalDate()); + + + public List getUnavailableRooms(List roomIds,LocalDateTime startTime, LocalDateTime endTime) { + if(roomIds == null || roomIds.isEmpty()) { + return new ArrayList<>(); } - for(LocalDate date: dates) { - List rooms = roomIds.parallelStream().map(roomId -> { - RoomDTO room = new RoomDTO(); - Optional findRoom = roomRepository.findById((roomId)); - Room roomFromDB = findRoom.orElseThrow(() -> new RuntimeException("Room not found")); - room.setRoomId(roomFromDB.getId()); - room.setRoomName(roomFromDB.getName()); - LocalDateTime currentDate = date.atStartOfDay(); - - List slotResponse = slots.parallelStream().map(slot->{ - String[] parts = slot.split("-"); - LocalDateTime startTime = currentDate.withHour(Integer.parseInt(parts[0].split(":")[0].trim())); - LocalDateTime endTime = currentDate.withHour(Integer.parseInt(parts[1].split(":")[0].trim())); - return new SlotDTO(startTime, endTime, roomRepository.isRoomAvailable(roomFromDB.getId(),startTime, endTime)); - }).collect(Collectors.toList()); - room.setSlots(slotResponse); - return room; - }).collect(Collectors.toList()); - response.add(new DateResponse(date,rooms)); + if(startTime == null || endTime == null) { + throw new RuntimeException("Invalid date"); } - return response; - } - - public List getUnavailableRooms(LocalDateTime startTime, LocalDateTime endTime) { - List orders = roomRepository.findRoomAvailabilityWithinDateRange(startTime, endTime); - System.out.println(orders.toString()); - return orders.stream() - .map(order -> RoomAvailabilityDTO.builder() - .roomId(order.getRoom().getId()) // Assuming Room has an 'id' field - .name(order.getRoom().getName()) // Assuming Room has a 'name' field - .startTime(order.getStartTime()) - .endTime(order.getEndTime()) - .build()) - .collect(Collectors.toList()); + List roomAvailabilityDTOList = new ArrayList<>(); + for(Integer roomId: roomIds) { + List slotList = roomRepository.getSlotsByRoomAndDate(roomId, startTime, endTime); + Room room = roomRepository.findById(roomId).orElseThrow(() -> new RuntimeException("Room not found")); + roomAvailabilityDTOList.add(RoomAvailabilityDTO.builder() + .roomId(roomId) + .name(room.getName()) + .slots(slotList) + .build()); + } + return roomAvailabilityDTOList; } public List getBookedRooms(String customerId) { @@ -215,4 +173,62 @@ public List getBookedRooms(String customerId) { public int countCurrentlyServedRooms() { return roomRepository.countCurrentlyServedRooms(LocalDateTime.now()); } + + public List getRoomsByTypeAndDate(Integer typeId, LocalDate date) { + List result = new ArrayList<>(); + List listSlotConstants = new ArrayList<>(); + LocalDateTime current = date.atTime(7, 0, 0); + while (current.isBefore(date.atTime(21, 0, 0))) { + if(current.isBefore(LocalDateTime.now())) { + current = current.plusHours(2); + continue; + } + listSlotConstants.add(new SlotDTO(current, current.plusHours(2))); + current = current.plusHours(2); + } + LocalDateTime startTime = date.atStartOfDay(); + LocalDateTime endTime = date.atTime(23, 59, 59); + List rooms =roomRepository.findAllByTypeId(typeId); + for(Room room: rooms) { + List slotList = roomRepository.getSlotsByRoomAndDate(room.getId(), startTime, endTime); + List tmp = new ArrayList<>(listSlotConstants); + tmp.removeAll(slotList); + if(!tmp.isEmpty()) { + result.add(room); + } + } + + return result; + } + + public List getSlotsByRoomsAndDate(List roomIds, String date) { + LocalDate selectedDate = date == null? LocalDate.now() : LocalDate.parse(date); + if(selectedDate.isBefore(LocalDate.now())) { + throw new RuntimeException("Invalid date"); + } + if(selectedDate.isEqual(LocalDate.now()) && LocalDateTime.now().getHour() >= 21) { + throw new RuntimeException("Invalid date"); + } + + LocalDateTime startTime = LocalDateTime.now().toLocalDate().equals(selectedDate) ? LocalDateTime.now() : selectedDate.atStartOfDay(); + LocalDateTime endTime = selectedDate.atTime(23, 59, 59); + List listSlotConstants = new ArrayList<>(); + LocalDateTime current = selectedDate.atTime(7, 0, 0); + while (current.isBefore(selectedDate.atTime(21, 0, 0))) { + if(current.isBefore(LocalDateTime.now())) { + current = current.plusHours(2); + continue; + } + listSlotConstants.add(new SlotDTO(current, current.plusHours(2))); + current = current.plusHours(2); + } + if(roomIds == null || roomIds.isEmpty()) { + return listSlotConstants; + } + for (Integer roomId : roomIds) { + List listSlotDateTime = roomRepository.getSlotsByRoomAndDate(roomId, startTime, endTime); + listSlotConstants.removeAll(listSlotDateTime); + } + return listSlotConstants; + } } diff --git a/src/main/java/com/swp/PodBookingSystem/service/SendEmailService.java b/src/main/java/com/swp/PodBookingSystem/service/SendEmailService.java index abee8e57..dd4028ed 100644 --- a/src/main/java/com/swp/PodBookingSystem/service/SendEmailService.java +++ b/src/main/java/com/swp/PodBookingSystem/service/SendEmailService.java @@ -6,6 +6,7 @@ import biweekly.property.Method; import biweekly.util.Duration; import com.swp.PodBookingSystem.dto.request.CalendarRequest; +import com.swp.PodBookingSystem.dto.respone.Order.OrderManagementResponse; import com.swp.PodBookingSystem.entity.OrderDetail; import jakarta.activation.DataHandler; import jakarta.activation.DataSource; @@ -21,18 +22,25 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -57,6 +65,56 @@ public void sendEmail(String recipient, String body, String subject) throws Mess helper.setSubject(subject); helper.setText(body, true); + javaMailSender.send(mimeMessage); + } + + public void sendMailTemplate(String recipient, OrderManagementResponse order, String subject) throws MessagingException, IOException { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + ClassPathResource resource = new ClassPathResource("templates/emailTemplate.html"); + String content; + try (var inputStream = resource.getInputStream()) { + content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + } + var roomHaveAmenities = order.getOrderDetails().stream() + .filter(od -> !od.getAmenities().isEmpty()) + .collect(Collectors.toList()); + double totalPriceRoom = order.getOrderDetails().stream() + .mapToDouble(orderDetail -> orderDetail.getRoomPrice()) + .sum(); + double totalPriceAmenity = order.getOrderDetails().stream() + .mapToDouble(orderDetail -> orderDetail.getAmenities().stream() + .mapToDouble(amenity -> amenity.getPrice() * amenity.getQuantity()) + .sum() + ) + .sum(); + + double priceBeforeDiscount = totalPriceRoom + totalPriceAmenity; + double discountPercentage = order.getOrderDetails().get(0).getServicePackage().getDiscountPercentage(); + double finalPrice = priceBeforeDiscount * (1 - discountPercentage / 100); + int integerAmount = (int) Math.round(finalPrice); + String formattedAmount = String.format("%,d", integerAmount).replace(",", "."); + String status; + if (order.getOrderDetails().getFirst().getStatus().equals("Successfully")) { + status = "Đã thanh toán"; + } else if (order.getOrderDetails().getFirst().getStatus().equals("Rejected")) { + status = "Đã hủy"; + } else { + status = "Đang chờ xử lí"; + } + + content = content.replace("{{orderId}}", order.getId()) + .replace("{{orderStartTime}}", order.getCreatedAt().format(DateTimeFormatter.ofPattern("HH:mm:ss dd-MM-yyyy"))) + .replace("{{roomName}}", order.getOrderDetails().getFirst().getRoomTypeName()) + .replace("{{status}}", status) + .replace("{{amenity}}", roomHaveAmenities.isEmpty() ? "Không có" : "Có") + .replace("{{totalPrice}}", formattedAmount + " VND"); + + helper.setFrom(fromEmailId); + helper.setTo(recipient); + helper.setSubject(subject); + helper.setText(content, true); + javaMailSender.send(mimeMessage); log.info("Send email successfully"); } diff --git a/src/main/resources/templates/emailTemplate.html b/src/main/resources/templates/emailTemplate.html new file mode 100644 index 00000000..f2d11a97 --- /dev/null +++ b/src/main/resources/templates/emailTemplate.html @@ -0,0 +1,118 @@ + + + + + + FlexiPod Email + + + + + + + +
+ + + + + +
+

FlexiPod

+
+ + + + + + +
+

Hóa đơn của bạn tại + FlexiPod

+

+ Mã đơn: {{orderId}} +

+

+ Ngày đặt: {{orderStartTime}} +

+

+ Trạng thái: {{status}} +

+

+ Loại phòng đặt: {{roomName}} +

+

+ Tiện tích đặt thêm: {{amenity}} +

+

+ Tổng tiền: {{totalPrice}} +

+

+ Cảm ơn vì đã chọn FlexiPod! +

+
+ + + + + + + +
+ + + + + + + +
+ FlexiPod +
Copyright © 2024
+
+ Điều khoản và chính sách + Liên hệ + +
+
+ +