using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Stripe; using Stripe.Checkout; using Syncfusion.DocIO; using Syncfusion.DocIO.DLS; using Syncfusion.DocIORenderer; using Syncfusion.Drawing; using Syncfusion.Pdf; using System.Security.Claims; using WhiteLagoon.Application.Common.Interfaces; using WhiteLagoon.Application.Common.Utility; using WhiteLagoon.Application.Contract; using WhiteLagoon.Application.Services.Interface; using WhiteLagoon.Domain.Entities; using WhiteLagoon.Infrastructure.Repository; namespace WhiteLagoon.Web.Controllers { public class BookingController : Controller { private readonly IBookingService _bookingService; private readonly IWebHostEnvironment _webHostEnvironment; private readonly IVillaService _villaService; private readonly UserManager _userManager; private readonly IVillaNumberService _villaNumberService; private readonly IPaymentService _paymentService; private readonly IEmailService _emailService; public BookingController(IBookingService bookingService, IPaymentService paymentService, IVillaService villaService, IVillaNumberService villaNumberService, IWebHostEnvironment webHostEnvironment, UserManager userManager, IEmailService emailService) { _emailService = emailService; _paymentService = paymentService; _userManager = userManager; _villaService = villaService; _villaNumberService = villaNumberService; _bookingService = bookingService; _webHostEnvironment = webHostEnvironment; } [Authorize] public IActionResult Index() { return View(); } [Authorize] public IActionResult FinalizeBooking(int villaId, DateOnly checkInDate, int nights) { var claimsIdentity = (ClaimsIdentity)User.Identity; var userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value; ApplicationUser user = _userManager.FindByIdAsync(userId).GetAwaiter().GetResult(); Booking booking = new() { VillaId = villaId, Villa = _villaService.GetVillaById(villaId), CheckInDate = checkInDate, Nights = nights, CheckOutDate = checkInDate.AddDays(nights), UserId = userId, Phone=user.PhoneNumber, Email=user.Email, Name=user.Name }; booking.TotalCost = booking.Villa.Price * nights; return View(booking); } [Authorize] [HttpPost] public IActionResult FinalizeBooking(Booking booking) { var villa = _villaService.GetVillaById(booking.VillaId); booking.TotalCost = villa.Price * booking.Nights; booking.Status=SD.StatusPending; booking.BookingDate = DateTime.Now; if (!_villaService.IsVillaAvailableByDate(villa.Id,booking.Nights,booking.CheckInDate)) { TempData["error"] = "Room has been sold out!"; //no rooms available return RedirectToAction(nameof(FinalizeBooking), new { villaId = booking.VillaId, checkInDate = booking.CheckInDate, nights = booking.Nights }); } _bookingService.CreateBooking(booking); var domain = Request.Scheme+"://"+Request.Host.Value+"/"; var options = _paymentService.CreateStripeSessionOptions(booking, villa, domain); var session = _paymentService.CreateStripeSession(options); _bookingService.UpdateStripePaymentID(booking.Id, session.Id, session.PaymentIntentId); Response.Headers.Add("Location", session.Url); return new StatusCodeResult(303); } [Authorize] public IActionResult BookingConfirmation(int bookingId) { Booking bookingFromDb = _bookingService.GetBookingById(bookingId); if (bookingFromDb.Status == SD.StatusPending) { //this is a pending order, we need to confirm if payment was successful var service = new SessionService(); Session session = service.Get(bookingFromDb.StripeSessionId); if (session.PaymentStatus == "paid") { _bookingService.UpdateStatus(bookingFromDb.Id, SD.StatusApproved,0); _bookingService.UpdateStripePaymentID(bookingFromDb.Id,session.Id,session.PaymentIntentId); _emailService.SendEmailAsync(bookingFromDb.Email,"Booking Confirmation - White Lagoon", "

Your booking has been confirmed. Booking ID - " + bookingFromDb.Id+"

"); } } return View(bookingId); } [Authorize] public IActionResult BookingDetails(int bookingId) { Booking bookingFromDb = _bookingService.GetBookingById(bookingId); if (bookingFromDb.VillaNumber==0 && bookingFromDb.Status == SD.StatusApproved) { var availableVillaNumber = AssignAvailableVillaNumberByVilla(bookingFromDb.VillaId); bookingFromDb.VillaNumbers = _villaNumberService.GetAllVillaNumbers().Where(u => u.VillaId == bookingFromDb.VillaId && availableVillaNumber.Any(x => x == u.Villa_Number)).ToList(); } return View(bookingFromDb); } [HttpPost] [Authorize] public IActionResult GenerateInvoice(int id, string downloadType) { string basePath = _webHostEnvironment.WebRootPath; WordDocument document = new WordDocument(); // Load the template. string dataPath = basePath + @"/exports/BookingDetails.docx"; using FileStream fileStream = new (dataPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); document.Open(fileStream, FormatType.Automatic); //Update Template Booking bookingFromDb = _bookingService.GetBookingById(id); TextSelection textSelection = document.Find("xx_customer_name", false, true); WTextRange textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.Name; textSelection = document.Find("xx_customer_phone", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.Phone; textSelection = document.Find("xx_customer_email", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.Email; textSelection = document.Find("XX_BOOKING_NUMBER", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = "BOOKING ID - " + bookingFromDb.Id; textSelection = document.Find("XX_BOOKING_DATE", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = "BOOKING DATE - " + bookingFromDb.BookingDate.ToShortDateString(); textSelection = document.Find("xx_payment_date", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.PaymentDate.ToShortDateString(); textSelection = document.Find("xx_checkin_date", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.CheckInDate.ToShortDateString(); textSelection = document.Find("xx_checkout_date", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.CheckOutDate.ToShortDateString(); ; textSelection = document.Find("xx_booking_total", false, true); textRange = textSelection.GetAsOneRange(); textRange.Text = bookingFromDb.TotalCost.ToString("c"); WTable table = new(document); table.TableFormat.Borders.LineWidth = 1f; table.TableFormat.Borders.Color = Color.Black; table.TableFormat.Paddings.Top = 7f; table.TableFormat.Paddings.Bottom = 7f; table.TableFormat.Borders.Horizontal.LineWidth = 1f; int rows = bookingFromDb.VillaNumber > 0 ? 3 : 2; table.ResetCells(rows, 4); WTableRow row0 = table.Rows[0]; row0.Cells[0].AddParagraph().AppendText("NIGHTS"); row0.Cells[0].Width=80; row0.Cells[1].AddParagraph().AppendText("VILLA"); row0.Cells[1].Width = 220; row0.Cells[2].AddParagraph().AppendText("PRICE PER NIGHT"); row0.Cells[3].AddParagraph().AppendText("TOTAL"); row0.Cells[3].Width = 80; WTableRow row1 = table.Rows[1]; row1.Cells[0].AddParagraph().AppendText(bookingFromDb.Nights.ToString()); row1.Cells[0].Width = 80; row1.Cells[1].AddParagraph().AppendText(bookingFromDb.Villa.Name); row1.Cells[1].Width = 220; row1.Cells[2].AddParagraph().AppendText((bookingFromDb.TotalCost/bookingFromDb.Nights).ToString("c")); row1.Cells[3].AddParagraph().AppendText(bookingFromDb.TotalCost.ToString("c")); row1.Cells[3].Width = 80; if (bookingFromDb.VillaNumber > 0) { WTableRow row2 = table.Rows[2]; row2.Cells[0].Width = 80; row2.Cells[1].AddParagraph().AppendText("Villa Number - " + bookingFromDb.VillaNumber.ToString()); row2.Cells[1].Width = 220; row2.Cells[3].Width = 80; } WTableStyle tableStyle = document.AddTableStyle("CustomStyle") as WTableStyle; tableStyle.TableProperties.RowStripe = 1; tableStyle.TableProperties.ColumnStripe = 2; tableStyle.TableProperties.Paddings.Top = 2; tableStyle.TableProperties.Paddings.Bottom = 1; tableStyle.TableProperties.Paddings.Left = 5.4f; tableStyle.TableProperties.Paddings.Right = 5.4f; ConditionalFormattingStyle firstRowStyle = tableStyle.ConditionalFormattingStyles.Add(ConditionalFormattingType.FirstRow); firstRowStyle.CharacterFormat.Bold = true; firstRowStyle.CharacterFormat.TextColor = Color.FromArgb(255, 255, 255, 255); firstRowStyle.CellProperties.BackColor = Color.Black; table.ApplyStyle("CustomStyle"); TextBodyPart bodyPart = new(document); bodyPart.BodyItems.Add(table); document.Replace("", bodyPart, false, false); using DocIORenderer renderer = new (); MemoryStream stream = new(); if (downloadType == "word") { document.Save(stream, FormatType.Docx); stream.Position = 0; return File(stream, "application/docx", "BookingDetails.docx"); } else { PdfDocument pdfDocument = renderer.ConvertToPDF(document); pdfDocument.Save(stream); stream.Position = 0; return File(stream, "application/pdf", "BookingDetails.pdf"); } } [HttpPost] [Authorize(Roles = SD.Role_Admin)] public IActionResult CheckIn(Booking booking) { _bookingService.UpdateStatus(booking.Id, SD.StatusCheckedIn, booking.VillaNumber); TempData["Success"] = "Booking Updated Successfully."; return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id }); } [HttpPost] [Authorize(Roles = SD.Role_Admin)] public IActionResult CheckOut(Booking booking) { _bookingService.UpdateStatus(booking.Id, SD.StatusCompleted , booking.VillaNumber); TempData["Success"] = "Booking Completed Successfully."; return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id }); } [HttpPost] [Authorize(Roles = SD.Role_Admin)] public IActionResult CancelBooking(Booking booking) { _bookingService.UpdateStatus(booking.Id, SD.StatusCancelled, 0); TempData["Success"] = "Booking Cancelled Successfully."; return RedirectToAction(nameof(BookingDetails), new { bookingId = booking.Id }); } private List AssignAvailableVillaNumberByVilla(int villaId) { List availableVillaNumbers = new(); var villaNumbers = _villaNumberService.GetAllVillaNumbers().Where(u => u.VillaId == villaId); var checkedInVilla = _bookingService.GetCheckedInVillaNumbers(villaId); foreach(var villaNumber in villaNumbers) { if (!checkedInVilla.Contains(villaNumber.Villa_Number)) { availableVillaNumbers.Add(villaNumber.Villa_Number); } } return availableVillaNumbers; } #region API Calls [HttpGet] [Authorize] public IActionResult GetAll(string status) { IEnumerable objBookings; string userId = ""; if (string.IsNullOrEmpty(status)) { status = ""; } if (!User.IsInRole(SD.Role_Admin)) { var claimsIdentity = (ClaimsIdentity)User.Identity; userId = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value; } objBookings = _bookingService.GetAllBookings(userId, status); return Json(new { data = objBookings }); } #endregion } }