roomTypePacketServices = $roomTypePacketServices; $this->roomServices = $roomServices; $this->roomBookingServices = $roomBookingServices; $this->paymentServices = $paymentServices; $this->packetServices = $packetServices; } public function index($request, $customerId = null) { $limit = $request->get("limit"); $query_array = $request->query(); $query = $this->model; $status = $query_array['status'] ?? ""; if (!empty($status)) { $query = $query->where('status', $status); } if ($customerId && !empty($customerId)) { $query = $query->where("customer_id", $customerId); // $query->with('customer', function ($query) use ($customerId) { // $query->where('id', $customerId); // }); } $query->with("payments", function ($query) { $query->select("payments.id", "payments.payment_date", "payments.email", "payments.address", "payments.payment_method", "payments.description", "payments.payment_amount", "payments.booking_id"); }); $query->with("rooms", function ($query) { $query->select("rooms.id", "rooms.room_view", "rooms.room_number", "rooms.room_type_packet_id"); }); $query->select("id", "checkout_at", "checkin_at", "total_price" , "number_guests", "status", "cancel_reason"); $query = $query->orderBy('updated_at', 'desc'); $rs = empty($limit) ? ($query->get()) : ($query->paginate($limit)); $this->prepareRoom($rs); return $rs; } public function prepareRoom(&$booking) { $booking->each(function ($item) { $this->roomServices->getRoomByIdsAndPacket($item); }); } public function getBookingByNotAvailble($param) { $from_time = $param['checkin_at']; $to_time = $param['checkout_at']; $query = $this->model; $query = $query->whereHas('bookingStatus', function ($query) { $query->where('name', '!=', BookingStatus::getKey(BookingStatus::CANCEL)); }); $query->where(function ($query) use ($from_time, $to_time) { $query->orwhere(function ($query) use ($from_time, $to_time) { $query ->whereRaw("bookings.checkin_at <= STR_TO_DATE(?, '%Y-%m-%d %H:%i:%s')", $from_time) ->whereRaw("bookings.checkout_at >= STR_TO_DATE(?, '%Y-%m-%d %H:%i:%s')", $from_time); }); $query->orwhere(function ($query) use ($from_time, $to_time) { $query ->whereRaw("bookings.checkin_at >= STR_TO_DATE(?, '%Y-%m-%d %H:%i:%s')", $from_time) ->whereRaw("bookings.checkin_at <= STR_TO_DATE(?, '%Y-%m-%d %H:%i:%s')", $to_time); }); }); return $query->get(); } public function makeCheckout($request) { // todo: tính lại total price dựa vào giá phòng, và giá packet // todo: nhận về id room type, list id packet, tìm ra các room ứng với dữ liệu trên // todo: thuế đc lấy từ db ? // nếu số lượng room search nhỏ hơn số lượng room cần đăt , thì báo lỗi // 1. tạo 1 record booking với thông tin booking // nếu dữ liệu của paymentamount bằng với total price, thì set status là complete // nhỏ hơn thì set partialy paid , nếu paymentamount = 0 thì set pending // 2. tạo reocrd bookin_room với id booking và id room // 3. tạo record payment với id booking $gstRate = 0.12; $totalPrice = 0; $roomTypeId = $request["room"]["id"]; $numberRoom = count($request["packets"]); $packets = []; $paymentAmount = $request["payment"]["payment_amount"] ?? 0; foreach ($request["packets"] as $item) { $packets[] = $item["id"]; } $isStopBooking = false; $booking = []; $hashCheck = []; // tạo dữ liệu số lượng packet ứng với packet foreach ($packets as $packet) { if (isset($hashCheck[$packet])) { $hashCheck[$packet] += 1; } else { $hashCheck[$packet] = 1; } } // tinh tong tien $checkout_at = Carbon::createFromFormat('Y-m-d', $request["checkout_at"]); $checkin_at = Carbon::createFromFormat('Y-m-d', $request["checkin_at"]); $bookingPeriodDays = $checkout_at->diff($checkin_at)->days; $bookingPeriodDays = $bookingPeriodDays > 0 ? $bookingPeriodDays : 1; $roomTypeService = app()->make(RoomTypeServices::class); $tmp_packets = $this->packetServices->getPacketByIds($packets); $roomType = $roomTypeService->getRoomTypeById($roomTypeId); if (!$roomType || $isStopBooking) { throw new \Exception("room not available"); } $roomTypePrice = $roomType->base_price ?? 0; $tmp_packets->each(function ($packet) use (&$totalPrice, $roomTypePrice, $bookingPeriodDays, $hashCheck) { $totalPrice += (($packet->base_price) + $roomTypePrice) * $hashCheck[$packet->id] * $bookingPeriodDays; }); $totalPrice = ($totalPrice * $gstRate) + $totalPrice; $roomAvailable = collect(); foreach ($hashCheck as $key => $value) { // lấy ra roomtypepacket ứng với packet roomtype $roomTypePackets = $this->roomTypePacketServices->getRoomTypePacketByRoomTypeAndPacket($roomTypeId, $key)->pluck("id"); if (count($roomTypePackets) < 1) { $isStopBooking = true; break; } // điều kiện booking về ngày check in phải thõa $bookings = $this->getBookingByNotAvailble($request)->pluck("id"); // lấy ra room thõa đk booking, và thõa đk room type $rooms = $this->roomServices->getRoomByRoomTypePacketsAndBooking($roomTypePackets, $bookings); // nếu số room tìm đc nhỏ hơn số room muốn đặt thì lỗi if ($rooms->count() < $value) { $isStopBooking = true; break; } else { $rooms = $rooms->take($value); $roomAvailable = $roomAvailable->merge($rooms); } } if ($isStopBooking) { throw new \Exception("room not available"); } if ($paymentAmount == 0) { $booking["status"] = BookingStatus::PENDING; } else if ($totalPrice > $paymentAmount) { $booking["status"] = BookingStatus::PENDING; } else if ($paymentAmount >= $totalPrice) { $booking["status"] = BookingStatus::PENDING; } $booking["customer_id"] = $this->getCurrentUser()->id; $booking["checkin_at"] = $request["checkin_at"]; $booking["checkout_at"] = $request["checkout_at"]; $booking["total_price"] = $totalPrice; $booking["number_guests"] = $request["guests"]; $booking = $this->save($booking); if (!$booking || $isStopBooking) { throw new \Exception("booking not available"); } $roomBookings = collect(); // các room thõa đk có thể đặt phòng $roomAvailable->each(function ($room) use ($booking, &$roomBookings) { $roomBooking = [ "booking_id" => $booking->id, "room_id" => $room->id, "room_type_packet_id" => $room->room_type_packet_id ]; $roomBooking = $this->roomBookingServices->save($roomBooking); if (!$roomBooking) { $isStopBooking = true; return false; } $roomBookings->push($roomBooking); }); if ($isStopBooking) { throw new \Exception("booking not available"); } $payment = [ "booking_id" => $booking->id, "payment_date" => $request["payment"]["payment_date"] ?? "", "payment_method" => $request["payment"]["payment_method"] ?? "", "description" => $request["payment"]["description"] ?? "", "payment_amount" => $paymentAmount, "address" => $request["payment"]["address"] ?? "", "email" => $request["payment"]["email"] ?? "", "city" => $request["payment"]["city"] ?? "", "state" => $request["payment"]["state"] ?? "", "post_code" => $request["payment"]["post_code"] ?? "" ]; $payment = $this->paymentServices->save($payment); if (!$payment || $isStopBooking) { throw new \Exception("payment not available"); } $booking->rooms = $roomAvailable; $this->roomServices->getRoomByIdsAndPacket($booking); $gmailProvider = new Mail; $gmailProvider->from('lisatthu35@gmail.com'); $gmailProvider->subject( "noreply-mail" ); $gmailProvider->to($payment->email); $mailableInstance = new BookingMail($booking,$payment, "Thông tin đơn đặt phòng"); $gmailProvider->message($mailableInstance->render()); $gmailProvider->send(); //Mail::to($payment->email)->send(new BookingMail($booking,$payment, "Thông tin đơn đặt phòng")); return $booking; } public function show($id) { $data = $this->model->where('id', $id)->first(); return $data; } public function save(array $attributes) { $mailSubject = false; $entity = null; if (!empty($attributes['id'])) { $entity = $this->model->where('id', $attributes['id'])->first(); if ($entity) { $entity->fill($attributes)->save(); if ($entity->status === BookingStatus::CANCEL) { $mailSubject = "Đơn đặt phòng đã bị từ chối"; } if ($entity->status === BookingStatus::COMPLETED) { $mailSubject = "Đơn đặt phòng đã thành công"; } } } else { $entity = $this->model->create($attributes); } if ($mailSubject) { $gmailProvider = new Mail; $gmailProvider->from('lisatthu35@gmail.com'); $gmailProvider->subject( "noreply-mail" ); $gmailProvider->to($entity->payments[0]->email); $mailableInstance = new BookingMail($entity, $entity->payments[0], $mailSubject); $gmailProvider->message($mailableInstance->render()); $gmailProvider->send(); //Mail::to($entity->payments[0]->email)->send(new BookingMail($entity, $entity->payments[0], $mailSubject)); } return $entity; } public function delete($id) { $entity = $this->model ->where('id', $id)->first(); return !empty($entity) ? $entity->delete() : null; } }