package com.mgm.mcrm.allotment.services; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.mgm.mcrm.allotment.dtos.*; import com.mgm.mcrm.allotment.dtos.daylight.availability.*; import com.mgm.mcrm.allotment.dtos.daylight.sync.MappingDataCache; import com.mgm.mcrm.allotment.dtos.daylight.sync.MissMappingLog; import com.mgm.mcrm.allotment.dtos.request.*; import com.mgm.mcrm.basesetting.agebucket.models.SysAgebucket; import com.mgm.mcrm.basesetting.agebucket.services.AgebucketService; import com.mgm.mcrm.basesetting.room.models.CfgRoomsRoomTypes; import com.mgm.mcrm.common.dtos.AjaxResult; import com.mgm.mcrm.common.dtos.CheckCalendarDaylightRequest; import com.mgm.mcrm.common.dtos.dataimport.appsetting.AppChannelDaylightImportRow; import com.mgm.mcrm.allotment.mappers.CfgOtherAllotmentMapper; import com.mgm.mcrm.allotment.mappers.CfgRoomCriteriaDaylightMapper; import com.mgm.mcrm.allotment.models.*; import com.mgm.mcrm.allotment.repositories.*; import com.mgm.mcrm.appsetting.repositories.SettingDao; import com.mgm.mcrm.basesetting.daylight.dtos.CfgDaylightViewDto; import com.mgm.mcrm.basesetting.daylight.dtos.CfgExceptionDaylightViewDto; import com.mgm.mcrm.basesetting.daylight.mappers.CfgDaylightMapper; import com.mgm.mcrm.basesetting.daylight.mappers.CfgExceptionDaylightMapper; import com.mgm.mcrm.basesetting.daylight.models.CfgBlockCodes; import com.mgm.mcrm.basesetting.daylight.models.CfgBlocks; import com.mgm.mcrm.basesetting.daylight.repositories.*; import com.mgm.mcrm.basesetting.property.models.CfgProperties; import com.mgm.mcrm.basesetting.property.repositories.PropertyDao; import com.mgm.mcrm.basesetting.room.dtos.CfgRoomsRoomTypesDto; import com.mgm.mcrm.basesetting.room.mappers.RoomTypeMapper; import com.mgm.mcrm.basesetting.room.models.CfgRoomTypes; import com.mgm.mcrm.basesetting.room.models.CfgRooms; import com.mgm.mcrm.basesetting.room.repositories.RoomDao; import com.mgm.mcrm.basesetting.room.repositories.RoomRoomTypeDao; import com.mgm.mcrm.basesetting.room.repositories.RoomTypeDao; import com.mgm.mcrm.basesetting.team.dtos.CfgOtherUserMappingDto; import com.mgm.mcrm.basesetting.team.mappers.CfgOtherUserMapper; import com.mgm.mcrm.basesetting.team.repositories.OtherUserMappingDao; import com.mgm.mcrm.common.constants.SysConstants; import com.mgm.mcrm.common.dtos.DataTableResult; import com.mgm.mcrm.common.dtos.ServiceResult; import com.mgm.mcrm.common.dtos.dataimport.ValidateResult; import com.mgm.mcrm.common.dtos.excelmodel.GroupItem; import com.mgm.mcrm.common.dtos.excelmodel.ImportDefine; import com.mgm.mcrm.common.httpclient.HttpHeaderBuilder; import com.mgm.mcrm.common.services.HttpService; import com.mgm.mcrm.common.utils.DaoUtil; import com.mgm.mcrm.common.utils.DateTimeUtil; import com.mgm.mcrm.common.utils.ExcelUtils; import com.mgm.mcrm.reservation.models.BookingsView; import com.mgm.mcrm.reservation.repositories.BookingViewDao; import jakarta.annotation.Resource; import jakarta.persistence.criteria.Predicate; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.hc.core5.http.Header; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @Slf4j @Service public class RoomCriteriaDaylightService { @Resource private RoomCriteriaDaylightDao criteriaDaylightDao; @Resource private RoomCriteriaDaylightViewDao criteriaDaylightViewDao; @Resource private AppChannelDaylightDao appChannelDaylightDao; @Resource private SettingDao settingDao; @Resource private PropertyDao propertyDao; @Resource private RoomDao roomDao; @Resource private BlockDao blockDao; @Resource private RoomTypeDao roomTypeDao; @Resource private RoomRoomTypeDao roomRoomTypeDao; @Resource private DaylightMappingRoomTypeDao daylightMappingRoomTypeDao; @Resource private BlockCodeDao blockCodeDao; @Resource private BookingViewDao bookingViewDao; @Autowired private OtherUserMappingDao otherUserMappingDao; @Autowired private OtherAllotmentViewDao otherAllotmentDao; @Resource private DaylightViewDao daylightViewDao; @Resource private ExceptionDaylightViewDao exceptionDaylightViewDao; @Resource private DaylightRoomTypeAllotmentDao daylightRoomTypeAllotmentDao; @Resource private CfgRoomCriteriaDaylightMapper cfgRoomCriteriaDaylightMapper; @Resource private RoomTypeMapper roomTypeMapper; @Resource private CfgExceptionDaylightMapper cfgExceptionDaylightMapper; @Resource private CfgDaylightMapper cfgDaylightMapper; @Resource private CfgOtherAllotmentMapper cfgOtherAllotmentMapper; @Resource private CfgOtherUserMapper cfgOtherUserMapper; @Resource private HttpService httpService; @Resource private AgebucketService agebucketService; private final String[] dayNames = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; public ServiceResult createRoomCriteria(CfgRoomCriteriaDaylightRequest criteriaRequest) { ServiceResult processResult = new ServiceResult(); LocalDateTime createDate = LocalDateTime.now(); List dateRange = criteriaRequest.getDateRange(); LocalDateTime startDate = DateTimeUtil.getDateFromString(String.valueOf(dateRange.get(0)), "yyyy-MM-dd"); LocalDateTime endDate = DateTimeUtil.getDateFromString(String.valueOf(dateRange.get(1)), "yyyy-MM-dd"); int numDay = Integer.parseInt(DateTimeUtil.getDiffDate(startDate, endDate, "day")); List dow = criteriaRequest.getDow(); List channelList = new ArrayList(); if (criteriaRequest.getBlockCodeChannels() != null && !criteriaRequest.getBlockCodeChannels().isEmpty()) { List blockCodeChannels = criteriaRequest.getBlockCodeChannels(); for (int i = 0; i < numDay + 1; i++) { LocalDateTime bookDate = DateTimeUtil.addDay(startDate, i); int bDay = bookDate.getDayOfWeek().getValue(); if (dow != null) { if (!dow.contains(String.valueOf(bDay))) { continue; } } CfgRoomCriteriasDaylight criteriaObj = new CfgRoomCriteriasDaylight(); BeanUtils.copyProperties(criteriaRequest, criteriaObj); List roomCriteriaList = new ArrayList(); criteriaObj.setId(null); criteriaObj.setBookDate(bookDate); criteriaObj.setCreatedAt(createDate); criteriaObj.setBookDow(bDay); List existCriteria = criteriaDaylightDao. findByRoomIdAndPropertyIdAndBookDate(criteriaObj.getRoomId(), criteriaObj.getPropertyId(), criteriaObj.getBookDate()); if (!existCriteria.isEmpty()) { for (CfgRoomCriteriasDaylight ec : existCriteria) { BeanUtils.copyProperties(criteriaObj, ec, "id", "createdAt", "createdBy"); ec.setCreatedAt(createDate); criteriaDaylightDao.save(ec); roomCriteriaList.add(ec); } } else { CfgRoomCriteriasDaylight newRoomCriteria = criteriaDaylightDao.save(criteriaObj); roomCriteriaList.add(newRoomCriteria); } for (CfgRoomCriteriasDaylight nc : roomCriteriaList) { for (BlockCodeChannelDto blockCodeChannel : blockCodeChannels) { if (blockCodeChannel.getChannelTotal() == null) { blockCodeChannel.setChannelTotal(0); } CfgAppChannelDaylight channel = appChannelDaylightDao.findByCriteriaIdAndBlockCodeId(nc.getId(), blockCodeChannel.getBlockCodeId()); if (channel != null) { channel.setChannelTotal(blockCodeChannel.getChannelTotal()); channel.setAvailable(blockCodeChannel.getChannelTotal() - (channel.getPickedUp() == null ? 0 : channel.getPickedUp())); } else { channel = new CfgAppChannelDaylight(); channel.setCriteriaId(nc.getId()); channel.setBlockCodeId(blockCodeChannel.getBlockCodeId()); channel.setChannelTotal(blockCodeChannel.getChannelTotal()); channel.setPickedUp(0); channel.setAvailable(blockCodeChannel.getChannelTotal()); channel.setCreatedAt(LocalDateTime.now()); } channelList.add(channel); } } } if (!channelList.isEmpty()) { appChannelDaylightDao.saveAll(channelList); } processResult.setSuccess(true); processResult.setReturnData(criteriaRequest); }else{ processResult.setErrorMessage("Empty BlockCode Channel setting"); processResult.setSuccess(false); } return processResult; } @Transactional public ServiceResult updateRoomCriteria(CfgRoomCriteriaDaylightRequest criteriaRequest) { ServiceResult processResult = new ServiceResult(); CfgRoomCriteriasDaylight existsType = criteriaDaylightDao.findById(criteriaRequest.getId()).orElse(null); if (existsType == null) { processResult.setErrorCode("ERR_OBJECT_NOT_FOUND"); processResult.setErrorMessage("Can't find Criteria record by Id"); } else { LocalDateTime currentTime = LocalDateTime.now(); String[] ignoreProperties = new String[]{"id", "category", "createdAt", "createdBy", "updatedAt", "updatedBy"}; BeanUtils.copyProperties(criteriaRequest, existsType, ignoreProperties); if (existsType.getBookDate() != null) { existsType.setBookDow(existsType.getBookDate().getDayOfWeek().getValue()); } existsType.setUpdatedAt(currentTime); criteriaDaylightDao.save(existsType); if (criteriaRequest.getBlockCodeChannels() != null && !criteriaRequest.getBlockCodeChannels().isEmpty()) { // 只有在请求明确带了 blockCodeChannels 时,才执行"删除旧→插入新"的 channel 替换流程, // 否则保留原有 channel,避免修改 sharer/waitlist 等字段时 channel 被误删。 appChannelDaylightDao.deleteByCriteriaId(existsType.getId()); List blockCodeChannels = criteriaRequest.getBlockCodeChannels(); for (BlockCodeChannelDto blockCodeChannel :blockCodeChannels) { CfgAppChannelDaylight channel = new CfgAppChannelDaylight(); channel.setCriteriaId(existsType.getId()); channel.setBlockCodeId(blockCodeChannel.getBlockCodeId()); Integer channelTotal = blockCodeChannel.getChannelTotal(); if (channelTotal == null) { channelTotal = 0; } channel.setChannelTotal(channelTotal); channel.setPickedUp(blockCodeChannel.getPickedUp() == null ? 0 : blockCodeChannel.getPickedUp()); channel.setAvailable(channelTotal > 0 ? (channelTotal - channel.getPickedUp()) : 0); channel.setCreatedAt(currentTime); appChannelDaylightDao.save(channel); } } processResult.setReturnData(existsType); processResult.setSuccess(true); } return processResult; } public ServiceResult updateBatchRoomCriteria(JSONArray criterias, Integer type) { ServiceResult processResult = new ServiceResult(); ArrayList saveCriterias = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); for (int i = 0; i < criterias.size(); i++) { CfgRoomCriteriasDaylight updateCriteria = new CfgRoomCriteriasDaylight(); JSONObject criteria = criterias.getJSONObject(i); updateCriteria.setId(criteria.getLong("id")); updateCriteria.setBookDate(LocalDateTime.ofInstant(criteria.getDate("bookDate").toInstant(), ZoneId.of("GMT+8"))); updateCriteria.setBookDow(criteria.getInteger("bookDow")); updateCriteria.setPropertyId(criteria.getLong("propertyId")); updateCriteria.setRoomId(criteria.getLong("roomId")); updateCriteria.setCreatedAt(LocalDateTime.ofInstant(criteria.getDate("createdAt").toInstant(), ZoneId.of("GMT+8"))); updateCriteria.setCreatedBy(criteria.getString("createdBy")); updateCriteria.setSharer(criteria.getInteger("sharer")); updateCriteria.setIsWaitlist(criteria.getInteger("isWaitlist")); updateCriteria.setRate(criteria.getInteger("rate")); if (type == 0) { updateCriteria.setSharer(0); } else if (type == 1) { updateCriteria.setSharer(1); } else if (type == 2) { updateCriteria.setIsWaitlist(1); } else if (type == 3) { updateCriteria.setIsWaitlist(0); } updateCriteria.setUpdatedAt(LocalDateTime.now()); saveCriterias.add(updateCriteria); } criteriaDaylightDao.saveAll(saveCriterias); processResult.setReturnData(saveCriterias); processResult.setSuccess(true); return processResult; } public ServiceResult updateBatchAppChannel(JSONArray channels, JSONObject filter) { ServiceResult processResult = new ServiceResult(); ArrayList saveChannel = new ArrayList(); List getCriterias = new ArrayList<>(); Long propertyId = filter.getLong("searchPropertyId"); JSONArray bookDate = filter.getJSONArray("searchBookDate"); LocalDateTime startDate = LocalDateTime.now(); LocalDateTime endDate = LocalDateTime.now(); String category = ""; if (filter.containsKey("searchCategory")) { category = filter.getString("searchCategory"); } if (StringUtils.isBlank(category)) { category = "BOOKING"; } List roomIds = (List) filter.get("searchRoomId"); List dow = (List) filter.get("searchDow"); List roomId = new ArrayList<>(); for (int i = 0; i < roomIds.size(); i++) { roomId.add(Long.valueOf(String.valueOf(roomIds.get(i)))); } if (bookDate != null) { startDate = DateTimeUtil.getDateFromString(String.valueOf(bookDate.get(0)), "yyyy-MM-dd"); endDate = DateTimeUtil.getDateFromString(String.valueOf(bookDate.get(1)), "yyyy-MM-dd"); } if (propertyId != null && bookDate == null && roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByPropertyId(propertyId); } else if (propertyId == null && bookDate != null && roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByBookDateBetween(startDate, endDate); } else if (propertyId == null && bookDate == null && !roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByRoomIdIn(roomId); } else if (propertyId != null && bookDate != null && roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByPropertyIdAndBookDateBetween(propertyId, startDate, endDate); } else if (propertyId == null && bookDate != null && !roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByRoomIdInAndBookDateBetween(roomId, startDate, endDate); } else if (propertyId != null && bookDate == null && !roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByRoomIdInAndPropertyId(roomId, propertyId); } else if (propertyId != null && bookDate != null && !roomId.isEmpty()) { getCriterias = criteriaDaylightViewDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomId, propertyId, startDate, endDate); } List categoryRoomIds; if ("WAIT_LIST".equalsIgnoreCase(category)) { categoryRoomIds = roomDao.queryWaitlistRoomIds(); } else { categoryRoomIds = roomDao.queryBookingRoomIds(); } if (dow != null) { for (int i = 0; i < dow.size(); i++) { int num = Integer.parseInt(String.valueOf(dow.get(i))); dow.set(i, num); } } for (int i = 0; i < getCriterias.size(); i++) { CfgRoomCriteriasDaylightView criteria = getCriterias.get(i); if (!categoryRoomIds.contains(criteria.getRoomId())) { continue; } if (dow != null) { LocalDateTime getDate = criteria.getBookDate(); if (!dow.contains(getDate.getDayOfWeek().getValue())) { continue; } } Set appChannels = criteria.getChannels(); for (int j = 0; j < channels.size(); j++) { JSONObject ch = (JSONObject) channels.get(j); CfgAppChannelDaylight appChannel = null; Integer channelTotal = ch.getInteger("channelTotal") != null ? ch.getInteger("channelTotal") : 0; for (CfgAppChannelDaylight channelItem : appChannels) { if (Objects.equals(channelItem.getBlockCodeId(), ch.getLong("blockCodeId"))) { appChannel = channelItem; appChannel.setChannelTotal(channelTotal); if (appChannel.getPickedUp() == null) { appChannel.setPickedUp(0); } appChannel.setAvailable(channelTotal - appChannel.getPickedUp()); break; } } if (appChannel == null) { appChannel = new CfgAppChannelDaylight(); appChannel.setCriteriaId(criteria.getId()); appChannel.setBlockCodeId(ch.getLong("blockCodeId")); appChannel.setChannelTotal(channelTotal); appChannel.setAvailable(channelTotal); appChannel.setPickedUp(0); appChannel.setCreatedAt(LocalDateTime.now()); } saveChannel.add(appChannel); } } appChannelDaylightDao.saveAll(saveChannel); processResult.setReturnData(saveChannel); processResult.setSuccess(true); return processResult; } public CfgRoomCriteriasDaylightDto getRoomCriteriaById(long id) { CfgRoomCriteriasDaylight criteria = criteriaDaylightDao.findById(id); return cfgRoomCriteriaDaylightMapper.toDto(criteria); } public CfgRoomCriteriasDaylightViewDto getRoomCriteriaViewById(Long id) { CfgRoomCriteriasDaylightView criteria = criteriaDaylightViewDao.findById(id).orElse(null); return cfgRoomCriteriaDaylightMapper.toViewResponse(criteria); } public CfgRoomCriteriasDaylight getRoomCriteriaById(String id) { return criteriaDaylightDao.getById(id); } public CfgRoomCriteriasDaylight save(CfgRoomCriteriasDaylight criteria) { return criteriaDaylightDao.save(criteria); } public DataTableResult getRoomCriteriaByPage(QueryRoomCriteriaRequest queryFilter) { List categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory()); Specification listSpec = buildSpecificationByQueryFilter(queryFilter, categoryRoomIds); int pageSize = queryFilter.getPageSize(); int pageStart = queryFilter.getPageNo(); Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc"); Pageable pageable = PageRequest.of(pageStart, pageSize, sort); Page resultPage = criteriaDaylightDao.findAll(listSpec, pageable); DataTableResult dataResult = new DataTableResult<>(); dataResult.setTotalRecords(resultPage.getTotalElements()); dataResult.setPageSize(pageSize); List resultList = resultPage.getContent(); dataResult.setRowData(resultList); return dataResult; } public DataTableResult getRoomCriteriaViewByPage(QueryRoomCriteriaRequest queryFilter) { //--先主表找分页,然后再按照分页结果找View的对象 List categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory()); Specification listSpec = buildSpecificationByQueryFilter(queryFilter, categoryRoomIds); int pageSize = queryFilter.getPageSize(); int pageStart = queryFilter.getPageNo(); Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc"); Pageable pageable = PageRequest.of(pageStart, pageSize, sort); Page resultPage = criteriaDaylightDao.findAll(listSpec, pageable); DataTableResult dataResult = new DataTableResult<>(); dataResult.setTotalRecords(resultPage.getTotalElements()); dataResult.setPageSize(pageSize); List resultList = new ArrayList<>(); List masterPageData = resultPage.getContent(); if (!masterPageData.isEmpty()) { List ids = new ArrayList(); for (CfgRoomCriteriasDaylight item : masterPageData) { ids.add(item.getId()); } queryFilter.setPageIds(ids); resultList = this.listRoomCriteriasView(queryFilter); } dataResult.setRowData(resultList); return dataResult; } private List getCategoryRoomIds(String category) { List result = new ArrayList<>(); if (StringUtils.isNotBlank(category)) { List cateIds = null; if ("WAIT_LIST".equalsIgnoreCase(category)) { cateIds = roomDao.queryWaitlistRoomIds(); } else { cateIds = roomDao.queryBookingRoomIds(); } if (cateIds != null && !cateIds.isEmpty()) { result = cateIds; } else { result.add(-1L); } } return result; } public List listRoomCriteria(QueryRoomCriteriaRequest queryFilter) { List categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory()); Specification listSpec = buildSpecificationByQueryFilter(queryFilter, categoryRoomIds); Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc"); return criteriaDaylightDao.findAll(listSpec, sort); } public List listRoomCriteriasView(QueryRoomCriteriaRequest queryFilter) { List categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory()); Specification listSpec = buildSpecificationViewByQueryFilter(queryFilter, categoryRoomIds); Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc"); List resultList = criteriaDaylightViewDao.findAll(listSpec, sort); return cfgRoomCriteriaDaylightMapper.toViewDtoList(resultList); } private Specification buildSpecificationByQueryFilter(QueryRoomCriteriaRequest queryFilter, List cateRoomIds) { return (root, criteriaQuery, cb) -> { List list = new ArrayList<>(); if (cateRoomIds != null && !cateRoomIds.isEmpty()) { list.add(root.get("roomId").in(cateRoomIds)); } if (queryFilter.getSearchPropertyId() != null) { list.add(cb.equal(root.get("propertyId"), queryFilter.getSearchPropertyId())); } if (queryFilter.getSearchBookDate() != null) { List dates = queryFilter.getSearchBookDate(); if (!dates.isEmpty()) list.add(cb.greaterThanOrEqualTo(root.get("bookDate"), DateTimeUtil.getDateFromString(dates.get(0), "yyyy-MM-dd"))); if (dates.size() > 1) list.add(cb.lessThanOrEqualTo(root.get("bookDate"), DateTimeUtil.getDateFromString(dates.get(1), "yyyy-MM-dd"))); } if (queryFilter.getSearchRoomId() != null) { List roomIds = queryFilter.getSearchRoomId(); if (!roomIds.isEmpty()) { list.add(root.get("roomId").in(roomIds)); } } if (queryFilter.getSearchDow() != null) { List weekDays = queryFilter.getSearchDow(); if (!weekDays.isEmpty()) { list.add(root.get("bookDow").in(weekDays)); } } Predicate[] predicates = new Predicate[list.size()]; criteriaQuery.where(list.toArray(predicates)); return cb.and(list.toArray(predicates)); }; } private Specification buildSpecificationViewByQueryFilter(QueryRoomCriteriaRequest queryFilter, List cateRoomIds) { return (root, criteriaQuery, cb) -> { List list = new ArrayList<>(); if (cateRoomIds != null && !cateRoomIds.isEmpty()) { list.add(root.get("roomId").in(cateRoomIds)); } if (queryFilter.getSearchPropertyId() != null) { list.add(cb.equal(root.get("propertyId"), queryFilter.getSearchPropertyId())); } if (queryFilter.getSearchBookDate() != null) { List dates = queryFilter.getSearchBookDate(); if (!dates.isEmpty()) list.add(cb.greaterThanOrEqualTo(root.get("bookDate"), DateTimeUtil.getDateFromString(dates.get(0), "yyyy-MM-dd"))); if (dates.size() > 1) list.add(cb.lessThanOrEqualTo(root.get("bookDate"), DateTimeUtil.getDateFromString(dates.get(1), "yyyy-MM-dd"))); } if (queryFilter.getSearchRoomId() != null) { List roomIds = queryFilter.getSearchRoomId(); if (!roomIds.isEmpty()) { list.add(root.get("roomId").in(roomIds)); } } if (queryFilter.getSearchDow() != null) { List weekDays = queryFilter.getSearchDow(); if (!weekDays.isEmpty()) { list.add(root.get("bookDow").in(weekDays)); } } if (queryFilter.getPageIds() != null) { List pageIds = queryFilter.getPageIds(); if (!pageIds.isEmpty()) { list.add(root.get("id").in(pageIds)); } } Predicate[] predicates = new Predicate[list.size()]; criteriaQuery.where(list.toArray(predicates)); return cb.and(list.toArray(predicates)); }; } public boolean deleteRoomCriteria(CfgRoomCriteriaDaylightRequest criteria) { criteriaDaylightDao.deleteById(criteria.getId()); appChannelDaylightDao.deleteByCriteriaId(criteria.getId()); return true; } public Map listRoomCriteriaCalendar(CheckCalendarDaylightRequest checkCalendarRequest) throws Exception { Map resultList = new HashMap<>(); Long bookingTypeId = checkCalendarRequest.getBookingTypeId(); Long blockCodeId = checkCalendarRequest.getBlockCodeId(); Long segmentId = checkCalendarRequest.getSegmentId(); long propertyId = checkCalendarRequest.getPropertyId(); long roomId = checkCalendarRequest.getRoomId(); String userId = checkCalendarRequest.getUserId(); String userName = checkCalendarRequest.getUserName(); String playerId = checkCalendarRequest.getPlayerId(); Long teamId = checkCalendarRequest.getTeamId(); Long bookId = checkCalendarRequest.getBookId(); //check opera criteria or other criteria CfgProperties property = propertyDao.findById(propertyId).orElse(null); CfgRooms room = roomDao.findById(roomId); boolean isDaylight = false; boolean isWaitlist = false; if ("DAYLIGHT".equalsIgnoreCase(property.getCategory())) isDaylight = true; if (room.getForCreateWaitlist() == 1 && room.getForCreateBooking() == 0) isWaitlist = true; if (isDaylight || isWaitlist) { resultList = getDaylightCriteria(blockCodeId, teamId, bookingTypeId, propertyId, roomId, userId); } else { resultList = getOtherCriteria(segmentId, teamId, bookingTypeId, propertyId, roomId); } if (!resultList.isEmpty()) { resultList = checkCriteriaBooking(resultList, playerId, userId, userName, bookId); } return resultList; } public Map getDaylightCriteria(Long blockCodeId, Long teamId, Long bookingTypeId, Long propertyId, Long roomId, String userId) throws Exception { Long roomTypeId = null; List roomIds = new ArrayList<>(); roomIds.add(roomId); Map resultList = new HashMap<>(); LocalDateTime today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd"); String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues(); LocalDateTime endDate = DateTimeUtil.addDay(today, Integer.parseInt(maxDay)); List teamOpera = new ArrayList<>(); List exceptionOpera = new ArrayList<>(); // 如果有BedTypeId根据BedTypeId拿到RoomTypeId List后随机,否则按RoomId List roomTypes = new ArrayList<>(); if (blockCodeId == null) { roomTypes = roomTypeMapper.toCfgRoomsRoomTypesDtoList(roomRoomTypeDao.queryByRoomId(Integer.valueOf(String.valueOf(roomId))));// 该方法可能要改成一个view的直接拿到RoomTypeId和RoomTypeCode if (roomTypes != null && !roomTypes.isEmpty()) { // 暂时先拿第一个,这里要改成随机算法。拿roomType用得少就用那个要实现平均分配 roomTypeId = roomTypes.get(0).getRoomTypeId(); } //先从exception opera mapping拿,没有再去 opera mapping拿 List eoperas = cfgExceptionDaylightMapper.toCfgExceptionOperaViewDtoList(exceptionDaylightViewDao.findByUserIdLikeAndPropertyIdAndBookingTypeId("%" + userId + "%", propertyId, Long.valueOf(bookingTypeId))); if (!eoperas.isEmpty()) { for (CfgExceptionDaylightViewDto o : eoperas) { for (CfgRoomTypes r : o.getDaylightRoomType()) { if (Objects.equals(r.getId(), roomTypeId)) { exceptionOpera.add(o); } } } } // 筛选出符合条件的opear mapping记录,没有Opera mapping要提示前端配置 List operas = cfgDaylightMapper.toCfgDaylightViewDtoList(daylightViewDao.findByPropertyIdAndBookingTypeId(propertyId, Long.valueOf(bookingTypeId))); for (CfgDaylightViewDto o : operas) { for (CfgRoomTypes r : o.getDaylightRoomType()) { if (Objects.equals(r.getId(), roomTypeId)) { teamOpera.add(o); } } } if (!exceptionOpera.isEmpty()) { blockCodeId = exceptionOpera.getFirst().getBlockCodeId(); } else if (!teamOpera.isEmpty()) { blockCodeId = teamOpera.getFirst().getBlockCodeId(); } } List criterias = cfgRoomCriteriaDaylightMapper.toCfgRoomCriteriasDaylightDtoList(criteriaDaylightDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomIds, propertyId, today, endDate)); for (CfgRoomCriteriasDaylightDto criteriaItem : criterias) { JSONObject res = new JSONObject(); String bookDate = DateTimeUtil.getDateByFormat(criteriaItem.getBookDate(), "yyyy-MM-dd"); res.put("bookDate", bookDate); res.put("isWaitlist", criteriaItem.getIsWaitlist()); res.put("sharer", criteriaItem.getSharer()); CfgAppChannelDaylight channel = new CfgAppChannelDaylight(); Set channels = criteriaItem.getChannels(); for (CfgAppChannelDaylight a : channels) { if (Objects.equals(a.getBlockCodeId(), blockCodeId)) channel = a; } res.put("available", channel.getAvailable()); resultList.put(bookDate, res); } return resultList; } public Map getOtherCriteria(Long segmentId, Long teamId, Long bookingTypeId, Long propertyId, Long roomId) throws Exception { Long roomTypeId = null; List roomIds = new ArrayList<>(); roomIds.add(roomId); LocalDateTime today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd"); // 如果today为null,则使用当前时间 if (today == null) { today = LocalDateTime.now(); } String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues(); String minDay = settingDao.getByKeys(SysConstants.MAX_PREVIOUS_BOOKING_DAYS).getKeyValues(); LocalDateTime endDate = DateTimeUtil.addDay(today, Integer.parseInt(maxDay)); LocalDateTime startDate = DateTimeUtil.addDay(today, -Integer.parseInt(minDay)); Map resultList = new HashMap<>(); List userMappingList; if (segmentId == null) { // 筛选出符合条件的 mapping记录 userMappingList = cfgOtherUserMapper.toCfgOtherUserMappingDtoList(otherUserMappingDao.findByPropertyIdAndBookingTypeId(propertyId, Long.valueOf(bookingTypeId))); if (!userMappingList.isEmpty()) { segmentId = userMappingList.getFirst().getSegmentId(); } } List criterias = cfgOtherAllotmentMapper.toCfgOtherAllotmentViewDtos(otherAllotmentDao.findByRoomIdInAndPropertyIdAndBookDateBetween(roomIds, propertyId, startDate, endDate)); for (CfgOtherAllotmentViewDto c : criterias) { JSONObject res = new JSONObject(); String bookDate = DateTimeUtil.getDateByFormat(c.getBookDate(), "yyyy-MM-dd"); res.put("bookDate", bookDate); res.put("isWaitlist", c.getIsWaitlist()); res.put("sharer", c.getSharer()); CfgOtherAppChannelDto channel = new CfgOtherAppChannelDto(); Set channels = c.getChannels(); for (CfgOtherAppChannelDto a : channels) { if (a.getSegmentId() != null && segmentId != null) { if (a.getSegmentId().longValue() == segmentId.longValue()) channel = a; } } res.put("available", channel.getAvailable()); resultList.put(bookDate, res); } return resultList; } private Map checkCriteriaBooking(Map resultList, String playerId, String userId, String userName, Long bookId) throws Exception { LocalDateTime today = DateTimeUtil.getCurrentDateTime("yyyy-MM-dd"); // 如果today为null,则使用当前时间 if (today == null) { today = LocalDateTime.now(); } String maxDay = settingDao.getByKeys(SysConstants.MAX_ADVANCE_BOOKING_DAYS).getKeyValues(); boolean enableProtection = "1".equals(settingDao.getByKeys(SysConstants.PROTECT_PERIOD_ENABLE).getKeyValues()); String checkinProtection = settingDao.getByKeys(SysConstants.PROTECTION_PERIOD_CHECKIN).getKeyValues(); String checkoutProtection = settingDao.getByKeys(SysConstants.PROTECTION_PERIOD_CHECKOUT).getKeyValues(); LocalDateTime endDate = DateTimeUtil.addDay(today, Integer.parseInt(maxDay)); List bookingList = bookingViewDao.getCalendarBooking(endDate, playerId); Set protectionPeriod = new HashSet<>(); Set crPeriod = new HashSet<>(); for (BookingsView book : bookingList) { if (StringUtils.isEmpty(book.getLastOperaStatus()) || "DUE_IN".equals(book.getLastOperaStatus()) || "RESERVED".equals(book.getLastOperaStatus()) || "CHECKED_IN".equals(book.getLastOperaStatus())) { // no coded boolean differentUser = true; if (!StringUtils.isEmpty(book.getCreatedBy())) { differentUser = !book.getCreatedBy().equals(userId); } else if (!StringUtils.isEmpty(book.getCreatedByName())) { differentUser = !book.getCreatedByName().equals(userName); } boolean isCR = "CCREL".equals(book.getMarketCode()); if (enableProtection && differentUser) { if (Integer.parseInt(checkinProtection) >= 0) { for (int q = 0; q <= Integer.parseInt(checkinProtection); q++) { LocalDateTime protectCheckin = DateTimeUtil.addDay(book.getCheckinDate(), q); protectionPeriod.add(protectCheckin); if (isCR) crPeriod.add(protectCheckin); } } else { for (int q = 0; q >= Integer.parseInt(checkinProtection); q--) { LocalDateTime protectCheckin = DateTimeUtil.addDay(book.getCheckinDate(), q); protectionPeriod.add(protectCheckin); if (isCR) crPeriod.add(protectCheckin); } } //change check out date to check in if (Integer.parseInt(checkoutProtection) >= 0) { for (int q = 0; q <= Integer.parseInt(checkoutProtection); q++) { LocalDateTime protectCheckout = DateTimeUtil.addDay(book.getCheckinDate(), Integer.valueOf(q)); protectionPeriod.add(protectCheckout); if (isCR) crPeriod.add(protectCheckout); } } else { for (int q = 0; q >= Integer.parseInt(checkoutProtection); q--) { LocalDateTime protectCheckout = DateTimeUtil.addDay(book.getCheckinDate(), Integer.valueOf(q)); protectionPeriod.add(protectCheckout); if (isCR) crPeriod.add(protectCheckout); } } } //edit booking 不计算当前booking数 if (bookId != null && bookId.longValue() == book.getId().longValue()) continue; LocalDateTime checkInDate = book.getCheckinDate(); LocalDateTime checkOutDate = book.getCheckoutDate(); while (checkInDate.isBefore(checkOutDate)) { String getDate = DateTimeUtil.getDateByFormat(checkInDate, "yyyy-MM-dd"); if (resultList.containsKey(getDate)) { JSONObject res = resultList.get(getDate); if (StringUtils.isEmpty(book.getLastOperaStatus()) || "DUE_IN".equals(book.getLastOperaStatus()) || "RESERVED".equals(book.getLastOperaStatus())) { res.put("reserved", 1); } else if ("CHECKED_IN".equals(book.getLastOperaStatus())) { res.put("staying", 1); } if ("Mass".equals(book.getBookingTypeName()) && book.getRevisionOf() == null) { if ("Standard Room".equals(book.getRoomCategory())) { if (res.containsKey("massStandard")) { int standareNum = res.getInteger("massStandard") + 1; res.put("massStandard", standareNum); } else { res.put("massStandard", 1); } } if ("Suite".equals(book.getRoomCategory())) { if (res.containsKey("massSuite")) { int suiteNum = res.getInteger("massSuite") + 1; res.put("massSuite", suiteNum); } else { res.put("massSuite", 1); } } } else if ("IM".equals(book.getBookingTypeName()) && book.getRevisionOf() == null) { if (res.containsKey("im")) { int suiteNum = res.getInteger("im") + 1; res.put("im", suiteNum); } else { res.put("im", 1); } } resultList.put(getDate, res); } checkInDate = DateTimeUtil.addDay(checkInDate, 1); } } } for (LocalDateTime period : protectionPeriod) { String date = DateTimeUtil.getDateByFormat(period, "yyyy-MM-dd"); if (resultList.containsKey(date)) { JSONObject res = resultList.get(date); res.put("protection", 1); resultList.put(date, res); } } for (LocalDateTime period : crPeriod) { String date = DateTimeUtil.getDateByFormat(period, "yyyy-MM-dd"); if (resultList.containsKey(date)) { JSONObject res = resultList.get(date); res.put("cr", true); resultList.put(date, res); } } return resultList; } public HashSet listRoomCriteriaAvailableRoom(Map queryParas) { HashSet resultList = new HashSet<>(); List selectDate = (List) queryParas.get("selectDate"); LocalDateTime checkinDate = DateTimeUtil.getDateFromString(String.valueOf(selectDate.get(0)), "yyyy-MM-dd"); LocalDateTime checkoutDate = DateTimeUtil.getDateFromString(String.valueOf(selectDate.get(1)), "yyyy-MM-dd"); Long blockId = Long.valueOf(String.valueOf(queryParas.get("blockId"))); Long propertyId = Long.valueOf(String.valueOf(queryParas.get("propertyId"))); Long roomId = Long.valueOf(String.valueOf(queryParas.get("roomId"))); List roomIds = new ArrayList<>(); roomIds.add(roomId); String category = queryParas.get("category") != null ? queryParas.get("category").toString() : ""; if (StringUtils.isBlank(category)) { category = "BOOKING"; } List criterias = criteriaDaylightViewDao.findByRoomIdNotInAndPropertyIdAndBookDateBetween(roomIds, propertyId, checkinDate, checkoutDate); for (CfgRoomCriteriasDaylightView c : criterias) { if (c.getIsWaitlist() == 0) { CfgAppChannelDaylight channel = new CfgAppChannelDaylight(); Set channels = c.getChannels(); for (CfgAppChannelDaylight a : channels) { if (a.getBlockCodeId().intValue() == blockId.intValue()) channel = a; } if (channel.getAvailable() > 0) { resultList.add(c.getRoom().getName()); } } } return resultList; } private int getMatchPropertyId(List properties, String name) { int matchId = 0; for (CfgProperties item : properties) { if (name.equalsIgnoreCase(item.getName())) { matchId = item.getId().intValue(); break; } } return matchId; } private long getMatchRoomId(List roomCates, String name, Long propertyId) { long matchId = 0; for (CfgRooms item : roomCates) { int pId = 0; if (propertyId != null) { pId = Integer.valueOf(String.valueOf(propertyId)); } if (name.equalsIgnoreCase(item.getName()) && pId == item.getPropertyId().intValue()) { matchId = item.getId().intValue(); break; } } return matchId; } private long getMatchBlockCodeId(List blockCodes, String name) { long matchId = 0; for (CfgBlockCodes item : blockCodes) { if (name.equalsIgnoreCase(item.getCode())) { matchId = item.getId(); break; } } return matchId; } private ValidateResult validateImportData(List roomCriteriaList, String category) { ValidateResult result = new ValidateResult(); int totalRows = 0; int failedRows = 0; int successRows = 0; Map uniqueKeys = new HashMap(); if (!roomCriteriaList.isEmpty()) { List categoryRoomIds = new ArrayList(); if (category.equalsIgnoreCase("WAIT_LIST")) { categoryRoomIds = roomDao.queryWaitlistRoomIds(); } else { categoryRoomIds = roomDao.queryBookingRoomIds(); } SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd"); totalRows = roomCriteriaList.size(); List propertyList = propertyDao.findAll(); List roomList = roomDao.findAll(); List blockCodeList = blockCodeDao.findAll(); if (!propertyList.isEmpty()) { for (int i = 0; i < propertyList.size(); i++) { CfgProperties pItem = propertyList.get(i); if (!"DAYLIGHT".equalsIgnoreCase(pItem.getCategory())) { propertyList.remove(i); i--; } } } for (int i = 0; i < roomCriteriaList.size(); i++) { String errMsg = ""; boolean isPassed = true; RoomCriteriaDaylightImportRow pItem = roomCriteriaList.get(i); if (StringUtils.isBlank(pItem.getPropertyName())) { errMsg += "Property Name is blank;"; isPassed = false; } else { int propertyId = this.getMatchPropertyId(propertyList, pItem.getPropertyName()); if (propertyId > 0) { pItem.setPropertyId((long) propertyId); } else { errMsg += "No match Property of [" + pItem.getPropertyName() + "];"; isPassed = false; } } if (StringUtils.isBlank(pItem.getBookDateText())) { errMsg += "Date is blank;"; isPassed = false; } else { LocalDateTime bookDate = null; try { if (DateTimeUtil.isValidDate(pItem.getBookDateText())) { bookDate = DateTimeUtil.getDateFromString(pItem.getBookDateText(), "yyyy-MM-dd"); } } catch (Exception ignored) { } if (bookDate != null) { pItem.setBookDate(bookDate); } else { errMsg += "Date value should be yyyy-mm-dd format;"; isPassed = false; } } if (StringUtils.isBlank(pItem.getRoomCategory())) { errMsg += "Room Group is blank;"; isPassed = false; } else { long roomId = this.getMatchRoomId(roomList, pItem.getRoomCategory(), pItem.getPropertyId()); if (roomId > 0) { pItem.setRoomId(roomId); if (!categoryRoomIds.contains(pItem.getRoomId())) { errMsg += ("Room Group [" + pItem.getRoomCategory() + "] is not for create " + ("WAIT_LIST".equalsIgnoreCase(category) ? "wait list" : "booking") + ";"); isPassed = false; } } else { errMsg += "No match Room Group of [" + pItem.getRoomCategory() + "];"; isPassed = false; } } if (isPassed) { String bizKey = pItem.getPropertyId() + "-" + pItem.getBookDateText() + "-" + pItem.getRoomCategory(); if (uniqueKeys.containsKey(bizKey)) { errMsg += "Duplicate records [" + pItem.getPropertyName() + "--" + pItem.getBookDateText() + "--" + pItem.getRoomCategory() + "] in list"; isPassed = false; } else { uniqueKeys.put(bizKey, bizKey); } } if (isPassed) { if ("BOOKING".equalsIgnoreCase(category)) { if (StringUtils.isBlank(pItem.getSharerValue())) { errMsg += "Sharer Flag is blank;"; isPassed = false; } else { if ("YES".equalsIgnoreCase(pItem.getSharerValue())) { pItem.setSharerFlag(1); } else if ("NO".equalsIgnoreCase(pItem.getSharerValue())) { pItem.setSharerFlag(0); } else { errMsg += "Sharer should be value of [Yes/No];"; isPassed = false; } } } if (StringUtils.isBlank(pItem.getWaitListValue())) { errMsg += "Waitlist Flag is blank;"; isPassed = false; } else { if ("YES".equalsIgnoreCase(pItem.getWaitListValue())) { pItem.setWaitlistFlag(1); } else if ("NO".equalsIgnoreCase(pItem.getWaitListValue())) { pItem.setWaitlistFlag(0); } else { errMsg += "Waitlist should be value of [Yes/No];"; isPassed = false; } } int rate = 0; try { rate = Integer.parseInt(pItem.getRateValue()); } catch (Exception err) { } pItem.setRate(rate); } if (isPassed && "BOOKING".equalsIgnoreCase(category)) { List appChannelRows = pItem.getChannelList(); if (appChannelRows != null && !appChannelRows.isEmpty()) { for (AppChannelDaylightImportRow channelRow : appChannelRows) { if (StringUtils.isBlank(channelRow.getBlockCodeName())) { errMsg += "Empty Block Code;"; isPassed = false; } else { long blockCodeId = this.getMatchBlockCodeId(blockCodeList, channelRow.getBlockCodeName()); if (blockCodeId > 0) { channelRow.setBlockCodeId(blockCodeId); } else { errMsg += "No Match Block name [" + channelRow.getBlockCodeName() + "];"; isPassed = false; } if (StringUtils.isBlank(channelRow.getChannelTotalVal())) { channelRow.setChannelTotal(0); } else { try { channelRow.setChannelTotal(Integer.parseInt(channelRow.getChannelTotalVal())); } catch (Exception err) { errMsg += "Invalid number of app channel for block code [" + channelRow.getBlockCodeName() + "];"; isPassed = false; } } } } } else { errMsg += "No any app channel is set;"; isPassed = false; } } if (isPassed) { if (criteriaDaylightDao.countByKeys(pItem.getPropertyId(), pItem.getBookDate(), pItem.getRoomId()) > 0) { errMsg += "Record exists"; isPassed = false; } } pItem.setValidatePassed(isPassed); pItem.setErrorMessage(errMsg); if (isPassed) successRows++; else failedRows++; } //-- } result.setResultCount(totalRows); result.setPassedCount(successRows); result.setFailedCount(failedRows); result.setResultRows(roomCriteriaList); return result; } public ServiceResult parseImportExcel(String importFilePath, String category) { ServiceResult result = new ServiceResult(); String importName = "WAIT_LIST".equalsIgnoreCase(category) ? "IMPORT_WAITLIST_CRITERIA" : "IMPORT_ROOM_CRITERIA"; ImportDefine importDef = ExcelUtils.getImportDefineByName(importName); if (importDef != null) { List blocks = blockDao.findAll(); List blockItems = new ArrayList(); for (CfgBlocks block : blocks) { GroupItem groupItem = new GroupItem(); groupItem.setItemText(block.getName()); groupItem.setItemKey(block.getId().toString()); groupItem.setHeaderIndex(1); blockItems.add(groupItem); } Map> groupInfos = new HashMap<>(); groupInfos.put("CHANNEL_GROUP", blockItems); ServiceResult importResult = ExcelUtils.importDataBlock(importDef, importFilePath, groupInfos); if (!importResult.isSuccess()) { result.setSuccess(false); result.setErrorMessage(importResult.getErrorMessage()); } else { if (importResult.getReturnData() != null) { List dataList = (List) importResult.getReturnData(); if (!dataList.isEmpty()) { List roomCriteriaList = (List) dataList.getFirst(); ValidateResult validateRes = validateImportData(roomCriteriaList, category); if (validateRes.getResultCount() > 0) { result.setSuccess(true); validateRes.setGroupItems(groupInfos.get("CHANNEL_GROUP")); result.setReturnData(validateRes); } else { result.setSuccess(false); result.setErrorMessage("No import data detected"); } } else { result.setSuccess(false); result.setErrorMessage("No import data detected"); } } else { result.setSuccess(false); result.setErrorMessage("Empty import data"); } } } else { result.setSuccess(false); result.setErrorMessage("Import [" + importName + "] not defined"); } return result; } public ServiceResult importBatch(List importRows, String category) { ServiceResult result = new ServiceResult(); if (importRows != null && !importRows.isEmpty()) { ValidateResult validateRes = validateImportData(importRows, category); if (validateRes.getResultCount() > 0 && validateRes.getFailedCount() <= 0) { LocalDateTime currentTime = LocalDateTime.now(); List newAppChannelList = new ArrayList(); for (RoomCriteriaDaylightImportRow pItem : importRows) { CfgRoomCriteriasDaylight newRoomCriteria = new CfgRoomCriteriasDaylight(); newRoomCriteria.setPropertyId(pItem.getPropertyId()); newRoomCriteria.setBookDate(pItem.getBookDate()); newRoomCriteria.setRoomId(pItem.getRoomId()); newRoomCriteria.setRate(pItem.getRate()); newRoomCriteria.setIsWaitlist(pItem.getWaitlistFlag()); newRoomCriteria.setSharer(pItem.getSharerFlag()); newRoomCriteria.setCreatedAt(currentTime); newRoomCriteria.setUpdatedAt(currentTime); newRoomCriteria.setBookDow(newRoomCriteria.getBookDate().getDayOfWeek().getValue()); criteriaDaylightDao.save(newRoomCriteria); if ("BOOKING".equalsIgnoreCase(category)) { List channelRows = pItem.getChannelList(); for (AppChannelDaylightImportRow channelRow : channelRows) { CfgAppChannelDaylight appChannel = new CfgAppChannelDaylight(); appChannel.setCriteriaId(newRoomCriteria.getId()); appChannel.setBlockCodeId(channelRow.getBlockCodeId()); appChannel.setChannelTotal(channelRow.getChannelTotal()); appChannel.setPickedUp(0); appChannel.setAvailable(appChannel.getChannelTotal()); newAppChannelList.add(appChannel); } } } if (!newAppChannelList.isEmpty()) { appChannelDaylightDao.saveAll(newAppChannelList); } result.setSuccess(true); } else { result.setSuccess(false); result.setErrorMessage("Import data validate failed"); result.setReturnData(validateRes); } } else { result.setSuccess(false); result.setErrorMessage("Empty import data"); } return result; } public List listRoomCriteriasViewToExport(QueryRoomCriteriaRequest queryFilter) { DateTimeFormatter dtFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd"); List listRoomCriteriaView = this.listRoomCriteriasView(queryFilter); for (CfgRoomCriteriasDaylightViewDto exportItem : listRoomCriteriaView) { //--Set special content for export if (exportItem.getProperty() != null) { exportItem.setPropertyName(exportItem.getProperty().getName()); } if (exportItem.getBookDate() != null) { exportItem.setBookDateText(dtFormat.format(exportItem.getBookDate())); } if (exportItem.getBookDow() != null) { try { int dayIndex = exportItem.getBookDow(); if (dayIndex >= 1 && dayIndex <= 7) { exportItem.setBookWeekDay(this.dayNames[dayIndex - 1]); } } catch (Exception ignored) { } } if (exportItem.getRoom() != null) { exportItem.setRoomCategory(exportItem.getRoom().getName()); List roomTypes = exportItem.getRoom().getRoomRoomType(); if (roomTypes != null) { StringBuilder roomTypeNames = new StringBuilder(); for (CfgRoomTypes roomType : roomTypes) { if (!roomTypeNames.toString().isEmpty()) { roomTypeNames.append(","); } roomTypeNames.append(roomType.getCode()); } exportItem.setRoomTypeNames(roomTypeNames.toString()); } } Set appChannels = exportItem.getChannels(); List appChannelList = new ArrayList(); if (appChannels != null && !appChannels.isEmpty()) { appChannelList.addAll(appChannels); } exportItem.setChannelList(appChannelList); exportItem.setRateValue(String.valueOf(exportItem.getRate())); exportItem.setSharerValue(exportItem.getSharer() != null && exportItem.getSharer() > 0 ? "Yes" : "No"); exportItem.setWaitListValue(exportItem.getIsWaitlist() != null && exportItem.getIsWaitlist() > 0 ? "Yes" : "No"); } return listRoomCriteriaView; } //-- Catch mapping data to reduce private Map cacheDlRoomTypeMapping(){ Map cacheData = new HashMap(); List dlRoomTypes = roomTypeDao.findAllByDlRoomTypeIdIsNotNull(); for(CfgRoomTypes roomType: dlRoomTypes){ cacheData.put(roomType.getDlRoomTypeId(),roomType.getId()); } return cacheData; } private Map cachePropertyRoomCategory(Long propertyId){ Map cacheData = new HashMap(); List propertyRoomMappings = roomRoomTypeDao.queryPropertyRoomMapping(propertyId); for(CfgRoomsRoomTypes roomRoomType: propertyRoomMappings){ cacheData.put(roomRoomType.getRoomTypeId(),roomRoomType.getRoomId()); } return cacheData; } private Map cacheDlBlockCodeMapping(Long propertyId){ Map cacheData = new HashMap(); List dlBlockCodes = blockCodeDao.findAllByPropertyIdAndDlBlockIdIsNotNull(propertyId); for(CfgBlockCodes blockCode: dlBlockCodes){ cacheData.put(blockCode.getDlBlockId(),blockCode.getId()); } return cacheData; } public void calculateDaylightAllotment(DlAllotmentUpdateRequest syncRequest) { if(syncRequest!=null){ CfgRoomCriteriasDaylight roomAllotment = null; List roomCriterias = criteriaDaylightDao.findByRoomIdAndPropertyIdAndBookDate( syncRequest.getRoomId(), syncRequest.getPropertyId(), syncRequest.getCalendarDate().atStartOfDay() ); if(!roomCriterias.isEmpty()){ roomAllotment = roomCriterias.getFirst(); if(roomCriterias.size()>1){ //-- Remove duplicated records if has for(int i=1;i existAppChannels = appChannelDaylightDao.findAllByCriteriaIdAndBlockCodeId(allotmentId,syncRequest.getBlockCodeId()); if(!existAppChannels.isEmpty()){ appChannel = existAppChannels.getFirst(); for(int i=1;i queryParams = new HashMap<>(); queryParams.put("blockIds", String.join(",", cacheMapping.getCacheBlockCodes().keySet())); queryParams.put("startDate", syncRequest.getFromDate()); queryParams.put("endDate", syncRequest.getToDate()); String responseContent = httpService.sslGet(url, headers, queryParams); DlBlockAvailabilityResponse responseData = JSONObject.parseObject(responseContent, DlBlockAvailabilityResponse.class); if(responseData == null || responseData.getResults() == null){ result.setSuccess(false); result.setMessage(responseContent); return result; } List calculateRequests = new ArrayList<>(); MissMappingLog missMappingLog = new MissMappingLog(); for (BlockAvailabilityResult blockResult : responseData.getResults()) { List changeItems = this.processBlockAvailabilityResult( syncRequest.getDlPropertyId(), propertyId, blockResult, cacheMapping, missMappingLog); calculateRequests.addAll(changeItems); } if (!missMappingLog.getMissDlRoomTypeIds().isEmpty()) { for(String missDlRoomTypeId:missMappingLog.getMissDlRoomTypeIds()){ log.warn("[SYNC_CALENDAR]No Room Type config match with daylight ID[{}]",missDlRoomTypeId); } } if (!missMappingLog.getMissRoomCateIds().isEmpty()) { for(Long missRoomCateId:missMappingLog.getMissRoomCateIds()){ log.warn("[SYNC_CALENDAR]No Room Category(RoomId) config match with room type ID[{}]",missRoomCateId); } } if (!missMappingLog.getMissBlockCodeIds().isEmpty()) { for(String missDlBlockCodeId:missMappingLog.getMissBlockCodeIds()){ log.warn("[SYNC_CALENDAR]No Block code config match with daylight ID[{}]",missDlBlockCodeId); } } if(!calculateRequests.isEmpty()){ for(DlAllotmentUpdateRequest calculateRequest:calculateRequests){ this.calculateDaylightAllotment(calculateRequest); } result.setMessage("["+calculateRequests.size()+"] Allotment Calendar Entries is(are) updated"); }else{ result.setMessage("No Allotment Calendar Entry is updated"); } result.setSuccess(true); } catch (Exception err) { result.setSuccess(false); result.setMessage("Failed to Sync DayLight Allotment:"+err.getMessage()); log.error("Failed to Sync DayLight Allotment :{}", err.getMessage()); } return result; } private List processBlockAvailabilityResult(String dlPropertyId, Long propertyId, BlockAvailabilityResult blockResult, MappingDataCache cacheMapping, MissMappingLog missMappingLog) { List calculateRequests = new ArrayList<>(); String dlBlockCodeId = blockResult.getId(); String allotmentDateVal = blockResult.getDate(); if (blockResult.getRoomTypeAvailabilities() == null) return calculateRequests; Map cacheRoomTypeIds = cacheMapping.getCacheRoomTypeIds(); Map cacheBlockCodes = cacheMapping.getCacheBlockCodes(); Map cacheRoomCate = cacheMapping.getCachePropertyRoomCate(); Set calculateKeys = new HashSet<>(); List allExistingAllotments = daylightRoomTypeAllotmentDao.queryAllotmentByPropertyAndBlockCodeAndDate(dlPropertyId, dlBlockCodeId, allotmentDateVal); Map> existingAllotmentMap = allExistingAllotments.stream() .collect(Collectors.groupingBy(CfgDlRoomTypeAllotment::getDaylightRoomTypeId)); List toSaveList = new ArrayList<>(); List toDeleteList = new ArrayList<>(); for (RoomTypeAvailability rtAvail : blockResult.getRoomTypeAvailabilities()) { String dlRoomTypeId = rtAvail.getRoomTypeId(); AllocationVariants variants = rtAvail.getAllocationVariants(); if (variants == null) continue; int available = variants.getAvailable() != null ? Math.max(variants.getAvailable(), 0) : 0; int deducted = variants.getCreatesDeduct() != null ? Math.max(variants.getCreatesDeduct(), 0) : 0; Long roomTypeId = null; Long blockCodeId = null; Long roomId = null; if (StringUtils.isNotBlank(dlRoomTypeId)) { roomTypeId = cacheRoomTypeIds.get(dlRoomTypeId); if (roomTypeId != null) { roomId = cacheRoomCate.get(roomTypeId); if (roomId == null && !missMappingLog.getMissRoomCateIds().contains(roomTypeId)) { missMappingLog.getMissRoomCateIds().add(roomTypeId); } } else { if (!missMappingLog.getMissDlRoomTypeIds().contains(dlRoomTypeId)) { missMappingLog.getMissDlRoomTypeIds().add(dlRoomTypeId); } } } if (StringUtils.isNotBlank(dlBlockCodeId)) { blockCodeId = cacheBlockCodes.get(dlBlockCodeId); if (blockCodeId == null && !missMappingLog.getMissBlockCodeIds().contains(dlBlockCodeId)) { missMappingLog.getMissBlockCodeIds().add(dlBlockCodeId); } } CfgDlRoomTypeAllotment matchAllotment = null; List roomAllotments = existingAllotmentMap.getOrDefault(dlRoomTypeId, new ArrayList<>()); if (!roomAllotments.isEmpty()) { matchAllotment = roomAllotments.getFirst(); for (int i = 1; i < roomAllotments.size(); i++) { toDeleteList.add(roomAllotments.get(i)); } } if (matchAllotment == null) { matchAllotment = new CfgDlRoomTypeAllotment(); matchAllotment.setAllotmentDate(allotmentDateVal); matchAllotment.setDaylightPropertyId(dlPropertyId); matchAllotment.setDaylightRoomTypeId(dlRoomTypeId); matchAllotment.setDaylightBlockCodeId(dlBlockCodeId); matchAllotment.setPropertyId(propertyId); matchAllotment.setRoomTypeId(roomTypeId); matchAllotment.setBlockCodeId(blockCodeId); matchAllotment.setCreatedAt(LocalDateTime.now()); } matchAllotment.setAllNonDeduct(available); matchAllotment.setAllDeduct(deducted - available); matchAllotment.setTotalRooms(deducted); matchAllotment.setUpdatedAt(LocalDateTime.now()); matchAllotment.setUpdateSource("SYNC_CALENDAR"); toSaveList.add(matchAllotment); if (roomId != null && propertyId != null && blockCodeId != null) { String allotmentKey = allotmentDateVal + "-" + propertyId + "-" + roomId + "-" + blockCodeId; if (!calculateKeys.contains(allotmentKey)) { DlAllotmentUpdateRequest syncUpdateReq = new DlAllotmentUpdateRequest(); syncUpdateReq.setPropertyId(propertyId); syncUpdateReq.setBlockCodeId(blockCodeId); syncUpdateReq.setRoomId(roomId); syncUpdateReq.setCalendarDate(LocalDate.parse(allotmentDateVal, DateTimeFormatter.ofPattern("yyyy-MM-dd"))); syncUpdateReq.setUpdateSource("SYNC_CALENDAR"); calculateRequests.add(syncUpdateReq); calculateKeys.add(allotmentKey); } } } if (!toSaveList.isEmpty()) { daylightRoomTypeAllotmentDao.saveAll(toSaveList); } if (!toDeleteList.isEmpty()) { daylightRoomTypeAllotmentDao.deleteAllInBatch(toDeleteList); } return calculateRequests; } }