整改收货地址可以导出全部的福利地址

This commit is contained in:
2026-11-05 11:50:13 +08:00
parent d8f6298dd8
commit 7f578e1f9e
5 changed files with 49 additions and 15 deletions
@@ -134,7 +134,7 @@ public class FamilyActivity extends BaseModel implements Serializable, SysHomeCo
private Integer familyCountScope;
@Column
@Comment("是否禁止同一教职工报名本活动内时间重叠的子活动,含候补报名")
@Comment("是否禁止同一教职工下同一家属报名本活动内时间重叠的子活动,含候补报名")
@ColDefine(type = ColType.BOOLEAN)
@Default("0")
private Boolean timeConflictCheck;
@@ -1224,14 +1224,38 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
}
/**
* 在同一活动、同一教职工内校验时间重叠,含候补,修改和调班排除当前报名记录。
* 参数为本次报名、所属课程、活动配置和实际报名用户ID;无返回值,冲突时提示已有课程和时间。
* 提取一条报名中的全部家属唯一标识,用于判断两次报名是否包含同一个孩子。
* user 为当前或历史报名,activity.onlyKey 为管理员配置的统一字段编码;返回规范化后的标识集合。
* 缺少字段或值为空时提示核对数据,不能将无法识别的历史报名当作不同孩子而跳过冲突校验。
*/
private Set<String> getTimeConflictFamilyIdentities(FamilyUser user, FamilyActivity activity) {
if (StrUtil.isBlank(activity.getOnlyKey())) {
throw new BaseException("活动未配置家属唯一标识,请联系管理员");
}
if (Lang.isEmpty(user.getMobileColumnsValue())) {
throw new BaseException("报名记录缺少家属信息,请联系管理员核对历史数据");
}
Set<String> identities = new HashSet<>();
for (List<NutMap> family : user.getMobileColumnsValue()) {
String identity = normalizeFamilyIdentityValue(getFamilyIdentity(family, activity));
if (StrUtil.isBlank(identity)) {
throw new BaseException("报名记录缺少家属唯一标识,请联系管理员核对字段编码和历史数据");
}
identities.add(identity);
}
return identities;
}
/**
* 在同一活动、同一教职工下仅校验同一家属的时间重叠,含候补,修改和调班排除当前报名记录。
* 参数为本次报名、所属课程、活动配置和实际报名用户ID;无返回值,同一家属冲突时提示已有课程和时间。
* 使用半开区间:一场结束时刻等于另一场开始时刻允许报名;不同日期自然不会冲突。
*/
private void validateTimeConflict(FamilyUser user, FamilyCourse course, FamilyActivity activity, String userId) {
if (!Boolean.TRUE.equals(activity.getTimeConflictCheck())) {
return;
}
Set<String> currentIdentities = getTimeConflictFamilyIdentities(user, activity);
List<FamilyActivityCourse> currentTimes = getSignUpCourseTimes(course, user.getActivityCourseId());
Cnd cnd = Cnd.where(FamilyUser::getActivityId, "=", activity.getId())
.and(FamilyUser::getUserId, "=", userId).and(FamilyUser::getState, "in", List.of(1, 2, 3));
@@ -1239,6 +1263,11 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
cnd.and(FamilyUser::getId, "!=", user.getId());
}
for (FamilyUser existing : dao().query(FamilyUser.class, cnd)) {
Set<String> existingIdentities = getTimeConflictFamilyIdentities(existing, activity);
// 两次报名没有相同孩子时允许同时段报名;多人报名只要有一个相同孩子,仍需检查时间。
if (Collections.disjoint(currentIdentities, existingIdentities)) {
continue;
}
FamilyCourse oldCourse = dao().fetch(FamilyCourse.class, existing.getCourseId());
if (oldCourse == null || !Objects.equals(oldCourse.getActivityId(), activity.getId())) {
throw new BaseException("已有报名的子活动不存在或已变更,请联系管理员核对");
@@ -1247,7 +1276,7 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
for (FamilyActivityCourse currentTime : currentTimes) {
if (currentTime.getCourseStartTime().before(oldTime.getCourseEndTime())
&& oldTime.getCourseStartTime().before(currentTime.getCourseEndTime())) {
throw new BaseException("您已报名【" + oldCourse.getCourseName() + "】("
throw new BaseException("同一家属已报名【" + oldCourse.getCourseName() + "】("
+ DateUtil.format(oldTime.getCourseStartTime(), "yyyy-MM-dd HH:mm") + "至"
+ DateUtil.format(oldTime.getCourseEndTime(), "yyyy-MM-dd HH:mm")
+ "),与当前报名时间重叠,不能兼报");
@@ -1480,8 +1509,9 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
return Map.of(false, activity.getKeyWord() + "人数最多为" + currentType.getFamilyMaxCount());
}
List<FamilyType> typeList = dao().query(FamilyType.class, Cnd.NEW());
Map<String, String> typeMap = typeList.stream().collect(Collectors.toMap(FamilyType::getId, FamilyType::getTypeName));
// 冲突提示显示历史报名对应的具体子活动名称,不使用类型名称或本次尝试报名的名称。
Map<String, String> courseNameMap = courseList.stream().collect(Collectors.toMap(FamilyCourse::getId,
course -> StrUtil.isBlank(course.getCourseName()) ? "原子活动" : course.getCourseName()));
List<List<NutMap>> currentValue = user.getMobileColumnsValue();
@@ -1527,13 +1557,16 @@ public class FamilyActivityServiceImpl extends BaseServiceImpl<FamilyActivity> i
if(Objects.equals(onlyKeyValue, hisKeyValue)) {
oneFamilyCount ++;
if(Objects.equals(courseMap.get(user.getCourseId()), courseMap.get(hisRecord.getCourseId()))) {
return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(user.getCourseId())) + "分场");
return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动")
+ "”,不能重复报名同时间段");
}
if(aa.contains(user.getCourseId()) && bb.contains(hisRecord.getCourseId())) {
return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(hisRecord.getCourseId())) + "分场,存在冲突");
return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动")
+ "”,与当前子活动存在冲突");
}
if(bb.contains(user.getCourseId()) && aa.contains(hisRecord.getCourseId())) {
return Map.of(false, onlyKeyValue + "已经报名" + typeMap.get(courseMap.get(hisRecord.getCourseId())) + "分场,存在冲突");
return Map.of(false, onlyKeyValue + "已经报名“" + courseNameMap.getOrDefault(hisRecord.getCourseId(), "原子活动")
+ "”,与当前子活动存在冲突");
}
}
}
@@ -43,11 +43,12 @@ public class WelfareAddressManageServiceImpl extends BaseServiceImpl<WelfareMemb
SELECT
u.loginname,
u.username,
CONCAT(IFNULL(a.province, ''), IFNULL(a.city, ''),
CONCAT('收货人:', IFNULL(a.userName, ''), ' 电话:', IFNULL(a.tel, ''),
'详细地址:', IFNULL(a.province, ''), IFNULL(a.city, ''),
IFNULL(a.county, ''), IFNULL(a.addressDetail, '')) AS address
FROM sys_user u
INNER JOIN (
SELECT userId, province, city, county, addressDetail,
SELECT userId, userName, tel, province, city, county, addressDetail,
ROW_NUMBER() OVER (PARTITION BY userId ORDER BY isDefault DESC, id) AS rn
FROM welfare_member_address
) a ON a.userId = u.id AND a.rn = 1
@@ -55,7 +56,7 @@ public class WelfareAddressManageServiceImpl extends BaseServiceImpl<WelfareMemb
""");
List<NutMap> list = listMap(sql);
// 工号按字符串导出,保留前导零;收货地址只包含省市区县和详细地址。
// 工号按字符串导出,保留前导零;收货地址合并所选地址的收货人、电话及省市区县和详细地址。
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginname", 20));
entities.add(new ExcelExportEntity("姓名", "username", 20));
@@ -127,9 +127,9 @@ const basicForm = {
<el-form-item label="报名时间冲突" prop="timeConflictCheck">
<el-switch :value="formData.timeConflictCheck"
@input="(val) => { this.$set(formData, 'timeConflictCheck', val) }"
active-text="禁止时间重叠报名"></el-switch>
active-text="禁止同一家属时间重叠报名"></el-switch>
<div style="color: #c64120; font-size: 12px">
按子活动实际日期及起止时间判断,含候补报名。上午与同日全天互斥,上午与下午、不同日期可兼报。
按同一教职工下同一家属的子活动实际日期及起止时间判断,含候补报名。同一家属上午与同日全天互斥,上午与下午、不同日期可兼报;不同家属可以报名同时段的不同子活动。
</div>
</el-form-item>
<el-form-item :rules="{required:true,message: '请输入活动介绍', trigger: 'blur'}" label="活动介绍" prop="introduce">
@@ -13,7 +13,7 @@ const info = {
<el-descriptions-item label="报名结束时间">{{viewData.activitySignUpEndTime}}</el-descriptions-item>
<el-descriptions-item label="家属人数范围">{{viewData.familyCountScope === 2 ? '按整个活动累计' : '按子活动类型累计'}}</el-descriptions-item>
<el-descriptions-item label="活动家属最多数">{{viewData.familyMaxCount}}</el-descriptions-item>
<el-descriptions-item label="禁止时间重叠报名">{{viewData.timeConflictCheck === true ? '是(含候补)' : '否'}}</el-descriptions-item>
<el-descriptions-item label="禁止同一家属时间重叠">{{viewData.timeConflictCheck === true ? '是(含候补)' : '否'}}</el-descriptions-item>
<el-descriptions-item label="家属唯一标识编码">{{viewData.onlyKey}}</el-descriptions-item>
<el-descriptions-item label="详细信息" :span="2">
<div v-html="viewData.introduce"></div>