Merge remote-tracking branch 'origin/main'
This commit is contained in:
+31
-4
@@ -24,6 +24,8 @@ import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||
import com.budwk.app.zhgh.activity.basic.param.ActivityUserScopePageParam;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.activity.basic.template.UserTemp;
|
||||
import com.budwk.app.zhgh.club.model.SysClub;
|
||||
import com.budwk.app.zhgh.club.service.SysClubService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@@ -84,6 +86,9 @@ public class ActivityBasicScopeController {
|
||||
@Inject
|
||||
private RedisService redisService;
|
||||
|
||||
@Inject
|
||||
private SysClubService sysClubService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:platform/zhgh/activity/basic/userScope/index.html")
|
||||
@SaCheckPermission("activity.basic.scope")
|
||||
@@ -97,7 +102,6 @@ public class ActivityBasicScopeController {
|
||||
* @return {@link Result}
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("activity.basic")
|
||||
public Result pageData(@Param("data") ActivityUserScopePageParam pageForm) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -216,6 +220,8 @@ public class ActivityBasicScopeController {
|
||||
return Result.success(new NutMap() {{
|
||||
addv("is_A06", StpUtil.hasRole(RoleConstant.SCHOOL_UNION_ADMIN.name()));
|
||||
addv("is_H04", StpUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name()));
|
||||
addv("is_H02", StpUtil.hasRole(RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name()));
|
||||
addv("is_CLUB_PRESIDENT", StpUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name()));
|
||||
addv("is_sysadmin", StpUtil.hasRole(RoleConstant.SYSADMIN.name()));
|
||||
addv("unionid", SecurityUtil.getUnionId());
|
||||
}});
|
||||
@@ -344,9 +350,30 @@ public class ActivityBasicScopeController {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())){
|
||||
cnd.andEX("u.unionid", "=", SecurityUtil.getUnionId());
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
boolean isBranchUnionChairman = AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name());
|
||||
boolean isClubPresident = AuthUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name());
|
||||
if (isBranchUnionChairman && isClubPresident) {
|
||||
// 同时具备分工会主席和社团会长身份时,未额外筛选前默认查看两类权限范围的并集。
|
||||
List<String> manageClubIdList = sysClubService.getMyManageClub().stream().map(SysClub::getId).toList();
|
||||
SqlExpressionGroup scopeGroup = new SqlExpressionGroup();
|
||||
scopeGroup.or("u.unionid", "=", SecurityUtil.getUnionId());
|
||||
if (!manageClubIdList.isEmpty()) {
|
||||
scopeGroup.or("clubuser.clubid", "in", manageClubIdList);
|
||||
}
|
||||
cnd.and(scopeGroup);
|
||||
} else if (isClubPresident) {
|
||||
// 社团会长设置活动人员范围时,只允许查看自己可管理社团下的成员。
|
||||
List<String> manageClubIdList = sysClubService.getMyManageClub().stream().map(SysClub::getId).toList();
|
||||
if (manageClubIdList.isEmpty()) {
|
||||
cnd.and("clubuser.clubid", "in", List.of("__EMPTY_CLUB_ID__"));
|
||||
} else {
|
||||
cnd.and("clubuser.clubid", "in", manageClubIdList);
|
||||
}
|
||||
} else {
|
||||
// 分工会主席等分工会侧角色,继续只允许查看本分工会人员。
|
||||
cnd.andEX("u.unionid", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
}
|
||||
String[] unionIds = getUnionIds(activityUserScopePageParam);
|
||||
if (Lang.isNotEmpty(unionIds)) {
|
||||
|
||||
+12
-2
@@ -21,6 +21,7 @@ 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;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.json.Json;
|
||||
@@ -125,8 +126,17 @@ public class ActivityCultureApplyUserController {
|
||||
public Result queryTeammate(@Valid String keyword, Integer signUpMethod, String tissueId) {
|
||||
Sql sql = Sqls.create("select id userId,username userName,loginname loginName,sex,mobile,unitName from vw_user $condition limit 0,10");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.or(Cnd.likeEX("username", keyword));
|
||||
cnd.or(Cnd.likeEX("loginname", keyword));
|
||||
SqlExpressionGroup keywordGroup = new SqlExpressionGroup();
|
||||
keywordGroup.andLike("username", keyword);
|
||||
keywordGroup.orLike("loginname", keyword);
|
||||
cnd.and(keywordGroup);
|
||||
if (StrUtil.isNotBlank(tissueId)) {
|
||||
ActivityTissue tissue = dao.fetch(ActivityTissue.class, tissueId);
|
||||
// 组队/分工会报名选人时,候选人必须落在活动新建时配置的参加人员范围内。
|
||||
if (ObjectUtil.isNotNull(tissue) && ObjectUtil.isNotNull(tissue.getGroupId())) {
|
||||
cnd.and("id", "in", activityBasicScopeService.buildGroupUserIdSubSql(tissue.getGroupId()));
|
||||
}
|
||||
}
|
||||
if (signUpMethod == 3) {
|
||||
cnd.and("unionid", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ public class ActivityCultureAuditActivityController {
|
||||
cnd.andEX("tissue.unionId", "=", unionId);
|
||||
cnd.andEX("tissue.activity_type", "=", activity_type);
|
||||
if (approval) {
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
|
||||
} else {
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
|
||||
+5
@@ -161,6 +161,11 @@ public class ActivityCultureUserStatisticsController {
|
||||
cnd.and("tissue.signUpMethod", "in", List.of(1, 2, 3));
|
||||
if (activity_type == 40002) {
|
||||
cnd.and("tissue.unionId", "=", SecurityUtil.getUnionId());
|
||||
} else if (activity_type == 40003) {
|
||||
// 协会会长进入社团报名统计时,只允许查看自己管理社团下的活动名称。
|
||||
List<SysClub> myManageClub = sysClubService.getMyManageClub();
|
||||
List<String> clubIdList = myManageClub.stream().map(SysClub::getId).collect(Collectors.toList());
|
||||
cnd.and("tissue.clubId", "in", clubIdList);
|
||||
}
|
||||
}
|
||||
// 只查询流程实例状态为20的数据(已完成状态)
|
||||
|
||||
+6
-5
@@ -169,34 +169,35 @@ public class ActivityPrizeListController {
|
||||
Map fourMap = NutMap.NEW();
|
||||
Map fiveMap = NutMap.NEW();
|
||||
|
||||
// 部分历史数据可能未配置竞赛类别,分组汇总时需要做空值保护,避免筛选时空指针
|
||||
//甲组
|
||||
List<NutMap> oneList = allList.stream().filter(a -> a.getString("bszbName").equals("甲组")).collect(toList());
|
||||
List<NutMap> oneList = allList.stream().filter(a -> Objects.equals("甲组", a.getString("bszbName"))).collect(toList());
|
||||
if (Lang.isNotEmpty(oneList)) {
|
||||
oneMap = oneList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||
}
|
||||
|
||||
//乙组
|
||||
List<NutMap> twoList = allList.stream().filter(a -> a.getString("bszbName").equals("乙组")).collect(toList());
|
||||
List<NutMap> twoList = allList.stream().filter(a -> Objects.equals("乙组", a.getString("bszbName"))).collect(toList());
|
||||
if (Lang.isNotEmpty(twoList)) {
|
||||
twoMap = twoList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||
}
|
||||
|
||||
|
||||
//丙组
|
||||
List<NutMap> threeList = allList.stream().filter(a -> a.getString("bszbName").equals("丙组")).collect(toList());
|
||||
List<NutMap> threeList = allList.stream().filter(a -> Objects.equals("丙组", a.getString("bszbName"))).collect(toList());
|
||||
if (Lang.isNotEmpty(threeList)) {
|
||||
threeMap = threeList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||
}
|
||||
|
||||
|
||||
//丁组
|
||||
List<NutMap> fourList = allList.stream().filter(a -> a.getString("bszbName").equals("丁组")).collect(toList());
|
||||
List<NutMap> fourList = allList.stream().filter(a -> Objects.equals("丁组", a.getString("bszbName"))).collect(toList());
|
||||
if (Lang.isNotEmpty(fourList)) {
|
||||
fourMap = fourList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||
}
|
||||
|
||||
//团体
|
||||
List<NutMap> fiveList = allList.stream().filter(a -> a.getString("bszbName").equals("团体")).collect(toList());
|
||||
List<NutMap> fiveList = allList.stream().filter(a -> Objects.equals("团体", a.getString("bszbName"))).collect(toList());
|
||||
if (Lang.isNotEmpty(fiveList)) {
|
||||
fiveMap = fiveList.stream().collect(Collectors.groupingBy(v -> v.getString("allName")));
|
||||
}
|
||||
|
||||
+45
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.activity.sports.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
@@ -9,6 +10,8 @@ import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
||||
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService;
|
||||
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsService;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -19,7 +22,12 @@ import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.nutz.mvc.annotation.AdaptBy;
|
||||
import org.nutz.mvc.upload.TempFile;
|
||||
import org.nutz.mvc.upload.UploadAdaptor;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -45,6 +53,10 @@ public class ActivitySportsReadingController {
|
||||
public Dao dao;
|
||||
@Inject
|
||||
public BaseService baseService;
|
||||
@Inject
|
||||
private ActivitySportsService activitySportsService;
|
||||
@Inject
|
||||
private ActivitySportsApplyUserService activitySportsApplyUserService;
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.reading")
|
||||
@@ -150,5 +162,38 @@ public class ActivitySportsReadingController {
|
||||
return Result.success(apply);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("activity.reading")
|
||||
public void downloadImportTemplate(HttpServletResponse response) {
|
||||
checkManageRole();
|
||||
activitySportsApplyUserService.downloadImportTemplate(response);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.reading")
|
||||
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
|
||||
public Result importUserActivitys(@Param("file") TempFile file, @Param("businessId") String activityId) {
|
||||
checkManageRole();
|
||||
return Result.success(activitySportsApplyUserService.importUserActivitys(file, activityId));
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@SaCheckPermission("activity.reading")
|
||||
public void doExportByEnroll(String id, String unionId, HttpServletResponse response) {
|
||||
checkManageRole();
|
||||
activitySportsService.exportXlsx(id, unionId, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参考原项目,导入和整表导出只开放给校工会管理员和系统管理员,避免普通阅览权限误操作。
|
||||
*/
|
||||
private void checkManageRole() {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
throw new BaseException("您没有操作权限");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+18
@@ -6,7 +6,9 @@ import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
||||
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.upload.TempFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
public interface ActivitySportsApplyUserService extends BaseService<ActivitySchoolApply> {
|
||||
@@ -31,4 +33,20 @@ public interface ActivitySportsApplyUserService extends BaseService<ActivityScho
|
||||
|
||||
List<NutMap> getUserUnion(String query);
|
||||
|
||||
/**
|
||||
* 下载报名人员导入模板。
|
||||
*
|
||||
* @param response 响应流
|
||||
*/
|
||||
void downloadImportTemplate(HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 导入报名人员并返回错误明细,全部成功时返回 null。
|
||||
*
|
||||
* @param file 导入文件
|
||||
* @param activityId 活动ID
|
||||
* @return 导入错误统计
|
||||
*/
|
||||
NutMap importUserActivitys(TempFile file, String activityId);
|
||||
|
||||
}
|
||||
|
||||
+234
-1
@@ -1,22 +1,33 @@
|
||||
package com.budwk.app.zhgh.activity.sports.service.impl;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityEvent;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnion;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityBasicUnit;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchool;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolApply;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolEvent;
|
||||
import com.budwk.app.zhgh.activity.sports.models.ActivitySchoolTeam;
|
||||
import com.budwk.app.zhgh.activity.sports.param.ActivitySportsApplyUserPageParam;
|
||||
import com.budwk.app.zhgh.activity.sports.service.ActivitySportsApplyUserService;
|
||||
import com.budwk.app.zhgh.activity.sports.template.ActivitySportsApplyImportTemp;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -31,7 +42,9 @@ import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.Strings;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.upload.TempFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -487,4 +500,224 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
|
||||
sql.setCondition(cnd);
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadImportTemplate(HttpServletResponse response) {
|
||||
try {
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, ActivitySportsApplyImportTemp.class, new ArrayList<>());
|
||||
CommonDownloadUtil.download("报名人员导入模板.xlsx", workbook, response);
|
||||
} catch (Exception e) {
|
||||
throw new BaseException("下载导入模板失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public NutMap importUserActivitys(TempFile file, String activityId) {
|
||||
if (file == null) {
|
||||
throw new BaseException("请选择导入文件");
|
||||
}
|
||||
if (StrUtil.isBlank(activityId)) {
|
||||
throw new BaseException("请先选择活动名称");
|
||||
}
|
||||
ActivitySchool activitySchool = dao().fetch(ActivitySchool.class, activityId);
|
||||
if (activitySchool == null) {
|
||||
throw new BaseException("活动不存在");
|
||||
}
|
||||
try {
|
||||
List<ActivitySportsApplyImportTemp> importList = ExcelImportUtil.importExcel(file.getFile(), ActivitySportsApplyImportTemp.class, new ImportParams());
|
||||
if (Lang.isEmpty(importList)) {
|
||||
return null;
|
||||
}
|
||||
List<ActivitySportsApplyImportTemp> errorList = new ArrayList<>();
|
||||
int totalCount = 0;
|
||||
int successCount = 0;
|
||||
String currentUnionId = getUnionId();
|
||||
for (ActivitySportsApplyImportTemp importTemp : importList) {
|
||||
totalCount++;
|
||||
String loginName = normalizeLoginName(importTemp.getLoginName());
|
||||
if (StrUtil.isBlank(loginName)) {
|
||||
importTemp.setNotes("工号不能为空");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
Sys_user sysUser = dao().fetch(Sys_user.class, Cnd.where("loginname", "=", loginName));
|
||||
if (sysUser == null) {
|
||||
importTemp.setNotes("此用户不存在,请检查工号");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
ActivityBasicUnit basicUnit = dao().fetch(ActivityBasicUnit.class, Cnd.where("id", "=", sysUser.getUnitId()));
|
||||
if (basicUnit == null) {
|
||||
importTemp.setNotes("请检查该人员活动单位是否配置正确");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
ActivityBasicUnion basicUnion = dao().fetch(ActivityBasicUnion.class, Cnd.where("id", "=", basicUnit.getUnionId()));
|
||||
if (basicUnion == null) {
|
||||
importTemp.setNotes("请检查该人员所属活动工会是否配置正确");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
if (!hasImportAuth() && !basicUnion.getId().equals(currentUnionId)) {
|
||||
importTemp.setNotes("此用户不是当前工会人员");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
String identityName = normalizeIdentityName(importTemp.getIdentity());
|
||||
String projectCode = normalizeText(importTemp.getProjectCode());
|
||||
if (StrUtil.isBlank(projectCode) && StrUtil.isBlank(identityName)) {
|
||||
importTemp.setNotes("项目编号和身份不能同时为空");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
|
||||
ActivitySchoolApply activitySchoolApply = buildBaseApply(activityId, sysUser, basicUnit, basicUnion);
|
||||
if (StrUtil.isNotBlank(identityName)) {
|
||||
fillIdentityInfo(activitySchoolApply, identityName);
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(projectCode) && StrUtil.isNotBlank(identityName)) {
|
||||
replaceUnionRoleUser(activitySchoolApply, identityName);
|
||||
insert(activitySchoolApply);
|
||||
successCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ActivityEvent activityEvent = dao().fetch(ActivityEvent.class, Cnd.where("projectCode", "=", projectCode));
|
||||
if (activityEvent == null) {
|
||||
importTemp.setNotes("项目编号不存在,请检查后重试");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
ActivitySchoolEvent schoolEvent = dao().fetch(ActivitySchoolEvent.class, Cnd.where("activityId", "=", activityId).and("eventId", "=", activityEvent.getId()));
|
||||
if (schoolEvent == null) {
|
||||
importTemp.setNotes("该项目不属于当前活动,请检查项目编号");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
|
||||
activitySchoolApply.setEventId(schoolEvent.getEventId());
|
||||
activitySchoolApply.setAwardsMode(activityEvent.getProjectType());
|
||||
if ("2".equals(activityEvent.getProjectType())) {
|
||||
ActivitySchoolTeam schoolTeam = dao().fetch(ActivitySchoolTeam.class, Cnd.where("activityId", "=", activityId).and("eventId", "=", schoolEvent.getEventId()).asc("location"));
|
||||
if (schoolTeam == null) {
|
||||
importTemp.setNotes("团体项目未配置队伍信息,请先维护小队");
|
||||
errorList.add(importTemp);
|
||||
continue;
|
||||
}
|
||||
activitySchoolApply.setTeamId(schoolTeam.getId());
|
||||
activitySchoolApply.setTeam(schoolTeam.getName());
|
||||
}
|
||||
// 兼容参考项目导入逻辑:带项目编号的记录按运动员处理。
|
||||
activitySchoolApply.setIdentity(List.of("1"));
|
||||
clear(Cnd.where("activityId", "=", activityId).and("userId", "=", sysUser.getId()).and("eventId", "=", schoolEvent.getEventId()));
|
||||
insert(activitySchoolApply);
|
||||
successCount++;
|
||||
}
|
||||
|
||||
if (Lang.isNotEmpty(errorList)) {
|
||||
NutMap result = NutMap.NEW();
|
||||
result.setv("totalCount", totalCount);
|
||||
result.setv("successCount", successCount);
|
||||
result.setv("errorCount", errorList.size());
|
||||
result.setv("errorList", errorList.stream().map(v -> NutMap.NEW()
|
||||
.addv("工会", normalizeText(v.getUnionName()))
|
||||
.addv("工号", normalizeText(v.getLoginName()))
|
||||
.addv("姓名", normalizeText(v.getUserName()))
|
||||
.addv("性别", normalizeText(v.getSex()))
|
||||
.addv("项目编号", normalizeText(v.getProjectCode()))
|
||||
.addv("身份", normalizeText(v.getIdentity()))
|
||||
.addv("错误信息", normalizeText(v.getNotes()))).collect(Collectors.toList()));
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new BaseException("导入报名人员失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入记录统一补齐报名基础字段,避免多入口写入时字段不一致。
|
||||
*/
|
||||
private ActivitySchoolApply buildBaseApply(String activityId, Sys_user sysUser, ActivityBasicUnit basicUnit, ActivityBasicUnion basicUnion) {
|
||||
ActivitySchoolApply activitySchoolApply = new ActivitySchoolApply();
|
||||
activitySchoolApply.setActivityId(activityId);
|
||||
activitySchoolApply.setUnitId(basicUnit.getId());
|
||||
activitySchoolApply.setUnionId(basicUnion.getId());
|
||||
activitySchoolApply.setApplyUser(SecurityUtil.getUserId());
|
||||
activitySchoolApply.setUserId(sysUser.getId());
|
||||
activitySchoolApply.setLoginname(sysUser.getLoginname());
|
||||
activitySchoolApply.setUsername(sysUser.getUsername());
|
||||
activitySchoolApply.setSex(sysUser.getSex());
|
||||
activitySchoolApply.setMobile(sysUser.getMobile());
|
||||
activitySchoolApply.setProfessionalLevel(sysUser.getProfessionalLevel());
|
||||
activitySchoolApply.setBirthday(sysUser.getBirthday() == null ? null : DateUtil.formatDate(sysUser.getBirthday()));
|
||||
activitySchoolApply.setApplyDate(DateUtil.now());
|
||||
activitySchoolApply.setStatus(2);
|
||||
activitySchoolApply.setUnitname(basicUnit.getName());
|
||||
activitySchoolApply.setActivityUnionId(basicUnion.getId());
|
||||
activitySchoolApply.setActivityUnionName(basicUnion.getName());
|
||||
return activitySchoolApply;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色类导入只保留当前活动当前工会当前人员的一条对应身份记录,防止重复导入产生脏数据。
|
||||
*/
|
||||
private void replaceUnionRoleUser(ActivitySchoolApply activitySchoolApply, String identityName) {
|
||||
Cnd cnd = Cnd.where("activityId", "=", activitySchoolApply.getActivityId())
|
||||
.and("activityUnionId", "=", activitySchoolApply.getActivityUnionId())
|
||||
.and("userId", "=", activitySchoolApply.getUserId());
|
||||
if ("教练".equals(identityName)) {
|
||||
cnd.and("unionCoach", "=", true);
|
||||
} else if ("领队".equals(identityName)) {
|
||||
cnd.and("unionLeader", "=", true);
|
||||
} else if ("团长".equals(identityName)) {
|
||||
cnd.and("unionHead", "=", true);
|
||||
} else if ("工作人员".equals(identityName)) {
|
||||
cnd.and("unionStaff", "=", true);
|
||||
}
|
||||
clear(cnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一处理导入身份映射,保证页面展示、导出与后续查询读取到一致的身份字段。
|
||||
*/
|
||||
private void fillIdentityInfo(ActivitySchoolApply activitySchoolApply, String identityName) {
|
||||
if ("教练".equals(identityName)) {
|
||||
activitySchoolApply.setUnionCoach(true);
|
||||
activitySchoolApply.setIdentity(List.of("2"));
|
||||
} else if ("领队".equals(identityName)) {
|
||||
activitySchoolApply.setUnionLeader(true);
|
||||
activitySchoolApply.setIdentity(List.of("3"));
|
||||
} else if ("团长".equals(identityName)) {
|
||||
activitySchoolApply.setUnionHead(true);
|
||||
activitySchoolApply.setIdentity(List.of("6"));
|
||||
} else if ("工作人员".equals(identityName)) {
|
||||
activitySchoolApply.setUnionStaff(true);
|
||||
activitySchoolApply.setIdentity(List.of("7"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasImportAuth() {
|
||||
return AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name());
|
||||
}
|
||||
|
||||
private String normalizeLoginName(String loginName) {
|
||||
return StrUtil.isBlank(loginName) ? "" : loginName.replaceAll("\\s+", "");
|
||||
}
|
||||
|
||||
private String normalizeText(String text) {
|
||||
return StrUtil.trimToEmpty(text);
|
||||
}
|
||||
|
||||
private String normalizeIdentityName(String identity) {
|
||||
String identityName = normalizeText(identity);
|
||||
if ("运动员".equals(identityName)) {
|
||||
return "";
|
||||
}
|
||||
return identityName;
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.budwk.app.zhgh.activity.sports.template;
|
||||
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 体育活动报名导入模板
|
||||
*/
|
||||
@Data
|
||||
public class ActivitySportsApplyImportTemp {
|
||||
|
||||
@Excel(name = "工会", width = 20)
|
||||
private String unionName;
|
||||
|
||||
@Excel(name = "工号", width = 20)
|
||||
private String loginName;
|
||||
|
||||
@Excel(name = "姓名", width = 20)
|
||||
private String userName;
|
||||
|
||||
@Excel(name = "性别", width = 12)
|
||||
private String sex;
|
||||
|
||||
@Excel(name = "项目编号", width = 20)
|
||||
private String projectCode;
|
||||
|
||||
@Excel(name = "身份", width = 20)
|
||||
private String identity;
|
||||
|
||||
@Excel(name = "备注", width = 30)
|
||||
private String notes;
|
||||
}
|
||||
+21
@@ -9,6 +9,7 @@ import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.sys.services.SysMsgService;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
@@ -81,17 +82,20 @@ public class ActivityWorksCollectionManageController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.manage")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result insert(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||
worksCollection.setIsSubmit(true);
|
||||
dao.insertWith(worksCollection, "subjectTypes");
|
||||
worksCollection.getSubjectTypes().forEach(item -> {
|
||||
dao.insertLinks(item, "worksTypes");
|
||||
});
|
||||
syncHomeActivity(worksCollection);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.manage")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result save(@Param("data") @Valid Activity_works_collection worksCollection) {
|
||||
worksCollection.setIsSubmit(false);
|
||||
dao.insertWith(worksCollection, "subjectTypes");
|
||||
@@ -122,6 +126,7 @@ public class ActivityWorksCollectionManageController {
|
||||
Cnd.where(Activity_works_worksType::getId, "not in ", workIds)
|
||||
.and(Activity_works_worksType::getSubjectId,"=",item.getId()));
|
||||
});
|
||||
syncHomeActivity(worksCollection);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -132,6 +137,7 @@ public class ActivityWorksCollectionManageController {
|
||||
dao.delete(Activity_works_collection.class, id);
|
||||
dao.clear(Activity_works_collection_upload.class, Cnd.where(Activity_works_collection_upload::getActivityId, "=", id));
|
||||
dao.clear(Activity_works_subjectType.class, Cnd.where(Activity_works_subjectType::getActivityId, "=", id));
|
||||
dao.delete(Sys_home_activity.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -148,11 +154,26 @@ public class ActivityWorksCollectionManageController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.manage")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result enableChange(@Valid String id, @Valid Boolean enable) {
|
||||
dao.update(Activity_works_collection.class, Chain.make("enable", enable), Cnd.where("id", "=", id));
|
||||
Activity_works_collection worksCollection = dao.fetch(Activity_works_collection.class, id);
|
||||
worksCollection.setEnable(enable);
|
||||
syncHomeActivity(worksCollection);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步作品征集到首页活动表:开启的活动写入首页,关闭的活动移除首页入口。
|
||||
*/
|
||||
private void syncHomeActivity(Activity_works_collection worksCollection) {
|
||||
if (Boolean.TRUE.equals(worksCollection.getEnable())) {
|
||||
dao.insertOrUpdate(worksCollection.covertToSysHomeActivity());
|
||||
} else {
|
||||
dao.delete(Sys_home_activity.class, worksCollection.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.manage")
|
||||
public Result sendNotice(@Valid String id) {
|
||||
|
||||
+24
-3
@@ -11,6 +11,7 @@ import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection;
|
||||
import com.budwk.app.zhgh.activity.workscollection.models.Activity_works_collection_upload;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.FieldFilter;
|
||||
@@ -18,6 +19,7 @@ import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.Daos;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
@@ -94,11 +96,17 @@ public class ActivityWorksCollectionUploadController {
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.upload")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result insert(@Param("data") @Valid Activity_works_collection_upload upload) {
|
||||
|
||||
String activityId = upload.getActivityId();
|
||||
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, activityId);
|
||||
if (activity.getEndDateTime().getTime() < System.currentTimeMillis()){
|
||||
long now = System.currentTimeMillis();
|
||||
// 作品上传只允许在活动开始时间和结束时间之间提交,防止活动未开始或已结束后继续上传。
|
||||
if (activity.getStartDateTime().getTime() > now) {
|
||||
return Result.error("活动未开始,不能上传!");
|
||||
}
|
||||
if (activity.getEndDateTime().getTime() < now){
|
||||
return Result.error("活动已结束!");
|
||||
}
|
||||
if (activity.getActivityGroupId() != null) {
|
||||
@@ -124,9 +132,15 @@ public class ActivityWorksCollectionUploadController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.upload")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result update(@Param("data") @Valid Activity_works_collection_upload upload) {
|
||||
Activity_works_collection activity = dao.fetch(Activity_works_collection.class, upload.getActivityId());
|
||||
if (activity.getEndDateTime().getTime() < System.currentTimeMillis()){
|
||||
long now = System.currentTimeMillis();
|
||||
// 编辑作品同样按活动时间窗口控制,避免过期或未开始活动被继续提交作品信息。
|
||||
if (activity.getStartDateTime().getTime() > now) {
|
||||
return Result.error("活动未开始,不能上传!");
|
||||
}
|
||||
if (activity.getEndDateTime().getTime() < now){
|
||||
return Result.error("活动已结束!");
|
||||
}
|
||||
dao.updateIgnoreNull(upload);
|
||||
@@ -155,12 +169,19 @@ public class ActivityWorksCollectionUploadController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("activity.workscollection.upload")
|
||||
/**
|
||||
* 查询当前登录人有权限上传作品的活动主题。
|
||||
*
|
||||
* @param year 活动年度,前端传年度选择框的 yyyy 值,按活动开始时间所在年份过滤。
|
||||
* @return Result,data 为活动列表,仅返回 id、name,且保留已开启和面向对象权限过滤。
|
||||
*/
|
||||
@ApiOperation("获取有权限的活动列表")
|
||||
@Ok("json:{ignoreNull:true}")
|
||||
public Result listPerMissionActivity() {
|
||||
public Result listPerMissionActivity(Long year) {
|
||||
Dao extDao = Daos.ext(dao, FieldFilter.create(Activity_works_collection.class, "id|name|"));
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and(Activity_works_collection::getEnable,"=",1);
|
||||
cnd.andEX("YEAR(startDateTime)", "=", year);
|
||||
cnd.desc(Activity_works_collection::getStartDateTime);
|
||||
List<Activity_works_collection> list = extDao.query(Activity_works_collection.class, cnd);
|
||||
list = list.stream().filter(item -> {
|
||||
|
||||
+20
-1
@@ -1,6 +1,8 @@
|
||||
package com.budwk.app.zhgh.activity.workscollection.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import com.budwk.app.sys.models.Sys_home_activity;
|
||||
import com.budwk.app.sys.services.SysHomeConvert;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
@@ -17,7 +19,7 @@ import java.util.List;
|
||||
@Table("activity_works_collection")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("作品征集活动")
|
||||
public class Activity_works_collection extends BaseModel {
|
||||
public class Activity_works_collection extends BaseModel implements SysHomeConvert {
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@@ -123,4 +125,21 @@ public class Activity_works_collection extends BaseModel {
|
||||
@Many(field = "activityId")
|
||||
private List<Activity_works_collection_upload> uploads;
|
||||
|
||||
@Override
|
||||
public Sys_home_activity covertToSysHomeActivity() {
|
||||
Sys_home_activity sysHomeActivity = new Sys_home_activity();
|
||||
sysHomeActivity.setId(this.getId());
|
||||
sysHomeActivity.setName(this.getName());
|
||||
sysHomeActivity.setCover(this.getCover());
|
||||
sysHomeActivity.setContent(this.getContent());
|
||||
sysHomeActivity.setUrl("/platform/activity/worksCollection/upload");
|
||||
sysHomeActivity.setH5Url("/platform/activity/worksCollection/upload/h5");
|
||||
sysHomeActivity.setStartDate(this.getStartDateTime());
|
||||
sysHomeActivity.setEndDate(this.getEndDateTime());
|
||||
sysHomeActivity.setAllowUserGroupId(this.getActivityGroupId());
|
||||
sysHomeActivity.setEnable(Boolean.TRUE.equals(this.getEnable()));
|
||||
sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName());
|
||||
return sysHomeActivity;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-1
@@ -68,7 +68,7 @@ public class ClubUserJoinApplyController {
|
||||
@Inject
|
||||
private ClubUserJoinService clubUserJoinService;
|
||||
|
||||
@At("/")
|
||||
@At("")
|
||||
@SaCheckPermission("club.join.apply")
|
||||
@Ok("beetl:/platform/zhgh/club/join/apply/index.html")
|
||||
public void index() {
|
||||
@@ -128,6 +128,12 @@ public class ClubUserJoinApplyController {
|
||||
@SLog(tag = "社团管理系统-申请入/退会", msg = "申请社团入/退会")
|
||||
public Result submit(@Param("data") ClubUserApply clubUserApply,
|
||||
@Param("mode") Boolean mode) {
|
||||
if (Boolean.TRUE.equals(mode)) {
|
||||
String qualificationMsg = clubUserJoinService.checkJoinQualification(SecurityUtil.getUserId());
|
||||
if (StrUtil.isNotBlank(qualificationMsg)) {
|
||||
return Result.error(99, qualificationMsg);
|
||||
}
|
||||
}
|
||||
if(mode == false) {
|
||||
clubUserApply = clubUserJoinService.buildExitApply(clubUserApply.getClubId(), SecurityUtil.getUserId());
|
||||
if (ObjectUtil.isEmpty(clubUserApply)) {
|
||||
@@ -192,6 +198,10 @@ public class ClubUserJoinApplyController {
|
||||
@ApiOperation("校验是否申请过社团")
|
||||
@SaCheckPermission(value = {"club.join.apply", "h5.club.join.apply"}, mode = SaMode.OR)
|
||||
public Result checkApplyClub(@Valid String clubId) {
|
||||
String qualificationMsg = clubUserJoinService.checkJoinQualification(SecurityUtil.getUserId());
|
||||
if (StrUtil.isNotBlank(qualificationMsg)) {
|
||||
return Result.error(99, qualificationMsg);
|
||||
}
|
||||
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
|
||||
if (user.getMember() != 1) {
|
||||
return Result.error(99, "抱歉,您不满足入会的条件!");
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class ClubUserJoinApprovalController {
|
||||
@Inject
|
||||
private ClubUserJoinService clubUserJoinService;
|
||||
|
||||
@At("/")
|
||||
@At("")
|
||||
@SaCheckPermission("club.join.clubApproval")
|
||||
@Ok("beetl:/platform/zhgh/club/join/clubApproval/index.html")
|
||||
public void index() {}
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class ClubUserJoinMineController {
|
||||
@Inject
|
||||
private ClubUserJoinService clubUserJoinService;
|
||||
|
||||
@At("/")
|
||||
@At("")
|
||||
@SaCheckPermission("club.join.mine")
|
||||
@Ok("beetl:/platform/zhgh/club/join/mine/index.html")
|
||||
public void index() {}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ClubCommonController {
|
||||
@SaCheckLogin
|
||||
public Result listClubByRole() {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.SCHOOL_UNION_CLUB_ADMIN.name())) {
|
||||
// 报销申请只允许选择当前用户已加入的协会,避免看到未加入的协会数据。
|
||||
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()));
|
||||
List<String> myClubId = clubUsers.stream().map(ClubUser::getClubId).distinct().toList();
|
||||
@@ -78,4 +78,12 @@ public class ClubCommonController {
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
public Result listManageClubByRole() {
|
||||
// 活动人员范围设置只允许按“可管理的社团”选择,避免把仅作为成员加入的社团也展示出来。
|
||||
List<SysClub> clubList = sysClubService.getMyManageClub();
|
||||
return Result.success(clubList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,4 +25,12 @@ public interface ClubUserJoinService extends BaseService<ClubUserApply> {
|
||||
* @return 入会时间
|
||||
*/
|
||||
java.util.Date resolveJoinTime(String clubId, String userId);
|
||||
|
||||
/**
|
||||
* 校验当前用户是否满足申请加入社团的资格。
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 校验不通过时返回提示语,通过时返回null
|
||||
*/
|
||||
String checkJoinQualification(String userId);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.budwk.app.zhgh.club.service.impl;
|
||||
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
import com.budwk.app.zhgh.club.model.ClubUser;
|
||||
import com.budwk.app.zhgh.club.model.ClubUserApply;
|
||||
@@ -15,10 +18,37 @@ import java.util.List;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ClubUserJoinServiceImpl extends BaseServiceImpl<ClubUserApply> implements ClubUserJoinService {
|
||||
private static final List<String> ALLOW_JOIN_PERSON_TYPES = List.of(
|
||||
"教职工",
|
||||
"未起薪人员",
|
||||
"教职工新入会",
|
||||
"教职工其他",
|
||||
"劳动服务公司",
|
||||
"后勤聘用人员",
|
||||
"退休人员[一]",
|
||||
"退休人员[二]",
|
||||
"校聘劳务派遣全额"
|
||||
);
|
||||
|
||||
public ClubUserJoinServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String checkJoinQualification(String userId) {
|
||||
View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", userId));
|
||||
if (user == null) {
|
||||
return "抱歉,您不满足入会的条件!";
|
||||
}
|
||||
if (user.getMember() == null || user.getMember() != 1) {
|
||||
return "抱歉,您不满足入会的条件!";
|
||||
}
|
||||
if (StrUtil.isBlank(user.getPersonType()) || !ALLOW_JOIN_PERSON_TYPES.contains(user.getPersonType())) {
|
||||
return "抱歉,您不满足入会的条件!";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClubUserApply buildExitApply(String clubId, String userId) {
|
||||
// 优先复用最近一次申请记录中的补充信息,避免用户重复填写基础资料。
|
||||
|
||||
@@ -275,7 +275,14 @@ public class SysClubServiceImpl extends BaseServiceImpl<SysClub> implements SysC
|
||||
}
|
||||
cnd.andEX("year(info.createTime)", "=", pageForm.getYear());
|
||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||
cnd.desc("createTime");
|
||||
// 我的注册列表默认按社团编码升序展示,点击表头时按用户选择的方向排序。
|
||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.asc("info.clubCode");
|
||||
} else if ("clubCode".equals(pageForm.getPageOrderName())) {
|
||||
cnd.orderBy("info.clubCode", PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
} else {
|
||||
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
}
|
||||
cnd.groupBy("info.id");
|
||||
sql.setCondition(cnd);
|
||||
return listPageVO(pageForm, sql, ClubRegisterPageVo.class);
|
||||
|
||||
+11
-13
@@ -1,6 +1,7 @@
|
||||
package com.budwk.app.zhgh.dayofficework.message.strategy.impl;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.sms.SmsService;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel;
|
||||
import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy;
|
||||
@@ -21,6 +22,8 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private SmsService smsService;
|
||||
|
||||
@Override
|
||||
public GlobalMessageChannel getChannel() {
|
||||
@@ -70,29 +73,24 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信消息
|
||||
* 发送短信消息。
|
||||
* 接收人由全局消息服务传入的用户ID或登录名查询得到,发送时使用用户工号对接通讯平台;
|
||||
* 返回结果由 SmsService 内部解析并记录,当前策略只负责逐个用户触发发送并记录异常。
|
||||
*/
|
||||
private void sendSmsMessage(String title, String content, Integer type, List<Sys_user> users, JSONObject config) {
|
||||
for (Sys_user user : users) {
|
||||
try {
|
||||
String mobile = user.getMobile();
|
||||
if (mobile == null || mobile.trim().isEmpty()) {
|
||||
log.warn("用户{}没有手机号,跳过短信发送", user.getUsername());
|
||||
String loginName = user.getLoginname();
|
||||
if (loginName == null || loginName.trim().isEmpty()) {
|
||||
log.warn("用户{}没有工号,跳过短信发送", user.getUsername());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构建短信内容
|
||||
String smsContent = buildSmsContent(title, content, type);
|
||||
|
||||
// 执行发送
|
||||
|
||||
boolean success = true;
|
||||
|
||||
if (success) {
|
||||
log.info("短信发送成功:用户{},手机号:{}", user.getUsername(), mobile);
|
||||
} else {
|
||||
log.warn("短信发送失败:用户{},手机号:{}", user.getUsername(), mobile);
|
||||
}
|
||||
smsService.sendSmsByAccount(loginName, smsContent);
|
||||
log.info("短信发送完成:用户{},工号:{}", user.getUsername(), loginName);
|
||||
} catch (Exception e) {
|
||||
log.error("发送短信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e);
|
||||
}
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package com.budwk.app.zhgh.dayofficework.message.strategy.impl;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.sms.SmsService;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel;
|
||||
import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 微信发送策略
|
||||
*/
|
||||
@IocBean
|
||||
@Slf4j
|
||||
public class WechatMessageSendStrategy implements GlobalMessageSendStrategy {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private SmsService smsService;
|
||||
|
||||
@Override
|
||||
public GlobalMessageChannel getChannel() {
|
||||
return GlobalMessageChannel.WECHAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportAsync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String title, String content, Integer type, List<String> receiverIds, JSONObject config) {
|
||||
try {
|
||||
log.info("开始发送微信消息,标题:{},接收人数量:{}", title, receiverIds.size());
|
||||
|
||||
// receiverIds 为 sys_user.id,按用户ID查询后使用工号对接通讯平台微信文本消息接口。
|
||||
List<Sys_user> users = dao.query(Sys_user.class, Cnd.where(Sys_user::getId, "in", receiverIds));
|
||||
sendWechatMessage(title, content, type, users, config);
|
||||
|
||||
log.info("微信消息发送完成,标题:{},接收人数量:{}", title, users.size());
|
||||
} catch (Exception e) {
|
||||
log.error("微信消息发送失败,标题:{},错误:{}", title, e.getMessage(), e);
|
||||
throw new RuntimeException("微信消息发送失败:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendByLoginName(String title, String content, Integer type, List<String> receiverLoginNames, JSONObject config) {
|
||||
try {
|
||||
log.info("开始发送微信消息(按登录名),标题:{},接收人数量:{}", title, receiverLoginNames.size());
|
||||
|
||||
// receiverLoginNames 为 sys_user.loginname,查询用户后仍使用工号作为通讯平台接收人标识。
|
||||
List<Sys_user> users = dao.query(Sys_user.class, Cnd.where(Sys_user::getLoginname, "in", receiverLoginNames));
|
||||
sendWechatMessage(title, content, type, users, config);
|
||||
|
||||
log.info("微信消息发送完成(按登录名),标题:{},接收人数量:{}", title, users.size());
|
||||
} catch (Exception e) {
|
||||
log.error("微信消息发送失败(按登录名),标题:{},错误:{}", title, e.getMessage(), e);
|
||||
throw new RuntimeException("微信消息发送失败:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送微信文本消息。
|
||||
* 接收人来自全局消息服务传入的用户ID或登录名,方法内部转换为 Sys_user 后取工号发送;
|
||||
* SmsService 返回 MsgPlatformResponse,当前策略按单人发送记录日志,单个用户失败不影响其他接收人。
|
||||
*/
|
||||
private void sendWechatMessage(String title, String content, Integer type, List<Sys_user> users, JSONObject config) {
|
||||
for (Sys_user user : users) {
|
||||
try {
|
||||
String loginName = user.getLoginname();
|
||||
if (loginName == null || loginName.trim().isEmpty()) {
|
||||
log.warn("用户{}没有工号,跳过微信发送", user.getUsername());
|
||||
continue;
|
||||
}
|
||||
|
||||
String wechatContent = buildWechatContent(title, content, type);
|
||||
smsService.sendWechatTextByAccountOrMobile(loginName, wechatContent);
|
||||
log.info("微信发送完成:用户{},工号:{}", user.getUsername(), loginName);
|
||||
} catch (Exception e) {
|
||||
log.error("发送微信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建微信文本内容。
|
||||
* type=2 表示待办消息,其余类型按系统通知处理,内容格式保持与短信策略一致。
|
||||
*/
|
||||
private String buildWechatContent(String title, String content, Integer type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (type != null && type == 2) {
|
||||
sb.append("【待办通知】");
|
||||
} else {
|
||||
sb.append("【系统通知】");
|
||||
}
|
||||
|
||||
sb.append(title);
|
||||
if (content != null && !content.trim().isEmpty()) {
|
||||
sb.append(":").append(content);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -457,9 +457,13 @@ public class SiteCugApplyController {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当预约日期就是今天时,已经过了开始时间的时间块直接标记为不可预约,
|
||||
* 这样全天候和分段预约在前端展示时都会统一变成禁用状态。
|
||||
*/
|
||||
private NutMap buildAvailabilityBlock(String day, int startMinute, int endMinute, List<int[]> reservedRanges, List<int[]> disabledRanges, boolean siteClosed, int groupIndex, String groupLabel) {
|
||||
String status = "available";
|
||||
if (siteClosed || intersectsAny(startMinute, endMinute, disabledRanges)) {
|
||||
if (siteClosed || isExpiredAvailabilityBlock(day, startMinute) || intersectsAny(startMinute, endMinute, disabledRanges)) {
|
||||
status = "closed";
|
||||
} else if (intersectsAny(startMinute, endMinute, reservedRanges)) {
|
||||
status = "reserved";
|
||||
@@ -478,6 +482,19 @@ public class SiteCugApplyController {
|
||||
.addv("endDateTime", day + " " + formatMinutes(endMinute) + ":00");
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅在当天按“时间块开始时间是否已经过去”判断是否失效,
|
||||
* 避免用户继续选中已经开始或已经结束的预约时段。
|
||||
*/
|
||||
private boolean isExpiredAvailabilityBlock(String day, int startMinute) {
|
||||
String today = DateUtil.today();
|
||||
if (!StrUtil.equals(today, day)) {
|
||||
return false;
|
||||
}
|
||||
DateTime blockStart = DateUtil.parseDateTime(day + " " + formatMinutes(startMinute) + ":00");
|
||||
return !blockStart.isAfter(DateUtil.date());
|
||||
}
|
||||
|
||||
private boolean isSiteClosed(SiteCugInfo siteInfo, String day, Set<String> holidaySet) {
|
||||
if (isWeekend(day)) {
|
||||
return true;
|
||||
|
||||
+26
-17
@@ -113,22 +113,23 @@ public class UnionReimburseApplyController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
// @At
|
||||
// @ApiOperation("重新提交申请")
|
||||
// @Aop(TransAop.READ_COMMITTED)
|
||||
// @SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
// public Result submitAgain(@Param("data") UnionReimburse unionReimburse, @Param("taskId") Long taskId) {
|
||||
// if (StrUtil.isBlank(unionReimburse.getId())) unionReimburse.setCreateTime(new Date());
|
||||
//
|
||||
// dao.insertOrUpdate(unionReimburse);
|
||||
//
|
||||
// Dict dict = Dict.create();
|
||||
// dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
|
||||
// dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
||||
// dict.set("userId", unionReimburse.getCondolenceUserId());
|
||||
// flowCommonService.executeTask(dict);
|
||||
// return Result.success();
|
||||
// }
|
||||
@At
|
||||
@ApiOperation("重新提交申请")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
public Result submitAgain(@Param("data") UnionReimburse unionReimburse, @Param("taskId") Long taskId) {
|
||||
// 退回重提也必须复用当前提交保存逻辑,避免绕过发票明细落库和提交校验。
|
||||
Result result = unionReimburseService.saveApply(unionReimburse, 2);
|
||||
if (result.getCode() != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Dict dict = Dict.create();
|
||||
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
|
||||
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
||||
flowCommonService.executeTask(dict);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@@ -179,6 +180,14 @@ public class UnionReimburseApplyController {
|
||||
return Result.success(pagination.getList());
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("查询付款人")
|
||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
@SLog(type = "unionReimburse", tag = "查询付款人", msg = "按经费来源查询付款人")
|
||||
public Result listPayerUser(String keyword, String reimburseFundSource, String clubId) {
|
||||
return Result.success(unionReimburseService.listPayerUser(keyword, reimburseFundSource, clubId));
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("查询职工慰问类型")
|
||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
@@ -267,6 +276,6 @@ public class UnionReimburseApplyController {
|
||||
@ApiOperation("统一查询经费余额")
|
||||
@SaCheckPermission(value = {"unionReimburse.apply", "h5.unionReimburse.apply"}, mode = SaMode.OR)
|
||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
||||
return unionReimburseService.getBudgetBalance(reimburseFundSource, clubId);
|
||||
return unionReimburseService.getBudgetBalance(reimburseFundSource, clubId, null);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -7,6 +7,7 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
@@ -26,12 +27,14 @@ import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
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;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
@@ -117,12 +120,10 @@ public class UnionReimburseCollectController {
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"unionReimburse.collect", "h5.unionReimburse.collect"}, mode = SaMode.OR)
|
||||
public Result updateActuallyAmount(String id,Double realMoney) {
|
||||
UnionReimburse unionReimburse = unionReimburseService.fetch(id);
|
||||
unionReimburse.setRealMoney(realMoney);
|
||||
unionReimburseService.updateIgnoreNull(unionReimburse);
|
||||
return Result.success();
|
||||
return unionReimburseService.updateActuallyAmount(id, realMoney);
|
||||
}
|
||||
|
||||
@At
|
||||
@@ -237,6 +238,9 @@ public class UnionReimburseCollectController {
|
||||
item.setReimburseFundSource(typeDict.getName());
|
||||
}
|
||||
}
|
||||
if (StrUtil.isNotBlank(item.getCreateTime())) {
|
||||
item.setCreateTime(DateUtil.format(DateUtil.parse(item.getCreateTime()), "yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
// 拼接备注字段(仿照系统代码逻辑,使用activityName和condolenceName字段)
|
||||
if (cn.hutool.core.util.StrUtil.isNotBlank(item.getActivityName())) {
|
||||
|
||||
+3
-3
@@ -189,7 +189,7 @@ public class UnionReimburseMineController {
|
||||
@SaCheckPermission(value = {"unionReimburse.mine", "h5.unionReimburse.mine"}, mode = SaMode.OR)
|
||||
@SLog( tag = "删除工会报销", msg = "删除工会报销")
|
||||
public Result delete(@Param("id") String id) {
|
||||
unionReimburseService.delete(id);
|
||||
unionReimburseService.deleteApply(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class UnionReimburseMineController {
|
||||
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd"));
|
||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||
docData.put("unitName", unionReimburse.getUnitName());
|
||||
docData.put("userName", unionReimburse.getUserName());
|
||||
docData.put("loginName", unionReimburse.getLoginName());
|
||||
@@ -309,7 +309,7 @@ public class UnionReimburseMineController {
|
||||
.create();
|
||||
docData.put("qrcode", pictureRenderData);
|
||||
|
||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd"));
|
||||
docData.put("createTime", DateUtil.format(unionReimburse.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
|
||||
docData.put("unitName", unionReimburse.getUnitName());
|
||||
docData.put("userName", unionReimburse.getUserName());
|
||||
docData.put("loginName", unionReimburse.getLoginName());
|
||||
|
||||
+2
-16
@@ -12,7 +12,6 @@ import com.budwk.app.zhgh.dayofficework.unionReimburse.model.UnionReimburse;
|
||||
import com.budwk.app.zhgh.dayofficework.unionReimburse.service.UnionReimburseService;
|
||||
import io.swagger.annotations.Api;
|
||||
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.Sqls;
|
||||
@@ -32,7 +31,6 @@ import java.util.List;
|
||||
@At("/platform/unionReimburse/review")
|
||||
@Ok("json:full")
|
||||
@Api("工会报销审核")
|
||||
@Slf4j
|
||||
public class UnionReimburseReviewController {
|
||||
|
||||
@Inject
|
||||
@@ -110,19 +108,7 @@ public class UnionReimburseReviewController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission(value = {"unionReimburse.review", "h5.unionReimburse.review"}, mode = SaMode.OR)
|
||||
@SLog(tag = "工会报销审核", msg = "一键审核工会报销")
|
||||
public Result allReview() {
|
||||
try {
|
||||
List<UnionReimburse> reimbursements = unionReimburseService.query(Cnd.where("stateId", "=", 2));
|
||||
for (UnionReimburse reimbursement : reimbursements) {
|
||||
Result result = unionReimburseService.reviewApply(reimbursement.getId(), "通过", 3);
|
||||
if (result.getCode() != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Result.success("一键审核完成,共处理" + reimbursements.size() + "条记录");
|
||||
} catch (Exception e) {
|
||||
log.error("一键审核失败", e);
|
||||
return Result.error("一键审核失败: " + e.getMessage());
|
||||
}
|
||||
public Result allReview(@Param("ids[]") String[] ids) {
|
||||
return unionReimburseService.batchReviewApply(ids);
|
||||
}
|
||||
}
|
||||
|
||||
+30
-1
@@ -6,6 +6,7 @@ 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;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,11 +24,26 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
*/
|
||||
UnionReimburse getApplyForm(String id);
|
||||
|
||||
/**
|
||||
* 删除报销申请,并同步删除关联发票明细。
|
||||
*/
|
||||
void deleteApply(String id);
|
||||
|
||||
/**
|
||||
* 查询付款人的历史收款信息。
|
||||
*/
|
||||
List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer);
|
||||
|
||||
/**
|
||||
* 查询付款人候选人;协会经费按所选协会过滤,只返回该协会成员。
|
||||
*
|
||||
* @param keyword 姓名或工号关键字
|
||||
* @param reimburseFundSource 当前选择的经费来源
|
||||
* @param clubId 协会经费对应的协会ID
|
||||
* @return 可选付款人列表
|
||||
*/
|
||||
List<NutMap> listPayerUser(String keyword, String reimburseFundSource, String clubId);
|
||||
|
||||
/**
|
||||
* 校验发票号码是否与历史报销记录重复。
|
||||
*/
|
||||
@@ -41,10 +57,23 @@ public interface UnionReimburseService extends BaseService<UnionReimburse> {
|
||||
/**
|
||||
* 查询报销可用经费余额,同时校验是否已分配以及协会归属权限。
|
||||
*/
|
||||
Result getBudgetBalance(String reimburseFundSource, String clubId);
|
||||
Result getBudgetBalance(String reimburseFundSource, String clubId, String unionId);
|
||||
|
||||
/**
|
||||
* 审核报销,审核通过时扣减对应预算并新增预算使用详情。
|
||||
*/
|
||||
Result reviewApply(String reimburseId, String reviewOpinion, int submitType);
|
||||
|
||||
/**
|
||||
* 管理员修改实际报销金额,已报销成功的数据需要同步调整经费预算管理台账。
|
||||
*/
|
||||
Result updateActuallyAmount(String id, Double realMoney);
|
||||
|
||||
/**
|
||||
* 批量审核选中的待审核报销申请。
|
||||
*
|
||||
* @param reimburseIds 前端表格勾选的报销申请ID数组,只处理状态为待审核确认的数据
|
||||
* @return Result,成功时返回本次实际审核通过的记录数量,失败时返回具体错误原因
|
||||
*/
|
||||
Result batchReviewApply(String[] reimburseIds);
|
||||
}
|
||||
|
||||
+307
-17
@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.sys.models.Sys_file;
|
||||
@@ -122,7 +123,10 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
normalizeInvoiceDetails(unionReimburse);
|
||||
if (needInvoiceDetails(unionReimburse)) {
|
||||
fillInvoiceSummary(unionReimburse);
|
||||
} else {
|
||||
fillCondolenceInvoiceSummary(unionReimburse);
|
||||
}
|
||||
fillDefaultRealMoney(unionReimburse);
|
||||
if (stateId == 2) {
|
||||
Result validateResult = validateBeforeSubmit(unionReimburse);
|
||||
if (validateResult != null) {
|
||||
@@ -139,23 +143,29 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
}
|
||||
|
||||
if (oldRecord == null) {
|
||||
unionReimburse.setCreateTime(DateUtil.date());
|
||||
unionReimburse.setCreateTime(toSecondPrecision(DateUtil.date()));
|
||||
unionReimburse.setDocumentNo(generateDocumentNo());
|
||||
} else {
|
||||
unionReimburse.setCreateTime(oldRecord.getCreateTime());
|
||||
unionReimburse.setCreateTime(toSecondPrecision(oldRecord.getCreateTime()));
|
||||
unionReimburse.setDocumentNo(oldRecord.getDocumentNo());
|
||||
}
|
||||
unionReimburse.setStateId(stateId);
|
||||
if ("UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())) {
|
||||
unionReimburse.setRealMoney(unionReimburse.getCondolenceMoney());
|
||||
} else {
|
||||
unionReimburse.setRealMoney(unionReimburse.getMoney());
|
||||
}
|
||||
fillDefaultRealMoney(unionReimburse);
|
||||
this.dao().insertOrUpdate(unionReimburse);
|
||||
saveInvoiceDetails(unionReimburse.getId(), unionReimburse.getInvoiceDetails());
|
||||
return Result.success(stateId == 2 ? "提交成功" : "保存成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请时间统一保存到秒,避免数据库和页面出现毫秒级时间。
|
||||
*/
|
||||
private Date toSecondPrecision(Date date) {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
return new Date((date.getTime() / 1000) * 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnionReimburse getApplyForm(String id) {
|
||||
UnionReimburse unionReimburse = this.fetch(id);
|
||||
@@ -170,6 +180,16 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
return unionReimburse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteApply(String id) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return;
|
||||
}
|
||||
// 删除申请主记录时同步清理发票明细,避免遗留无归属的发票关联数据。
|
||||
this.dao().clear(UnionReimburseInvoiceDetail.class, Cnd.where("reimburseId", "=", id));
|
||||
this.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UnionReimburseBankHistoryVO> getUserBankHistory(String payer) {
|
||||
if (StrUtil.isBlank(payer)) {
|
||||
@@ -199,6 +219,55 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
return this.listVO(sql, UnionReimburseBankHistoryVO.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款人查询要跟随经费来源;选择协会经费时,只允许从当前协会会员中选择付款人。
|
||||
*/
|
||||
@Override
|
||||
public List<NutMap> listPayerUser(String keyword, String reimburseFundSource, String clubId) {
|
||||
boolean clubFundSource = "UNION_REIMBURSE_FUND_SOURCE_3".equals(reimburseFundSource);
|
||||
if (clubFundSource && StrUtil.isBlank(clubId)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
String clubJoinSql = clubFundSource ? "INNER JOIN club_user cu ON cu.userId = u.id" : "";
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
u.id,
|
||||
u.username AS userName,
|
||||
u.loginname AS loginName,
|
||||
u.sex,
|
||||
u.mobile,
|
||||
u.technicalTitle,
|
||||
IFNULL(u.unitname, '暂无') AS unitName,
|
||||
u.unitid AS unitId,
|
||||
u.unionid AS unionId,
|
||||
u.unionname AS unionName,
|
||||
DATE(u.birthday) AS birthday,
|
||||
u.idCard,
|
||||
u.unionCode
|
||||
FROM
|
||||
vw_user u
|
||||
%s
|
||||
$condition
|
||||
""".formatted(clubJoinSql));
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.or("u.loginname", "like", "%" + keyword + "%");
|
||||
seg.or("u.username", "like", "%" + keyword + "%");
|
||||
cnd.and(seg);
|
||||
}
|
||||
cnd.and("u.id", "!=", SecurityUtil.getUserId());
|
||||
if (clubFundSource) {
|
||||
cnd.and("cu.clubId", "=", clubId);
|
||||
} else if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("u.unionid", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
cnd.groupBy("u.id");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = this.listPageMap(1, 50, sql);
|
||||
return pagination.getList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result checkInvoiceDuplicate(String invoiceNo, String reimburseId) {
|
||||
String currentInvoiceNo = StrUtil.blankToDefault(StrUtil.trim(invoiceNo), "");
|
||||
@@ -244,7 +313,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
* 按经费来源统一查询当前可用余额,未分配或权限不匹配时直接拦截。
|
||||
*/
|
||||
@Override
|
||||
public Result getBudgetBalance(String reimburseFundSource, String clubId) {
|
||||
public Result getBudgetBalance(String reimburseFundSource, String clubId, String unionId) {
|
||||
if (StrUtil.isBlank(reimburseFundSource)) {
|
||||
return Result.error("请选择经费来源");
|
||||
}
|
||||
@@ -257,8 +326,9 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
return Result.success(formatMoney(outlayManageSchool.getTotalQuota().subtract(outlayManageSchool.getUsedQuota())));
|
||||
}
|
||||
if ("UNION_REIMBURSE_FUND_SOURCE_2".equals(reimburseFundSource)) {
|
||||
String queryUnionId = StrUtil.blankToDefault(unionId, SecurityUtil.getUnionId());
|
||||
OutlayManageUnion outlayManageUnion = dao().fetch(OutlayManageUnion.class,
|
||||
Cnd.where("unionId", "=", SecurityUtil.getUnionId()).and("year", "=", DateUtil.thisYear()));
|
||||
Cnd.where("unionId", "=", queryUnionId).and("year", "=", DateUtil.thisYear()));
|
||||
if (outlayManageUnion == null) {
|
||||
return Result.error("分工会经费未分配");
|
||||
}
|
||||
@@ -315,6 +385,58 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量审核前只查询前端勾选且仍处于待审核确认状态的数据,避免误处理未勾选或状态已变化的申请。
|
||||
*/
|
||||
@Override
|
||||
public Result batchReviewApply(String[] reimburseIds) {
|
||||
if (reimburseIds == null || reimburseIds.length == 0) {
|
||||
return Result.error("请选择需要审核的报销申请");
|
||||
}
|
||||
List<UnionReimburse> reimbursements = this.query(Cnd.where("id", "in", reimburseIds).and("stateId", "=", 2));
|
||||
if (reimbursements.isEmpty()) {
|
||||
return Result.error("所选记录中没有待审核的数据");
|
||||
}
|
||||
for (UnionReimburse reimbursement : reimbursements) {
|
||||
Result result = this.reviewApply(reimbursement.getId(), "通过", 3);
|
||||
if (result.getCode() != 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return Result.success("一键审核完成,共处理" + reimbursements.size() + "条记录");
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员修改实际金额时,报销成功的数据已经写入预算台账,需要按差额同步已使用额度和使用明细。
|
||||
*/
|
||||
@Override
|
||||
public Result updateActuallyAmount(String id, Double realMoney) {
|
||||
if (StrUtil.isBlank(id)) {
|
||||
return Result.error("报销记录ID不能为空");
|
||||
}
|
||||
BigDecimal newMoney = normalizeActualMoney(realMoney);
|
||||
if (newMoney == null || newMoney.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return Result.error("实际报销金额必须大于0");
|
||||
}
|
||||
UnionReimburse dbRecord = this.fetch(id);
|
||||
if (dbRecord == null) {
|
||||
return Result.error("未找到对应的报销记录");
|
||||
}
|
||||
if (Integer.valueOf(3).equals(dbRecord.getStateId())) {
|
||||
OutlayUseDetail oldDetail = dao().fetch(OutlayUseDetail.class, Cnd.where("outlayReimburseId", "=", dbRecord.getId()));
|
||||
BigDecimal oldMoney = oldDetail != null && oldDetail.getAdjustMoney() != null
|
||||
? oldDetail.getAdjustMoney()
|
||||
: getApplyMoney(dbRecord);
|
||||
Result syncResult = syncApprovedActualAmount(dbRecord, oldDetail, oldMoney, newMoney);
|
||||
if (syncResult != null && syncResult.getCode() != 0) {
|
||||
return syncResult;
|
||||
}
|
||||
}
|
||||
dbRecord.setRealMoney(newMoney.doubleValue());
|
||||
this.updateIgnoreNull(dbRecord);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private void normalizeInvoiceDetails(UnionReimburse unionReimburse) {
|
||||
if (unionReimburse.getInvoiceDetails() == null) {
|
||||
unionReimburse.setInvoiceDetails(new ArrayList<>());
|
||||
@@ -360,6 +482,36 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
unionReimburse.setInvoiceNumber(String.valueOf(invoiceFileCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* 慰问类报销允许不填发票;有发票时按发票汇总金额申请,没有发票时按慰问金额申请。
|
||||
*/
|
||||
private void fillCondolenceInvoiceSummary(UnionReimburse unionReimburse) {
|
||||
double totalMoney = 0D;
|
||||
int invoiceFileCount = 0;
|
||||
for (UnionReimburseInvoiceDetail detail : unionReimburse.getInvoiceDetails()) {
|
||||
if (detail.getInvoiceAmount() != null) {
|
||||
totalMoney = BigDecimal.valueOf(totalMoney)
|
||||
.add(BigDecimal.valueOf(detail.getInvoiceAmount()))
|
||||
.doubleValue();
|
||||
}
|
||||
if (Lang.isNotEmpty(detail.getInvoiceFiles())) {
|
||||
invoiceFileCount++;
|
||||
}
|
||||
}
|
||||
Double applyMoney = invoiceFileCount > 0
|
||||
? BigDecimal.valueOf(totalMoney).setScale(2, RoundingMode.HALF_UP).doubleValue()
|
||||
: unionReimburse.getCondolenceMoney();
|
||||
unionReimburse.setMoney(applyMoney);
|
||||
unionReimburse.setInvoiceNumber(String.valueOf(invoiceFileCount));
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认实际金额跟随申请金额,后续管理员可在汇总页按最终报销金额调整。
|
||||
*/
|
||||
private void fillDefaultRealMoney(UnionReimburse unionReimburse) {
|
||||
unionReimburse.setRealMoney(getDeclaredApplyMoney(unionReimburse).doubleValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交前补一层后端校验,防止前端绕过校验直接提交。
|
||||
*/
|
||||
@@ -379,11 +531,8 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
// if (StrUtil.isBlank(unionReimburse.getBankOfDeposit())) {
|
||||
// return Result.error("请填写开户行");
|
||||
// }
|
||||
if (StrUtil.isBlank(unionReimburse.getPaymentNotes())) {
|
||||
return Result.error("请填写支付内容");
|
||||
}
|
||||
if (!needInvoiceDetails(unionReimburse)) {
|
||||
return null;
|
||||
return validateInvoiceDetails(unionReimburse, false);
|
||||
}
|
||||
if (StrUtil.isBlank(unionReimburse.getActivityName())) {
|
||||
return Result.error("请填写活动名称");
|
||||
@@ -397,7 +546,17 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
if (Lang.isEmpty(unionReimburse.getFiles())) {
|
||||
return Result.error("请上传附件");
|
||||
}
|
||||
return validateInvoiceDetails(unionReimburse, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发票明细提交校验:活动类必须至少一条,慰问类允许为空但填写后必须完整。
|
||||
*/
|
||||
private Result validateInvoiceDetails(UnionReimburse unionReimburse, boolean required) {
|
||||
if (Lang.isEmpty(unionReimburse.getInvoiceDetails())) {
|
||||
if (!required) {
|
||||
return null;
|
||||
}
|
||||
return Result.error("请至少维护一条发票明细");
|
||||
}
|
||||
for (int i = 0; i < unionReimburse.getInvoiceDetails().size(); i++) {
|
||||
@@ -426,7 +585,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
* 提交和审核前统一校验预算是否已分配、余额是否充足。
|
||||
*/
|
||||
private Result validateFundSourceBeforeSubmit(UnionReimburse unionReimburse) {
|
||||
Result balanceResult = getBudgetBalance(unionReimburse.getReimburseFundSource(), unionReimburse.getClubId());
|
||||
Result balanceResult = getBudgetBalance(unionReimburse.getReimburseFundSource(), unionReimburse.getClubId(), unionReimburse.getUnionId());
|
||||
if (balanceResult == null || balanceResult.getCode() != 0) {
|
||||
return balanceResult == null ? Result.error("经费余额校验失败") : balanceResult;
|
||||
}
|
||||
@@ -493,6 +652,117 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
return Result.error("不支持的经费来源");
|
||||
}
|
||||
|
||||
/**
|
||||
* 已通过报销单修改实际金额时,用差额同步预算主表和使用明细,避免重复全量扣减。
|
||||
*/
|
||||
private Result syncApprovedActualAmount(UnionReimburse unionReimburse, OutlayUseDetail oldDetail,
|
||||
BigDecimal oldMoney, BigDecimal newMoney) {
|
||||
BigDecimal diffMoney = newMoney.subtract(safeMoney(oldMoney)).setScale(2, RoundingMode.HALF_UP);
|
||||
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("校工会经费未分配");
|
||||
}
|
||||
Result quotaResult = updateSchoolUsedQuota(outlayManageSchool, diffMoney);
|
||||
if (quotaResult.getCode() != 0) {
|
||||
return quotaResult;
|
||||
}
|
||||
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageSchool.getId(), newMoney);
|
||||
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("分工会经费未分配");
|
||||
}
|
||||
Result quotaResult = updateUnionUsedQuota(outlayManageUnion, diffMoney);
|
||||
if (quotaResult.getCode() != 0) {
|
||||
return quotaResult;
|
||||
}
|
||||
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageUnion.getId(), newMoney);
|
||||
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("该协会本年度未生成预算记录,请先在协会预算分配中补分配");
|
||||
}
|
||||
Result quotaResult = updateClubUsedQuota(outlayManageClub, diffMoney);
|
||||
if (quotaResult.getCode() != 0) {
|
||||
return quotaResult;
|
||||
}
|
||||
saveOrUpdateUseDetail(unionReimburse, oldDetail, outlayManageClub.getId(), newMoney);
|
||||
return Result.success();
|
||||
}
|
||||
return Result.error("不支持的经费来源");
|
||||
}
|
||||
|
||||
private Result updateSchoolUsedQuota(OutlayManageSchool outlayManageSchool, BigDecimal diffMoney) {
|
||||
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageSchool.getTotalQuota(), outlayManageSchool.getUsedQuota(), diffMoney, "校工会经费");
|
||||
if (newUsedQuota == null) {
|
||||
return Result.error("校工会经费余额不足");
|
||||
}
|
||||
outlayManageSchool.setUsedQuota(newUsedQuota);
|
||||
dao().updateIgnoreNull(outlayManageSchool);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private Result updateUnionUsedQuota(OutlayManageUnion outlayManageUnion, BigDecimal diffMoney) {
|
||||
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageUnion.getTotalQuota(), outlayManageUnion.getUsedQuota(), diffMoney, "分工会经费");
|
||||
if (newUsedQuota == null) {
|
||||
return Result.error("分工会经费余额不足");
|
||||
}
|
||||
outlayManageUnion.setUsedQuota(newUsedQuota);
|
||||
dao().updateIgnoreNull(outlayManageUnion);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
private Result updateClubUsedQuota(OutlayManageClub outlayManageClub, BigDecimal diffMoney) {
|
||||
BigDecimal newUsedQuota = buildNewUsedQuota(outlayManageClub.getTotalQuota(), outlayManageClub.getUsedQuota(), diffMoney, "协会经费");
|
||||
if (newUsedQuota == null) {
|
||||
return Result.error("协会经费余额不足");
|
||||
}
|
||||
outlayManageClub.setUsedQuota(newUsedQuota);
|
||||
dao().updateIgnoreNull(outlayManageClub);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算调整后的已使用额度,调增时不能超过总额度,调减时不能小于0。
|
||||
*/
|
||||
private BigDecimal buildNewUsedQuota(BigDecimal totalQuota, BigDecimal usedQuota, BigDecimal diffMoney, String outlayName) {
|
||||
BigDecimal safeTotalQuota = safeMoney(totalQuota);
|
||||
BigDecimal safeUsedQuota = safeMoney(usedQuota);
|
||||
BigDecimal safeDiffMoney = safeMoney(diffMoney);
|
||||
BigDecimal newUsedQuota = safeUsedQuota.add(safeDiffMoney).setScale(2, RoundingMode.HALF_UP);
|
||||
if (safeDiffMoney.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return newUsedQuota;
|
||||
}
|
||||
if (newUsedQuota.compareTo(BigDecimal.ZERO) < 0) {
|
||||
return null;
|
||||
}
|
||||
if (newUsedQuota.compareTo(safeTotalQuota) > 0) {
|
||||
log.warn("{}实际金额调增后超出预算,总额度:{}, 已使用:{}, 调整差额:{}", outlayName, safeTotalQuota, safeUsedQuota, diffMoney);
|
||||
return null;
|
||||
}
|
||||
return newUsedQuota;
|
||||
}
|
||||
|
||||
private void saveOrUpdateUseDetail(UnionReimburse unionReimburse, OutlayUseDetail oldDetail,
|
||||
String outlayManageId, BigDecimal newMoney) {
|
||||
if (oldDetail == null) {
|
||||
insertUseDetail(unionReimburse, outlayManageId, newMoney);
|
||||
return;
|
||||
}
|
||||
oldDetail.setOutlayManageId(outlayManageId);
|
||||
oldDetail.setAdjustMoney(newMoney);
|
||||
dao().updateIgnoreNull(oldDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一张报销单只写入一条预算使用详情,避免重复通过或重复点击造成重复明细。
|
||||
*/
|
||||
@@ -516,11 +786,31 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
}
|
||||
|
||||
private BigDecimal getApplyMoney(UnionReimburse unionReimburse) {
|
||||
Double money = "UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())
|
||||
? unionReimburse.getCondolenceMoney() : unionReimburse.getMoney();
|
||||
if (unionReimburse.getRealMoney() != null) {
|
||||
return BigDecimal.valueOf(unionReimburse.getRealMoney()).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
return getDeclaredApplyMoney(unionReimburse);
|
||||
}
|
||||
|
||||
private BigDecimal getDeclaredApplyMoney(UnionReimburse unionReimburse) {
|
||||
Double money = unionReimburse.getMoney();
|
||||
if (money == null && "UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject())) {
|
||||
money = unionReimburse.getCondolenceMoney();
|
||||
}
|
||||
return BigDecimal.valueOf(money == null ? 0D : money).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private BigDecimal normalizeActualMoney(Double realMoney) {
|
||||
if (realMoney == null || realMoney.isNaN() || realMoney.isInfinite()) {
|
||||
return null;
|
||||
}
|
||||
return realMoney == null ? null : BigDecimal.valueOf(realMoney).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private BigDecimal safeMoney(BigDecimal money) {
|
||||
return money == null ? BigDecimal.ZERO : money.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private String buildUseDetailProjectName(UnionReimburse unionReimburse) {
|
||||
if (StrUtil.isNotBlank(unionReimburse.getActivityName())) {
|
||||
return unionReimburse.getActivityName();
|
||||
@@ -851,7 +1141,7 @@ public class UnionReimburseServiceImpl extends BaseServiceImpl<UnionReimburse> i
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前仅活动类报销维护发票明细,慰问类仍按原有逻辑处理金额。
|
||||
* 非慰问类报销必须维护发票明细,慰问类发票明细为可选。
|
||||
*/
|
||||
private boolean needInvoiceDetails(UnionReimburse unionReimburse) {
|
||||
return unionReimburse != null && !"UNION_REIMBURSE_PROJECT_1".equals(unionReimburse.getReimburseProject());
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class ProposalDashboardController {
|
||||
nodes.add(NutMap.NEW().addv("name", "提案总数").addv("id", "total").addv("type", "total").addv("count", 0));
|
||||
|
||||
// 节点
|
||||
ProcessDefine define = processDefineService.getLastByName("JDHTA");
|
||||
ProcessDefine define = processDefineService.getLastByName("JDHTA_NC");
|
||||
ProcessModel processModel = processDefineService.processDefineToModel(define);
|
||||
List<TaskModel> taskModels = processModel.getTasks();
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ public class ProposalQueryChartController {
|
||||
FROM
|
||||
wf_process_design
|
||||
WHERE
|
||||
NAME = 'JDHTA'
|
||||
NAME = 'JDHTA_NC'
|
||||
""");
|
||||
sql.setCallback(Sqls.callback.map());
|
||||
dao.execute(sql);
|
||||
|
||||
+1
@@ -120,6 +120,7 @@ public class ProposalSecondedController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
|
||||
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
|
||||
cnd.and("info.createUserId", "!=", SecurityUtil.getUserId());
|
||||
|
||||
if (approval) {
|
||||
// 已附议页签只展示当前登录附议人已经处理过的记录。
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ public class TeacherCongressDelegatePushController {
|
||||
""");
|
||||
sql.setParam("sessionId", sessionId);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
// cnd.and("u.member", "=", 1);
|
||||
cnd.and("u.member", "=", 1);
|
||||
cnd.and("u.username", "is not", null);
|
||||
cnd.andEX("u.id", "not in", userIds);
|
||||
cnd.and("tcd.userId", "is", null);
|
||||
|
||||
+9
@@ -12,6 +12,8 @@ import com.budwk.app.bpm.service.BpmService;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin;
|
||||
import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType;
|
||||
import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord;
|
||||
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberChangePageForm;
|
||||
import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService;
|
||||
@@ -22,6 +24,7 @@ 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.Static;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
@@ -111,6 +114,12 @@ public class MemberChangeMineController {
|
||||
cnd.and("info.userId", "=", SecurityUtil.getUserId());
|
||||
}
|
||||
}
|
||||
// Filter manual input records created by member info input
|
||||
cnd.and(new Static(
|
||||
"(info.changeOrigin <> '" + MemberChangeOrigin.HAND_MOVEMENT.name()
|
||||
+ "' OR info.changeOrigin IS NULL OR info.changeType <> '" + MemberChangeType.NEW.name()
|
||||
+ "' OR info.changeType IS NULL)"
|
||||
));
|
||||
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||
cnd.desc("info.applyDateTime");
|
||||
} else {
|
||||
|
||||
+37
@@ -46,6 +46,8 @@ import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.random.R;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -298,6 +300,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
||||
|
||||
@Override
|
||||
public void compareChangeInfoAndUpdateMember(MemberChangeRecord record) {
|
||||
normalizeArrivalAtSchoolDate(record);
|
||||
List<NutMap> changeList = getChangeInfos(record);
|
||||
|
||||
// 如果有工会关系人员,这个user用来存储数据
|
||||
@@ -503,6 +506,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
||||
|
||||
@Override
|
||||
public void validateChangeAndSetBasicData(MemberChangeRecord record, MemberChangeOrigin origin) {
|
||||
normalizeArrivalAtSchoolDate(record);
|
||||
// 校验有没有发生变更
|
||||
List<NutMap> changeInfos = getChangeInfos(record);
|
||||
if (Lang.isEmpty(changeInfos)) {
|
||||
@@ -521,6 +525,39 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 统一规范变更记录中的到校日期,避免 Date 对象复制后以英文字符串形式参与比较或直接落库。
|
||||
*/
|
||||
private void normalizeArrivalAtSchoolDate(MemberChangeRecord record) {
|
||||
if (record == null || StrUtil.isBlank(record.getArrivalAtSchoolDate())) {
|
||||
return;
|
||||
}
|
||||
String arrivalAtSchoolDate = StrUtil.trim(record.getArrivalAtSchoolDate());
|
||||
try {
|
||||
Date parsedDate = parseArrivalAtSchoolDate(arrivalAtSchoolDate);
|
||||
record.setArrivalAtSchoolDate(DateUtil.format(parsedDate, "yyyy-MM-dd"));
|
||||
} catch (Exception e) {
|
||||
throw new BaseException("到校日期格式不正确,请使用yyyy-MM-dd格式");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容页面手工变更时从视图对象复制出的英文日期字符串。
|
||||
*/
|
||||
private Date parseArrivalAtSchoolDate(String arrivalAtSchoolDate) throws ParseException {
|
||||
if (arrivalAtSchoolDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
|
||||
return DateUtil.parseDate(arrivalAtSchoolDate);
|
||||
}
|
||||
try {
|
||||
return DateUtil.parse(arrivalAtSchoolDate);
|
||||
} catch (Exception ignore) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
|
||||
format.setLenient(false);
|
||||
return format.parse(arrivalAtSchoolDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证申请或变更是否正在进行
|
||||
* @param userId 用户id
|
||||
|
||||
@@ -214,7 +214,7 @@ public class WelfareProject extends BaseModel implements SysHomeConvert {
|
||||
sysHomeActivity.setH5Url("/platform/h5/welfare/userSelect/index?id=" + this.getId());
|
||||
sysHomeActivity.setStartDate(this.getChoiceTimeStart());
|
||||
sysHomeActivity.setEndDate(this.getChoiceTimeEnd());
|
||||
sysHomeActivity.setAllowUserSql("select userId from welfare_list where projectId = '" + this.getId() + "' and userId = @userId");
|
||||
sysHomeActivity.setAllowUserSql("select userId from welfare_list where projectId = (select id from welfare_project where id='" + this.getId() + "' and provideMode!=1) and userId = @userId ");
|
||||
sysHomeActivity.setEnable(true);
|
||||
sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName());
|
||||
return sysHomeActivity;
|
||||
|
||||
Reference in New Issue
Block a user