diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java index 2059bc9c..1adcf926 100644 --- a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/controller/TicketController.java @@ -99,6 +99,12 @@ public class TicketController extends ControllerBase { @Resource private ITBasePartService partService; + @Resource + private ITicketSolutionService ticketSolutionService; + + @Resource + private ITicketSolutionAuditService ticketSolutionAuditService; + /** * 获取问题类型 * @return 问题类型列表 @@ -276,6 +282,19 @@ public class TicketController extends ControllerBase { .setExperienceEvaluation(vo.getExperienceEvaluation()); } + /** + * 获取工单根本原因分析 + * @param ticketId 工单id + * @return 根本原因分析 + */ + @GetMapping("getReason") + @ApiMark(moduleName = "工单管理", apiName = "获取工单根本原因分析",isPublic = true) + public ApiResult getReason(@Valid @RequestParam @NotNull Integer ticketId){ + Ticket ticket=ticketService.getById(ticketId); + VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); + return ApiResult.success(ticket.getReason()); + } + /** * 导出搜索工单 * @param request 请求参数 @@ -399,30 +418,30 @@ public class TicketController extends ControllerBase { return ApiResult.success(); } - /** - * 关闭工单 - * @param request 请求参数 - */ - @PostMapping("closeTicket") - @MethodInfoMark(value = "关闭工单", menuName = "工单管理") - @ApiMark(moduleName = "工单管理", apiName = "关闭工单") - public ApiResult closeTicket(@Valid @RequestBody TicketCloseRequest request) { - Ticket ticket=ticketService.closeTicket(request); - ticketEventPublisher.publishTicketCloseEvent(ticket); - ChatMessageDTO message = new ChatMessageDTO() - .setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr()) - .setFrom("system") - .setTicketState(ticket.getState()) - .setSenderId(0) - .setSenderName("服务助手") - .setContent("工单已关闭
感谢你的使用,如有问题,请重新提交新的工单。") - .setCreateTime(Instant.now()); - ticketChatService.addMessage(request.getTicketId(), message); - //推送消息 - ssePushService.sendTicketMessageToAdmin(ticket.getId(),message); - ssePushService.sendTicketMessageToApp(ticket.getId(),message); - return ApiResult.success(); - } +// /** +// * 关闭工单 +// * @param request 请求参数 +// */ +// @PostMapping("closeTicket") +// @MethodInfoMark(value = "关闭工单", menuName = "工单管理") +// @ApiMark(moduleName = "工单管理", apiName = "关闭工单") +// public ApiResult closeTicket(@Valid @RequestBody TicketCloseRequest request) { +// Ticket ticket=ticketService.closeTicket(request); +// ticketEventPublisher.publishTicketCloseEvent(ticket); +// ChatMessageDTO message = new ChatMessageDTO() +// .setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr()) +// .setFrom("system") +// .setTicketState(ticket.getState()) +// .setSenderId(0) +// .setSenderName("服务助手") +// .setContent("工单已关闭
感谢你的使用,如有问题,请重新提交新的工单。") +// .setCreateTime(Instant.now()); +// ticketChatService.addMessage(request.getTicketId(), message); +// //推送消息 +// ssePushService.sendTicketMessageToAdmin(ticket.getId(),message); +// ssePushService.sendTicketMessageToApp(ticket.getId(),message); +// return ApiResult.success(); +// } /** * 导出工单为pdf @@ -490,7 +509,7 @@ public class TicketController extends ControllerBase { .setUrgency(ticket.getUrgency()) .setUpdateTime(DateTimeUtil.format(ticket.getUpdateTime())) .setHandleUserName(handle) - .setSolution(ticket.getSolution()) + .setSolution(ticket.getReason()) .setImages(images) .setFiles(files); Map variables = new HashMap<>(); @@ -579,6 +598,7 @@ public class TicketController extends ControllerBase { .setNo(ticket.getNo()) .setTitle(ticket.getTitle()) .setDeviceNo(ticket.getDeviceNo()) + .setDeviceAddress(ticket.getDeviceAddress()) .setModelNo(device.getModelNo()) .setDeviceType(device.getDeviceType()) .setComponent(ticket.getComponent()) @@ -603,8 +623,7 @@ public class TicketController extends ControllerBase { .setAreaName(areaName) .setCompanyName(device.getCustomerName()) .setHandle(handle) - .setSolution(ticket.getSolution()) - .setSolutionAttachments(StrUtil.isNotBlank(ticket.getSolutionAttachments()) ? StrUtil.split(ticket.getSolutionAttachments(), ",") : Collections.emptyList()) + .setSolution(ticket.getReason()) .setEvaluate(getTicketEvaluate(ticket.getId())); return ApiResult.success(vo); } @@ -727,4 +746,48 @@ public class TicketController extends ControllerBase { ticketEventPublisher.publishTicketReplyEvent(ticket); return ApiResult.success(); } + + /** + * 获取工单解决方案措施 + * @param ticketId 工单编号 + * @return 解决方案措施 + **/ + @GetMapping("getSolutionMeasures") + @ApiMark(moduleName = "工单管理", apiName = "获取工单解决方案措施") + public ApiResult> getSolutionMeasures(@Valid @RequestParam @NotNull Integer ticketId){ + return ApiResult.success(ticketSolutionService.getSolutionMeasures(ticketId)); + } + + /** + * 保存工单解决方案措施 + * @param request 请求信息 + **/ + @PostMapping("saveSolutionMeasures") + @ApiMark(moduleName = "工单管理", apiName = "保存工单解决方案措施") + public ApiResult saveSolutionMeasures(@Valid @RequestBody SolutionMeasuresSaveRequest request){ + ticketSolutionService.saveSolutionMeasures(request); + return ApiResult.success(); + } + + /** + * 获取工单解决方案评审部门 + * @param ticketId 工单编号 + * @return 评审部门 + **/ + @GetMapping("getSolutionReviewDepartment") + @ApiMark(moduleName = "工单管理", apiName = "获取工单解决方案评审部门") + public ApiResult> getSolutionReviewDepartment(@Valid @RequestParam @NotNull Integer ticketId){ + return ApiResult.success(ticketSolutionAuditService.getByTicket(ticketId)); + } + + /** + * 保存工单解决方案评审部门 + * @param request 请求信息 + **/ + @PostMapping("saveSolutionReviewDepartment") + @ApiMark(moduleName = "工单管理", apiName = "保存工单解决方案评审部门") + public ApiResult saveSolutionReviewDepartment(@Valid @RequestBody SolutionReviewDepartmentSaveRequest request){ + ticketSolutionAuditService.saveSolutionReviewDepartment(request); + return ApiResult.success(); + } } \ No newline at end of file diff --git a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/task/TicketScheduledTasks.java b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/task/TicketScheduledTasks.java index 720e309e..e09af1ed 100644 --- a/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/task/TicketScheduledTasks.java +++ b/nflg-mobilebroken-admin/src/main/java/com/nflg/mobilebroken/admin/task/TicketScheduledTasks.java @@ -5,9 +5,12 @@ import cn.hutool.core.date.DatePattern; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.nflg.mobilebroken.admin.pojo.dto.TiketTimeoutDTO; +import com.nflg.mobilebroken.admin.publisher.TicketEventPublisher; +import com.nflg.mobilebroken.admin.service.SsePushService; import com.nflg.mobilebroken.common.constant.Constant; import com.nflg.mobilebroken.common.constant.MessageSubType; import com.nflg.mobilebroken.common.constant.UserState; +import com.nflg.mobilebroken.common.pojo.dto.ChatMessageDTO; import com.nflg.mobilebroken.common.pojo.request.TicketEvaluateAddRequest; import com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateAddVO; import com.nflg.mobilebroken.common.pojo.vo.TicketEvaluateItemVO; @@ -22,6 +25,7 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.mail.MessagingException; import java.math.BigDecimal; +import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; @@ -68,6 +72,15 @@ public class TicketScheduledTasks { @Resource private IDeviceService deviceService; + @Resource + private TicketEventPublisher ticketEventPublisher; + + @Resource + private TicketChatService ticketChatService; + + @Resource + private SsePushService ssePushService; + /** * 工单评论邀请邮件 * 每天午夜12点执行一次 @@ -126,6 +139,21 @@ public class TicketScheduledTasks { tickets.forEach(ticket -> { request.setTicketId(ticket.getId()); ticketEvaluateService.add(request); + if (ticketService.close(ticket)){ + ticketEventPublisher.publishTicketCloseEvent(ticket); + ChatMessageDTO message = new ChatMessageDTO() + .setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr()) + .setFrom("system") + .setTicketState(ticket.getState()) + .setSenderId(0) + .setSenderName("服务助手") + .setContent("工单已关闭
感谢你的使用,如有问题,请重新提交新的工单。") + .setCreateTime(Instant.now()); + ticketChatService.addMessage(request.getTicketId(), message); + //推送消息 + ssePushService.sendTicketMessageToAdmin(ticket.getId(),message); + ssePushService.sendTicketMessageToApp(ticket.getId(),message); + } }); log.info("【工单自动评论】执行完成"); } diff --git a/nflg-mobilebroken-admin/src/test/java/Test.java b/nflg-mobilebroken-admin/src/test/java/Test.java new file mode 100644 index 00000000..4213918e --- /dev/null +++ b/nflg-mobilebroken-admin/src/test/java/Test.java @@ -0,0 +1,15 @@ +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; + +public class Test { + + @org.junit.jupiter.api.Test + public void test1(){ + LocalDate t1=LocalDateTime.now().toLocalDate(); + LocalDate t2=LocalDateTime.now().toLocalDate().minusDays(1); + System.out.println(t1); + System.out.println(t2); + System.out.println(ChronoUnit.DAYS.between(null, t1)); + } +} diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java index c68e8c8f..ccedfa84 100644 --- a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/controller/TiketController.java @@ -206,6 +206,7 @@ public class TiketController extends ControllerBase { .setNo(ticket.getNo()) .setTitle(ticket.getTitle()) .setDeviceNo(ticket.getDeviceNo()) + .setDeviceAddress(ticket.getDeviceAddress()) .setModelNo(device.getModelNo()) .setComponent(ticket.getComponent()) .setUseTime(ticket.getUseTime()) @@ -221,8 +222,7 @@ public class TiketController extends ControllerBase { .setSolveTime(ticket.getSolveTime()) .setCompanyName(StrUtil.join(",",companys.stream().map(TBaseCustomer::getAgencyCompanyName).collect(Collectors.toList()))) .setHandle(handle) - .setSolution(ticket.getSolution()) - .setSolutionAttachments(StrUtil.isNotBlank(ticket.getSolutionAttachments()) ? StrUtil.split(ticket.getSolutionAttachments(), ",") : Collections.emptyList()) + .setSolution(ticket.getReason()) .setEvaluate(getTicketEvaluate(ticket.getId())); return ApiResult.success(vo); } @@ -386,7 +386,20 @@ public class TiketController extends ControllerBase { **/ @PostMapping("addTicketEvaluate") public ApiResult addTicketEvaluate(@Valid @RequestBody TicketEvaluateAddRequest request) { - ticketEvaluateService.add(request); + Ticket ticket=ticketEvaluateService.add(request); + ticketEventPublisher.publishTicketEvaluateEvent(ticket, MultilingualUtil.getLanguage(), MultilingualUtil.getZone()); + ChatMessageDTO message = new ChatMessageDTO() + .setId(cn.hutool.core.util.IdUtil.getSnowflakeNextIdStr()) + .setFrom("system") + .setTicketState(ticket.getState()) + .setSenderId(0) + .setSenderName("服务助手") + .setContent("工单已评价
感谢你的评价。") + .setCreateTime(Instant.now()); + ticketChatService.addMessage(request.getTicketId(), message); + //推送消息 + ssePushService.sendTicketMessageToAdmin(ticket.getId(),message); + ssePushService.sendTicketMessageToApp(ticket.getId(),message); return ApiResult.success(); } } diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/event/TicketEvaluateEvent.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/event/TicketEvaluateEvent.java new file mode 100644 index 00000000..7a7b416f --- /dev/null +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/event/TicketEvaluateEvent.java @@ -0,0 +1,80 @@ +package com.nflg.mobilebroken.cfs.event; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import com.nflg.mobilebroken.common.constant.MessageSubType; +import com.nflg.mobilebroken.common.constant.MessageType; +import com.nflg.mobilebroken.repository.entity.AdminMessage; +import com.nflg.mobilebroken.repository.entity.AdminUser; +import com.nflg.mobilebroken.repository.entity.Ticket; +import com.nflg.mobilebroken.repository.service.*; +import com.nflg.mobilebroken.starter.service.EmailService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; + +@Slf4j +public class TicketEvaluateEvent extends ApplicationEvent implements ApplicationContextAware { + + private static final DateTimeFormatter FORMATTER= DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN); + private final Ticket ticket; + private final String language; + private final String zone; + + private IDictionaryItemTranslateService dictionaryItemTranslateService; + private IAppUserService appUserService; + private EmailService emailService; + private ITBaseDeviceTypeService deviceTypeService; + private IAdminUserService adminUserService; + private IAdminMessageService adminMessageService; + + public TicketEvaluateEvent(Object source, Ticket ticket,String language,String zone) { + super(source); + this.ticket = ticket; + this.language = language; + this.zone = zone; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.dictionaryItemTranslateService = applicationContext.getBean(IDictionaryItemTranslateService.class); + this.appUserService = applicationContext.getBean(IAppUserService.class); + this.emailService = applicationContext.getBean(EmailService.class); + this.adminUserService = applicationContext.getBean(IAdminUserService.class); + this.adminMessageService = applicationContext.getBean(IAdminMessageService.class); + this.deviceTypeService = applicationContext.getBean(ITBaseDeviceTypeService.class); + } + + public void send(){ + sendUserMessage(); + } + + private void sendUserMessage(){ + //我的待办 + List cqms=deviceTypeService.getCqmsByDeviceType(ticket.getDeviceNo()); + if (CollectionUtil.isEmpty(cqms)){ + log.warn("该设备尚未设置CQM负责人:{}", ticket.getDeviceNo()); + }else { + List cqmUsers = adminUserService.listByIds(cqms); + if (CollectionUtil.isNotEmpty(cqmUsers)) { + cqmUsers.forEach(c -> adminMessageService.add( + new AdminMessage() + .setNo(ticket.getNo()) + .setTitle(ticket.getTitle()) + .setUserId(c.getId()) + .setSourceId(ticket.getId()) + .setSource(0) + .setType(MessageType.WorkOrderAssignment.getState()) + .setSubType(MessageSubType.TicketCompletion.getState()) + .setIsRead(false) + .setCreateTime(LocalDateTime.now())) + ); + } + } + } +} diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/listener/TicketEventListener.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/listener/TicketEventListener.java index 436d7fef..98946eeb 100644 --- a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/listener/TicketEventListener.java +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/listener/TicketEventListener.java @@ -1,6 +1,7 @@ package com.nflg.mobilebroken.cfs.listener; import com.nflg.mobilebroken.cfs.event.TicketCreateEvent; +import com.nflg.mobilebroken.cfs.event.TicketEvaluateEvent; import com.nflg.mobilebroken.cfs.event.TicketReplyEvent; import com.nflg.mobilebroken.cfs.event.TicketRevokeEvent; import org.springframework.context.event.EventListener; @@ -27,4 +28,10 @@ public class TicketEventListener { public void handleTicketRevokeEvent(TicketRevokeEvent event) { event.send(); } + + @Async + @EventListener + public void handleTicketEvaluateEvent(TicketEvaluateEvent event) { + event.send(); + } } diff --git a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/publisher/TicketEventPublisher.java b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/publisher/TicketEventPublisher.java index ecdef729..b941a1de 100644 --- a/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/publisher/TicketEventPublisher.java +++ b/nflg-mobilebroken-cfs-app/src/main/java/com/nflg/mobilebroken/cfs/publisher/TicketEventPublisher.java @@ -1,9 +1,6 @@ package com.nflg.mobilebroken.cfs.publisher; -import com.nflg.mobilebroken.cfs.event.TicketCreateEvent; -import com.nflg.mobilebroken.cfs.event.TicketReopenEvent; -import com.nflg.mobilebroken.cfs.event.TicketReplyEvent; -import com.nflg.mobilebroken.cfs.event.TicketRevokeEvent; +import com.nflg.mobilebroken.cfs.event.*; import com.nflg.mobilebroken.repository.entity.Ticket; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEventPublisher; @@ -43,4 +40,10 @@ public class TicketEventPublisher { event.setApplicationContext(applicationContext); eventPublisher.publishEvent(event); } + + public void publishTicketEvaluateEvent(Ticket ticket, String language, String zone) { + TicketEvaluateEvent event = new TicketEvaluateEvent(this, ticket, language, zone); + event.setApplicationContext(applicationContext); + eventPublisher.publishEvent(event); + } } diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java index 97a8321a..ba217841 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/Constant.java @@ -111,4 +111,7 @@ public class Constant { public static final String DICTIONARY_ITEM_ACCOUNT_HAS_EXPIRED="AccountHasExpired"; public static final List ROLE_CODE_TICKET_MANAGERS = ListUtil.of(TITLE_DIRECTOROF_BUSINESS_UNIT,TITLE_TECHNICAL_MANAGER,TITLE_SALES_MANAGER,TITLE_TEST_MANAGER,TITLE_QUALITY_MANAGER,DICTIONARY_TYPE_TITLE_CQM); + + public static final String DICTIONARY_SOLUTION_MEASURES = "SolutionMeasures"; + public static final String DICTIONARY_SOLUTION_REVIEW_DEPARTMENT = "SolutionReviewDepartment"; } diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/MessageSubType.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/MessageSubType.java index 0a5b5b3f..bcf6c36d 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/MessageSubType.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/constant/MessageSubType.java @@ -17,7 +17,8 @@ public enum MessageSubType { TicketClosed(7, "工单关闭"), TicketRevoke(8, "工单撤销"), TicketReopen(9, "工单重启"), - TicketTimeout(10, "工单超时"); + TicketTimeout(10, "工单超时"), + TicketSolutionAudit(11, "工单解决方案审核"); private final Integer state; private final String description; diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionMeasuresSaveRequest.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionMeasuresSaveRequest.java new file mode 100644 index 00000000..e115a948 --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionMeasuresSaveRequest.java @@ -0,0 +1,33 @@ +package com.nflg.mobilebroken.common.pojo.request; + +import com.nflg.mobilebroken.common.pojo.vo.SolutionMeasuresVO; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +public class SolutionMeasuresSaveRequest { + + /** + * 工单编号 + */ + @NotNull + private Integer ticketId; + + /** + * 根本原因 + */ + @NotBlank + private String reason; + + /** + * 解决措施 + */ + @Valid + @NotEmpty + private List solutionMeasures; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionReviewDepartmentSaveRequest.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionReviewDepartmentSaveRequest.java new file mode 100644 index 00000000..67da4c9d --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/SolutionReviewDepartmentSaveRequest.java @@ -0,0 +1,18 @@ +package com.nflg.mobilebroken.common.pojo.request; + +import com.nflg.mobilebroken.common.pojo.vo.SolutionReviewDepartmentVO; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +public class SolutionReviewDepartmentSaveRequest { + + @NotNull + private Integer ticketId; + + @NotEmpty + private List departments; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/TicketAddRequest.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/TicketAddRequest.java index b7c1a2c8..3ab450c5 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/TicketAddRequest.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/request/TicketAddRequest.java @@ -34,4 +34,8 @@ public class TicketAddRequest { //附件 private List attachments; + + //设备地址 + @Size(max = 300, message = "设备地址长度不能超过300") + private String deviceAddress; } \ No newline at end of file diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/AdminTicketVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/AdminTicketVO.java index a17bb123..750bd954 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/AdminTicketVO.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/AdminTicketVO.java @@ -1,5 +1,6 @@ package com.nflg.mobilebroken.common.pojo.vo; +import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.annotation.JsonIgnore; import com.nflg.mobilebroken.common.constant.TicketState; import com.nflg.mobilebroken.common.constant.TicketUrgency; @@ -8,6 +9,7 @@ import org.ttzero.excel.annotation.ExcelColumn; import org.ttzero.excel.annotation.IgnoreExport; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Objects; @Data @@ -51,9 +53,21 @@ public class AdminTicketVO { @ExcelColumn("问题类型") private String question; - //解决方案 - @ExcelColumn("解决方案") - private String solution; + //根本原因分析 + @IgnoreExport + private String reason; + + public String getReason() { + return StrUtil.subWithLength(reason, 0, 10); + } + + //根本原因分析 + @ExcelColumn("根本原因分析") + private String reason1; + + public String getReason1() { + return reason; + } //代理区域 @ExcelColumn("代理区域") @@ -164,4 +178,18 @@ public class AdminTicketVO { //评价 @IgnoreExport private TicketEvaluateVO evaluate; + + //处理时长 + @ExcelColumn("处理时长") + private Long processingTime; + + public Long getProcessingTime() { + if (TicketState.Processing.getState().compareTo(state)>=0){ + return ChronoUnit.DAYS.between(createTime.toLocalDate(),LocalDateTime.now().toLocalDate())+1; + } + if (TicketState.Closed.getState().compareTo(state)>=0) { + return ChronoUnit.DAYS.between(completeTime, LocalDateTime.now()) + 1; + } + return null; + } } \ No newline at end of file diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresItemVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresItemVO.java new file mode 100644 index 00000000..5bcb618c --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresItemVO.java @@ -0,0 +1,47 @@ +package com.nflg.mobilebroken.common.pojo.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; + +@Data +@Accessors(chain = true) +public class SolutionMeasuresItemVO { + + private Integer id; + + /** + * 措施名称 + */ + @NotBlank + private String name; + + /** + * 负责人 + */ + @NotBlank + private String superintendent; + + /** + * 计划日期 + */ + @NotBlank + private String scheduleDate; + + /** + * 确认日期 + */ + @NotBlank + private String confirmedDate; + + /** + * 备注 + */ + private String remark; + + /** + * 创建人id + */ + private Integer createUserId; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresVO.java new file mode 100644 index 00000000..8e9f09d0 --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionMeasuresVO.java @@ -0,0 +1,23 @@ +package com.nflg.mobilebroken.common.pojo.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Data +@Accessors(chain = true) +public class SolutionMeasuresVO { + + @NotNull + private Integer id; + + @NotBlank + private String name; + + @Valid + private List items; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionReviewDepartmentVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionReviewDepartmentVO.java new file mode 100644 index 00000000..c4eb4aeb --- /dev/null +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/SolutionReviewDepartmentVO.java @@ -0,0 +1,23 @@ +package com.nflg.mobilebroken.common.pojo.vo; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@Data +public class SolutionReviewDepartmentVO { + + private Integer id; + + //部门名称 + @NotBlank + private String deptName; + + //用户id + @NotNull + private Integer userId; + + //用户名称 + private String userName; +} diff --git a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java index 81f3376d..a1d3c6b0 100644 --- a/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java +++ b/nflg-mobilebroken-common/src/main/java/com/nflg/mobilebroken/common/pojo/vo/TicketInfoVO.java @@ -98,11 +98,13 @@ public class TicketInfoVO { //解决方案 private String solution; - //解决方案附件 - private List solutionAttachments; - /** * 解决时间 */ private LocalDateTime solveTime; + + /** + * 设备地址 + */ + private String deviceAddress; } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/Ticket.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/Ticket.java index 5a3fc646..6314db0b 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/Ticket.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/Ticket.java @@ -67,6 +67,11 @@ public class Ticket implements Serializable { */ private String attachments; + /** + * 设备地址 + */ + private String deviceAddress; + /** * 状态,0:待处理;1:处理中;2:处理完成;3:已关闭 */ @@ -95,12 +100,7 @@ public class Ticket implements Serializable { /** * 解决方案 */ - private String solution; - - /** - * 解决方案附件 - */ - private String solutionAttachments; + private String reason; /** * 解决时间 diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolution.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolution.java new file mode 100644 index 00000000..8db9ef96 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolution.java @@ -0,0 +1,76 @@ +package com.nflg.mobilebroken.repository.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("ticket_solution") +public class TicketSolution implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 工单id + */ + private Integer ticketId; + + /** + * 字典项id + */ + private Integer dictionaryId; + + /** + * 字典项值 + */ + private String dictionaryName; + + /** + * 负责人 + */ + private String superintendent; + + /** + * 计划日期 + */ + private String scheduleDate; + + /** + * 确认日期 + */ + private String confirmedDate; + + /** + * 备注 + */ + private String remark; + + /** + * 创建人id + */ + private Integer createUserid; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAudit.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAudit.java new file mode 100644 index 00000000..26a03060 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAudit.java @@ -0,0 +1,48 @@ +package com.nflg.mobilebroken.repository.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("ticket_solution_audit") +public class TicketSolutionAudit implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer id; + + /** + * 工单id + */ + private Integer ticketId; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 用户id + */ + private Integer userId; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAuditState.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAuditState.java new file mode 100644 index 00000000..fbfd4806 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/entity/TicketSolutionAuditState.java @@ -0,0 +1,53 @@ +package com.nflg.mobilebroken.repository.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Getter +@Setter +@Accessors(chain = true) +@TableName("ticket_solution_audit_state") +public class TicketSolutionAuditState implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer id; + + /** + * 工单id + */ + private Integer ticketId; + + /** + * 用户id + */ + private Integer userId; + + /** + * 审核状态,0:不通过;1:通过 + */ + private Integer state; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 审核不通过的原因 + */ + private String reason; +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/DictionaryItemMapper.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/DictionaryItemMapper.java index ab4c8760..86827f18 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/DictionaryItemMapper.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/DictionaryItemMapper.java @@ -5,6 +5,8 @@ import com.nflg.mobilebroken.repository.entity.DictionaryItem; import org.apache.ibatis.annotations.Select; import org.springframework.data.repository.query.Param; +import java.util.List; + /** *

* 字典值 Mapper 接口 @@ -19,4 +21,6 @@ public interface DictionaryItemMapper extends BaseMapper { Integer getId(@Param("dictionaryName") String dictionaryName, @Param("dictionaryItemName") String dictionaryItemName); String getName(String dictionaryCode, String itemCode); + + List getListByDictionaryCode(String code); } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditMapper.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditMapper.java new file mode 100644 index 00000000..54371e13 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditMapper.java @@ -0,0 +1,20 @@ +package com.nflg.mobilebroken.repository.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nflg.mobilebroken.common.pojo.vo.SolutionReviewDepartmentVO; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAudit; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface TicketSolutionAuditMapper extends BaseMapper { + + List getByTicket(Integer ticketId); +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditStateMapper.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditStateMapper.java new file mode 100644 index 00000000..6020ffaf --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionAuditStateMapper.java @@ -0,0 +1,17 @@ +package com.nflg.mobilebroken.repository.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAuditState; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface TicketSolutionAuditStateMapper extends BaseMapper { + + boolean existsNotPass(Integer id); +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionMapper.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionMapper.java new file mode 100644 index 00000000..7f799f01 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/mapper/TicketSolutionMapper.java @@ -0,0 +1,16 @@ +package com.nflg.mobilebroken.repository.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nflg.mobilebroken.repository.entity.TicketSolution; + +/** + *

+ * Mapper 接口 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface TicketSolutionMapper extends BaseMapper { + +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IAdminUserService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IAdminUserService.java index 3663b337..c73930c2 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IAdminUserService.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IAdminUserService.java @@ -52,4 +52,6 @@ public interface IAdminUserService extends IService { void deleteAccount(Integer id); List getTickerMangagers(); + + List getCQMIds(); } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IDictionaryItemService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IDictionaryItemService.java index 67023f70..32907cad 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IDictionaryItemService.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/IDictionaryItemService.java @@ -6,6 +6,8 @@ import com.nflg.mobilebroken.common.pojo.request.DictionaryItemSearchRequest; import com.nflg.mobilebroken.common.pojo.request.SaveDictionaryItemRequest; import com.nflg.mobilebroken.repository.entity.DictionaryItem; +import java.util.List; + /** *

* 字典值 服务类 @@ -21,4 +23,6 @@ public interface IDictionaryItemService extends IService { void save(SaveDictionaryItemRequest request); Integer getId(String dictionaryName, String dictionaryItemName); + + List getListByDictionaryCode(String code); } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketEvaluateService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketEvaluateService.java index b4d764ca..26269181 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketEvaluateService.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketEvaluateService.java @@ -2,6 +2,7 @@ package com.nflg.mobilebroken.repository.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nflg.mobilebroken.common.pojo.request.TicketEvaluateAddRequest; +import com.nflg.mobilebroken.repository.entity.Ticket; import com.nflg.mobilebroken.repository.entity.TicketEvaluate; /** @@ -14,5 +15,5 @@ import com.nflg.mobilebroken.repository.entity.TicketEvaluate; */ public interface ITicketEvaluateService extends IService { - void add(TicketEvaluateAddRequest request); + Ticket add(TicketEvaluateAddRequest request); } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketService.java index 8e0bc1c6..ef236685 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketService.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketService.java @@ -31,7 +31,7 @@ public interface ITicketService extends IService { Ticket completeTicket(Integer id); - Ticket closeTicket(TicketCloseRequest request); +// Ticket closeTicket(TicketCloseRequest request); List exportSearch(AdminTicketSearchRequest request); @@ -54,4 +54,6 @@ public interface ITicketService extends IService { List getAdminFavorites(Integer userId,Integer favoritesId); Ticket rejectTicket(Integer id); + + boolean close(Ticket ticket); } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditService.java new file mode 100644 index 00000000..6a1dc4b6 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditService.java @@ -0,0 +1,23 @@ +package com.nflg.mobilebroken.repository.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nflg.mobilebroken.common.pojo.request.SolutionReviewDepartmentSaveRequest; +import com.nflg.mobilebroken.common.pojo.vo.SolutionReviewDepartmentVO; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAudit; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface ITicketSolutionAuditService extends IService { + + List getByTicket(Integer ticketId); + + void saveSolutionReviewDepartment(SolutionReviewDepartmentSaveRequest request); +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditStateService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditStateService.java new file mode 100644 index 00000000..9a6ba501 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionAuditStateService.java @@ -0,0 +1,17 @@ +package com.nflg.mobilebroken.repository.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAuditState; + +/** + *

+ * 服务类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface ITicketSolutionAuditStateService extends IService { + + boolean existsNotPass(Integer id); +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionService.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionService.java new file mode 100644 index 00000000..5906af51 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/ITicketSolutionService.java @@ -0,0 +1,23 @@ +package com.nflg.mobilebroken.repository.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nflg.mobilebroken.common.pojo.request.SolutionMeasuresSaveRequest; +import com.nflg.mobilebroken.common.pojo.vo.SolutionMeasuresVO; +import com.nflg.mobilebroken.repository.entity.TicketSolution; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +public interface ITicketSolutionService extends IService { + + List getSolutionMeasures(Integer ticketId); + + void saveSolutionMeasures(SolutionMeasuresSaveRequest request); +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/AdminUserServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/AdminUserServiceImpl.java index a5a0bae2..5a0146af 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/AdminUserServiceImpl.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/AdminUserServiceImpl.java @@ -1,6 +1,7 @@ package com.nflg.mobilebroken.repository.service.impl; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -339,6 +340,11 @@ public class AdminUserServiceImpl extends ServiceImpl getCQMIds() { + return baseMapper.getTickerMangagers(ListUtil.of(Constant.DICTIONARY_TYPE_TITLE_CQM)); + } + private String getDepartmentName(Long departmentId) { TBaseDepartment department = departmentService.lambdaQuery() .eq(TBaseDepartment::getId, departmentId) diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/DictionaryItemServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/DictionaryItemServiceImpl.java index 79246cc6..244ea2e9 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/DictionaryItemServiceImpl.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/DictionaryItemServiceImpl.java @@ -130,4 +130,9 @@ public class DictionaryItemServiceImpl extends ServiceImpl getListByDictionaryCode(String code) { + return baseMapper.getListByDictionaryCode(code); + } } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketEvaluateServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketEvaluateServiceImpl.java index d3404dd2..48c28576 100644 --- a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketEvaluateServiceImpl.java +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketEvaluateServiceImpl.java @@ -31,7 +31,7 @@ public class TicketEvaluateServiceImpl extends ServiceImpl impleme @Resource private IFileUploadRecordService fileUploadRecordService; + @Resource + private ITicketSolutionAuditStateService ticketSolutionAuditStateService; + @Override public Ticket add(TicketAddRequest request, Integer userId) { Ticket lastTicket=lambdaQuery() @@ -63,6 +63,7 @@ public class TicketServiceImpl extends ServiceImpl impleme Ticket ticket = new Ticket() .setNo(no) .setDeviceNo(request.getDeviceNo()) + .setDeviceAddress(request.getDeviceAddress()) .setComponent(request.getComponent()) .setUseTime(request.getUseTime()) .setTitle(request.getTitle()) @@ -204,28 +205,27 @@ public class TicketServiceImpl extends ServiceImpl impleme return ticket; } - @Override - public Ticket closeTicket(TicketCloseRequest request) { - Ticket ticket = getById(request.getTicketId()); - VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单"); - VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState())) - .throwMessage("非处理完成状态不允许关闭"); - VUtils.trueThrowBusinessError(!ticketEvaluateService.lambdaQuery() - .eq(TicketEvaluate::getTicketId, request.getTicketId()) - .exists()) - .throwMessage("工单尚未评价,不能关闭"); - List tickerMangagers = adminUserService.getTickerMangagers(); - tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList())); - VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId()))) - .throwMessage("你无权关闭工单"); - ticket.setState(TicketState.Closed.getState()); - ticket.setSolution(request.getSolution()); - ticket.setSolutionAttachments(StrUtil.join(",", request.getAttachments())); - ticket.setSolveTime(LocalDateTime.now()); - ticket.setCurrentHandle(AdminUserUtil.getUserId()); - updateById(ticket); - return ticket; - } +// @Override +// public Ticket closeTicket(TicketCloseRequest request) { +// Ticket ticket = getById(request.getTicketId()); +// VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("未找到工单"); +// VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState())) +// .throwMessage("非处理完成状态不允许关闭"); +// VUtils.trueThrowBusinessError(!ticketEvaluateService.lambdaQuery() +// .eq(TicketEvaluate::getTicketId, request.getTicketId()) +// .exists()) +// .throwMessage("工单尚未评价,不能关闭"); +// List tickerMangagers = adminUserService.getTickerMangagers(); +// tickerMangagers.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList())); +// VUtils.trueThrowBusinessError(tickerMangagers.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId()))) +// .throwMessage("你无权关闭工单"); +// ticket.setState(TicketState.Closed.getState()); +// ticket.setReason(request.getSolution()); +// ticket.setSolveTime(LocalDateTime.now()); +// ticket.setCurrentHandle(AdminUserUtil.getUserId()); +// updateById(ticket); +// return ticket; +// } @Override public List exportSearch(AdminTicketSearchRequest request) { @@ -346,4 +346,28 @@ public class TicketServiceImpl extends ServiceImpl impleme updateById(ticket); return ticket; } + + public boolean close(Ticket ticket){ + if (!Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState())){ + return false; + } + if (!ticketEvaluateService.lambdaQuery() + .eq(TicketEvaluate::getTicketId, ticket.getId()) + .exists()){ + return false; + } + if (!ticketSolutionAuditStateService.lambdaQuery().eq(TicketSolutionAuditState::getTicketId, ticket.getId()).exists()) { + return false; + } + if (ticketSolutionAuditStateService.existsNotPass(ticket.getId())){ + return false; + } + return lambdaUpdate() + .set(Ticket::getState, TicketState.Closed.getState()) + .set(Ticket::getSolveTime, LocalDateTime.now()) + .set(Ticket::getUpdateTime, LocalDateTime.now()) + .eq(Ticket::getId, ticket.getId()) + .eq(Ticket::getState, TicketState.ProcessingCompleted.getState()) + .update(); + } } diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditServiceImpl.java new file mode 100644 index 00000000..3f2cccc6 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditServiceImpl.java @@ -0,0 +1,80 @@ +package com.nflg.mobilebroken.repository.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nflg.mobilebroken.common.constant.Constant; +import com.nflg.mobilebroken.common.pojo.request.SolutionReviewDepartmentSaveRequest; +import com.nflg.mobilebroken.common.pojo.vo.SolutionReviewDepartmentVO; +import com.nflg.mobilebroken.repository.entity.DictionaryItem; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAudit; +import com.nflg.mobilebroken.repository.mapper.TicketSolutionAuditMapper; +import com.nflg.mobilebroken.repository.service.IDictionaryItemService; +import com.nflg.mobilebroken.repository.service.ITicketSolutionAuditService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Service +public class TicketSolutionAuditServiceImpl extends ServiceImpl implements ITicketSolutionAuditService { + + @Resource + private IDictionaryItemService dictionaryItemService; + + @Override + public List getByTicket(Integer ticketId) { + List items=dictionaryItemService.getListByDictionaryCode(Constant.DICTIONARY_SOLUTION_REVIEW_DEPARTMENT); + List vos=baseMapper.getByTicket(ticketId); + items.forEach(item->{ + if (vos.stream().noneMatch(vo->vo.getDeptName().equals(item.getName()))){ + SolutionReviewDepartmentVO vo=new SolutionReviewDepartmentVO(); + vo.setDeptName(item.getName()); + vos.add(vo); + } + }); + return vos; + } + + @Transactional + @Override + public void saveSolutionReviewDepartment(SolutionReviewDepartmentSaveRequest request) { + remove(new LambdaQueryWrapper() + .eq(TicketSolutionAudit::getTicketId,request.getTicketId()) + .notIn(TicketSolutionAudit::getDeptName,request.getDepartments().stream().map(SolutionReviewDepartmentVO::getDeptName).collect(Collectors.toList()))); + List forAdd=new ArrayList<>(); + List forUpdate=new ArrayList<>(); + request.getDepartments().forEach(detp->{ + TicketSolutionAudit audit=new TicketSolutionAudit() + .setTicketId(request.getTicketId()) + .setDeptName(detp.getDeptName()) + .setUserId(detp.getUserId()); + if (Objects.isNull(detp.getId())){ + audit.setCreateTime(LocalDateTime.now()); + forAdd.add(audit); + }else { + audit.setId(detp.getId()); + forUpdate.add(audit); + } + }); + if (CollectionUtil.isNotEmpty(forAdd)){ + saveBatch(forAdd); + } + if (CollectionUtil.isNotEmpty(forUpdate)){ + updateBatchById(forUpdate); + } + } +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditStateServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditStateServiceImpl.java new file mode 100644 index 00000000..9ada773b --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionAuditStateServiceImpl.java @@ -0,0 +1,24 @@ +package com.nflg.mobilebroken.repository.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nflg.mobilebroken.repository.entity.TicketSolutionAuditState; +import com.nflg.mobilebroken.repository.mapper.TicketSolutionAuditStateMapper; +import com.nflg.mobilebroken.repository.service.ITicketSolutionAuditStateService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Service +public class TicketSolutionAuditStateServiceImpl extends ServiceImpl implements ITicketSolutionAuditStateService { + + @Override + public boolean existsNotPass(Integer id) { + return baseMapper.existsNotPass(id); + } +} diff --git a/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionServiceImpl.java b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionServiceImpl.java new file mode 100644 index 00000000..aa09ea00 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/java/com/nflg/mobilebroken/repository/service/impl/TicketSolutionServiceImpl.java @@ -0,0 +1,148 @@ +package com.nflg.mobilebroken.repository.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nflg.mobilebroken.common.constant.Constant; +import com.nflg.mobilebroken.common.constant.TicketState; +import com.nflg.mobilebroken.common.pojo.request.SolutionMeasuresSaveRequest; +import com.nflg.mobilebroken.common.pojo.vo.SolutionMeasuresItemVO; +import com.nflg.mobilebroken.common.pojo.vo.SolutionMeasuresVO; +import com.nflg.mobilebroken.common.util.AdminUserUtil; +import com.nflg.mobilebroken.common.util.VUtils; +import com.nflg.mobilebroken.repository.entity.DictionaryItem; +import com.nflg.mobilebroken.repository.entity.Ticket; +import com.nflg.mobilebroken.repository.entity.TicketSolution; +import com.nflg.mobilebroken.repository.mapper.TicketSolutionMapper; +import com.nflg.mobilebroken.repository.service.IAdminUserService; +import com.nflg.mobilebroken.repository.service.IDictionaryItemService; +import com.nflg.mobilebroken.repository.service.ITicketService; +import com.nflg.mobilebroken.repository.service.ITicketSolutionService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +/** + *

+ * 服务实现类 + *

+ * + * @author 代码生成器生成 + * @since 2025 + */ +@Service +public class TicketSolutionServiceImpl extends ServiceImpl implements ITicketSolutionService { + + @Resource + private ITicketService ticketService; + + @Resource + private IDictionaryItemService dictionaryItemService; + + @Resource + private IAdminUserService adminUserService; + + @Override + public List getSolutionMeasures(Integer ticketId) { + Ticket ticket = ticketService.getById(ticketId); + VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); + List initialNames= new ArrayList<>(); + if (Objects.equals(ticket.getState(), TicketState.Processing.getState())) { + List items = dictionaryItemService.getListByDictionaryCode(Constant.DICTIONARY_SOLUTION_MEASURES); + initialNames=items.stream().map(DictionaryItem::getValue).collect(Collectors.toList()); + } + List solutions = lambdaQuery().eq(TicketSolution::getTicketId, ticketId).orderByAsc(TicketSolution::getId).list(); + Map> groupedSolutions = solutions.stream().collect(Collectors.groupingBy(TicketSolution::getDictionaryName, LinkedHashMap::new, Collectors.toList())); + if (CollectionUtil.isEmpty(groupedSolutions)) { + return initialNames.stream().map(ticketSolutions -> new SolutionMeasuresVO() + .setName(ticketSolutions) + .setItems(Collections.emptyList())) + .collect(Collectors.toList()); + } else if (CollectionUtil.isEmpty(initialNames)) { + return groupedSolutions.entrySet().stream().map(ks -> new SolutionMeasuresVO() + .setName(ks.getKey()) + .setItems(ks.getValue().stream().map(v -> new SolutionMeasuresItemVO() + .setName(v.getDictionaryName()) + .setSuperintendent(v.getSuperintendent()) + .setScheduleDate(v.getScheduleDate()) + .setConfirmedDate(v.getConfirmedDate()) + .setRemark(v.getRemark()) + .setCreateUserId(v.getCreateUserid())).collect(Collectors.toList()) + )).collect(Collectors.toList()); + } else { + List vos = new ArrayList<>(); + initialNames.forEach(name -> { + List values = groupedSolutions.get(name); + if (CollectionUtil.isEmpty(values)) { + vos.add(new SolutionMeasuresVO().setName(name).setItems(Collections.emptyList())); + } else { + vos.add(new SolutionMeasuresVO() + .setName(name) + .setItems(values.stream().map(v -> new SolutionMeasuresItemVO() + .setName(v.getDictionaryName()) + .setSuperintendent(v.getSuperintendent()) + .setScheduleDate(v.getScheduleDate()) + .setConfirmedDate(v.getConfirmedDate()) + .setRemark(v.getRemark()) + .setCreateUserId(v.getCreateUserid())).collect(Collectors.toList()) + ) + ); + } + }); + return vos; + } + } + + @Transactional + @Override + public void saveSolutionMeasures(SolutionMeasuresSaveRequest request) { + Ticket ticket=ticketService.getById(request.getTicketId()); + VUtils.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); + VUtils.trueThrowBusinessError(!Objects.equals(ticket.getState(), TicketState.Processing.getState()) + && !Objects.equals(ticket.getState(), TicketState.ProcessingCompleted.getState())) + .throwMessage("当前工单状态不允许修改解决方案"); + List cqmIds=adminUserService.getCQMIds(); + cqmIds.addAll(Arrays.stream(ticket.getHandle().split(",")).map(Integer::parseInt).collect(Collectors.toList())); + VUtils.trueThrowBusinessError(cqmIds.stream().noneMatch(uid -> Objects.equals(uid, AdminUserUtil.getUserId()))) + .throwMessage("无权修改解决方案"); + ticketService.lambdaUpdate() + .set(Ticket::getReason, request.getReason()) + .eq(Ticket::getId, request.getTicketId()) + .update(); + baseMapper.delete(new LambdaQueryWrapper() + .eq(TicketSolution::getTicketId,request.getTicketId()) + .notIn(TicketSolution::getId, request.getSolutionMeasures().stream().flatMap(s -> s.getItems().stream()).map(SolutionMeasuresItemVO::getId).collect(Collectors.toList())) + ); + List forAdd=new ArrayList<>(); + List forUpdate=new ArrayList<>(); + for (SolutionMeasuresVO solutionMeasuresVO : request.getSolutionMeasures()) { + for (SolutionMeasuresItemVO solutionMeasuresItemVO : solutionMeasuresVO.getItems()){ + TicketSolution solution=new TicketSolution() + .setTicketId(request.getTicketId()) + .setDictionaryId(solutionMeasuresVO.getId()) + .setDictionaryName(solutionMeasuresVO.getName()) + .setSuperintendent(solutionMeasuresItemVO.getSuperintendent()) + .setScheduleDate(solutionMeasuresItemVO.getScheduleDate()) + .setConfirmedDate(solutionMeasuresItemVO.getConfirmedDate()); + if (Objects.isNull(solutionMeasuresItemVO.getId())){ + solution.setCreateUserid(AdminUserUtil.getUserId()) + .setCreateTime(LocalDateTime.now()); + forAdd.add(solution); + }else { + solution.setId(solutionMeasuresItemVO.getId()); + forUpdate.add(solution); + } + } + } + if (CollectionUtil.isNotEmpty(forAdd)){ + saveBatch(forAdd); + } + if (CollectionUtil.isNotEmpty(forUpdate)){ + updateBatchById(forUpdate); + } + } +} diff --git a/nflg-mobilebroken-repository/src/main/resources/mapper/DictionaryItemMapper.xml b/nflg-mobilebroken-repository/src/main/resources/mapper/DictionaryItemMapper.xml index 6ceca46f..0b1cf3fc 100644 --- a/nflg-mobilebroken-repository/src/main/resources/mapper/DictionaryItemMapper.xml +++ b/nflg-mobilebroken-repository/src/main/resources/mapper/DictionaryItemMapper.xml @@ -8,4 +8,12 @@ INNER JOIN dictionary_item di ON d.id=di.dictionary_id WHERE d.`code`=#{dictionaryCode} AND di.`code`=#{itemCode} + + diff --git a/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditMapper.xml b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditMapper.xml new file mode 100644 index 00000000..8d7ce0d1 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditMapper.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditStateMapper.xml b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditStateMapper.xml new file mode 100644 index 00000000..8edba620 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionAuditStateMapper.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionMapper.xml b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionMapper.xml new file mode 100644 index 00000000..d0d3f4d3 --- /dev/null +++ b/nflg-mobilebroken-repository/src/main/resources/mapper/TicketSolutionMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nflg-mobilebroken-repository/src/test/java/com/nflg/mobilebroken/repository/CodeGenerator.java b/nflg-mobilebroken-repository/src/test/java/com/nflg/mobilebroken/repository/CodeGenerator.java index 51943365..a755b3fd 100644 --- a/nflg-mobilebroken-repository/src/test/java/com/nflg/mobilebroken/repository/CodeGenerator.java +++ b/nflg-mobilebroken-repository/src/test/java/com/nflg/mobilebroken/repository/CodeGenerator.java @@ -33,7 +33,7 @@ public class CodeGenerator { , Paths.get(System.getProperty("user.dir")) + "/src/main/resources/mapper")) ) .strategyConfig(builder -> { - builder.addInclude("ticket_favorites") //只生成指定表 + builder.addInclude("ticket_solution_audit,ticket_solution_audit_state") //只生成指定表 .entityBuilder() .enableLombok() .enableChainModel()