修改了工单bug
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
yuyongle 2025-08-13 10:21:58 +08:00
parent 7b74451547
commit e73d6abf62
12 changed files with 224 additions and 21 deletions

View File

@ -0,0 +1,47 @@
package org.dromara.property.controller.mobile;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.property.domain.bo.InspectionPointBo;
import org.dromara.property.domain.vo.InspectionPointVo;
import org.dromara.property.service.IInspectionPointService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 巡检点
* 前端访问路由地址为:/property/point
*
* @author mocheng
* @date 2025-07-11
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/mobile/point")
public class MInspectionPointController extends BaseController {
private final IInspectionPointService inspectionPointService;
/**
* 扫码签到
*/
@PostMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody InspectionPointBo bo) {
return toAjax(inspectionPointService.updateByBo(bo));
}
}

View File

@ -1,6 +1,4 @@
package org.dromara.property.domain; package org.dromara.property.domain;
import cn.idev.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;

View File

@ -97,7 +97,9 @@ public class CostItemsBo extends BaseEntity {
/** /**
* 计费单价 * 计费单价
*/ */
@NotBlank(message = "计费单价", groups = { AddGroup.class, EditGroup.class }) @NotNull(message = "计费单价不能为空", groups = { AddGroup.class, EditGroup.class })
@DecimalMin(value = "0.00", inclusive = false, message = "计费单价必须大于0")
@ExcelProperty("计费单价")
private BigDecimal unitPrice; private BigDecimal unitPrice;
/** /**

View File

@ -7,11 +7,11 @@ package org.dromara.property.domain.enums;
**/ **/
public enum MeetAttachStatusEnum { public enum MeetAttachStatusEnum {
/** /**
* 待确认 * 上架
*/ */
ENAABLE("上架", "0"), ENAABLE("上架", "0"),
/** /**
* 待提货 * 下架
*/ */
DEACTIVATE("下架", "1"); DEACTIVATE("下架", "1");

View File

@ -3,7 +3,7 @@ package org.dromara.property.domain.enums;
/** /**
* @Author:yuyongle * @Author:yuyongle
* @Date:2025/7/4 10:35 * @Date:2025/7/4 10:35
* @Description: * @Description:会议室状态枚举
**/ **/
public enum MeetStatusEnum { public enum MeetStatusEnum {
/** /**

View File

@ -0,0 +1,33 @@
package org.dromara.property.domain.enums;
/**
* @Author:yuyongle
* @Date:2025/8/11 10:59
* @Description:工单状态枚举
**/
public enum WorkOrderStatusEnum {
CREATE_ORDER("创建工单", "0"),
DISPATCHED("已派单", "1"),
ROB_ORDER("已抢单", "2"),
IN_HAND("处理中", "3"),
DONE("已完成", "4"),
ABANDON("已废弃", "5");
private final String name;
private final String value;
WorkOrderStatusEnum(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return this.name;
}
public String getValue() {
return this.value;
}
}

View File

@ -99,9 +99,11 @@ public class CostCarChargeServiceImpl implements ICostCarChargeService {
lqw.eq(bo.getFloorId() != null, CostCarCharge::getFloorId, bo.getFloorId()); lqw.eq(bo.getFloorId() != null, CostCarCharge::getFloorId, bo.getFloorId());
lqw.eq(StringUtils.isNotBlank(bo.getLocation()), CostCarCharge::getLocation, bo.getLocation()); lqw.eq(StringUtils.isNotBlank(bo.getLocation()), CostCarCharge::getLocation, bo.getLocation());
lqw.eq(StringUtils.isNotBlank(bo.getState()), CostCarCharge::getState, bo.getState()); lqw.eq(StringUtils.isNotBlank(bo.getState()), CostCarCharge::getState, bo.getState());
lqw.eq(StringUtils.isNotBlank(bo.getChargeStatus()), CostCarCharge::getChargeStatus, bo.getChargeStatus());
lqw.eq(bo.getCostItemsId() != null, CostCarCharge::getCostItemsId, bo.getCostItemsId()); lqw.eq(bo.getCostItemsId() != null, CostCarCharge::getCostItemsId, bo.getCostItemsId());
lqw.eq(bo.getStarTime() != null, CostCarCharge::getStarTime, bo.getStarTime()); lqw.eq(bo.getStarTime() != null, CostCarCharge::getStarTime, bo.getStarTime());
lqw.eq(bo.getEndTime() != null, CostCarCharge::getEndTime, bo.getEndTime()); lqw.eq(bo.getEndTime() != null, CostCarCharge::getEndTime, bo.getEndTime());
lqw.eq(StringUtils.isNotBlank(bo.getState()), CostCarCharge::getState, bo.getState());
lqw.eq(StringUtils.isNotBlank(bo.getSearchValue()), CostCarCharge::getSearchValue, bo.getSearchValue()); lqw.eq(StringUtils.isNotBlank(bo.getSearchValue()), CostCarCharge::getSearchValue, bo.getSearchValue());
return lqw; return lqw;
} }

View File

@ -78,6 +78,7 @@ public class CostItemsServiceImpl implements ICostItemsService {
lqw.orderByAsc(CostItems::getId); lqw.orderByAsc(CostItems::getId);
lqw.eq(StringUtils.isNotBlank(bo.getCostType()), CostItems::getCostType, bo.getCostType()); lqw.eq(StringUtils.isNotBlank(bo.getCostType()), CostItems::getCostType, bo.getCostType());
lqw.eq(StringUtils.isNotBlank(bo.getChargeItem()), CostItems::getChargeItem, bo.getChargeItem()); lqw.eq(StringUtils.isNotBlank(bo.getChargeItem()), CostItems::getChargeItem, bo.getChargeItem());
lqw.eq(StringUtils.isNotBlank(bo.getChargeNo()), CostItems::getChargeNo, bo.getChargeNo());
lqw.eq(StringUtils.isNotBlank(bo.getCostMark()), CostItems::getCostMark, bo.getCostMark()); lqw.eq(StringUtils.isNotBlank(bo.getCostMark()), CostItems::getCostMark, bo.getCostMark());
lqw.eq(StringUtils.isNotBlank(bo.getPaymentType()), CostItems::getPaymentType, bo.getPaymentType()); lqw.eq(StringUtils.isNotBlank(bo.getPaymentType()), CostItems::getPaymentType, bo.getPaymentType());
lqw.eq(bo.getChargeCycle() != null, CostItems::getChargeCycle, bo.getChargeCycle()); lqw.eq(bo.getChargeCycle() != null, CostItems::getChargeCycle, bo.getChargeCycle());

View File

@ -178,15 +178,16 @@ public class MachineMaintainPlanServiceImpl implements IMachineMaintainPlanServi
*/ */
private void validEntityBeforebo(Long id, MachineMaintainPlanBo bo) { private void validEntityBeforebo(Long id, MachineMaintainPlanBo bo) {
//TODO 做一些数据校验,如唯一约束 //TODO 做一些数据校验,如唯一约束
Assert.isTrue(CollUtil.isNotEmpty(bo.getMachineMaintainPlanStaffBoList()), "巡检人员不存在"); if(CollUtil.isNotEmpty(bo.getMachineMaintainPlanStaffBoList())){
QueryWrapper<MachineMaintainPlanStaff> staffLambdaQueryWrapper = new QueryWrapper<>(); QueryWrapper<MachineMaintainPlanStaff> staffLambdaQueryWrapper = new QueryWrapper<>();
staffLambdaQueryWrapper.eq("maintain_plan_id", id); staffLambdaQueryWrapper.eq("maintain_plan_id", id);
machineMaintainPlanStaffMapper.delete(staffLambdaQueryWrapper); machineMaintainPlanStaffMapper.delete(staffLambdaQueryWrapper);
List<MachineMaintainPlanStaffBo> machineMaintainPlanStaffBoList = bo.getMachineMaintainPlanStaffBoList(); List<MachineMaintainPlanStaffBo> machineMaintainPlanStaffBoList = bo.getMachineMaintainPlanStaffBoList();
machineMaintainPlanStaffBoList.stream().forEach(s->{ machineMaintainPlanStaffBoList.stream().forEach(s->{
s.setMaintainPlanId(id); s.setMaintainPlanId(id);
}); });
machineMaintainPlanStaffMapper.insertBatch(BeanUtil.copyToList(machineMaintainPlanStaffBoList, MachineMaintainPlanStaff.class)); machineMaintainPlanStaffMapper.insertBatch(BeanUtil.copyToList(machineMaintainPlanStaffBoList, MachineMaintainPlanStaff.class));
}
} }
/** /**

View File

@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.property.domain.InspectionPlanStaff; import org.dromara.property.domain.InspectionPlanStaff;
import org.dromara.property.domain.InspectionTask; import org.dromara.property.domain.InspectionTask;
import org.dromara.property.domain.bo.InspectionPlanBo; import org.dromara.property.domain.bo.InspectionPlanBo;
@ -41,6 +42,7 @@ import static org.dromara.common.mybatis.core.mapper.BaseMapperPlus.log;
* @Date:2025/7/11 15:28 * @Date:2025/7/11 15:28
* @Description: 巡检任务定时处理器 * @Description: 巡检任务定时处理器
**/ **/
@Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
//@Validated //@Validated

View File

@ -8,6 +8,7 @@ import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.property.domain.MachineMaintainPlanStaff; import org.dromara.property.domain.MachineMaintainPlanStaff;
import org.dromara.property.domain.MachineMaintainTask; import org.dromara.property.domain.MachineMaintainTask;
import org.dromara.property.domain.bo.MachineMaintainPlanBo; import org.dromara.property.domain.bo.MachineMaintainPlanBo;
@ -42,6 +43,7 @@ import static org.dromara.common.mybatis.core.mapper.BaseMapperPlus.log;
* @Date:2025/7/17 09:25 * @Date:2025/7/17 09:25
* @Description: * @Description:
**/ **/
@Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
//@Validated //@Validated
@ -64,6 +66,7 @@ public class MachineTasks {
List<MachineMaintainPlanVo> machineMaintainPlanVoList = machineMaintainPlanService.queryList(machineMaintainPlanBo); List<MachineMaintainPlanVo> machineMaintainPlanVoList = machineMaintainPlanService.queryList(machineMaintainPlanBo);
// 如果没有有效计划直接返回 // 如果没有有效计划直接返回
if (ObjectUtil.isEmpty(machineMaintainPlanVoList)) { if (ObjectUtil.isEmpty(machineMaintainPlanVoList)) {
log.info("暂时没有有效的计划");
return; return;
} }
machineMaintainPlanVoList.stream().forEach(plan->{ machineMaintainPlanVoList.stream().forEach(plan->{

View File

@ -2,17 +2,31 @@ package org.dromara.property.tasks;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.property.domain.AttendanceUserGroup;
import org.dromara.property.domain.ServiceWorkOrders; import org.dromara.property.domain.ServiceWorkOrders;
import org.dromara.property.domain.ServiceWorkOrdersRecord;
import org.dromara.property.domain.enums.WorkOrderStatusEnum;
import org.dromara.property.mapper.AttendanceUserGroupMapper;
import org.dromara.property.mapper.ServiceWorkOrdersMapper; import org.dromara.property.mapper.ServiceWorkOrdersMapper;
import org.dromara.property.mapper.ServiceWorkOrdersRecordMapper;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.Date;
import java.util.List; import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.common.log.annotation.Log; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/** /**
* @Author:yuyongle * @Author:yuyongle
@ -20,23 +34,123 @@ import org.dromara.common.log.annotation.Log;
* @Description:自动派单 * @Description:自动派单
**/ **/
@Slf4j @Slf4j
@Component //@Component
//@RequiredArgsConstructor
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController
@RequestMapping("/serviceWorkOrderTasks")
public class ServiceWorkOrderTasks { public class ServiceWorkOrderTasks {
private ServiceWorkOrdersMapper workOrdersMapper; private ServiceWorkOrdersMapper workOrdersMapper;
private ServiceWorkOrdersRecordMapper workOrdersRecordMapper;
private AttendanceUserGroupMapper attendanceUserGroupMapper;
//查询状态为创建工单的工单 /**
* 查询状态为创建工单的工单,查询当天排班人员,为工单自动派单
*/
// @Transactional(rollbackFor = Exception.class)
// @Scheduled(cron = "0 0 */1 * * ?")
@GetMapping("/serviceWorkOrderTaskId")
private void handleServiceWorkOrder() { private void handleServiceWorkOrder() {
List<ServiceWorkOrders> serviceWorkOrderList = workOrdersMapper.selectList( List<ServiceWorkOrders> serviceWorkOrderList = workOrdersMapper.selectList(
new LambdaQueryWrapper<ServiceWorkOrders>() new LambdaQueryWrapper<ServiceWorkOrders>()
.eq(ServiceWorkOrders::getStatus, "0")); .eq(ServiceWorkOrders::getStatus, WorkOrderStatusEnum.CREATE_ORDER.getValue()));
if(CollUtil.isNotEmpty(serviceWorkOrderList)){ if(CollUtil.isNotEmpty(serviceWorkOrderList)){
serviceWorkOrderList.stream().forEach(s->{ serviceWorkOrderList.stream().forEach(s->{
//查询今天上班的人员
LocalDate today = LocalDate.now();
List<AttendanceUserGroup> attendanceUserGroups = attendanceUserGroupMapper.selectList(
new LambdaQueryWrapper<AttendanceUserGroup>()
.eq(AttendanceUserGroup::getStartDate, today)
);
if(CollUtil.isNotEmpty(attendanceUserGroups)){
attendanceUserGroups.stream().forEach(s1->{
ServiceWorkOrdersRecord serviceWorkOrdersRecord = new ServiceWorkOrdersRecord();
serviceWorkOrdersRecord.setOrderId(s.getId());
serviceWorkOrdersRecord.setStatus(WorkOrderStatusEnum.DISPATCHED.getValue());
serviceWorkOrdersRecord.setHandler(s1.getEmployeeId());
workOrdersRecordMapper.insert(serviceWorkOrdersRecord);
s.setStatus(WorkOrderStatusEnum.DISPATCHED.getValue());
s.setHandler(s1.getEmployeeId());
workOrdersMapper.updateById(s);
log.info("派单工单号为:{}",s.getOrderNo());
log.info("处理人为:{}",s1.getEmployeeId());
});
}else {
log.info("当天无排班人员");
}
}); });
}else { }else {
log.info("派单工单为:{}",serviceWorkOrderList.size()); log.info("派单工单为:{}",serviceWorkOrderList.size());
} }
}
/**
* 处理超过30分钟的工单
*/
// @Transactional(rollbackFor = Exception.class)
// @Scheduled(cron = "0 0 */1 * * ?")
@GetMapping("/thirtyWorkOrderTaskId")
private void thirtyHandleServiceWorkOrder() {
// 1. 查询当前状态为已派单的工单
List<ServiceWorkOrders> serviceWorkOrderList = workOrdersMapper.selectList(
new LambdaQueryWrapper<ServiceWorkOrders>()
.eq(ServiceWorkOrders::getStatus, WorkOrderStatusEnum.DISPATCHED.getValue())
);
LocalDate today = LocalDate.now();
// 2. 查询今天有排班的人员
List<AttendanceUserGroup> attendanceUserGroups = attendanceUserGroupMapper.selectList(
new LambdaQueryWrapper<AttendanceUserGroup>()
.eq(AttendanceUserGroup::getStartDate, today)
);
if (CollUtil.isEmpty(serviceWorkOrderList) || CollUtil.isEmpty(attendanceUserGroups)) {
log.info("当前无可处理的超时工单或今日无排班人员");
return;
}
Date now = new Date();
// 3. 遍历超时工单
serviceWorkOrderList.forEach(workOrder -> {
// 查询该工单的最新记录可能有多条记录
ServiceWorkOrdersRecord latestRecord = workOrdersRecordMapper.selectOne(
new LambdaQueryWrapper<ServiceWorkOrdersRecord>()
.eq(ServiceWorkOrdersRecord::getOrderId, workOrder.getId())
.orderByDesc(ServiceWorkOrdersRecord::getCreateTime)
.last("LIMIT 1") // 获取最新一条记录
);
if (ObjectUtil.isEmpty(latestRecord) || latestRecord.getCreateTime() == null) {
return;
}
// 判断是否超过30分钟
long minutesElapsed = DateUtil.between(latestRecord.getCreateTime(), now, DateUnit.MINUTE);
if (minutesElapsed <= 30) {
return; // 未超时跳过
}
// 4. 标记原记录为废弃
latestRecord.setStatus(WorkOrderStatusEnum.ABANDON.getValue());
workOrdersRecordMapper.updateById(latestRecord);
log.info("工单号:{} 的原记录已废弃,超时未处理", workOrder.getOrderNo());
// 5. 重新派单给今天所有排班人员排除原处理人根据业务决定
boolean hasNewDispatch = false;
for (AttendanceUserGroup group : attendanceUserGroups) {
Long employeeId = group.getEmployeeId();
// 可选避免重新派给原处理人
if (employeeId.equals(latestRecord.getHandler())) {
log.debug("跳过原处理人:{}", employeeId);
continue;
}
// 创建新的派单记录
ServiceWorkOrdersRecord newRecord = new ServiceWorkOrdersRecord();
newRecord.setOrderId(workOrder.getId());
newRecord.setHandler(employeeId);
newRecord.setStatus(WorkOrderStatusEnum.DISPATCHED.getValue());
newRecord.setCreateTime(now);
workOrdersRecordMapper.insert(newRecord);
log.info("工单号:{} 已重新派发给员工ID{}", workOrder.getOrderNo(), employeeId);
// 6. 更新主工单状态可选若只保留最新记录状态也可不更新主表
workOrder.setStatus(WorkOrderStatusEnum.DISPATCHED.getValue()); // 仍为已派单
workOrder.setHandler(employeeId); // 可清空或设为最后一个人根据业务
workOrdersMapper.updateById(workOrder);
}
});
} }
} }