出入库修改

工厂员工录入 模块
This commit is contained in:
furongxin 2024-06-06 22:30:57 +08:00
parent e6292c3ae2
commit ed8ed8c37b
41 changed files with 1109 additions and 55 deletions

View File

@ -38,7 +38,7 @@ public class ExcelUtils {
.autoCloseStream(false) // 不要自动关闭交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度自动适配最大 255 宽度
.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
.excelType(ExcelTypeEnum.XLSX)
.excelType(ExcelTypeEnum.XLS)
.sheet(sheetName)
.doWrite(data);
@ -58,6 +58,7 @@ public class ExcelUtils {
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度自动适配最大 255 宽度
.registerWriteHandler(new SpinnerWriteHandler(col, value, col1, value1))
.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
.excelType(ExcelTypeEnum.XLS)
.sheet(sheetName).doWrite(data);
// 设置 header contentType写在最后的原因是避免报错时响应 contentType 已经被修改了

View File

@ -55,8 +55,9 @@ public class SpinnerWriteHandler implements SheetWriteHandler {
DataValidation dataValidation = helper.createValidation(constraint, addressList);
/*** 处理Excel兼容性问题 **/
if (dataValidation instanceof XSSFDataValidation) {
dataValidation.setSuppressDropDownArrow(true);
dataValidation.setSuppressDropDownArrow(true); //验证输入数据是否真确
dataValidation.setShowErrorBox(true);
dataValidation.setShowPromptBox(true);
} else {
dataValidation.setSuppressDropDownArrow(false);
}

View File

@ -20,6 +20,7 @@ import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@ -90,6 +91,7 @@ public class AttendanceWebSocketMessageListener implements WebSocketMessageListe
}
if (object1.get("cmd").equals(AttendanceConstants.CMD_TO_CLIENT)) {
System.out.println("进来了"+ System.currentTimeMillis());
// 获取响应数据
DeviceResponseDTO dto = JsonUtils.parseObject2(object1.get("data").toString(), DeviceResponseDTO.class);
@ -133,11 +135,14 @@ public class AttendanceWebSocketMessageListener implements WebSocketMessageListe
// 响应失败的情况
if (dto.getCode() != 0) {
if ("setPasswordRet".equals(dto.getCmd())) {
if (!object1.get("to").toString().isEmpty()) {
webSocketMessageSender.sendObject(object1.get("to").toString(), "attendance-message-send", object1);
}else {
redisTemplate.opsForValue().set(object1.get("from").toString() + "msg", dto.getCode() + "_" + dto.getMsg());
redisTemplate.opsForValue().set(object1.get("from").toString(), "false");
redisTemplate.opsForValue().set(object1.get("from").toString() + "msg", dto.getCode() + "_" + dto.getMsg(), 30, TimeUnit.SECONDS);
redisTemplate.opsForValue().set(object1.get("from").toString(), "false", 30, TimeUnit.SECONDS);
}
return;
}
@ -172,11 +177,10 @@ public class AttendanceWebSocketMessageListener implements WebSocketMessageListe
String oldPassword = value.split("-")[0];
String newPassword = value.split("-")[1];
attendanceMachineApi.updateDevicePassword(object1.get("from").toString(), oldPassword, newPassword);
redisTemplate.delete(object1.get("from").toString());
}
break;
}
redisTemplate.delete(object1.get("from").toString());
}
if (!object1.get("to").toString().isEmpty()) {

View File

@ -42,6 +42,7 @@ public interface ErrorCodeConstants {
ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1_002_003_005, "用户密码校验失败");
ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})");
ErrorCode FACTORY_NOT_DEPT = new ErrorCode(1_002_003_009, "该工厂没有对应的部门,请联系管理员添加部门");
// ========== 部门模块 1-002-004-000 ==========
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
@ -235,13 +236,17 @@ public interface ErrorCodeConstants {
ErrorCode THE_CORRESPONDING_ASSET_TYPE_WAS_NOT_FOUND = new ErrorCode(1_010_001_006, "未找到对应的资产类型!");
// ========== 考勤设备相关 1-011-001-001 ==========
ErrorCode USERS_EXT_NOT_EXISTS = new ErrorCode(1_011_001_001, "用户信息不存在");
ErrorCode USERS_EXT_NOT_EXISTS = new ErrorCode(1_011_001_001, "用户信息不存在");
ErrorCode USERS_FACE_EXISTS = new ErrorCode(1_011_001_002, "用户人脸图片已存在");
ErrorCode USERS_FACE_EXISTS = new ErrorCode(1_011_001_002, "用户人脸图片已存在");
ErrorCode ATTENDANCE_MACHINE_NOT_EXISTS = new ErrorCode(1_011_002_001, "设备不存在");
ErrorCode USERS_EXT_EXISTS = new ErrorCode(1_011_001_003, "用户信息已存在!");
ErrorCode ATTENDANCE_PASSWORD_NOT_EQUAL = new ErrorCode(1_011_002_002, "旧密码错误,请重新输入");
ErrorCode ATTENDANCE_MACHINE_NOT_EXISTS = new ErrorCode(1_011_002_001, "设备不存在!");
ErrorCode REQUEST_FAILURE = new ErrorCode(1_011_002_003, "请求失败");
ErrorCode ATTENDANCE_PASSWORD_NOT_EQUAL = new ErrorCode(1_011_002_002, "旧密码错误,请重新输入!");
ErrorCode REQUEST_FAILURE = new ErrorCode(1_011_002_003, "请求失败!");
ErrorCode DEVICE_NO_EXISTS = new ErrorCode(1_011_002_004, "设备号已存在!");
}

View File

@ -176,6 +176,12 @@
<groupId>com.github.binarywang</groupId>
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId> <!-- 微信登录(小程序) -->
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>zn-module-smartfactory-api</artifactId>
<version>2.0.0-jdk8-snapshot</version>
<scope>compile</scope>
</dependency>
</dependencies>

View File

@ -118,7 +118,7 @@ public class AttendanceMachineController {
}
Long currentTime = System.currentTimeMillis();
if (currentTime - startTime > 3000) {
if (currentTime - startTime > 5000) {
throw exception(REQUEST_FAILURE);
}

View File

@ -76,14 +76,7 @@ public class UsersExtController {
@Operation(summary = "上传照片")
@Parameter(name = "createReqVO", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:users-ext:create')")
public CommonResult<Long> createUsersExt(@ModelAttribute UsersExtSaveReqVO createReqVO, @RequestParam("faceFile") MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
usersExtService.deleteUserFaceImg(getLoginUserId());
return success(1L);
}
public CommonResult<String> createUsersExt(@ModelAttribute UsersExtSaveReqVO createReqVO, @RequestParam("faceFile") MultipartFile file) throws Exception {
UsersExtDO updateDO = BeanUtils.toBean(createReqVO, UsersExtDO.class);
return success(usersExtService.createUsersExt(updateDO, file));

View File

@ -21,6 +21,12 @@ public class UsersExtSaveReqVO {
@NotNull(message = "部门编号不能为空")
private Long deptId;
@Schema(description = "工种类型 | 字典值 参考user_work_type")
private Integer workType;
@Schema(description = "图片地址")
private String faceImg;
@Schema(description = "绑定的考勤机设备号集合")
private List<String> attendanceMachineNos;

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "下发用户命令 VO")
@Data
public class AddUserVO {
@Schema(description = "指令")
private String cmd = "editUser";
@Schema(description = "用户id")
private String user_id;
@Schema(description = "用户姓名")
private String name;
@Schema(description = "人脸图片url")
private String face_template;
@Schema(description = "人员有效期")
private String id_valid;
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "删除用户命令 VO")
@Data
public class DeleteUserVO {
@Schema(description = "指令")
private String cmd;
@Schema(description = "用户id")
private String[] user_ids;
}

View File

@ -0,0 +1,179 @@
package cn.iocoder.yudao.module.system.controller.admin.user;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO;
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.convert.user.FactoryUserConvert;
import cn.iocoder.yudao.module.system.convert.user.UserConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.system.service.equipment.UsersExtService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import cn.iocoder.yudao.module.system.service.user.FactoryUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 工厂用户")
@RestController
@RequestMapping("/system/factory-user")
@Validated
public class FactoryUserController {
@Resource
private FactoryUserService factoryUserService;
@Resource
private AdminUserService userService;
@Resource
@Lazy
private DeptService deptService;
@Resource
private DictDataService dictDataService;
@Resource
@Lazy
private UsersExtService usersExtService;
@Resource
private FactoryInfoApi factoryInfoApi;
@PostMapping(value = "/create")
@Operation(summary = "新增工厂用户")
@PreAuthorize("@ss.hasPermission('system:factory-user:create')")
public CommonResult<String> createUser(@RequestBody FactoryUserSaveReqVO reqVO) {
String msg = factoryUserService.createUser(reqVO);
if (msg == null) {
return success("true");
}else {
return error(-1, msg);
}
}
@PutMapping(value = "/update")
@Operation(summary = "修改工厂用户")
@PreAuthorize("@ss.hasPermission('system:factory-user:update')")
public CommonResult<String> updateUser(@RequestBody FactoryUserSaveReqVO reqVO) {
String msg = factoryUserService.updateUser(reqVO);
if (msg == null) {
return success("true");
}else {
return error(-1, msg);
}
}
@DeleteMapping("/delete")
@Operation(summary = "删除工厂用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:factory-user:delete')")
public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
factoryUserService.deleteUser(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得工厂用户详情")
@Parameter(name = "id", description = "编号", required = true, example = "146")
@PreAuthorize("@ss.hasPermission('system:user:query')")
public CommonResult<FactoryUserRespVO> getUser(@RequestParam("id") Long id) {
AdminUserDO user = userService.getUser(id);
// 获得部门信息
DeptDO deptDO = deptService.getDept(user.getDeptId());
// 获得工厂信息
FactoryInfoDTO factoryInfoDTO = factoryInfoApi.getFactoryInfo(deptDO.getFactoryId()).getCheckedData();
// 获得拓展信息
UsersExtDO usersExtDO = usersExtService.getUsersExtByUserId(user.getId());
// 获得工种 字典信息
DictDataDO dictDataDO = dictDataService.getDictData("user_work_type", String.valueOf(usersExtDO.getWorkType()));
return success(FactoryUserConvert.INSTANCE.convert(user, factoryInfoDTO, dictDataDO, usersExtDO));
}
@GetMapping("/page")
@Operation(summary = "获得工厂用户分页列表")
@PreAuthorize("@ss.hasPermission('system:user:list')")
public CommonResult<PageResult<FactoryUserRespVO>> getUserPage(@Valid FactoryUserPageReqVO pageReqVO) {
// 获得用户分页列表
PageResult<AdminUserDO> pageResult = userService.getFactoryUserPage(pageReqVO);
if (pageResult.getList() == null || pageResult.getList().isEmpty()) {
return success(new PageResult<>(new ArrayList<>(), 0L));
}
// 部门信息
List<DeptDO> deptDOs = deptService.getDeptList(convertList(pageResult.getList(), AdminUserDO::getDeptId));
// 获得工厂信息
List<FactoryInfoDTO> factoryInfoDTOS = factoryInfoApi.getFactoryInfoList(convertList(deptDOs, DeptDO::getFactoryId)).getCheckedData();
Map<Long, FactoryInfoDTO> factoryInfoMap = new HashMap<>();
if (factoryInfoDTOS != null && !factoryInfoDTOS.isEmpty()) {
factoryInfoMap = deptDOs.stream()
.collect(Collectors.toMap(DeptDO::getId,
dept -> factoryInfoDTOS.stream().
filter(info -> info.getId().equals(dept.getFactoryId()))
.findFirst().orElseGet(FactoryInfoDTO::new)));
}
// 获得拓展信息
List<UsersExtDO> usersExtDOS = usersExtService.getListByUserId(convertList(pageResult.getList(), AdminUserDO::getId));
Map<Long, UsersExtDO> usersExtDOMap = convertMap(usersExtDOS, UsersExtDO::getUserId);
// 获得工种 字典信息
List<String> workTypes = usersExtDOS.stream().map(info -> info.getWorkType().toString()).collect(Collectors.toList());
List<DictDataDO> dictDataDO = dictDataService.getDictDataList("user_work_type", workTypes);
// 获得工种MAP
Map<String, DictDataDO> dictDataMap = convertMap(dictDataDO, DictDataDO::getValue);
return success(new PageResult<>(FactoryUserConvert.INSTANCE.convertList(pageResult.getList(), factoryInfoMap, dictDataMap, usersExtDOMap),
pageResult.getTotal()));
}
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 工厂用户分页 Request VO")
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class FactoryUserPageReqVO extends PageParam {
@Schema(description = "用户昵称,模糊匹配", example = "张三")
private String nickname;
@Schema(description = "工厂ID", example = "1000009")
private Long factoryId;
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 工厂用户信息 Response VO")
@Data
public class FactoryUserRespVO {
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
private Long id;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String nickname;
@Schema(description = "工厂ID", example = "1000009")
private Long factoryId;
@Schema(description = "工厂名称", example = "IT 部")
private String shortName;
@Schema(description = "工种编号")
private Integer workType;
@Schema(description = "工种名称")
private String workTypeName;
@Schema(description = "手机号码", example = "15601691300")
private String mobile;
@Schema(description = "身份证号码")
private String idcard;
@Schema(description = "人脸图片")
private String faceImg;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser;
import cn.iocoder.yudao.framework.common.validation.IdCard;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 工厂用户创建/修改 Request VO")
@Data
public class FactoryUserSaveReqVO {
@Schema(description = "用户编号", example = "146")
private Long id;
@Schema(description = "用户名称", example = "张三")
private String nickname;
@Schema(description = "工厂ID", example = "1000009")
private Long factoryId;
@Schema(description = "手机号码", example = "15601691300")
@Mobile
private String mobile;
@Schema(description = "身份证号码")
@IdCard
private String idcard;
@Schema(description = "工种 | 字典值 参考user_work_type")
private Integer workType;
@Schema(description = "人脸图片url")
private String faceImg;
}

View File

@ -0,0 +1,73 @@
package cn.iocoder.yudao.module.system.convert.user;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
@Mapper
public interface FactoryUserConvert {
FactoryUserConvert INSTANCE = Mappers.getMapper(FactoryUserConvert.class);
default List<FactoryUserRespVO> convertList(List<AdminUserDO> list,
Map<Long, FactoryInfoDTO> factoryInfoMap,
Map<String, DictDataDO> dictDataMap,
Map<Long, UsersExtDO> usersExtDOMap) {
return CollectionUtils.convertList(list, user -> convert(user, factoryInfoMap.get(user.getDeptId()), dictDataMap, usersExtDOMap.get(user.getId())));
}
default FactoryUserRespVO convert(AdminUserDO user, FactoryInfoDTO factoryInfo, Map<String, DictDataDO> dict, UsersExtDO usersExt) {
FactoryUserRespVO userVO = BeanUtils.toBean(user, FactoryUserRespVO.class);
if (factoryInfo != null) {
userVO.setFactoryId(factoryInfo.getId());
userVO.setShortName(factoryInfo.getShortName());
}
if (usersExt != null) {
userVO.setFaceImg(usersExt.getFaceImg());
userVO.setWorkType(usersExt.getWorkType());
userVO.setWorkTypeName(dict.get(usersExt.getWorkType().toString()).getLabel());
}
return userVO;
}
default FactoryUserRespVO convert(AdminUserDO user, FactoryInfoDTO factoryInfoDTO, DictDataDO dict, UsersExtDO usersExt) {
FactoryUserRespVO userVO = BeanUtils.toBean(user, FactoryUserRespVO.class);
if (factoryInfoDTO != null) {
userVO.setFactoryId(factoryInfoDTO.getId());
userVO.setShortName(factoryInfoDTO.getShortName());
}
if (usersExt != null) {
userVO.setWorkType(usersExt.getWorkType());
userVO.setFaceImg(usersExt.getFaceImg());
}
if (dict != null) {
userVO.setWorkTypeName(dict.getLabel());
}
return userVO;
}
}

View File

@ -39,6 +39,12 @@ public class UsersExtDO extends BaseDO {
*/
private Long deptId;
/**
* 工种编号 字典值 参考 user_work_type
* 针对工厂用户
*/
private Integer workType;
/**
* 人脸图片
*/

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.user;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@ -43,6 +44,15 @@ public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
.orderByDesc(AdminUserDO::getId));
}
default PageResult<AdminUserDO> selectFactoryUserPage(FactoryUserPageReqVO reqVO, Long deptId) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getNickname, reqVO.getNickname())
.eqIfPresent(AdminUserDO::getDeptId, deptId)
.eq(AdminUserDO::getUserType, 2)
.orderByDesc(AdminUserDO::getId));
}
default List<AdminUserDO> selectListByNickname(String nickname) {
return selectList(new LambdaQueryWrapperX<AdminUserDO>().like(AdminUserDO::getNickname, nickname));
}

View File

@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.system.framework.rpc.config;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class})
@EnableFeignClients(clients = {FileApi.class, WebSocketSenderApi.class, FactoryInfoApi.class})
public class RpcConfiguration {
}

View File

@ -102,7 +102,16 @@ public interface DeptService {
*/
List<DeptDO> getDeptByLeaderId(Long leaderUserId);
/**
* 获得 部门树
* @return 部门列表
*/
List<DeptDO> getDeptTree();
/**
* 获得指定部门信息
* @param factoryId 工厂编号
* @return 部门信息
*/
DeptDO getDeptByFactoryId(Long factoryId);
}

View File

@ -90,6 +90,15 @@ public interface DictDataService {
*/
DictDataDO getDictData(String dictType, String value);
/**
* 获得指定的字典数据列表
*
* @param dictType 字典类型
* @param value 字典数据值
* @return 字典数据
*/
List<DictDataDO> getDictDataList(String dictType, Collection<String> value);
/**
* 解析获得指定的字典数据从缓存中
*

View File

@ -164,6 +164,12 @@ public class DictDataServiceImpl implements DictDataService {
return dictDataMapper.selectByDictTypeAndValue(dictType, value);
}
@Override
public List<DictDataDO> getDictDataList(String dictType, Collection<String> value) {
return dictDataMapper.selectByDictTypeAndValues(dictType, value);
}
@Override
public DictDataDO parseDictData(String dictType, String label) {
return dictDataMapper.selectByDictTypeAndLabel(dictType, label);

View File

@ -84,4 +84,11 @@ public interface AttendanceMachineService {
* @return 设备列表
*/
List<AttendanceMachineDO> getListByStatus();
/**
* 获得指定部门绑定的设备列表
* @param deptId 部门编号
* @return 设备信息列表
*/
List<AttendanceMachineDO> getListByDeptId(Long deptId);
}

View File

@ -33,8 +33,7 @@ import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ATTENDANCE_MACHINE_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ATTENDANCE_PASSWORD_NOT_EQUAL;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 考勤设备 Service 实现类
@ -92,7 +91,7 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
public void updateAttendanceMachine(AttendanceMachineSaveReqVO updateReqVO) {
// 校验存在
validateAttendanceMachineExists(updateReqVO.getId());
validateAttendanceMachineExists(updateReqVO.getId(), updateReqVO.getDeviceNo());
//如果分配机构的情况 则调用资产分配方法
if (updateReqVO.getDeptId() != null) {
@ -146,10 +145,15 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
attendanceMachineMapper.update(attendanceMachineDO, new LambdaUpdateWrapper<AttendanceMachineDO>().eq(AttendanceMachineDO::getDeviceNo, updateReqVO.getDeviceNo()));
}
private void validateAttendanceMachineExists(Long id) {
private void validateAttendanceMachineExists(Long id, String deviceNo) {
if (attendanceMachineMapper.selectById(id) == null) {
throw exception(ATTENDANCE_MACHINE_NOT_EXISTS);
}
if (attendanceMachineMapper.selectCount(AttendanceMachineDO::getDeviceNo, deviceNo) > 0L) {
throw exception(DEVICE_NO_EXISTS);
}
}
@Override
@ -250,4 +254,10 @@ public class AttendanceMachineServiceImpl implements AttendanceMachineService {
return attendanceMachineMapper.selectList();
}
@Override
public List<AttendanceMachineDO> getListByDeptId(Long deptId) {
return attendanceMachineMapper.selectList(AttendanceMachineDO::getDeptId, deptId);
}
}

View File

@ -20,13 +20,19 @@ import java.util.List;
*/
public interface UsersExtService {
/**
* 创建用户信息
* @param createReqVO 创建信息
*/
void createUsers(UsersExtSaveReqVO createReqVO);
/**
* 创建用户信息拓展
*
* @param updateDO 创建信息
* @return 编号
*/
Long createUsersExt(UsersExtDO updateDO, MultipartFile file) throws IOException;
String createUsersExt(UsersExtDO updateDO, MultipartFile file) throws IOException;
/**
* 更新用户信息拓展
@ -35,6 +41,12 @@ public interface UsersExtService {
*/
void updateUsersExt(@Valid UsersExtSaveReqVO updateReqVO);
/**
* 修改用户信息
* @param updateReqVO 更新信息
*/
void updateUser(UsersExtSaveReqVO updateReqVO);
/**
* 批量更新用户 所下发得设备信息
*
@ -45,7 +57,7 @@ public interface UsersExtService {
/**
* 删除用户人脸信息
*/
void deleteUserFaceImg(Long userId) throws Exception;
void deleteUser(Long userId);
/**
* 获得用户信息拓展
@ -55,6 +67,14 @@ public interface UsersExtService {
*/
UsersExtDO getUsersExt(Long id);
/**
* 获得用户信息拓展
*
* @param userId 用户编号
* @return 用户信息拓展
*/
UsersExtDO getUsersExtByUserId(Long userId);
/**
* 获得指定得用户信息列表
* @param userId 用户编号

View File

@ -5,6 +5,7 @@ import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
@ -70,7 +71,19 @@ public class UsersExtServiceImpl implements UsersExtService {
private DistributeRecordService recordService;
@Override
public Long createUsersExt(UsersExtDO updateDO, MultipartFile file) throws IOException {
public void createUsers(UsersExtSaveReqVO createReqVO) {
if (usersExtMapper.selectCount(UsersExtDO::getUserId, createReqVO.getUserId()) > 0L) {
throw exception(USERS_EXT_EXISTS);
}
UsersExtDO usersExtDO = BeanUtils.toBean(createReqVO, UsersExtDO.class);
usersExtMapper.insert(usersExtDO);
}
@Override
public String createUsersExt(UsersExtDO updateDO, MultipartFile file) throws IOException {
String url = null;
String name = null;
@ -145,7 +158,7 @@ public class UsersExtServiceImpl implements UsersExtService {
}
// 返回
return updateDO.getUserId();
return url;
}
@Override
@ -158,6 +171,19 @@ public class UsersExtServiceImpl implements UsersExtService {
usersExtMapper.updateById(updateObj);
}
@Override
public void updateUser(UsersExtSaveReqVO updateReqVO) {
// 校验存在
validateUsersExtExists(updateReqVO.getUserId());
// 更新
UsersExtDO updateObj = BeanUtils.toBean(updateReqVO, UsersExtDO.class);
usersExtMapper.update(updateObj,
new LambdaQueryWrapperX<UsersExtDO>().eq(UsersExtDO::getUserId, updateReqVO.getUserId()));
}
@Override
public void updateListUsersExt(List<UsersExtDO> updateDo) {
@ -166,18 +192,18 @@ public class UsersExtServiceImpl implements UsersExtService {
}
@Override
public void deleteUserFaceImg(Long userId) throws Exception {
public void deleteUser(Long userId) {
//校验 当前用户人脸信息是否已存在
UsersExtDO usersExtDO = usersExtMapper.selectOne(UsersExtDO::getUserId, userId);
List<String> deviceNos = new ArrayList<>();
if (usersExtDO != null) {
//删除 文件存储器中人脸图片
fileApi.deleteBpmFile(usersExtDO.getFaceImg());
//更新 清空人脸图片信息
usersExtMapper.updateFaceImg(usersExtDO.getId());
deviceNos = usersExtDO.getAttendanceMachineNos();
usersExtMapper.delete(UsersExtDO::getUserId, userId);
}
}
private void validateUsersExtExists(Long userId) {
@ -193,6 +219,12 @@ public class UsersExtServiceImpl implements UsersExtService {
return usersExtMapper.selectById(id);
}
@Override
public UsersExtDO getUsersExtByUserId(Long userId) {
return usersExtMapper.selectOne(UsersExtDO::getUserId, userId);
}
@Override
public List<UsersExtDO> getListByUserId(List<Long> userId) {

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
@ -130,6 +131,14 @@ public interface AdminUserService {
*/
PageResult<AdminUserDO> getUserPage(UserPageReqVO reqVO);
/**
* 获得工厂用户分页列表
*
* @param reqVO 分页条件
* @return 分页列表
*/
PageResult<AdminUserDO> getFactoryUserPage(FactoryUserPageReqVO reqVO);
/**
* 通过用户 ID 查询用户
*

View File

@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.string.DTO.IdCardDO;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
@ -233,6 +234,8 @@ public class AdminUserServiceImpl implements AdminUserService {
userMapper.deleteById(id);
// 删除用户关联数据
permissionService.processUserDeleted(id);
// 删除用户拓展信息
// 删除用户岗位
userPostMapper.deleteByUserId(id);
}
@ -252,6 +255,20 @@ public class AdminUserServiceImpl implements AdminUserService {
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()));
}
@Override
public PageResult<AdminUserDO> getFactoryUserPage(FactoryUserPageReqVO reqVO) {
// 根据工厂ID 获取 对应部门ID
DeptDO deptDO = deptService.getDeptByFactoryId(reqVO.getFactoryId());
if (reqVO.getFactoryId() != null && deptDO == null) {
return new PageResult<>();
}
return userMapper.selectFactoryUserPage(reqVO, deptDO == null ? null : deptDO.getId());
}
@Override
public AdminUserDO getUser(Long id) {
return userMapper.selectById(id);

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.system.service.user;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* 后台工厂用户 Service 接口
*/
public interface FactoryUserService {
/**
* 创建工厂用户
*
* @param reqVO 创建信息
* @return 用户ID
*/
String createUser(FactoryUserSaveReqVO reqVO);
/**
* 修改工厂用户
* @param reqVO 修改信息
*/
String updateUser(FactoryUserSaveReqVO reqVO);
/**
* 删除工厂用户
* @param id 用户id
*/
void deleteUser(Long id);
}

View File

@ -0,0 +1,228 @@
package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.userExt.UsersExtSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.AddUserVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.AttendanceMachineDO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.UsersExtDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.equipment.AttendanceMachineService;
import cn.iocoder.yudao.module.system.service.equipment.UsersExtService;
import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import cn.iocoder.yudao.module.system.service.websocket.WebsocketService;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 后台工厂用户 Service 实现类
*/
@Service
@Slf4j
public class FactoryUserServiceImpl implements FactoryUserService{
@Resource
@Lazy // 延迟避免循环依赖报错
private TenantService tenantService;
@Resource
private AdminUserMapper userMapper;
@Resource
private PasswordEncoder passwordEncoder;
@Resource
@Lazy
private UsersExtService usersExtService;
@Resource
@Lazy
private DeptService deptService;
@Resource
private AttendanceMachineService attendanceMachineService;
@Resource
private WebsocketService websocketService;
@Override
@Transactional(rollbackFor = Exception.class) // 异常回滚
public String createUser(FactoryUserSaveReqVO createReqVO){
// 校验账户配合
tenantService.handleTenantInfo(tenant -> {
long count = userMapper.selectCount();
if (count >= tenant.getAccountCount()) {
throw exception(USER_COUNT_MAX, tenant.getAccountCount());
}
});
// 校验手机号唯一
validateMobileUnique(createReqVO.getMobile());
// 根据工厂ID 获取 对应部门ID
DeptDO deptDO = deptService.getDeptByFactoryId(createReqVO.getFactoryId());
if (deptDO == null) {
throw exception(FACTORY_NOT_DEPT);
}
// 插入用户
AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
user.setDeptId(deptDO.getId());
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
user.setPassword(encodePassword("123456")); // 设置默认密码
user.setUserType(2); // 设置用户类型为 工厂用户
userMapper.insert(user);
// 查询部门下是否绑定考勤设备
List<AttendanceMachineDO> attendanceMachineDOS = attendanceMachineService.getListByDeptId(deptDO.getId());
// 插入人脸图片
UsersExtSaveReqVO usersExtDO = BeanUtils.toBean(createReqVO, UsersExtSaveReqVO.class);
usersExtDO.setUserId(user.getId());
usersExtDO.setDeptId(deptDO.getId());
usersExtDO.setAttendanceMachineNos(convertList(attendanceMachineDOS, AttendanceMachineDO::getDeviceNo));
usersExtService.createUsers(usersExtDO);
try {
for (AttendanceMachineDO machineDO : attendanceMachineDOS) {
// 设置下发命令
AddUserVO addUserVO = new AddUserVO()
.setCmd("addUser")
.setUser_id(String.valueOf(user.getId()))
.setName(createReqVO.getNickname())
.setFace_template(usersExtDO.getFaceImg())
.setId_valid("");
// 发送指令至 考勤设备 下发员工
websocketService.sendSn(machineDO.getDeviceNo(), addUserVO, 1);
}
} catch (RuntimeException ex) {
return ex.getMessage();
}
return null;
}
@VisibleForTesting
void validateMobileUnique(String mobile) {
if (StrUtil.isBlank(mobile)) {
return;
}
AdminUserDO user = userMapper.selectByMobile(mobile);
if (user == null) {
return;
}
if (!user.getMobile().equals(mobile)) {
throw exception(USER_MOBILE_EXISTS);
}
}
@Override
@Transactional(rollbackFor = Exception.class) // 异常回滚
public String updateUser(FactoryUserSaveReqVO reqVO) {
// 校验是否存在
validateId(reqVO.getId());
// 根据工厂ID 获取 对应部门ID
DeptDO deptDO = deptService.getDeptByFactoryId(reqVO.getFactoryId());
if (deptDO == null) {
throw exception(FACTORY_NOT_DEPT);
}
// 更新用户信息
AdminUserDO userDO = BeanUtils.toBean(reqVO, AdminUserDO.class);
userDO.setDeptId(deptDO.getId());
userMapper.updateById(userDO);
// 查询部门下是否绑定考勤设备
List<AttendanceMachineDO> attendanceMachineDOS = attendanceMachineService.getListByDeptId(deptDO.getId());
// 同步更新用户拓展表中 人脸信息
UsersExtSaveReqVO usersExt = new UsersExtSaveReqVO()
.setUserId(reqVO.getId())
.setDeptId(deptDO.getId())
.setAttendanceMachineNos(convertList(attendanceMachineDOS, AttendanceMachineDO::getDeviceNo))
.setWorkType(reqVO.getWorkType())
.setFaceImg(reqVO.getFaceImg());
usersExtService.updateUser(usersExt);
try {
// 如果修改人脸图片的情况
for (AttendanceMachineDO machineDO : attendanceMachineDOS) {
// 设置下发命令
AddUserVO addUserVO = new AddUserVO()
.setCmd("addUser")
.setUser_id(String.valueOf(reqVO.getId()))
.setName(reqVO.getNickname())
.setFace_template(reqVO.getFaceImg())
.setId_valid("");
// 发送指令至 考勤设备 修改员工信息
websocketService.sendSn(machineDO.getDeviceNo(), addUserVO, 1);
}
}catch (RuntimeException ex) {
return ex.getMessage();
}
return null;
}
@Override
public void deleteUser(Long id) {
// 校验是否存在
validateId(id);
// 删除用户信息
userMapper.deleteById(id);
// 同步删除用户拓展信息
usersExtService.deleteUser(id);
}
private void validateId(Long id) {
if (userMapper.selectCount(AdminUserDO::getId, id) == 0L) {
throw exception(USER_USERNAME_EXISTS);
}
}
/**
* 对密码进行加密
*
* @param password 密码
* @return 加密后的密码
*/
private String encodePassword(String password) {
return passwordEncoder.encode(password);
}
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.system.service.websocket;
/**
* websocket 指令发送service
*/
public interface WebsocketService {
/**
* 发送指令至考勤设备
* @param deviceNo 设备号
* @param data 指令信息
* @param type 命令类型
*/
void sendSn(String deviceNo, Object data, Integer type);
}

View File

@ -0,0 +1,95 @@
package cn.iocoder.yudao.module.system.service.websocket;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import cn.iocoder.yudao.module.system.controller.admin.equipment.vo.websocket.WebsocketBaseVO;
import cn.iocoder.yudao.module.system.dal.dataobject.equipment.DistributeRecordDO;
import cn.iocoder.yudao.module.system.service.equipment.DistributeRecordService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xingyuv.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Collections;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REQUEST_FAILURE;
/**
* websocket Service 实现类
*/
@Service
@Slf4j
public class WebsocketServiceImpl implements WebsocketService{
@Resource
private DistributeRecordService recordService;
@Resource
private WebSocketSenderApi webSocketSenderApi;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
public void sendSn(String deviceNo, Object data, Integer type) {
String requestId = IdWorker.get32UUID();
WebsocketBaseVO baseVO = new WebsocketBaseVO()
.setFrom("")
.setTo(deviceNo)
.setExtra(requestId + "_" + getLoginUserId())
.setData(data);
// 设置 设备下发记录
DistributeRecordDO recordDO = new DistributeRecordDO();
recordDO.setRequestId(requestId);
recordDO.setDeviceNo(deviceNo);
recordDO.setUserId(getLoginUserId());
recordDO.setType(type);
recordDO.setResult("通讯失败");
// 更新下发记录信息
recordService.createDistributeRecord(Collections.singletonList(recordDO));
// 设备租户ID
TenantContextHolder.setTenantId(1L);
stringRedisTemplate.opsForValue().set(deviceNo, "true");
// 发送修改密码命令给设备
webSocketSenderApi.sendSN(deviceNo, "attendance-message-send", JsonUtils.toJsonString(baseVO));
Long startTime = System.currentTimeMillis();
while (true) {
String result = stringRedisTemplate.opsForValue().get(deviceNo);
if (StringUtil.isEmpty(result)) {
return;
}
if ("false".equals(result)) {
String msg = stringRedisTemplate.opsForValue().get(deviceNo + "msg").split("_")[1];
// 清楚 redis缓存
stringRedisTemplate.delete(deviceNo);
stringRedisTemplate.delete(deviceNo + "msg");
throw new RuntimeException(msg);
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Long currentTime = System.currentTimeMillis();
if (currentTime - startTime > 30000) {
throw exception(REQUEST_FAILURE);
}
}
}
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.smartfactory.api.factoryInfo;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO;
import cn.iocoder.yudao.module.smartfactory.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Collection;
import java.util.List;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@Tag(name = "RPC 服务 - 考勤设备")
public interface FactoryInfoApi {
String PREFIX = ApiConstants.PREFIX + "/factory-info";
@GetMapping(PREFIX + "/get")
@Operation(summary = "获得工厂信息")
CommonResult<FactoryInfoDTO> getFactoryInfo(@RequestParam("factoryId") Long factoryId);
@GetMapping(PREFIX + "/get-list")
@Operation(summary = "获得工厂信息列表")
CommonResult<List<FactoryInfoDTO>> getFactoryInfoList(@RequestParam("factoryId") Collection<Long> factoryId);
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "RPC 服务 - 工厂信息 DTO")
@Data
public class FactoryInfoDTO {
@Schema(description = "工厂编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100009")
private Long id;
@Schema(description = "工厂名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "江西省南昌市第一工厂")
private String name;
@Schema(description = "工厂简称", requiredMode = Schema.RequiredMode.REQUIRED, example = "第一工厂")
private String shortName;
@Schema(description = "工厂类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String type;
}

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.smartfactory.enums;
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
/**
* API 相关的枚举
*
*/
public class ApiConstants {
/**
* 服务名
*
* 注意需要保证和 spring.application.name 保持一致
*/
public static final String NAME = "smartfactory-server";
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/smartfactory";
public static final String VERSION = "1.0.0";
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.smartfactory.api.factoryInfo;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO;
import cn.iocoder.yudao.module.smartfactory.dal.dataobject.factoryinfo.FactoryInfoDO;
import cn.iocoder.yudao.module.smartfactory.service.factoryinfo.FactoryInfoService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
public class FactoryInfoApiImpl implements FactoryInfoApi {
@Resource
private FactoryInfoService factoryInfoService;
@Override
public CommonResult<FactoryInfoDTO> getFactoryInfo(Long factoryId) {
FactoryInfoDO factoryInfoDO = factoryInfoService.getFactoryInfo(factoryId);
return success(BeanUtils.toBean(factoryInfoDO, FactoryInfoDTO.class));
}
@Override
public CommonResult<List<FactoryInfoDTO>> getFactoryInfoList(Collection<Long> factoryId) {
List<FactoryInfoDO> factoryInfoDOS = factoryInfoService.getFactoryList(factoryId);
return success(BeanUtils.toBean(factoryInfoDOS, FactoryInfoDTO.class));
}
}

View File

@ -32,6 +32,7 @@ import java.util.List;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@Tag(name = "管理后台 - 工厂出库入库数据")
@ -146,15 +147,15 @@ public class FactoryDataController {
// 获取工厂信息
List<FactoryInfoDO> factoryInfoDOS = factoryInfoService.getFactoryListByType();
List<String> factory = factoryInfoDOS.stream().map(info -> info.getId() + ":" + info.getShortName()).collect(Collectors.toList());
List<String> factory = convertList(factoryInfoDOS, FactoryInfoDO::getShortName);
// 获取规格信息
List<SizeDO> sizeDOS = sizeService.getListSize();
List<String> size = sizeDOS.stream().map(info -> info.getId() + ":" + info.getName()).collect(Collectors.toList());
// 输出
ExcelUtils.write(response, "出入库数据导入模板.xlsx", "详情",
FactoryDataExportVO.class, null,
ExcelUtils.write(response, "出入库数据导入模板.xls", "详情",
FactoryDataImportVO.class, null,
0, factory,
2, size);
}

View File

@ -1,14 +1,20 @@
package cn.iocoder.yudao.module.smartfactory.controller.admin.factorydata.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import javax.swing.border.TitledBorder;
import java.time.LocalDate;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 出入库数据导入 VO
*/
@ -22,7 +28,8 @@ public class FactoryDataImportVO {
@ExcelProperty("工厂名称")
private String factoryName;
@ExcelProperty("日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
@ExcelProperty(value = "日期")
private LocalDate date;
@ExcelProperty("规格")

View File

@ -33,12 +33,14 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.smartfactory.enums.ErrorCodeConstants.*;
@ -225,7 +227,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
groupedByFactoryIdAndDate.forEach((factoryId, dateMap) -> {
//按日期倒叙 并遍历
dateMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach((date) -> {
dateMap.entrySet().stream().sorted(Map.Entry.<LocalDate, List<FactoryDataInfoRespVO>>comparingByKey().reversed()).forEach((date) -> {
FactoryDataDetailRespVO dataDetailRespVO = new FactoryDataDetailRespVO();
@ -324,25 +326,25 @@ public class FactoryDataServiceImpl implements FactoryDataService {
list.forEach(data -> {
//校验判断是否有不符合的原因
Long factoryId = null;
try {
validateFactoryForCreate(data.getFactoryName(), data.getSizeName(), data.getDate());
factoryId = validateFactoryForCreate(data.getFactoryName(), data.getSizeName(), data.getDate());
} catch (ServiceException ex) {
respVO.getFailureUsernames().put(data.getFactoryName(), ex.getMessage());
return;
}
// 获取 工厂ID
Long factoryId = Long.valueOf(data.getFactoryName().split(":")[0]);
// 获取 规格ID
Long sizeId = Long.valueOf(data.getSizeName().split(":")[0]);
// 获取 规格名称
String sizeName = data.getSizeName().split(":")[1];
PackageDO packageDO = packageService.getPackageByFactoryIdAndSize(factoryId, sizeId);
if (data.getNum() != null || data.getAutoNum() != null) {
if (packageDO != null && (data.getNum() != null || data.getAutoNum() != null)) {
PackageDataDO packageDataDO = BeanUtils.toBean(packageDO, PackageDataDO.class);
packageDataDO.setId(null);
packageDataDO.setPackageDate(data.getDate());
packageDataDO.setPackageId(packageDO.getId());
packageDataDO.setPackageName(packageDO.getName());
@ -350,6 +352,9 @@ public class FactoryDataServiceImpl implements FactoryDataService {
packageDataDO.setNum(data.getNum());
packageDataDO.setAutoNum(data.getAutoNum());
packageDataDO.setDamageNum(data.getDamageNum());
packageDataDO.setCreator(getLoginUserId().toString());
packageDataDO.setUpdater(null);
packageDataDO.setCreateTime(LocalDateTime.now());
//计算平方数
String[] size = sizeName.split("\\*");
@ -372,7 +377,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
FactoryDataSizeDO dataSizeDO = new FactoryDataSizeDO();
//设置规格信息
dataSizeDO.setId(sizeId);
dataSizeDO.setSizeId(sizeId);
dataSizeDO.setSizeName(sizeName);
dataSizeDO.setSizePieces(packageDO == null ? null : packageDO.getSizePieces());
//设置工厂和日期
@ -389,7 +394,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
FactoryDataSizeDO dataSizeDO = new FactoryDataSizeDO();
//设置规格信息
dataSizeDO.setId(sizeId);
dataSizeDO.setSizeId(sizeId);
dataSizeDO.setSizeName(sizeName);
dataSizeDO.setSizePieces(packageDO == null ? null : packageDO.getSizePieces());
//设置工厂和日期
@ -406,7 +411,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
FactoryDataSizeDO dataSizeDO = new FactoryDataSizeDO();
//设置规格信息
dataSizeDO.setId(sizeId);
dataSizeDO.setSizeId(sizeId);
dataSizeDO.setSizeName(sizeName);
//设置工厂和日期
dataSizeDO.setFactoryId(factoryId);
@ -422,7 +427,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
FactoryDataSizeDO dataSizeDO = new FactoryDataSizeDO();
//设置规格信息
dataSizeDO.setId(sizeId);
dataSizeDO.setSizeId(sizeId);
dataSizeDO.setSizeName(sizeName);
//设置工厂和日期
dataSizeDO.setFactoryId(factoryId);
@ -443,7 +448,7 @@ public class FactoryDataServiceImpl implements FactoryDataService {
return respVO;
}
private void validateFactoryForCreate(String factoryName, String sizeName, LocalDate date) {
private Long validateFactoryForCreate(String factoryName, String sizeName, LocalDate date) {
if (factoryName == null) {
throw exception(FACTORY_INFO_NOT_EXISTS);
@ -453,13 +458,15 @@ public class FactoryDataServiceImpl implements FactoryDataService {
throw exception(SIZE_NOT_EXISTS);
}
String factoryId = factoryName.split(":")[0];
FactoryInfoDO factoryInfoDO = factoryInfoService.getFactoryByName(factoryName);
Long count = factoryDataSizeMapper.selectCountByType(Long.valueOf(factoryId), date, Arrays.asList(1,2,3,4));
List<PackageDataDO> packageDOs = packageDataService.getListByFactoryIdAndDate(Long.valueOf(factoryId), date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
Long count = factoryDataSizeMapper.selectCountByType(factoryInfoDO.getId(), date, Arrays.asList(1,2,3,4));
List<PackageDataDO> packageDOs = packageDataService.getListByFactoryIdAndDate(factoryInfoDO.getId(), date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
if (count > 0L || !packageDOs.isEmpty()) {
throw exception(PACKAGE_DATA_EXISTS);
}
return factoryInfoDO.getId();
}
}

View File

@ -105,4 +105,11 @@ public interface FactoryInfoService {
* @return 工厂列表
*/
List<FactoryInfoDO> getFactoryListByAuthority();
/**
* 获得指定工厂信息
* @param factoryName 工厂简称
* @return 工厂信息
*/
FactoryInfoDO getFactoryByName(String factoryName);
}

View File

@ -216,4 +216,10 @@ public class FactoryInfoServiceImpl implements FactoryInfoService {
return factoryInfoMapper.selectListByType(factoryIds);
}
@Override
public FactoryInfoDO getFactoryByName(String factoryName) {
return factoryInfoMapper.selectOne(FactoryInfoDO::getShortName, factoryName);
}
}

View File

@ -77,7 +77,6 @@
</if>
</if>
</where>
GROUP BY a.id,a.factory_id,a.package_name,a.package_date,a.size_id,a.size_name,a.size_pieces
UNION
@ -109,7 +108,7 @@
FROM sf_package_data
WHERE
size_id = c.size_id
AND size_pieces != c.size_pieces
AND size_pieces = c.size_pieces
AND package_date = c.date
)
AND c.deleted = 0
@ -133,6 +132,7 @@
</if>
</if>
GROUP BY c.factory_id,c.date,c.size_id,c.size_name
ORDER BY date DESC
</select>
<select id="selectSUMByDateTimes" resultType="cn.iocoder.yudao.module.smartfactory.controller.admin.factorydata.vo.FactoryDataInfoRespVO">