✨ 新增异常关联维修记录:维修记录加 exception_id,异常详情内联记录并新增录入接口
This commit is contained in:
+9
@@ -36,6 +36,7 @@ import org.springblade.transport.pojo.dto.ExceptionDisposalFollowRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRejectRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRouteAdjustRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalUpdateRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionMaintenanceRecordRequest;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposal;
|
||||
import org.springblade.transport.pojo.vo.ExceptionDisposalVO;
|
||||
import org.springblade.transport.service.IExceptionDisposalService;
|
||||
@@ -140,4 +141,12 @@ public class ExceptionDisposalController extends BladeController {
|
||||
return R.success("已调整路线");
|
||||
}
|
||||
|
||||
@PostMapping("/maintenance-record")
|
||||
@ApiOperationSupport(order = 11)
|
||||
@Operation(summary = "录入维修记录", description = "车辆故障维修类异常的子流程:写一条关联维修记录并追加跟进记录,不结案;一条异常至多一条;仅需登录态")
|
||||
public R submitMaintenanceRecord(@RequestBody ExceptionMaintenanceRecordRequest request) {
|
||||
exceptionDisposalService.submitMaintenanceRecord(request);
|
||||
return R.success("已保存维修记录");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+41
-32
@@ -14,6 +14,7 @@
|
||||
<result column="is_deleted" property="isDeleted"/>
|
||||
<result column="vehicle_type" property="vehicleType"/>
|
||||
<result column="vehicle_no" property="vehicleNo"/>
|
||||
<result column="exception_id" property="exceptionId"/>
|
||||
<result column="maintainer" property="maintainer"/>
|
||||
<result column="maintenance_time" property="maintenanceTime"/>
|
||||
<result column="location" property="location"/>
|
||||
@@ -27,55 +28,63 @@
|
||||
<result column="mileage_unit" property="mileageUnit"/>
|
||||
<result column="attachments" property="attachments"/>
|
||||
<result column="remark" property="remark"/>
|
||||
<result column="waybill_no" property="waybillNo"/>
|
||||
<result column="exception_type" property="exceptionType"/>
|
||||
<result column="exception_reason" property="exceptionReason"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectMaintenanceRecordPage" resultMap="maintenanceRecordResultMap">
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
create_user,
|
||||
create_dept,
|
||||
create_time,
|
||||
update_user,
|
||||
update_time,
|
||||
status,
|
||||
is_deleted,
|
||||
vehicle_type,
|
||||
vehicle_no,
|
||||
maintainer,
|
||||
maintenance_time,
|
||||
location,
|
||||
replaced_part,
|
||||
cost,
|
||||
company,
|
||||
contact,
|
||||
address,
|
||||
factory_time,
|
||||
CASE WHEN mileage = -1 THEN NULL WHEN mileage < 0 THEN 0 ELSE mileage END AS mileage,
|
||||
mileage_unit,
|
||||
attachments,
|
||||
remark
|
||||
r.id,
|
||||
r.tenant_id,
|
||||
r.create_user,
|
||||
r.create_dept,
|
||||
r.create_time,
|
||||
r.update_user,
|
||||
r.update_time,
|
||||
r.status,
|
||||
r.is_deleted,
|
||||
r.vehicle_type,
|
||||
r.vehicle_no,
|
||||
r.exception_id,
|
||||
r.maintainer,
|
||||
r.maintenance_time,
|
||||
r.location,
|
||||
r.replaced_part,
|
||||
r.cost,
|
||||
r.company,
|
||||
r.contact,
|
||||
r.address,
|
||||
r.factory_time,
|
||||
CASE WHEN r.mileage = -1 THEN NULL WHEN r.mileage < 0 THEN 0 ELSE r.mileage END AS mileage,
|
||||
r.mileage_unit,
|
||||
r.attachments,
|
||||
r.remark,
|
||||
d.waybill_no,
|
||||
d.exception_type,
|
||||
d.exception_reason
|
||||
FROM
|
||||
blade_vehicle_maintenance_record
|
||||
blade_vehicle_maintenance_record r
|
||||
LEFT JOIN blade_exception_disposal d ON d.id = r.exception_id AND d.is_deleted = 0
|
||||
WHERE
|
||||
is_deleted = 0
|
||||
r.is_deleted = 0
|
||||
<if test="maintenanceRecord.createDept != null">
|
||||
AND create_dept = #{maintenanceRecord.createDept}
|
||||
AND r.create_dept = #{maintenanceRecord.createDept}
|
||||
</if>
|
||||
<if test="maintenanceRecord.vehicleType != null and maintenanceRecord.vehicleType != ''">
|
||||
AND vehicle_type = #{maintenanceRecord.vehicleType}
|
||||
AND r.vehicle_type = #{maintenanceRecord.vehicleType}
|
||||
</if>
|
||||
<if test="maintenanceRecord.vehicleNo != null and maintenanceRecord.vehicleNo != ''">
|
||||
<bind name="vehicleNoLike" value="'%' + maintenanceRecord.vehicleNo + '%'"/>
|
||||
AND vehicle_no LIKE #{vehicleNoLike}
|
||||
AND r.vehicle_no LIKE #{vehicleNoLike}
|
||||
</if>
|
||||
<if test="maintenanceRecord.createTimeStart != null">
|
||||
AND create_time >= #{maintenanceRecord.createTimeStart}
|
||||
AND r.create_time >= #{maintenanceRecord.createTimeStart}
|
||||
</if>
|
||||
<if test="maintenanceRecord.createTimeEnd != null">
|
||||
AND create_time <= #{maintenanceRecord.createTimeEnd}
|
||||
AND r.create_time <= #{maintenanceRecord.createTimeEnd}
|
||||
</if>
|
||||
ORDER BY create_time DESC
|
||||
ORDER BY r.create_time DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
+7
@@ -28,6 +28,7 @@ import org.springblade.transport.pojo.dto.ExceptionDisposalFollowRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRejectRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRouteAdjustRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalUpdateRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionMaintenanceRecordRequest;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposal;
|
||||
import org.springblade.transport.pojo.vo.ExceptionDisposalVO;
|
||||
|
||||
@@ -75,4 +76,10 @@ public interface IExceptionDisposalService extends BaseService<ExceptionDisposal
|
||||
*/
|
||||
void adjustRoute(ExceptionDisposalRouteAdjustRequest request);
|
||||
|
||||
/**
|
||||
* 录入关联维修记录:写一条维修记录并追加一条跟进记录,不结案。
|
||||
* 一条异常至多一条维修记录;已撤销的异常不允许录入。
|
||||
*/
|
||||
void submitMaintenanceRecord(ExceptionMaintenanceRecordRequest request);
|
||||
|
||||
}
|
||||
|
||||
+87
-1
@@ -41,22 +41,28 @@ import org.springblade.transport.pojo.dto.ExceptionDisposalFollowRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRejectRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRouteAdjustRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalUpdateRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionMaintenanceRecordRequest;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposal;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposalFollowRecord;
|
||||
import org.springblade.transport.pojo.entity.LoadingManage;
|
||||
import org.springblade.transport.pojo.entity.MaintenanceRecord;
|
||||
import org.springblade.transport.pojo.entity.Waybill;
|
||||
import org.springblade.transport.pojo.vo.ExceptionDisposalFollowRecordVO;
|
||||
import org.springblade.transport.pojo.vo.ExceptionDisposalVO;
|
||||
import org.springblade.transport.pojo.vo.MaintenanceRecordVO;
|
||||
import org.springblade.transport.service.IDriverWaybillService;
|
||||
import org.springblade.transport.service.IExceptionDisposalService;
|
||||
import org.springblade.transport.service.IMaintenanceRecordService;
|
||||
import org.springblade.transport.service.IWaybillService;
|
||||
import org.springblade.transport.support.MpUserDataScopeSupport;
|
||||
import org.springblade.transport.support.TransportBusinessSupport;
|
||||
import org.springblade.transport.support.WaybillProcessSupport;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -92,6 +98,12 @@ public class ExceptionDisposalServiceImpl
|
||||
/** 拒绝原因长度上限,与上报说明、异常原因同量级,且远小于跟进记录列宽 */
|
||||
private static final int REJECT_REASON_MAX_LENGTH = 200;
|
||||
|
||||
/** 异常子流程录入的维修记录固定为车辆:入口只对「车辆故障维修」类异常开放 */
|
||||
private static final String MAINTENANCE_VEHICLE_TYPE = "车辆";
|
||||
|
||||
/** 维修记录跟进说明前缀;金额必填,维修单位按实际填写拼在后面 */
|
||||
private static final String MAINTENANCE_FOLLOW_PREFIX = "已录入维修记录:费用";
|
||||
|
||||
/** 路线与任务信息的列宽上限,与 PC 改路线同一口径 */
|
||||
private static final int ROUTE_JSON_MAX_LENGTH = 8000;
|
||||
private static final int TASK_INFO_JSON_MAX_LENGTH = 8000;
|
||||
@@ -119,17 +131,20 @@ public class ExceptionDisposalServiceImpl
|
||||
private final IDriverWaybillService driverWaybillService;
|
||||
private final MpUserDataScopeSupport mpUserDataScopeSupport;
|
||||
private final LoadingManageMapper loadingManageMapper;
|
||||
private final IMaintenanceRecordService maintenanceRecordService;
|
||||
|
||||
public ExceptionDisposalServiceImpl(ExceptionDisposalFollowRecordMapper followRecordMapper,
|
||||
IWaybillService waybillService,
|
||||
IDriverWaybillService driverWaybillService,
|
||||
MpUserDataScopeSupport mpUserDataScopeSupport,
|
||||
LoadingManageMapper loadingManageMapper) {
|
||||
LoadingManageMapper loadingManageMapper,
|
||||
IMaintenanceRecordService maintenanceRecordService) {
|
||||
this.followRecordMapper = followRecordMapper;
|
||||
this.waybillService = waybillService;
|
||||
this.driverWaybillService = driverWaybillService;
|
||||
this.mpUserDataScopeSupport = mpUserDataScopeSupport;
|
||||
this.loadingManageMapper = loadingManageMapper;
|
||||
this.maintenanceRecordService = maintenanceRecordService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,6 +161,7 @@ public class ExceptionDisposalServiceImpl
|
||||
ExceptionDisposalVO vo = convertVO(entity);
|
||||
fillRouteNodes(vo, fillRouteAndCargo(vo, entity.getWaybillId()));
|
||||
vo.setFollowRecords(followRecords(id));
|
||||
vo.setMaintenanceRecord(maintenanceRecord(id));
|
||||
return vo;
|
||||
}
|
||||
|
||||
@@ -527,6 +543,76 @@ public class ExceptionDisposalServiceImpl
|
||||
updateById(disposal);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void submitMaintenanceRecord(ExceptionMaintenanceRecordRequest request) {
|
||||
if (request == null || request.getId() == null) {
|
||||
throw new ServiceException("请选择需要录入维修记录的异常");
|
||||
}
|
||||
ExceptionDisposal disposal = getExisting(request.getId());
|
||||
if (STATUS_REVOKED.equals(disposal.getDisposalStatus())) {
|
||||
throw new ServiceException("已撤销的异常不允许录入维修记录");
|
||||
}
|
||||
if (Func.isBlank(disposal.getVehicleNo())) {
|
||||
throw new ServiceException("异常未记录车牌号,无法录入维修记录");
|
||||
}
|
||||
// 唯一索引占位后无法再插入,先按 exception_id 拦住(含已逻辑删除的记录)
|
||||
long recorded = maintenanceRecordService.count(Wrappers.<MaintenanceRecord>lambdaQuery()
|
||||
.eq(MaintenanceRecord::getExceptionId, disposal.getId()));
|
||||
if (recorded > 0) {
|
||||
throw new ServiceException("该异常已录入维修记录");
|
||||
}
|
||||
|
||||
MaintenanceRecord record = new MaintenanceRecord();
|
||||
record.setExceptionId(disposal.getId());
|
||||
record.setVehicleType(MAINTENANCE_VEHICLE_TYPE);
|
||||
record.setVehicleNo(disposal.getVehicleNo());
|
||||
record.setMaintenanceTime(request.getMaintenanceTime());
|
||||
record.setLocation(request.getLocation());
|
||||
record.setMaintainer(request.getMaintainer());
|
||||
record.setCompany(request.getCompany());
|
||||
record.setContact(request.getContact());
|
||||
record.setReplacedPart(request.getReplacedPart());
|
||||
record.setCost(request.getCost());
|
||||
record.setMileage(request.getMileage());
|
||||
record.setFactoryTime(request.getFactoryTime());
|
||||
record.setAddress(request.getAddress());
|
||||
record.setRemark(request.getRemark());
|
||||
record.setAttachments(request.getAttachments());
|
||||
// 复用维修记录自身的校验与落库(车船类型、车牌、费用、出厂时间等口径与 PC 一致)
|
||||
try {
|
||||
maintenanceRecordService.submit(record);
|
||||
} catch (DuplicateKeyException exception) {
|
||||
// 并发重复提交:前一条尚在事务中、计数看不见,唯一索引是最终防线
|
||||
throw new ServiceException("该异常已录入维修记录");
|
||||
}
|
||||
|
||||
String followContent = maintenanceFollowContent(record.getCost(), record.getCompany());
|
||||
insertFollowRecord(disposal.getId(), followContent);
|
||||
disposal.setLatestFollowContent(followContent);
|
||||
// 录入维修记录不结案:已了结的异常只补记录与最近跟进,不回退状态
|
||||
if (!WaybillProcessSupport.SETTLED_DISPOSAL_STATUSES.contains(disposal.getDisposalStatus())) {
|
||||
disposal.setDisposalStatus(STATUS_PROCESSING);
|
||||
}
|
||||
updateById(disposal);
|
||||
}
|
||||
|
||||
/** 跟进说明:金额必填,维修单位为空时只写金额 */
|
||||
private String maintenanceFollowContent(BigDecimal cost, String company) {
|
||||
String amount = Func.isEmpty(cost) ? "" : cost.setScale(2, RoundingMode.HALF_UP).toPlainString();
|
||||
String content = MAINTENANCE_FOLLOW_PREFIX + amount + "元";
|
||||
return Func.isBlank(company) ? content : content + ",维修单位" + company.trim();
|
||||
}
|
||||
|
||||
/** 异常关联的维修记录:一条异常至多一条,逻辑删除的视为未录入 */
|
||||
private MaintenanceRecordVO maintenanceRecord(Long disposalId) {
|
||||
MaintenanceRecord record = maintenanceRecordService.getOne(Wrappers.<MaintenanceRecord>lambdaQuery()
|
||||
.eq(MaintenanceRecord::getExceptionId, disposalId)
|
||||
.eq(MaintenanceRecord::getIsDeleted, 0)
|
||||
.last("LIMIT 1"));
|
||||
return record == null ? null : BeanUtil.copyProperties(record, MaintenanceRecordVO.class);
|
||||
}
|
||||
|
||||
/** 已了结(已完成 / 已撤销)的异常不允许再次处置 */
|
||||
private void assertNotSettled(ExceptionDisposal disposal) {
|
||||
if (WaybillProcessSupport.SETTLED_DISPOSAL_STATUSES.contains(disposal.getDisposalStatus())) {
|
||||
|
||||
+13
@@ -27,6 +27,7 @@ package org.springblade.transport.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
@@ -81,6 +82,18 @@ public class MaintenanceRecordServiceImpl extends BaseServiceImpl<MaintenanceRec
|
||||
return saveOrUpdate(maintenanceRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteLogic(List<Long> ids) {
|
||||
if (Func.isNotEmpty(ids)) {
|
||||
// 唯一索引不因逻辑删除释放:不清空 exception_id,异常侧会永远显示「已录入」却查不到记录
|
||||
update(Wrappers.<MaintenanceRecord>lambdaUpdate()
|
||||
.set(MaintenanceRecord::getExceptionId, null)
|
||||
.in(MaintenanceRecord::getId, ids));
|
||||
}
|
||||
return super.deleteLogic(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<MaintenanceRecordExcel> importMaintenanceRecord(List<MaintenanceRecordExcel> data) {
|
||||
|
||||
Reference in New Issue
Block a user