# HkInventoryTaxRateServiceImpl.java

    package cloud.wconnect.workperformance.service.hkinventory.impl;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.pojo.dto.PropertyDTO;
    import cloud.wconnect.commonlib.redis.PropertyI18nRedisService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.commonlib.util.InternationalizationUtils;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventory;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryPurchaseOrder;
    import cloud.wconnect.workperformance.entity.hkinventory.HkInventoryTaxRate;
    import cloud.wconnect.workperformance.mapper.hkinventory.HkInventoryTaxRateMapper;
    import cloud.wconnect.workperformance.pojo.dto.hkinventory.HkInventoryTaxRateDTO;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryPurchaseOrderService;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryService;
    import cloud.wconnect.workperformance.service.hkinventory.IHkInventoryTaxRateService;
    import com.baomidou.dynamic.datasource.annotation.DS;
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Lazy;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.time.LocalDate;
    import java.time.YearMonth;
    import java.util.List;
    import java.util.Objects;

    /**
     * <p>
     * 税率表 服务实现类
     * </p>
     *
     * @author lichen
     * @since 2025-07-15
     */
    @Service
    @DS("work_performance")
    public class HkInventoryTaxRateServiceImpl extends ServiceImpl<HkInventoryTaxRateMapper, HkInventoryTaxRate> implements IHkInventoryTaxRateService {

        @Autowired
        @Lazy
        private IHkInventoryService hkInventoryService;
        @Autowired
        @Lazy
        private IHkInventoryPurchaseOrderService hkInventoryPurchaseOrderService;
        @Autowired
        private PropertyI18nRedisService propertyI18nRedisService;

        /**
         * 查询资产配置的税率
         *
         * @param propertyId 资产id
         * @return cloud.wconnect.workperformance.pojo.dto.hkinventory.HkInventoryTaxRateDTO
         * @author lichen
         * @date 2025/7/15
         */
        @Override
        public HkInventoryTaxRateDTO getByPropertyId(Integer propertyId) {
            HkInventoryTaxRate taxRate = getOne(new LambdaQueryWrapper<HkInventoryTaxRate>()
                    .eq(HkInventoryTaxRate::getPropertyId, propertyId));
            if (Objects.isNull(taxRate)) return new HkInventoryTaxRateDTO();
            return new HkInventoryTaxRateDTO(taxRate.getTaxRate());
        }

        /**
         * 保存或修改资产配置的税率
         *
         * @param tenantId   租户id
         * @param propertyId 资产id
         * @param taxRateDTO 税率信息
         * @return java.util.Map<java.lang.String, java.lang.Object>
         * @author lichen
         * @date 2025/7/15
         */
        @Override
        @Transactional(rollbackFor = Exception.class)
        public void saveOrUpdate(Integer tenantId, int propertyId, HkInventoryTaxRateDTO taxRateDTO) {
            HkInventoryTaxRate oriTaxRate = getOne(new LambdaQueryWrapper<HkInventoryTaxRate>()
                    .eq(HkInventoryTaxRate::getPropertyId, propertyId));
            if (Objects.isNull(oriTaxRate)) {
                oriTaxRate = new HkInventoryTaxRate();
                oriTaxRate.setTenantId(tenantId);
                oriTaxRate.setPropertyId(propertyId);
                oriTaxRate.setTaxRate(taxRateDTO.getTaxRate());
                save(oriTaxRate);
            } else {
                oriTaxRate.setTaxRate(taxRateDTO.getTaxRate());
                updateById(oriTaxRate);

                //更新采购单的单价
                PropertyDTO propertyDTO = propertyI18nRedisService.get(propertyId);
                updatePurchaseOrderUnitCost(propertyDTO, taxRateDTO.getTaxRate());
            }
        }

        /**
         * 更新Housekeeping Inventory的采购单价
         *
         * @param propertyDTO 资产DTO
         * @param taxRate     税率
         * @return void
         * @author lichen
         * @date 2025/7/15
         */
        private void updatePurchaseOrderUnitCost(PropertyDTO propertyDTO, BigDecimal taxRate) {
            String calculationRule = propertyDTO.getInternationalization().getNumber().getCalculationRule();
            RoundingMode roundingMode = InternationalizationUtils.getRoundingMode(calculationRule);

            //查询最后一个发布的Housekeeping Inventory
            HkInventory hkInventory = hkInventoryService.listRecentPublished(propertyDTO.getId());

            Long startPurchaseTime = null;
            if (Objects.nonNull(hkInventory)) {
                YearMonth yearMonth = YearMonth.of(hkInventory.getYear(), hkInventory.getMonth());
                //获取下个月的第一天
                LocalDate nextMonthFirstDay = yearMonth.atEndOfMonth().plusDays(1);
                startPurchaseTime = DateTimeUtils.localDateToLong(nextMonthFirstDay, propertyDTO.getTimezone());
            }

            List<HkInventoryPurchaseOrder> poList = hkInventoryPurchaseOrderService.list(new LambdaQueryWrapper<HkInventoryPurchaseOrder>()
                    .eq(HkInventoryPurchaseOrder::getPropertyId, propertyDTO.getId())
                    .ge(Objects.nonNull(startPurchaseTime), HkInventoryPurchaseOrder::getPurchaseTime, startPurchaseTime));
            //重新计算税后单价
            List<HkInventoryPurchaseOrder> updateBatch = poList.stream().map(po -> {
                Integer unitPerCs = po.getUnitPerCs();
                BigDecimal priceCs = po.getPriceCs();
                //计算单价
                BigDecimal unitCost = priceCs.divide(new BigDecimal(unitPerCs), BaseConstant.DATA_PRECISION, roundingMode);
                //计算税后单价
                BigDecimal afterTaxUnitCost = unitCost.multiply(new BigDecimal(1).add(taxRate));

                HkInventoryPurchaseOrder purchaseOrder = new HkInventoryPurchaseOrder();
                purchaseOrder.setId(po.getId());
                purchaseOrder.setUnitCost(afterTaxUnitCost);
                return purchaseOrder;
            }).toList();
            hkInventoryPurchaseOrderService.updateBatchById(updateBatch);
        }
    }