feat:学号快速查询
fix:商品统计排除退款、退款中 fix:售后列表增加退款类型
This commit is contained in:
1 parent
324708ffdb
commit
15743935ef
9 files changed
+192
-47
No files matched your search
+10
@@ -86,6 +86,16 @@ public interface RemoteCanteenSpuService {
|
||||
@PostMapping("/canteenSpu/ad/getSpuListByIds")
|
||||
R<List<CanteenSpuEntity>> getSpuListByIds(@RequestBody List<Long> ids);
|
||||
|
||||
/**
|
||||
* 供 Hardware 定时任务等无用户上下文的服务间调用批量查询菜品。
|
||||
*
|
||||
* @param ids 菜品 SPU 主键列表
|
||||
* @return 当前租户下命中的菜品列表
|
||||
*/
|
||||
@PostMapping("/canteenSpu/inner/getSpuListByIds")
|
||||
@NoToken
|
||||
R<List<CanteenSpuEntity>> getInnerSpuListByIds(@RequestBody List<Long> ids);
|
||||
|
||||
/**
|
||||
* 按套餐 SPU ID 批量查询套餐组成,用于跨服务补充只读展示数据。
|
||||
*
|
||||
|
||||
+24
-1
@@ -383,7 +383,30 @@ public class CanteenSpuController {
|
||||
@Operation(summary = "通过ids查询" , description = "通过ids查询" )
|
||||
@PostMapping("/ad/getSpuListByIds" )
|
||||
public R<List<CanteenSpuEntity>> getByIds(@RequestBody List<Long> ids) {
|
||||
List<CanteenSpuEntity> list = canteenSpuService.list(new LambdaQueryWrapper<CanteenSpuEntity>().in(CanteenSpuEntity::getId, ids));
|
||||
return querySpuByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为无用户令牌的 Hardware 服务间调用提供菜品批量查询,保持原管理端接口的鉴权行为不变。
|
||||
*
|
||||
* @param ids 菜品 SPU 主键列表
|
||||
* @return 当前租户下命中的菜品列表
|
||||
*/
|
||||
@Inner
|
||||
@PostMapping("/inner/getSpuListByIds")
|
||||
public R<List<CanteenSpuEntity>> getInnerByIds(@RequestBody List<Long> ids) {
|
||||
return querySpuByIds(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一执行菜品 SPU 批量查询,避免管理端和内部端点产生不同的数据筛选口径。
|
||||
*
|
||||
* @param ids 菜品 SPU 主键列表
|
||||
* @return 当前租户下命中的菜品列表
|
||||
*/
|
||||
private R<List<CanteenSpuEntity>> querySpuByIds(List<Long> ids) {
|
||||
List<CanteenSpuEntity> list = canteenSpuService.list(new LambdaQueryWrapper<CanteenSpuEntity>()
|
||||
.in(CanteenSpuEntity::getId, ids));
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -15,6 +15,24 @@ public class HardAfterSaleVo extends HardAfterSaleEntity implements BaseUserInte
|
||||
*/
|
||||
private String autoRefundTaskStatus;
|
||||
|
||||
/**
|
||||
* 自动退款任务场景编码;10 表示规定时间内用户免审退款,20 表示过期订单自动退款,人工审核时为空。
|
||||
* 该字段仅用于管理端列表响应,不对应售后表持久化字段。
|
||||
*/
|
||||
private String autoRefundTaskType;
|
||||
|
||||
/**
|
||||
* 用户免审退款采用的规则名称,来源于自动退款任务创建时的配置快照;非免审任务为空。
|
||||
* 该字段仅用于管理端列表响应,不对应售后表持久化字段。
|
||||
*/
|
||||
private String autoRefundRuleType;
|
||||
|
||||
/**
|
||||
* 用户免审退款资格截止时间,来源于自动退款任务创建时的规则快照;非免审任务为空。
|
||||
* 该字段仅用于管理端列表响应,不对应售后表持久化字段。
|
||||
*/
|
||||
private LocalDateTime autoRefundEligibilityDeadline;
|
||||
|
||||
/**
|
||||
* 用户相关
|
||||
*/
|
||||
|
||||
+16
-8
@@ -143,7 +143,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
List<HardOrderEntity> orderList = hardOrderMapper.list(hardOrderDto);
|
||||
HardUtil.convertOrderList(list.getRecords(), CollectionUtils.convertMap(orderList, HardOrderEntity::getId));
|
||||
}
|
||||
fillAutoRefundTaskStatus(list.getRecords());
|
||||
fillAutoRefundTaskInfo(list.getRecords());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
DataUtil.convertDeptList(list.getRecords(), deptList.getData());
|
||||
}
|
||||
}
|
||||
fillAutoRefundTaskStatus(list.getRecords());
|
||||
fillAutoRefundTaskInfo(list.getRecords());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -475,7 +475,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
DataUtil.convertDept(detail, dept.getData());
|
||||
}
|
||||
}
|
||||
fillAutoRefundTaskStatus(List.of(detail));
|
||||
fillAutoRefundTaskInfo(List.of(detail));
|
||||
}
|
||||
return detail;
|
||||
}
|
||||
@@ -1090,21 +1090,29 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量补充售后单关联的自动退款任务状态,普通人工售后保持为空。
|
||||
* 批量补充售后单关联的自动退款任务状态、场景及免审规则快照,普通人工售后保持为空。
|
||||
*
|
||||
* @param records 当前售后分页或详情响应
|
||||
*/
|
||||
private void fillAutoRefundTaskStatus(List<HardAfterSaleVo> records) {
|
||||
private void fillAutoRefundTaskInfo(List<HardAfterSaleVo> records) {
|
||||
List<Long> afterSaleIds = records.stream().map(HardAfterSaleVo::getId).filter(Objects::nonNull).distinct().toList();
|
||||
if (afterSaleIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Long, String> taskStatusMap = hardAutoRefundTaskService.list(
|
||||
Map<Long, HardAutoRefundTaskEntity> taskMap = hardAutoRefundTaskService.list(
|
||||
new LambdaQueryWrapper<HardAutoRefundTaskEntity>()
|
||||
.in(HardAutoRefundTaskEntity::getAfterSaleId, afterSaleIds))
|
||||
.stream().collect(Collectors.toMap(HardAutoRefundTaskEntity::getAfterSaleId,
|
||||
HardAutoRefundTaskEntity::getStatus, (first, second) -> first));
|
||||
records.forEach(item -> item.setAutoRefundTaskStatus(taskStatusMap.get(item.getId())));
|
||||
item -> item, (first, second) -> first));
|
||||
records.forEach(item -> {
|
||||
HardAutoRefundTaskEntity task = taskMap.get(item.getId());
|
||||
if (task != null) {
|
||||
item.setAutoRefundTaskStatus(task.getStatus());
|
||||
item.setAutoRefundTaskType(task.getTaskType());
|
||||
item.setAutoRefundRuleType(task.getRuleType());
|
||||
item.setAutoRefundEligibilityDeadline(task.getEligibilityDeadline());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -325,7 +325,7 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
|
||||
*/
|
||||
private void createDailyMenuCartItems(Long parentCarId, Long merchantId, List<HardCreateCarDto> productList) {
|
||||
List<Long> productIds = productList.stream().map(HardCreateCarDto::getProductId).distinct().toList();
|
||||
R<List<CanteenSpuEntity>> response = canteenSpuService.getSpuListByIds(productIds);
|
||||
R<List<CanteenSpuEntity>> response = canteenSpuService.getInnerSpuListByIds(productIds);
|
||||
if (response == null || !response.isOk() || response.getData() == null) {
|
||||
String message = response == null || response.getMsg() == null ? "查询每日菜谱商品失败" : response.getMsg();
|
||||
throw new RuntimeException(message);
|
||||
|
||||
+2
-2
@@ -1914,7 +1914,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
.map(HardCarEntity::getProductId)
|
||||
.distinct()
|
||||
.toList();
|
||||
R<List<CanteenSpuEntity>> result = remoteCanteenSpuService.getSpuListByIds(productIds);
|
||||
R<List<CanteenSpuEntity>> result = remoteCanteenSpuService.getInnerSpuListByIds(productIds);
|
||||
if (result == null || !result.isOk() || result.getData() == null) {
|
||||
throw new RuntimeException(result == null ? "查询每日菜谱商品无响应"
|
||||
: StrUtil.blankToDefault(result.getMsg(), "查询每日菜谱商品失败"));
|
||||
@@ -3898,7 +3898,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
Math::addExact,
|
||||
LinkedHashMap::new));
|
||||
R<List<CanteenSpuEntity>> productResult = remoteCanteenSpuService
|
||||
.getSpuListByIds(new ArrayList<>(stockChanges.keySet()));
|
||||
.getInnerSpuListByIds(new ArrayList<>(stockChanges.keySet()));
|
||||
if (productResult == null || !productResult.isOk() || productResult.getData() == null) {
|
||||
throw new RuntimeException(productResult == null ? "查询每日菜谱库存无响应"
|
||||
: StrUtil.blankToDefault(productResult.getMsg(), "查询每日菜谱库存失败"));
|
||||
|
||||
+62
-7
@@ -57,6 +57,61 @@
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<!--
|
||||
预约菜品统计统一使用退款扣减后的商品快照:先按父购物车和商品汇总原购买量,再扣除已完成(50)
|
||||
售后占用的数量、金额。退款申请中(10)仍属于有效预约,部分退款完成后只减少对应份数,取消或拒绝的售后仍正常统计;
|
||||
同一商品存在多行购物车快照时也不会重复扣减同一笔退款。
|
||||
-->
|
||||
<sql id="apptEffectiveCarSource">
|
||||
(
|
||||
select original_car.parent_car_id,
|
||||
original_car.product_id,
|
||||
original_car.product_name,
|
||||
original_car.product_pic,
|
||||
original_car.product_price,
|
||||
original_car.create_time,
|
||||
'0' as del_flag,
|
||||
greatest(original_car.product_count - ifnull(refund_car.product_count, 0), 0) as product_count,
|
||||
greatest(original_car.total_price - ifnull(refund_car.total_price, 0), 0) as total_price
|
||||
from (
|
||||
select c.parent_car_id,
|
||||
c.product_id,
|
||||
max(c.product_name) as product_name,
|
||||
max(c.product_pic) as product_pic,
|
||||
max(c.product_price) as product_price,
|
||||
min(c.create_time) as create_time,
|
||||
sum(ifnull(c.product_count, 0)) as product_count,
|
||||
sum(ifnull(c.total_price, 0)) as total_price
|
||||
from hard_car c
|
||||
where c.del_flag = '0'
|
||||
group by c.parent_car_id, c.product_id
|
||||
) original_car
|
||||
left join (
|
||||
select refund_item.parent_car_id,
|
||||
refund_item.product_id,
|
||||
sum(ifnull(refund_item.product_count, 0)) as product_count,
|
||||
sum(ifnull(refund_item.total_price, 0)) as total_price
|
||||
from hard_after_sale_car refund_item
|
||||
inner join hard_after_sale refund_order on refund_order.id = refund_item.refund_id
|
||||
and refund_order.del_flag = '0' and refund_order.status = '50'
|
||||
where refund_item.del_flag = '0'
|
||||
group by refund_item.parent_car_id, refund_item.product_id
|
||||
) refund_car on refund_car.parent_car_id = original_car.parent_car_id
|
||||
and refund_car.product_id = original_car.product_id
|
||||
where original_car.product_count > ifnull(refund_car.product_count, 0)
|
||||
) a
|
||||
</sql>
|
||||
|
||||
<!-- 通用统计接口被普通购买和预约页面共用,仅预约查询切换到退款扣减后的商品数据源。 -->
|
||||
<sql id="apptAwareCarSource">
|
||||
<choose>
|
||||
<when test="dto.apptIdOrApptRuleIdNotNull != null and dto.apptIdOrApptRuleIdNotNull == true">
|
||||
<include refid="apptEffectiveCarSource"/>
|
||||
</when>
|
||||
<otherwise>hard_car a</otherwise>
|
||||
</choose>
|
||||
</sql>
|
||||
|
||||
<select id="productTotalByDept" resultType="com.bsd.pjcloud.hard.api.vo.order.HardCanteenProductTotalVo">
|
||||
select DATE_FORMAT(a.create_time, '%Y-%m-%d') as createTime,
|
||||
o.user_dept_id,
|
||||
@@ -245,7 +300,7 @@
|
||||
SUM(a.total_price) as totalPrice,
|
||||
count(distinct o.id) as timeCount,
|
||||
count(distinct o.user_id) as payUserCount
|
||||
from hard_car a
|
||||
from <include refid="apptEffectiveCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0' and o.hour_type is not null and
|
||||
o.hour_type not in ('-1')
|
||||
@@ -344,7 +399,7 @@
|
||||
SUM(a.total_price) as totalPrice,
|
||||
count(distinct o.id) as timeCount,
|
||||
count(distinct o.user_id) as payUserCount
|
||||
from hard_car a
|
||||
from <include refid="apptEffectiveCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
|
||||
and o.hour_type is not null and o.hour_type not in ('-1')
|
||||
@@ -388,7 +443,7 @@
|
||||
count(distinct o.id) as timeCount,
|
||||
SUM(a.product_count) as payCount,
|
||||
SUM(a.total_price) as totalPrice
|
||||
from hard_car a
|
||||
from <include refid="apptEffectiveCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
|
||||
and o.hour_type is not null and o.hour_type not in ('-1')
|
||||
@@ -432,7 +487,7 @@
|
||||
a.product_name as productName,
|
||||
SUM(a.product_count) as payCount,
|
||||
SUM(a.total_price) as totalPrice
|
||||
from hard_car a
|
||||
from <include refid="apptEffectiveCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0'
|
||||
and o.hour_type is not null and o.hour_type not in ('-1')
|
||||
@@ -517,7 +572,7 @@
|
||||
SUM(a.product_count) as count,
|
||||
SUM(a.total_price) as totalPrice,
|
||||
DATE_FORMAT(a.create_time, '%Y-%m-%d') as create_time
|
||||
from hard_car a
|
||||
from <include refid="apptAwareCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0' and o.hour_type is not null
|
||||
<where>
|
||||
@@ -580,7 +635,7 @@
|
||||
SUM(a.total_price) as totalPrice,
|
||||
count(distinct o.id) as timeCount,
|
||||
count(distinct o.user_id) as payUserCount
|
||||
from hard_car a
|
||||
from <include refid="apptAwareCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0' and o.hour_type is not null and
|
||||
o.hour_type not in ('-1')
|
||||
@@ -645,7 +700,7 @@
|
||||
SUM(a.total_price) as totalPrice,
|
||||
count(distinct o.id) as timeCount,
|
||||
count(distinct o.user_id) as payUserCount
|
||||
from hard_car a
|
||||
from <include refid="apptAwareCarSource"/>
|
||||
inner join hard_parent_car p on a.parent_car_id = p.id and p.del_flag = '0'
|
||||
inner join hard_order o on o.parent_car_id = p.id and o.del_flag = '0' and o.hour_type is not null and
|
||||
o.hour_type not in ('-1')
|
||||
|
||||
+4
-4
@@ -63,15 +63,15 @@ public class UserDTO extends SysUser implements BaseIsIncludeTreeInterface {
|
||||
private List<String> identityTypes;
|
||||
|
||||
/**
|
||||
* 学生身份扩展信息
|
||||
* 学生身份扩展信息;写入时作为学生资料提交,查询时按各字段约定匹配。
|
||||
*/
|
||||
@Schema(description = "学生身份扩展信息")
|
||||
@Schema(description = "学生身份扩展信息或学生身份查询条件")
|
||||
private SysUserStudentDto studentInfo;
|
||||
|
||||
/**
|
||||
* 老师身份扩展信息,与学生身份扩展信息独立传输。
|
||||
* 老师身份扩展信息,与学生身份扩展信息独立传输;查询时老师学号按完整编号精确匹配。
|
||||
*/
|
||||
@Schema(description = "老师身份扩展信息")
|
||||
@Schema(description = "老师身份扩展信息或老师身份查询条件")
|
||||
private SysUserTeacherDto teacherInfo;
|
||||
|
||||
/**
|
||||
|
||||
@@ -136,6 +136,58 @@
|
||||
d.dept_id
|
||||
</sql>
|
||||
|
||||
<!--
|
||||
用户身份通用查询:身份类型命中任一选项;同一身份的多个扩展字段按 AND 组合。
|
||||
扩展资料使用固定列和参数化条件,学号/学校精确匹配,班级/监护人手机号包含匹配,避免动态列名。
|
||||
-->
|
||||
<sql id="userIdentityQuerySql">
|
||||
<if test="query.identityTypes != null and query.identityTypes.size() != 0">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_identity user_identity
|
||||
WHERE user_identity.user_id = u.user_id
|
||||
AND user_identity.identity_type IN
|
||||
<foreach collection="query.identityTypes" item="identityType" open="(" close=")" separator=",">
|
||||
#{identityType}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<if test="query.studentInfo != null">
|
||||
<if test="(query.studentInfo.studentNo != null and query.studentInfo.studentNo != '')
|
||||
or (query.studentInfo.schoolName != null and query.studentInfo.schoolName != '')
|
||||
or (query.studentInfo.className != null and query.studentInfo.className != '')
|
||||
or (query.studentInfo.guardianPhones != null and query.studentInfo.guardianPhones != '')">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_student student_identity
|
||||
WHERE student_identity.user_id = u.user_id
|
||||
<if test="query.studentInfo.studentNo != null and query.studentInfo.studentNo != ''">
|
||||
AND student_identity.student_no = #{query.studentInfo.studentNo}
|
||||
</if>
|
||||
<if test="query.studentInfo.schoolName != null and query.studentInfo.schoolName != ''">
|
||||
AND student_identity.school_name = #{query.studentInfo.schoolName}
|
||||
</if>
|
||||
<if test="query.studentInfo.className != null and query.studentInfo.className != ''">
|
||||
<bind name="studentClassNameLike" value="'%'+query.studentInfo.className+'%'"/>
|
||||
AND student_identity.class_name LIKE #{studentClassNameLike}
|
||||
</if>
|
||||
<if test="query.studentInfo.guardianPhones != null and query.studentInfo.guardianPhones != ''">
|
||||
<bind name="studentGuardianPhoneLike" value="'%'+query.studentInfo.guardianPhones+'%'"/>
|
||||
AND student_identity.guardian_phones LIKE #{studentGuardianPhoneLike}
|
||||
</if>
|
||||
)
|
||||
</if>
|
||||
</if>
|
||||
<if test="query.teacherInfo != null and query.teacherInfo.teacherNo != null and query.teacherInfo.teacherNo != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_teacher teacher_identity
|
||||
WHERE teacher_identity.user_id = u.user_id
|
||||
AND teacher_identity.teacher_no = #{query.teacherInfo.teacherNo}
|
||||
)
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<select id="getUserVoByUsername" resultMap="baseResultMap">
|
||||
SELECT
|
||||
<include refid="userRoleSql"/>
|
||||
@@ -219,18 +271,7 @@
|
||||
<if test="query.staffingType != null">
|
||||
AND u.staffing_type = #{query.staffingType}
|
||||
</if>
|
||||
<!-- 多身份查询按任一身份命中处理,EXISTS 可避免身份表的一对多关系放大用户结果集。 -->
|
||||
<if test="query.identityTypes != null and query.identityTypes.size() != 0">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_identity user_identity
|
||||
WHERE user_identity.user_id = u.user_id
|
||||
AND user_identity.identity_type IN
|
||||
<foreach collection="query.identityTypes" item="identityType" open="(" close=")" separator=",">
|
||||
#{identityType}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<include refid="userIdentityQuerySql"/>
|
||||
<if test="query.lockFlag != null and query.lockFlag != ''">
|
||||
AND u.lock_flag = #{query.lockFlag}
|
||||
</if>
|
||||
@@ -334,6 +375,7 @@
|
||||
#{userId}
|
||||
</foreach>
|
||||
</if>
|
||||
<include refid="userIdentityQuerySql"/>
|
||||
</where>
|
||||
<if test="_databaseId != 'mssql'">
|
||||
ORDER BY u.create_time DESC, u.user_id DESC
|
||||
@@ -396,18 +438,7 @@
|
||||
<if test="query.deptId != null and query.deptId != ''">
|
||||
AND u.dept_id = #{query.deptId}
|
||||
</if>
|
||||
<!-- 导出沿用列表页的身份筛选语义,确保导出结果与当前查询一致。 -->
|
||||
<if test="query.identityTypes != null and query.identityTypes.size() != 0">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM sys_user_identity user_identity
|
||||
WHERE user_identity.user_id = u.user_id
|
||||
AND user_identity.identity_type IN
|
||||
<foreach collection="query.identityTypes" item="identityType" open="(" close=")" separator=",">
|
||||
#{identityType}
|
||||
</foreach>
|
||||
)
|
||||
</if>
|
||||
<include refid="userIdentityQuerySql"/>
|
||||
<if test="query.staffingType != null">
|
||||
AND u.staffing_type = #{query.staffingType}
|
||||
</if>
|
||||
|
||||
Reference in new issue
Block a user