接入司机开票申请待办流程

This commit is contained in:
jsowell
2026-07-16 17:06:49 +08:00
parent 974e68cf54
commit cbc2e3c721
13 changed files with 353 additions and 20 deletions

View File

@@ -46,9 +46,9 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
| B03 | 当前用户查询、已读、完成、取消接口及测试 | P0 | done | 全量依赖编译、9 个专项测试通过 | `f84ec43ce` |
| B04 | 前端 API、待办中心页面和路由跳转 | P0 | done | ESLint 和生产构建通过 | 前端 `ff6b890` |
| B05 | 首页待办卡片、数量展示和轮询刷新 | P0 | done | ESLint 和生产构建通过 | 前端 `0627061` |
| B06 | 菜单权限 SQL、联调和首期回归 | P0 | done | 菜单 SQL、构建和专项回归通过待测试库执行 SQL | 本批提交 |
| B07 | 平台采购开票待办接入 | P1 | todo | - | - |
| B08 | 司机开票申请待办接入 | P1 | todo | - | - |
| B06 | 菜单权限 SQL、联调和首期回归 | P0 | done | 菜单 SQL、构建和专项回归通过待测试库执行 SQL | `974e68cf5` |
| B07 | 平台采购开票待办接入 | P1 | blocked | 仓库内未找到平台采购开票模型、审核状态或接口入口 | - |
| B08 | 司机开票申请待办接入 | P1 | done | 全依赖编译、12 个专项测试通过 | 本批提交 |
| B09 | 管理端创建、分配、取消和隐藏能力 | P1 | todo | - | - |
| B10 | 归档清理、过期任务和操作审计增强 | P2 | todo | - | - |
| B11 | 路由白名单、性能压测和安全专项验证 | P2 | todo | - | - |
@@ -121,7 +121,7 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
- 优先级P0
- 批次B06
- 状态:in_progress
- 状态:done
- 当前进展:
- 菜单、查询、已读、完成和取消权限 SQL 已完成。
- 列表、查询和已读权限默认授予正常角色;完成和取消权限保留为按业务角色授权。
@@ -138,7 +138,8 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
- 优先级P1
- 批次B07
- 状态:todo
- 状态:blocked
- 阻塞原因:当前仓库检索不到平台采购开票对应的数据库模型、审核拒绝/补充材料状态和业务接口,无法安全判断创建与完成时机。
- 目标:在平台采购开票审核拒绝或要求补充材料时创建待办,重新提交或平台关闭时完成。
- 验收标准:同一开票事件对同一接收人只产生一条有效待办,跳转参数和完成条件正确。
@@ -146,7 +147,7 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
- 优先级P1
- 批次B08
- 状态:todo
- 状态:in_progress
- 目标:收到司机开票申请时创建待办,审核通过、驳回或关闭时完成。
- 验收标准:创建和完成与开票业务事务一致,异常回滚时不产生脏任务状态。
@@ -184,4 +185,6 @@ PRD 同时要求“幂等键唯一”和“任务完成后允许同一业务重
- 2026-07-16B03完成当前用户数量、首页列表、分页列表、详情、已读、全部已读、完成和取消接口`mvn -pl jsowell-admin -am -DskipTests compile` 通过9 个 Service/Controller 专项测试通过commit `f84ec43ce`
- 2026-07-16B04完成前端 API、待办中心筛选分页、批量已读和安全路由跳转新增文件专项 ESLint 通过,`NODE_OPTIONS=--openssl-legacy-provider npm run build:prd` 构建通过;前端 commit `ff6b890`
- 2026-07-16B05完成首页右侧待办卡片、`99+` 数量、最近 3 条、空状态、错误重试和 60 秒轮询;专项 ESLint 与生产构建通过;前端 commit `0627061`
- 2026-07-16B06完成幂等菜单/权限 SQL列表、查询和已读权限默认授予正常角色完成和取消权限需按业务角色显式授权后端 9 个专项测试再次通过,前端构建沿用 B05 验证结果commit hash 在下一批记录中回填。
- 2026-07-16B06完成幂等菜单/权限 SQL列表、查询和已读权限默认授予正常角色完成和取消权限需按业务角色显式授权后端 9 个专项测试再次通过,前端构建沿用 B05 验证结果commit `974e68cf5`
- 2026-07-16B07 分析:当前仓库未发现平台采购开票业务落点,需补充对应模块/表/接口信息后继续。
- 2026-07-16B08司机开票记录创建后按运营商部门树为正常后台用户幂等创建待办开票状态更新为已开票时自动完成删除/关闭记录时自动取消;业务与待办状态处于同一事务;全依赖编译和 12 个专项测试通过commit hash 在下一批记录中回填。

View File

@@ -90,7 +90,7 @@ public class OrderInvoiceRecordController extends BaseController {
@Log(title = "申请开票", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody OrderInvoiceRecord orderInvoiceRecord) {
return toAjax(orderInvoiceRecordService.updateOrderInvoiceRecord(orderInvoiceRecord));
return toAjax(orderInvoiceRecordService.updateOrderInvoiceRecord(orderInvoiceRecord, getUserId(), getUsername()));
}
/**
@@ -100,6 +100,6 @@ public class OrderInvoiceRecordController extends BaseController {
@Log(title = "申请开票", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Integer[] ids) {
return toAjax(orderInvoiceRecordService.deleteOrderInvoiceRecordByIds(ids));
return toAjax(orderInvoiceRecordService.deleteOrderInvoiceRecordByIds(ids, getUsername()));
}
}

View File

@@ -0,0 +1,117 @@
package com.jsowell.pile.service;
import com.jsowell.pile.domain.OrderInvoiceRecord;
import com.jsowell.pile.domain.PileMerchantInfo;
import com.jsowell.pile.mapper.OrderInvoiceRecordMapper;
import com.jsowell.pile.service.impl.OrderInvoiceRecordServiceImpl;
import com.jsowell.system.constant.TodoTaskConstants;
import com.jsowell.system.domain.SysTodoTask;
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
import com.jsowell.system.service.TodoTaskAssigneeService;
import com.jsowell.system.service.TodoTaskService;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
class OrderInvoiceRecordTodoTest {
@Test
void insert_shouldCreateTodoForEachMerchantUser() {
OrderInvoiceRecordMapper mapper = mock(OrderInvoiceRecordMapper.class);
PileMerchantInfoService merchantService = mock(PileMerchantInfoService.class);
TodoTaskAssigneeService assigneeService = mock(TodoTaskAssigneeService.class);
TodoTaskService todoTaskService = mock(TodoTaskService.class);
OrderInvoiceRecordServiceImpl service = newService(mapper, merchantService, assigneeService, todoTaskService);
OrderInvoiceRecord invoiceRecord = new OrderInvoiceRecord();
invoiceRecord.setMerchantId("100");
doAnswer(invocation -> {
OrderInvoiceRecord record = invocation.getArgument(0);
record.setId(55);
return 1;
}).when(mapper).insertOrderInvoiceRecord(invoiceRecord);
PileMerchantInfo merchantInfo = new PileMerchantInfo();
merchantInfo.setDeptId("200");
when(merchantService.selectPileMerchantInfoById(100L)).thenReturn(merchantInfo);
when(assigneeService.findActiveUserIdsByDeptTree(200L)).thenReturn(Arrays.asList(8L, 9L));
when(todoTaskService.createTask(any(TodoTaskCreateCommand.class))).thenReturn(new SysTodoTask());
service.insertOrderInvoiceRecord(invoiceRecord);
ArgumentCaptor<TodoTaskCreateCommand> captor = ArgumentCaptor.forClass(TodoTaskCreateCommand.class);
verify(todoTaskService, times(2)).createTask(captor.capture());
List<TodoTaskCreateCommand> commands = captor.getAllValues();
assertEquals(Arrays.asList(8L, 9L), Arrays.asList(
commands.get(0).getAssigneeUserId(), commands.get(1).getAssigneeUserId()));
assertEquals("ORDER_INVOICE_RECORD", commands.get(0).getBusinessType());
assertEquals("55", commands.get(0).getBusinessId());
assertEquals("invoiceDetail", commands.get(0).getRouteName());
assertEquals(TodoTaskConstants.PRIORITY_IMPORTANT, commands.get(0).getPriority());
assertEquals("INVOICE_REVIEW:ORDER_INVOICE_RECORD:55:8", commands.get(0).getIdempotentKey());
}
@Test
void updateCompleted_shouldCompleteBusinessTodos() {
OrderInvoiceRecordMapper mapper = mock(OrderInvoiceRecordMapper.class);
TodoTaskService todoTaskService = mock(TodoTaskService.class);
OrderInvoiceRecordServiceImpl service = newService(mapper, mock(PileMerchantInfoService.class),
mock(TodoTaskAssigneeService.class), todoTaskService);
OrderInvoiceRecord invoiceRecord = new OrderInvoiceRecord();
invoiceRecord.setId(55);
invoiceRecord.setStatus("1");
when(mapper.updateOrderInvoiceRecord(invoiceRecord)).thenReturn(1);
service.updateOrderInvoiceRecord(invoiceRecord, 1L, "admin");
verify(todoTaskService).completeByBusiness("ORDER_INVOICE_RECORD", "55", null, 1L, "admin");
}
@Test
void delete_shouldCancelBusinessTodos() {
OrderInvoiceRecordMapper mapper = mock(OrderInvoiceRecordMapper.class);
TodoTaskService todoTaskService = mock(TodoTaskService.class);
OrderInvoiceRecordServiceImpl service = newService(mapper, mock(PileMerchantInfoService.class),
mock(TodoTaskAssigneeService.class), todoTaskService);
Integer[] ids = { 55, 56 };
when(mapper.deleteOrderInvoiceRecordByIds(ids)).thenReturn(2);
service.deleteOrderInvoiceRecordByIds(ids, "admin");
verify(todoTaskService).cancelByBusiness("ORDER_INVOICE_RECORD", "55", null,
"admin", "开票申请已关闭");
verify(todoTaskService).cancelByBusiness("ORDER_INVOICE_RECORD", "56", null,
"admin", "开票申请已关闭");
}
private static OrderInvoiceRecordServiceImpl newService(OrderInvoiceRecordMapper mapper,
PileMerchantInfoService merchantService, TodoTaskAssigneeService assigneeService,
TodoTaskService todoTaskService) {
OrderInvoiceRecordServiceImpl service = new OrderInvoiceRecordServiceImpl();
setField(service, "orderInvoiceRecordMapper", mapper);
setField(service, "pileMerchantInfoService", merchantService);
setField(service, "todoTaskAssigneeService", assigneeService);
setField(service, "todoTaskService", todoTaskService);
return service;
}
private static void setField(Object target, String fieldName, Object value) {
try {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}

View File

@@ -61,7 +61,7 @@ public interface OrderInvoiceRecordService {
* @param orderInvoiceRecord 申请开票
* @return 结果
*/
public int updateOrderInvoiceRecord(OrderInvoiceRecord orderInvoiceRecord);
public int updateOrderInvoiceRecord(OrderInvoiceRecord orderInvoiceRecord, Long operatorId, String operatorName);
/**
* 批量删除申请开票
@@ -69,7 +69,7 @@ public interface OrderInvoiceRecordService {
* @param ids 需要删除的申请开票主键集合
* @return 结果
*/
public int deleteOrderInvoiceRecordByIds(Integer[] ids);
public int deleteOrderInvoiceRecordByIds(Integer[] ids, String operatorName);
/**
* 删除申请开票信息
@@ -77,5 +77,5 @@ public interface OrderInvoiceRecordService {
* @param id 申请开票主键
* @return 结果
*/
public int deleteOrderInvoiceRecordById(Integer id);
public int deleteOrderInvoiceRecordById(Integer id, String operatorName);
}

View File

@@ -2,21 +2,31 @@ package com.jsowell.pile.service.impl;
import com.google.common.collect.Lists;
import com.jsowell.common.core.domain.vo.AuthorizedDeptVO;
import com.jsowell.common.util.StringUtils;
import com.jsowell.pile.domain.OrderInvoiceRecord;
import com.jsowell.pile.domain.PileMerchantInfo;
import com.jsowell.pile.dto.GetInvoiceInfoDTO;
import com.jsowell.pile.dto.QueryInvoiceRecordDTO;
import com.jsowell.pile.mapper.OrderInvoiceRecordMapper;
import com.jsowell.pile.service.MemberInvoiceTitleService;
import com.jsowell.pile.service.OrderInvoiceRecordService;
import com.jsowell.pile.service.OrderBasicInfoService;
import com.jsowell.pile.service.PileMerchantInfoService;
import com.jsowell.pile.util.UserUtils;
import com.jsowell.pile.vo.base.OrderAmountDetailVO;
import com.jsowell.pile.vo.uniapp.customer.InvoiceTitleVO;
import com.jsowell.pile.vo.web.InvoiceRecordVO;
import com.jsowell.pile.vo.web.OrderInvoiceRecordVO;
import com.jsowell.system.constant.TodoTaskConstants;
import com.jsowell.system.domain.dto.TodoTaskCreateCommand;
import com.jsowell.system.service.TodoTaskAssigneeService;
import com.jsowell.system.service.TodoTaskService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
@@ -30,6 +40,11 @@ import java.util.List;
*/
@Service
public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService {
private static final Logger log = LoggerFactory.getLogger(OrderInvoiceRecordServiceImpl.class);
private static final String TODO_TASK_TYPE = "INVOICE_REVIEW";
private static final String TODO_BUSINESS_TYPE = "ORDER_INVOICE_RECORD";
private static final String TODO_ROUTE_NAME = "invoiceDetail";
@Autowired
private OrderInvoiceRecordMapper orderInvoiceRecordMapper;
@@ -39,6 +54,15 @@ public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService
@Autowired
private OrderBasicInfoService orderBasicInfoService;
@Autowired
private PileMerchantInfoService pileMerchantInfoService;
@Autowired
private TodoTaskAssigneeService todoTaskAssigneeService;
@Autowired
private TodoTaskService todoTaskService;
/**
* 查询申请开票
*
@@ -132,8 +156,13 @@ public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService
* @return 结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertOrderInvoiceRecord(OrderInvoiceRecord orderInvoiceRecord) {
return orderInvoiceRecordMapper.insertOrderInvoiceRecord(orderInvoiceRecord);
int rows = orderInvoiceRecordMapper.insertOrderInvoiceRecord(orderInvoiceRecord);
if (rows > 0) {
createInvoiceReviewTodos(orderInvoiceRecord);
}
return rows;
}
/**
@@ -143,8 +172,14 @@ public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService
* @return 结果
*/
@Override
public int updateOrderInvoiceRecord(OrderInvoiceRecord orderInvoiceRecord) {
return orderInvoiceRecordMapper.updateOrderInvoiceRecord(orderInvoiceRecord);
@Transactional(rollbackFor = Exception.class)
public int updateOrderInvoiceRecord(OrderInvoiceRecord orderInvoiceRecord, Long operatorId, String operatorName) {
int rows = orderInvoiceRecordMapper.updateOrderInvoiceRecord(orderInvoiceRecord);
if (rows > 0 && "1".equals(orderInvoiceRecord.getStatus())) {
todoTaskService.completeByBusiness(TODO_BUSINESS_TYPE, String.valueOf(orderInvoiceRecord.getId()),
null, operatorId, operatorName);
}
return rows;
}
/**
@@ -154,8 +189,18 @@ public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService
* @return 结果
*/
@Override
public int deleteOrderInvoiceRecordByIds(Integer[] ids) {
return orderInvoiceRecordMapper.deleteOrderInvoiceRecordByIds(ids);
@Transactional(rollbackFor = Exception.class)
public int deleteOrderInvoiceRecordByIds(Integer[] ids, String operatorName) {
int rows = orderInvoiceRecordMapper.deleteOrderInvoiceRecordByIds(ids);
if (rows > 0 && ids != null) {
for (Integer id : ids) {
if (id != null) {
todoTaskService.cancelByBusiness(TODO_BUSINESS_TYPE, String.valueOf(id), null,
operatorName, "开票申请已关闭");
}
}
}
return rows;
}
/**
@@ -165,7 +210,71 @@ public class OrderInvoiceRecordServiceImpl implements OrderInvoiceRecordService
* @return 结果
*/
@Override
public int deleteOrderInvoiceRecordById(Integer id) {
return orderInvoiceRecordMapper.deleteOrderInvoiceRecordById(id);
@Transactional(rollbackFor = Exception.class)
public int deleteOrderInvoiceRecordById(Integer id, String operatorName) {
int rows = orderInvoiceRecordMapper.deleteOrderInvoiceRecordById(id);
if (rows > 0) {
todoTaskService.cancelByBusiness(TODO_BUSINESS_TYPE, String.valueOf(id), null,
operatorName, "开票申请已关闭");
}
return rows;
}
private void createInvoiceReviewTodos(OrderInvoiceRecord invoiceRecord) {
if (invoiceRecord.getId() == null || StringUtils.isBlank(invoiceRecord.getMerchantId())) {
log.warn("开票申请缺少主键或运营商无法创建待办invoiceId={}, merchantId={}",
invoiceRecord.getId(), invoiceRecord.getMerchantId());
return;
}
PileMerchantInfo merchantInfo;
try {
merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById(Long.parseLong(invoiceRecord.getMerchantId()));
} catch (NumberFormatException exception) {
log.warn("开票申请运营商 ID 非法无法创建待办invoiceId={}, merchantId={}",
invoiceRecord.getId(), invoiceRecord.getMerchantId());
return;
}
if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) {
log.warn("开票申请运营商未配置部门无法创建待办invoiceId={}, merchantId={}",
invoiceRecord.getId(), invoiceRecord.getMerchantId());
return;
}
Long merchantDeptId;
try {
merchantDeptId = Long.parseLong(merchantInfo.getDeptId());
} catch (NumberFormatException exception) {
log.warn("开票申请运营商部门 ID 非法无法创建待办invoiceId={}, deptId={}",
invoiceRecord.getId(), merchantInfo.getDeptId());
return;
}
List<Long> assigneeUserIds = todoTaskAssigneeService.findActiveUserIdsByDeptTree(merchantDeptId);
if (CollectionUtils.isEmpty(assigneeUserIds)) {
log.warn("开票申请运营商部门下没有正常用户无法创建待办invoiceId={}, deptId={}",
invoiceRecord.getId(), merchantInfo.getDeptId());
return;
}
for (Long assigneeUserId : assigneeUserIds) {
String idempotentKey = TODO_TASK_TYPE + ":" + TODO_BUSINESS_TYPE + ":"
+ invoiceRecord.getId() + ":" + assigneeUserId;
todoTaskService.createTask(TodoTaskCreateCommand.builder()
.taskType(TODO_TASK_TYPE)
.title("司机开票申请")
.summary("有新的司机开票申请需要处理,申请单号:" + invoiceRecord.getId())
.businessType(TODO_BUSINESS_TYPE)
.businessId(String.valueOf(invoiceRecord.getId()))
.routeName(TODO_ROUTE_NAME)
.routeParams("{\"params\":{\"id\":\"" + invoiceRecord.getId() + "\"}}")
.assigneeUserId(assigneeUserId)
.assigneeMerchantId(invoiceRecord.getMerchantId())
.priority(TodoTaskConstants.PRIORITY_IMPORTANT)
.idempotentKey(idempotentKey)
.createBy("invoice-system")
.build());
}
}
}

View File

@@ -56,4 +56,10 @@ public interface SysTodoTaskMapper {
int cancelTodo(@Param("todoId") Long todoId,
@Param("reason") String reason,
@Param("updateBy") String updateBy);
int cancelTodoByBusiness(@Param("businessType") String businessType,
@Param("businessId") String businessId,
@Param("assigneeUserId") Long assigneeUserId,
@Param("reason") String reason,
@Param("updateBy") String updateBy);
}

View File

@@ -19,6 +19,14 @@ public interface SysUserMapper {
*/
List<SysUser> selectUserList(SysUser sysUser);
/**
* 查询部门及下级部门的正常用户 ID。
*
* @param deptId 部门 ID
* @return 用户 ID 集合
*/
List<Long> selectActiveUserIdsByDeptTree(@Param("deptId") Long deptId);
/**
* 根据条件分页查询已配用户角色列表
*

View File

@@ -0,0 +1,12 @@
package com.jsowell.system.service;
import java.util.List;
/**
* 待办接收人解析服务。
*
* @author jsowell
*/
public interface TodoTaskAssigneeService {
List<Long> findActiveUserIdsByDeptTree(Long deptId);
}

View File

@@ -36,4 +36,7 @@ public interface TodoTaskService {
boolean cancelForAssignee(Long todoId, Long assigneeUserId, String operatorName, String reason);
boolean cancel(Long todoId, Long operatorId, String operatorName, String reason);
int cancelByBusiness(String businessType, String businessId, Long assigneeUserId,
String operatorName, String reason);
}

View File

@@ -0,0 +1,28 @@
package com.jsowell.system.service.impl;
import com.jsowell.common.exception.ServiceException;
import com.jsowell.system.mapper.SysUserMapper;
import com.jsowell.system.service.TodoTaskAssigneeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 待办接收人解析服务实现。
*
* @author jsowell
*/
@Service
public class TodoTaskAssigneeServiceImpl implements TodoTaskAssigneeService {
@Autowired
private SysUserMapper userMapper;
@Override
public List<Long> findActiveUserIdsByDeptTree(Long deptId) {
if (deptId == null || deptId <= 0) {
throw new ServiceException("待办接收部门不能为空");
}
return userMapper.selectActiveUserIdsByDeptTree(deptId);
}
}

View File

@@ -191,6 +191,20 @@ public class TodoTaskServiceImpl implements TodoTaskService {
throw new ServiceException("当前待办状态不允许取消");
}
@Override
@Transactional(rollbackFor = Exception.class)
public int cancelByBusiness(String businessType, String businessId, Long assigneeUserId,
String operatorName, String reason) {
String safeBusinessType = normalizeRequired(businessType, "业务类型", 64);
String safeBusinessId = normalizeRequired(businessId, "业务主键", 64);
if (assigneeUserId != null) {
validateUserId(assigneeUserId);
}
String safeReason = normalizeRequired(reason, "取消原因", 500);
return todoTaskMapper.cancelTodoByBusiness(safeBusinessType, safeBusinessId, assigneeUserId,
safeReason, normalizeOperator(operatorName, null));
}
private SysTodoTask buildTask(TodoTaskCreateCommand command) {
if (command.getAssigneeUserId() == null || command.getAssigneeUserId() <= 0) {
throw new ServiceException("待办接收用户不能为空");

View File

@@ -212,4 +212,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and del_flag = '0'
</update>
<update id="cancelTodoByBusiness">
update sys_todo_task
set task_status = 'CANCELLED',
cancel_reason = #{reason},
active_idempotent_key = null,
update_by = #{updateBy},
update_time = sysdate()
where business_type = #{businessType}
and business_id = #{businessId}
<if test="assigneeUserId != null">
and assignee_user_id = #{assigneeUserId}
</if>
and task_status in ('PENDING', 'PROCESSING')
and del_flag = '0'
</update>
</mapper>

View File

@@ -90,6 +90,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectActiveUserIdsByDeptTree" resultType="Long">
select distinct u.user_id
from sys_user u
where u.status = '0'
and u.del_flag = '0'
and (
u.dept_id = #{deptId}
or u.dept_id in (
select d.dept_id
from sys_dept d
where find_in_set(#{deptId}, d.ancestors)
and d.status = '0'
)
)
order by u.user_id
</select>
<select id="selectAllocatedList" parameterType="com.jsowell.common.core.domain.entity.SysUser" resultMap="SysUserResult">
select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phone, u.status, u.create_time
@@ -225,4 +242,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
</mapper>
</mapper>