commit
This commit is contained in:
@@ -8,11 +8,9 @@ import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.bpm.enums.BpmProcessInstanceStatusEnum;
|
||||
import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum;
|
||||
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_user_role;
|
||||
import com.budwk.app.sys.services.SysRoleService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.club.model.ClubUser;
|
||||
import com.budwk.app.zhgh.club.model.SysClub;
|
||||
import com.budwk.app.zhgh.club.service.SysClubService;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -38,8 +36,6 @@ public class ClubCommonController {
|
||||
|
||||
@Inject
|
||||
private SysClubService sysClubService;
|
||||
@Inject
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@@ -62,9 +58,9 @@ public class ClubCommonController {
|
||||
public Result listClubByRole() {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.CLUB_PRESIDENT);
|
||||
List<Sys_user_role> userRoles = sysClubService.dao().query(Sys_user_role.class, Cnd.where("userId", "=", SecurityUtil.getUserId()).and("roleId", "=", sysRole.getId()));
|
||||
List<String> myClubId = userRoles.stream().map(Sys_user_role::getClubId).toList();
|
||||
// 报销申请只允许选择当前用户已加入的协会,避免看到未加入的协会数据。
|
||||
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
|
||||
List<String> myClubId = clubUsers.stream().map(ClubUser::getClubId).distinct().toList();
|
||||
cnd.and("c.id", "in", myClubId);
|
||||
}
|
||||
cnd.and("inst.state","=",ProcessInstanceStateEnum.FINISHED.getCode());
|
||||
|
||||
+39
-22
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayManageClub;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.model.OutlayUseDetail;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.school.model.OutlayManageSchool;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayUseDetailService;
|
||||
@@ -21,49 +22,65 @@ public class OutlayUseDetailServiceImpl extends BaseServiceImpl<OutlayUseDetail>
|
||||
|
||||
@Override
|
||||
public void doDeleteDetail(String id, String outlayType) {
|
||||
//更新预算表的金额
|
||||
updateOutlayManage(id, null,outlayType,false);
|
||||
//更新完删除
|
||||
// 先回滚对应预算的已使用额度,再删除详情记录。
|
||||
updateOutlayManage(id, null, outlayType, false);
|
||||
delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doEditDetail(OutlayUseDetail outlayUseDetail,String outlayType) {
|
||||
updateOutlayManage(outlayUseDetail.getId(), outlayUseDetail,outlayType,true);
|
||||
public void doEditDetail(OutlayUseDetail outlayUseDetail, String outlayType) {
|
||||
// 编辑详情时需要先回退旧金额,再叠加新金额,保证预算台账准确。
|
||||
updateOutlayManage(outlayUseDetail.getId(), outlayUseDetail, outlayType, true);
|
||||
update(outlayUseDetail);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新预算表
|
||||
* 同步预算主表的已使用额度,保证校工会、分工会、协会三类台账口径一致。
|
||||
*
|
||||
* @param id
|
||||
* @param outlayType
|
||||
* @param id 详情主键
|
||||
* @param outlayUseDetail 编辑后的详情对象,删除场景可为空
|
||||
* @param outlayType 预算类型:school/union/club
|
||||
* @param isEdit 是否为编辑场景
|
||||
*/
|
||||
private void updateOutlayManage(String id, OutlayUseDetail outlayUseDetail,String outlayType,Boolean isEdit) {
|
||||
//找到是哪一条的预算详情
|
||||
private void updateOutlayManage(String id, OutlayUseDetail outlayUseDetail, String outlayType, Boolean isEdit) {
|
||||
OutlayUseDetail detail = fetch(id);
|
||||
//拿到预算详情的调整金额
|
||||
if (outlayType.equals("school")) {
|
||||
//找到预算分配的记录
|
||||
if (detail == null) {
|
||||
return;
|
||||
}
|
||||
if ("school".equals(outlayType)) {
|
||||
OutlayManageSchool manageSchool = dao().fetch(OutlayManageSchool.class, detail.getOutlayManageId());
|
||||
if (manageSchool == null) {
|
||||
return;
|
||||
}
|
||||
manageSchool.setUsedQuota(manageSchool.getUsedQuota().subtract(detail.getAdjustMoney()));
|
||||
if (isEdit){
|
||||
//如果是修改,就先减去原来的值在加上现在新的值
|
||||
if (Boolean.TRUE.equals(isEdit) && outlayUseDetail != null) {
|
||||
manageSchool.setUsedQuota(manageSchool.getUsedQuota().add(outlayUseDetail.getAdjustMoney()));
|
||||
}
|
||||
update(manageSchool);
|
||||
} else if (outlayType.equals("union")) {
|
||||
return;
|
||||
}
|
||||
if ("union".equals(outlayType)) {
|
||||
OutlayManageUnion manageUnion = dao().fetch(OutlayManageUnion.class, detail.getOutlayManageId());
|
||||
if (manageUnion == null) {
|
||||
return;
|
||||
}
|
||||
manageUnion.setUsedQuota(manageUnion.getUsedQuota().subtract(detail.getAdjustMoney()));
|
||||
if (isEdit){
|
||||
//如果是修改,就先减去原来的值在加上现在新的值
|
||||
if (Boolean.TRUE.equals(isEdit) && outlayUseDetail != null) {
|
||||
manageUnion.setUsedQuota(manageUnion.getUsedQuota().add(outlayUseDetail.getAdjustMoney()));
|
||||
}
|
||||
update(manageUnion);
|
||||
return;
|
||||
}
|
||||
if ("club".equals(outlayType)) {
|
||||
OutlayManageClub manageClub = dao().fetch(OutlayManageClub.class, detail.getOutlayManageId());
|
||||
if (manageClub == null) {
|
||||
return;
|
||||
}
|
||||
manageClub.setUsedQuota(manageClub.getUsedQuota().subtract(detail.getAdjustMoney()));
|
||||
if (Boolean.TRUE.equals(isEdit) && outlayUseDetail != null) {
|
||||
manageClub.setUsedQuota(manageClub.getUsedQuota().add(outlayUseDetail.getAdjustMoney()));
|
||||
}
|
||||
update(manageClub);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+9
-2
@@ -259,7 +259,14 @@ public class UnionReimburseApplyController {
|
||||
return Result.success(value);
|
||||
}
|
||||
|
||||
// 如果没有找到该社团的经费记录,返回0
|
||||
return Result.success(0.0);
|
||||
// 协会在年度预算分配之后才创建时,不会自动生成当年预算记录,这里给出明确提示。
|
||||
return Result.error("该协会本年度未生成预算记录,请先在协会预算分配中补分配");
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("统一查询经费余额")
|
||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
||||
return unionReimburseService.getBudgetBalance(reimburseFundSource, clubId);
|
||||
}
|
||||
}
|
||||
|
||||
+11
-23
@@ -15,7 +15,6 @@ import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
@@ -27,18 +26,15 @@ import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/unionReimburse/review")
|
||||
@Ok("json:full")
|
||||
@Api("审核报销")
|
||||
@Api("工会报销审核")
|
||||
@Slf4j
|
||||
public class UnionReimburseReviewController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private UnionReimburseService unionReimburseService;
|
||||
|
||||
@@ -98,42 +94,34 @@ public class UnionReimburseReviewController {
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("审核")
|
||||
@ApiOperation("审核报销")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"unionReimburse.review", "h5.unionReimburse.review"}, mode = SaMode.OR)
|
||||
@SLog(tag = "审核工会报销", msg = "审核工会报销")
|
||||
@SLog(tag = "工会报销审核", msg = "审核工会报销")
|
||||
public Result reviewTask(@Param("data") UnionReimburse unionReimburse, String submitType) {
|
||||
if (submitType == null || !List.of("3", "4", "5").contains(submitType)) {
|
||||
return Result.error("无效的审核操作类型");
|
||||
}
|
||||
UnionReimburse dbRecord = dao.fetch(UnionReimburse.class, unionReimburse.getId());
|
||||
if (dbRecord == null) {
|
||||
return Result.error("记录不存在");
|
||||
}
|
||||
dbRecord.setReviewTime(new Date());
|
||||
dbRecord.setStateId(Integer.parseInt(submitType));
|
||||
dbRecord.setReviewOpinion(unionReimburse.getReviewOpinion());
|
||||
dao.update(dbRecord);
|
||||
return Result.success();
|
||||
return unionReimburseService.reviewApply(unionReimburse.getId(), unionReimburse.getReviewOpinion(), Integer.parseInt(submitType));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("一键审核")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"unionReimburse.review", "h5.unionReimburse.review"}, mode = SaMode.OR)
|
||||
@SLog(tag = "一键审核", msg = "一键审核")
|
||||
@SLog(tag = "工会报销审核", msg = "一键审核工会报销")
|
||||
public Result allReview() {
|
||||
try {
|
||||
List<UnionReimburse> reimbursements = unionReimburseService.query(Cnd.where("stateId", "=", 2));
|
||||
for (UnionReimburse reimbursement : reimbursements) {
|
||||
reimbursement.setStateId(3);
|
||||
reimbursement.setReviewTime(new Date());
|
||||
reimbursement.setReviewOpinion("通过");
|
||||
dao.update(reimbursement);
|
||||
Result result = unionReimburseService.reviewApply(reimbursement.getId(), "通过", 3);
|
||||
if (result.getCode() != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Result.success("一键审核完成,共处理 " + reimbursements.size() + " 条记录");
|
||||
return Result.success("一键审核完成,共处理" + reimbursements.size() + "条记录");
|
||||
} catch (Exception e) {
|
||||
log.error("一键审核失败");
|
||||
log.error("一键审核失败", e);
|
||||
return Result.error("一键审核失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
+13
-4
@@ -1,7 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.unionReimburse.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburse;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.param.UnionReimbursePageForm;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.vo.UnionReimburseBankHistoryVO;
|
||||
@@ -9,7 +9,7 @@ import org.nutz.dao.sql.Sql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
|
||||
Sql getSql(UnionReimbursePageForm pageForm);
|
||||
|
||||
@@ -19,7 +19,7 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
Result saveApply(UnionReimburse unionReimburse, int stateId);
|
||||
|
||||
/**
|
||||
* 查询申请表单详情,补齐发票明细回显数据。
|
||||
* 查询申请表单详情,并补齐发票明细回显数据。
|
||||
*/
|
||||
UnionReimburse getApplyForm(String id);
|
||||
|
||||
@@ -34,8 +34,17 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
Result checkInvoiceDuplicate(String invoiceNo, String reimburseId);
|
||||
|
||||
/**
|
||||
* 识别单张发票文件,并在需要时调用腾讯云验真接口补齐票面信息。
|
||||
* 识别单张发票文件,并在需要时调用验真接口补齐票面信息。
|
||||
*/
|
||||
Result recognizeInvoice(String fileId, Boolean verifySwitch);
|
||||
|
||||
/**
|
||||
* 查询报销可用经费余额,同时校验是否已分配以及协会归属权限。
|
||||
*/
|
||||
Result getBudgetBalance(String reimburseFundSource, String clubId);
|
||||
|
||||
/**
|
||||
* 审核报销,审核通过时扣减对应预算并新增预算使用详情。
|
||||
*/
|
||||
Result reviewApply(String reimburseId, String reviewOpinion, int submitType);
|
||||
}
|
||||
|
||||
+243
-11
@@ -8,6 +8,11 @@ import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_file;
|
||||
import com.budwk.app.sys.services.SysFileService;
|
||||
import com.budwk.app.zhgh.club.model.ClubUser;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayManageClub;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.model.OutlayUseDetail;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.school.model.OutlayManageSchool;
|
||||
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutlayManageUnion;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburse;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburseInvoiceDetail;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.param.UnionReimbursePageForm;
|
||||
@@ -123,6 +128,10 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
Result fundValidateResult = validateFundSourceBeforeSubmit(unionReimburse);
|
||||
if (fundValidateResult != null) {
|
||||
return fundValidateResult;
|
||||
}
|
||||
Result duplicateResult = validateInvoiceDuplicate(unionReimburse);
|
||||
if (duplicateResult != null) {
|
||||
return duplicateResult;
|
||||
@@ -232,8 +241,80 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一规整发票明细中的文本和金额,避免空格、空数组等脏数据进入库表。
|
||||
* 按经费来源统一查询当前可用余额,未分配或权限不匹配时直接拦截。
|
||||
*/
|
||||
@Override
|
||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
||||
if (StrUtil.isBlank(reimburseFundSource)) {
|
||||
return Result.error("请选择经费来源");
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_1".equals(reimburseFundSource)) {
|
||||
OutlayManageSchool outlayManageSchool = dao().fetch(OutlayManageSchool.class,
|
||||
Cnd.where("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageSchool == null) {
|
||||
return Result.error("校工会经费未分配");
|
||||
}
|
||||
return Result.success(formatMoney(outlayManageSchool.getTotalQuota().subtract(outlayManageSchool.getUsedQuota())));
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
||||
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
||||
Cnd.where("unionId", "=", SecurityUtil.getUnionId()).and("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageUnion == null) {
|
||||
return Result.error("分工会经费未分配");
|
||||
}
|
||||
return Result.success(formatMoney(outlayManageUnion.getTotalQuota().subtract(outlayManageUnion.getUsedQuota())));
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_3".equals(reimburseFundSource)) {
|
||||
if (StrUtil.isBlank(clubId)) {
|
||||
return Result.error("请选择协会");
|
||||
}
|
||||
List<String> myClubIds = getCurrentUserClubIds();
|
||||
if (!isAdmin() && !myClubIds.contains(clubId)) {
|
||||
return Result.error("当前用户无权使用该协会经费");
|
||||
}
|
||||
OutlayManageClub outlayManageClub = dao().fetch(OutlayManageClub.class,
|
||||
Cnd.where("clubId", "=", clubId).and("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageClub == null) {
|
||||
return Result.error("该协会本年度未生成预算记录,请先在协会预算分配中补分配");
|
||||
}
|
||||
return Result.success(formatMoney(outlayManageClub.getTotalQuota().subtract(outlayManageClub.getUsedQuota())));
|
||||
}
|
||||
return Result.error("不支持的经费来源");
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过时统一校验余额、扣减预算并写入预算使用详情,避免控制器分散业务逻辑。
|
||||
*/
|
||||
@Override
|
||||
public Result reviewApply(String reimburseId, String reviewOpinion, int submitType) {
|
||||
if (!List.of(3, 4, 5).contains(submitType)) {
|
||||
return Result.error("无效的审核操作类型");
|
||||
}
|
||||
UnionReimburse dbRecord = this.fetch(reimburseId);
|
||||
if (dbRecord == null) {
|
||||
return Result.error("记录不存在");
|
||||
}
|
||||
if (submitType == 3) {
|
||||
// 已通过的单据再次触发通过时直接返回,避免重复扣减预算。
|
||||
if (Integer.valueOf(3).equals(dbRecord.getStateId())) {
|
||||
return Result.success();
|
||||
}
|
||||
Result validateResult = validateFundSourceBeforeSubmit(dbRecord);
|
||||
if (validateResult != null) {
|
||||
return validateResult;
|
||||
}
|
||||
Result deductResult = deductBudgetAndSaveUseDetail(dbRecord);
|
||||
if (deductResult != null && deductResult.getCode() != 0) {
|
||||
return deductResult;
|
||||
}
|
||||
}
|
||||
dbRecord.setReviewTime(new Date());
|
||||
dbRecord.setStateId(submitType);
|
||||
dbRecord.setReviewOpinion(reviewOpinion);
|
||||
dao().update(dbRecord);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void normalizeInvoiceDetails(UnionReimburse unionReimburse) {
|
||||
if (unionReimburse.getInvoiceDetails() == null) {
|
||||
unionReimburse.setInvoiceDetails(new ArrayList<>());
|
||||
@@ -289,15 +370,15 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
if (!isValidContact(unionReimburse.getMobile())) {
|
||||
return Result.error("请输入正确的联系方式");
|
||||
}
|
||||
if (StrUtil.isBlank(unionReimburse.getBankUserName())) {
|
||||
return Result.error("请填写户名");
|
||||
}
|
||||
if (StrUtil.isBlank(unionReimburse.getBankCardNumber())) {
|
||||
return Result.error("请填写银行账号");
|
||||
}
|
||||
if (StrUtil.isBlank(unionReimburse.getBankOfDeposit())) {
|
||||
return Result.error("请填写开户行");
|
||||
}
|
||||
// if (StrUtil.isBlank(unionReimburse.getBankUserName())) {
|
||||
// return Result.error("请填写户名");
|
||||
// }
|
||||
// if (StrUtil.isBlank(unionReimburse.getBankCardNumber())) {
|
||||
// return Result.error("请填写银行账号");
|
||||
// }
|
||||
// if (StrUtil.isBlank(unionReimburse.getBankOfDeposit())) {
|
||||
// return Result.error("请填写开户行");
|
||||
// }
|
||||
if (StrUtil.isBlank(unionReimburse.getPaymentNotes())) {
|
||||
return Result.error("请填写支付内容");
|
||||
}
|
||||
@@ -342,8 +423,159 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
}
|
||||
|
||||
/**
|
||||
* 同次提交和历史记录都要拦截重复发票,避免重复报销。
|
||||
* 提交和审核前统一校验预算是否已分配、余额是否充足。
|
||||
*/
|
||||
private Result validateFundSourceBeforeSubmit(UnionReimburse unionReimburse) {
|
||||
Result balanceResult = getBudgetBalance(unionReimburse.getReimburseFundSource(), unionReimburse.getClubId());
|
||||
if (balanceResult == null || balanceResult.getCode() != 0) {
|
||||
return balanceResult == null ? Result.error("经费余额校验失败") : balanceResult;
|
||||
}
|
||||
BigDecimal applyMoney = getApplyMoney(unionReimburse);
|
||||
if (applyMoney.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return Result.error("报销金额必须大于0");
|
||||
}
|
||||
BigDecimal balance = new BigDecimal(String.valueOf(balanceResult.getData()));
|
||||
if (balance.compareTo(applyMoney) < 0) {
|
||||
return Result.error("经费余额不足,当前余额:" + formatMoney(balance));
|
||||
}
|
||||
unionReimburse.setFundBalance(balance.doubleValue());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过后按经费来源扣减预算,并补写预算使用详情,便于后续台账追踪。
|
||||
*/
|
||||
private Result deductBudgetAndSaveUseDetail(UnionReimburse unionReimburse) {
|
||||
BigDecimal applyMoney = getApplyMoney(unionReimburse);
|
||||
String reimburseFundSource = unionReimburse.getReimburseFundSource();
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_1".equals(reimburseFundSource)) {
|
||||
OutlayManageSchool outlayManageSchool = dao().fetch(OutlayManageSchool.class,
|
||||
Cnd.where("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageSchool == null) {
|
||||
return Result.error("校工会经费未分配");
|
||||
}
|
||||
if (outlayManageSchool.getTotalQuota().subtract(outlayManageSchool.getUsedQuota()).compareTo(applyMoney) < 0) {
|
||||
return Result.error("校工会经费余额不足");
|
||||
}
|
||||
outlayManageSchool.setUsedQuota(outlayManageSchool.getUsedQuota().add(applyMoney));
|
||||
dao().updateIgnoreNull(outlayManageSchool);
|
||||
insertUseDetail(unionReimburse, outlayManageSchool.getId(), applyMoney);
|
||||
return Result.success();
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
||||
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
||||
Cnd.where("unionId", "=", unionReimburse.getUnionId()).and("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageUnion == null) {
|
||||
return Result.error("分工会经费未分配");
|
||||
}
|
||||
if (outlayManageUnion.getTotalQuota().subtract(outlayManageUnion.getUsedQuota()).compareTo(applyMoney) < 0) {
|
||||
return Result.error("分工会经费余额不足");
|
||||
}
|
||||
outlayManageUnion.setUsedQuota(outlayManageUnion.getUsedQuota().add(applyMoney));
|
||||
dao().updateIgnoreNull(outlayManageUnion);
|
||||
insertUseDetail(unionReimburse, outlayManageUnion.getId(), applyMoney);
|
||||
return Result.success();
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_3".equals(reimburseFundSource)) {
|
||||
OutlayManageClub outlayManageClub = dao().fetch(OutlayManageClub.class,
|
||||
Cnd.where("clubId", "=", unionReimburse.getClubId()).and("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageClub == null) {
|
||||
return Result.error("该协会本年度未生成预算记录,请先在协会预算分配中补分配");
|
||||
}
|
||||
if (outlayManageClub.getTotalQuota().subtract(outlayManageClub.getUsedQuota()).compareTo(applyMoney) < 0) {
|
||||
return Result.error("协会经费余额不足");
|
||||
}
|
||||
outlayManageClub.setUsedQuota(outlayManageClub.getUsedQuota().add(applyMoney));
|
||||
dao().updateIgnoreNull(outlayManageClub);
|
||||
insertUseDetail(unionReimburse, outlayManageClub.getId(), applyMoney);
|
||||
return Result.success();
|
||||
}
|
||||
return Result.error("不支持的经费来源");
|
||||
}
|
||||
|
||||
/**
|
||||
* 一张报销单只写入一条预算使用详情,避免重复通过或重复点击造成重复明细。
|
||||
*/
|
||||
private void insertUseDetail(UnionReimburse unionReimburse, String outlayManageId, BigDecimal applyMoney) {
|
||||
OutlayUseDetail oldDetail = dao().fetch(OutlayUseDetail.class, Cnd.where("outlayReimburseId", "=", unionReimburse.getId()));
|
||||
if (oldDetail != null) {
|
||||
return;
|
||||
}
|
||||
OutlayUseDetail detail = new OutlayUseDetail();
|
||||
detail.setOutlayManageId(outlayManageId);
|
||||
detail.setOutlayReimburseId(unionReimburse.getId());
|
||||
detail.setAdjustMoney(applyMoney);
|
||||
detail.setAdjustReason(StrUtil.blankToDefault(unionReimburse.getPaymentNotes(), getReimburseProjectName(unionReimburse.getReimburseProject())));
|
||||
detail.setAdjustUserId(SecurityUtil.getUserId());
|
||||
detail.setAdjustUserName(SecurityUtil.getUserUsername());
|
||||
detail.setAdjustLoginName(SecurityUtil.getUserLoginname());
|
||||
detail.setProjectName(buildUseDetailProjectName(unionReimburse));
|
||||
detail.setActivityNumber(unionReimburse.getActivityNumber());
|
||||
detail.setActivityTime(buildUseDetailTime(unionReimburse));
|
||||
dao().insert(detail);
|
||||
}
|
||||
|
||||
private BigDecimal getApplyMoney(UnionReimburse unionReimburse) {
|
||||
Double money = "UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())
|
||||
? unionReimburse.getCondolenceMoney() : unionReimburse.getMoney();
|
||||
return BigDecimal.valueOf(money == null ? 0D : money).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private String buildUseDetailProjectName(UnionReimburse unionReimburse) {
|
||||
if (StrUtil.isNotBlank(unionReimburse.getActivityName())) {
|
||||
return unionReimburse.getActivityName();
|
||||
}
|
||||
if (StrUtil.isNotBlank(unionReimburse.getCondolenceUserName())) {
|
||||
return getReimburseProjectName(unionReimburse.getReimburseProject()) + "-" + unionReimburse.getCondolenceUserName();
|
||||
}
|
||||
return StrUtil.blankToDefault(unionReimburse.getDocumentNo(), getReimburseProjectName(unionReimburse.getReimburseProject()));
|
||||
}
|
||||
|
||||
private String buildUseDetailTime(UnionReimburse unionReimburse) {
|
||||
if (unionReimburse.getActivityTime() != null) {
|
||||
return DateUtil.formatDate(unionReimburse.getActivityTime());
|
||||
}
|
||||
if (unionReimburse.getCondolenceTime() != null) {
|
||||
return DateUtil.formatDate(unionReimburse.getCondolenceTime());
|
||||
}
|
||||
if (unionReimburse.getCreateTime() != null) {
|
||||
return DateUtil.formatDate(unionReimburse.getCreateTime());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String getReimburseProjectName(String reimburseProject) {
|
||||
if ("UNION_REIMBURSE_PROJECT_1".equals(reimburseProject)) {
|
||||
return "慰问申请";
|
||||
}
|
||||
if ("UNION_REIMBURSE_PROJECT_2".equals(reimburseProject)) {
|
||||
return "文体活动申请";
|
||||
}
|
||||
if ("UNION_REIMBURSE_PROJECT_3".equals(reimburseProject)) {
|
||||
return "日常活动申请";
|
||||
}
|
||||
if ("UNION_REIMBURSE_PROJECT_4".equals(reimburseProject)) {
|
||||
return "专项活动申请";
|
||||
}
|
||||
return "报销申请";
|
||||
}
|
||||
|
||||
private Double formatMoney(BigDecimal money) {
|
||||
return money == null ? 0D : money.setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
private List<String> getCurrentUserClubIds() {
|
||||
if (isAdmin()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<ClubUser> clubUsers = dao().query(ClubUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
|
||||
return clubUsers.stream()
|
||||
.map(ClubUser::getClubId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Result validateInvoiceDuplicate(UnionReimburse unionReimburse) {
|
||||
Map<String, List<Integer>> currentInvoiceMap = new LinkedHashMap<>();
|
||||
List<UnionReimburseInvoiceDetail> details = unionReimburse.getInvoiceDetails();
|
||||
|
||||
Reference in New Issue
Block a user