Commit 12a21868 by HlQ

[add]

1.添加点位设计功能
2.添加请求日志功能
3.微信 openid 绑定使用 Spring Event
4.添加机器人推送功能
5.发货管理添加批量导入功能
1 parent d0b75b48
Showing 50 changed files with 1784 additions and 117 deletions
...@@ -13,22 +13,34 @@ ...@@ -13,22 +13,34 @@
<artifactId>Vion-DevOps</artifactId> <artifactId>Vion-DevOps</artifactId>
<version>1</version> <version>1</version>
<properties>
<pg.version>42.6.0</pg.version>
<sqlserver.version>12.2.0.jre8</sqlserver.version>
<lombok.version>1.18.30</lombok.version>
<hutool.version>5.8.25</hutool.version>
<mapstruct-plus.version>1.3.5</mapstruct-plus.version>
<mp.version>3.5.5</mp.version>
<mp-join.version>1.4.7.2</mp-join.version>
<wx-mp.version>4.6.0</wx-mp.version>
<sa-token.verion>1.37.0</sa-token.verion>
<myexcel.version>4.3.3</myexcel.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<version>42.6.0</version> <version>${pg.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.microsoft.sqlserver</groupId> <groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId> <artifactId>mssql-jdbc</artifactId>
<version>12.2.0.jre8</version> <version>${sqlserver.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.30</version> <version>${lombok.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
...@@ -37,33 +49,37 @@ ...@@ -37,33 +49,37 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-all</artifactId>
<version>5.8.24</version> <version>${hutool.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.github.linpeilie</groupId> <groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId> <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.3.5</version> <version>${mapstruct-plus.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.baomidou</groupId> <groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId> <artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4</version> <version>${mp.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.yulichang</groupId> <groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join-boot-starter</artifactId> <artifactId>mybatis-plus-join-boot-starter</artifactId>
<version>1.4.7.2</version> <version>${mp-join.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>wx-java-mp-spring-boot-starter</artifactId> <artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.5.0</version> <version>${wx-mp.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
...@@ -72,22 +88,17 @@ ...@@ -72,22 +88,17 @@
<dependency> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId> <artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.37.0</version> <version>${sa-token.verion}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId> <artifactId>sa-token-redis-jackson</artifactId>
<version>1.37.0</version> <version>${sa-token.verion}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.liaochong</groupId> <groupId>com.github.liaochong</groupId>
<artifactId>myexcel</artifactId> <artifactId>myexcel</artifactId>
<version>4.3.3</version> <version>${myexcel.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>4.2.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
......
package vion.advice;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author HlQ
* @date 2024/1/17
*/
@Component
@RequiredArgsConstructor
@Aspect
@Slf4j
public class LogAspect {
private final ObjectMapper objectMapper;
@Pointcut("execution(* vion.controller.*.*(..))")
public void logPointcut() {
}
@Before("logPointcut()")
public void doBefore(JoinPoint joinPoint) throws JsonProcessingException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjUtil.isNull(attributes)) {
return;
}
HttpServletRequest request = attributes.getRequest();
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
String requestId = (String) request.getAttribute("requestId");
MDC.put("requestId", requestId);
log.info("Request URL:{}, Method:{}, IP:{}, Arguments:{}",
request.getRequestURI(),
request.getMethod(),
ServletUtil.getClientIP(request),
objectMapper.writeValueAsString(request.getParameterMap())
);
}
@AfterReturning(pointcut = "logPointcut()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) throws JsonProcessingException {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ObjUtil.isNull(attributes)) {
return;
}
HttpServletRequest request = attributes.getRequest();
// Calculate response time
long startTime = (Long) request.getAttribute("startTime");
long responseTime = System.currentTimeMillis() - startTime;
String resStr = objectMapper.writeValueAsString(result);
if (resStr.length() > 1000) {
resStr = resStr.substring(0, 1000);
}
log.info("Response time: {} ms. Return value: {}",
responseTime,
resStr);
MDC.remove("requestId");
}
}
...@@ -20,7 +20,7 @@ public class UserNameConverter implements CustomWriteConverter<Long, String> { ...@@ -20,7 +20,7 @@ public class UserNameConverter implements CustomWriteConverter<Long, String> {
@Override @Override
public String convert(Long originalData, CustomWriteContext customWriteContext) { public String convert(Long originalData, CustomWriteContext customWriteContext) {
return Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:" + originalData))) return Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:id:" + originalData)))
.map(User::getUsername) .map(User::getUsername)
.orElse("未知"); .orElse("未知");
} }
......
...@@ -9,6 +9,8 @@ import vion.dto.DeliveryRecordDTO; ...@@ -9,6 +9,8 @@ import vion.dto.DeliveryRecordDTO;
import vion.service.IDeliveryRecordService; import vion.service.IDeliveryRecordService;
import vion.vo.DeliveryRecordVO; import vion.vo.DeliveryRecordVO;
import java.util.List;
/** /**
* 发货记录管理 * 发货记录管理
*/ */
...@@ -38,6 +40,12 @@ public class DeliveryRecordController { ...@@ -38,6 +40,12 @@ public class DeliveryRecordController {
return deliveryRecordService.save(dto); return deliveryRecordService.save(dto);
} }
@PostMapping("/deliveryRecord/batch")
@SaCheckPermission(value = "deliveryRecord:save", orRole = "admin")
public String save(@RequestBody List<DeliveryRecordDTO> dto) {
return deliveryRecordService.saveBatch(dto);
}
@PostMapping("/deliveryRecord/{id}") @PostMapping("/deliveryRecord/{id}")
@SaCheckPermission(value = "deliveryRecord:edit", orRole = "admin") @SaCheckPermission(value = "deliveryRecord:edit", orRole = "admin")
public String updateById(@PathVariable Long id, DeliveryRecordDTO dto) { public String updateById(@PathVariable Long id, DeliveryRecordDTO dto) {
......
package vion.controller; package vion.controller;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
...@@ -35,6 +36,11 @@ public class FileController { ...@@ -35,6 +36,11 @@ public class FileController {
@GetMapping("/files") @GetMapping("/files")
public Page<FileInfo> getFiles(FileInfoDTO data) { public Page<FileInfo> getFiles(FileInfoDTO data) {
return fileService.lambdaQuery(converter.convert(data, new FileInfo())) return fileService.lambdaQuery(converter.convert(data, new FileInfo()))
.eq(ObjUtil.isNotNull(data.getStoreId()), FileInfo::getStoreId, data.getStoreId())
.eq(ObjUtil.isNotNull(data.getSourceId()), FileInfo::getSourceId, data.getSourceId())
.eq(ObjUtil.isNotNull(data.getContractId()), FileInfo::getContractId, data.getContractId())
.eq(ObjUtil.isNotNull(data.getSourceType()), FileInfo::getSourceType, data.getSourceType())
.in(CollUtil.isNotEmpty(data.getSourceTypeList()), FileInfo::getSourceType, data.getSourceTypeList())
.page(Page.of(data.getPageNum(), data.getPageSize())); .page(Page.of(data.getPageNum(), data.getPageSize()));
} }
...@@ -50,21 +56,36 @@ public class FileController { ...@@ -50,21 +56,36 @@ public class FileController {
} }
@PostMapping("/upLoadFile") @PostMapping("/upLoadFile")
public String uploadFile(Long storeId, Long sourceId, FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) { public String uploadFile(FileInfo fileInfo, @RequestParam(name = "file") MultipartFile infile) {
try { try {
//上传url地址 //上传url地址
String filename = infile.getOriginalFilename() + "_" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN); String orgName = infile.getOriginalFilename();
// String path = fileurl + FileUtil.FILE_SEPARATOR + storeId + FileUtil.FILE_SEPARATOR + sourceId + FileUtil.FILE_SEPARATOR + filename; String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
// todo 路径未确定
String path = fileUrl + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
infile.transferTo(file); infile.transferTo(file);
String sha256 = SecureUtil.sha256(file).toUpperCase(); FileInfo tempFileInfo = new FileInfo();
String extName = FileUtil.extName(file); tempFileInfo.setStoreId(fileInfo.getStoreId());
tempFileInfo.setSourceId(fileInfo.getSourceId());
tempFileInfo.setSourceType(fileInfo.getSourceType());
tempFileInfo.setName(filename);
tempFileInfo.setUrl(path);
tempFileInfo.setType(FileUtil.extName(file));
tempFileInfo.setSha256(SecureUtil.sha256(file).toUpperCase());
tempFileInfo.setUploader(fileInfo.getUploader());
if (fileService.save(tempFileInfo)) {
return path; return path;
} else {
return "文件保存失败";
}
} catch (IOException e) { } catch (IOException e) {
log.error("上传文件失败", e); log.error("上传文件失败", e);
} }
return "success"; return "文件保存成功";
} }
@PostMapping("/uploadFile1") @PostMapping("/uploadFile1")
......
package vion.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.liaochong.myexcel.core.DefaultExcelBuilder;
import com.github.liaochong.myexcel.core.watermark.Watermark;
import com.github.liaochong.myexcel.utils.AttachmentExportUtil;
import com.github.liaochong.myexcel.utils.WatermarkUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.*;
import vion.dto.PointInfoDTO;
import vion.model.RejectInfo;
import vion.service.IPointInfoService;
import vion.third.WechatMod;
import vion.vo.PointInfoVO;
import vion.vo.UserVO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.Date;
import java.util.List;
/**
* 点位管理
*
* @author HlQ
* @date 2024/1/8
*/
@RestController
@RequestMapping("/api/point")
@RequiredArgsConstructor
@Slf4j
public class PointDesignController {
private final IPointInfoService pointInfoService;
private final WechatMod wechatMod;
@PostMapping("/frontSubmit")
public Object frontSubmit(PointInfoDTO dto) {
return pointInfoService.frontSubmit(dto);
}
@PostMapping
@SaCheckPermission(value = "point:save", orRole = "admin")
public Object save(PointInfoDTO dto) {
return pointInfoService.save(dto);
}
@PostMapping("/{id}")
@SaCheckPermission(value = "point:edit", orRole = "admin")
public String updById(@PathVariable Long id, PointInfoDTO dto) {
return pointInfoService.upd(id, null, dto);
}
@PostMapping("/upd/{uuid}")
public String updById(@PathVariable String uuid, PointInfoDTO dto) {
return pointInfoService.upd(null, uuid, dto);
}
@GetMapping
@SaCheckPermission(value = "point:list", orRole = "admin")
public Page<PointInfoVO> list(PointInfoDTO dto) {
return pointInfoService.list(dto);
}
@GetMapping("/{id}")
@SaCheckPermission(value = "point:query", orRole = "admin")
public PointInfoVO getPointById(@PathVariable Long id) {
return pointInfoService.getPointByDetail(id, null);
}
@GetMapping("/get/{uuid}")
public PointInfoVO getPointByUuid(@PathVariable String uuid) {
return pointInfoService.getPointByDetail(null, uuid);
}
@DeleteMapping("/{id}")
@SaCheckPermission(value = "point:remove", orRole = "admin")
public String delById(@PathVariable Long id) {
return pointInfoService.delById(id);
}
@PostMapping("/client/reject")
public String clientReject(@RequestBody RejectInfo dto) {
return pointInfoService.reject(dto, "client");
}
@PostMapping("/reject")
@SaCheckPermission(value = "point:reject", orRole = "admin")
public String reject(@RequestBody RejectInfo dto) {
return pointInfoService.reject(dto, null);
}
@GetMapping("/reject/{pointId}")
@SaCheckPermission(value = "point:reject:list", orRole = "admin")
public Page<RejectInfo> rejectInfoList(@PathVariable Long pointId, RejectInfo dto) {
return pointInfoService.rejectInfoList(pointId, dto);
}
@GetMapping("/reject/uuid/{uuid}")
public Page<RejectInfo> rejectInfoPage(@PathVariable String uuid, RejectInfo dto) {
return pointInfoService.rejectInfoList(uuid, dto);
}
@GetMapping("/desgin/push")
@SaCheckPermission(value = "point:design:push", orRole = "admin")
public Object designPush(Long pointId, String pushType) {
return pointInfoService.designPush(pointId, null, pushType);
}
@GetMapping("/export")
@SaCheckPermission(value = "point:export", orRole = "admin")
public void pointExport(PointInfoDTO dto, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
dto.setPageSize(9999);
Page<PointInfoVO> voPage = pointInfoService.list(dto);
voPage.getRecords().forEach(v -> v.setPointUrl("https://yunwei.vionyun.com:8443/wap/setup-device?uuid=" + v.getUuid()));
try (DefaultExcelBuilder<PointInfoVO> pointInfoVODefaultExcelBuilder = DefaultExcelBuilder.of(PointInfoVO.class)) {
Workbook workbook = pointInfoVODefaultExcelBuilder.build(voPage.getRecords());
// 水印添加指定字体,并在服务器上安装 SimSun 字体,解决中文字体变成方块的问题
Watermark watermark = new Watermark();
watermark.setText(user.getUsername() + "-" + user.getPhone());
watermark.setFont(new Font("SimSun", Font.PLAIN, 16));
WatermarkUtil.addWatermark(workbook, watermark);
AttachmentExportUtil.export(workbook, StrUtil.format("点位设计列表_{}", DateUtil.formatDateTime(new Date())), response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@PostMapping("/install/submit/{uuid}")
public String installSubmit(@PathVariable String uuid, @RequestBody List<String> deviceList) {
return pointInfoService.installSubmit(uuid, deviceList);
}
@GetMapping("/getBindQRCode")
public String getBindQRCode(String uuid) {
return wechatMod.genBindOpenidQRCode(uuid);
}
@GetMapping("/getBindOpenid")
public Object genBindOpenidQRCode(String uuid, String code) {
return pointInfoService.bindOpenid(uuid, code);
}
}
...@@ -82,7 +82,7 @@ public class TaskController { ...@@ -82,7 +82,7 @@ public class TaskController {
@GetMapping("/task/export") @GetMapping("/task/export")
@SaCheckPermission(value = "task:export", orRole = "admin") @SaCheckPermission(value = "task:export", orRole = "admin")
public void defaultBuild(TaskDTO data, HttpServletResponse response) { public void taskExport(TaskDTO data, HttpServletResponse response) {
UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser"); UserVO user = (UserVO) StpUtil.getTokenSession().get("curLoginUser");
data.setPageSize(9999); data.setPageSize(9999);
Page<TaskVO> voPage = taskService.getTaskList(data); Page<TaskVO> voPage = taskService.getTaskList(data);
......
...@@ -6,15 +6,11 @@ import io.github.linpeilie.Converter; ...@@ -6,15 +6,11 @@ import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import vion.third.WechatMod;
import vion.dto.TaskTempDTO; import vion.dto.TaskTempDTO;
import vion.model.TaskTemp; import vion.model.TaskTemp;
import vion.service.ITaskTempService; import vion.service.ITaskTempService;
import vion.vo.TaskTempVO; import vion.vo.TaskTempVO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/** /**
* 预工单 * 预工单
*/ */
...@@ -25,7 +21,6 @@ import java.io.IOException; ...@@ -25,7 +21,6 @@ import java.io.IOException;
public class TaskTempController { public class TaskTempController {
private final ITaskTempService taskTempService; private final ITaskTempService taskTempService;
private final WechatMod wechatMod;
private final Converter converter; private final Converter converter;
@GetMapping("/taskTemps") @GetMapping("/taskTemps")
...@@ -46,17 +41,6 @@ public class TaskTempController { ...@@ -46,17 +41,6 @@ public class TaskTempController {
return taskTempService.saveOrUpdTaskTemp(data); return taskTempService.saveOrUpdTaskTemp(data);
} }
@GetMapping("/taskTemp/wechatCallback")
public Object wechatCallback(String code, HttpServletResponse res) throws IOException {
Object obj = wechatMod.wechatCallback(code);
if (obj instanceof String) {
res.sendRedirect("https://yunwei.vionyun.com/wap/?openid=" + obj);
} else {
return obj;
}
return "success";
}
@PostMapping("/taskTemp/{id}") @PostMapping("/taskTemp/{id}")
@SaCheckPermission(value = "taskTemp:edit", orRole = "admin") @SaCheckPermission(value = "taskTemp:edit", orRole = "admin")
public String upd(@PathVariable(name = "id") Long id, TaskTempDTO data) { public String upd(@PathVariable(name = "id") Long id, TaskTempDTO data) {
......
...@@ -4,24 +4,24 @@ import cn.dev33.satoken.annotation.SaCheckPermission; ...@@ -4,24 +4,24 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.github.linpeilie.Converter; import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import vion.dto.DingDTO; import vion.dto.DingDTO;
import vion.dto.UserDTO; import vion.dto.UserDTO;
import vion.model.RUserRole; import vion.model.RUserRole;
import vion.model.Role; import vion.model.Role;
import vion.model.TaskTemp;
import vion.model.User; import vion.model.User;
import vion.service.IRUserRoleService; import vion.service.IRUserRoleService;
import vion.service.IRoleService; import vion.service.IRoleService;
import vion.service.ITaskTempService;
import vion.service.IUserService; import vion.service.IUserService;
import vion.third.DingMod; import vion.third.DingMod;
import vion.third.WechatMod; import vion.third.WechatMod;
...@@ -29,7 +29,9 @@ import vion.vo.RoleVO; ...@@ -29,7 +29,9 @@ import vion.vo.RoleVO;
import vion.vo.UserVO; import vion.vo.UserVO;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -40,7 +42,6 @@ import java.util.stream.Collectors; ...@@ -40,7 +42,6 @@ import java.util.stream.Collectors;
public class UserController { public class UserController {
private final IUserService userService; private final IUserService userService;
private final ITaskTempService taskTempService;
private final IRUserRoleService userRoleService; private final IRUserRoleService userRoleService;
private final IRoleService roleService; private final IRoleService roleService;
private final Converter converter; private final Converter converter;
...@@ -106,14 +107,36 @@ public class UserController { ...@@ -106,14 +107,36 @@ public class UserController {
return "注销成功"; return "注销成功";
} }
@GetMapping("/wechat/callback") /**
public Object wechatCallback(String code, Long taskTempId) { * 用于微信公众号自定义菜单里填写的回调地址
Object obj = wechatMod.wechatCallback(code); *
if (obj instanceof String) { * @param code 授权码
return taskTempService.lambdaUpdate().set(TaskTemp::getOpenid, obj).eq(TaskTemp::getId, taskTempId).update(new TaskTemp()) ? new ModelAndView("weChatNeedAttention") : new ModelAndView("weChatError"); * @param active 前端标识,根据此标识跳转到不同的页面
* @param res
* @return java.lang.Object
*/
@GetMapping("/wechatCallback")
public Object wechatCallback(String code, Integer active, HttpServletResponse res) throws IOException {
Object obj = wechatMod.getOpenid(code);
if (obj instanceof Map) {
Map<String, String> map = (Map<String, String>) obj;
res.sendRedirect(StrUtil.format("https://yunwei.vionyun.com/wap?openid={}&nickname={}&active={}", map.get("openid"), URLUtil.encode(map.get("nickname")), active));
} else { } else {
return obj; return obj;
} }
return "success";
}
@GetMapping("/getQRCode")
public String getCallbackQRCode(Long id, Integer flag) {
Assert.notNull(id, "id 不能为空");
Assert.notNull(flag, "flag 不能为空");
return wechatMod.genCallbackQRCode(id, flag);
}
@GetMapping("/getFollowingOpenid")
public Object getOpenid(Long id, Integer flag, String code) {
return wechatMod.getFollowingOpenid(id, flag, code);
} }
} }
...@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component; ...@@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
import vion.model.Contract; import vion.model.Contract;
import vion.model.ContractPayment; import vion.model.ContractPayment;
import vion.model.Dictionary; import vion.model.Dictionary;
import vion.model.Payment;
import vion.service.*; import vion.service.*;
import java.math.BigDecimal; import java.math.BigDecimal;
...@@ -35,6 +36,7 @@ public class ContractRunner { ...@@ -35,6 +36,7 @@ public class ContractRunner {
private final IDictionaryService dictionaryService; private final IDictionaryService dictionaryService;
private final IContractPaymentService contractPaymentService; private final IContractPaymentService contractPaymentService;
private final IStoreService storeService; private final IStoreService storeService;
private final IPaymentService paymentService;
private final RedisTemplate redisTemplate; private final RedisTemplate redisTemplate;
@Scheduled(cron = "0 0 * * * *") @Scheduled(cron = "0 0 * * * *")
...@@ -122,8 +124,8 @@ public class ContractRunner { ...@@ -122,8 +124,8 @@ public class ContractRunner {
}); });
contractService.saveOrUpdateBatch(insOrUpdContractList, 500); contractService.saveOrUpdateBatch(insOrUpdContractList, 500);
List<ContractPayment> paymentList = contractPaymentService.list(); List<ContractPayment> existContractPaymentList = contractPaymentService.list();
Map<Long, Map<Integer, Long>> contractId2PaymentMap = paymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.toMap(ContractPayment::getPaymentType, ContractPayment::getId))); Map<Long, Map<Integer, Long>> contractId2PaymentMap = existContractPaymentList.stream().collect(Collectors.groupingBy(ContractPayment::getContractId, Collectors.toMap(ContractPayment::getPaymentType, ContractPayment::getId)));
// 合同付款比例 // 合同付款比例
List<ContractPayment> contractPaymentList = new ArrayList<>(); List<ContractPayment> contractPaymentList = new ArrayList<>();
...@@ -203,12 +205,15 @@ public class ContractRunner { ...@@ -203,12 +205,15 @@ public class ContractRunner {
} }
contractPaymentService.saveOrUpdateBatch(contractPaymentList); contractPaymentService.saveOrUpdateBatch(contractPaymentList);
List<Payment> paymentList = paymentService.list();
Map<String, BigDecimal> no2PaymentMap = paymentList.stream().collect(Collectors.groupingBy(Payment::getContractNo, Collectors.reducing(BigDecimal.ZERO, Payment::getPaymentAmount, BigDecimal::add)));
insOrUpdContractList.forEach(c -> { insOrUpdContractList.forEach(c -> {
String contractNo = c.getContractNo(); String contractNo = c.getContractNo();
Contract exist = contractService.lambdaQuery().eq(Contract::getContractNo, contractNo).one(); Contract exist = contractService.lambdaQuery().eq(Contract::getContractNo, contractNo).one();
Contract updDto = new Contract(); Contract updDto = new Contract();
updDto.setId(exist.getId()); updDto.setId(exist.getId());
updDto.setPaidAmount(exist.getPaidAmount()); updDto.setPaidAmount(no2PaymentMap.getOrDefault(contractNo, BigDecimal.ZERO));
contractPaymentService.calMoney(exist, updDto); contractPaymentService.calMoney(exist, updDto);
contractService.updateById(updDto); contractService.updateById(updDto);
}); });
......
...@@ -18,13 +18,27 @@ public class DeliveryRecordDTO extends BaseDTO { ...@@ -18,13 +18,27 @@ public class DeliveryRecordDTO extends BaseDTO {
*/ */
private String contractNo; private String contractNo;
/** /**
* 合同id * 合同id
*/ */
private Long contractId; private Long contractId;
/** /**
* 收货人
*/
private String consignee;
/**
* 收货地址
*/
private String address;
/**
* 收货电话
*/
private String phone;
/**
* 合同名称 * 合同名称
*/ */
private String contractName; private String contractName;
...@@ -48,6 +62,21 @@ public class DeliveryRecordDTO extends BaseDTO { ...@@ -48,6 +62,21 @@ public class DeliveryRecordDTO extends BaseDTO {
@DateTimeFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
private Date signDate; private Date signDate;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 发货清单
*/
private String shippingRemark;
private String remark; private String remark;
private MultipartFile[] files; private MultipartFile[] files;
......
...@@ -3,6 +3,8 @@ package vion.dto; ...@@ -3,6 +3,8 @@ package vion.dto;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.util.List;
@Getter @Getter
@Setter @Setter
public class FileInfoDTO extends BaseDTO { public class FileInfoDTO extends BaseDTO {
...@@ -13,6 +15,7 @@ public class FileInfoDTO extends BaseDTO { ...@@ -13,6 +15,7 @@ public class FileInfoDTO extends BaseDTO {
private String type; private String type;
/** 文件来源(1项目、2工单预处理,3工单操作,4巡检) */ /** 文件来源(1项目、2工单预处理,3工单操作,4巡检) */
private Integer sourceType; private Integer sourceType;
private List<Integer> sourceTypeList;
/** 文件来源id */ /** 文件来源id */
private Long sourceId; private Long sourceId;
/** 合同id */ /** 合同id */
......
package vion.dto;
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;
/**
* @author HlQ
* @date 2024/1/8
*/
@Getter
@Setter
public class PointInfoDTO extends BaseDTO {
private Long id;
/**
* 集团id
*/
private Long accountId;
/**
* 项目名称(用户填写的)
*/
private String projectName;
/**
* 联系人
*/
private String contact;
/**
* 手机号码
*/
private String phone;
/**
* 点位数量
*/
private Integer pointNum;
/**
* 发货状态
*/
private Integer shippingStatus;
/**
* 收货地址
*/
private String shippingAddress;
/**
* 收货联系人
*/
private String receivingContact;
/**
* 收货联系电话
*/
private String receivingPhone;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 状态
*/
private Integer status;
/**
* 合同编号
*/
private String contractNo;
/**
* 合同id
*/
private Long contractId;
/**
* 是否施工 0:不施工 1:施工
*/
private Integer isConstruct;
/**
* 施工地址
*/
private String constructAddress;
/**
* 施工联系人
*/
private String constructContact;
/**
* 施工联系电话
*/
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
private Integer invoiceType;
/**
* 发票抬头
*/
private String invoiceHeader;
/**
* 税号
*/
private String taxIdNum;
/**
* 单位地址
*/
private String invoiceAddress;
/**
* 单位电话
*/
private String invoicePhone;
/**
* 开户银行
*/
private String accountBank;
/**
* 银行卡号
*/
private String bankNumber;
/**
* 邮箱地址
*/
private String email;
/**
* 发票邮寄地址
*/
private String invoiceRecAddress;
/**
* 发票联系人
*/
private String invoiceContact;
/**
* 发票联系电话
*/
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
private String invoiceTrackingNumber;
/**
* 备注
*/
private String remake;
/**
* uuid
*/
private String uuid;
/**
* 施工方
*/
private String constructionSide;
/**
* 文件来源
*/
private Integer sourceType;
private MultipartFile[] files;
/** 客户上传合同文件 */
private MultipartFile contractFile;
/** 上传的合同范本 */
private MultipartFile contractTemplateFile;
/* 终版合同 */
private MultipartFile finalContractFile;
}
\ No newline at end of file \ No newline at end of file
package vion.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
/**
* @author HlQ
* @date 2024/1/16
*/
@Getter
@Setter
@Builder
public class WxDTO {
/**
* 微信openid
*/
private String openid;
/**
* 微信昵称
*/
private String nickname;
/**
* 单子的id
*/
private Long id;
/**
* flag 1:故障保修 2:点位设计
*/
private Integer flag;
}
package vion.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import vion.dto.WxDTO;
/**
* @author HlQ
* @date 2024/1/16
*/
@Getter
public class WxDTOEvent extends ApplicationEvent {
private final WxDTO wxDTO;
public WxDTOEvent(Object source, WxDTO dto) {
super(source);
this.wxDTO = dto;
}
}
package vion.event.listener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import vion.dto.WxDTO;
import vion.event.WxDTOEvent;
import vion.model.RPointWx;
import vion.model.TaskTemp;
import vion.service.IRPointWxService;
import vion.service.ITaskTempService;
/**
* @author HlQ
* @date 2024/1/16
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class WxDTOEventListener implements ApplicationListener<WxDTOEvent> {
private final ITaskTempService taskTempService;
private final IRPointWxService pointWxService;
@Override
public void onApplicationEvent(WxDTOEvent event) {
WxDTO wxDTO = event.getWxDTO();
Integer flag = wxDTO.getFlag();
String openid = wxDTO.getOpenid();
Long id = wxDTO.getId();
String nickname = wxDTO.getNickname();
if (flag == 1) {
updateTaskTemp(openid, id);
} else if (flag == 2) {
updatePointInfo(openid, nickname, id);
}
}
private void updateTaskTemp(String openid, Long id) {
taskTempService.lambdaUpdate()
.set(TaskTemp::getOpenid, openid)
.eq(TaskTemp::getId, id)
.update(new TaskTemp());
log.info("故障保修单子[id:{}]绑定openid成功!", id);
}
private void updatePointInfo(String openid, String nickname, Long id) {
RPointWx pointWx = new RPointWx();
pointWx.setPointId(id);
pointWx.setOpenid(openid);
pointWx.setWxName(nickname);
pointWxService.save(pointWx);
log.info("点位设计单子[id:{}]绑定openid成功!", id);
}
}
...@@ -18,9 +18,15 @@ public class InterceptorConfig implements WebMvcConfigurer { ...@@ -18,9 +18,15 @@ public class InterceptorConfig implements WebMvcConfigurer {
StpUtil.renewTimeout(3600L); StpUtil.renewTimeout(3600L);
})) }))
.addPathPatterns("/api/**") .addPathPatterns("/api/**")
.excludePathPatterns("/api/dictionarys")
.excludePathPatterns("/api/upLoadFile", "/api/ding/callback/**", "/api/wechat/**", "/error") .excludePathPatterns("/api/upLoadFile", "/api/ding/callback/**", "/api/wechat/**", "/error")
.excludePathPatterns("/api/order/sign/*") .excludePathPatterns("/api/order/sign/*")
.excludePathPatterns("/api/form/sign/*") .excludePathPatterns("/api/form/sign/*")
.excludePathPatterns("/api/taskTemp", "/api/taskTemp/wechatCallback"); .excludePathPatterns("/api/wechatCallback")
.excludePathPatterns("/api/taskTemp")
.excludePathPatterns("/api/point/frontSubmit")
.excludePathPatterns("/api/getQRCode", "/api/getFollowingOpenid", "/api/verifyScan")
.excludePathPatterns("/api/point/getBindQRCode", "/api/point/getBindOpenid")
.excludePathPatterns("/api/point/upd/{uuid}", "/api/point/get/{uuid}", "/api/point/install/submit/{uuid}", "/api/point/client/reject", "/api/point/reject/uuid/{uuid}");
} }
} }
package vion.interceptor;
import cn.hutool.core.util.IdUtil;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
public class RequestIdFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
httpServletRequest.setAttribute("requestId", IdUtil.fastSimpleUUID());
chain.doFilter(request, response);
}
}
\ No newline at end of file \ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.PointInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface PointInfoMapper extends MPJBaseMapper<PointInfo> {
}
\ No newline at end of file \ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RPointDevice;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface RPointDeviceMapper extends MPJBaseMapper<RPointDevice> {
}
\ No newline at end of file \ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RPointWx;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface RPointWxMapper extends MPJBaseMapper<RPointWx> {
}
\ No newline at end of file \ No newline at end of file
package vion.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import vion.model.RejectInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface RejectInfoMapper extends MPJBaseMapper<RejectInfo> {
}
\ No newline at end of file \ No newline at end of file
...@@ -34,6 +34,18 @@ public class DeliveryRecord { ...@@ -34,6 +34,18 @@ public class DeliveryRecord {
@TableField(value = "contract_id") @TableField(value = "contract_id")
private Long contractId; private Long contractId;
/** 收货人 */
@TableField(value = "consignee")
private String consignee;
/** 收货地址 */
@TableField(value = "address")
private String address;
/** 收货电话 */
@TableField(value = "phone")
private String phone;
/** /**
* 发货日期 * 发货日期
*/ */
...@@ -47,6 +59,24 @@ public class DeliveryRecord { ...@@ -47,6 +59,24 @@ public class DeliveryRecord {
private Date signDate; private Date signDate;
/** /**
* 快递公司
*/
@TableField(value = "courier_company")
private String courierCompany;
/**
* 快递单号
*/
@TableField(value = "tracking_number")
private String trackingNumber;
/**
* 发货清单
*/
@TableField(value = "shipping_remark")
private String shippingRemark;
/**
* 备注 * 备注
*/ */
private String remark; private String remark;
......
...@@ -26,9 +26,10 @@ public class FileInfo { ...@@ -26,9 +26,10 @@ public class FileInfo {
private String type; private String type;
/** /**
* 文件来源 * 文件来源
* <br>1项目、2工单预处理,3工单操作,4巡检,5合同,6发货记录</br> * <br>1项目、2工单预处理,3工单操作,4巡检,5合同,6发货记录</br>
* <br>7签订,8到货,9系统初验,10项目终验,11质保,12第一笔维保款,13第二笔维保款,14第三笔维保款</br> * <br>7签订,8到货,9系统初验,10项目终验,11质保,12第一笔维保款,13第二笔维保款,14第三笔维保款</br>
* <br>15结算差异</br> * <br>15结算差异</br>
* <br>16客户提交的门店图纸,17点位设计图,18合同范本,19客户上传的合同,20安装上线,与总部邮件截图</br>
*/ */
private Integer sourceType; private Integer sourceType;
/** 文件来源id */ /** 文件来源id */
......
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import io.github.linpeilie.annotations.AutoMapper;
import io.github.linpeilie.annotations.AutoMappers;
import lombok.Data;
import vion.dto.PointInfoDTO;
import vion.vo.PointInfoVO;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/8
*/
@Data
@TableName(value = "tbl_point_info")
@AutoMappers({
@AutoMapper(target = PointInfoVO.class),
@AutoMapper(target = PointInfoDTO.class),
})
public class PointInfo {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 集团id
*/
@TableField(value = "account_id")
private Long accountId;
/**
* 项目名称(用户填写的)
*/
@TableField(value = "project_name")
private String projectName;
/**
* 联系人
*/
@TableField(value = "contact", condition = SqlCondition.LIKE)
private String contact;
/**
* 手机号码
*/
@TableField(value = "phone", condition = SqlCondition.LIKE)
private String phone;
/**
* 点位数量
*/
@TableField(value = "point_num")
private Integer pointNum;
/**
* 发货状态
*/
@TableField(value = "shipping_status")
private Integer shippingStatus;
/**
* 收货地址
*/
@TableField(value = "shipping_address")
private String shippingAddress;
/**
* 收货联系人
*/
@TableField(value = "receiving_contact")
private String receivingContact;
/**
* 收货联系电话
*/
@TableField(value = "receiving_phone")
private String receivingPhone;
/**
* 快递公司
*/
@TableField(value = "courier_company")
private String courierCompany;
/**
* 快递单号
*/
@TableField(value = "tracking_number")
private String trackingNumber;
/**
* 状态
*/
@TableField(value = "\"status\"")
private Integer status;
/**
* 合同编号
*/
@TableField(value = "contract_no")
private String contractNo;
/**
* 是否施工 0:不施工 1:施工
*/
@TableField(value = "is_construct")
private Integer isConstruct;
/**
* 施工地址
*/
@TableField(value = "construct_address")
private String constructAddress;
/**
* 施工联系人
*/
@TableField(value = "construct_contact")
private String constructContact;
/**
* 施工联系电话
*/
@TableField(value = "construct_phone")
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
@TableField(value = "is_invoice")
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
@TableField(value = "invoice_type")
private Integer invoiceType;
/**
* 发票抬头
*/
@TableField(value = "invoice_header")
private String invoiceHeader;
/**
* 税号
*/
@TableField(value = "tax_id_num")
private String taxIdNum;
/**
* 单位地址
*/
@TableField(value = "invoice_address")
private String invoiceAddress;
/**
* 单位电话
*/
@TableField(value = "invoice_phone")
private String invoicePhone;
/**
* 开户银行
*/
@TableField(value = "account_bank")
private String accountBank;
/**
* 银行卡号
*/
@TableField(value = "bank_number")
private String bankNumber;
/**
* 邮箱地址
*/
@TableField(value = "email")
private String email;
/**
* 发票邮寄地址
*/
@TableField(value = "invoice_rec_address")
private String invoiceRecAddress;
/**
* 发票联系人
*/
@TableField(value = "invoice_contact")
private String invoiceContact;
/**
* 发票联系电话
*/
@TableField(value = "invoice_rec_phone")
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
@TableField(value = "invoice_courier_company")
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
@TableField(value = "invoice_tracking_number")
private String invoiceTrackingNumber;
/**
* 备注
*/
@TableField(value = "remake")
private String remake;
/**
* 施工方
*/
@TableField(value = "construction_side")
private String constructionSide;
/**
* uuid
*/
@TableField(value = "uuid")
private String uuid;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
\ No newline at end of file \ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/12
*/
@Data
@TableName(value = "r_point_device")
public class RPointDevice {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位记录id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 设备序列号
*/
@TableField(value = "device_no")
private String deviceNo;
@TableField(value = "create_time")
private Date createTime;
@TableField(value = "update_time")
private Date updateTime;
}
\ No newline at end of file \ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/12
*/
@Data
@TableName(value = "r_point_wx")
public class RPointWx {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位记录id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 微信昵称
*/
@TableField(value = "wx_name")
private String wxName;
/**
* 微信openid
*/
@TableField(value = "openid")
private String openid;
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}
\ No newline at end of file \ No newline at end of file
package vion.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import vion.dto.BaseDTO;
import java.util.Date;
/**
* @author HlQ
* @date 2024/1/8
*/
@Data
@TableName(value = "tbl_reject_info")
public class RejectInfo extends BaseDTO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 点位信息id
*/
@TableField(value = "point_id")
private Long pointId;
/**
* 驳回类型
*/
@TableField(value = "\"type\"")
private Integer type;
/**
* 内容
*/
@TableField(value = "content")
private String content;
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}
\ No newline at end of file \ No newline at end of file
...@@ -6,6 +6,8 @@ import vion.dto.DeliveryRecordDTO; ...@@ -6,6 +6,8 @@ import vion.dto.DeliveryRecordDTO;
import vion.model.DeliveryRecord; import vion.model.DeliveryRecord;
import vion.vo.DeliveryRecordVO; import vion.vo.DeliveryRecordVO;
import java.util.List;
/** /**
* @author HlQ * @author HlQ
* @date 2023/12/5 * @date 2023/12/5
...@@ -16,5 +18,7 @@ public interface IDeliveryRecordService extends MPJBaseService<DeliveryRecord> { ...@@ -16,5 +18,7 @@ public interface IDeliveryRecordService extends MPJBaseService<DeliveryRecord> {
String save(DeliveryRecordDTO dto); String save(DeliveryRecordDTO dto);
String saveBatch(List<DeliveryRecordDTO> dto);
String updateById(DeliveryRecordDTO dto); String updateById(DeliveryRecordDTO dto);
} }
package vion.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import vion.dto.PointInfoDTO;
import vion.model.PointInfo;
import vion.model.RejectInfo;
import vion.vo.PointInfoVO;
import java.util.List;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface IPointInfoService extends MPJBaseService<PointInfo> {
Object frontSubmit(PointInfoDTO dto);
Object save(PointInfoDTO dto);
String upd(Long id, String uuid, PointInfoDTO dto);
Page<PointInfoVO> list(PointInfoDTO dto);
PointInfoVO getPointByDetail(Long id, String uuid);
String delById(Long id);
String reject(RejectInfo dto, String userStr);
Page<RejectInfo> rejectInfoList(Long pointId, RejectInfo dto);
Page<RejectInfo> rejectInfoList(String uuid, RejectInfo dto);
Object designPush(Long pointId, PointInfo pointInfo, String pushType);
String installSubmit(String uuid, List<String> deviceList);
Object bindOpenid(String uuid, String code);
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RPointDevice;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface IRPointDeviceService extends MPJBaseService<RPointDevice> {
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RPointWx;
/**
* @author HlQ
* @date 2024/1/12
*/
public interface IRPointWxService extends MPJBaseService<RPointWx> {
}
package vion.service;
import com.github.yulichang.base.MPJBaseService;
import vion.model.RejectInfo;
/**
* @author HlQ
* @date 2024/1/8
*/
public interface IRejectInfoService extends MPJBaseService<RejectInfo> {
}
...@@ -4,24 +4,25 @@ import cn.dev33.satoken.stp.StpUtil; ...@@ -4,24 +4,25 @@ import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl; import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper;
import io.github.linpeilie.Converter; import io.github.linpeilie.Converter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import vion.dto.ContractDTO; import vion.dto.ContractDTO;
import vion.dto.DeliveryRecordDTO; import vion.dto.DeliveryRecordDTO;
import vion.mapper.DeliveryRecordMapper; import vion.mapper.DeliveryRecordMapper;
import vion.model.Contract; import vion.model.*;
import vion.model.DeliveryRecord; import vion.service.*;
import vion.model.FileInfo; import vion.third.DingMod;
import vion.service.IContractService;
import vion.service.IDeliveryRecordService;
import vion.service.IFileService;
import vion.vo.DeliveryRecordVO; import vion.vo.DeliveryRecordVO;
import vion.vo.UserVO; import vion.vo.UserVO;
...@@ -29,6 +30,8 @@ import java.io.File; ...@@ -29,6 +30,8 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/** /**
* @author HlQ * @author HlQ
...@@ -40,6 +43,10 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord ...@@ -40,6 +43,10 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
private final IFileService fileService; private final IFileService fileService;
private final IContractService contractService; private final IContractService contractService;
private final IRContractUserService contractUserService;
private final IPointInfoService pointInfoService;
private final DingMod dingMod;
private final RedisTemplate redisTemplate;
private final Converter converter; private final Converter converter;
@Value("${fileUrl:}") @Value("${fileUrl:}")
...@@ -55,16 +62,23 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord ...@@ -55,16 +62,23 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
.like(StrUtil.isNotBlank(dto.getContractName()), Contract::getName, dto.getContractName()) .like(StrUtil.isNotBlank(dto.getContractName()), Contract::getName, dto.getContractName())
.like(StrUtil.isNotBlank(dto.getCustomerName()), Contract::getCustomerName, dto.getCustomerName()) .like(StrUtil.isNotBlank(dto.getCustomerName()), Contract::getCustomerName, dto.getCustomerName())
.orderByDesc(DeliveryRecord::getCreateTime); .orderByDesc(DeliveryRecord::getCreateTime);
return this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), DeliveryRecordVO.class, wrapper); Page<DeliveryRecordVO> voPage = this.selectJoinListPage(Page.of(dto.getPageNum(), dto.getPageSize()), DeliveryRecordVO.class, wrapper);
Opt.ofEmptyAble(voPage.getRecords())
.map(recs -> recs.stream().map(DeliveryRecordVO::getId).collect(Collectors.toList()))
.map(ids -> {
List<FileInfo> fileInfos = fileService.lambdaQuery().in(FileInfo::getSourceId, ids).eq(FileInfo::getSourceType, 6).list();
return fileInfos.stream().collect(Collectors.groupingBy(FileInfo::getSourceId));
})
.filter(MapUtil::isNotEmpty)
.ifPresent(map -> voPage.getRecords().forEach(rec -> rec.setFileList(map.get(rec.getId()))));
return voPage;
} }
@Override @Override
public String save(DeliveryRecordDTO dto) { public String save(DeliveryRecordDTO dto) {
DeliveryRecord record = converter.convert(dto, DeliveryRecord.class); DeliveryRecord record = converter.convert(dto, DeliveryRecord.class);
if (this.save(record)) { if (this.save(record)) {
ContractDTO contractDTO = new ContractDTO(); updStatusAndPushMsg(record);
contractDTO.setStatus(2);
contractService.updateById(null, dto.getContractNo(), contractDTO);
Opt.ofNullable(dto.getFiles()) Opt.ofNullable(dto.getFiles())
.ifPresent(fileList -> { .ifPresent(fileList -> {
...@@ -74,7 +88,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord ...@@ -74,7 +88,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
String orgName = infile.getOriginalFilename(); String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName); String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName); String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);; String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + dto.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + dto.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
try { try {
...@@ -103,6 +117,66 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord ...@@ -103,6 +117,66 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
} }
@Override @Override
public String saveBatch(List<DeliveryRecordDTO> dto) {
List<DeliveryRecord> records = converter.convert(dto, DeliveryRecord.class);
if (this.saveBatch(records)) {
records.forEach(record -> updStatusAndPushMsg(record));
return "新增成功";
} else {
return "新增失败";
}
}
private void updStatusAndPushMsg(DeliveryRecord record) {
ContractDTO contractDTO = new ContractDTO();
contractDTO.setStatus(2);
Contract existContract = contractService.lambdaQuery().eq(Contract::getContractNo, record.getContractNo()).one();
if (existContract.getStatus() < 2) {
contractService.updateById(null, record.getContractNo(), contractDTO);
}
// 更新点位信息的发货状态
pointInfoService.lambdaUpdate().set(PointInfo::getShippingStatus, 1)
.set(PointInfo::getCourierCompany, record.getCourierCompany())
.set(PointInfo::getTrackingNumber, record.getTrackingNumber())
.set(PointInfo::getStatus, 9)
.eq(PointInfo::getContractNo, record.getContractNo()).update(new PointInfo());
Opt.ofNullable(pointInfoService.lambdaQuery().eq(PointInfo::getContractNo, record.getContractNo()).one())
.ifPresent(p -> pointInfoService.designPush(null, p, "发货"));
List<String> useridList = contractUserService.listObjs(Wrappers.<RContractUser>lambdaQuery().select(RContractUser::getUserId).eq(RContractUser::getContractId, existContract.getId()), Object::toString);
Opt.ofNullable(((User) redisTemplate.opsForValue().get("dingtalk:user:name:" + existContract.getSaleName())))
.map(User::getUserid)
.ifPresent(useridList::add);
dingMod.sendMessage(buildMsg(useridList.stream().distinct().collect(Collectors.joining(",")), record, existContract));
}
JSONObject buildMsg(String userid, DeliveryRecord rec, Contract contract) {
JSONObject jsonObj = new JSONObject();
jsonObj.set("agent_id", 2358374016L);
jsonObj.set("userid_list", userid);
JSONObject msg = new JSONObject();
JSONObject content = new JSONObject();
content.set("title", "设备发货提醒");
String markdown = StrUtil.format("#### 发货通知" +
" \n #### 合同名称:{}" +
" \n #### 合同编号:{}" +
" \n #### 快递公司:{}" +
" \n #### 快递单号:{}" +
" \n #### 收件人:{}" +
" \n #### 发货日期:{}" +
" \n #### 发送时间:{}",
contract.getName(), contract.getContractNo(), rec.getCourierCompany(), rec.getTrackingNumber(), rec.getConsignee(), DateUtil.formatDate(rec.getShipDate()), DateUtil.now());
content.set("text", markdown);
msg.set("msgtype", "markdown");
msg.set("markdown", content);
jsonObj.set("msg", msg);
return jsonObj;
}
@Override
public String updateById(DeliveryRecordDTO dto) { public String updateById(DeliveryRecordDTO dto) {
DeliveryRecord record = converter.convert(dto, DeliveryRecord.class); DeliveryRecord record = converter.convert(dto, DeliveryRecord.class);
if (this.updateById(record)) { if (this.updateById(record)) {
...@@ -115,7 +189,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord ...@@ -115,7 +189,7 @@ public class DeliveryRecordServiceImpl extends MPJBaseServiceImpl<DeliveryRecord
String orgName = infile.getOriginalFilename(); String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName); String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName); String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);; String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + deliveryRecord.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + "delivery" + FileUtil.FILE_SEPARATOR + deliveryRecord.getContractId() + FileUtil.FILE_SEPARATOR + record.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
try { try {
......
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RPointDeviceMapper;
import vion.model.RPointDevice;
import vion.service.IRPointDeviceService;
/**
* @author HlQ
* @date 2024/1/12
*/
@Service
public class RPointDeviceServiceImpl extends MPJBaseServiceImpl<RPointDeviceMapper, RPointDevice> implements IRPointDeviceService {
}
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RPointWxMapper;
import vion.model.RPointWx;
import vion.service.IRPointWxService;
/**
* @author HlQ
* @date 2024/1/12
*/
@Service
public class RPointWxServiceImpl extends MPJBaseServiceImpl<RPointWxMapper, RPointWx> implements IRPointWxService {
}
package vion.service.impl;
import com.github.yulichang.base.MPJBaseServiceImpl;
import org.springframework.stereotype.Service;
import vion.mapper.RejectInfoMapper;
import vion.model.RejectInfo;
import vion.service.IRejectInfoService;
/**
* @author HlQ
* @date 2024/1/8
*/
@Service
public class RejectInfoServiceImpl extends MPJBaseServiceImpl<RejectInfoMapper, RejectInfo> implements IRejectInfoService {
}
...@@ -132,7 +132,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp ...@@ -132,7 +132,7 @@ public class StoreServiceImpl extends MPJBaseServiceImpl<StoreMapper, Store> imp
String orgName = infile.getOriginalFilename(); String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName); String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName); String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);; String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + statusDTO.getStoreId() + FileUtil.FILE_SEPARATOR + statusDTO.getSourceId() + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + statusDTO.getStoreId() + FileUtil.FILE_SEPARATOR + statusDTO.getSourceId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
try { try {
......
...@@ -5,12 +5,10 @@ import cn.hutool.core.collection.CollUtil; ...@@ -5,12 +5,10 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.*;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
...@@ -134,7 +132,10 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem ...@@ -134,7 +132,10 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
} }
// 可能直接提工单,而不是预工单确认之后生成的工单 // 可能直接提工单,而不是预工单确认之后生成的工单
if (data.getTaskTempId() != null) { if (ObjUtil.isNotNull(data.getTaskTempId())) {
Task existTask = this.lambdaQuery().eq(Task::getTaskTempId, data.getTaskTempId()).one();
Assert.isNull(existTask, "工单已创建,无需再次确认");
taskTempService.lambdaUpdate() taskTempService.lambdaUpdate()
.set(TaskTemp::getStatus, 3) .set(TaskTemp::getStatus, 3)
.set(TaskTemp::getOperator, data.getActiveUser()) .set(TaskTemp::getOperator, data.getActiveUser())
...@@ -221,11 +222,12 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem ...@@ -221,11 +222,12 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
.put(4, "挂起") .put(4, "挂起")
.build(); .build();
List<WxMpTemplateData> wxMpTemplateDataList = ListUtil.of( List<WxMpTemplateData> wxMpTemplateDataList = ListUtil.of(
new WxMpTemplateData("character_string1", existTask.getUuid()), new WxMpTemplateData("character_string21", existTask.getUuid()),
new WxMpTemplateData("thing7", DesensitizedUtil.chineseName(user.getUsername())), new WxMpTemplateData("thing12", DesensitizedUtil.chineseName(user.getUsername())),
new WxMpTemplateData("time4", DateUtil.formatDateTime(new Date())), new WxMpTemplateData("time11", DateUtil.formatDateTime(new Date())),
new WxMpTemplateData("const3", statusMap.get(existTask.getStatus()))); new WxMpTemplateData("thing20", existTask.getFaultDescription().length() > 20 ? StrUtil.sub(existTask.getFaultDescription(), 0, 17) + "..." : existTask.getFaultDescription()),
String sentMsg = wechatMod.sendMsg("ueJlVya7uOfYhFlIv28pC0kiHPe1b6Q-gkWsYKkoRWo", openid, wxMpTemplateDataList, null); new WxMpTemplateData("phrase25", statusMap.get(existTask.getStatus())));
String sentMsg = wechatMod.sendMsg("H3zWJysLWrcxrUlrgqPnjDV7LyWLaml_Ap9WsLuQDCs", openid, wxMpTemplateDataList, null);
}); });
} }
...@@ -235,7 +237,7 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem ...@@ -235,7 +237,7 @@ public class TaskServiceImpl extends MPJBaseServiceImpl<TaskMapper, Task> implem
String orgName = infile.getOriginalFilename(); String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName); String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName); String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);; String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + data.getStoreId() + FileUtil.FILE_SEPARATOR + task.getId() + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + data.getStoreId() + FileUtil.FILE_SEPARATOR + task.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
try { try {
......
...@@ -3,6 +3,7 @@ package vion.service.impl; ...@@ -3,6 +3,7 @@ package vion.service.impl;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.Opt;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
...@@ -26,7 +27,6 @@ import vion.service.IFileService; ...@@ -26,7 +27,6 @@ import vion.service.IFileService;
import vion.service.ITaskTempService; import vion.service.ITaskTempService;
import vion.service.IUserService; import vion.service.IUserService;
import vion.third.DingMod; import vion.third.DingMod;
import vion.third.WechatMod;
import vion.vo.TaskTempVO; import vion.vo.TaskTempVO;
import java.io.File; import java.io.File;
...@@ -43,7 +43,6 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task ...@@ -43,7 +43,6 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
private final IFileService fileService; private final IFileService fileService;
private final IUserService userService; private final IUserService userService;
private final DingMod dingMod; private final DingMod dingMod;
private final WechatMod wechatMod;
private final Converter converter; private final Converter converter;
@Value("${fileUrl:}") @Value("${fileUrl:}")
...@@ -88,7 +87,7 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task ...@@ -88,7 +87,7 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
String orgName = infile.getOriginalFilename(); String orgName = infile.getOriginalFilename();
String mainName = FileUtil.mainName(orgName); String mainName = FileUtil.mainName(orgName);
String fileExt = FileUtil.extName(orgName); String fileExt = FileUtil.extName(orgName);
String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);; String filename = StrUtil.format("{}_{}.{}", mainName, DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), fileExt);
String path = fileUrl + FileUtil.FILE_SEPARATOR + 0 + FileUtil.FILE_SEPARATOR + taskTemp.getId() + FileUtil.FILE_SEPARATOR + filename; String path = fileUrl + FileUtil.FILE_SEPARATOR + 0 + FileUtil.FILE_SEPARATOR + taskTemp.getId() + FileUtil.FILE_SEPARATOR + filename;
File file = FileUtil.touch(path); File file = FileUtil.touch(path);
try { try {
...@@ -114,11 +113,9 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task ...@@ -114,11 +113,9 @@ public class TaskTempServiceImpl extends MPJBaseServiceImpl<TaskTempMapper, Task
String userids = userList.stream().map(User::getUserid).collect(Collectors.joining(",")); String userids = userList.stream().map(User::getUserid).collect(Collectors.joining(","));
dingMod.sendMessage(buildMsg(userids, taskTemp)); dingMod.sendMessage(buildMsg(userids, taskTemp));
if (StrUtil.isNotBlank(data.getOpenid())) { return MapUtil.<String, Long>builder()
return "工单提交成功!"; .put("id", taskTemp.getId())
} else { .build();
return wechatMod.genQRCodeUrl(taskTemp.getId());
}
} }
JSONObject buildMsg(String userid, TaskTemp taskTemp) { JSONObject buildMsg(String userid, TaskTemp taskTemp) {
......
...@@ -148,7 +148,8 @@ public class DingMod { ...@@ -148,7 +148,8 @@ public class DingMod {
} }
userService.saveOrUpdate(user, Wrappers.<User>lambdaUpdate().eq(User::getUserid, userid)); userService.saveOrUpdate(user, Wrappers.<User>lambdaUpdate().eq(User::getUserid, userid));
User one = userService.lambdaQuery().eq(User::getUserid, userid).one(); User one = userService.lambdaQuery().eq(User::getUserid, userid).one();
redisTemplate.opsForValue().set("dingtalk:user:" + one.getId(), user); redisTemplate.opsForValue().set("dingtalk:user:id:" + one.getId(), user);
redisTemplate.opsForValue().set("dingtalk:user:name:" + one.getUsername(), user);
} }
} }
}); });
...@@ -190,7 +191,9 @@ public class DingMod { ...@@ -190,7 +191,9 @@ public class DingMod {
*/ */
public String sendMessage(JSONObject msg) { public String sendMessage(JSONObject msg) {
String token = getToken(); String token = getToken();
return HttpUtil.post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=" + token, msg.toString()); String res = HttpUtil.post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=" + token, msg.toString());
log.info("钉钉工作通知消息推送:{}", res);
return res;
} }
/** /**
...@@ -329,4 +332,10 @@ public class DingMod { ...@@ -329,4 +332,10 @@ public class DingMod {
} }
return ""; return "";
} }
public String robotPush(String access_token, String body) {
String res = HttpUtil.post("https://oapi.dingtalk.com/robot/send?access_token=" + access_token, body);
log.info("钉钉机器人消息推送:{}", res);
return res;
}
} }
package vion.third; package vion.third;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -8,10 +10,14 @@ import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; ...@@ -8,10 +10,14 @@ import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken; import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData; import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import vion.dto.WxDTO;
import vion.event.WxDTOEvent;
import java.util.List; import java.util.List;
...@@ -25,18 +31,24 @@ import java.util.List; ...@@ -25,18 +31,24 @@ import java.util.List;
public class WechatMod { public class WechatMod {
private final WxMpService wxMpService; private final WxMpService wxMpService;
private final ApplicationEventPublisher publisher;
/** /**
* 微信扫码获取用户 openid * 用于微信公众号内提交单子。
* 用户已关注公众号,直接获取 openid 即可。
* *
* @param code 授权码 * @param code 授权码
* @return java.lang.Object * @return java.lang.Object
*/ */
public Object wechatCallback(String code) { public Object getOpenid(String code) {
try { try {
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code); WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
WxOAuth2UserInfo wxMpUser = wxMpService.getOAuth2Service().getUserInfo(accessToken, null); WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
return wxMpUser.getOpenid(); String openid = userInfo.getOpenid();
String nickname = userInfo.getNickname();
return MapUtil.<String, String>builder()
.put("nickname", nickname)
.put("openid", openid).build();
} catch (WxErrorException e) { } catch (WxErrorException e) {
log.error("调用微信接口异常!", e); log.error("调用微信接口异常!", e);
} }
...@@ -44,14 +56,55 @@ public class WechatMod { ...@@ -44,14 +56,55 @@ public class WechatMod {
} }
/** /**
* 生成微信网页授权链接 * 生成微信网页授权链接用于 pc 端故障保修、点位设计等页面,绑定openid
* *
* @param taskTempId 预工单 id * @param id 生成单子的 id
* @param flag 1:故障保修 2:点位设计
* @return java.lang.String * @return java.lang.String
*/ */
public String genQRCodeUrl(Long taskTempId) { public String genCallbackQRCode(Long id, Integer flag) {
String url = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/wechat/callback?taskTempId={}", taskTempId); String redirectUri = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/getFollowingOpenid?id={}&flag={}", id, flag);
return wxMpService.getOAuth2Service().buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null); return wxMpService.getOAuth2Service().buildAuthorizationUrl(redirectUri, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
}
/**
* 用户提交单子,需要判断用户是否关注公众号。
* 关注公众号的用户,直接获取 openid,返回前端,前端提交工单(或其他单子)时带上 openid。
* 未关注公众号的用户,直接返回一个页面,提示用户关注公众号。
*
* @param code 授权码
* @return java.lang.Object
*/
public Object getFollowingOpenid(Long id, Integer flag, String code) {
try {
WxOAuth2AccessToken accessToken = wxMpService.getOAuth2Service().getAccessToken(code);
WxOAuth2UserInfo userInfo = wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
String openid = userInfo.getOpenid();
WxMpUser wxMpUser = wxMpService.getUserService().userInfo(openid);
if (!wxMpUser.getSubscribe()) {
return new ModelAndView("weChatNeedAttention");
}
String nickname = userInfo.getNickname();
WxDTO wxDTO = WxDTO.builder().nickname(nickname).openid(openid).id(id).flag(flag).build();
WxDTOEvent wxDTOEvent = new WxDTOEvent(this, wxDTO);
publisher.publishEvent(wxDTOEvent);
return new ModelAndView("weChatSuccess");
} catch (WxErrorException e) {
log.error("调用微信接口异常!", e);
}
return new ModelAndView("weChatError");
}
/**
* 点位设计详情页获取绑定微信二维码
*
* @param uuid 点位记录 uuid
* @return java.lang.String
*/
public String genBindOpenidQRCode(String uuid) {
String redirectUri = StrUtil.format("https://yunwei.vionyun.com/yunwei/api/point/getBindOpenid?uuid={}&rid={}", uuid, IdUtil.fastSimpleUUID());
return wxMpService.getOAuth2Service().buildAuthorizationUrl(redirectUri, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
} }
public String sendMsg(String templateId, String openId, List<WxMpTemplateData> wxMpTemplateDataList, String url) { public String sendMsg(String templateId, String openId, List<WxMpTemplateData> wxMpTemplateDataList, String url) {
......
...@@ -24,6 +24,20 @@ public class DeliveryRecordVO { ...@@ -24,6 +24,20 @@ public class DeliveryRecordVO {
*/ */
private Long contractId; private Long contractId;
/**
* 收货人
*/
private String consignee;
/**
* 收货地址
*/
private String address;
/**
* 收货电话
*/
private String phone;
/** /**
* 客户名称 * 客户名称
...@@ -43,6 +57,21 @@ public class DeliveryRecordVO { ...@@ -43,6 +57,21 @@ public class DeliveryRecordVO {
private Date signDate; private Date signDate;
/** /**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 发货清单
*/
private String shippingRemark;
/**
* 备注 * 备注
*/ */
private String remark; private String remark;
......
package vion.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.liaochong.myexcel.core.annotation.ExcelColumn;
import com.github.liaochong.myexcel.core.annotation.ExcelModel;
import com.github.liaochong.myexcel.core.constant.LinkType;
import lombok.Getter;
import lombok.Setter;
import vion.model.FileInfo;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* @author HlQ
* @date 2024/1/8
*/
@Getter
@Setter
@ExcelModel(sheetName = "点位设计", includeAllField = false)
public class PointInfoVO {
private Long id;
/**
* 集团id
*/
private Long accountId;
private String accountName;
/**
* 项目名称(用户填写的)
*/
@ExcelColumn(order = 0, title = "门店名称")
private String projectName;
/**
* 联系人
*/
@ExcelColumn(order = 1, title = "联系人")
private String contact;
/**
* 手机号码
*/
@ExcelColumn(order = 2, title = "联系电话")
private String phone;
/**
* 点位数量
*/
@ExcelColumn(order = 3, title = "点位数量")
private Integer pointNum;
/**
* 点位设计图url
*/
@ExcelColumn(order = 4, title = "点位设计图", linkType = LinkType.URL)
private String pointUrl;
/**
* 发货状态
*/
private Integer shippingStatus;
/**
* 收货地址
*/
private String shippingAddress;
/**
* 收货联系人
*/
private String receivingContact;
/**
* 收货联系电话
*/
private String receivingPhone;
/**
* 快递公司
*/
private String courierCompany;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 状态
*/
private Integer status;
/**
* 合同编号
*/
private String contractNo;
/**
* 合同金额
*/
private BigDecimal contractAmount;
/**
* 是否施工 0:不施工 1:施工
*/
private Integer isConstruct;
/**
* 施工地址
*/
private String constructAddress;
/**
* 施工联系人
*/
private String constructContact;
/**
* 施工联系电话
*/
private String constructPhone;
/**
* 是否开票 0:不开票 1:开票
*/
private Integer isInvoice;
/**
* 发票类型 1:电子发票 2:纸质发票
*/
private Integer invoiceType;
/**
* 发票抬头
*/
private String invoiceHeader;
/**
* 税号
*/
private String taxIdNum;
/**
* 单位地址
*/
private String invoiceAddress;
/**
* 单位电话
*/
private String invoicePhone;
/**
* 开户银行
*/
private String accountBank;
/**
* 银行卡号
*/
private String bankNumber;
/**
* 邮箱地址
*/
private String email;
/**
* 发票邮寄地址
*/
private String invoiceRecAddress;
/**
* 发票联系人
*/
private String invoiceContact;
/**
* 发票联系电话
*/
private String invoiceRecPhone;
/**
* 邮寄发票的快递公司
*/
private String invoiceCourierCompany;
/**
* 邮寄发票的快递单号
*/
private String invoiceTrackingNumber;
/**
* 图纸数量
*/
private Long drawingCnt;
/**
* 点位设计图的数量
*/
private Long designCnt;
/**
* 合同相关的数量
*/
private Long contractCnt;
/**
* 回执单的数量
*/
private Long receiptCnt;
/**
* 备注
*/
private String remake;
/**
* 施工方
*/
private String constructionSide;
/**
* uuid
*/
private String uuid;
private List<String> wxNameList;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
/**
* 客户上传的图纸文件
*/
private List<FileInfo> drawingFiles;
/**
* 点位设计图文件
*/
private List<FileInfo> designFiles;
/**
* 合同范本文件
*/
private List<FileInfo> contractTemplateFiles;
/**
* 终版合同
*/
private List<FileInfo> finalContractFiles;
/**
* 合同文件
*/
private List<FileInfo> contractFiles;
/**
* 回执单文件
*/
private List<FileInfo> receiptFiles;
}
\ No newline at end of file \ No newline at end of file
debug=false debug=false
################################## DATABASE ######################################## ################################## DATABASE ########################################
#spring.datasource.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order spring.datasource.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order
#spring.datasource.username=vion spring.datasource.username=vion
#spring.datasource.password=jkou72j32m4K5d8k spring.datasource.password=jkou72j32m4K5d8k
#spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.dynamic.primary=master
spring.datasource.dynamic.strict=false
spring.datasource.dynamic.datasource.master.url=jdbc:postgresql://pgm-2ze3cjpyjgjw0bl5uo.pg.rds.aliyuncs.com:1921/work-order
spring.datasource.dynamic.datasource.master.username=vion
spring.datasource.dynamic.datasource.master.password=jkou72j32m4K5d8k
spring.datasource.dynamic.datasource.master.driver-class-name=org.postgresql.Driver
spring.datasource.dynamic.datasource.slave_1.url=jdbc:postgresql://47.102.107.41:5432/f_serv
spring.datasource.dynamic.datasource.slave_1.username=postgres
spring.datasource.dynamic.datasource.slave_1.password=zxl123456
spring.datasource.dynamic.datasource.slave_1.driver-class-name=org.postgresql.Driver
spring.redis.host=r-2zejlb88mng3q50aw7pd.redis.rds.aliyuncs.com spring.redis.host=r-2zejlb88mng3q50aw7pd.redis.rds.aliyuncs.com
spring.redis.password=RtOTnx2V spring.redis.password=RtOTnx2V
spring.redis.port=6379 spring.redis.port=6379
spring.redis.database=8 spring.redis.database=8
wx.mp.config-storage.type=RedisTemplate
wx.mp.config-storage.key-prefix=wa
wx.mp.config-storage.redis.host=r-2zejlb88mng3q50aw7pd.redis.rds.aliyuncs.com
wx.mp.config-storage.redis.password==RtOTnx2V
wx.mp.config-storage.redis.port=6379
wx.mp.config-storage.redis.database=8
server.port=8011 server.port=8011
fileUrl=D:/pic fileUrl=D:/pic
#fileurl=/nas-data/work-order #fileurl=/nas-data/work-order
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<contextName>logback</contextName> <contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 --> <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="logs"/> <property name="log.path" value="logs"/>
<property name="pattern" value="[%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS})] %highlight([%-5level]) [%thread] %green(%logger{50} [%L]) - %msg%n"/> <property name="pattern" value="[%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS})] %cyan(%X{requestId}) %highlight([%-5level]) [%thread] %green(%logger{50} [%L]) - %msg%n"/>
<property name="datapattern" value="%msg%n"/> <property name="datapattern" value="%msg%n"/>
<!--输出到控制台--> <!--输出到控制台-->
......
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xml; charset=utf-8" />
</head>
<title>绑定成功</title>
<style>
.center{
line-height: 200px;
height: 100%;
text-align: center;
}
.center p {
line-height: 1.5;
display: inline-block;
vertical-align: middle;
font-size: 6rem;
}
</style>
<body>
<div class="center">
<p>绑定成功</p>
</div>
</body>
</html>
\ No newline at end of file \ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/xml; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/xml; charset=utf-8" />
</head> </head>
<title>绑定成功</title> <title>扫码成功</title>
<style> <style>
.center{ .center{
line-height: 200px; line-height: 200px;
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</style> </style>
<body> <body>
<div class="center"> <div class="center">
<p>绑定成功</p> <p>扫码成功</p>
</div> </div>
</body> </body>
</html> </html>
\ No newline at end of file \ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!