package com.mgm.mcrm.player.services; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import com.google.gson.Gson; import com.mgm.mcrm.appsetting.models.CfgSettings; import com.mgm.mcrm.appsetting.services.SettingService; import com.mgm.mcrm.appsetting.services.SysSettingService; import com.mgm.mcrm.authorization.dtos.LoginUserInfo; import com.mgm.mcrm.basesetting.daylight.dtos.response.ReservationDoorKeyResponse; import com.mgm.mcrm.basesetting.daylight.dtos.response.ReservationQueueResponse; import com.mgm.mcrm.basesetting.daylight.services.DaylightApiService; import com.mgm.mcrm.basesetting.property.models.CfgProperties; import com.mgm.mcrm.basesetting.property.repositories.PropertyDao; import com.mgm.mcrm.basesetting.room.models.CfgOtherRoomStatus; import com.mgm.mcrm.basesetting.room.repositories.OtherRoomStatusDao; import com.mgm.mcrm.basesetting.room.services.OtherRoomStatusService; import com.mgm.mcrm.booking.controllers.BookingController; import com.mgm.mcrm.booking.dtos.BookingDto; import com.mgm.mcrm.booking.dtos.opera.CancelBookingRequest; import com.mgm.mcrm.booking.dtos.opera.FetchBookingRequest; import com.mgm.mcrm.booking.dtos.opera.GuestRequestsRequest; import com.mgm.mcrm.booking.dtos.opera.ModifyBookingRequest; import com.mgm.mcrm.booking.mappers.BookingMapper; import com.mgm.mcrm.booking.models.Bookings; import com.mgm.mcrm.booking.models.BookingsView; import com.mgm.mcrm.booking.repositories.BookingDao; import com.mgm.mcrm.booking.repositories.BookingViewDao; import com.mgm.mcrm.booking.services.*; import com.mgm.mcrm.common.constants.SysCommon; import com.mgm.mcrm.common.constants.SysConstants; import com.mgm.mcrm.common.dtos.BaseApiResponse; import com.mgm.mcrm.common.dtos.http_util.HttpResponseResult; import com.mgm.mcrm.common.dtos.mgm_api.*; import com.mgm.mcrm.common.services.HttpService; import com.mgm.mcrm.common.services.MGMEsbApiService; import com.mgm.mcrm.common.utils.DateTimeUtil; import com.mgm.mcrm.common.utils.LogUtil; import com.mgm.mcrm.logging.models.SysLogBooking; import com.mgm.mcrm.logging.services.SysLogBookingService; import com.mgm.mcrm.notification.models.Email; import com.mgm.mcrm.notification.repositories.EmailDao; import com.mgm.mcrm.notification.services.SendEmailService; import com.mgm.mcrm.player.dtos.request.EtaRecordInfo; import com.mgm.mcrm.player.dtos.request.TodoCancelBookingRequest; import com.mgm.mcrm.player.dtos.request.TodoChangeDateRequest; import com.mgm.mcrm.player.dtos.response.GetDashboardResponse; import com.mgm.mcrm.player.dtos.response.GetTodoDetailResponse; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Strings; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.TimeUnit; @Slf4j @Service public class TodoService { @Resource private MGMEsbApiService mgmEsbApiService; @Resource private SysSettingService sysSettingService; @Resource private OperaDBBookingService operaDBBookingService; @Resource private BookingDao bookingDao; @Resource private BookingViewDao bookingViewDao; @Resource private PropertyDao propertyDao; @Resource private OtherRoomStatusDao otherRoomStatusDao; @Resource OperaService operaService; @Resource private NonMGMBookingService otherBookingService; @Resource private SettingService settingService; @Resource private EmailDao emailDao; @Resource private OtherRoomStatusService otherRoomStatusService; @Resource private SysLogBookingService sysLogBookingService; @Resource private OtherRoomStatusDao roomStatusDao; @Resource private WaitlistBookingService waitlistBookingService; @Resource private PlayerService playerService; @Resource private HttpService httpService; @Resource private BookingService bookingService; @Resource private DaylightApiService dlService; @Resource private BookingMapper bookingMapper; @Resource private SendEmailService sendEmailService; public GetDashboardResponse getTodoDashboard(String userId) throws Exception { GetDashboardResponse result = new GetDashboardResponse(); try { HttpResponseResult httpResult = mgmEsbApiService.invokeGetTodoDashboard(userId, 0); try { TodoDashboardResult resultObj = JSONObject.parseObject(httpResult.getResponseContent(), TodoDashboardResult.class, Feature.SupportNonPublicField, Feature.IgnoreNotMatch); if (Strings.CI.equals(resultObj.getStatusCode(), "OK")) { result.setSuccess(true); result.setReturnData(resultObj); } else { result.setSuccess(false); result.setErrorCode(resultObj.getStatusDescription()); LogUtil.info(TodoService.class, "[GetDashboardData Error]" + resultObj.getStatusDescription()); } } catch (Exception err) { result.setSuccess(false); result.setErrorCode("RETURN_DATA_ERROR"); LogUtil.info(TodoService.class, "[GetDashboardData Error]" + err.getMessage()); } } catch (Exception err) { result.setSuccess(false); result.setErrorCode("INVOKE_TODODASHBOARD_API_ERROR"); LogUtil.info(TodoService.class, "[GetDashboardData Error]" + err.getMessage()); } return result; } public GetTodoDetailResponse getTodoDetail(String playerId, String todoCategory, String todoSegment, String date) throws Exception { GetTodoDetailResponse result = new GetTodoDetailResponse(); try { HttpResponseResult httpResult = mgmEsbApiService.invokeGetTodoDetail(playerId, todoCategory, todoSegment, date, 1); try { TodoDetailResult resultObj = JSONObject.parseObject(httpResult.getResponseContent(), TodoDetailResult.class, Feature.SupportNonPublicField, Feature.IgnoreNotMatch); if (Strings.CI.equals(resultObj.getStatusCode(), "OK")) { if (resultObj.getDescriptions() != null) { for (TodoDetailDescription detailRecord : resultObj.getDescriptions()) { if ("Room".equalsIgnoreCase(detailRecord.getItemRecordType())) { String recordDesc = detailRecord.getItemRecordDescription(); if (StringUtils.isNotBlank(recordDesc)) { String confNum = null; int index = recordDesc.indexOf("Conf#"); if (index != -1) { String sub = recordDesc.substring(index + 5); int pipeIndex = sub.indexOf("|"); if (pipeIndex != -1) { confNum = sub.substring(0, pipeIndex).trim(); } else { confNum = sub.trim(); } } if (StringUtils.isNotBlank(confNum)) { if ("Inhouse".equalsIgnoreCase(todoCategory) || "Arrival".equalsIgnoreCase(todoCategory)) { Bookings bookings = bookingDao.findFirstByConfirmationNoAndPropertyIdIsNotNull(confNum); if (Objects.nonNull(bookings)) { CfgProperties property = propertyDao.findById(bookings.getPropertyId()).orElse(null); if (Objects.nonNull(property)) { if ("Inhouse".equalsIgnoreCase(todoCategory)) { // Parse checkinDate from recordDesc (e.g., "Jun 25 – Jul 1 ...") LocalDate ciDate = null; try { String ciDatePart = recordDesc.split("–")[0].trim(); // Use the year from the 'date' parameter int year = Integer.parseInt(date.substring(0, 4)); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM d yyyy", Locale.US); ciDate = LocalDate.parse(ciDatePart + " " + year, formatter); } catch (Exception e) { LogUtil.warn(TodoService.class, "Parse checkinDate error: " + e.getMessage() + ", recordDesc: " + recordDesc); } if (ciDate != null) { LocalDate today = LocalDate.now(); if (ciDate.isAfter(today)) { // 当checkindate大于今天不用拿room number 和room ready continue; } BaseApiResponse doorKeyResult = dlService.getReservationDoorKeyByConfirmationNumber(property.getDlPropertyId(), confNum); ReservationDoorKeyResponse doorKeyData = doorKeyResult.getData(); if (doorKeyResult.isSuccess() && doorKeyData != null) { String replaceStr = "Conf#" + confNum; if (StringUtils.isNotBlank(doorKeyData.getRoomNumber())) { detailRecord.setRoomNumber(doorKeyData.getRoomNumber()); replaceStr += " [Rm #" + doorKeyData.getRoomNumber() + "]"; } if (ciDate.isEqual(today)) { // 当今天的时候要检查room ready boolean isRoomReady = StringUtils.isNotBlank(doorKeyData.getId()) && !doorKeyData.isHasKey(); if (isRoomReady) { replaceStr += " [Rm Ready]"; } } if (!replaceStr.equals("Conf#" + confNum)) { detailRecord.setItemRecordDescription(recordDesc.replace("Conf#" + confNum, replaceStr)); } } } }else{ BaseApiResponse queueResult = dlService.getReservationQueueByConfirmationNumber(property.getDlPropertyId(), confNum); ReservationQueueResponse queueData = queueResult.getData(); boolean isQueue = queueResult.isSuccess() && queueData != null && queueData.isQueue(); if (isQueue) { detailRecord.setItemRecordDescription(recordDesc.replace("Conf#" + confNum, "Conf#" + confNum + " [In Queue]")); } } } } else { // result.setSuccess(false); // result.setErrorCode("BOOKING NOT FOUND"); // result.setErrorMessage("BOOKING NOT FOUND"); // LogUtil.warn(TodoService.class, "[GetTodoDetail] BOOKING NOT FOUND"); // return result; } } } } } } } result.setSuccess(true); result.setReturnData(resultObj); } else { result.setSuccess(false); result.setErrorCode(resultObj.getStatusDescription()); } } catch (Exception err) { result.setSuccess(false); result.setErrorCode("RETURN_DATA_ERROR"); LogUtil.info(TodoService.class, "[GetTodoDetail Error]" + err.getMessage()); } } catch (Exception err) { result.setSuccess(false); result.setErrorCode("INVOKE_TODOLISTDETAIL_API_ERROR"); LogUtil.info(TodoService.class, "[GetTodoDetail Error]" + err.getMessage()); } return result; } public BaseApiResponse cancelBooking(TodoCancelBookingRequest param, HttpServletRequest request) throws Exception { BaseApiResponse processResult= new BaseApiResponse<>(); Long bookId = param.getId(); String oStatus = ""; if (bookId == null) { processResult.setSuccess(false); processResult.setMessage("No Booking Id."); processResult.setData(param); return processResult; } Gson gson = new Gson(); BookingsView bookingView = bookingViewDao.findById(bookId).orElse(null); boolean isMock =sysSettingService.isMockReplicate(); String userId = param.getUserId(); String userName = param.getUserName(); String category = bookingView.getPropertyCategory(); boolean isOpera = Strings.CS.equals("OPERA", category); boolean isDaylight = Strings.CS.equals("DAYLIGHT", category); boolean isOther = Strings.CS.equals("OTHER", category); CfgProperties property = propertyDao.findByNameAndCategory(param.getPropertyName(), category); String dlReservationId = null; if (Strings.CS.equals(category,"DAYLIGHT")) { dlReservationId = param.getDlReservationId(); } if (isOther) { // CancelOtherBooking Flow // 获取setting表Cancel状态和时间区间 CfgSettings enAbleCancel = settingService.getSettingByKey("CAN_CANCEL_OTHERBOOKING"); // 判断状态是否启用 if(Strings.CS.equals(enAbleCancel.getKeyValues(), "1")) { // 方法启用(==1),判断时间 // 状态启用判断现在时间是否再时间区间内 if(isPassTimeNow()) { //Cancel Non MGM Booking Bookings obooking = cancelOtherBooking(bookId,request); if(obooking != null) { processResult.setSuccess(true); processResult.setData(bookingView); }else { processResult.setSuccess(false); processResult.setCode("SYSTEM_ERROR"); processResult.setMessage("System error"); } }else { processResult.setSuccess(false); processResult.setCode("ERR_CANCEL_TIME"); processResult.setData(param); } }else{ // 如果enAbleCancel方法没有启用(==0)直接cancelbooking //Cancel Non MGM Booking Bookings obooking = cancelOtherBooking(bookId,request); if(obooking != null) { processResult.setSuccess(true); processResult.setData(bookingView); }else { processResult.setSuccess(false); processResult.setCode("SYSTEM_ERROR"); processResult.setMessage("System error"); } } return processResult; } // 如果是模拟数据 if(isMock) { Bookings booking = bookingDao.findById(bookId).orElse(null); booking.setApproveStatus("C"); booking.setLastOperaStatus("CANCELED"); booking.setChangeCheckinDate(null); booking.setChangeCheckoutDate(null); bookingDao.save(booking); processResult.setSuccess(true); processResult.setData(booking); TimeUnit.SECONDS.sleep(1L); if (isDaylight) { dlService.daylightCancelReservationNew( dlReservationId, property.getDlPropertyId(), param.getDlSharerIds(), param.getDlVersion() ); } return processResult; } if (isDaylight) { Date newDate = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"); Bookings booking = bookingDao.findById(bookId).orElse(null); booking.setApproveStatus("C"); booking.setLastOperaStatus("CANCELED"); booking.setCancelledBy(userId); booking.setCancelledAt(newDate); booking.setUpdatedAt(newDate); booking.setUpdatedBy(userId); bookingDao.save(booking); BaseApiResponse cancelResult = dlService.daylightCancelReservationNew( dlReservationId, property.getDlPropertyId(), param.getDlSharerIds(), param.getDlVersion() ); if (cancelResult.isSuccess()) { LogUtil.info(TodoService.class, "[Cancel Booking] Cancel Success, bookingId=" + bookId); processResult.setSuccess(true); processResult.setData(dlReservationId); }else { LogUtil.warn(TodoService.class, "[Cancel Booking] Cancel Fail"); booking.setUpdatedAt(newDate); booking.setCreatedAt(newDate); booking.setApproveStatus("F"); booking.setErrorMessage("Call Daylight CANCEL_RESERVATION fail,Fail reason: "+cancelResult.getMessage()); bookingDao.save(booking); processResult.setSuccess(false); processResult.setData(cancelResult.getMessage()); } return processResult; } if (isOpera) { boolean hasShare = false; List shareConfList = new ArrayList(); JSONObject fetchResponse = new JSONObject(); FetchBookingRequest owsReq = new FetchBookingRequest(); owsReq.setConfirmationNo(bookingView.getConfirmationNo()); fetchResponse = operaService.fetchBooking(owsReq); if(fetchResponse.containsKey("shareConfList")) { shareConfList = (List) fetchResponse.get("shareConfList"); hasShare = true; } CancelBookingRequest cancelRequest = new CancelBookingRequest(); JSONObject cancelResponse = new JSONObject(); cancelRequest.setHotelCode(bookingView.getHotelCode()); cancelRequest.setConfirmationNo(bookingView.getConfirmationNo()); LogUtil.info(BookingController.class, "[cancelBooking] cancelRequest begin" + gson.toJson(cancelRequest)); cancelResponse = operaService.cancelBooking(cancelRequest); LogUtil.info(BookingController.class, "[cancelBooking] Cancel Booking res" + gson.toJson(cancelResponse)); JSONObject errors = new JSONObject(); //cancel share booking if (shareConfList!=null) { for (int a = 0; a < shareConfList.size(); a++) { String shareConfirmationNo = String.valueOf(shareConfList.get(a)); if(!StringUtils.isEmpty(shareConfirmationNo)) { cancelRequest = new CancelBookingRequest(); cancelResponse = new JSONObject(); cancelRequest.setHotelCode(bookingView.getHotelCode()); cancelRequest.setConfirmationNo(shareConfirmationNo); cancelResponse = operaService.cancelBooking(cancelRequest); } } } if (cancelResponse != null) { processResult.setSuccess(true); processResult.setData(bookingView); }else { Date newDate = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"); Bookings booking = bookingDao.findById(bookId).orElse(null); errors = cancelResponse; String errorMessage = errors != null && StringUtils.isNotBlank(errors.getString("message")) ? errors.getString("message") : "Cancel Booking Fail"; booking.setUpdatedAt(newDate); booking.setCreatedAt(newDate); booking.setApproveStatus("F"); booking.setErrorMessage(errorMessage); processResult.setSuccess(false); processResult.setMessage(errorMessage); processResult.setCode("SYSTEM_ERROR"); processResult.setData(bookingView); } return processResult; } processResult.setSuccess(false); processResult.setMessage("Cancel booking fail, invalid property"); return processResult; } public BaseApiResponse getTodoList(String userId, String category, String type, Date startDate, Date endDate) throws Exception { BaseApiResponse result = new BaseApiResponse<>(); HttpResponseResult httpResult; try { // TODO 这里现在写死只拿daylight的todolist,后面会要拿到Opera的todoList,这个时候要改成两个都拿 by Mauve httpResult = mgmEsbApiService.invokeGetTodoList(userId, category, type, startDate, endDate, 1); } catch (Exception err) { result.setSuccess(false); result.setCode("INVOKE_TODOLISTDETAIL_API_ERROR"); LogUtil.info(TodoService.class, "[GetTodoList Error]" + err.getMessage()); return result; } try { TodoListResult resultObj = JSONObject.parseObject( httpResult.getResponseContent(), TodoListResult.class, Feature.SupportNonPublicField, Feature.IgnoreNotMatch ); if ("OK".equals(resultObj.getStatusCode())) { List recordList = resultObj.getRecords(); TodoDateListResult dateResult = new TodoDateListResult(); Map dateMap = new LinkedHashMap<>(); for (TodoListRecord record : recordList) { if (!dateMap.containsKey(record.getDate())) { TodoDateListRecord dateRecord = new TodoDateListRecord(); dateRecord.setDate(record.getDate()); dateRecord.setDateRecords(new ArrayList<>()); dateMap.put(record.getDate(), dateRecord); } dateMap.get(record.getDate()).getDateRecords().add(record); } List dateList = new ArrayList<>(dateMap.values()); // TODO daylight专用,后面要改 by Mauve for (TodoDateListRecord todoDateListRecord : dateList) { List dateRecords = todoDateListRecord.getDateRecords(); for (TodoListRecord record : dateRecords) { List descriptions = record.getDescriptions(); if (CollectionUtils.isEmpty(descriptions)) { continue; } try { for (String description : descriptions) { if (StringUtils.isBlank(description)) { continue; } int confIndex = description.indexOf("Conf#"); if (confIndex == -1) { continue; } String confPart = description.substring(confIndex + 5); int pipeIndex = confPart.indexOf("|"); String confNum = (pipeIndex == -1 ? confPart : confPart.substring(0, pipeIndex)).trim(); if (StringUtils.isNotBlank(confNum)) { if ("Inhouse".equalsIgnoreCase(category) || "Arrival".equalsIgnoreCase(category)) { Bookings bookings = bookingDao.findFirstByConfirmationNoAndPropertyIdIsNotNull(confNum); if (Objects.nonNull(bookings)) { CfgProperties property = propertyDao.findById(bookings.getPropertyId()).orElse(null); if (Objects.nonNull(property)) { if ("Inhouse".equalsIgnoreCase(category)) { BaseApiResponse doorKeyResult = dlService.getReservationDoorKeyByConfirmationNumber(property.getDlPropertyId(), confNum); ReservationDoorKeyResponse doorKeyData = doorKeyResult.getData(); boolean isRoomReady = doorKeyResult.isSuccess() && doorKeyData != null && StringUtils.isNotBlank(doorKeyData.getId()) && !doorKeyData.isHasKey(); if (isRoomReady) { record.setRoomReady(true); updateTodoRecordDescription(record, confNum, "[Rm Ready]"); } } else { BaseApiResponse queueResult = dlService.getReservationQueueByConfirmationNumber(property.getDlPropertyId(), confNum); ReservationQueueResponse queueData = queueResult.getData(); boolean isQueue = queueResult.isSuccess() && queueData != null && queueData.isQueue(); if (isQueue) { record.setIsQueue(true); updateTodoRecordDescription(record, confNum, "[In Queue]"); } } } } } } List bookingByConfirmationNo = bookingService.getBookingByDaylightConf(confNum); for (BookingsView bookingsView : bookingByConfirmationNo) { if (StringUtils.isNotBlank(bookingsView.getEta())) { String[] split2 = bookingsView.getEta().split(":"); record.setETA(split2[0] + ":" + split2[1]); } } } } catch (Exception e) { log.warn("Failed to process todo descriptions={}", descriptions, e); } } } dateResult.setRecords(dateList); result.setSuccess(true); result.setData(dateResult); } else { result.setSuccess(false); result.setCode(resultObj.getStatusDescription()); } } catch (Exception err) { result.setSuccess(false); result.setCode("RETURN_DATA_ERROR"); LogUtil.info(TodoService.class, "[GetTodoList Error]" + err.getMessage()); } return result; } public BaseApiResponse submitETA(String etaTime, List recordInfos, Long id) throws Exception { BaseApiResponse result = new BaseApiResponse<>(); boolean isMock = sysSettingService.isMockReplicate(); if (StringUtils.isBlank(etaTime) || CollectionUtils.isEmpty(recordInfos)) { return missParameter(result); } for (EtaRecordInfo recordInfo : recordInfos) { result = handleSingleRecord(etaTime, recordInfo, isMock, id); // 保持原逻辑:最终返回最后一条 } return result; } private BaseApiResponse handleSingleRecord( String etaTime, EtaRecordInfo recordInfo, boolean isMock, Long id) throws Exception { BaseApiResponse result = new BaseApiResponse<>(); String hotelName = StringUtils.trim(recordInfo.getHotelName()); String confNo = StringUtils.trim(recordInfo.getConfNo()); if (StringUtils.isBlank(hotelName) || StringUtils.isBlank(confNo)) { return missParameter(result); } String category = bookingDao.findCategoryById(id); CfgProperties property = propertyDao.findByLikeNameAndCategory(hotelName, category); if (property == null) { return noRecord(result); } if (Strings.CI.equals("DAYLIGHT", category)) { return handleDaylightETA(etaTime, confNo, property, id); } if (Strings.CI.equals("OPERA", category)) { return handleOperaETA(etaTime, confNo, property, isMock); } if (Strings.CI.equals("OTHER", category)) { return handleOtherETA(etaTime, confNo, property); } return noRecord(result); } private BaseApiResponse handleOperaETA( String etaTime, String confNo, CfgProperties property, boolean isMock) throws Exception { BaseApiResponse result = new BaseApiResponse<>(); Gson gson = new Gson(); Bookings booking = new Bookings(); booking.setConfirmationNo(confNo); booking.setHotelCode(property.getHotelCode()); booking.setCategory("OPERA"); ModifyBookingRequest request = new ModifyBookingRequest(); request.setEta(etaTime); request.setBooking(booking); LogUtil.info(TodoService.class, "[submitETA] OPERA submit begin " + gson.toJson(request)); if (isMock) { // mock 环境:直接操作 DB Bookings editBooking = bookingDao.getByConfNoForETA(confNo, property.getId()); if (editBooking == null) { return noRecord(result); } editBooking.setEta(etaTime); bookingDao.save(editBooking); result.setSuccess(true); result.setData(editBooking); return result; } // dev / prod:调用 OPERA 接口 JSONObject response = operaService.modifyETA(request); LogUtil.info(TodoService.class, "[submitETA] OPERA submit res " + gson.toJson(response)); if (!response.containsKey("message")) { result.setSuccess(true); result.setData(booking); } else { result.setSuccess(false); result.setCode(response.getString("message")); result.setData(booking); } return result; } private BaseApiResponse handleDaylightETA( String etaTime, String confNo, CfgProperties property, Long id) throws Exception { BaseApiResponse result = new BaseApiResponse<>(); Bookings booking; if (id != null) { booking = bookingDao.findById(id).orElse(null); } else { booking = bookingDao.getByConfNoForETA(confNo, property.getId()); } booking.setEta(etaTime); bookingDao.save(booking); if (StringUtils.isNotBlank(confNo)) { LogUtil.info(TodoService.class, "[submitETA] DAYLIGHT submit res"); BaseApiResponse> submitEta = bookingService.callDaylightUpsertReservation(booking, "SUBMIT_ETA"); if (submitEta.isSuccess()) { result.setSuccess(true); result.setMessage(submitEta.getMessage()); } else { result.setSuccess(false); result.setMessage(submitEta.getMessage()); } return result; } return noRecord(result); } private BaseApiResponse handleOtherETA( String etaTime, String confNo, CfgProperties property) { BaseApiResponse result = new BaseApiResponse<>(); Bookings editBooking = bookingDao.getByConfNoForETA(confNo, property.getId()); if (editBooking == null) { return noRecord(result); } LogUtil.info(TodoService.class, "[submitETA] OTHER submit res"); editBooking.setEta(etaTime); editBooking.setCategory("OTHER"); bookingDao.save(editBooking); result.setSuccess(true); result.setData(editBooking); return result; } private BaseApiResponse missParameter(BaseApiResponse result) { result.setSuccess(false); result.setCode("MISS_PARAMETER"); result.setMessage("Miss Parameter"); return result; } private BaseApiResponse noRecord(BaseApiResponse result) { result.setSuccess(false); result.setCode("NO_RECORD"); result.setMessage("There are no corresponding booking records."); return result; } public BaseApiResponse changeBookingDate(TodoChangeDateRequest param, HttpServletRequest request) throws Exception { BaseApiResponse processResult = new BaseApiResponse<>(); Long bookId = param.getId(); String confNo = param.getConfirmationNo(); String ciDate = DateTimeUtil.getDateByFormat(param.getCheckinDate(), "yyyy-MM-dd"); String coDate = DateTimeUtil.getDateByFormat(param.getCheckoutDate(), "yyyy-MM-dd"); String userId = param.getUserId(); String userName = param.getUserName(); String playerId = param.getPlayerId(); PlayerProfileEntry profile = null; BaseApiResponse res = playerService.findPlayerProfileByPlayerIdAndUserId(playerId, userId); if (res.isSuccess()) { profile = res.getData(); } if (bookId != null) { Gson gson = new Gson(); BookingsView bookingView; if (confNo != null) { List bookingsViews = bookingViewDao.findByConfirmationNo(confNo); bookingView = bookingsViews.getFirst(); } else { bookingView = bookingViewDao.findById(bookId).orElse(null); } if (bookingView == null) { processResult.setSuccess(false); processResult.setMessage("Booking not found"); log.warn("booking not found"); return processResult; } Bookings booking = bookingDao.findById(bookingView.getId()).orElse(null); boolean isMock = sysSettingService.isMockReplicate(); Date checkinDate = DateTimeUtil.getDateFromString(ciDate, "yyyy-MM-dd"); Date checkoutDate = DateTimeUtil.getDateFromString(coDate, "yyyy-MM-dd"); if ("DAYLIGHT".equals(bookingView.getPropertyCategory())) { //Change Daylight Booking booking.setCheckinDate(checkinDate); booking.setCheckoutDate(checkoutDate); bookingDao.save(booking); processResult.setSuccess(true); processResult.setData(bookingMapper.entityToDto(booking)); bookingService.daylightReservationChangeDate(param, profile, false, false); LogUtil.info(TodoService.class, "[ChangeBookingDate] ID:"+bookingView.getDlReservationId()); return processResult; } else if ("OPERA".equalsIgnoreCase(bookingView.getPropertyCategory())) { boolean hasShare = false; JSONObject fetchResponse = new JSONObject(); FetchBookingRequest owsReq = new FetchBookingRequest(); owsReq.setConfirmationNo(bookingView.getConfirmationNo()); fetchResponse = operaService.fetchBooking(owsReq); if (fetchResponse.containsKey("shareConfList")) { hasShare = true; } if (hasShare) { //sendEmail Email email = new Email(); email.setBookId(booking.getId()); email.setCreatedAt(DateTimeUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss")); email.setCreatedBy(userId); booking.setChangeCheckinDate(ciDate); booking.setChangeCheckoutDate(coDate); bookingView = this.getEmailInfo(bookingView, userId); CfgSettings emailAddress = settingService.getSettingByKey(SysConstants.MGM_EMAIL_ADDRESS); email = sendEmailService.sendCancelEmail(booking, bookingView, email, userId, userName, emailAddress.getKeyValues()); if (email.getStatus() == 1) { processResult.setSuccess(true); } else { processResult.setSuccess(false); processResult.setCode("Send Email Failed."); } emailDao.save(email); processResult.setData(bookingMapper.entityToDto(booking)); return processResult; } ModifyBookingRequest modifyBookingRequest = new ModifyBookingRequest(); JSONObject modifyBookingResponse = new JSONObject(); booking.setCheckinDate(checkinDate); booking.setCheckoutDate(checkoutDate); modifyBookingRequest.setBooking(booking); LogUtil.info(TodoService.class, "[changeBookingDate] changeBookingDate begin" + gson.toJson(modifyBookingRequest)); modifyBookingResponse = operaService.changeBookingDate(modifyBookingRequest); LogUtil.info(TodoService.class, "[changeBookingDate] Change Booking res" + gson.toJson(modifyBookingResponse)); JSONObject errors = new JSONObject(); if (!modifyBookingResponse.containsKey("message")) { String bookComment = operaService.makeChangeDateComment(booking); CfgProperties property = propertyDao.findById(booking.getPropertyId()).orElse(null); GuestRequestsRequest changeDateCommentRequest = new GuestRequestsRequest(); JSONObject changeDateCommentResponse = new JSONObject(); changeDateCommentRequest.setActionType("ADD"); changeDateCommentRequest.setProperty(property); changeDateCommentRequest.setComment(bookComment); changeDateCommentRequest.setConfirmationNo(booking.getConfirmationNo()); changeDateCommentRequest.setCommentType("CASHIER"); changeDateCommentResponse = operaService.guestRequests(changeDateCommentRequest); processResult.setSuccess(true); processResult.setData(bookingMapper.entityToDto(booking)); } else { Date newDate = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"); String errorMsg = errors.getString("message") != null ? errors.getString("message") : "System Error"; errors = modifyBookingResponse; booking.setUpdatedAt(newDate); booking.setCreatedAt(newDate); booking.setApproveStatus("F"); booking.setTryTime(5); booking.setErrorMessage("Cancel booking fail.Error Message [ " + errorMsg + " ] "); bookingDao.save(booking); processResult.setSuccess(false); processResult.setMessage(errors.getString("message") != null ? errors.getString("message") : "System Error"); processResult.setCode("SYSTEM_ERROR"); processResult.setData(bookingMapper.entityToDto(booking)); } } else { // 获取setting表Cancel状态和时间区间 CfgSettings enAbleCancel = settingService.getSettingByKey("CAN_CANCEL_OTHERBOOKING"); // 判断状态是否启用 if (Strings.CS.equals(enAbleCancel.getKeyValues(), "1")) { // 方法启用(==1),判断时间 // 状态启用判断现在时间是否再时间区间内 if (isPassTimeNow()) { //Change Non MGM Booking Bookings obooking = changeOtherBooking(bookId, ciDate, coDate, request); if (obooking != null) { processResult.setSuccess(true); processResult.setData(bookingMapper.entityToDto(obooking)); } else { processResult.setSuccess(false); processResult.setCode("SYSTEM_ERROR"); processResult.setMessage("System error"); } } else { processResult.setSuccess(false); processResult.setCode("ERR_CANCEL_TIME"); processResult.setData(bookingMapper.changeDateRequestToDto(param)); } } else { // 如果enAbleCancel方法没有启用(==0)直接changedate //Change Non MGM Booking Bookings obooking = changeOtherBooking(bookId, ciDate, coDate, request); if (obooking != null) { processResult.setSuccess(true); processResult.setData(bookingMapper.entityToDto(obooking)); } else { processResult.setSuccess(false); processResult.setCode("SYSTEM_ERROR"); processResult.setMessage("System error"); } } } } else { processResult.setSuccess(false); processResult.setCode("No Booking Id."); processResult.setData(bookingMapper.changeDateRequestToDto(param)); } return processResult; } private Bookings cancelOtherBooking(Long bookId, HttpServletRequest request) { Bookings oBooking = bookingDao.findById(bookId).orElse(null); CfgOtherRoomStatus roomStatus = roomStatusDao.findByStatusName("Pending Cancel"); SysLogBooking logBooking = new SysLogBooking(); LoginUserInfo userInfo = SysCommon.parseUserFromToken(request); String oStatus = oBooking.getLastOperaStatus(); Date now = new Date(); // CfgOtherRoomStatus roomStatus = // oBooking.setCheckinDate(checkinDate); // oBooking.setCheckinDate(checkoutDate); oBooking.setOtherRoomStatusId(roomStatus.getId()); oBooking.setLastOperaStatus("Pending Cancel"); oBooking.setOtherFollowUpStatusId(Long.valueOf("5")); LogUtil.info(BookingController.class, "[changeBookingDate] Start Cancel Other Booking BookingId = " + oBooking.getId()); bookingDao.save(oBooking); // 写入Audit Trail logBooking.setOccurTime(now); logBooking.setBookId(oBooking.getId()); logBooking.setEventCode("Room Status"); logBooking.setChangeFrom(oStatus); logBooking.setChangeTo("Pending Cancel(CANCEL BOOKING)"); logBooking.setLoginId(userInfo.getLoginId()); logBooking.setLoginName(userInfo.getLoginId()); sysLogBookingService.save(logBooking); // otherBookingService.processOtherAllotment(oBooking.getRoomId(), checkoutDate, // checkinDate, oBooking.getPropertyId(), oBooking.getSegmentId()); return oBooking; } private Bookings changeOtherBooking(Long bookId, String checkInDate, String checkOutDate, HttpServletRequest request) throws Exception { Bookings oBooking = bookingDao.findById(bookId).orElse(null); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); CfgOtherRoomStatus roomStatus = otherRoomStatusDao.findByStatusName("Pending Cancel"); CfgOtherRoomStatus oRoomStatus = otherRoomStatusService.getOtherRoomStatusById(oBooking.getOtherRoomStatusId()); String oStatus = oBooking.getLastOperaStatus(); SysLogBooking logBooking = new SysLogBooking(); Date now = new Date(); LoginUserInfo userInfo = SysCommon.parseUserFromToken(request); // 将String转换为Date Date checkIn = dateFormat.parse(checkInDate); Date checkOut = dateFormat.parse(checkOutDate); oBooking.setChangeCheckinDate(checkInDate); oBooking.setChangeCheckoutDate(checkOutDate); oBooking.setLastOperaStatus("Pending Cancel"); oBooking.setOtherRoomStatusId(roomStatus.getId()); oBooking.setOtherFollowUpStatusId(Long.valueOf("5")); LogUtil.info(BookingController.class, "[changeBookingDate] Start Change Other Booking BookingId = " + oBooking.getId()); bookingDao.save(oBooking); // 写入Audit Trail logBooking.setOccurTime(now); logBooking.setBookId(oBooking.getId()); logBooking.setEventCode("Status"); logBooking.setChangeFrom(oStatus); logBooking.setChangeTo("Pending Cancel(CHANGE DATE)"); logBooking.setLoginId(userInfo.getLoginId()); logBooking.setLoginName(userInfo.getLoginId()); sysLogBookingService.save(logBooking); otherBookingService.processOtherAllotment(oBooking.getRoomId(), checkOut, checkIn, oBooking.getPropertyId(), oBooking.getSegmentId()); return oBooking; } private BookingsView getEmailInfo(BookingsView bookView, String userId) { if (bookView != null) { JSONArray dynList = !StringUtils.isEmpty(bookView.getSharer()) && !Strings.CS.equals("[]", bookView.getSharer()) ? JSONArray.parseArray(bookView.getSharer()) : new JSONArray(); String sharerString = ""; if (!dynList.isEmpty()) { for (int a = 0; a < dynList.size(); a++) { Gson gson = new Gson(); JSONObject shareObj = (JSONObject) dynList.get(a); String sharePlayerId = shareObj.getString("playerId"); String shareName = shareObj.getString("name"); LogUtil.info(BookingService.class, "[editBooking] sharePlayerId " + gson.toJson(sharePlayerId)); LogUtil.info(BookingService.class, "[editBooking] shareName " + gson.toJson(shareName)); if (!StringUtils.isEmpty(sharePlayerId)) { sharerString += (sharePlayerId + " " + shareName) + " "; } else if (!StringUtils.isEmpty(shareName)) { sharerString += (shareName) + " "; } else { continue; } } } bookView.setSharerName(sharerString); String playerId = bookView.getPlayerId() != null ? bookView.getPlayerId() : null; BaseApiResponse findWebPlayerResult = playerService.findWebPlayerProfileByPlayerId(playerId); if (findWebPlayerResult.isSuccess()) { try { PlayerProfileEntry profile = findWebPlayerResult.getData(); bookView.setMemberTier(profile.getTierName()); bookView.setMemberLastName(profile.getName()); } catch (Exception e) { e.printStackTrace(); } } } return bookView; } // 判断时间是否超过viewYesterday Range private boolean isPassTimeNow() { boolean isPass = false; CfgSettings cancelStart = settingService.getSettingByKey("OTHERBOOKING_CANCEL_START"); CfgSettings cancelEnd = settingService.getSettingByKey("OTHERBOOKING_CANCEL_END"); int startMinute = Integer.parseInt(cancelStart.getKeyValues().split(":")[0]) * 60 + Integer.parseInt(cancelStart.getKeyValues().split(":")[1]); int endMinute = Integer.parseInt(cancelEnd.getKeyValues().split(":")[0]) * 60 + Integer.parseInt(cancelEnd.getKeyValues().split(":")[1]); // 获跟当就的日期和时间 LocalDateTime currentDateTime = LocalDateTime.now(); int currentMinute = currentDateTime.getMinute() + currentDateTime.getHour() * 60; if (currentMinute > startMinute && currentMinute < endMinute) { isPass = true; } return isPass; } private void updateTodoRecordDescription(TodoListRecord record, String confNum, String tag) { List descriptions = record.getDescriptions(); if (CollectionUtils.isNotEmpty(descriptions)) { for (int i = 0; i < descriptions.size(); i++) { String desc = descriptions.get(i); if (StringUtils.isNotBlank(desc) && desc.contains("Conf#" + confNum)) { descriptions.set(i, desc.replace("Conf#" + confNum, "Conf#" + confNum + " " + tag)); } } } } }