diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/outlay/outlayManage/service/impl/OutlayManageUnionAllocateServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/outlay/outlayManage/service/impl/OutlayManageUnionAllocateServiceImpl.java new file mode 100644 index 00000000..e4dcee80 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/outlay/outlayManage/service/impl/OutlayManageUnionAllocateServiceImpl.java @@ -0,0 +1,167 @@ +package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageUnionAllocateService; +import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutLayAllocateUnion; +import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutlayManageUnion; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 分工会季度额度分配实现。 + * + * @author zhf + */ +@IocBean(args = {"refer:dao"}) +public class OutlayManageUnionAllocateServiceImpl extends BaseServiceImpl implements OutlayManageUnionAllocateService { + + public OutlayManageUnionAllocateServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Result doEdit(String id, BigDecimal allocateMoney) { + OutLayAllocateUnion allocateUnion = fetch(id); + if (Lang.isEmpty(allocateUnion)) { + return Result.error("分配记录不存在!"); + } + int currentQuarter = getCurrentQuarter(); + if (allocateUnion.getQuarterly() < currentQuarter) { + return Result.error("当前是第【" + currentQuarter + "季度】无法修改【第" + allocateUnion.getQuarterly() + "季度】的额度!"); + } + applyAllocateMoney(allocateUnion, allocateMoney); + return Result.success(); + } + + @Override + public Result doBatchAllocate(BigDecimal allocateMoney, Integer quarterly, Integer year) { + List allocateUnionList = dao().query(OutLayAllocateUnion.class, + Cnd.where(OutLayAllocateUnion::getQuarterly, "=", quarterly) + .and(OutLayAllocateUnion::getYear, "=", year) + .and(OutLayAllocateUnion::getDelFlag, "=", false)); + if (allocateUnionList == null || allocateUnionList.isEmpty()) { + return Result.error("当前季度没有分配记录!"); + } + for (OutLayAllocateUnion allocateUnion : allocateUnionList) { + applyAllocateMoney(allocateUnion, allocateMoney); + } + return Result.success(); + } + + @Override + public Result deleteAllocateRecord() { + int currentQuarter = getCurrentQuarter(); + List allocateUnionList = dao().query(OutLayAllocateUnion.class, + Cnd.where(OutLayAllocateUnion::getQuarterly, "=", currentQuarter) + .and(OutLayAllocateUnion::getYear, "=", DateUtil.thisYear()) + .and(OutLayAllocateUnion::getDelFlag, "=", false)); + if (allocateUnionList == null || allocateUnionList.isEmpty()) { + return Result.error("当前季度还未分配,无法重置!"); + } + + for (OutLayAllocateUnion allocateUnion : allocateUnionList) { + rollbackAllocateMoney(allocateUnion); + } + + dao().update(OutLayAllocateUnion.class, Chain.make("delFlag", true), + Cnd.where(OutLayAllocateUnion::getQuarterly, "=", currentQuarter) + .and(OutLayAllocateUnion::getYear, "=", DateUtil.thisYear()) + .and(OutLayAllocateUnion::getDelFlag, "=", false)); + return Result.success(); + } + + /** + * 按“先回退旧额度,再写入新额度”的方式同步季度记录和年度预算表。 + * + * @param allocateUnion 当前季度分配记录,包含分工会、年份、旧分配额度等上下文 + * @param newAllocateMoney 本次最终要保存的季度分配金额 + */ + private void applyAllocateMoney(OutLayAllocateUnion allocateUnion, BigDecimal newAllocateMoney) { + BigDecimal oldAllocateMoney = defaultValue(allocateUnion.getAllocateMoney()); + OutlayManageUnion manageUnion = dao().fetch(OutlayManageUnion.class, + Cnd.where(OutlayManageUnion::getUnionId, "=", allocateUnion.getUnionId()) + .and(OutlayManageUnion::getYear, "=", DateUtil.thisYear())); + + if (Lang.isEmpty(manageUnion)) { + manageUnion = buildManageUnion(allocateUnion, newAllocateMoney); + insert(manageUnion); + } else { + // 当前 totalQuota 里已经包含了旧季度额度,因此要先减旧值,再加新值,避免重复累加。 + BigDecimal newTotalQuota = defaultValue(manageUnion.getTotalQuota()) + .subtract(oldAllocateMoney) + .add(newAllocateMoney); + dao().update(OutlayManageUnion.class, Chain.make("totalQuota", newTotalQuota), + Cnd.where(OutlayManageUnion::getId, "=", manageUnion.getId())); + } + + dao().update(OutLayAllocateUnion.class, Chain.make("allocateMoney", newAllocateMoney), + Cnd.where(OutLayAllocateUnion::getId, "=", allocateUnion.getId())); + } + + /** + * 回滚当前季度已分配到年度预算表中的金额。 + * + * @param allocateUnion 当前季度分配记录,allocateMoney 表示本次需要从年度额度中扣回的金额 + */ + private void rollbackAllocateMoney(OutLayAllocateUnion allocateUnion) { + OutlayManageUnion manageUnion = dao().fetch(OutlayManageUnion.class, + Cnd.where(OutlayManageUnion::getUnionId, "=", allocateUnion.getUnionId()) + .and(OutlayManageUnion::getYear, "=", DateUtil.thisYear())); + if (Lang.isEmpty(manageUnion)) { + return; + } + BigDecimal newTotalQuota = defaultValue(manageUnion.getTotalQuota()) + .subtract(defaultValue(allocateUnion.getAllocateMoney())); + dao().update(OutlayManageUnion.class, Chain.make("totalQuota", newTotalQuota), + Cnd.where(OutlayManageUnion::getId, "=", manageUnion.getId())); + } + + /** + * 当前年份预算表不存在时,按“分配前额度 + 本次分配额度”创建年度预算记录。 + * + * @param allocateUnion 当前季度分配记录,allocateHeadMoney 表示生成记录时的剩余额度快照 + * @param allocateMoney 本次要设置的季度分配额度 + * @return OutlayManageUnion 新建的年度预算实体 + */ + private OutlayManageUnion buildManageUnion(OutLayAllocateUnion allocateUnion, BigDecimal allocateMoney) { + Sys_union union = dao().fetch(Sys_union.class, allocateUnion.getUnionId()); + OutlayManageUnion manageUnion = new OutlayManageUnion(); + manageUnion.setYear(DateUtil.thisYear()); + manageUnion.setUnionId(allocateUnion.getUnionId()); + manageUnion.setTotalQuota(defaultValue(allocateUnion.getAllocateHeadMoney()).add(allocateMoney)); + manageUnion.setUsedQuota(BigDecimal.ZERO); + if (Lang.isNotEmpty(union)) { + manageUnion.setUnionName(union.getName()); + manageUnion.setUnionCode(union.getUnionCode()); + } + return manageUnion; + } + + /** + * 统一处理空金额,避免金额运算时出现空指针。 + * + * @param value 可能为空的金额字段 + * @return BigDecimal 非空金额;为空时返回 0 + */ + private BigDecimal defaultValue(BigDecimal value) { + return value == null ? BigDecimal.ZERO : value; + } + + /** + * 计算当前自然季度。 + * + * @return int 当前季度,取值范围 1-4 + */ + private int getCurrentQuarter() { + return DateUtil.month(DateUtil.date()) / 3 + 1; + } +}