Files
mgm-daylight-mcrm-api-cms/src/main/java/com/mgm/mcrm/allotment/services/RoomCriteriaDaylightService.java
T
2026-10-12 15:16:50 +08:00

1525 lines
67 KiB
Java

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<String> 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<String> dow = criteriaRequest.getDow();
List<CfgAppChannelDaylight> channelList = new ArrayList<CfgAppChannelDaylight>();
if (criteriaRequest.getBlockCodeChannels() != null && !criteriaRequest.getBlockCodeChannels().isEmpty()) {
List<BlockCodeChannelDto> 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<CfgRoomCriteriasDaylight> roomCriteriaList = new ArrayList<CfgRoomCriteriasDaylight>();
criteriaObj.setId(null);
criteriaObj.setBookDate(bookDate);
criteriaObj.setCreatedAt(createDate);
criteriaObj.setBookDow(bDay);
List<CfgRoomCriteriasDaylight> 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<BlockCodeChannelDto> 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<CfgRoomCriteriasDaylight> 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<CfgAppChannelDaylight> saveChannel = new ArrayList<CfgAppChannelDaylight>();
List<CfgRoomCriteriasDaylightView> 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<Long> 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<Long> 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<CfgAppChannelDaylight> 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<CfgRoomCriteriasDaylight> getRoomCriteriaByPage(QueryRoomCriteriaRequest queryFilter) {
List<Long> categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory());
Specification<CfgRoomCriteriasDaylight> 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<CfgRoomCriteriasDaylight> resultPage = criteriaDaylightDao.findAll(listSpec, pageable);
DataTableResult<CfgRoomCriteriasDaylight> dataResult = new DataTableResult<>();
dataResult.setTotalRecords(resultPage.getTotalElements());
dataResult.setPageSize(pageSize);
List<CfgRoomCriteriasDaylight> resultList = resultPage.getContent();
dataResult.setRowData(resultList);
return dataResult;
}
public DataTableResult<CfgRoomCriteriasDaylightViewDto> getRoomCriteriaViewByPage(QueryRoomCriteriaRequest queryFilter) {
//--先主表找分页,然后再按照分页结果找View的对象
List<Long> categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory());
Specification<CfgRoomCriteriasDaylight> 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<CfgRoomCriteriasDaylight> resultPage = criteriaDaylightDao.findAll(listSpec, pageable);
DataTableResult<CfgRoomCriteriasDaylightViewDto> dataResult = new DataTableResult<>();
dataResult.setTotalRecords(resultPage.getTotalElements());
dataResult.setPageSize(pageSize);
List<CfgRoomCriteriasDaylightViewDto> resultList = new ArrayList<>();
List<CfgRoomCriteriasDaylight> masterPageData = resultPage.getContent();
if (!masterPageData.isEmpty()) {
List<Long> ids = new ArrayList<Long>();
for (CfgRoomCriteriasDaylight item : masterPageData) {
ids.add(item.getId());
}
queryFilter.setPageIds(ids);
resultList = this.listRoomCriteriasView(queryFilter);
}
dataResult.setRowData(resultList);
return dataResult;
}
private List<Long> getCategoryRoomIds(String category) {
List<Long> result = new ArrayList<>();
if (StringUtils.isNotBlank(category)) {
List<Long> 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<CfgRoomCriteriasDaylight> listRoomCriteria(QueryRoomCriteriaRequest queryFilter) {
List<Long> categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory());
Specification<CfgRoomCriteriasDaylight> listSpec = buildSpecificationByQueryFilter(queryFilter, categoryRoomIds);
Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc");
return criteriaDaylightDao.findAll(listSpec, sort);
}
public List<CfgRoomCriteriasDaylightViewDto> listRoomCriteriasView(QueryRoomCriteriaRequest queryFilter) {
List<Long> categoryRoomIds = this.getCategoryRoomIds(queryFilter.getSearchCategory());
Specification<CfgRoomCriteriasDaylightView> listSpec = buildSpecificationViewByQueryFilter(queryFilter, categoryRoomIds);
Sort sort = DaoUtil.buildSortByString(queryFilter.getSortOrder(), "bookDate-desc");
List<CfgRoomCriteriasDaylightView> resultList = criteriaDaylightViewDao.findAll(listSpec, sort);
return cfgRoomCriteriaDaylightMapper.toViewDtoList(resultList);
}
private Specification<CfgRoomCriteriasDaylight> buildSpecificationByQueryFilter(QueryRoomCriteriaRequest queryFilter, List<Long> cateRoomIds) {
return (root, criteriaQuery, cb) -> {
List<Predicate> 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<String> 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<Long> roomIds = queryFilter.getSearchRoomId();
if (!roomIds.isEmpty()) {
list.add(root.get("roomId").in(roomIds));
}
}
if (queryFilter.getSearchDow() != null) {
List<Integer> 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<CfgRoomCriteriasDaylightView> buildSpecificationViewByQueryFilter(QueryRoomCriteriaRequest queryFilter, List<Long> cateRoomIds) {
return (root, criteriaQuery, cb) -> {
List<Predicate> 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<String> 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<Long> roomIds = queryFilter.getSearchRoomId();
if (!roomIds.isEmpty()) {
list.add(root.get("roomId").in(roomIds));
}
}
if (queryFilter.getSearchDow() != null) {
List<Integer> weekDays = queryFilter.getSearchDow();
if (!weekDays.isEmpty()) {
list.add(root.get("bookDow").in(weekDays));
}
}
if (queryFilter.getPageIds() != null) {
List<Long> 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<String, JSONObject> listRoomCriteriaCalendar(CheckCalendarDaylightRequest checkCalendarRequest) throws Exception {
Map<String, JSONObject> 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<String, JSONObject> getDaylightCriteria(Long blockCodeId, Long teamId, Long bookingTypeId, Long propertyId, Long roomId, String userId) throws Exception {
Long roomTypeId = null;
List<Long> roomIds = new ArrayList<>();
roomIds.add(roomId);
Map<String, JSONObject> 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<CfgDaylightViewDto> teamOpera = new ArrayList<>();
List<CfgExceptionDaylightViewDto> exceptionOpera = new ArrayList<>();
// 如果有BedTypeId根据BedTypeId拿到RoomTypeId List后随机,否则按RoomId
List<CfgRoomsRoomTypesDto> 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<CfgExceptionDaylightViewDto> 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<CfgDaylightViewDto> 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<CfgRoomCriteriasDaylightDto> 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<CfgAppChannelDaylight> 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<String, JSONObject> getOtherCriteria(Long segmentId, Long teamId, Long bookingTypeId, Long propertyId, Long roomId) throws Exception {
Long roomTypeId = null;
List<Long> 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<String, JSONObject> resultList = new HashMap<>();
List<CfgOtherUserMappingDto> userMappingList;
if (segmentId == null) {
// 筛选出符合条件的 mapping记录
userMappingList = cfgOtherUserMapper.toCfgOtherUserMappingDtoList(otherUserMappingDao.findByPropertyIdAndBookingTypeId(propertyId, Long.valueOf(bookingTypeId)));
if (!userMappingList.isEmpty()) {
segmentId = userMappingList.getFirst().getSegmentId();
}
}
List<CfgOtherAllotmentViewDto> 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<CfgOtherAppChannelDto> 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<String, JSONObject> checkCriteriaBooking(Map<String, JSONObject> 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<BookingsView> bookingList = bookingViewDao.getCalendarBooking(endDate, playerId);
Set<LocalDateTime> protectionPeriod = new HashSet<>();
Set<LocalDateTime> 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<String> listRoomCriteriaAvailableRoom(Map<String, Object> queryParas) {
HashSet<String> resultList = new HashSet<>();
List<String> selectDate = (List<String>) 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<Long> roomIds = new ArrayList<>();
roomIds.add(roomId);
String category = queryParas.get("category") != null ? queryParas.get("category").toString() : "";
if (StringUtils.isBlank(category)) {
category = "BOOKING";
}
List<CfgRoomCriteriasDaylightView> criterias = criteriaDaylightViewDao.findByRoomIdNotInAndPropertyIdAndBookDateBetween(roomIds, propertyId, checkinDate, checkoutDate);
for (CfgRoomCriteriasDaylightView c : criterias) {
if (c.getIsWaitlist() == 0) {
CfgAppChannelDaylight channel = new CfgAppChannelDaylight();
Set<CfgAppChannelDaylight> 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<CfgProperties> 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<CfgRooms> 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<CfgBlockCodes> 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<RoomCriteriaDaylightImportRow> roomCriteriaList, String category) {
ValidateResult result = new ValidateResult();
int totalRows = 0;
int failedRows = 0;
int successRows = 0;
Map<String, String> uniqueKeys = new HashMap<String, String>();
if (!roomCriteriaList.isEmpty()) {
List<Long> categoryRoomIds = new ArrayList<Long>();
if (category.equalsIgnoreCase("WAIT_LIST")) {
categoryRoomIds = roomDao.queryWaitlistRoomIds();
} else {
categoryRoomIds = roomDao.queryBookingRoomIds();
}
SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd");
totalRows = roomCriteriaList.size();
List<CfgProperties> propertyList = propertyDao.findAll();
List<CfgRooms> roomList = roomDao.findAll();
List<CfgBlockCodes> 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<AppChannelDaylightImportRow> 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<CfgBlocks> blocks = blockDao.findAll();
List<GroupItem> blockItems = new ArrayList<GroupItem>();
for (CfgBlocks block : blocks) {
GroupItem groupItem = new GroupItem();
groupItem.setItemText(block.getName());
groupItem.setItemKey(block.getId().toString());
groupItem.setHeaderIndex(1);
blockItems.add(groupItem);
}
Map<String, List<GroupItem>> 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<Object> dataList = (List<Object>) importResult.getReturnData();
if (!dataList.isEmpty()) {
List<RoomCriteriaDaylightImportRow> roomCriteriaList = (List<RoomCriteriaDaylightImportRow>) 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<RoomCriteriaDaylightImportRow> 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<CfgAppChannelDaylight> newAppChannelList = new ArrayList<CfgAppChannelDaylight>();
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<AppChannelDaylightImportRow> 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<CfgRoomCriteriasDaylightViewDto> listRoomCriteriasViewToExport(QueryRoomCriteriaRequest queryFilter) {
DateTimeFormatter dtFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
List<CfgRoomCriteriasDaylightViewDto> 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<CfgRoomTypes> 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<CfgAppChannelDaylight> appChannels = exportItem.getChannels();
List<CfgAppChannelDaylight> appChannelList = new ArrayList<CfgAppChannelDaylight>();
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<String,Long> cacheDlRoomTypeMapping(){
Map<String,Long> cacheData = new HashMap<String,Long>();
List<CfgRoomTypes> dlRoomTypes = roomTypeDao.findAllByDlRoomTypeIdIsNotNull();
for(CfgRoomTypes roomType: dlRoomTypes){
cacheData.put(roomType.getDlRoomTypeId(),roomType.getId());
}
return cacheData;
}
private Map<Long, Long> cachePropertyRoomCategory(Long propertyId){
Map<Long, Long> cacheData = new HashMap<Long,Long>();
List<CfgRoomsRoomTypes> propertyRoomMappings = roomRoomTypeDao.queryPropertyRoomMapping(propertyId);
for(CfgRoomsRoomTypes roomRoomType: propertyRoomMappings){
cacheData.put(roomRoomType.getRoomTypeId(),roomRoomType.getRoomId());
}
return cacheData;
}
private Map<String,Long> cacheDlBlockCodeMapping(Long propertyId){
Map<String,Long> cacheData = new HashMap<String,Long>();
List<CfgBlockCodes> 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<CfgRoomCriteriasDaylight> 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<roomCriterias.size();i++){
criteriaDaylightDao.delete(roomCriterias.get(i));
}
}
}
LocalDateTime currentTime = LocalDateTime.now();
if(roomAllotment==null){
roomAllotment = new CfgRoomCriteriasDaylight();
roomAllotment.setPropertyId(syncRequest.getPropertyId());
roomAllotment.setBookDate(syncRequest.getCalendarDate().atStartOfDay());
roomAllotment.setRoomId(syncRequest.getRoomId());
roomAllotment.setRate(0);
roomAllotment.setIsWaitlist(0);
roomAllotment.setSharer(1);
roomAllotment.setCreatedAt(currentTime);
roomAllotment.setUpdatedAt(currentTime);
roomAllotment.setBookDow(roomAllotment.getBookDate().getDayOfWeek().getValue());
criteriaDaylightDao.save(roomAllotment);
}
Long allotmentId = roomAllotment.getId();
//--
DaylightRoomTypeAllotmentDao.DaylightBlockCodeAllotmentSum roomAllotmentSum = daylightRoomTypeAllotmentDao.countRoomTypeAllotmentByBlockCode(
syncRequest.getCalendarDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
syncRequest.getPropertyId(),
syncRequest.getRoomId(),
syncRequest.getBlockCodeId()
);
CfgAppChannelDaylight appChannel=null;
List<CfgAppChannelDaylight> existAppChannels = appChannelDaylightDao.findAllByCriteriaIdAndBlockCodeId(allotmentId,syncRequest.getBlockCodeId());
if(!existAppChannels.isEmpty()){
appChannel = existAppChannels.getFirst();
for(int i=1;i<existAppChannels.size();i++){
appChannelDaylightDao.delete(existAppChannels.get(i));
}
}
if(appChannel==null){
appChannel = new CfgAppChannelDaylight();
appChannel.setCriteriaId(allotmentId);
appChannel.setBlockCodeId(syncRequest.getBlockCodeId());
appChannel.setCreatedAt(LocalDateTime.now());
appChannel.setCreatedSource(syncRequest.getUpdateSource());
}
appChannel.setChannelTotal(roomAllotmentSum.getChannelTotal());
appChannel.setPickedUp(roomAllotmentSum.getPickedUp());
appChannel.setAvailable(roomAllotmentSum.getAvailable());
appChannelDaylightDao.save(appChannel);
}
}
public AjaxResult syncCalendarAllotment(SyncDaylightAllotmentRequest syncRequest) {
AjaxResult result = new AjaxResult();
try {
CfgProperties cfgProperty = propertyDao.findByDlPropertyId(syncRequest.getDlPropertyId());
if (cfgProperty == null) {
result.setSuccess(false);
result.setMessage("No property config match with this dlPropertyId ["+syncRequest.getDlPropertyId()+"]");
return result;
}
if (syncRequest.getDlBlockCodeIds()==null || syncRequest.getDlBlockCodeIds().isEmpty()) {
result.setSuccess(false);
result.setMessage("Daylight Block Code ID list can not be null or empty");
return result;
}
SysAgebucket sysAgebucket = agebucketService.getSysAgebucket(syncRequest.getDlPropertyId());
syncRequest.setAgeBucketId(sysAgebucket.getDlAgeBucketId());
Long propertyId = cfgProperty.getId();
MappingDataCache cacheMapping = new MappingDataCache();
cacheMapping.setCacheRoomTypeIds(this.cacheDlRoomTypeMapping());
cacheMapping.setCachePropertyRoomCate(this.cachePropertyRoomCategory(propertyId));
cacheMapping.setCacheBlockCodes(this.cacheDlBlockCodeMapping(propertyId));
String url = "/api-gateway/data-api/v1/blocks/availability";
Header[] headers = HttpHeaderBuilder.create()
.contentType("application/json")
.ac_property_id(syncRequest.getDlPropertyId())
.build();
Map<String, Object> 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<DlAllotmentUpdateRequest> calculateRequests = new ArrayList<>();
MissMappingLog missMappingLog = new MissMappingLog();
for (BlockAvailabilityResult blockResult : responseData.getResults()) {
List<DlAllotmentUpdateRequest> 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<DlAllotmentUpdateRequest> processBlockAvailabilityResult(String dlPropertyId,
Long propertyId,
BlockAvailabilityResult blockResult,
MappingDataCache cacheMapping,
MissMappingLog missMappingLog) {
List<DlAllotmentUpdateRequest> calculateRequests = new ArrayList<>();
String dlBlockCodeId = blockResult.getId();
String allotmentDateVal = blockResult.getDate();
if (blockResult.getRoomTypeAvailabilities() == null) return calculateRequests;
Map<String, Long> cacheRoomTypeIds = cacheMapping.getCacheRoomTypeIds();
Map<String, Long> cacheBlockCodes = cacheMapping.getCacheBlockCodes();
Map<Long, Long> cacheRoomCate = cacheMapping.getCachePropertyRoomCate();
Set<String> calculateKeys = new HashSet<>();
List<CfgDlRoomTypeAllotment> allExistingAllotments = daylightRoomTypeAllotmentDao.queryAllotmentByPropertyAndBlockCodeAndDate(dlPropertyId, dlBlockCodeId, allotmentDateVal);
Map<String, List<CfgDlRoomTypeAllotment>> existingAllotmentMap = allExistingAllotments.stream()
.collect(Collectors.groupingBy(CfgDlRoomTypeAllotment::getDaylightRoomTypeId));
List<CfgDlRoomTypeAllotment> toSaveList = new ArrayList<>();
List<CfgDlRoomTypeAllotment> 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<CfgDlRoomTypeAllotment> 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;
}
}