# ParseGuestsInHouseComplimentaryByOther.java

    package cloud.wconnect.frontoffice.parsereport.comproom.impl;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.CommonErrorI18nConstant;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.exception.BadRequestException;
    import cloud.wconnect.commonlib.exception.InternalServerErrorException;
    import cloud.wconnect.commonlib.exception.ParseReportException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyBusinessDateRedisService;
    import cloud.wconnect.commonlib.util.CellUtils;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.I18nMessageUtils;
    import cloud.wconnect.commonlib.util.UploadUtils;
    import cloud.wconnect.frontoffice.entity.comproom.CompRoomReportLog;
    import cloud.wconnect.frontoffice.parsereport.comproom.IParseGuestsInHouseComplimentary;
    import cloud.wconnect.frontoffice.pojo.bo.comproom.GuestsInHouseComplimentaryBO;
    import cloud.wconnect.frontoffice.pojo.bo.comproom.GuestsInHouseComplimentaryWrapperBO;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomComplimentaryService;
    import cloud.wconnect.frontoffice.service.comproom.ICompRoomReportLogService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.google.common.collect.Lists;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.usermodel.WorkbookFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.web.multipart.MultipartFile;

    import java.io.IOException;
    import java.io.InputStream;
    import java.text.MessageFormat;
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeParseException;
    import java.util.*;

    /**
     * 解析Guests In-House Complimentary报告
     *
     * @author lichen
     * @date 2023/8/7
     */
    @Slf4j
    @Service
    @DS("logbook")
    public class ParseGuestsInHouseComplimentaryByOther implements IParseGuestsInHouseComplimentary {

        @Autowired
        private ICompRoomComplimentaryService compRoomComplimentaryService;
        @Autowired
        private ICompRoomReportLogService compRoomReportLogService;
        @Autowired
        private I18nMessageUtils i18nMessageUtils;
        @Autowired
        private PropertyBusinessDateRedisService propertyBusinessDateRedisService;

        /**
         * 支持的报告源
         *
         * @param source 报告来源
         * @return boolean
         * @author lichen
         * @date 2023/8/7
         */
        @Override
        public boolean supports(String source) {
            return SystemPlatformEnum.OTHER.getDesc().equals(source);
        }

        /**
         * 解析报告
         *
         * @param in 文件流
         * @return java.util.List<cloud.wconnect.frontoffice.pojo.bo.comproom.GuestsInHouseComplimentaryBO>
         * @author lichen
         * @date 2023/8/7
         */
        @Override
        public List<GuestsInHouseComplimentaryBO> parse(InputStream in) throws ParseReportException {
            try(Workbook workbook = WorkbookFactory.create(in)) {
                Sheet sheet = workbook.getSheetAt(0);
                //获取最大行数
                int lastRowNum = sheet.getLastRowNum();
                //只包含标题
                if (lastRowNum < 1) return Collections.emptyList();

                ArrayList<GuestsInHouseComplimentaryBO> resultList = Lists.newArrayList();

                for (int i = 1; i <= lastRowNum; i++) {
                    Row row = sheet.getRow(i);

                    GuestsInHouseComplimentaryBO guestsInHouseComplimentaryBO = new GuestsInHouseComplimentaryBO();
                    //客人姓名
                    guestsInHouseComplimentaryBO.setGuestName(CellUtils.convertCellStr(row.getCell(0)));
                    //入住日期
                    guestsInHouseComplimentaryBO.setArrivalDate(CellUtils.convertCellStr(row.getCell(1)));
                    //退房日期
                    guestsInHouseComplimentaryBO.setDepartureDate(CellUtils.convertCellStr(row.getCell(2)));
                    //成年人数
                    String adultsNumberStr = CellUtils.convertCellStr(row.getCell(3));
                    if (StringUtils.isNotBlank(adultsNumberStr)) {
                        guestsInHouseComplimentaryBO.setAdultsNumber(Integer.valueOf(adultsNumberStr));
                    }
                    //儿童人数
                    String childrenNumberStr = CellUtils.convertCellStr(row.getCell(4));
                    if (StringUtils.isNotBlank(childrenNumberStr)) {
                        guestsInHouseComplimentaryBO.setChildrenNumber(Integer.valueOf(childrenNumberStr));
                    }
                    //房间号
                    guestsInHouseComplimentaryBO.setRoomNumber(CellUtils.convertCellStr(row.getCell(5)));
                    //房间类型
                    guestsInHouseComplimentaryBO.setRoomType(CellUtils.convertCellStr(row.getCell(6)));
                    //备注
                    String comment = CellUtils.convertCellStr(row.getCell(7));
                    if (StringUtils.isNotBlank(comment)) {
                        guestsInHouseComplimentaryBO.setCommentList(Lists.newArrayList(comment));
                    }
                    resultList.add(guestsInHouseComplimentaryBO);
                }
                return resultList;
            } catch (Exception e) {
                throw new ParseReportException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(),
                        "parse [Guests In-House Complimentary] excel error", e);
            }
        }

        /**
         * 校验文件内容是否合法
         *
         * @param file 文件
         * @return void
         * @author lichen
         * @date 2024/7/29
         */
        @Override
        public void checkFile(MultipartFile file) {
            //校验文件格式
            UploadUtils.checkFileFormat(file, Lists.newArrayList("xlsx", "xls"));
            try (InputStream in = file.getInputStream();
                 Workbook workbook = WorkbookFactory.create(in)) {
                Sheet sheet = workbook.getSheetAt(0);
                //获取最大行数
                int lastRowNum = sheet.getLastRowNum();
                //只包含标题
                if (lastRowNum < 1) return;

                //标题行
                Row titleRow = sheet.getRow(0);
                //标题集合
                ArrayList<String> titles = Lists.newArrayList();
                for (int i = 0; i < 8; i++) {
                    titles.add(CellUtils.convertCellStr(titleRow.getCell(i)));
                }

                DateTimeFormatter formatter = DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYYY_MM_DD, Locale.ENGLISH);

                for (int i = 1; i <= lastRowNum; i++) {
                    Row row = sheet.getRow(i);

                    //客人姓名
                    String guestName = CellUtils.convertCellStr(row.getCell(0));
                    if (StringUtils.isEmpty(guestName)) {
                        //获取国际化的参数
                        Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(0));
                        throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY, language2ParamList,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                "The guest name cannot be null");
                    } else {
                        if (guestName.length() > 60) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(0),
                                    "60");
                            throw new BadRequestException(CommonErrorI18nConstant.OVERLENGTH, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The guest name length cannot be greater than 60, guestName = " + guestName);
                        }
                    }

                    //入住日期
                    String checkInDateStr = CellUtils.convertCellStr(row.getCell(1));
                    LocalDate checkInDateOfLocalDate = null;
                    if (StringUtils.isEmpty(checkInDateStr)) {
                        //获取国际化的参数
                        Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(1));
                        throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY, language2ParamList,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                "The check-in date cannot be null");
                    } else {
                        try {
                            checkInDateOfLocalDate = LocalDate.parse(checkInDateStr, formatter);
                        } catch (DateTimeParseException e) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(1),
                                    BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                            throw new BadRequestException(CommonErrorI18nConstant.FORMAT_INCORRECT, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The check-in date format is incorrect, check-in date = " + checkInDateStr);
                        }
                    }

                    //退房日期
                    String checkOutDateStr = CellUtils.convertCellStr(row.getCell(2));
                    LocalDate checkOutDateOfLocalDate = null;
                    if (StringUtils.isEmpty(checkOutDateStr)) {
                        //获取国际化的参数
                        Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(2));
                        throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY, language2ParamList,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                "The check-out date cannot be null");
                    } else {
                        try {
                            checkOutDateOfLocalDate = LocalDate.parse(checkOutDateStr, formatter);
                        } catch (DateTimeParseException e) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(2),
                                    BaseConstant.DATE_FORMAT_YYYY_MM_DD);
                            throw new BadRequestException(CommonErrorI18nConstant.FORMAT_INCORRECT, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The check-out date format is incorrect, check-out date = " + checkOutDateStr);
                        }
                    }

                    //校验入住日期不能晚于退房日期
                    if (checkInDateOfLocalDate.isAfter(checkOutDateOfLocalDate)) {
                        throw new BadRequestException(CommonErrorI18nConstant.CHECK_IN_DATE_CANNOT_GREATER_THAN_CHECK_OUT_DATE,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                MessageFormat.format("Check-in Date Cannot Be Later Than Check-out Date, check-in date:{0}, check-out date:{1}", checkInDateStr, checkOutDateStr));
                    }

                    //成年人数
                    String adultsNumberStr = CellUtils.convertCellStr(row.getCell(3));
                    if (StringUtils.isNotEmpty(adultsNumberStr)) {
                        try {
                            Integer adultsNumber = Integer.valueOf(adultsNumberStr);
                            if (adultsNumber.compareTo(Integer.valueOf("0")) < 0) {
                                //获取国际化的参数
                                Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(3));
                                throw new BadRequestException(CommonErrorI18nConstant.CANNOT_LESS_THAN_ZERO, language2ParamList,
                                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                        "The adults number cannot be less than 0, adultsNumberStr  = " + adultsNumberStr);
                            }
                        } catch (NumberFormatException exception) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(3));
                            throw new BadRequestException(CommonErrorI18nConstant.MUST_INTEGER, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The adults number must be a number, adultsNumberStr  = " + adultsNumberStr);
                        }
                    }

                    //儿童人数
                    String childrenNumberStr = CellUtils.convertCellStr(row.getCell(4));
                    if (StringUtils.isNotEmpty(childrenNumberStr)) {
                        try {
                            Integer childrenNumber = Integer.valueOf(childrenNumberStr);
                            if (childrenNumber.compareTo(Integer.valueOf("0")) < 0) {
                                //获取国际化的参数
                                Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(4));
                                throw new BadRequestException(CommonErrorI18nConstant.CANNOT_LESS_THAN_ZERO, language2ParamList,
                                        BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                        "The children number cannot be less than 0, childrenNumberStr  = " + childrenNumberStr);
                            }
                        } catch (NumberFormatException exception) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(4));
                            throw new BadRequestException(CommonErrorI18nConstant.MUST_INTEGER, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The children number must be a number, childrenNumberStr  = " + childrenNumberStr);
                        }
                    }

                    //房间号
                    String roomNumber = CellUtils.convertCellStr(row.getCell(5));
                    if (StringUtils.isEmpty(roomNumber)) {
                        //获取国际化的参数
                        Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(5));
                        throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY, language2ParamList,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                "The room number cannot be null");
                    } else {
                        if (roomNumber.length() > 10) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(5),
                                    "10");
                            throw new BadRequestException(CommonErrorI18nConstant.OVERLENGTH, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The room number length cannot be greater than 10, roomNumber = " + roomNumber);
                        }
                    }

                    //房间类型
                    String roomType = CellUtils.convertCellStr(row.getCell(6));
                    if (StringUtils.isEmpty(roomType)) {
                        //获取国际化的参数
                        Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(6));
                        throw new BadRequestException(CommonErrorI18nConstant.CANNOT_EMPTY, language2ParamList,
                                BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                "The room type cannot be null");
                    } else {
                        if (roomType.length() > 10) {
                            //获取国际化的参数
                            Map<String, List<Object>> language2ParamList = i18nMessageUtils.getErrorParamMapNotNeedTranslate(titles.get(6),
                                    "10");
                            //获取所有语言的错误描述
                            throw new BadRequestException(CommonErrorI18nConstant.OVERLENGTH, language2ParamList,
                                    BaseErrorCodeEnum.DATA_VALIDATION_ERROR.getCode(),
                                    "The room type length cannot be greater than 10, roomType = " + roomType);
                        }
                    }
                }
            } catch (IOException ioException) {
                throw new InternalServerErrorException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(), "parse [Guests In-House Complimentary] excel error");
            }
        }

        /**
         * 处理数据
         *
         * @param propertyDTO 资产DTO
         * @param file        文件
         * @param userId      操作人ID
         * @return void
         * @author lichen
         * @date 2024/7/29
         */
        @Override
        public void handleData(PropertyDTO propertyDTO, MultipartFile file, int userId) {
            try (InputStream inputStream = file.getInputStream()) {
                // 解析报告获得的数据
                List<GuestsInHouseComplimentaryBO> boList = parse(inputStream);

                // 获取当前日期
                String theDate = DateTimeUtils.dateNowStr(propertyDTO.getTimezone(), BaseConstant.DATE_FORMAT_YYYYMMDD);

                // 处理报告数据
                compRoomComplimentaryService.handleGuestsInHouseComplimentaryData(propertyDTO, boList, Long.valueOf(theDate));
                // 保存导入报告时间
                compRoomReportLogService.save(propertyDTO, CompRoomReportLog.REPORT_TYPE_GUESTS_IN_HOUSE_COMPLIMENTARY, userId);
            } catch (IOException e) {
                throw new InternalServerErrorException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(), "handle import [Guests In-House Complimentary] error", e);
            }
        }

    }