示例#1
0
        public async Task <BookingResponseModel> CancelBookingAsync(BookingCancellationModel bookingCancellationModel)
        {
            var response = new BookingResponseModel {
                IsSuccess = true
            };

            var booking = bookingCancellationModel.BookingId > 0 ? await _context.Set <Booking>().FirstOrDefaultAsync(b => b.Id == bookingCancellationModel.BookingId)
                                                                 : await _context.Set <Booking>().FirstOrDefaultAsync(b => b.BookingReference == bookingCancellationModel.BookingReference &&
                                                                                                                      b.ReaderTicket == bookingCancellationModel.ReaderTicket);

            if (booking == null)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"There is no booking found for the booking id {bookingCancellationModel.BookingId}";
                return(response);
            }

            _context.Attach(booking);
            booking.BookingStatusId = (int)BookingStatuses.Cancelled;
            booking.LastModifiedBy  = bookingCancellationModel.CancelledBy;
            await _context.SaveChangesAsync();

            if (!string.IsNullOrWhiteSpace(booking.Email))
            {
                var cancelledBooking = await _context.Bookings.AsNoTracking <Booking>().Include(s => s.Seat).FirstOrDefaultAsync(b => b.Id == booking.Id);

                var bookingModel = GetSerialisedBooking(cancelledBooking);
                await _emailService.SendEmailAsync(EmailType.BookingCancellation, bookingModel.Email, bookingModel);
            }

            return(response);
        }
示例#2
0
        public async Task <BookingResponseModel> CreateBookingAsync(BookingModel bookingModel)
        {
            var response = new BookingResponseModel {
                IsSuccess = true
            };

            using var transaction = await _context.Database.BeginTransactionAsync();

            try
            {
                var seatAvailable = await(from seat in _context.Set <Seat>().Where(s => (SeatTypes)s.SeatTypeId == bookingModel.SeatType)
                                          join booking in _context.Set <Booking>().Where(b => b.VisitStartDate == bookingModel.VisitStartDate && b.BookingStatusId != (int)BookingStatuses.Cancelled)
                                          on seat.Id equals booking.SeatId into lj
                                          from subseat in lj.DefaultIfEmpty()
                                          where subseat == null
                                          select seat).FirstOrDefaultAsync();

                if (seatAvailable?.Id == null)
                {
                    await transaction.RollbackAsync();

                    response.IsSuccess    = false;
                    response.ErrorMessage = $"There is no seat available for the given seat type {bookingModel.SeatType} on the date {bookingModel.VisitStartDate:dd-MM-yyyy}";
                    return(response);
                }

                var bookingId = (await _context.Set <Booking>().OrderByDescending(b => b.Id).FirstOrDefaultAsync())?.Id ?? 0 + 1;

                response.BookingReference = IdGenerator.GenerateBookingReference(bookingId);
                response.CreatedDate      = DateTime.UtcNow;

                await _context.Set <Booking>().AddAsync(new Booking
                {
                    CreatedDate          = response.CreatedDate,
                    BookingReference     = response.BookingReference,
                    BookingTypeId        = (int)bookingModel.BookingType,
                    IsAcceptTsAndCs      = false,
                    IsAcceptCovidCharter = false,
                    IsNoFaceCovering     = false,
                    IsNoShow             = false,
                    SeatId          = seatAvailable.Id,
                    BookingStatusId = (int)BookingStatuses.Created,
                    VisitStartDate  = bookingModel.VisitStartDate,
                    VisitEndDate    = bookingModel.VisitEndDate,
                    LastModifiedBy  = Modified_By
                });

                await _context.SaveChangesAsync();

                await transaction.CommitAsync();
            }
            catch
            {
                await transaction.RollbackAsync();

                response.IsSuccess    = false;
                response.ErrorMessage = $"Error reserving the given seat type {bookingModel.SeatType} on the date {bookingModel.VisitStartDate:dd-MM-yyyy}";
            }
            return(response);
        }
示例#3
0
        public async Task <BookingResponseModel> NewBooking(BookingRequestModel request)
        {
            BookingResponseModel response = new BookingResponseModel();

            response.BookingReference = 12345;

            return(response);
        }
        public async Task <IActionResult> Retrieve([FromQuery] string bookingRef)
        {
            try
            {
                var booking = await this._bookingRepository.GetByBookingReferenceAsync(bookingRef);

                if (booking == null)
                {
                    return(NotFound(bookingRef));
                }

                var trip = await this._tripRepository.GetByTripReferenceAsync(booking.TripReference);

                if (trip == null)
                {
                    return(NotFound(booking.TripReference));
                }

                // Retrieve seat information for this booking from trip
                var bookedSeats = new List <Seat>();
                foreach (var seat in booking.BookedSeats)
                {
                    var tripSeat = trip.Seats.FirstOrDefault(s => s.SeatNumber == seat);
                    if (tripSeat != null)
                    {
                        bookedSeats.Add(tripSeat);
                    }
                }

                var bookingResponse = new BookingResponseModel
                {
                    BookingReference = booking.BookingReference,
                    BookingStatus    = booking.Status.ToString(),
                    FromCity         = trip.Details.FromCity,
                    ToCity           = trip.Details.ToCity,
                    DepartureTime    = trip.Details.DepartureTime,
                    ArrivalTime      = trip.Details.ArrivalTime,
                    BookedSeats      = bookedSeats.Select(s => new BookingResponseModel.Seat
                    {
                        SeatNumber   = s.SeatNumber,
                        SeatPosition = s.Position.ToString()
                    }),
                    VehicleDetails = new BookingResponseModel.Vehicle
                    {
                        TrafficServiceProvider = trip.Tsp,
                        VehicleNumber          = trip.Vin,
                        VehicleName            = trip.VehicleName
                    }
                };

                return(Ok(bookingResponse));
            }
            catch (Exception ex)
            {
                _logger.LogError("{0}", ex);
                throw;
            }
        }
        static string BuildEmailContent(BookingResponseModel bookingInfo, string instanceId)
        {
            var strBuilder = new StringBuilder($"Please confirm your booking: {bookingInfo.BookingGuid} - {bookingInfo.CarName}");

            strBuilder.Append($"<p>Thank you for your booking.</p>");
            var confirmLink = $"<a href='{Settings.BaseUrl}/api/ConfirmBooking?bookingId={instanceId}'>Confirm booking for {bookingInfo.CarName}</a>";

            //var cancelLink = $"";
            strBuilder.Append($"<p>Please click on this link to confirm your booking: {confirmLink}</p>");
            //strBuilder.Append($"If you would like to cancel the booking, please click on this link: {cancelLink}{newLine}");
            strBuilder.Append($"<p>For customer support please call us at +84 32843843849 or email us at [email protected]<p>");
            return(strBuilder.ToString());
        }
示例#6
0
        public async Task <ActionResult <BookingResponseModel> > UpdateReservedSeat([FromBody] KewBookingSeatUpdateModel model)
        {
            BookingResponseModel result = await _bookingService.UpdateSeatBookingAsync(model.BookingId, model.NewSeatId, model.Comment, model.UpdatedBy);

            if (result.IsSuccess)
            {
                return(Ok());
            }
            else
            {
                return(Conflict(result.ErrorMessage));
            }
        }
示例#7
0
        public async Task <BookingResponseModel> ConfirmBookingAsync(BookingModel bookingModel)
        {
            var response = new BookingResponseModel {
                IsSuccess = true, BookingReference = bookingModel.BookingReference
            };

            var booking = await _context.Set <Booking>().Include(b => b.Seat).FirstOrDefaultAsync(b => b.BookingReference == bookingModel.BookingReference);

            if (booking == null)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"There is no booking found for the booking reference {bookingModel.BookingReference}";
                return(response);
            }
            response.CompleteByDate = await _workingDayService.GetCompleteByDateAsync(booking.VisitStartDate);

            response.SeatNumber = booking.Seat.Number;

            _context.Attach(booking);
            booking.CompleteByDate       = response.CompleteByDate;
            booking.ReaderTicket         = bookingModel.ReaderTicket;
            booking.FirstName            = bookingModel.FirstName;
            booking.LastName             = bookingModel.LastName;
            booking.Email                = bookingModel.Email;
            booking.Phone                = bookingModel.Phone;
            booking.IsAcceptTsAndCs      = bookingModel.IsAcceptTsAndCs;
            booking.IsAcceptCovidCharter = bookingModel.IsAcceptCovidCharter;
            booking.IsNoFaceCovering     = bookingModel.IsNoFaceCovering;

            await _context.SaveChangesAsync();

            if (!string.IsNullOrWhiteSpace(bookingModel.Email))
            {
                bookingModel.SeatType       = (SeatTypes)booking.Seat.SeatTypeId;
                bookingModel.BookingType    = (BookingTypes)booking.BookingTypeId;
                bookingModel.CompleteByDate = response.CompleteByDate;
                bookingModel.SeatNumber     = response.SeatNumber;
                bookingModel.VisitStartDate = booking.VisitStartDate;
                bookingModel.OrderDocuments = new List <OrderDocumentModel>();
                await _emailService.SendEmailAsync(EmailType.ReservationConfirmation, bookingModel.Email, bookingModel);
            }
            return(response);
        }
示例#8
0
        public async Task <BookingResponseModel> UpsertDocumentsAsync(BookingModel bookingModel)
        {
            var response = new BookingResponseModel {
                IsSuccess = true, BookingReference = bookingModel.BookingReference
            };
            var booking = await _context.Set <Booking>().FirstOrDefaultAsync(b => b.BookingReference == bookingModel.BookingReference);

            if (booking == null)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"There is no booking found for the booking reference {bookingModel.BookingReference}";
                return(response);
            }

            _context.Attach(booking);
            booking.AdditionalRequirements = bookingModel.AdditionalRequirements;

            var documents = await _context.Set <OrderDocument>().Where(d => d.BookingId == booking.Id).ToListAsync();

            _context.Set <OrderDocument>().RemoveRange(documents);

            var orderDocuments = (from document in bookingModel.OrderDocuments
                                  select new OrderDocument
            {
                DocumentReference = document.DocumentReference,
                Description = document.Description,
                BookingId = booking.Id,
                LetterCode = document.LetterCode,
                ClassNumber = document.ClassNumber,
                PieceId = document.PieceId,
                PieceReference = document.PieceReference,
                SubClassNumber = document.SubClassNumber,
                ItemReference = document.ItemReference,
                Site = document.Site,
                IsReserve = document.IsReserve
            }).ToList();

            await _context.Set <OrderDocument>().AddRangeAsync(orderDocuments);

            await _context.SaveChangesAsync();

            return(response);
        }
示例#9
0
        public static async Task <Tuple <BookingResponseModel, ErrorModel> > PostBookingObjects(PostBookingObjv3 fullbookingobj)
        {
            using (HttpClientHelper client = new HttpClientHelper())
            {
                var        bookobj    = new BookingResponseModel();
                ErrorModel errorModel = null;

                await client.ProcessClientRequestAsync <BookingResponseModel>(GigUrl.CreatBookingRef, HttpMethod.Post, fullbookingobj,
                                                                              success =>
                {
                    bookobj = success;
                },
                                                                              error =>
                {
                    errorModel = error;
                }
                                                                              );

                return(new Tuple <BookingResponseModel, ErrorModel>(bookobj, errorModel));
            }
        }
示例#10
0
        public async Task <BookingResponseModel> UpdateSeatBookingAsync(int bookingId, int newSeatId, string comment, string updatedBy)
        {
            var response = new BookingResponseModel {
                IsSuccess = true
            };

            var booking = await _context.Set <Booking>().FirstOrDefaultAsync(b => b.Id == bookingId);

            if (booking == null)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"There is no booking found for the booking id {bookingId}";
                return(response);
            }

            bool seatTaken = await _context.Set <Booking>().Where(b => b.VisitStartDate == booking.VisitStartDate && b.SeatId == newSeatId && b.Id != bookingId).AnyAsync();

            if (seatTaken)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"The requested seat is not available on {booking.VisitStartDate:dd-MM-yyyy}";
                return(response);
            }

            _context.Attach(booking);
            if (!String.IsNullOrWhiteSpace(booking.Comments))
            {
                booking.Comments += " " + comment;
            }
            else
            {
                booking.Comments = comment;
            }
            booking.SeatId         = newSeatId;
            booking.LastModifiedBy = updatedBy;

            await _context.SaveChangesAsync();

            return(response);
        }
示例#11
0
        public async Task <BookingResponseModel> UpdateSeatBookingAsync(int bookingId, int newSeatId, string comment, string updatedBy)
        {
            var response = new BookingResponseModel {
                IsSuccess = true
            };

            var booking = await _context.Set <Booking>().FirstOrDefaultAsync(b => b.Id == bookingId);

            if (booking == null)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"There is no booking found for the booking id {bookingId}";
                return(response);
            }

            // First pass check that the seat is available.
            bool seatTaken = await _context.Set <Booking>().Where(b => b.VisitStartDate == booking.VisitStartDate && b.SeatId == newSeatId &&
                                                                  b.BookingStatus.Id != (int)BookingStatuses.Cancelled && b.Id != bookingId).AnyAsync();

            if (seatTaken)
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"The requested seat is not available on {booking.VisitStartDate:dd-MM-yyyy}";
                return(response);
            }

            try
            {
                await _context.Database.ExecuteSqlInterpolatedAsync($"EXEC dbo.proc_change_booked_seat {bookingId}, {newSeatId}, {comment}, {updatedBy}");
            }
            catch
            {
                response.IsSuccess    = false;
                response.ErrorMessage = $"Error updating booking id {bookingId} on the date {booking.VisitStartDate:dd-MM-yyyy} to seat id {newSeatId}";
            }

            return(response);
        }
示例#12
0
        public JsonResult Post([FromBody] BookingRequestModel bookRQ)
        {
            BookingResponseModel bookRS = new BookingResponseModel();

            Website.Instance.logger.Info($"Gateway Router Start! KKday PkgOid:{bookRQ.order.packageOid},OrderMid:{bookRQ.order.orderMid}");

            string result = "";

            //https不需驗證
            HttpClientHandler handler = new HttpClientHandler();

            handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            handler.ServerCertificateCustomValidationCallback =
                (httpRequestMessage, cert, cetChain, policyErrors) =>
            {
                return(true);
            };

            HttpClient client = new HttpClient(handler);

            client.DefaultRequestHeaders.Accept.Add(
                new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

            try
            {
                //套餐與供應上API分流
                var xdoc = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "//App_Data//RouteMapping.xml");
                if (xdoc.Descendants("item").Where(x => x.Element("kkday_pkg_oid").Value.Contains(bookRQ.order.packageOid)).Count() <= 0)
                {
                    Metadata metadata = new Metadata();
                    metadata.status      = "JTR-10002";
                    metadata.description = $"此套餐編號找不到串接的供應商,且不再即訂即付的商品項目中";
                    bookRS.metadata      = metadata;

                    return(Json(bookRS));
                }

                string sup = xdoc.Descendants("item").Where(x => x.Element("kkday_pkg_oid").Value.Contains(bookRQ.order.packageOid)).
                             Select(x => x.Element("sup").Value).FirstOrDefault().ToString();
                string sup_url = Website.Instance.Configuration[$"{sup}:BOOK_URL"];
                string sup_id  = Website.Instance.Configuration[$"{sup}:SUP_ID"];
                string sup_key = Website.Instance.Configuration[$"{sup}:SUP_KEY"];


                bookRQ.sup_id  = sup_id;
                bookRQ.sup_key = sup_key;

                string json = JsonConvert.SerializeObject(bookRQ);

                var contentData = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
                HttpResponseMessage response = client.PostAsync(sup_url, contentData).Result;

                Website.Instance.logger.Info($"Supplier:{sup},Booking URL:{sup_url},URL Response StatusCode:{response.StatusCode}");

                //與API串接失敗
                if (response.StatusCode.ToString() != "OK")
                {
                    throw new Exception(response.Content.ReadAsStringAsync().Result);
                }

                result = response.Content.ReadAsStringAsync().Result;
                bookRS = JsonConvert.DeserializeObject <BookingResponseModel>(result);
            }
            catch (Exception ex)
            {
                Metadata metadata = new Metadata();
                metadata.status      = "JTR-10002";
                metadata.description = $"Gateway Error :{ex.Message}";
                bookRS.metadata      = metadata;

                Website.Instance.logger.Fatal($"Gateway Error :{ex.Message},{ex.StackTrace}");
            }

            //回傳真正的JSON格式
            return(Json(bookRS));
        }
        public async Task <IActionResult> Confirm([FromBody] string bookingRef)
        {
            try
            {
                var booking = await this._bookingRepository.GetByBookingReferenceAsync(bookingRef);

                if (booking == null)
                {
                    return(NotFound(bookingRef));
                }

                // Verify booking status
                switch (booking.Status)
                {
                case BookingStatus.Cancelled:
                {
                    return(StatusCode(ErrorCodes.BOOKING_ALREADY_CANCELLED, nameof(ErrorCodes.BOOKING_ALREADY_CANCELLED)));
                }

                case BookingStatus.Completed:
                {
                    return(StatusCode(ErrorCodes.BOOKING_ALREADY_COMPLETED, nameof(ErrorCodes.BOOKING_ALREADY_COMPLETED)));
                }
                }

                var trip = await this._tripRepository.GetByTripReferenceAsync(booking.TripReference);

                if (trip == null)
                {
                    return(NotFound(booking.TripReference));
                }

                // Verify trip status
                switch (trip.Status)
                {
                case TripStatus.Started:
                {
                    return(StatusCode(ErrorCodes.TRIP_ALREADY_STARTED, nameof(ErrorCodes.TRIP_ALREADY_STARTED)));
                }

                case TripStatus.Completed:
                {
                    return(StatusCode(ErrorCodes.TRIP_ALREADY_COMPLETED, nameof(ErrorCodes.TRIP_ALREADY_COMPLETED)));
                }

                case TripStatus.Cancelled:
                {
                    return(StatusCode(ErrorCodes.TRIP_ALREADY_CANCELLED, nameof(ErrorCodes.TRIP_ALREADY_CANCELLED)));
                }
                }

                // Confirm booking status
                await this._bookingRepository.ConfirmAsync(booking);

                // Update trip seat status of confirmed booking to booked
                var bookedSeats = new List <Seat>();
                foreach (var seat in booking.BookedSeats)
                {
                    var tripSeat = trip.Seats.FirstOrDefault(s => s.SeatNumber == seat);
                    if (tripSeat != null)
                    {
                        tripSeat.Status = SeatStatus.Booked;
                        bookedSeats.Add(tripSeat);
                    }
                }

                await _tripRepository.UpdateAsync(trip);

                // Return confirmed booking response
                var bookingResponse = new BookingResponseModel
                {
                    BookingReference = booking.BookingReference,
                    FromCity         = trip.Details.FromCity,
                    ToCity           = trip.Details.ToCity,
                    DepartureTime    = trip.Details.DepartureTime,
                    ArrivalTime      = trip.Details.ArrivalTime,
                    BookingStatus    = BookingStatus.Completed.ToString(),
                    BookedSeats      = bookedSeats.Select(s => new BookingResponseModel.Seat
                    {
                        SeatNumber   = s.SeatNumber,
                        SeatPosition = s.Position.ToString()
                    }),
                    VehicleDetails = new BookingResponseModel.Vehicle
                    {
                        TrafficServiceProvider = trip.Tsp,
                        VehicleNumber          = trip.Vin,
                        VehicleName            = trip.VehicleName
                    }
                };
                return(Ok(bookingResponse));
            }
            catch (Exception ex)
            {
                _logger.LogError("{0}", ex);
                throw;
            }
        }
示例#14
0
        public async Task <BookingResponseModel> CreateMultiDayBookingAsync(BookingModelMultiDay multiDayBooking)
        {
            var response = new BookingResponseModel {
                IsSuccess = true
            };

            using var transaction = await _context.Database.BeginTransactionAsync(System.Data.IsolationLevel.RepeatableRead);

            try
            {
                var completeByDate = await _workingDayService.GetCompleteByDateAsync(multiDayBooking.VisitStartDate);

                var bookingId = (await _context.Set <Booking>().OrderByDescending(b => b.Id).FirstOrDefaultAsync())?.Id ?? 0 + 1;

                response.BookingReference = IdGenerator.GenerateBookingReference(bookingId);
                response.CreatedDate      = DateTime.UtcNow;

                var booking = new Booking()
                {
                    CreatedDate          = response.CreatedDate,
                    CompleteByDate       = completeByDate,
                    BookingReference     = response.BookingReference,
                    BookingTypeId        = (int)BookingTypes.StandardOrderVisit,
                    ReaderTicket         = multiDayBooking.ReaderTicket,
                    FirstName            = multiDayBooking.FirstName,
                    LastName             = multiDayBooking.LastName,
                    Email                = multiDayBooking.Email,
                    IsAcceptTsAndCs      = true,
                    IsAcceptCovidCharter = true,
                    IsNoFaceCovering     = false,
                    IsNoShow             = false,
                    SeatId               = multiDayBooking.SeatId,
                    BookingStatusId      = (int)BookingStatuses.Submitted,
                    VisitStartDate       = multiDayBooking.VisitStartDate,
                    VisitEndDate         = multiDayBooking.VisitEndDate,
                    LastModifiedBy       = Modified_By
                };

                var bookingModel = new BookingModel()
                {
                    BookingReference     = booking.BookingReference,
                    BookingType          = BookingTypes.StandardOrderVisit,
                    ReaderTicket         = booking.ReaderTicket,
                    VisitStartDate       = booking.VisitStartDate,
                    VisitEndDate         = booking.VisitEndDate,
                    CreatedDate          = booking.CreatedDate,
                    CompleteByDate       = booking.CompleteByDate,
                    FirstName            = booking.FirstName,
                    LastName             = booking.LastName,
                    Email                = booking.Email,
                    IsAcceptTsAndCs      = true,
                    IsAcceptCovidCharter = true,
                    IsNoFaceCovering     = false,
                    IsNoShow             = false,
                    SeatId               = booking.SeatId,
                    BookingStatus        = BookingStatuses.Submitted,
                    OrderDocuments       = new List <OrderDocumentModel>(),
                    LastModifiedBy       = Modified_By
                };

                await _context.Set <Booking>().AddAsync(booking);

                // Check that the seat booked in the back office application is still available.
                List <SeatModel> availableSeats = await _availabilityService.GetAvailabileSeatsForMultiDayVisitAsync(booking.VisitStartDate, booking.VisitEndDate, true);

                SeatModel selectedSeat = availableSeats.SingleOrDefault(s => s.Id == booking.SeatId);
                if (selectedSeat == null)
                {
                    throw new Exception($"Error creating booking for user {booking.FirstName} {booking.LastName}, email {booking.Email} fromm the Back Office.  The requested seat id {booking.SeatId} is no longer available for the date range {booking.VisitStartDate} to {booking.VisitEndDate}.");
                }

                await _context.SaveChangesAsync();

                await transaction.CommitAsync();

                await _emailService.SendEmailAsync(EmailType.BookingConfirmation, multiDayBooking.Email, bookingModel);
            }
            catch (Exception)
            {
                await transaction?.RollbackAsync();

                response.IsSuccess    = false;
                response.ErrorMessage = "Error creating multi day booking";
            }

            return(response);
        }
示例#15
0
        public BookingResponseModel Booking([FromBody] BookingRequestModel bookRQ)
        {
            Website.Instance.logger.Info($"JTR Booking Start!");

            BookingResponseModel bookRS   = new BookingResponseModel();
            Metadata             metadata = new Metadata();
            Data data = new Data();

            List <Mappinginfo> info = new List <Mappinginfo>();

            try
            {
                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Accept.Add(
                    new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));


                //I.Prod的Mapping
                //bookRQ.pkg_oid+價格別(bookRQ.Price1Qty) 找出訂購JTR的商編
                string jtr_prod_no = "";

                try
                {
                    var xdoc = XDocument.Load(System.AppDomain.CurrentDomain.BaseDirectory + "//App_Data//ProdMapping.xml");
                    if (bookRQ.order.price1Qty > 0)
                    {
                        if (xdoc.Descendants("item").Where(x => x.Element("kkday_prod_pkg").Value.Contains(bookRQ.order.packageOid) && x.Element("kkday_price_type").Value.Equals("price1")).Count() <= 0)
                        {
                            throw new Exception("此套餐編號找不到相對應JTR產編,請與BD確認產編再請it修改");
                        }


                        jtr_prod_no = xdoc.Descendants("item").Where(x => x.Element("kkday_prod_pkg").Value.Equals(bookRQ.order.packageOid) && x.Element("kkday_price_type").Value.Equals("price1")).
                                      Select(x => x.Element("jtr_prod_no").Value).FirstOrDefault().ToString();

                        info.Add(new Mappinginfo()
                        {
                            price_type  = "price1",
                            qty         = bookRQ.order.price1Qty,
                            jtr_prod_no = jtr_prod_no//"10457115"//
                        });
                    }
                    if (bookRQ.order.price2Qty > 0)
                    {
                        if (xdoc.Descendants("item").Where(x => x.Element("kkday_prod_pkg").Value.Contains(bookRQ.order.packageOid) && x.Element("kkday_price_type").Value.Equals("price2")).Count() <= 0)
                        {
                            throw new Exception("此套餐編號找不到相對應JTR產編,請與BD確認產編再請it修改");
                        }

                        jtr_prod_no = xdoc.Descendants("item").Where(x => x.Element("kkday_prod_pkg").Value.Equals(bookRQ.order.packageOid) && x.Element("kkday_price_type").Value.Equals("price2")).
                                      Select(x => x.Element("jtr_prod_no").Value).FirstOrDefault().ToString();

                        info.Add(new Mappinginfo()
                        {
                            price_type  = "price2",
                            qty         = bookRQ.order.price2Qty,
                            jtr_prod_no = jtr_prod_no//"10457115"//
                        });
                    }
                    if (bookRQ.order.price3Qty > 0 || bookRQ.order.price4Qty > 0)
                    {
                        throw new Exception("旅客購買的套餐身份別(老人,嬰兒)不在即訂即付的約定內");
                    }
                }
                catch (Exception ex)
                {
                    metadata.status      = $"JTR-10002";
                    metadata.description = $"{ex.Message}";
                    bookRS.metadata      = metadata;
                    Website.Instance.logger.FatalFormat($"Mapping Error :{ex.Message},{ex.StackTrace}");
                    return(bookRS);
                }


                pay_result   payRS   = new pay_result();
                order_result orderRS = new order_result();

                List <JtrRsinfo> RS_info = new List <JtrRsinfo>();
                List <Orderinfo> OD_info = new List <Orderinfo>();

                int qty = 1;

                try
                {
                    //II.依照jtr_prod_no數量 呼叫JTR order API 及 pay API
                    foreach (var lst in info)
                    {
                        //訂單資訊!!因商品結構單純 放必須值即可 link_man 為旅客代表人orderCusList得第一位
                        order jtrorder = new order()
                        {
                            info_id         = lst.jtr_prod_no ?? string.Empty,
                            cust_id         = bookRQ.sup_id ?? string.Empty,
                            order_source_id = info.Count() > 1 ? $"{bookRQ.order.orderMid}-{qty.ToString()}" : bookRQ.order.orderMid,
                            travel_date     = bookRQ.order.begLstGoDt,
                            num             = lst.qty,
                            link_man        = bookRQ.order.orderCusList[0].cusFirstname.ToUpper() + bookRQ.order.orderCusList[0].cusLastname.ToUpper(),
                            link_phone      = string.Empty,
                            link_email      = Website.Instance.Configuration["CONTENT_EMAIL"] ?? "*****@*****.**"
                        };

                        //需replace成UTF-8不然會有error
                        string orderRSxmlData = XMLTool.XMLSerialize(jtrorder).Replace("utf-16", "utf-8").Replace("utf - 16", "utf - 8");


                        string orderUrl = $"{Website.Instance.Configuration["JTR_API_URL:ORDER_URL"]}?custId={bookRQ.sup_id}&apikey={bookRQ.sup_key}&param={orderRSxmlData}".Replace("\n", "");
                        HttpResponseMessage orderResponse = client.GetAsync(orderUrl).Result;
                        Website.Instance.logger.Info($"URL:{Website.Instance.Configuration["JTR_API_URL:ORDER_URL"]},URL Response StatusCode:{orderResponse.StatusCode}");
                        orderRS = (order_result)XMLTool.XMLDeSerialize(orderResponse.Content.ReadAsStringAsync().Result, orderRS.GetType().ToString());

                        Website.Instance.logger.Info($"[ORDER]kkOrderNo:{bookRQ.order.orderMid},priceType:{lst.price_type},jtrOrderNo:{orderRS.order_id},jtrErr:{orderRS.error_msg}");

                        string payUrl = $"{Website.Instance.Configuration["JTR_API_URL:PAY_URL"]}?custId={bookRQ.sup_id}&apikey={bookRQ.sup_key}&orderId={orderRS.order_id}";
                        HttpResponseMessage payRresponse = client.GetAsync(payUrl).Result;
                        Website.Instance.logger.Info($"URL:{Website.Instance.Configuration["JTR_API_URL:PAY_URL"]},URL Response StatusCode:{payRresponse.StatusCode}");

                        payRS = (pay_result)XMLTool.XMLDeSerialize(payRresponse.Content.ReadAsStringAsync().Result, payRS.GetType().ToString());

                        Website.Instance.logger.Info($"[PAY]kkOrderNo:{bookRQ.order.orderMid},priceType:{lst.price_type},jtrTktNo:{payRS.code},jtrErr:{payRS.error_msg}");


                        RS_info.Add(
                            new JtrRsinfo()
                        {
                            kkOrder_no   = jtrorder.order_source_id,
                            kkprice_type = lst.price_type,
                            kkprice_qty  = lst.qty,

                            order_id          = orderRS.order_id ?? string.Empty,
                            order_error_msg   = orderRS.error_msg ?? string.Empty,
                            order_error_state = orderRS.error_state ?? string.Empty,

                            code            = payRS.code ?? string.Empty,
                            pay_error_msg   = payRS.error_msg ?? string.Empty,
                            pay_error_state = payRS.error_state ?? string.Empty
                        });

                        //RS 狀況一
                        //第一筆 訂單成立/付款失敗 直接跳出迴圈
                        if (qty == 1 && (payRS.error_state != "10000" || string.IsNullOrEmpty(payRS.code) || orderRS.error_state != "10000" || string.IsNullOrEmpty(orderRS.order_id)))
                        {
                            break;
                        }


                        qty++;
                    }

                    //RS 判斷Mapping
                    //result = "OK","OrdErr","PayErr","NoTicket"
                    foreach (var rs in RS_info)
                    {
                        data.isMuiltSupOrder  = info.Count() > 1 ? true : false;
                        data.supTicketNumber += !string.IsNullOrEmpty(rs.code) ? rs.code + "<br/>" : "";


                        OD_info.Add(new Orderinfo()
                        {
                            priceType    = rs.kkprice_type,
                            qty          = rs.kkprice_qty,
                            kkOrderNo    = rs.kkOrder_no,
                            ticketNumber = rs.code,
                            result       = !string.IsNullOrEmpty(rs.code) && rs.order_error_state == "10000" && rs.pay_error_state == "10000" ? "OK" :
                                           string.IsNullOrEmpty(rs.code) && rs.order_error_state != "10000" && rs.pay_error_state != "10000" ? "OrdErr" :
                                           string.IsNullOrEmpty(rs.code) && rs.order_error_state == "10000" && rs.pay_error_state != "10000" ? "PayErr" :
                                           string.IsNullOrEmpty(rs.code) && rs.order_error_state == "10000" && rs.pay_error_state == "10000" ? "NoTicket" : string.Empty
                        });
                    }

                    data.orderinfo = OD_info;
                    bookRS.data    = data;

                    //metadata status 跟 描述 mapping
                    //order error
                    string code = "", note = "";

                    if (OD_info.AsEnumerable().Any(x => x.result.Contains("OrdErr")))
                    {
                        //多筆
                        if (data.isMuiltSupOrder && OD_info.Count() > 1)
                        {
                            code = RS_info[1].order_error_state;
                            note = $"1對多訂單類型,其中第1筆 {RS_info[0].order_id}支付成功,{RS_info[0].code},但第2筆成立訂單失敗,請OP至JTR後台協助確認";
                        }
                        else if (data.isMuiltSupOrder && OD_info.Count() == 1)
                        {
                            code = RS_info[0].order_error_state;
                            note = $"1對多訂單類型,下單失敗,{RS_info[0].order_error_msg}";
                        }
                        else
                        {
                            code = RS_info[0].order_error_state;
                            note = RS_info[0].order_error_msg;
                        }
                    }
                    else if (OD_info.AsEnumerable().Any(x => x.result.Contains("PayErr")))
                    {
                        //多筆
                        if (data.isMuiltSupOrder && OD_info.Count() > 1)
                        {
                            code = RS_info[1].pay_error_state;
                            note = $"1對多訂單類型,其中第1筆{RS_info[0].order_id},{RS_info[0].code},但第2筆{RS_info[1].order_id},{RS_info[1].pay_error_msg},請OP至JTR後台協助確認";
                        }
                        else if (data.isMuiltSupOrder && OD_info.Count() > 1)
                        {
                            code = RS_info[0].pay_error_state;
                            note = $"1對多訂單類型,第1筆{RS_info[0].order_id}支付失敗,{RS_info[0].pay_error_msg},請確認訂單其他細項是否完成";
                        }
                        else
                        {
                            code = RS_info[0].pay_error_state;
                            note = $"{RS_info[0].order_id}支付失敗,{RS_info[0].pay_error_msg}";
                        }
                    }
                    else if (OD_info.AsEnumerable().Any(x => x.result.Contains("NoTicket")))
                    {
                        //多筆
                        if (data.isMuiltSupOrder && OD_info.Count() > 1)
                        {
                            code = "10091";
                            note = $"1對多訂單類型,其中第1筆{RS_info[0].order_id}交易支付成功{RS_info[0].code},但第2筆{RS_info[1].order_id}支付成功未取得12碼供應商訂編,請OP至JTR後台協助確認";
                        }
                        else
                        {
                            code = "10091";
                            note = $"{RS_info[0].order_id}支付成功,但未取得12碼供應商訂編,請OP至JTR後台協助確認";
                        }
                    }
                    else
                    {
                        code = RS_info[0].pay_error_state;
                        note = RS_info[0].pay_error_msg;
                    }


                    metadata.status      = $"JTR-{code}";
                    metadata.description = note;

                    bookRS.metadata = metadata;
                }
                catch (Exception ex)
                {
                    //與JTR API串接
                    Website.Instance.logger.FatalFormat($"JTR Connect Error :{ex.Message},{ex.StackTrace}");
                    throw ex;
                }
            }
            catch (TimeoutException timeoutex)
            {
                metadata.status      = $"JTR-10090";
                metadata.description = timeoutex.Message;
                bookRS.metadata      = metadata;
                Website.Instance.logger.FatalFormat($"Timeout Error :{timeoutex.Message},{timeoutex.StackTrace}");
                return(bookRS);
            }
            catch (Exception ex)
            {
                metadata.status      = $"JTR-00000";
                metadata.description = $"System Error :{ex.Message}";
                bookRS.metadata      = metadata;
                Website.Instance.logger.FatalFormat($"System Error :{ex.Message},{ex.StackTrace}");
                return(bookRS);
            }

            return(bookRS);
        }