体育报名外援优化;体育服装管理整改,关联选择活动;比赛名称录入可选工会补全;沿用保存活动bug修复
This commit is contained in:
@@ -89,7 +89,11 @@ public class ActivityApplyController {
|
||||
LEFT JOIN activity_school acts ON acts.id=apply.activityId
|
||||
LEFT JOIN activity_event ev ON ev.id = apply.eventId $condition
|
||||
""");
|
||||
cnd.and("apply.activityUnionId", "=", getUnionId());
|
||||
// 其他工会出战的外援仍由原报名人维护,重新打开项目时必须回显。
|
||||
SqlExpressionGroup ownerOrUnion = new SqlExpressionGroup();
|
||||
ownerOrUnion.or("apply.activityUnionId", "=", getUnionId());
|
||||
ownerOrUnion.or("apply.applyUser", "=", ShiroUtil.getUserId());
|
||||
cnd.and(ownerOrUnion);
|
||||
/* if (!ShiroUtil.hasAnyRoles("A06,sysadmin")) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
if (ShiroUtil.hasAnyRoles("H01")) {
|
||||
@@ -239,12 +243,13 @@ public class ActivityApplyController {
|
||||
WHERE
|
||||
asa.eventId = @eventId
|
||||
AND asa.activityId=@activityId
|
||||
AND asa.activityUnionId = @unionid
|
||||
AND (asa.activityUnionId = @unionid OR asa.applyUser = @applyUser)
|
||||
AND asa.`status` != 3
|
||||
ORDER BY
|
||||
asa.identity DESC,
|
||||
asa.sex
|
||||
""").setParam("eventId", eventId).setParam("unionid", union_id).setParam("activityId", activityId);
|
||||
""").setParam("eventId", eventId).setParam("unionid", union_id)
|
||||
.setParam("applyUser", ShiroUtil.getUserId()).setParam("activityId", activityId);
|
||||
List<ActivitySchoolApply> list = activitySchoolApplyService.listEntity(applySql);
|
||||
//团体人数
|
||||
List<ActivitySchoolApply> awardsModeT = list.stream().filter(v -> v.getAwardsMode().equals("2")).collect(Collectors.toList());
|
||||
@@ -387,20 +392,26 @@ public class ActivityApplyController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建报名专用外援,工号由服务端生成,页面不能指定。
|
||||
* 创建报名专用人员;工号留空时由服务端生成,手动填写时服务端负责查重。
|
||||
* @param username 外援姓名
|
||||
* @param sex 性别,男或女
|
||||
* @param birthday 出生日期,yyyy-MM-dd
|
||||
* @param loginname 可为空;留空时自动生成,手动填写时不能与现有账号重复
|
||||
* @param idcard 18位身份证号,出生日期由服务端从身份证号读取
|
||||
* @param mobile 手机号码
|
||||
* @return Sys_user,id 为报名人员 ID,loginname 为 wy 年份流水工号,其他字段用于页面回显
|
||||
* @param fitForCompetition 身体条件是否适合参赛,只有 true 可创建
|
||||
* @return Sys_user,id 为报名人员 ID,loginname 为最终工号,其他字段用于页面回显
|
||||
*/
|
||||
@At
|
||||
@ViReturn
|
||||
@RequiresPermissions("activity.apply")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object addExternalUser(String username, String sex, String birthday, String mobile) {
|
||||
public Object addExternalUser(String username, String loginname, String sex, String idcard, String mobile,
|
||||
Boolean fitForCompetition) {
|
||||
if (!Boolean.TRUE.equals(fitForCompetition)) {
|
||||
throw new IllegalArgumentException("身体条件不适合参赛,不能添加外援");
|
||||
}
|
||||
Sys_user operator = (Sys_user) ShiroUtil.getPrincipal();
|
||||
return activitySchoolApplyService.createExternalUser(username, sex, birthday, mobile, operator.getUnitid());
|
||||
return activitySchoolApplyService.createExternalUser(username, loginname, sex, idcard, mobile, operator.getUnitid());
|
||||
}
|
||||
|
||||
/** @return String,当前年份的下一个外援工号预览,实际编号以创建接口返回值为准。 */
|
||||
@@ -765,25 +776,18 @@ public class ActivityApplyController {
|
||||
return insert.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询添加外援时可复用的系统人员。
|
||||
* @param queryString 姓名或工号片段;空值不查询
|
||||
* @param userId 不参与返回的用户 ID 列表,可为空
|
||||
* @return List<NutMap>,每项包含 id、username、loginname、sex、idcard、birthday、mobile、unitid、unitname
|
||||
*/
|
||||
@At
|
||||
@ViReturn
|
||||
@RequiresPermissions("activity.apply")
|
||||
@Ok("json:{ignoreNull:true}")
|
||||
public Object getSysUser(String queryString, String[] userId) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("id", "not in", userId);
|
||||
if (StrUtil.isNotBlank(queryString)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.andLike("username", queryString).orLike("loginname", queryString);
|
||||
cnd.and(group);
|
||||
}
|
||||
// cnd.and("unionid", "=", Vi.getUnionId());
|
||||
Sql sql = Sqls.create("select id,loginname,username,sex,mobile,unitid,birthday from `user` $condition LIMIT 30");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.entities());
|
||||
sql.setEntity(sysUserService.getEntity());
|
||||
List<Sys_user> list = sysUserService.execute(sql).getList(Sys_user.class);
|
||||
return list;
|
||||
return activitySchoolApplyService.searchSystemUsers(queryString, userId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ public class ActivityCommonController {
|
||||
app.activityUnionName,
|
||||
app.sex,
|
||||
COALESCE(NULLIF(app.mobile, ''), u.mobile) mobile,
|
||||
u.idCard idcard,
|
||||
COALESCE(NULLIF(app.idCard, ''), u.idCard) idcard,
|
||||
COALESCE(unit.unitcode, u.unitcode) unitcode,
|
||||
CASE WHEN u.member = 1 THEN '是' ELSE '否' END isMember,
|
||||
CASE
|
||||
|
||||
@@ -179,8 +179,8 @@ public class ActivityGradesController {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
us.unitname,
|
||||
apply.*
|
||||
apply.*,
|
||||
COALESCE(NULLIF(apply.unitname, ''), us.unitname) unitname
|
||||
FROM
|
||||
activity_school_apply apply
|
||||
LEFT JOIN `user` us ON apply.userId = us.id $condition
|
||||
|
||||
@@ -138,6 +138,10 @@ public class ActivityInfoManageController {
|
||||
} else if ("four".equals(query)) {
|
||||
cnd.and(new Static("now() > school.endTime"));
|
||||
}
|
||||
// 时间状态快捷查询只展示已提交活动;历史记录的 isSave 可能为空。
|
||||
if ("one".equals(query) || "two".equals(query) || "three".equals(query) || "four".equals(query)) {
|
||||
cnd.and(new Static("(school.isSave IS NULL OR school.isSave <> 1)"));
|
||||
}
|
||||
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")) {
|
||||
if (ActivityRoleUtil.isUnionManager()) {
|
||||
cnd.and("school.belongUnionId", "in", ActivityRoleUtil.getManageUnionStr(ShiroUtil.getUserId()));
|
||||
|
||||
@@ -112,42 +112,21 @@ public class ActivityReadingController {
|
||||
ActivityBasicUnit basicUnit = activitySchoolService.dao().fetch(ActivityBasicUnit.class, Cnd.where("id", "=", unitId));
|
||||
ActivityBasicUnion basicUnion = activitySchoolService.dao().fetch(ActivityBasicUnion.class, Cnd.where("id", "=", basicUnit.getUnionid()));
|
||||
ActivitySchool activitySchool = activitySchoolService.fetch(id);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
app.*,
|
||||
school.`name` activityName,
|
||||
school.applyType applyType,
|
||||
school.belongUnionId belongUnionId,
|
||||
school.belongClubId belongClubId,
|
||||
team.`name` team,
|
||||
COALESCE(NULLIF(app.unitname, ''), unit.`name`) unitname,
|
||||
ev.allName,
|
||||
ev.id evid,
|
||||
ev.projectType
|
||||
FROM
|
||||
activity_school_apply app
|
||||
LEFT JOIN activity_school school ON school.id = app.activityId
|
||||
LEFT JOIN activity_school_team team ON app.teamId = team.id
|
||||
LEFT JOIN activity_event ev ON ev.id = app.eventId
|
||||
LEFT JOIN sys_unit unit ON app.unitId = unit.id
|
||||
$condition
|
||||
""");
|
||||
|
||||
cnd.and("app.activityId", "=", id);
|
||||
// cnd.and("YEAR(app.applyDate)", "=", year);
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> applies = activitySchoolApplyService.listRepresentedApplies(id);
|
||||
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")) {
|
||||
if ((ActivityRoleUtil.isUnionManager() || ShiroUtil.hasRole("gh08")) && activityLevel.equals("40002")) {
|
||||
cnd.and("app.activityUnionId", "=", basicUnit.getUnionid());
|
||||
cnd.and("school.belongUnionId", "=", basicUnit.getUnionid());
|
||||
// 权限仍按活动所属工会限制;报名分组按外援选中的单位工会计算。
|
||||
applies = basicUnit.getUnionid().equals(activitySchool.getBelongUnionId())
|
||||
? applies.stream().filter(v -> basicUnit.getUnionid().equals(v.getString("representedActivityUnionId")))
|
||||
.collect(Collectors.toList()) : List.of();
|
||||
}
|
||||
if (ShiroUtil.hasRole("H02") && activityLevel.equals("40003")) {
|
||||
cnd.and("school.belongClubId", "in", vi.getMangeClubStr());
|
||||
if (activitySchoolService.count(Cnd.where("id", "=", id)
|
||||
.and("belongClubId", "in", vi.getMangeClubStr())) == 0) {
|
||||
applies = List.of();
|
||||
}
|
||||
}
|
||||
}
|
||||
cnd.desc("ev.allName").asc("ev.projectType").asc("team.`name`");
|
||||
List<NutMap> applies = activitySchoolApplyService.listMap(sql);
|
||||
|
||||
List<NutMap> apply = new ArrayList();
|
||||
|
||||
@@ -157,10 +136,6 @@ public class ActivityReadingController {
|
||||
unionCnd.and("id", "=", basicUnit.getUnionid());
|
||||
}
|
||||
}
|
||||
if (activityLevel.equals("40002")) {
|
||||
unionCnd.and("id", "=", activitySchool.getBelongUnionId());
|
||||
}
|
||||
unionCnd.and("isEnable", "=", true);
|
||||
unionCnd.asc("unioncode");
|
||||
|
||||
if (!activityLevel.equals("40003")) {
|
||||
@@ -168,10 +143,20 @@ public class ActivityReadingController {
|
||||
|
||||
for (ActivityBasicUnion union : unions) {
|
||||
String unionId = union.getId();
|
||||
boolean hasApplies = applies.stream()
|
||||
.anyMatch(v -> unionId.equals(v.getString("representedActivityUnionId")));
|
||||
if (!union.isEnable() && !hasApplies) {
|
||||
continue;
|
||||
}
|
||||
// 院级活动保留主办工会,同时展示由所选单位代表其他工会出战的报名。
|
||||
if (activityLevel.equals("40002") && !unionId.equals(activitySchool.getBelongUnionId())
|
||||
&& !hasApplies) {
|
||||
continue;
|
||||
}
|
||||
NutMap map = new NutMap();
|
||||
|
||||
List<NutMap> applyList = applies.stream().filter(v -> {
|
||||
return v.getString("activityUnionId").equals(unionId);
|
||||
return unionId.equals(v.getString("representedActivityUnionId"));
|
||||
}).collect(Collectors.toList());
|
||||
map.setv("id", unionId);
|
||||
map.setv("unionname", union.getUnionname());
|
||||
@@ -183,7 +168,7 @@ public class ActivityReadingController {
|
||||
}
|
||||
} else {
|
||||
NutMap map = new NutMap();
|
||||
Sys_club sysClub = sysClubService.fetch(cnd.where("id", "=", activitySchool.getBelongClubId()));
|
||||
Sys_club sysClub = sysClubService.fetch(Cnd.where("id", "=", activitySchool.getBelongClubId()));
|
||||
map.setv("id", sysClub.getId());
|
||||
map.setv("unionname", sysClub.getName());
|
||||
map.setv("unioncode", sysClub.getCode());
|
||||
@@ -246,12 +231,16 @@ public class ActivityReadingController {
|
||||
FROM
|
||||
`activity_school_apply` apply
|
||||
LEFT JOIN activity_event `event` ON `event`.id = apply.eventId
|
||||
LEFT JOIN sys_unit selectedUnit ON selectedUnit.id = apply.unitId
|
||||
LEFT JOIN activity_basic_unit activityUnit ON activityUnit.id = apply.unitId
|
||||
LEFT JOIN activity_basic_settings groupSetting ON groupSetting.id = `event`.competitionCategory
|
||||
LEFT JOIN activity_basic_settings projectNameSetting ON projectNameSetting.id = `event`.sports
|
||||
LEFT JOIN activity_basic_settings distanceSetting ON distanceSetting.id = `event`.distance
|
||||
WHERE
|
||||
apply.activityId = @id
|
||||
AND apply.unionId = @unionId
|
||||
AND (CASE WHEN apply.unitname = selectedUnit.name AND selectedUnit.unionid IS NOT NULL
|
||||
AND activityUnit.unionid IS NOT NULL THEN selectedUnit.unionid
|
||||
ELSE apply.unionId END) = @unionId
|
||||
AND JSON_CONTAINS(apply.identity,JSON_Array( '1' ))
|
||||
ORDER BY
|
||||
FIELD( apply.sex, '男', '女 ' ),
|
||||
|
||||
@@ -23,10 +23,12 @@ import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -139,20 +141,21 @@ public class ActivityRemindController {
|
||||
WHERE
|
||||
sur.unionid = un.id
|
||||
AND sr.id IN (@h04RoleId, @activityRoleId)
|
||||
) unionleader,
|
||||
( SELECT COUNT( 1 ) FROM activity_school_apply asp WHERE asp.unionId = un.id AND asp.activityId = @activityId ) num
|
||||
) unionleader
|
||||
FROM
|
||||
`sys_union` un
|
||||
ORDER BY
|
||||
un.unioncode
|
||||
""").setParam("h04RoleId", Roles.UNION_MANGER)
|
||||
.setParam("activityRoleId", Roles.SPORTS_ACTIVITY_UNION_ADMIN)
|
||||
.setParam("activityId", activityId);
|
||||
.setParam("activityRoleId", Roles.SPORTS_ACTIVITY_UNION_ADMIN);
|
||||
|
||||
List<Record> unions = sysUnionService.list(sql);
|
||||
Map<String, List<NutMap>> appliesByUnion = activitySchoolApplyService.groupRepresentedAppliesByUnion(activityId);
|
||||
|
||||
unions.forEach(v -> {
|
||||
v.set("users", activitySchoolApplyService.query(Cnd.where("unionId", "=", v.getString("id")).and("activityId", "=", activityId).desc("identity")));
|
||||
List<NutMap> users = appliesByUnion.getOrDefault(v.getString("id"), List.of());
|
||||
v.set("users", users);
|
||||
v.set("num", users.size());
|
||||
});
|
||||
|
||||
return unions;
|
||||
@@ -185,20 +188,20 @@ public class ActivityRemindController {
|
||||
WHERE
|
||||
sur.unionid = un.id
|
||||
AND sr.id IN (@h04RoleId, @activityRoleId)
|
||||
) telephone,
|
||||
( SELECT COUNT( 1 ) FROM activity_school_apply asp WHERE asp.unionId = un.id AND asp.activityId = @activityId ) num
|
||||
) telephone
|
||||
FROM
|
||||
`sys_union` un
|
||||
ORDER BY
|
||||
un.unioncode
|
||||
""").setParam("h04RoleId", Roles.UNION_MANGER)
|
||||
.setParam("activityRoleId", Roles.SPORTS_ACTIVITY_UNION_ADMIN)
|
||||
.setParam("activityId", activityId);
|
||||
.setParam("activityRoleId", Roles.SPORTS_ACTIVITY_UNION_ADMIN);
|
||||
|
||||
List<Record> unions = sysUnionService.list(sql);
|
||||
Map<String, List<NutMap>> appliesByUnion = activitySchoolApplyService.groupRepresentedAppliesByUnion(activityId);
|
||||
|
||||
List<Record> collect = unions.stream().filter(v -> {
|
||||
return v.getInt("num") <= 0 && v.getString("telephone") != null;
|
||||
return appliesByUnion.getOrDefault(v.getString("id"), List.of()).isEmpty()
|
||||
&& v.getString("telephone") != null;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
collect.forEach(v -> {
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.v.nutz.activity.models.ActivityBasicUnion;
|
||||
import io.v.nutz.activity.models.ActivityBasicUnit;
|
||||
import io.v.nutz.activity.models.ActivityResults;
|
||||
import io.v.nutz.activity.models.ActivitySchoolApply;
|
||||
import io.v.nutz.activity.services.ActivitySchoolApplyService;
|
||||
import io.v.nutz.annontation.ViReturn;
|
||||
import io.v.nutz.base.utils.DateUtil;
|
||||
import io.v.nutz.base.utils.Vi;
|
||||
@@ -47,6 +48,9 @@ public class ActivityResultsController {
|
||||
@Inject("ActivitySchoolApply")
|
||||
private ViService<ActivitySchoolApply> activitySchoolApplyViService;
|
||||
|
||||
@Inject
|
||||
private ActivitySchoolApplyService activitySchoolApplyService;
|
||||
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:platform/activity/school/ActivityResults.html")
|
||||
@@ -195,32 +199,14 @@ public class ActivityResultsController {
|
||||
|
||||
|
||||
/**
|
||||
* 查询团体参赛部门工会
|
||||
*
|
||||
* @param activityId
|
||||
* @param eventId
|
||||
* @return
|
||||
* activityId、eventId 为页面当前活动和项目ID,仅保留接口参数兼容原调用。
|
||||
* 返回全部系统工会列表,每项包含 id 和 unionname,供团体成绩录入选择。
|
||||
*/
|
||||
|
||||
@At
|
||||
@ViReturn
|
||||
public Object getUnionList(String activityId, String eventId) {
|
||||
Sql sql = Sqls.create("""
|
||||
|
||||
SELECT
|
||||
un.id,
|
||||
un.unionname
|
||||
FROM
|
||||
activity_school_apply asa
|
||||
LEFT JOIN sys_union un ON un.id = asa.unionId
|
||||
WHERE
|
||||
asa.activityId = @activityId
|
||||
AND asa.eventId = @eventId
|
||||
|
||||
GROUP BY
|
||||
un.unionname
|
||||
""").setParam("activityId", activityId).setParam("eventId", eventId);
|
||||
return activitySchoolApplyViService.list(sql);
|
||||
return activitySchoolApplyService.getResultUnionOptions();
|
||||
}
|
||||
|
||||
@Inject("Sys_user")
|
||||
|
||||
@@ -168,6 +168,9 @@ public class ActivitySchoolApply implements Serializable {
|
||||
private String mobile;
|
||||
|
||||
|
||||
@Column
|
||||
@Comment("报名时使用的身份证号,系统资料为空时保存本次手动补充值")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
@Excel(name = "身份证号", width = 20)
|
||||
private String idCard;
|
||||
|
||||
|
||||
@@ -13,19 +13,49 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ActivitySchoolApplyService extends ViService<ActivitySchoolApply> {
|
||||
|
||||
/**
|
||||
* 获取团体成绩录入可选的全部系统工会,不受活动项目报名情况或启用状态限制。
|
||||
* @return 工会列表,每项包含 id(成绩记录使用的工会ID)和 unionname(下拉显示名称)
|
||||
*/
|
||||
List<NutMap> getResultUnionOptions();
|
||||
|
||||
/** @return 当前年份预计分配的外援工号;实际工号以创建接口返回值为准。 */
|
||||
String previewExternalLoginname();
|
||||
|
||||
/**
|
||||
* 创建仅用于报名的外援用户,按年份生成 wy+年份+流水号的工号。
|
||||
* 按姓名或工号查找可复用的系统人员。
|
||||
* @param queryString 搜索内容,空值返回空列表
|
||||
* @param excludedUserIds 当前页面需要排除的用户 ID
|
||||
* @return 人员列表,每项包含 id、姓名、工号、性别、身份证号、出生日期、电话和系统单位
|
||||
*/
|
||||
List<NutMap> searchSystemUsers(String queryString, String[] excludedUserIds);
|
||||
|
||||
/**
|
||||
* 查询活动报名及其代表出战的工会;历史报名仅在所存单位 ID 与单位名称一致时按该单位归属。
|
||||
* @param activityId 活动 ID
|
||||
* @return 报名列表,representedUnionId 是系统工会 ID,representedActivityUnionId 是活动工会 ID,
|
||||
* 其余字段为报名、活动、项目和队伍的展示字段
|
||||
*/
|
||||
List<NutMap> listRepresentedApplies(String activityId);
|
||||
|
||||
/**
|
||||
* 按代表出战的系统工会归集活动报名,供工会提醒名单和报名人数共用。
|
||||
* @param activityId 活动 ID
|
||||
* @return 以系统工会 ID 为键、该工会报名记录列表为值的 Map
|
||||
*/
|
||||
Map<String, List<NutMap>> groupRepresentedAppliesByUnion(String activityId);
|
||||
|
||||
/**
|
||||
* 创建仅用于报名的用户;工号可采用 wy 年份流水号,也可手动填写。
|
||||
* @param username 外援姓名
|
||||
* @param sex 性别,男或女
|
||||
* @param birthday 出生日期,yyyy-MM-dd
|
||||
* @param loginname 留空时自动生成的工号;手动填写时不能与系统现有工号重复
|
||||
* @param idcard 身份证号,出生日期从中读取
|
||||
* @param mobile 手机号码
|
||||
* @param unitId 报名人所在单位 ID,用于归属当前报名工会
|
||||
* @return 已创建的系统用户,包含用户 ID 和自动生成的工号
|
||||
* @return 已创建的系统用户,包含用户 ID、最终工号和系统资料
|
||||
*/
|
||||
Sys_user createExternalUser(String username, String sex, String birthday, String mobile, String unitId);
|
||||
Sys_user createExternalUser(String username, String loginname, String sex, String idcard, String mobile, String unitId);
|
||||
|
||||
void doApplies(List<ActivitySchoolApply> applies);
|
||||
|
||||
|
||||
+134
-17
@@ -1,6 +1,7 @@
|
||||
package io.v.nutz.activity.services.impl;
|
||||
|
||||
|
||||
import cn.hutool.core.util.IdcardUtil;
|
||||
import io.v.nutz.activity.models.ActivityBasicUnion;
|
||||
import io.v.nutz.activity.models.ActivityBasicUnit;
|
||||
import io.v.nutz.activity.models.ActivitySchoolApply;
|
||||
@@ -8,11 +9,13 @@ import io.v.nutz.activity.services.ActivitySchoolApplyService;
|
||||
import io.v.nutz.base.utils.DateUtil;
|
||||
import io.v.nutz.service.impl.ViServiceImpl;
|
||||
import io.v.nutz.sys.models.Sys_user;
|
||||
import io.v.nutz.sys.models.Sys_unit;
|
||||
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;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
@@ -30,6 +33,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
@@ -41,44 +45,122 @@ public class ActivitySchoolApplyServiceImpl extends ViServiceImpl<ActivitySchool
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> getResultUnionOptions() {
|
||||
// 团体成绩可以选择未报名该项目的工会,因此从系统工会表完整读取。
|
||||
return listMap(Sqls.create("SELECT id, unionname FROM sys_union ORDER BY unioncode"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String previewExternalLoginname() {
|
||||
String prefix = "wy" + Year.now().getValue();
|
||||
Sql next = Sqls.create("SELECT COALESCE(MAX(CAST(SUBSTRING(loginname, 7) AS UNSIGNED)), 0) "
|
||||
+ "FROM sys_user WHERE loginname REGEXP @pattern");
|
||||
next.setParam("pattern", "^" + prefix + "[0-9]+$");
|
||||
next.setCallback(Sqls.callback.integer());
|
||||
dao().execute(next);
|
||||
int number = ((Number) next.getResult()).intValue() + 1;
|
||||
return prefix + String.format("%02d", number);
|
||||
Sql sql = Sqls.create("SELECT loginname FROM sys_user WHERE loginname LIKE @prefix");
|
||||
sql.setParam("prefix", prefix + "%");
|
||||
long number = 0;
|
||||
for (NutMap row : listMap(sql)) {
|
||||
String loginname = row.getString("loginname");
|
||||
if (Strings.isBlank(loginname) || !loginname.matches("^" + prefix + "[0-9]+$")) continue;
|
||||
try {
|
||||
number = Math.max(number, Long.parseLong(loginname.substring(prefix.length())));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// 非法超长工号不参与流水号计算,保留其他有效工号的最大值。
|
||||
}
|
||||
}
|
||||
return prefix + String.format("%02d", number + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> searchSystemUsers(String queryString, String[] excludedUserIds) {
|
||||
String query = Strings.sNull(queryString).trim();
|
||||
if (query.isEmpty()) return List.of();
|
||||
Sql sql = Sqls.create("SELECT u.id,u.loginname,u.username,u.sex,u.idcard,u.birthday,u.mobile,"
|
||||
+ "u.unitid,un.name unitname FROM sys_user u "
|
||||
+ "LEFT JOIN sys_unit un ON un.id=u.unitid $condition LIMIT 30");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("u.id", "not in", excludedUserIds);
|
||||
SqlExpressionGroup names = new SqlExpressionGroup();
|
||||
names.orLike("u.username", query).orLike("u.loginname", query);
|
||||
cnd.and(names);
|
||||
sql.setCondition(cnd);
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> listRepresentedApplies(String activityId) {
|
||||
// 兼容提交时曾写入操作人工会的外援记录;只有保存的单位 ID 和名称一致才采用所选单位的工会。
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT app.*, school.name activityName, school.applyType, school.belongUnionId,
|
||||
school.belongClubId, team.name team,
|
||||
COALESCE(NULLIF(app.unitname, ''), unit.name) unitname,
|
||||
ev.allName, ev.id evid, ev.projectType,
|
||||
CASE WHEN app.unitname = unit.name AND unit.unionid IS NOT NULL
|
||||
AND basicUnit.unionid IS NOT NULL THEN unit.unionid
|
||||
ELSE app.unionId END representedUnionId,
|
||||
CASE WHEN app.unitname = unit.name AND unit.unionid IS NOT NULL
|
||||
AND basicUnit.unionid IS NOT NULL THEN basicUnit.unionid
|
||||
ELSE app.activityUnionId END representedActivityUnionId
|
||||
FROM activity_school_apply app
|
||||
LEFT JOIN activity_school school ON school.id = app.activityId
|
||||
LEFT JOIN activity_school_team team ON team.id = app.teamId
|
||||
LEFT JOIN activity_event ev ON ev.id = app.eventId
|
||||
LEFT JOIN sys_unit unit ON unit.id = app.unitId
|
||||
LEFT JOIN activity_basic_unit basicUnit ON basicUnit.id = app.unitId
|
||||
WHERE app.activityId = @activityId
|
||||
ORDER BY ev.allName DESC, ev.projectType ASC, team.name ASC
|
||||
""").setParam("activityId", activityId);
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<NutMap>> groupRepresentedAppliesByUnion(String activityId) {
|
||||
return listRepresentedApplies(activityId).stream()
|
||||
.filter(row -> Strings.isNotBlank(row.getString("representedUnionId")))
|
||||
.collect(Collectors.groupingBy(row -> row.getString("representedUnionId")));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Sys_user createExternalUser(String username, String sex, String birthday, String mobile, String unitId) {
|
||||
public Sys_user createExternalUser(String username, String loginname, String sex, String idcard, String mobile, String unitId) {
|
||||
String name = Strings.sNull(username).trim();
|
||||
String account = Strings.sNull(loginname).trim();
|
||||
String card = Strings.sNull(idcard).trim().toUpperCase();
|
||||
String phone = Strings.sNull(mobile).trim();
|
||||
if (name.isEmpty() || name.length() > 50 || !("男".equals(sex) || "女".equals(sex))
|
||||
|| !phone.matches("^1[3456789]\\d{9}$")) {
|
||||
throw new IllegalArgumentException("请填写外援姓名、性别及正确的手机号码");
|
||||
}
|
||||
if (account.length() > 50) {
|
||||
throw new IllegalArgumentException("工号不能超过50位");
|
||||
}
|
||||
if (!card.matches("^[0-9]{17}[0-9X]$") || !IdcardUtil.isValidCard(card)) {
|
||||
throw new IllegalArgumentException("请填写正确的18位身份证号");
|
||||
}
|
||||
String birthday = card.substring(6, 10) + "-" + card.substring(10, 12) + "-" + card.substring(12, 14);
|
||||
try {
|
||||
LocalDate.parse(birthday);
|
||||
} catch (DateTimeParseException | NullPointerException e) {
|
||||
throw new IllegalArgumentException("请选择正确的出生年月");
|
||||
throw new IllegalArgumentException("身份证号中的出生日期不正确");
|
||||
}
|
||||
ActivityBasicUnit unit = dao().fetch(ActivityBasicUnit.class, unitId);
|
||||
if (unit == null || Strings.isBlank(unit.getUnionid())) {
|
||||
throw new IllegalArgumentException("当前报名单位未配置活动工会");
|
||||
}
|
||||
// 工号在服务端分配,避免多个浏览器按相同的前端预览号建人。
|
||||
// 自动工号与手填工号都在同一锁内查重,避免并发创建出相同账号。
|
||||
synchronized (EXTERNAL_NUMBER_LOCK) {
|
||||
if (account.isEmpty()) account = previewExternalLoginname();
|
||||
if (dao().count(Sys_user.class, Cnd.where("loginname", "=", account)) > 0) {
|
||||
throw new IllegalArgumentException("工号已存在,请更换工号");
|
||||
}
|
||||
if (dao().count(Sys_user.class, Cnd.where("idcard", "=", card)) > 0) {
|
||||
throw new IllegalArgumentException("身份证号已存在,请搜索并选择系统人员");
|
||||
}
|
||||
Sys_user user = new Sys_user();
|
||||
user.setId(R.UU32());
|
||||
user.setLoginname(previewExternalLoginname());
|
||||
user.setLoginname(account);
|
||||
user.setUsername(name);
|
||||
user.setSex(sex);
|
||||
user.setBirthday(birthday);
|
||||
user.setIdcard(card);
|
||||
user.setMobile(phone);
|
||||
user.setUnitid(unitId);
|
||||
user.setUnionid(unit.getUnionid());
|
||||
@@ -102,17 +184,52 @@ public class ActivitySchoolApplyServiceImpl extends ViServiceImpl<ActivitySchool
|
||||
public void doApplies(String activity, String union_id, String eventId,List<ActivitySchoolApply> applies) {
|
||||
for (ActivitySchoolApply apply : applies) {
|
||||
Sys_user user = Strings.isBlank(apply.getUserId()) ? null : dao().fetch(Sys_user.class, apply.getUserId());
|
||||
if (Strings.isNotBlank(apply.getIdCard())) {
|
||||
String card = apply.getIdCard().trim().toUpperCase();
|
||||
if (!IdcardUtil.isValidCard(card)) {
|
||||
throw new IllegalArgumentException("报名人员身份证号不正确");
|
||||
}
|
||||
apply.setIdCard(card);
|
||||
}
|
||||
if (user != null && user.isDisabled() && Strings.isNotBlank(user.getLoginname())
|
||||
&& user.getLoginname().matches("wy[0-9]{6,}")) {
|
||||
// 外援资料以创建时保存的用户记录为准,不接受浏览器修改工号或单位名称。
|
||||
// 工号和姓名保持系统身份;身份证、出生日期和电话保留本次报名的纠错值。
|
||||
apply.setLoginname(user.getLoginname());
|
||||
apply.setUsername(user.getUsername());
|
||||
apply.setSex(user.getSex());
|
||||
apply.setBirthday(user.getBirthday());
|
||||
apply.setMobile(user.getMobile());
|
||||
apply.setUnitId(user.getUnitid());
|
||||
apply.setUnitname("外援");
|
||||
if (Strings.isNotBlank(user.getSex())) apply.setSex(user.getSex());
|
||||
if (Strings.isBlank(apply.getIdCard())) apply.setIdCard(user.getIdcard());
|
||||
if (Strings.isBlank(apply.getBirthday())) apply.setBirthday(user.getBirthday());
|
||||
if (Strings.isBlank(apply.getMobile())) apply.setMobile(user.getMobile());
|
||||
if (Strings.isBlank(apply.getUnitId())) {
|
||||
apply.setUnitId(user.getUnitid());
|
||||
}
|
||||
if (Strings.isBlank(apply.getUnitname())) {
|
||||
throw new IllegalArgumentException("请填写外援报名单位");
|
||||
}
|
||||
}
|
||||
if (Strings.isNotBlank(apply.getUnitId()) && Strings.isNotBlank(apply.getUnitname())) {
|
||||
Sys_unit selectedUnit = dao().fetch(Sys_unit.class, apply.getUnitId());
|
||||
// 单位来自系统下拉时,所属工会就是本次代表出战的工会;手填单位保留报名人工会。
|
||||
if (selectedUnit != null && apply.getUnitname().trim().equals(selectedUnit.getName())) {
|
||||
ActivityBasicUnit activityUnit = dao().fetch(ActivityBasicUnit.class, apply.getUnitId());
|
||||
if (Strings.isBlank(selectedUnit.getUnionid()) || activityUnit == null
|
||||
|| Strings.isBlank(activityUnit.getUnionid())) {
|
||||
throw new IllegalArgumentException("所选单位未配置活动工会,不能确定代表出战的工会");
|
||||
}
|
||||
ActivityBasicUnion activityUnion = dao().fetch(ActivityBasicUnion.class, activityUnit.getUnionid());
|
||||
if (activityUnion == null) {
|
||||
throw new IllegalArgumentException("所选单位对应的活动工会不存在");
|
||||
}
|
||||
apply.setUnionId(selectedUnit.getUnionid());
|
||||
apply.setActivityUnionId(activityUnion.getId());
|
||||
apply.setActivityUnionName(activityUnion.getUnionname());
|
||||
}
|
||||
}
|
||||
}
|
||||
// 重存时清理本操作人以前代表其他工会报名的记录,避免换单位后留下重复报名。
|
||||
if (!applies.isEmpty()) {
|
||||
clear(Cnd.where("activityId", "=", activity).and("eventId", "=", eventId)
|
||||
.and("applyUser", "=", applies.get(0).getApplyUser()).and("activityUnionId", "!=", union_id));
|
||||
}
|
||||
clear(Cnd.where("activityId", "=", activity).and("activityUnionId", "=", union_id).and("eventId","=",eventId));
|
||||
doApplies(applies);
|
||||
|
||||
@@ -97,7 +97,11 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public String doReuseAdd(String sourceId, ActivitySchool school, ActivitySchoolEvent[] events) {
|
||||
findReuseActivity(sourceId);
|
||||
if (school.getEventsIds() == null || school.getEventsIds().isEmpty()) {
|
||||
if (school.getEventsIds() == null) {
|
||||
school.setEventsIds(new java.util.ArrayList<>());
|
||||
}
|
||||
boolean isDraft = Integer.valueOf(1).equals(school.getIsSave());
|
||||
if (!isDraft && school.getEventsIds().isEmpty()) {
|
||||
throw new IllegalArgumentException("请选择活动项目");
|
||||
}
|
||||
ActivitySchoolEvent[] cleanEvents = Arrays.stream(events == null ? new ActivitySchoolEvent[0] : events)
|
||||
@@ -108,19 +112,22 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
event.setId(null);
|
||||
event.setActivityId(null);
|
||||
}).toArray(ActivitySchoolEvent[]::new);
|
||||
for (String eventId : school.getEventsIds()) {
|
||||
ActivityEvent event = dao().fetch(ActivityEvent.class, Cnd.where("id", "=", eventId).and("whetherEnable", "=", 1));
|
||||
if (event == null) {
|
||||
throw new IllegalArgumentException("所选项目已停用或不存在,请重新选择");
|
||||
}
|
||||
if (Arrays.stream(cleanEvents).noneMatch(config -> eventId.equals(config.getEventId()))) {
|
||||
throw new IllegalArgumentException("项目配置不完整,请进入下一步完善项目信息");
|
||||
// 草稿允许暂不选择或配置项目;正式提交仍需验证项目可用且配置齐全。
|
||||
if (!isDraft) {
|
||||
for (String eventId : school.getEventsIds()) {
|
||||
ActivityEvent event = dao().fetch(ActivityEvent.class, Cnd.where("id", "=", eventId).and("whetherEnable", "=", 1));
|
||||
if (event == null) {
|
||||
throw new IllegalArgumentException("所选项目已停用或不存在,请重新选择");
|
||||
}
|
||||
if (Arrays.stream(cleanEvents).noneMatch(config -> eventId.equals(config.getEventId()))) {
|
||||
throw new IllegalArgumentException("项目配置不完整,请进入下一步完善项目信息");
|
||||
}
|
||||
}
|
||||
}
|
||||
school.setId(null);
|
||||
school.setClose(false);
|
||||
school.setFoundDate(DateUtil.getDate());
|
||||
if (school.getActivityLevel() == 40002) {
|
||||
if (Integer.valueOf(40002).equals(school.getActivityLevel())) {
|
||||
school.setBelongUnionId(ActivityRoleUtil.getCurrentUnionId(dao()));
|
||||
} else {
|
||||
school.setBelongUnionId(null);
|
||||
@@ -166,7 +173,7 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
public String doAdd(ActivitySchool activitySchool, ActivitySchoolEvent[] events) {
|
||||
activitySchool.setClose(false);
|
||||
ActivitySchool school = insert(activitySchool);
|
||||
addTeam(school.getId(), events);
|
||||
addTeam(school.getId(), events == null ? new ActivitySchoolEvent[0] : events);
|
||||
return school.getId();
|
||||
|
||||
}
|
||||
@@ -174,7 +181,12 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void doEdit(ActivitySchool activitySchool, ActivitySchoolEvent[] events, String applyEndTime) {
|
||||
long time = DateUtil.formatDate(applyEndTime);
|
||||
// 未填写报名结束时间的草稿也可再次保存;没有项目时按空配置处理。
|
||||
long time = Strings.isBlank(applyEndTime) ? 0 : DateUtil.formatDate(applyEndTime);
|
||||
if (activitySchool.getEventsIds() == null) {
|
||||
activitySchool.setEventsIds(new java.util.ArrayList<>());
|
||||
}
|
||||
ActivitySchoolEvent[] safeEvents = events == null ? new ActivitySchoolEvent[0] : events;
|
||||
long l = System.currentTimeMillis();
|
||||
|
||||
if (l < time) {
|
||||
@@ -191,7 +203,7 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
return !activitySchool.getEventsIds().contains(v.getEventId());
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
List<ActivitySchoolEvent> collect1 = Lang.array2list(events).stream().filter(v -> {
|
||||
List<ActivitySchoolEvent> collect1 = Lang.array2list(safeEvents).stream().filter(v -> {
|
||||
return !query.stream().map(x -> x.getEventId()).collect(Collectors.toList()).contains(v.getEventId()) && (v.getId() == null || !v.getId().equals("allItems"));
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
@@ -206,7 +218,7 @@ public class ActivitySchoolServiceImpl extends ViServiceImpl<ActivitySchool> imp
|
||||
if (collect1.size() > 0) {
|
||||
addTeam(activitySchool.getId(), collect1.toArray(new ActivitySchoolEvent[collect1.size()]));
|
||||
}
|
||||
for (ActivitySchoolEvent event : events) {
|
||||
for (ActivitySchoolEvent event : safeEvents) {
|
||||
update(event);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.entity.Record;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
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;
|
||||
@@ -67,16 +69,17 @@ public class ClothingRecordController {
|
||||
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object doDelete(String projectId, String year, String userId) {
|
||||
|
||||
if(StrUtil.isBlank(projectId)) {
|
||||
Result.error("项目不能为空!");
|
||||
return Result.error("项目不能为空!");
|
||||
}
|
||||
if(StrUtil.isBlank(year)) {
|
||||
Result.error("年份不能为空!");
|
||||
return Result.error("年份不能为空!");
|
||||
}
|
||||
if(StrUtil.isBlank(userId)) {
|
||||
Result.error("登记人不能为空!");
|
||||
return Result.error("登记人不能为空!");
|
||||
}
|
||||
boolean b = clothingRegisterService.doDelete(projectId, year, userId);
|
||||
return b ? Result.success(): Result.error();
|
||||
@@ -104,6 +107,10 @@ public class ClothingRecordController {
|
||||
return b ? Result.success(): Result.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* year 为活动报名年度,projectId 为活动ID,userId 为登记人ID;旧项目记录按登记年度筛选。
|
||||
* request 和 response 为当前 HTTP 请求及下载响应;返回值为 void,内容写入响应流。
|
||||
*/
|
||||
@At
|
||||
@Ok("void")
|
||||
public void doExport(String year, String projectId, String userId, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
@@ -135,11 +142,13 @@ public class ClothingRecordController {
|
||||
FROM
|
||||
clothing_register c
|
||||
LEFT JOIN `user` u ON u.id = c.buyUserId
|
||||
LEFT JOIN activity_school s ON s.id = c.projectId
|
||||
$condition
|
||||
""");
|
||||
cnd.and("year(ctime)", "=", year);
|
||||
cnd.and("projectId", "=", projectId);
|
||||
cnd.and("userId", "=", userId);
|
||||
// 导出与台账采用同一业务年度,旧项目记录回退到登记年度。
|
||||
cnd.and("COALESCE(YEAR(s.applyStartTime), YEAR(c.ctime))", "=", year);
|
||||
cnd.and("c.projectId", "=", projectId);
|
||||
cnd.and("c.userId", "=", userId);
|
||||
sql.setCondition(cnd);
|
||||
List<Record> buyUserList = clothingRegisterService.list(sql);
|
||||
for (int i = 0; i < buyUserList.size(); i++) {
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.entity.Record;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
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;
|
||||
@@ -41,30 +43,43 @@ public class ClothingRegisterController {
|
||||
@RequiresPermissions("clothing.register")
|
||||
public void index() {}
|
||||
|
||||
/** pageForm 为分页和姓名工号条件;projectId 为活动ID;isBuy 为购买状态;sex、unionId 为可选筛选,返回人员分页数据。 */
|
||||
@At
|
||||
@ViReturn
|
||||
public Object pageData(PageForm pageForm, Integer year, String projectId, Boolean isBuy, String sex, String unionId) {
|
||||
public Object pageData(PageForm pageForm, String projectId, Boolean isBuy, String sex, String unionId) {
|
||||
|
||||
return clothingRegisterService.getRegisterUser(pageForm, year, projectId, isBuy, sex, unionId);
|
||||
return clothingRegisterService.getRegisterUser(pageForm, projectId, isBuy, sex, unionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* ids 为所选人员ID;projectId 为活动ID,购买限制以该活动的报名年度和已选项目为准;
|
||||
* isBuy 为购买状态,true 时仅移除当前活动记录,false 时登记;
|
||||
* 成功返回 null 由 ViReturn 包装,业务校验失败返回含错误说明的 Result。
|
||||
*/
|
||||
@At
|
||||
@ViReturn
|
||||
public Object doHandler(String[] ids, String projectId, Integer year, Boolean isBuy) {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object doHandler(String[] ids, String projectId, Boolean isBuy) {
|
||||
|
||||
if(!isBuy) {
|
||||
clothingRegisterService.add(ids, projectId);
|
||||
} else {
|
||||
clothingRegisterService.removeBuyUser(ids, projectId, year);
|
||||
try {
|
||||
if(!Boolean.TRUE.equals(isBuy)) {
|
||||
clothingRegisterService.add(ids, projectId);
|
||||
} else {
|
||||
clothingRegisterService.removeBuyUser(ids, projectId);
|
||||
}
|
||||
} catch (IllegalArgumentException exception) {
|
||||
// 重复购衣等业务校验错误直接返回给页面,供提交按钮显示明确原因。
|
||||
return Result.error(exception.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** year 为空时返回全部已提交活动,否则按报名开始时间所属年度筛选;data 数组的每项包含活动 id 和 name。 */
|
||||
@At
|
||||
@ViReturn
|
||||
public Object getBuyClothesProject() {
|
||||
public Object getBuyClothesProject(Integer year) {
|
||||
|
||||
return clothingRegisterService.getBuyClothesProject();
|
||||
return clothingRegisterService.getBuyClothesProject(year);
|
||||
}
|
||||
|
||||
@At
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.v.nutz.clothing.services;
|
||||
|
||||
import cn.wizzer.framework.page.Pagination;
|
||||
import io.v.nutz.activity.models.ActivityBasicSettings;
|
||||
import io.v.nutz.clothing.models.ClothingRegister;
|
||||
import io.v.nutz.modules.models.PageForm;
|
||||
import io.v.nutz.service.ViService;
|
||||
@@ -20,29 +19,31 @@ public interface ClothingRegisterService extends ViService<ClothingRegister> {
|
||||
/**
|
||||
* 列表查询
|
||||
*
|
||||
* @param pageForm: 表单
|
||||
* @param projectId: 项目id
|
||||
* @param year: 年份
|
||||
* @return io.v.nutz.base.page.Pagination
|
||||
* @param pageForm: 分页及查询表单
|
||||
* @param projectId: 活动ID,可为空
|
||||
* @param year: 活动报名年度;旧项目记录按登记年度筛选
|
||||
* @param unionId: 工会ID,可为空
|
||||
* @return Pagination,list 为按活动、登记人和年度分组的台账,totalCount 为分组总数
|
||||
* @author JyuHsin
|
||||
* @date 2022/12/5
|
||||
*/
|
||||
Pagination pageData(PageForm pageForm, String projectId, String year, String unionId);
|
||||
|
||||
/**
|
||||
* 获取所有买服装的项目
|
||||
* @author JyuHsin
|
||||
* @date 2022/12/5
|
||||
* @return java.util.List<io.v.nutz.activity.models.ActivityBasicSettings>
|
||||
* 获取已提交的校级活动,供服装登记、记录和台账选择项目。
|
||||
* year 为空时返回全部年度,否则按活动报名开始时间所属年度筛选。
|
||||
* 返回的每项包含活动 id(作为 projectId 保存和筛选)及 name(下拉显示名称)。
|
||||
*/
|
||||
List<ActivityBasicSettings> getBuyClothesProject();
|
||||
List<NutMap> getBuyClothesProject(Integer year);
|
||||
|
||||
/**
|
||||
* 获取项目人员名单
|
||||
* @author JyuHsin
|
||||
* @date 2022/12/5
|
||||
* @param projectId: 项目id
|
||||
* @return java.util.List<org.nutz.lang.util.NutMap>
|
||||
* @param projectId: 活动ID
|
||||
* @param userId: 登记人ID
|
||||
* @param year: 活动报名年度,可为空;旧项目记录按登记年度筛选
|
||||
* @return 人员列表,每项包含购买人资料及登记记录
|
||||
*/
|
||||
List<NutMap> findBuyClothesUser(String projectId, String userId, String year);
|
||||
|
||||
@@ -50,28 +51,25 @@ public interface ClothingRegisterService extends ViService<ClothingRegister> {
|
||||
* 删除
|
||||
* @author JyuHsin
|
||||
* @date 2022/12/5
|
||||
* @param projectId: 项目id
|
||||
* @param year: 年份
|
||||
* @param userId: 登记人
|
||||
* @return void
|
||||
* @param projectId: 活动ID
|
||||
* @param year: 活动报名年度;旧项目记录按登记年度删除
|
||||
* @param userId: 登记人ID
|
||||
* @return 是否完成指定活动、年度和登记人的删除
|
||||
*/
|
||||
boolean doDelete(String projectId, String year, String userId);
|
||||
|
||||
/**
|
||||
* 服装登记菜单查询用户
|
||||
* @author JyuHsin
|
||||
* @date 2022/12/5
|
||||
* @param pageForm:
|
||||
* @param year:
|
||||
* @param projectId:
|
||||
* @param isBuy:
|
||||
* @return cn.wizzer.framework.page.Pagination
|
||||
* 查询服装登记人员。pageForm 包含页码、页大小和姓名或工号查询条件;projectId 为当前活动ID;
|
||||
* isBuy 为购买状态,true 返回与活动年度相差不超过一年且同类项目已购买的人员,false 返回未购买人员;
|
||||
* sex 为可选性别,unionId 为可选工会ID。返回 Pagination,list 为人员及可移除状态,totalCount 为总人数。
|
||||
*/
|
||||
Pagination getRegisterUser(PageForm pageForm, Integer year, String projectId, Boolean isBuy, String sex, String unionId);
|
||||
Pagination getRegisterUser(PageForm pageForm, String projectId, Boolean isBuy, String sex, String unionId);
|
||||
|
||||
/** ids 为本次登记的人员ID,projectId 为活动ID;两年内同类项目已有购买记录时拒绝提交。 */
|
||||
Object add(String[] ids, String projectId);
|
||||
|
||||
boolean removeBuyUser(String[] ids, String projectId, Integer year);
|
||||
/** ids 为人员ID,projectId 为当前活动ID;仅移除当前活动的登记记录,不删除其他同类活动的历史记录。 */
|
||||
boolean removeBuyUser(String[] ids, String projectId);
|
||||
|
||||
boolean deleteBuyUser(String id);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.v.nutz.clothing.services.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.wizzer.framework.page.Pagination;
|
||||
import io.v.nutz.activity.models.ActivityBasicSettings;
|
||||
import io.v.nutz.activity.models.ActivitySchool;
|
||||
import io.v.nutz.base.utils.DateUtil;
|
||||
import io.v.nutz.base.utils.Vi;
|
||||
import io.v.nutz.clothing.models.ClothingRegister;
|
||||
@@ -20,13 +20,18 @@ 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.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Strings;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.trans.Trans;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author JyuHsin
|
||||
@@ -48,14 +53,15 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
c.*,
|
||||
YEAR ( c.ctime ) AS `year`,
|
||||
COALESCE(YEAR(s.applyStartTime), YEAR(c.ctime)) AS `year`,
|
||||
u.username,
|
||||
u.unionname,
|
||||
a.name AS projectName,
|
||||
COALESCE(s.name, a.name) AS projectName,
|
||||
count(c.buyUserId) AS buyCount
|
||||
FROM
|
||||
clothing_register c
|
||||
LEFT JOIN `user` u ON u.id = c.userId
|
||||
LEFT JOIN activity_school s ON s.id = c.projectId
|
||||
LEFT JOIN activity_basic_settings a ON a.CODE = c.projectId
|
||||
$condition
|
||||
""");
|
||||
@@ -65,8 +71,9 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
}
|
||||
cnd.andExcludeEmpty("u.unionId", "=", unionId);
|
||||
cnd.andExcludeEmpty("c.projectId", "=", projectId);
|
||||
cnd.andExcludeEmpty("year(c.ctime)", "=", year);
|
||||
cnd.groupBy("c.userId");
|
||||
// 活动记录按报名年度归档;无法关联活动的旧记录仍按实际登记年度展示。
|
||||
cnd.andExcludeEmpty("COALESCE(YEAR(s.applyStartTime), YEAR(c.ctime))", "=", year);
|
||||
cnd.groupBy("c.projectId", "c.userId", "COALESCE(YEAR(s.applyStartTime), YEAR(c.ctime))");
|
||||
cnd.desc("year").asc("projectId");
|
||||
sql.setCondition(cnd);
|
||||
|
||||
@@ -74,8 +81,17 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityBasicSettings> getBuyClothesProject() {
|
||||
return dao().query(ActivityBasicSettings.class, Cnd.where("clothing", "is not", null));
|
||||
public List<NutMap> getBuyClothesProject(Integer year) {
|
||||
// isSave=1 是草稿;历史已提交活动可能为 NULL,需与活动管理页的判定保持一致。
|
||||
CndPlus cnd = CndPlus.create();
|
||||
cnd.and(new Static("(isSave IS NULL OR isSave <> 1)"));
|
||||
cnd.andExcludeEmpty("YEAR(applyStartTime)", "=", year);
|
||||
cnd.desc("startTime").desc("foundDate");
|
||||
return listMap(Sqls.create("""
|
||||
SELECT id, name
|
||||
FROM activity_school
|
||||
$condition
|
||||
""").setCondition(cnd));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,26 +110,38 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
FROM
|
||||
clothing_register c
|
||||
LEFT JOIN `user` u ON u.id = c.buyUserId
|
||||
LEFT JOIN activity_school s ON s.id = c.projectId
|
||||
$condition
|
||||
""");
|
||||
cnd.andExcludeEmpty("c.projectId", "=", projectId);
|
||||
cnd.andExcludeEmpty("c.userId", "=", userId);
|
||||
cnd.andExcludeEmpty("year(c.ctime)", "=", year);
|
||||
cnd.andExcludeEmpty("COALESCE(YEAR(s.applyStartTime), YEAR(c.ctime))", "=", year);
|
||||
|
||||
sql.setCondition(cnd);
|
||||
return listMap(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean doDelete(String projectId, String year, String userId) {
|
||||
|
||||
int clearCount = dao().clear(ClothingRegister.class, Cnd.where("projectId", "=", projectId)
|
||||
.and("year(ctime)", "=", year).and("userId", "=", userId));
|
||||
Cnd cnd = Cnd.where("projectId", "=", projectId).and("userId", "=", userId);
|
||||
ActivitySchool school = dao().fetch(ActivitySchool.class, projectId);
|
||||
String applyStartTime = school == null ? null : school.getApplyStartTime();
|
||||
// 新活动以报名年度定位整组登记;旧项目没有活动年度时沿用登记时间筛选。
|
||||
if (Strings.isNotBlank(applyStartTime) && applyStartTime.length() >= 4) {
|
||||
if (!year.equals(applyStartTime.substring(0, 4))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
cnd.and("year(ctime)", "=", year);
|
||||
}
|
||||
int clearCount = dao().clear(ClothingRegister.class, cnd);
|
||||
return clearCount >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination getRegisterUser(PageForm pageForm, Integer year, String projectId, Boolean isBuy, String sex, String unionId) {
|
||||
public Pagination getRegisterUser(PageForm pageForm, String projectId, Boolean isBuy, String sex, String unionId) {
|
||||
|
||||
CndPlus cnd = CndPlus.create();
|
||||
Sql sql = Sqls.create("""
|
||||
@@ -129,20 +157,105 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
if (Strings.isNotBlank(pageForm.getSearchName()) && Strings.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
cnd.where().andLike(pageForm.getSearchName(), pageForm.getSearchKeyword());
|
||||
}
|
||||
if(year != null) {
|
||||
int lastYear = year - 1;
|
||||
cnd.and(new Static("id %s (select buyUserId from clothing_register where projectId = '%s' and (year(ctime) = '%s' or year(ctime) = '%s'))"
|
||||
.formatted(isBuy ? "in" : "not in", projectId, year, lastYear)));
|
||||
if (Strings.isBlank(projectId)) {
|
||||
// 没有活动时不能把全部会员误显示为该活动的“未购买”人员。
|
||||
cnd.and(new Static("1 = 0"));
|
||||
} else {
|
||||
// 活动名称和ID每年可能变化,购买状态按活动选中项目的运动项目及活动年度判断。
|
||||
Set<String> purchasedIds = findPurchasedUserIds(projectId);
|
||||
if (purchasedIds.isEmpty()) {
|
||||
if (Boolean.TRUE.equals(isBuy)) cnd.and(new Static("1 = 0"));
|
||||
} else {
|
||||
cnd.and("u.id", Boolean.TRUE.equals(isBuy) ? "in" : "not in", purchasedIds.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
Pagination result = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
if (Boolean.TRUE.equals(isBuy) && Strings.isNotBlank(projectId)) {
|
||||
// 历史活动中已购买的人员可查看,但只能移除当前活动自身的登记记录。
|
||||
Set<String> currentIds = listMap(Sqls.create("SELECT DISTINCT buyUserId AS buy_user_id FROM clothing_register WHERE projectId = @projectId")
|
||||
.setParam("projectId", projectId)).stream()
|
||||
.map(row -> row.getString("buy_user_id")).collect(Collectors.toSet());
|
||||
List<NutMap> users = result.getList();
|
||||
users.forEach(user -> user.setv("canRemove", currentIds.contains(user.getString("id"))));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* projectId 为当前活动ID;返回该活动选择的运动项目标识。项目未配置 sports 时以项目ID兜底,
|
||||
* 避免把不同项目误判为同类;已选项目为空时拒绝登记,防止绕过重复购买限制。
|
||||
*/
|
||||
private List<String> getSelectedSportKeys(String projectId) {
|
||||
List<NutMap> events = listMap(Sqls.create("""
|
||||
SELECT DISTINCT COALESCE(NULLIF(ae.sports, ''), ae.id) AS sport_key
|
||||
FROM activity_school_event ase
|
||||
JOIN activity_event ae ON ae.id = ase.eventId
|
||||
WHERE ase.activityId = @projectId
|
||||
""").setParam("projectId", projectId));
|
||||
List<String> keys = events.stream().map(event -> event.getString("sport_key"))
|
||||
.filter(Strings::isNotBlank).distinct().collect(Collectors.toList());
|
||||
if (keys.isEmpty()) throw new IllegalArgumentException("当前活动未配置可识别的活动项目,无法登记服装");
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* projectId 为当前活动ID;返回与活动年度相差不超过一年、购买过任一相同运动项目服装的人员ID。
|
||||
* 年度取活动报名开始时间,避免跨年补登记时因 clothing_register.ctime 不同而漏判。
|
||||
*/
|
||||
private Set<String> findPurchasedUserIds(String projectId) {
|
||||
ActivitySchool school = dao().fetch(ActivitySchool.class, projectId);
|
||||
if (school == null || Integer.valueOf(1).equals(school.getIsSave())) {
|
||||
throw new IllegalArgumentException("活动不存在或尚未提交");
|
||||
}
|
||||
String applyStartTime = school.getApplyStartTime();
|
||||
if (Strings.isBlank(applyStartTime) || applyStartTime.length() < 4) {
|
||||
throw new IllegalArgumentException("当前活动未设置报名开始时间,无法判断两年购买范围");
|
||||
}
|
||||
int activityYear;
|
||||
try {
|
||||
activityYear = Integer.parseInt(applyStartTime.substring(0, 4));
|
||||
} catch (NumberFormatException exception) {
|
||||
throw new IllegalArgumentException("当前活动报名开始时间格式不正确", exception);
|
||||
}
|
||||
List<String> sportKeys = getSelectedSportKeys(projectId);
|
||||
CndPlus cnd = CndPlus.create();
|
||||
// 补录历史活动时也要检查后一年的购买记录,避免登记顺序改变查重结果。
|
||||
cnd.and("YEAR(s.applyStartTime)", "in", new Integer[]{activityYear - 1, activityYear, activityYear + 1});
|
||||
cnd.and("COALESCE(NULLIF(ae.sports, ''), ae.id)", "in", sportKeys.toArray(new String[0]));
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT c.buyUserId AS buy_user_id
|
||||
FROM clothing_register c
|
||||
JOIN activity_school s ON s.id = c.projectId
|
||||
JOIN activity_school_event ase ON ase.activityId = s.id
|
||||
JOIN activity_event ae ON ae.id = ase.eventId
|
||||
$condition
|
||||
""").setCondition(cnd);
|
||||
return listMap(sql).stream().map(row -> row.getString("buy_user_id"))
|
||||
.filter(Strings::isNotBlank).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object add(String[] ids, String projectId) {
|
||||
|
||||
if (ids == null || ids.length == 0 || Strings.isBlank(projectId)) {
|
||||
throw new IllegalArgumentException("请选择活动和登记人员");
|
||||
}
|
||||
List<String> userIds = Arrays.stream(ids).filter(Strings::isNotBlank).distinct().sorted().collect(Collectors.toList());
|
||||
if (userIds.isEmpty()) throw new IllegalArgumentException("请选择登记人员");
|
||||
// 锁定人员行后再查重,防止并发提交同时通过两年内同项目的校验。
|
||||
for (String id : userIds) {
|
||||
if (listMap(Sqls.create("SELECT id FROM `user` WHERE id = @id FOR UPDATE").setParam("id", id)).isEmpty()) {
|
||||
throw new IllegalArgumentException("所选人员不存在,请刷新名单");
|
||||
}
|
||||
}
|
||||
Set<String> purchasedIds = findPurchasedUserIds(projectId);
|
||||
if (userIds.stream().anyMatch(purchasedIds::contains)) {
|
||||
throw new IllegalArgumentException("所选人员在近两年内已购买同类项目服装,不能重复提交,请刷新名单");
|
||||
}
|
||||
List<ClothingRegister> clothingRegisterList = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
for (String id : userIds) {
|
||||
ClothingRegister clothingRegister = new ClothingRegister();
|
||||
clothingRegister.setProjectId(projectId);
|
||||
clothingRegister.setUserId(ShiroUtil.getPrincipalProperty("id").toString());
|
||||
@@ -154,12 +267,17 @@ public class ClothingRegisterServiceImpl extends ViServiceImpl<ClothingRegister>
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBuyUser(String[] ids, String projectId, Integer year) {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public boolean removeBuyUser(String[] ids, String projectId) {
|
||||
|
||||
if (ids == null || ids.length == 0 || Strings.isBlank(projectId)) {
|
||||
throw new IllegalArgumentException("请选择当前活动中需要移除的人员");
|
||||
}
|
||||
Trans.exec(() -> {
|
||||
for (String id : ids) {
|
||||
dao().clear(ClothingRegister.class, Cnd.where("projectId", "=", projectId)
|
||||
.and("year(ctime)", "=", year).and("buyUserId", "=", id));
|
||||
Cnd cnd = Cnd.where("projectId", "=", projectId).and("buyUserId", "=", id);
|
||||
// 同类历史活动的购买记录仍保留,仅删除当前活动中选中的登记。
|
||||
dao().clear(ClothingRegister.class, cnd);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -14,4 +14,9 @@ public interface SysConfigService extends BaseService<Sys_config> {
|
||||
* @return
|
||||
*/
|
||||
List<Sys_config> getAllList();
|
||||
|
||||
/**
|
||||
* 确保系统配置中存在学校待办开关;首次创建时默认关闭。
|
||||
*/
|
||||
void ensureTodoTaskConfig();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package io.v.nutz.sys.services.impl;
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.sys.models.Sys_config;
|
||||
import io.v.nutz.sys.services.SysConfigService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.List;
|
||||
@@ -21,4 +23,16 @@ public class SysConfigServiceImpl extends BaseServiceImpl<Sys_config> implements
|
||||
public List<Sys_config> getAllList() {
|
||||
return this.query(Cnd.where("delFlag", "=", false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void ensureTodoTaskConfig() {
|
||||
if (fetch("TodoTaskEnabled") == null) {
|
||||
Sys_config config = new Sys_config();
|
||||
config.setConfigKey("TodoTaskEnabled");
|
||||
config.setConfigValue("false");
|
||||
config.setNote("启用学校统一待办推送、更新和删除;关闭时不调用学校待办网关");
|
||||
insert(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import io.v.nutz.sys.models.Sys_config;
|
||||
import io.v.nutz.sys.services.SysConfigService;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Dao;
|
||||
@@ -26,6 +28,17 @@ import java.util.Map;
|
||||
@Slf4j
|
||||
public class TodoTaskInterfaceImpl implements TodoTaskInterface {
|
||||
|
||||
/**
|
||||
* 只有系统配置明确开启时,才调用学校统一待办网关。
|
||||
*/
|
||||
private boolean isTodoTaskEnabled() {
|
||||
Sys_config config = sysConfigService.fetch("TodoTaskEnabled");
|
||||
return config != null && "true".equals(config.getConfigValue());
|
||||
}
|
||||
|
||||
@Inject
|
||||
private SysConfigService sysConfigService;
|
||||
|
||||
@Inject
|
||||
private RedisService redisService;
|
||||
|
||||
@@ -52,6 +65,9 @@ public class TodoTaskInterfaceImpl implements TodoTaskInterface {
|
||||
|
||||
@Override
|
||||
public void pushTask(TodoTask todoTask) {
|
||||
if (!isTodoTaskEnabled()) {
|
||||
return;
|
||||
}
|
||||
log.info("【推送待办入参】:" + Json.toJson(todoTask));
|
||||
String accessToken = getAccessToken();
|
||||
HttpRequest httpRequest = HttpUtil.createPost(TodoTaskConstants.PUSH_TASK_URL);
|
||||
@@ -69,6 +85,9 @@ public class TodoTaskInterfaceImpl implements TodoTaskInterface {
|
||||
|
||||
@Override
|
||||
public void updateTask(TodoTask todoTask) {
|
||||
if (!isTodoTaskEnabled()) {
|
||||
return;
|
||||
}
|
||||
log.info("【更新待办入参】:" + Json.toJson(todoTask));
|
||||
String accessToken = getAccessToken();
|
||||
HttpRequest httpRequest = HttpUtil.createPost(TodoTaskConstants.UPDATE_TASK_URL);
|
||||
@@ -86,6 +105,9 @@ public class TodoTaskInterfaceImpl implements TodoTaskInterface {
|
||||
|
||||
@Override
|
||||
public void deleteTask(TodoTask todoTask) {
|
||||
if (!isTodoTaskEnabled()) {
|
||||
return;
|
||||
}
|
||||
log.info("【删除待办入参】:" + Json.toJson(todoTask));
|
||||
String accessToken = getAccessToken();
|
||||
HttpRequest httpRequest = HttpUtil.createPost(TodoTaskConstants.DELETE_TASK_URL);
|
||||
|
||||
@@ -34,7 +34,7 @@ public class SysConfController {
|
||||
@Ok("beetl:/platform/sys/conf/index.html")
|
||||
@RequiresPermissions("sys.manager.conf")
|
||||
public void index() {
|
||||
|
||||
sysConfigService.ensureTodoTaskConfig();
|
||||
}
|
||||
|
||||
@At
|
||||
|
||||
@@ -27,6 +27,8 @@ 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.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
@@ -98,7 +100,12 @@ public class CondolenceApplyCon {
|
||||
|
||||
@At
|
||||
@ViReturn
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object doAdd(@Param("data") Condolence condolence, String sign) {
|
||||
if (condolenceService.hasHospitalCondolenceInCurrentYear(condolence)) {
|
||||
return Result.error().addMsg("住院慰问每年只能申请一次,请于下一年度再申请");
|
||||
}
|
||||
|
||||
List<Sys_file> files = condolence.getFiles();
|
||||
if (Lang.isEmpty(files)) {
|
||||
condolence.setFiles_num("0");
|
||||
|
||||
@@ -19,6 +19,14 @@ public interface CondolenceService extends ViService<Condolence> {
|
||||
*/
|
||||
NutMap findOne(String id);
|
||||
|
||||
/**
|
||||
* 判断被慰问人在当前自然年是否已有住院慰问申请。
|
||||
*
|
||||
* @param application 本次申请,包含慰问类型、被慰问人和编辑时的申请 ID
|
||||
* @return 已有其他同年住院慰问申请时返回 true,否则返回 false
|
||||
*/
|
||||
boolean hasHospitalCondolenceInCurrentYear(Condolence application);
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
|
||||
@@ -2,9 +2,11 @@ package io.v.nutz.zgfw.service.impl;
|
||||
|
||||
|
||||
import cn.wizzer.framework.base.service.BaseService;
|
||||
import io.v.nutz.base.utils.DateUtil;
|
||||
import io.v.nutz.modules.services.ReviewService;
|
||||
import io.v.nutz.service.impl.ViServiceImpl;
|
||||
import io.v.nutz.zgfw.model.condolence.Condolence;
|
||||
import io.v.nutz.zgfw.model.condolence.CondolenceType;
|
||||
import io.v.nutz.zgfw.service.CondolenceService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
@@ -28,9 +30,30 @@ public class CondolenceServiceImpl extends ViServiceImpl<Condolence> implements
|
||||
private ReviewService reviewService;
|
||||
@Inject
|
||||
private BaseService baseService;
|
||||
private final Dao condolenceDao;
|
||||
|
||||
public CondolenceServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
this.condolenceDao = dao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasHospitalCondolenceInCurrentYear(Condolence application) {
|
||||
CondolenceType type = condolenceDao.fetch(CondolenceType.class, application.getType());
|
||||
if (type == null || !"C".equals(type.getCode())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 按被慰问人和申请年份限制次数;编辑时排除当前申请,已退回的其他申请仍计入次数。
|
||||
String year = String.valueOf(DateUtil.getYear());
|
||||
Cnd cnd = Cnd.where("be_user", "=", application.getBe_user())
|
||||
.and("type", "=", application.getType())
|
||||
.and("apply_time", ">=", year + "-01-01")
|
||||
.and("apply_time", "<", (DateUtil.getYear() + 1) + "-01-01");
|
||||
if (Strings.isNotBlank(application.getId())) {
|
||||
cnd.and("id", "!=", application.getId());
|
||||
}
|
||||
return count(cnd) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user