| | |
| | | import com.java110.core.context.ICmdDataFlowContext; |
| | | import com.java110.core.event.cmd.Cmd; |
| | | import com.java110.core.event.cmd.CmdEvent; |
| | | import com.java110.core.factory.CommunitySettingFactory; |
| | | import com.java110.core.factory.GenerateCodeFactory; |
| | | import com.java110.core.factory.Java110TransactionalFactory; |
| | | import com.java110.core.log.LoggerFactory; |
| | |
| | | import com.java110.po.owner.RepairUserPo; |
| | | import com.java110.po.payFee.PayFeeDetailDiscountPo; |
| | | import com.java110.utils.cache.CommonCache; |
| | | import com.java110.utils.cache.MappingCache; |
| | | import com.java110.utils.constant.FeeFlagTypeConstant; |
| | | import com.java110.utils.exception.CmdException; |
| | | import com.java110.utils.lock.DistributedLock; |
| | |
| | | import com.java110.vo.ResultVo; |
| | | import org.slf4j.Logger; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.text.ParseException; |
| | |
| | | @Autowired |
| | | private IFinishFeeNotify finishFeeNotifyImpl; |
| | | |
| | | //域 |
| | | public static final String DOMAIN_COMMON = "DOMAIN.COMMON"; |
| | | |
| | | //键 |
| | | public static final String TOTAL_FEE_PRICE = "TOTAL_FEE_PRICE"; |
| | | |
| | | //键 |
| | | public static final String RECEIVED_AMOUNT_SWITCH = "RECEIVED_AMOUNT_SWITCH"; |
| | | |
| | | //禁用电脑端提交收费按钮 |
| | | public static final String OFFLINE_PAY_FEE_SWITCH = "OFFLINE_PAY_FEE_SWITCH"; |
| | | |
| | | @Override |
| | | public void validate(CmdEvent event, ICmdDataFlowContext cmdDataFlowContext, JSONObject reqJson) throws CmdException { |
| | | Assert.jsonObjectHaveKey(reqJson, "communityId", "请求报文中未包含communityId节点"); |
| | |
| | | Assert.hasLength(reqJson.getString("cycles"), "周期不能为空"); |
| | | Assert.hasLength(reqJson.getString("receivedAmount"), "实收金额不能为空"); |
| | | Assert.hasLength(reqJson.getString("feeId"), "费用ID不能为空"); |
| | | |
| | | //当支付方式为转账时,需要校验转账人是否为空 |
| | | String primeRate = reqJson.getString("primeRate"); |
| | | if(!StringUtils.isEmpty(primeRate) && primeRate.equals("7")){ |
| | | String transferorName = reqJson.getString("transferorName"); |
| | | if(StringUtils.isEmpty(transferorName)){ |
| | | Assert.hasLength(reqJson.getString("transferorName"), "支付方式为转账时,转账人不能为空"); |
| | | } |
| | | } |
| | | //判断是否 费用状态为缴费结束 |
| | | FeeDto feeDto = new FeeDto(); |
| | | feeDto.setFeeId(reqJson.getString("feeId")); |
| | |
| | | Assert.hasKeyAndValue(param, "discountId", "未包含优惠ID"); |
| | | Assert.hasKeyAndValue(param, "discountPrice", "未包含优惠金额"); |
| | | } |
| | | } |
| | | //校验实付金额不能大于欠款金额 |
| | | computeFeePrice(feeDtos); |
| | | BigDecimal amountOwed = new BigDecimal(feeDtos.get(0).getAmountOwed()); //应收款 |
| | | BigDecimal receivedAmount = new BigDecimal(reqJson.getString("receivedAmount")); |
| | | if(receivedAmount.compareTo(amountOwed) >= 1){ |
| | | throw new IllegalArgumentException("实付金额不能大于欠费金额"); |
| | | } |
| | | } |
| | | |
| | |
| | | cmdDataFlowContext.setResponseEntity(ResultVo.createResponseEntity(feeReceiptDetailDto)); |
| | | } |
| | | |
| | | private void computeFeePrice(List<FeeDto> feeDtos) { |
| | | if (ListUtil.isNull(feeDtos)) { |
| | | return; |
| | | } |
| | | String val = CommunitySettingFactory.getValue(feeDtos.get(0).getCommunityId(), TOTAL_FEE_PRICE); |
| | | if (StringUtil.isEmpty(val)) { |
| | | val = MappingCache.getValue(DOMAIN_COMMON, TOTAL_FEE_PRICE); |
| | | } |
| | | //先取单小区的如果没有配置 取 全局的 |
| | | String received_amount_switch = CommunitySettingFactory.getValue(feeDtos.get(0).getCommunityId(), RECEIVED_AMOUNT_SWITCH); |
| | | if (StringUtil.isEmpty(received_amount_switch)) { |
| | | received_amount_switch = MappingCache.getValue(DOMAIN_COMMON, RECEIVED_AMOUNT_SWITCH); |
| | | } |
| | | //先取单小区的如果没有配置 取 全局的 |
| | | String offlinePayFeeSwitch = CommunitySettingFactory.getValue(feeDtos.get(0).getCommunityId(), OFFLINE_PAY_FEE_SWITCH); |
| | | if (StringUtil.isEmpty(offlinePayFeeSwitch)) { |
| | | offlinePayFeeSwitch = MappingCache.getValue(DOMAIN_COMMON, OFFLINE_PAY_FEE_SWITCH); |
| | | } |
| | | for (FeeDto feeDto : feeDtos) { |
| | | try { |
| | | // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间 |
| | | Map<String, Object> targetEndDateAndOweMonth = computeFeeSMOImpl.getTargetEndDateAndOweMonth(feeDto); |
| | | Date targetEndDate = (Date) targetEndDateAndOweMonth.get("targetEndDate"); |
| | | double oweMonth = (double) targetEndDateAndOweMonth.get("oweMonth"); |
| | | feeDto.setCycle(feeDto.getPaymentCycle()); |
| | | //todo 这里考虑 账单模式的场景 |
| | | if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) { |
| | | feeDto.setCycle(oweMonth + ""); |
| | | } |
| | | feeDto.setDeadlineTime(targetEndDate); |
| | | //todo 算费 |
| | | doComputeFeePrice(feeDto, oweMonth); |
| | | |
| | | feeDto.setVal(val); |
| | | //关闭 线下收银功能 |
| | | if (StringUtil.isEmpty(received_amount_switch)) { |
| | | feeDto.setReceivedAmountSwitch("1");//默认启用实收款输入框 |
| | | } else { |
| | | feeDto.setReceivedAmountSwitch(received_amount_switch); |
| | | } |
| | | feeDto.setOfflinePayFeeSwitch(offlinePayFeeSwitch); |
| | | } catch (Exception e) { |
| | | logger.error("查询费用信息 ,费用信息错误", e); |
| | | } |
| | | //去掉多余0 |
| | | feeDto.setSquarePrice(Double.parseDouble(feeDto.getSquarePrice()) + ""); |
| | | feeDto.setAdditionalAmount(Double.parseDouble(feeDto.getAdditionalAmount()) + ""); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据房屋来算单价 |
| | | * |
| | | * @param feeDto |
| | | */ |
| | | private void doComputeFeePrice(FeeDto feeDto, double oweMonth) { |
| | | String computingFormula = feeDto.getComputingFormula(); |
| | | Map feePriceAll = computeFeeSMOImpl.getFeePrice(feeDto); |
| | | feeDto.setFeePrice(Double.parseDouble(feePriceAll.get("feePrice").toString())); |
| | | //BigDecimal feeTotalPrice = new BigDecimal(Double.parseDouble(feePriceAll.get("feeTotalPrice").toString())); |
| | | feeDto.setFeeTotalPrice(MoneyUtil.computePriceScale(Double.parseDouble(feePriceAll.get("feeTotalPrice").toString()), |
| | | feeDto.getScale(), |
| | | Integer.parseInt(feeDto.getDecimalPlace()))); |
| | | BigDecimal curFeePrice = new BigDecimal(feeDto.getFeePrice()); |
| | | curFeePrice = curFeePrice.multiply(new BigDecimal(oweMonth)); |
| | | feeDto.setAmountOwed(MoneyUtil.computePriceScale(curFeePrice.doubleValue(), feeDto.getScale(), Integer.parseInt(feeDto.getDecimalPlace())) + ""); |
| | | //动态费用 |
| | | if ("4004".equals(computingFormula) |
| | | && FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag()) |
| | | && !FeeDto.STATE_FINISH.equals(feeDto.getState()) |
| | | && feeDto.getDeadlineTime() == null) { |
| | | feeDto.setDeadlineTime(DateUtil.getCurrentDate()); |
| | | } |
| | | //考虑租金递增 |
| | | computeFeeSMOImpl.dealRentRate(feeDto); |
| | | } |
| | | |
| | | private void dealUserAccount(JSONObject paramObj, PayFeeDetailPo payFeeDetailPo) { |
| | | //判断选择的账号 |
| | |
| | | return; |
| | | } |
| | | // todo 自己是间接性费用 |
| | | if (FeeDto.FEE_FLAG_CYCLE.equals(feeConfigDto.getFeeFlag())) { |
| | | if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeConfigDto.getFeeFlag())) { |
| | | return; |
| | | } |
| | | |
| | | FeeConfigDto tmpFeeConfigDto = new FeeConfigDto(); |
| | | tmpFeeConfigDto.setFeeNameEq(feeConfigDto.getFeeName() + "欠费"); |
| | | tmpFeeConfigDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE); |
| | | // tmpFeeConfigDto.setFeeNameEq(feeConfigDto.getFeeName() + "欠费"); |
| | | tmpFeeConfigDto.setFeeNameEq(feeConfigDto.getFeeName()); |
| | | tmpFeeConfigDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE_ONCE); |
| | | tmpFeeConfigDto.setComputingFormula(feeConfigDto.getComputingFormula()); |
| | | List<FeeConfigDto> feeConfigDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(tmpFeeConfigDto); |
| | | |
| | | Assert.listOnlyOne(feeConfigDtos, "按自定义时间段缴费时,费用必须为周期性,或者存在名称为 " + feeConfigDto.getFeeName() + "欠费 的周期性费用,它的公式计算必须要和" + feeConfigDto.getFeeName() + "一致"); |
| | | // Assert.listOnlyOne(feeConfigDtos, "按自定义时间段缴费时,费用必须为间接性费用,或者存在名称为 " + feeConfigDto.getFeeName() + "欠费 的间接性费用,它的公式计算必须要和" + feeConfigDto.getFeeName() + "一致"); |
| | | } |
| | | |
| | | |
| | |
| | | * @param payFeeDetailPo |
| | | * @param payFeePo |
| | | */ |
| | | private void ifCustomStartEndTimePayFee(String cycles, Date endTime, PayFeeDetailPo payFeeDetailPo, PayFeePo payFeePo, JSONObject reqJson) { |
| | | public void ifCustomStartEndTimePayFee(String cycles, Date endTime, PayFeeDetailPo payFeeDetailPo, PayFeePo payFeePo, JSONObject reqJson) { |
| | | if (!"-105".equals(cycles)) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | int flag = payFeeDetailNewV1InnerServiceSMOImpl.savePayFeeDetailNew(tmpPayFeeDetailPo); |
| | | |
| | | //3 |
| | | if (flag < 1) { |
| | | throw new CmdException("生成欠费失败"); |
| | | } |
| | |
| | | //todo 生成费用 |
| | | PayFeePo tmpPayFeePo = BeanConvertUtil.covertBean(feeInfo, PayFeePo.class); |
| | | tmpPayFeePo.setFeeId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_feeId)); |
| | | tmpPayFeePo.setEndTime(DateUtil.getFormatTimeStringB(endTime)); |
| | | |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(endTime); |
| | | |
| | | // 减去一天 |
| | | calendar.add(Calendar.DAY_OF_MONTH, -1); |
| | | |
| | | // 获取减去一天后的日期 |
| | | Date dayBefore = calendar.getTime(); |
| | | |
| | | tmpPayFeePo.setEndTime(DateUtil.getFormatTimeStringB(dayBefore)); |
| | | tmpPayFeePo.setState(FeeDto.STATE_DOING); |
| | | |
| | | // todo 处理configId |
| | |
| | | tmpFeeAttrPo = new FeeAttrPo(); |
| | | tmpFeeAttrPo.setAttrId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_attrId, true)); |
| | | tmpFeeAttrPo.setFeeId(tmpPayFeePo.getFeeId()); |
| | | tmpFeeAttrPo.setCommunityId(tmpPayFeePo.getCommunityId()); |
| | | tmpFeeAttrPo.setCommunityId(tmpFeeAttrPo.getCommunityId()); |
| | | tmpFeeAttrPo.setSpecCd(FeeAttrDto.SPEC_CD_ONCE_FEE_DEADLINE_TIME); |
| | | tmpFeeAttrPo.setValue(reqJson.getString("customStartTime")); |
| | | tmpFeeAttrPos.add(tmpFeeAttrPo); |
| | | } |
| | | |
| | | feeAttrInnerServiceSMOImpl.saveFeeAttrs(tmpFeeAttrPos); |
| | | |
| | | } |
| | | |
| | | |
| | | public void ifCustomStartEndTimePayFee(String cycles, Date endTime, FeeDetailDto payFeeDetailPo, FeeDto payFeePo, String customStartTime) { |
| | | //todo 如果是同一天不创建 |
| | | if (DateUtil.getFormatTimeStringB(payFeePo.getEndTime()).equals(customStartTime.split(" ")[0])) { |
| | | return; |
| | | } |
| | | |
| | | FeeDto feeInfo = payFeePo; |
| | | String payObjNameRemark = "房屋"; |
| | | if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeInfo.getPayerObjType())) { |
| | | payObjNameRemark = "车辆"; |
| | | } else if (FeeDto.PAYER_OBJ_TYPE_CONTRACT.equals(feeInfo.getPayerObjType())) { |
| | | payObjNameRemark = "合同"; |
| | | } |
| | | |
| | | //todo 补充一条 缴费记录数据 |
| | | PayFeeDetailPo tmpPayFeeDetailPo = BeanConvertUtil.covertBean(payFeeDetailPo, PayFeeDetailPo.class); |
| | | tmpPayFeeDetailPo.setDetailId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_detailId)); |
| | | tmpPayFeeDetailPo.setCycles("0"); |
| | | tmpPayFeeDetailPo.setReceivableAmount("0"); |
| | | tmpPayFeeDetailPo.setReceivedAmount("0"); |
| | | tmpPayFeeDetailPo.setPayableAmount("0"); |
| | | tmpPayFeeDetailPo.setStartTime(DateUtil.getFormatTimeStringB(payFeePo.getEndTime())); |
| | | tmpPayFeeDetailPo.setEndTime(DateUtil.getAddDayString(payFeeDetailPo.getStartTime(),"yyyy-MM-dd HH:mm:ss",-1).split(" ")[0] + "23:59:59"); |
| | | tmpPayFeeDetailPo.setState(FeeDetailDto.STATE_OWE); |
| | | tmpPayFeeDetailPo.setOpenInvoice("N"); |
| | | tmpPayFeeDetailPo.setRemark("按缴费时间段缴费,这部分费用按欠费的方式重新生成,请在" + payObjNameRemark + "上查看"); |
| | | |
| | | // if (!StringUtil.isEmpty(reqJson.getString("cashAmount"))) { |
| | | // BigDecimal cashAmount = new BigDecimal(reqJson.getString("cashAmount")).setScale(2, BigDecimal.ROUND_HALF_UP); |
| | | // if (!StringUtil.isEmpty(tmpPayFeeDetailPo.getRemark())) { |
| | | // tmpPayFeeDetailPo.setRemark(tmpPayFeeDetailPo.getRemark() + ",现金账户抵扣" + cashAmount + "元"); |
| | | // } else { |
| | | // tmpPayFeeDetailPo.setRemark("现金账户抵扣" + cashAmount + "元"); |
| | | // } |
| | | // } |
| | | |
| | | int flag = payFeeDetailNewV1InnerServiceSMOImpl.savePayFeeDetailNew(tmpPayFeeDetailPo); |
| | | //3 |
| | | if (flag < 1) { |
| | | throw new CmdException("生成欠费失败"); |
| | | } |
| | | |
| | | //todo 生成费用 |
| | | PayFeePo tmpPayFeePo = BeanConvertUtil.covertBean(feeInfo, PayFeePo.class); |
| | | tmpPayFeePo.setFeeId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_feeId)); |
| | | |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.setTime(payFeePo.getEndTime()); |
| | | |
| | | // 减去一天 |
| | | // calendar.add(Calendar.DAY_OF_MONTH, -1); |
| | | |
| | | // 获取减去一天后的日期 |
| | | Date dayBefore = calendar.getTime(); |
| | | |
| | | tmpPayFeePo.setEndTime(DateUtil.getFormatTimeStringB(dayBefore)); |
| | | tmpPayFeePo.setState(FeeDto.STATE_DOING); |
| | | |
| | | // todo 处理configId |
| | | doChangeConfigId(tmpPayFeePo, feeInfo); |
| | | |
| | | |
| | | flag = payFeeV1InnerServiceSMOImpl.savePayFee(tmpPayFeePo); |
| | | if (flag < 1) { |
| | | throw new CmdException("生成欠费失败"); |
| | | } |
| | | |
| | | //todo 补充 费用属性 |
| | | FeeAttrDto feeAttrDto = new FeeAttrDto(); |
| | | feeAttrDto.setFeeId(payFeePo.getFeeId()); |
| | | feeAttrDto.setCommunityId(payFeePo.getCommunityId()); |
| | | List<FeeAttrDto> feeAttrDtos = feeAttrInnerServiceSMOImpl.queryFeeAttrs(feeAttrDto); |
| | | |
| | | if (feeAttrDtos == null || feeAttrDtos.size() < 1) { |
| | | return; |
| | | } |
| | | |
| | | List<FeeAttrPo> tmpFeeAttrPos = new ArrayList<>(); |
| | | FeeAttrPo tmpFeeAttrPo = null; |
| | | boolean hasDeadLineTime = false; |
| | | for (FeeAttrDto tmpFeeAttrDto : feeAttrDtos) { |
| | | tmpFeeAttrDto.setFeeId(tmpPayFeePo.getFeeId()); |
| | | tmpFeeAttrDto.setAttrId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_attrId, true)); |
| | | |
| | | if (FeeAttrDto.SPEC_CD_ONCE_FEE_DEADLINE_TIME.equals(tmpFeeAttrDto.getSpecCd())) { |
| | | tmpFeeAttrDto.setValue(DateUtil.getAddHoursStringA(DateUtil.getDateFromStringB(customStartTime.split(" ")[0]),-24).split(" ")[0]+" 23:59:59"); |
| | | hasDeadLineTime = true; |
| | | } |
| | | tmpFeeAttrPo = BeanConvertUtil.covertBean(tmpFeeAttrDto, FeeAttrPo.class); |
| | | tmpFeeAttrPos.add(tmpFeeAttrPo); |
| | | } |
| | | //todo 没有结束时间时 |
| | | if (!hasDeadLineTime) { |
| | | tmpFeeAttrPo = new FeeAttrPo(); |
| | | tmpFeeAttrPo.setAttrId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_attrId, true)); |
| | | tmpFeeAttrPo.setFeeId(tmpPayFeePo.getFeeId()); |
| | | tmpFeeAttrPo.setCommunityId(tmpFeeAttrPo.getCommunityId()); |
| | | tmpFeeAttrPo.setSpecCd(FeeAttrDto.SPEC_CD_ONCE_FEE_DEADLINE_TIME); |
| | | tmpFeeAttrPo.setValue(customStartTime); |
| | | tmpFeeAttrPos.add(tmpFeeAttrPo); |
| | | } |
| | | |
| | |
| | | feeConfigDto.setCommunityId(feeInfo.getCommunityId()); |
| | | List<FeeConfigDto> feeConfigDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(feeConfigDto); |
| | | Assert.listOnlyOne(feeConfigDtos, "费用项不存在"); |
| | | if (FeeDto.FEE_FLAG_CYCLE.equals(feeConfigDtos.get(0).getFeeFlag())) { |
| | | if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeConfigDtos.get(0).getFeeFlag())) { |
| | | return; |
| | | } |
| | | |
| | | |
| | | FeeConfigDto tmpFeeConfigDto = new FeeConfigDto(); |
| | | tmpFeeConfigDto.setFeeNameEq(feeConfigDtos.get(0).getFeeName() + "欠费"); |
| | | tmpFeeConfigDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE); |
| | | tmpFeeConfigDto.setComputingFormula(feeConfigDto.getComputingFormula()); |
| | | // tmpFeeConfigDto.setFeeNameEq(feeConfigDtos.get(0).getFeeName() + "欠费"); |
| | | tmpFeeConfigDto.setFeeNameEq(feeConfigDtos.get(0).getFeeName()); |
| | | tmpFeeConfigDto.setCommunityId(feeInfo.getCommunityId()); |
| | | // tmpFeeConfigDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE_ONCE); |
| | | // tmpFeeConfigDto.setComputingFormula(feeConfigDto.getComputingFormula()); |
| | | //todo 校验的时候校验过了 所以这里不可能为空 |
| | | feeConfigDtos = feeConfigInnerServiceSMOImpl.queryFeeConfigs(tmpFeeConfigDto); |
| | | |