# PastReservationCreditLimitParseByOpera.java

    package cloud.wconnect.frontoffice.service.pastreservation.report.listener.creditlimit;

    import cloud.wconnect.commonlib.cons.BaseErrorCodeEnum;
    import cloud.wconnect.commonlib.cons.SystemPlatformEnum;
    import cloud.wconnect.commonlib.exception.ParseReportException;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.frontoffice.pojo.bo.pastreservation.CreditLimitInfoBO;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.google.common.collect.Lists;
    import org.apache.commons.lang3.StringUtils;
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.Node;
    import org.dom4j.io.SAXReader;
    import org.springframework.stereotype.Service;

    import java.io.InputStream;
    import java.math.BigDecimal;
    import java.util.*;
    import java.util.stream.Collectors;

    /**
     * @author yyt
     * 2024/12/12
     */
    @Service
    @DS("logbook")
    public class PastReservationCreditLimitParseByOpera implements IPastReservationCreditLImitParse {

        /**
         * 判断支持的平台
         *
         * @param source 平台数据源
         * @return boolean
         * @author yyt
         * @date 2024/12/12
         */
        @Override
        public boolean supports(String source) {
            return SystemPlatformEnum.OPERA.getDesc().equals(source);
        }

        /**
         * 解析报告数据
         *
         * @param inputStream 文件流
         * @param propertyDTO 资产
         * @return credit limit
         * @author yyt
         * @date 2024/12/12
         */
        @Override
        public List<CreditLimitInfoBO> parsReport(InputStream inputStream, PropertyDTO propertyDTO) {
            try {
                Document document = new SAXReader().read(inputStream);
                List<Node> nodes = document.selectNodes("//G_HEADER");
                if (nodes.isEmpty()) {
                    return Collections.emptyList();
                }

                List<CreditLimitInfoBO> creditLimitInfoBOS = Lists.newArrayListWithExpectedSize(nodes.size());
                for (Node node : nodes) {
                    Element element = (Element) node;
                    CreditLimitInfoBO creditLimitInfo = new CreditLimitInfoBO();
                    creditLimitInfo.setFullName(element.elementText("FULL_NAME").trim());
                    String room = element.elementText("ROOM");
                    creditLimitInfo.setRoomNumber(Objects.isNull(room) ? StringUtils.EMPTY : room.trim());

                    String totalBalance = element.elementText("TOTAL_BALANCE_DISP");
                    creditLimitInfo.setTotalBalance(StringUtils.isEmpty(totalBalance) ? BigDecimal.ZERO : new BigDecimal(totalBalance));

                    String totalApprovalAmount = element.elementText("TOTAL_APPROVAL_AMOUNT_DISP");
                    creditLimitInfo.setTotalApprovalAmount(StringUtils.isEmpty(totalApprovalAmount) ? BigDecimal.ZERO : new BigDecimal(totalApprovalAmount));

                    creditLimitInfoBOS.add(creditLimitInfo);
                }

                // 数据去重（姓名、房间号）
                return creditLimitInfoBOS.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(CreditLimitInfoBO::getUniKey))), ArrayList::new));
            } catch (Exception e) {
                throw new ParseReportException(BaseErrorCodeEnum.SYSTEM_ERROR.getI18nCode(),
                        BaseErrorCodeEnum.SYSTEM_ERROR.getCode(), "parse credit limit report error." + e, e);
            }
        }

    }