package com.yuchen.saas.park.service.service.property.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thinkunion.park.service.common.cache.CacheNames;
import com.yuchen.saas.manage.system.api.entity.NestOrgUser;
import com.yuchen.saas.manage.system.api.feign.ISysClient;
import com.yuchen.saas.manage.user.api.entity.User;
import com.yuchen.saas.manage.user.api.feign.IUserClient;
import com.yuchen.saas.park.api.dto.property.*;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.entity.property.*;
import com.yuchen.saas.park.api.enums.property.CreateBillTypeEnum;
import com.yuchen.saas.park.api.enums.property.MeterShareTypeEnum;
import com.yuchen.saas.park.api.vo.property.*;
import com.yuchen.saas.park.service.mapper.property.SaasParkPropertyAutoPublicMeterReadingMapper;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import com.yuchen.saas.park.service.service.property.*;
import com.yuchen.saas.park.service.service.property.bill.PropertyBillFactoryService;
import com.yuchen.saas.park.service.util.BigdecimalUtil;
import com.yuchen.saas.parking.api.util.DateUtils;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.NestPage;
import org.nest.springwrap.core.redis.lock.RedisLock;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.Func;
import org.nest.springwrap.core.tool.utils.SpringUtil;
import org.nest.springwrap.core.tool.utils.StringPool;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 自动抄表-公摊抄表 服务实现类
 * </p>
 *
 * @author miaoqs
 * @since 2024-09-30
 */
@Service
public class SaasParkPropertyAutoPublicMeterReadingServiceImpl extends BaseServiceImpl<SaasParkPropertyAutoPublicMeterReadingMapper, SaasParkPropertyAutoPublicMeterReading> implements SaasParkPropertyAutoPublicMeterReadingService {

    @Lazy
    @Resource
    private IPropertyPublicMeterService iPropertyPublicMeterService;

    @Resource
    private IPropertyMeterService iPropertyMeterService;

    @Resource
    private IPropertyPublicMeterReadingLogService iPropertyPublicMeterReadingLogService;

    @Resource
    private ISysClient sysClient;

    @Resource
    private IUserClient iUserClient;

    @Resource
    private IPropertyHouseMeterReadingService iPropertyHouseMeterReadingService;

    @Resource
    private IPropertyHouseMeterService iPropertyHouseMeterService;

    @Resource
    private IPropertyPublicMeterReadingShareService iPropertyPublicMeterReadingShareService;

    @Resource
    private IPropertyPublicMeterReadingShareDetailService iPropertyPublicMeterReadingShareDetailService;

    @Resource
    private IPropertyPublicMeterShareService iPropertyPublicMeterShareService;

    @Resource
    private PropertyHousesService propertyHousesService;

    @Resource
    private IPropertyPublicMeterReadingShareMeterService iPropertyPublicMeterReadingShareMeterService;

    @Resource
    private IPropertyHouseOwnerService iPropertyHouseOwnerService;

    @Resource
    private IPropertyCustomerArchivesService iPropertyCustomerArchivesService;

    @Resource
    private PmgBatParkInfoService pmgBatParkInfoService;

    @Resource
    private PropertyFeeStandardService propertyFeeStandardService;

    @Resource
    private PropertyBillFactoryService propertyBillFactoryService;

    @Resource
    private PropertyBillingSettingsService propertyBillingSettingsService;

    @Resource
    private IPropertyPublicMeterReadingService propertyPublicMeterReadingService;

    @Override
    public PropertyPublicMeterReadingForMeterVo listForMeter(PropertyPublicMeterReadingQueryDto dto) {
        PropertyPublicMeterReadingForMeterVo vo = new PropertyPublicMeterReadingForMeterVo();
        int totalMeterNum = 0;
        int totalReadNum = 0;
        int totalUnReadNum = 0;
        List<PropertyPublicMeter> list = iPropertyPublicMeterService.listByParkIdAndMeterId(dto.getParkId(), dto.getMeterId());
        if (Func.isEmpty(list)) {
            vo.setTotalMeterNum(totalMeterNum);
            vo.setTotalReadNum(totalReadNum);
            vo.setTotalUnReadNum(totalUnReadNum);
            vo.setList(new ArrayList<>());
            return vo;
        }
        Date monthFirstDayDate = DateUtils.getMonthFirstDayDate(dto.getMeterReadingTime());
        Date monthLastDayDate = DateUtils.getMonthLastDayDate(dto.getMeterReadingTime());
        Map<Long, PropertyPublicMeterReadingForMeterVo.PropertyPublicMeterReadingForMeterItemVo> buildingMap = new HashMap<>();
        for (PropertyPublicMeter item : list) {
            totalMeterNum++;
            PropertyPublicMeterReadingForMeterVo.PropertyPublicMeterReadingForMeterItemVo itemVo;
            if (buildingMap.containsKey(item.getMeterId())) {
                itemVo = buildingMap.get(item.getMeterId());
            } else {
                itemVo = new PropertyPublicMeterReadingForMeterVo.PropertyPublicMeterReadingForMeterItemVo();
                PropertyMeter meter = iPropertyMeterService.getById(item.getMeterId());
                if (Func.isNotEmpty(meter)) {
                    itemVo.setMeterName(meter.getMeterName());
                }
                itemVo.setMeterNum(0);
                itemVo.setReadNum(0);
                itemVo.setUnReadNum(0);
                itemVo.setShareNum(0);
                itemVo.setUnShareNum(0);
                buildingMap.put(item.getMeterId(), itemVo);
            }
            itemVo.setMeterNum(itemVo.getMeterNum() + 1);
            LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(PropertyPublicMeterReading::getPublicMeterId, item.getId())
                    .le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthLastDayDate)
                    .ge(Func.isNotEmpty(monthFirstDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthFirstDayDate);
            if (propertyPublicMeterReadingService.count(queryWrapper) > 0) {
                totalReadNum++;
                itemVo.setReadNum(itemVo.getReadNum() + 1);
            } else {
                totalUnReadNum++;
                itemVo.setUnReadNum(itemVo.getUnReadNum() + 1);
            }
            LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.eq(PropertyPublicMeterReading::getPublicMeterId, item.getId())
                    .eq(PropertyPublicMeterReading::getIsShare,1)
                    .le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthLastDayDate)
                    .ge(Func.isNotEmpty(monthFirstDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthFirstDayDate);
            if(propertyPublicMeterReadingService.count(queryWrapper2)> 0){
                itemVo.setShareNum(itemVo.getShareNum()+1);
            }else{
                itemVo.setUnShareNum(itemVo.getUnShareNum()+1);
            }

        }
        List<PropertyPublicMeterReadingForMeterVo.PropertyPublicMeterReadingForMeterItemVo> listVo = buildingMap.entrySet().stream()
                .map(e -> e.getValue())
                .collect(Collectors.toList());
        vo.setTotalMeterNum(totalMeterNum);
        vo.setTotalReadNum(totalReadNum);
        vo.setTotalUnReadNum(totalUnReadNum);
        vo.setList(listVo);
        return vo;
    }

    @Override
    public PropertyPublicMeterReading getByPublicMeterIdAndQuery(Long publicMeterId, Integer isInit, Integer isShare, Date monthFirstDayDate, Date monthLastDayDate, int firstOrLast) {
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PropertyPublicMeterReading::getPublicMeterId, publicMeterId)
                .eq(Func.isNotEmpty(isInit), PropertyPublicMeterReading::getIsInit, isInit)
                .eq(Func.isNotEmpty(isShare), PropertyPublicMeterReading::getIsShare, isShare)
                .le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthLastDayDate)
                .ge(Func.isNotEmpty(monthFirstDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthFirstDayDate);
        //.between(Func.isNotEmpty(monthFirstDayDate)&&Func.isNotEmpty(monthLastDayDate),PropertypublicMeterReading::getMeterReadingTime,monthFirstDayDate,monthLastDayDate)
        if (firstOrLast == 1) {
            queryWrapper.orderByDesc(PropertyPublicMeterReading::getMeterReadingTime,PropertyPublicMeterReading::getUpdateTime);
        }
        if (firstOrLast == 0) {
            queryWrapper.orderByAsc(PropertyPublicMeterReading::getMeterReadingTime,PropertyPublicMeterReading::getUpdateTime);
        }
        queryWrapper.last("limit 1");
        return propertyPublicMeterReadingService.getOne(queryWrapper);
    }

    @Override
    public Boolean addList(List<PropertyPublicMeterReadingAddDto> list) {
        StringBuilder stringBuilder = new StringBuilder();
        for (PropertyPublicMeterReadingAddDto item : list) {
            try {
                SpringUtil.getBean(IPropertyPublicMeterReadingService.class).add(item.getId(), item.getMeterReadingNum(), item.getMeterReadingTime(),false);
            } catch (ServiceException e) {
                stringBuilder.append(e.getMessage());
            }
        }
        if (stringBuilder.length() > 0) {
            throw new ServiceException(stringBuilder.toString());
        }
        return true;
    }

    @Override
    @RedisLock(value = CacheNames.LOCK_PUBLIC_METER_READING, param = "#publicMeterId", leaseTime = -1)
    public Boolean add(Long publicMeterId, BigDecimal meterReadingNum, Date meterReadingTime, Boolean isUpdate) {
        PropertyPublicMeter publicMeter = iPropertyPublicMeterService.getById(publicMeterId);
        if (Func.isEmpty(publicMeter)) {
            return false;
        }
        if(Func.isNotEmpty(publicMeter.getIsSealed())&&publicMeter.getIsSealed()==1){
            throw new ServiceException("资源代码{" + publicMeter.getMeterFullName() + "}已经封存无法进行抄表!");
        }
        if(Func.isNotEmpty(publicMeter.getIsMeterReading())&&publicMeter.getIsMeterReading()==0){
            throw new ServiceException("资源代码{" + publicMeter.getMeterFullName() + "}已设置不进行抄表!");
        }
        //把最新的抄表日期跟抄表读数记录在仪表上
        publicMeter.setFinallyMeterReadingNum(meterReadingNum);
        publicMeter.setFinallyMeterReadingTime(meterReadingTime);
        iPropertyPublicMeterService.updateById(publicMeter);

        //获取最新一条抄表记录
        PropertyPublicMeterReading publicMeterReading = getByPublicMeterIdAndQuery(publicMeterId, null, null, null, null, 1);
        //是不是更改仪表数据
        if(Func.isNotEmpty(isUpdate)&&isUpdate){
            if(Func.isNotEmpty(publicMeterReading)){
                if (Func.isNotEmpty(publicMeterReading.getIsInit()) && publicMeterReading.getIsInit() == 1) {
                    if (BigdecimalUtil.gt(meterReadingNum, publicMeter.getMaxNum())) {
                        throw new ServiceException("资源代码{" + publicMeter.getMeterFullName() + "}抄表数据不能大于仪表最大读数!");
                    }
                    publicMeterReading.setMeterReadingNum(meterReadingNum);
                    publicMeterReading.setMeterReadingTime(meterReadingTime);
                    return propertyPublicMeterReadingService.updateById(publicMeterReading);
                }
            }
        }
        if (Func.isEmpty(publicMeterReading)) {
            //如果为空的话,说明是初始记录,作为初始记录新增
            return addPublicMeterReading(publicMeter, 1, meterReadingTime, meterReadingNum, null, null, null, null);
        }
        //判断最新的一条是不是初始记录
        if (Func.isNotEmpty(publicMeterReading.getIsInit()) && publicMeterReading.getIsInit() == 1) {
            //是初始记录的话,不管是否计费都作为初始记录,
            return addPublicMeterReading(publicMeter, 0, meterReadingTime, meterReadingNum, publicMeterReading.getMeterReadingTime(),
                    publicMeterReading.getMeterReadingNum(), publicMeterReading.getId(), null);
        } else {
            //不是初始记录的话
            //判断是否已经计费
            if (Func.isNotEmpty(publicMeterReading.getIsShare()) && publicMeterReading.getIsShare() == 1) {
                //已经计费的话进行新增
                return addPublicMeterReading(publicMeter, 0, meterReadingTime, meterReadingNum, publicMeterReading.getMeterReadingTime(),
                        publicMeterReading.getMeterReadingNum(), publicMeterReading.getId(), null);
            } else {
                return addPublicMeterReading(publicMeter, 0, meterReadingTime, meterReadingNum, publicMeterReading.getLastMeterReadingTime(),
                        publicMeterReading.getLastMeterReadingNum(), publicMeterReading.getLastMeterReadingId(), publicMeterReading.getId());
            }
        }
    }

    @Override
    public NestPage<PropertyPublicMeterReadingDetailPageVo> getPageForDetail(PropertyPublicMeterReadingDetailQueryDto dto) {
        Page<PropertyPublicMeterReadingDetailPageVo> result = new Page<>();
        List<PropertyPublicMeterReadingDetailPageVo> resultList;
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper = Wrappers.lambdaQuery();
        if (Func.isNotEmpty(dto.getMeterReadingTime())) {
            Date monthFirstDayDate = DateUtils.getMonthFirstDayDate(dto.getMeterReadingTime());
            Date monthLastDayDate = DateUtils.getMonthLastDayDate(dto.getMeterReadingTime());
            queryWrapper.le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthLastDayDate)
                    .ge(Func.isNotEmpty(monthFirstDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthFirstDayDate);
        }
        queryWrapper.eq(Func.isNotEmpty(dto.getMeterId()), PropertyPublicMeterReading::getMeterId, dto.getMeterId())
                .eq(Func.isNotEmpty(dto.getParkId()), PropertyPublicMeterReading::getParkId, dto.getParkId())
                .eq(Func.isNotEmpty(dto.getIsShare()), PropertyPublicMeterReading::getIsShare, dto.getIsShare())
                .orderByDesc(PropertyPublicMeterReading::getMeterReadingTime);
        //已抄表数据
        if (Func.isNotEmpty(dto.getIsReading()) && dto.getIsReading() == 1) {
            IPage<PropertyPublicMeterReading> page = propertyPublicMeterReadingService.page(Condition.getPage(dto), queryWrapper);
            Func.copy(page, result);
            List<PropertyPublicMeterReading> list = page.getRecords();
            if (Func.isEmpty(list)) {
                return NestPage.of(result);
            }
            resultList = list.stream().map(a -> {
                PropertyPublicMeterReadingDetailPageVo vo = Func.copy(a, PropertyPublicMeterReadingDetailPageVo.class);
                buildDetailPageVo(vo);
                R<User> userR = iUserClient.userInfoById(vo.getCreateUser());
                if (userR.isSuccess() && Func.isNotEmpty(userR.getData())) {
                    vo.setPhone(userR.getData().getPhone());
                }

                return vo;
            }).collect(Collectors.toList());
        } else {
            List<PropertyPublicMeterReading> list = propertyPublicMeterReadingService.list(queryWrapper);
            LambdaQueryWrapper<PropertyPublicMeter> publicMeterQueryWrapper = Wrappers.lambdaQuery();
            if (Func.isNotEmpty(list)) {
                Set<Long> publicMeterIds = list.stream().map(a -> a.getPublicMeterId()).collect(Collectors.toSet());
                publicMeterQueryWrapper.notIn(PropertyPublicMeter::getId, publicMeterIds);
            }
            //初始日期要小于所选月份才进行显示
            if (Func.isNotEmpty(dto.getMeterReadingTime())) {
                Date monthLastDayDate = DateUtils.getMonthLastDayDate(dto.getMeterReadingTime());
                publicMeterQueryWrapper.le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeter::getInitTime, monthLastDayDate);
            }
            publicMeterQueryWrapper.eq(Func.isNotEmpty(dto.getMeterId()), PropertyPublicMeter::getMeterId, dto.getMeterId())
                    .eq(Func.isNotEmpty(dto.getParkId()), PropertyPublicMeter::getParkId, dto.getParkId())
                    .orderByDesc(PropertyPublicMeter::getCreateTime);
            IPage<PropertyPublicMeter> page = iPropertyPublicMeterService.page(Condition.getPage(dto), publicMeterQueryWrapper);
            Func.copy(page, result);
            List<PropertyPublicMeter> publicMeters = page.getRecords();
            if (Func.isEmpty(publicMeters)) {
                return NestPage.of(result);
            }
            resultList = publicMeters.stream().map(a -> {
                PropertyPublicMeterReadingDetailPageVo vo = Func.copy(a, PropertyPublicMeterReadingDetailPageVo.class);
                buildDetailPageVo(vo);
                return vo;
            }).collect(Collectors.toList());
        }
        result.setRecords(resultList);
        return NestPage.of(result);
    }

    @Override
    public Boolean deleteList(List<Long> ids) {
        if (Func.isEmpty(ids)) {
            throw new ServiceException("请选择要操作的记录!");
        }
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(PropertyPublicMeterReading::getId, ids)
                .and(wrapper -> wrapper
                        .or(item -> item
                                .eq(PropertyPublicMeterReading::getIsInit, 1))
                        .or(item -> item
                                .eq(PropertyPublicMeterReading::getIsShare, 1)));
        if (propertyPublicMeterReadingService.count(queryWrapper) > 0) {
            throw new ServiceException("删除数据存在初始记录或存在已分摊的记录,请重新刷新!");
        }
        return removeByIds(ids);
    }

    @Override
    public NestPage<PropertyPublicMeterReadingPageVo> getPageByReading(PropertyPublicMeterReadingQueryDto dto) {
        IPage<PropertyPublicMeterReading> page = propertyPublicMeterReadingService.page(Condition.getPage(dto), getReadingQuery(dto));
        IPage<PropertyPublicMeterReadingPageVo> result = new Page<>();
        Func.copy(page, result);
        List<PropertyPublicMeterReadingPageVo> list = page.getRecords().stream().map(a -> {
            PropertyPublicMeterReadingPageVo vo = Func.copy(a,PropertyPublicMeterReadingPageVo.class);
            PropertyPublicMeter publicMeter = iPropertyPublicMeterService.getById(a.getPublicMeterId());
            if (Func.isNotEmpty(publicMeter)) {
                vo.setPublicMeterName(publicMeter.getMeterFullName());
            }
            //未分摊的情况倍率跟用量取设置的倍率计算
            if (Func.isNotEmpty(a.getIsShare()) && a.getIsShare() == 0) {
                if (Func.isNotEmpty(publicMeter)) {
                    vo.setRate(publicMeter.getRate());
                    vo.setAttritionRate(publicMeter.getAttritionRate());
                    vo.setDosage(this.getDosage(a.getMeterReadingNum(), a.getLastMeterReadingNum(), publicMeter.getRate(),publicMeter.getAttritionRate(),publicMeter.getParkId()));
                }
            }
            return vo;
        }).collect(Collectors.toList());
        result.setRecords(list);
        return NestPage.of(result);
    }

    private LambdaQueryWrapper<PropertyPublicMeterReading> getReadingQuery(PropertyPublicMeterReadingQueryDto dto) {
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(PropertyPublicMeterReading::getParkId, dto.getParkId())
                .eq(Func.isNotEmpty(dto.getMeterId()), PropertyPublicMeterReading::getMeterId, dto.getMeterId())
                .eq(Func.isNotEmpty(dto.getIsShare()), PropertyPublicMeterReading::getIsShare, dto.getIsShare())
                .orderByDesc(PropertyPublicMeterReading::getMeterReadingTime);
        if (Func.isNotEmpty(dto.getMeterReadingTime())) {
            Date monthFirstDayDate = DateUtils.getMonthFirstDayDate(dto.getMeterReadingTime());
            Date monthLastDayDate = DateUtils.getMonthLastDayDate(dto.getMeterReadingTime());
            queryWrapper.le(Func.isNotEmpty(monthLastDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthLastDayDate)
                    .ge(Func.isNotEmpty(monthFirstDayDate), PropertyPublicMeterReading::getMeterReadingTime, monthFirstDayDate);
        }
        return queryWrapper;
    }

    @Override
    public PropertyPublicMeterReadingCountVo getShareCount(PropertyPublicMeterReadingQueryDto dto) {
        PropertyPublicMeterReadingCountVo vo = new PropertyPublicMeterReadingCountVo();
        vo.setTotalReadingNum(propertyPublicMeterReadingService.count(getReadingQuery(dto)));
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapperShare = getReadingQuery(dto);
        queryWrapperShare.eq(PropertyPublicMeterReading::getIsShare, 1);
        vo.setTotalShareNum(propertyPublicMeterReadingService.count(queryWrapperShare));
        LambdaQueryWrapper<PropertyPublicMeterReading> queryWrapperUnShare = getReadingQuery(dto);
        queryWrapperUnShare.eq(PropertyPublicMeterReading::getIsShare, 0);
        vo.setTotalUnShareNum(propertyPublicMeterReadingService.count(queryWrapperUnShare));
        return vo;
    }

    @RedisLock(value = CacheNames.LOCK_PUBLIC_METER_READING, param = "#meterReading.publicMeterId", leaseTime = -1)
    public Boolean share(PropertyPublicMeterReading meterReading, int i) {
        if (Func.isEmpty(meterReading)) {
            throw new ServiceException("所选数据已经不存在!");
        }
        PropertyPublicMeter publicMeter = iPropertyPublicMeterService.getById(meterReading.getPublicMeterId());
        if (Func.isEmpty(publicMeter)) {
            throw new ServiceException("抄表数据公摊仪表已经不存在!");
        }
        List<PropertyPublicMeterShare> propertyPublicMeterShares = iPropertyPublicMeterShareService.listByPublicMeterId(publicMeter.getId());
        if (Func.isEmpty(propertyPublicMeterShares)) {
            throw new ServiceException(String.format("%s 原因:%s", publicMeter.getMeterFullName(), "未添加分摊房间!"));
        }

        if (Func.isNotEmpty(meterReading.getIsShare()) && meterReading.getIsShare() == 1) {
            throw new ServiceException(String.format("%s 原因:%s", publicMeter.getMeterFullName(), "抄表数据已经被分摊!"));
        }
        if (Func.isEmpty(publicMeter.getChargingStandardId())) {
            throw new ServiceException(String.format("%s 原因:%s", publicMeter.getMeterFullName(), "仪表未绑定收费标准!"));
        }
        BigDecimal childTotalDosage = BigdecimalUtil.ZERO;
        List<PropertyPublicMeterReadingShareMeter> shareMeters=new ArrayList<>();
        //总表的话要先扣子表区间账单用量
        if (Func.isNotEmpty(publicMeter.getShareMeterType()) && publicMeter.getShareMeterType() == 2) {
            //获取子表用量,同时对子表未计费的抄表进行计费
            PropertyPublicMeterReadingShareMeterVo shareMeterVo = getChildDosage(publicMeter, meterReading, i);
            childTotalDosage=shareMeterVo.getChildTotalDosage();
            shareMeters=shareMeterVo.getShareMeters();
        }
        Date now = new Date();
        BigDecimal dosage = this.getDosage(meterReading.getMeterReadingNum(), meterReading.getLastMeterReadingNum(), publicMeter.getRate(),publicMeter.getAttritionRate(),publicMeter.getParkId());
        PropertyPublicMeterReadingShare dto = new PropertyPublicMeterReadingShare();
        dto.setParkId(publicMeter.getParkId());
        dto.setPublicMeterReadingId(meterReading.getId());
        dto.setPublicMeterId(publicMeter.getId());
        dto.setMeterId(publicMeter.getMeterId());
        dto.setShareMeterType(publicMeter.getShareMeterType());
        dto.setMeterFullName(publicMeter.getMeterFullName());
        dto.setShareType(publicMeter.getShareType());
        dto.setShareNum(BigdecimalUtil.subtract(dosage, childTotalDosage));
        dto.setTotalShareNum(dosage);
        dto.setShareTime(now);
        iPropertyPublicMeterReadingShareService.save(dto);
        if(Func.isNotEmpty(shareMeters)){
            for (PropertyPublicMeterReadingShareMeter item:shareMeters) {
                item.setParkId(dto.getParkId());
                item.setPublicMeterReadingShareId(dto.getId());
                item.setPublicMeterReadingId(dto.getPublicMeterReadingId());
                item.setPublicMeterId(dto.getPublicMeterId());
                item.setMeterId(item.getMeterId());
                item.setShareMeterType(dto.getShareMeterType());
                item.setMeterFullName(dto.getMeterFullName());
                item.setShareType(dto.getShareType());
                item.setShareNum(dto.getShareNum());
                item.setTotalShareNum(dto.getTotalShareNum());
                item.setShareTime(dto.getShareTime());
                item.setShareDosage(BigdecimalUtil.ZERO);
            }
        }

        BigDecimal itemDosage = BigdecimalUtil.ZERO;
        switch (MeterShareTypeEnum.matchCode(publicMeter.getShareType())) {
            case SHARE_ALIKE:
                for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                    itemDosage = getDosageDivide(dto.getShareNum(), new BigDecimal(propertyPublicMeterShares.size()),publicMeter.getParkId());
                    savePublicMeterReadingShareDetail(dto, itemDosage, item.getId(), item.getHouseId(), now, meterReading.getMeterReadingTime(), publicMeter, meterReading);
                }
                break;

            case SHARE_BY_AREA:
                //有分摊总面积取设置的分摊总面积 1
                if (Func.isNotEmpty(publicMeter.getShareArea()) && BigdecimalUtil.gt(publicMeter.getShareArea(), BigdecimalUtil.ZERO)) {
                    BigDecimal shareArea = publicMeter.getShareArea();
                    for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                        PropertyHouses houses = propertyHousesService.getById(item.getHouseId());
                        itemDosage = getDosageDivide(houses.getConstructionArea().multiply(dto.getShareNum()), shareArea,publicMeter.getParkId());
                        savePublicMeterReadingShareDetail(dto, itemDosage, item.getId(),item.getHouseId(),now, meterReading.getMeterReadingTime(), publicMeter, meterReading);
                    }
                } else {
                    BigDecimal shareArea = BigdecimalUtil.ZERO;
                    List<PropertyPublicMeterShareDto> publicMeterShareDtoList = new ArrayList<>();
                    for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                        PropertyHouses houses = propertyHousesService.getById(item.getHouseId());
                        if (Func.isNotEmpty(houses)) {
                            shareArea = BigdecimalUtil.add(shareArea, houses.getUseArea());
                            PropertyPublicMeterShareDto publicMeterShareDto = Func.copy(item, PropertyPublicMeterShareDto.class);
                            publicMeterShareDto.setConstructionArea(houses.getConstructionArea());
                            publicMeterShareDtoList.add(publicMeterShareDto);
                        }
                    }
                    for (PropertyPublicMeterShareDto item : publicMeterShareDtoList) {
                        itemDosage = getDosageDivide(item.getConstructionArea().multiply(dto.getShareNum()), shareArea,publicMeter.getParkId());
                        savePublicMeterReadingShareDetail(dto, itemDosage,item.getId(),item.getHouseId(), now, meterReading.getMeterReadingTime(), publicMeter, meterReading);
                    }
                }
                break;

            case SHARE_BY_USE_AREA:
                //有分摊总面积取设置的分摊总面积 1
                if (Func.isNotEmpty(publicMeter.getShareArea()) && BigdecimalUtil.gt(publicMeter.getShareArea(), BigdecimalUtil.ZERO)) {
                    BigDecimal shareArea = publicMeter.getShareArea();
                    for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                        PropertyHouses houses = propertyHousesService.getById(item.getHouseId());
                        itemDosage = getDosageDivide(houses.getUseArea().multiply(dto.getShareNum()), shareArea,publicMeter.getParkId());
                        savePublicMeterReadingShareDetail(dto, itemDosage,  item.getId(),item.getHouseId(), now, meterReading.getMeterReadingTime(), publicMeter, meterReading);
                    }
                } else {
                    BigDecimal shareArea = BigdecimalUtil.ZERO;
                    List<PropertyPublicMeterShareDto> publicMeterShareDtoList = new ArrayList<>();
                    for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                        PropertyHouses houses = propertyHousesService.getById(item.getHouseId());
                        if (Func.isNotEmpty(houses)) {
                            shareArea = BigdecimalUtil.add(shareArea, houses.getUseArea());
                            PropertyPublicMeterShareDto publicMeterShareDto = Func.copy(item, PropertyPublicMeterShareDto.class);
                            publicMeterShareDto.setUseArea(houses.getUseArea());
                            publicMeterShareDtoList.add(publicMeterShareDto);
                        }
                    }
                    for (PropertyPublicMeterShareDto item : publicMeterShareDtoList) {
                        itemDosage = getDosageDivide(item.getUseArea().multiply(dto.getShareNum()), shareArea,publicMeter.getParkId());
                        savePublicMeterReadingShareDetail(dto, itemDosage, item.getId(), item.getHouseId(), now,
                                meterReading.getMeterReadingTime(), publicMeter, meterReading);
                    }
                }
                break;


            case SHARE_BY_DOSAGE:

                BigDecimal totalDosage = BigdecimalUtil.ZERO;
                List<PropertyPublicMeterShareDto> addList = new ArrayList<>();
                //按产品的说法只考虑当前绑定的仪表不考虑历史的账单,所以不直接查账单,先查当前房间绑定的仪表,再查仪表的账单
                for (PropertyPublicMeterShare item : propertyPublicMeterShares) {
                    List<PropertyPublicMeterReadingShareMeter> shareMeters2=new ArrayList<>();
                    BigDecimal houseDosage = BigdecimalUtil.ZERO;
                    List<PropertyHouseMeter> houseMeters = iPropertyHouseMeterService.listByParentIdAndHouseId(publicMeter.getId(), item.getHouseId());
                    PropertyHouses houses = propertyHousesService.getById(item.getHouseId());
                    if (Func.isEmpty(houseMeters)) {

                        throw new ServiceException(String.format("%s 原因:%s %s", publicMeter.getMeterFullName(), Func.isNotEmpty(houses) ? houses.getHouseName() : StringPool.EMPTY, "房间没有绑定仪表!"));
                    }
                    boolean flag = false;
                    for (PropertyHouseMeter houseMeter : houseMeters) {
                        LambdaQueryWrapper<PropertyHouseMeterReading> houseMeterReadingQueryWrapper = Wrappers.lambdaQuery();
                        houseMeterReadingQueryWrapper.eq(PropertyHouseMeterReading::getHouseMeterId, houseMeter.getId())
                                .le(PropertyHouseMeterReading::getMeterReadingTime, meterReading.getMeterReadingTime())
                                .gt(Func.isNotEmpty(meterReading.getLastMeterReadingTime()), PropertyHouseMeterReading::getMeterReadingTime, meterReading.getLastMeterReadingTime());
                        List<PropertyHouseMeterReading> houseMeterReadings = iPropertyHouseMeterReadingService.list(houseMeterReadingQueryWrapper);
                        if (Func.isEmpty(houseMeterReadings)) {

                            throw new ServiceException(String.format("%s 原因:%s %s", publicMeter.getMeterFullName(), Func.isNotEmpty(houses) ? houses.getHouseName() : StringPool.EMPTY, "房间没有绑定仪表!"));
                        }
                        for (PropertyHouseMeterReading readingItem : houseMeterReadings) {
                            if (readingItem.getMeterReadingTime().equals(meterReading.getMeterReadingTime())) {
                                flag = true;
                            }
                            //如果是未抄表的进行抄表,
                            if (Func.isNotEmpty(item) && readingItem.getIsCharging() == 0) {
                                //生成计费
                                iPropertyHouseMeterReadingService.buildCharge(houseMeter.getId(),readingItem.getId(),null);

                                PropertyPublicMeterReadingShareMeter shareMeter= new PropertyPublicMeterReadingShareMeter();
                                shareMeter.setParkId(dto.getParkId());
                                shareMeter.setPublicMeterReadingShareId(dto.getId());
                                shareMeter.setPublicMeterReadingId(dto.getPublicMeterReadingId());
                                shareMeter.setPublicMeterId(dto.getPublicMeterId());
                                shareMeter.setMeterId(shareMeter.getMeterId());
                                shareMeter.setShareMeterType(dto.getShareMeterType());
                                shareMeter.setMeterFullName(dto.getMeterFullName());
                                shareMeter.setShareType(dto.getShareType());
                                shareMeter.setShareNum(dto.getShareNum());
                                shareMeter.setTotalShareNum(dto.getTotalShareNum());
                                shareMeter.setShareTime(dto.getShareTime());
                                shareMeter.setDosage(readingItem.getDosage());
                                shareMeter.setDeductionType(2);
                                shareMeter.setDeductionMeterType(1);
                                shareMeter.setDeductionMeterId(readingItem.getHouseMeterId());
                                shareMeter.setDeductionMeterReadingId(item.getId());
                                shareMeters2.add(shareMeter);
                            }
                            houseDosage = BigdecimalUtil.add(houseDosage, readingItem.getDosage());
                        }
                        if (!flag) {
                            throw new ServiceException(String.format("%s 原因:%s %s", publicMeter.getMeterFullName(), houseMeter.getMeterFullName(), "在总表当天未存在抄表计费记录!"));
                        }
                    }
                    totalDosage = BigdecimalUtil.add(totalDosage, houseDosage);
                    PropertyPublicMeterShareDto publicMeterShareDto = Func.copy(houses, PropertyPublicMeterShareDto.class);
                    publicMeterShareDto.setDosage(houseDosage);
                    publicMeterShareDto.setShareMeters(shareMeters2);
                    addList.add(publicMeterShareDto);
                }
                for (PropertyPublicMeterShareDto item : addList) {
                    itemDosage = getDosageDivide(item.getDosage().multiply(dto.getShareNum()), totalDosage,publicMeter.getParkId());
                    PropertyPublicMeterReadingShareDetail shareDatail= savePublicMeterReadingShareDetail(dto, itemDosage, item.getId(), item.getHouseId(), now, meterReading.getMeterReadingTime(), publicMeter, meterReading);
                    //记录相关仪表的分摊用量记录
                    for (PropertyPublicMeterReadingShareMeter shareMeter:item.getShareMeters()) {
                        itemDosage = getDosageDivide(item.getDosage().multiply(dto.getShareNum()), totalDosage,publicMeter.getParkId());
                        shareMeter.setShareDosage(itemDosage);
                        shareMeter.setPublicMeterReadingShareDetailId(shareDatail.getId());
                        iPropertyPublicMeterReadingShareMeterService.save(shareMeter);
                    }
                }

                break;
            case SHARE_BY_CUSTOM:
                throw new ServiceException("自定义公式暂未开放!");
            default:
                break;
        }
        if(Func.isNotEmpty(shareMeters)){
            iPropertyPublicMeterReadingShareMeterService.saveBatch(shareMeters);
        }


        meterReading.setIsShare(1);
        meterReading.setShareTime(now);
        meterReading.setDosage(dosage);
        meterReading.setRate(publicMeter.getRate());
        meterReading.setAttritionRate(publicMeter.getAttritionRate());
        return propertyPublicMeterReadingService.updateById(meterReading);
    }


    private PropertyPublicMeterReadingShareDetail savePublicMeterReadingShareDetail(PropertyPublicMeterReadingShare dto, BigDecimal dosage, Long publicMeterShareId, Long houseId, Date shareTime, Date meterReadingTime,PropertyPublicMeter publicMeter,PropertyPublicMeterReading meterReading) {
        PropertyPublicMeterReadingShareDetail detail = new PropertyPublicMeterReadingShareDetail();
        detail.setPublicMeterReadingShareId(dto.getId());
        detail.setDosage(dosage);
        detail.setParkId(dto.getParkId());
        detail.setPublicMeterReadingId(dto.getPublicMeterReadingId());
        detail.setPublicMeterShareId(publicMeterShareId);
        detail.setPublicMeterId(dto.getPublicMeterId());
        detail.setMeterId(dto.getMeterId());
        detail.setShareType(dto.getShareType());
        detail.setHouseId(houseId);
        detail.setTotalShareNum(dto.getTotalShareNum());
        detail.setShareNum(dto.getShareNum());
        detail.setShareTime(shareTime);
        detail.setIsCharging(1);
        detail.setMeterReadingTime(meterReadingTime);
        detail.setShareMeterType(dto.getShareMeterType());
        detail.setMeterFullName(dto.getMeterFullName());
        PropertyHouses houses = propertyHousesService.getById(houseId);
        if(Func.isNotEmpty(houses)){
            detail.setBuildingId(houses.getBuildingId());
            detail.setResourceCode(houses.getResourceCode());
        }
        PropertyHouseOwner houseOwner = iPropertyHouseOwnerService.getByHouseId(houseId);
        if(Func.isNotEmpty(houseOwner)){
            PropertyCustomerArchives customerArchives = iPropertyCustomerArchivesService.getById(houseOwner.getCustomerArchivesId());
            if(Func.isNotEmpty(customerArchives)){
                detail.setCustomerArchivesId(customerArchives.getId());
                detail.setCustomerName(customerArchives.getCustomerName());
            }
        }
        iPropertyPublicMeterReadingShareDetailService.save(detail);
        //生成计费
        CreateBillDto createBillDto= new CreateBillDto();
        createBillDto.setCreateBillTypeEnum(CreateBillTypeEnum.METER);
        PropertyMeterCreateBillDto meterCreateBillDto=new PropertyMeterCreateBillDto();
        meterCreateBillDto.setMeterReadingType(2);
        meterCreateBillDto.setMeterReadingId(detail.getId());
        meterCreateBillDto.setBuildingId(houses.getBuildingId());
        meterCreateBillDto.setHouseId(houses.getId());
        meterCreateBillDto.setFeeId(publicMeter.getChargingStandardId());
        PropertyFeeStandard feeStandard = propertyFeeStandardService.getById(publicMeter.getChargingStandardId());
        if(Func.isNotEmpty(feeStandard)){
            meterCreateBillDto.setFeeItemId(feeStandard.getFeeItemId());
        }
        meterCreateBillDto.setBillableQuantity(detail.getDosage());
        meterCreateBillDto.setStartDate(meterReading.getLastMeterReadingTime());
        meterCreateBillDto.setEndDate(meterReading.getMeterReadingTime());
        meterCreateBillDto.setMeterFullName(publicMeter.getMeterFullName());
        meterCreateBillDto.setLastMeterReadingNum(meterReading.getLastMeterReadingNum());
        meterCreateBillDto.setMeterReadingNum(meterReading.getMeterReadingNum());
        PropertyMeter meter = iPropertyMeterService.getById(meterReading.getMeterId());
        if(Func.isNotEmpty(meter)){
            meterCreateBillDto.setMeterUnit(meter.getUnit());
        }
        createBillDto.setMeterCreateBillDtoList(Arrays.asList(meterCreateBillDto));
        propertyBillFactoryService.createBill(createBillDto);
        return detail;
    }

    public PropertyPublicMeterReadingShareMeterVo getChildDosage(PropertyPublicMeter publicMeter, PropertyPublicMeterReading meterReading, int i) {
        List<PropertyPublicMeterReadingShareMeter> shareMeters=new ArrayList<>();
        if (i > 999) {
            //总表绑定避免死循环跳出
            throw new ServiceException(publicMeter.getMeterFullName() + "总表绑定异常请联系管理员");
        }
        //需扣减的子表的总量
        BigDecimal childTotalDosage = BigdecimalUtil.ZERO;
        //未计费需要计费的子表
        List<PropertyHouseMeterReading> chargingList = new ArrayList<>();

        //获取当前总表下的子表
        List<PropertyHouseMeter> houseMeters = iPropertyHouseMeterService.listByParentId(publicMeter.getId());
        if (Func.isNotEmpty(houseMeters)) {
            //同时要满足同一个子表必须有一条跟总表相同日期的计费抄表
            //获取区间历史已计费抄表记录//包含可能总表改到别的总表去的
            LambdaQueryWrapper<PropertyHouseMeterReading> houseMeterReadingQueryWrapper = Wrappers.lambdaQuery();
            houseMeterReadingQueryWrapper.in(PropertyHouseMeterReading::getHouseMeterId, houseMeters.stream().map(a->a.getId()).collect(Collectors.toList()))
                    .le(PropertyHouseMeterReading::getMeterReadingTime, meterReading.getMeterReadingTime())
                    .gt(Func.isNotEmpty(meterReading.getLastMeterReadingTime()), PropertyHouseMeterReading::getMeterReadingTime, meterReading.getLastMeterReadingTime());
            List<PropertyHouseMeterReading> houseMeterReadings = iPropertyHouseMeterReadingService.list(houseMeterReadingQueryWrapper);
            if (Func.isEmpty(houseMeterReadings)) {
                throw new ServiceException(String.format("%s 原因:%s", publicMeter.getMeterFullName(), "当前总表下的分表在当前时间段内未存在抄表计费记录!"));
            }
            Map<Long, List<PropertyHouseMeterReading>> map = houseMeterReadings.stream().collect(Collectors.groupingBy(PropertyHouseMeterReading::getHouseMeterId));
            for (PropertyHouseMeter item : houseMeters) {
                if (!map.containsKey(item.getId())) {
                    throw new ServiceException(String.format("%s 原因:%s %s", publicMeter.getMeterFullName(), item.getMeterFullName(), "该分表在当前时间段内未存在抄表计费记录!"));
                }
            }
            Iterator<Map.Entry<Long, List<PropertyHouseMeterReading>>> itr = map.entrySet().iterator();
            while (itr.hasNext()) {
                Map.Entry<Long, List<PropertyHouseMeterReading>> e = itr.next();
                List<PropertyHouseMeterReading> value = e.getValue();
                boolean flag = false;
                for (PropertyHouseMeterReading item : value) {

                    if (Func.isNotEmpty(item) && item.getIsCharging() == 0) {
                        PropertyHouseMeter byId = iPropertyHouseMeterService.getById(e.getKey());
                        //重新计费
                        item.setDosage(getDosage(item.getMeterReadingNum(), item.getLastMeterReadingNum(), byId.getRate(),byId.getAttritionRate(),publicMeter.getParkId()));
                        item.setRate(byId.getRate());
                        item.setAttritionRate(byId.getAttritionRate());
                        chargingList.add(item);
                    }
                    PropertyPublicMeterReadingShareMeter shareMeter= new PropertyPublicMeterReadingShareMeter();
                    shareMeter.setDosage(item.getDosage());
                    shareMeter.setDeductionType(1);
                    shareMeter.setDeductionMeterType(1);
                    shareMeter.setDeductionMeterId(item.getHouseMeterId());
                    shareMeter.setDeductionMeterReadingId(item.getId());
                    shareMeters.add(shareMeter);

                    childTotalDosage = BigdecimalUtil.add(childTotalDosage, item.getDosage());
                    //子表必须存在一条抄表时间跟当前总表同一天的
                    if (item.getMeterReadingTime().equals(meterReading.getMeterReadingTime())) {
                        flag = true;
                    }
                }
                if (!flag) {
                    PropertyHouseMeter byId = iPropertyHouseMeterService.getById(e.getKey());
                    throw new ServiceException(String.format("%s 原因:%s %s", Func.isNotEmpty(byId) ? byId.getMeterFullName() : StringPool.EMPTY, "该分表在当前时间段内未存在抄表计费记录!"));
                }
            }
        }

        //获取当前总表下的子表
        List<PropertyPublicMeter> publicMeters = iPropertyPublicMeterService.listByParentId(publicMeter.getId());
        if (Func.isNotEmpty(publicMeters)) {
            //公摊仪表的分表
            //未分摊的公摊仪表抄表记录
            List<PropertyPublicMeterReading> shareList = new ArrayList<>();
            LambdaQueryWrapper<PropertyPublicMeterReading> publicMeterReadingQueryWrapper = Wrappers.lambdaQuery();
            publicMeterReadingQueryWrapper.in(PropertyPublicMeterReading::getPublicMeterId, publicMeters.stream().map(a->a.getId()).collect(Collectors.toList()))
                    .le(PropertyPublicMeterReading::getMeterReadingTime, meterReading.getMeterReadingTime())
                    .gt(Func.isNotEmpty(meterReading.getLastMeterReadingTime()), PropertyPublicMeterReading::getMeterReadingTime, meterReading.getLastMeterReadingTime());
            List<PropertyPublicMeterReading> publicMeterReadings = propertyPublicMeterReadingService.list(publicMeterReadingQueryWrapper);
            if(Func.isEmpty(publicMeterReadings)){
                throw new ServiceException(String.format("%s 原因:%s", publicMeter.getMeterFullName(), "当前总表下的分表在当前时间段内未存在抄表计费记录!"));
            }
            Map<Long, List<PropertyPublicMeterReading>>  publicMap = publicMeterReadings.stream().collect(Collectors.groupingBy(PropertyPublicMeterReading::getPublicMeterId));
            for (PropertyHouseMeter item : houseMeters) {
                if (!publicMap.containsKey(item.getId())) {
                    throw new ServiceException(String.format("%s 原因:%s %s", publicMeter.getMeterFullName(), item.getMeterFullName(), "该分表在当前时间段内未存在抄表计费记录!"));
                }
            }
            Iterator<Map.Entry<Long, List<PropertyPublicMeterReading>>> publicitr = publicMap.entrySet().iterator();
            while (publicitr.hasNext()) {
                Map.Entry<Long, List<PropertyPublicMeterReading>> e = publicitr.next();
                List<PropertyPublicMeterReading> value = e.getValue();
                boolean flag = false;
                for (PropertyPublicMeterReading item : value) {
                    PropertyPublicMeterReadingShareMeter shareMeter= new PropertyPublicMeterReadingShareMeter();
                    shareMeter.setDosage(item.getDosage());
                    shareMeter.setDeductionType(1);
                    shareMeter.setDeductionMeterType(2);
                    shareMeter.setDeductionMeterId(item.getPublicMeterId());
                    shareMeter.setDeductionMeterReadingId(item.getId());
                    shareMeters.add(shareMeter);
                    childTotalDosage = BigdecimalUtil.add(childTotalDosage, item.getDosage());
                    if (Func.isNotEmpty(item) && item.getIsShare() == 0) {
                        shareList.add(item);
                    }
                    //子表必须存在一条抄表时间跟当前总表同一天的
                    if (item.getMeterReadingTime().equals(meterReading.getMeterReadingTime())) {
                        flag = true;
                    }
                }
                if (!flag) {
                    PropertyHouseMeter byId = iPropertyHouseMeterService.getById(e.getKey());
                    throw new ServiceException(String.format("%s 原因:%s %s", Func.isNotEmpty(byId) ? byId.getMeterFullName() : StringPool.EMPTY, "该分表在当前时间段内未存在抄表计费记录!"));
                }
            }
            if (Func.isNotEmpty(chargingList)) {
                //房源仪表生成计费,
                for (PropertyHouseMeterReading item : chargingList) {
                    iPropertyHouseMeterReadingService.buildCharge(item.getHouseMeterId(),item.getId(),null);
                }
            }

            //总表的子表是公摊表,未分摊,进行分摊
            if (Func.isNotEmpty(shareList)) {
                i++;
                for (PropertyPublicMeterReading item : shareList) {
                    try {
                        SpringUtil.getBean(PropertyPublicMeterReadingServiceImpl.class).share(item, i);
                    } catch (Exception e) {
                        throw new ServiceException(String.format("%s->%s", publicMeter.getMeterFullName(), e.getMessage()));
                    }

                }
            }
        }
        PropertyPublicMeterReadingShareMeterVo vo=new PropertyPublicMeterReadingShareMeterVo();
        vo.setChildTotalDosage(childTotalDosage);
        vo.setShareMeters(shareMeters);
        return vo;
    }


    private void buildDetailPageVo(PropertyPublicMeterReadingDetailPageVo vo) {
        PropertyMeter meter = iPropertyMeterService.getById(vo.getMeterId());
        if (Func.isNotEmpty(meter)) {
            vo.setMeterName(meter.getMeterName());
        }
        PropertyPublicMeter publicMeter = iPropertyPublicMeterService.getById(vo.getPublicMeterId());
        if (Func.isNotEmpty(publicMeter)) {
            vo.setMeterFullName(publicMeter.getMeterFullName());
            //未计费状态倍率取配置的,用量重新算
            if (Func.isNotEmpty(vo.getIsShare()) && vo.getIsShare() == 0) {
                vo.setRate(publicMeter.getRate());
                vo.setAttritionRate(publicMeter.getAttritionRate());
                vo.setDosage(this.getDosage(vo.getMeterReadingNum(), vo.getLastMeterReadingNum(), vo.getRate(), vo.getAttritionRate(),publicMeter.getParkId()));
            }
        }
    }

    private boolean addPublicMeterReading(PropertyPublicMeter publicMeter, Integer isInit, Date meterReadingTime,
                                          BigDecimal meterReadingNum, Date lastMeterReadingTime, BigDecimal lastMeterReadingNum,
                                          Long lastMeterReadingId, Long oldId) {
        if (Func.isNotEmpty(meterReadingTime) && Func.isNotEmpty(lastMeterReadingTime)) {
            if (meterReadingTime.getTime() <= lastMeterReadingTime.getTime()) {
                throw new ServiceException("仪表{" + publicMeter.getMeterFullName() + "}抄表日期不能早于已计费抄表记录的抄表日期!");
            }
        }
        if (Func.isEmpty(meterReadingNum)) {
            throw new ServiceException("仪表{" + publicMeter.getMeterFullName() + "}抄表数据不能为空!");
        }
        if (BigdecimalUtil.gt(meterReadingNum, publicMeter.getMaxNum())) {
            throw new ServiceException("仪表{" + publicMeter.getMeterFullName() + "}抄表数据不能大于仪表最大读数!");
        }
        PropertyPublicMeterReading publicMeterReading = new PropertyPublicMeterReading();
        publicMeterReading.setParkId(publicMeter.getParkId());
        publicMeterReading.setPublicMeterId(publicMeter.getId());
        publicMeterReading.setMeterId(publicMeter.getMeterId());
        publicMeterReading.setIsInit(isInit);
        publicMeterReading.setParentId(publicMeter.getParentId());
        //publicMeterReading.setIsCharging() 默认未计费,取数据库默认值
        publicMeterReading.setMeterReadingTime(meterReadingTime);
        publicMeterReading.setMeterReadingNum(meterReadingNum);
        publicMeterReading.setLastMeterReadingTime(lastMeterReadingTime);
        publicMeterReading.setLastMeterReadingNum(lastMeterReadingNum);
        publicMeterReading.setLastMeterReadingId(lastMeterReadingId);
        publicMeterReading.setRate(publicMeter.getRate());//未计费的情况是临时值
        publicMeterReading.setAttritionRate(publicMeter.getAttritionRate());
        ContextUser contextUser = AuthUtil.getUser();
        if (Func.isNotEmpty(contextUser)) {
            contextUser.getOrgUserId();
            R<NestOrgUser> orgUserR = sysClient.getOrgUserById(contextUser.getOrgUserId());
            if (orgUserR.isSuccess() && Func.isNotEmpty(orgUserR.getData())) {
                publicMeterReading.setOrgUserName(orgUserR.getData().getName());
            }
        }
        if (Func.isNotEmpty(meterReadingNum) && Func.isNotEmpty(lastMeterReadingNum)) {
            if (BigdecimalUtil.lt(meterReadingNum, lastMeterReadingNum)) {
                throw new ServiceException("仪表{" + publicMeter.getMeterFullName() + "}抄表数据不能小于上期读数!");
            }
            publicMeterReading.setDosage(this.getDosage(meterReadingNum, lastMeterReadingNum, publicMeter.getRate(),publicMeter.getAttritionRate(),publicMeter.getParkId()));
        }
        if (Func.isNotEmpty(oldId)) {
            publicMeterReading.setId(oldId);
        }
        Boolean flag = propertyPublicMeterReadingService.saveOrUpdate(publicMeterReading);
        if (flag) {
            //日志记录,目前没业务需求,抄表被变更记录使用
            PropertyPublicMeterReadingLog readingLog = Func.copy(publicMeterReading, PropertyPublicMeterReadingLog.class);
            readingLog.setPublicMeterReadingId(publicMeterReading.getId());
            readingLog.setId(null);
            iPropertyPublicMeterReadingLogService.save(readingLog);
        }
        return flag;
    }

    private BigDecimal getDosage(BigDecimal meterReadingNum, BigDecimal lastMeterReadingNum, BigDecimal rate,BigDecimal attritionRate,Long parkId) {
        if (Func.isNotEmpty(meterReadingNum) && Func.isNotEmpty(lastMeterReadingNum) && Func.isNotEmpty(rate)) {
            return getDosageDivide(BigdecimalUtil.subtract(meterReadingNum, lastMeterReadingNum), Func.isEmpty(attritionRate)?rate:BigdecimalUtil.add(rate,attritionRate),parkId);
        } else {
            return BigdecimalUtil.ZERO;
        }
    }

    private BigDecimal getDosageDivide(BigDecimal dosage, BigDecimal divisor,Long parkId) {
        int scale = 2;
        PropertyBillingSettings billingSettings = propertyBillingSettingsService.getBillingSettings(parkId);
        if(Func.isNotEmpty(billingSettings)&&Func.isNotEmpty(billingSettings.getMeterDigitsType())
                &&billingSettings.getMeterDigitsType()>=0&&billingSettings.getMeterDigitsType()<=2){
            scale=billingSettings.getMeterDigitsType();
        }
        return BigdecimalUtil.divide(dosage, divisor, scale, RoundingMode.DOWN);
    }

}
