TaskStocktakingServiceImpl.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package com.jsh.erp.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4. import com.jsh.erp.datasource.dto.TaskStocktakingDTO;
  5. import com.jsh.erp.datasource.dto.TaskStocktakingItemQueryDTO;
  6. import com.jsh.erp.datasource.dto.TaskStocktakingQueryDTO;
  7. import com.jsh.erp.datasource.entities.*;
  8. import com.jsh.erp.datasource.mappers.*;
  9. import com.jsh.erp.datasource.pda.dto.PDATaskStocktakingItemDTO;
  10. import com.jsh.erp.datasource.pda.vo.PDATaskStocktakingItemVO;
  11. import com.jsh.erp.datasource.pda.vo.PDATaskStocktakingVO;
  12. import com.jsh.erp.datasource.vo.TaskStocktakingItemVO;
  13. import com.jsh.erp.datasource.vo.TaskStocktakingVO;
  14. import com.jsh.erp.query.LambdaQueryWrapperX;
  15. import com.jsh.erp.service.DepotService;
  16. import com.jsh.erp.service.SequenceService;
  17. import com.jsh.erp.service.TaskStocktakingService;
  18. import com.jsh.erp.service.UserService;
  19. import lombok.RequiredArgsConstructor;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.beans.BeanUtils;
  22. import org.springframework.stereotype.Service;
  23. import org.springframework.transaction.annotation.Transactional;
  24. import java.math.BigDecimal;
  25. import java.math.RoundingMode;
  26. import java.util.ArrayList;
  27. import java.util.Collections;
  28. import java.util.Date;
  29. import java.util.List;
  30. import java.util.stream.Collectors;
  31. @Service
  32. @RequiredArgsConstructor
  33. @Slf4j
  34. public class TaskStocktakingServiceImpl extends ServiceImpl<TaskStocktakingMapper, TaskStocktaking> implements TaskStocktakingService {
  35. private final MaterialExtendMapper materialExtendMapper;
  36. private final UserMapper userMapper;
  37. private final DepotService depotService;
  38. private final TaskStocktakingItemMapper taskStocktakingItemMapper;
  39. private final TaskStocktakingMapper taskStocktakingMapper;
  40. private final MaterialMapper materialMapper;
  41. private final UserService userService;
  42. private final SequenceService sequenceService;
  43. @Override
  44. public List<TaskStocktakingVO> listBy(TaskStocktakingQueryDTO taskStocktakingQueryDTO) {
  45. return taskStocktakingMapper.listBy(taskStocktakingQueryDTO);
  46. }
  47. /**
  48. * 创建盘点任务
  49. * @param taskStocktakingDTO
  50. * @return
  51. */
  52. @Override
  53. @Transactional(value = "transactionManager", rollbackFor = Exception.class)
  54. public boolean add(TaskStocktakingDTO taskStocktakingDTO) {
  55. try {
  56. List<String> collect;
  57. List<MaterialExtend> materialExtendList;
  58. //全盘,抽盘,处理任务明细
  59. if (taskStocktakingDTO.getTaskType() == 1) {
  60. materialExtendList = materialExtendMapper.selectList(new LambdaQueryWrapper<MaterialExtend>().ne(MaterialExtend::getInventory, BigDecimal.ZERO).isNotNull(MaterialExtend::getInventory));
  61. collect = materialExtendList
  62. .stream()
  63. .map(MaterialExtend::getPosition)
  64. .collect(Collectors.toList());
  65. List<Long> materialIdList = materialExtendList.stream().map(MaterialExtend::getMaterialId).distinct().collect(Collectors.toList());
  66. List<Material> materialList = materialMapper.selectList(new LambdaQueryWrapperX<Material>().eq(Material::getId, materialIdList));
  67. List<Long> categoryIdList = materialList.stream().map(Material::getCategoryId).distinct().collect(Collectors.toList());
  68. taskStocktakingDTO.setCategoryCount(categoryIdList.size());
  69. taskStocktakingDTO.setMaterialCount(materialExtendList.size());
  70. } else {
  71. materialExtendList = materialExtendMapper.selectList(new LambdaQueryWrapper<MaterialExtend>().in(MaterialExtend::getBatchNumber, taskStocktakingDTO.getMaterialExtendIdList()));
  72. collect = materialExtendList.stream().map(MaterialExtend::getPosition).collect(Collectors.toList());
  73. List<Long> materialIdList = materialExtendList.stream().map(MaterialExtend::getMaterialId).collect(Collectors.toList());
  74. List<Material> materialList = materialMapper.selectList(new LambdaQueryWrapperX<Material>().in(Material::getId, materialIdList));
  75. List<Long> categoryIdList = materialList.stream().map(Material::getCategoryId).distinct().collect(Collectors.toList());
  76. taskStocktakingDTO.setCategoryCount(categoryIdList.size());
  77. taskStocktakingDTO.setMaterialCount(materialExtendList.size());
  78. }
  79. //处理商品库位范围处理
  80. String positionRange = extractRangePair(collect);
  81. taskStocktakingDTO.setPositionRange(positionRange);
  82. User currentUser = userService.getCurrentUser();
  83. taskStocktakingDTO.setCreateBy(currentUser.getId());
  84. taskStocktakingDTO.setCreateTime(new Date());
  85. taskStocktakingDTO.setTaskStatus(1);
  86. //生成单据编号
  87. taskStocktakingDTO.setNumber("PDRW"+sequenceService.buildOnlyNumber());
  88. //生成任务
  89. this.save(taskStocktakingDTO);
  90. //生成任务明细
  91. List<TaskStocktakingItem> taskStocktakingItemList = new ArrayList<>();
  92. materialExtendList.forEach(item -> {
  93. TaskStocktakingItem taskStocktakingItem = new TaskStocktakingItem();
  94. taskStocktakingItem.setTaskStocktakingId(taskStocktakingDTO.getId());
  95. taskStocktakingItem.setMaterialItemId(item.getId());
  96. taskStocktakingItemList.add(taskStocktakingItem);
  97. });
  98. taskStocktakingItemMapper.insertBatch(taskStocktakingItemList);
  99. } catch (Exception e) {
  100. log.error("创建盘点任务失败", e);
  101. return false;
  102. }
  103. return true;
  104. }
  105. /**
  106. * 任务-详情
  107. * @param id 任务ID
  108. * @return
  109. * @throws Exception
  110. */
  111. @Override
  112. public TaskStocktakingVO detail(Long id) throws Exception{
  113. TaskStocktaking one = getOne(new LambdaQueryWrapperX<TaskStocktaking>().eq(TaskStocktaking::getId, id));
  114. TaskStocktakingVO taskStocktakingVO = new TaskStocktakingVO();
  115. BeanUtils.copyProperties(one, taskStocktakingVO);
  116. //获取负责人名称
  117. User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, one.getCreator()));
  118. if (user != null) {
  119. taskStocktakingVO.setCreatorName(user.getLoginName());
  120. }
  121. //获取创建人名称
  122. User user1 = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, one.getCreateBy()));
  123. if (user1 != null) {
  124. taskStocktakingVO.setCreateByName(user1.getLoginName());
  125. }
  126. //获取仓库名称
  127. Depot depot = depotService.getDepot(one.getDepotId());
  128. taskStocktakingVO.setDepotName(depot.getName());
  129. //当任务类型是抽盘时,返回商品盘点信息
  130. return taskStocktakingVO;
  131. }
  132. /**
  133. * 任务详情-修改
  134. * @param taskStocktakingDTO
  135. * @return
  136. */
  137. @Override
  138. public boolean detailUpdate(TaskStocktakingDTO taskStocktakingDTO) {
  139. try {
  140. List<String> collect;
  141. List<MaterialExtend> materialExtendList;
  142. //全盘,抽盘,处理任务明细
  143. if (taskStocktakingDTO.getTaskType() == 1) {
  144. materialExtendList = materialExtendMapper.selectList(new LambdaQueryWrapper<MaterialExtend>().ne(MaterialExtend::getInventory, BigDecimal.ZERO).isNotNull(MaterialExtend::getInventory));
  145. collect = materialExtendList
  146. .stream()
  147. .map(MaterialExtend::getPosition)
  148. .collect(Collectors.toList());
  149. List<Long> materialIdList = materialExtendList.stream().map(MaterialExtend::getMaterialId).distinct().collect(Collectors.toList());
  150. List<Material> materialList = materialMapper.selectList(new LambdaQueryWrapperX<Material>().eq(Material::getId, materialIdList));
  151. List<Long> categoryIdList = materialList.stream().map(Material::getCategoryId).distinct().collect(Collectors.toList());
  152. taskStocktakingDTO.setCategoryCount(categoryIdList.size());
  153. taskStocktakingDTO.setMaterialCount(materialExtendList.size());
  154. } else {
  155. materialExtendList = materialExtendMapper.selectList(new LambdaQueryWrapper<MaterialExtend>().in(MaterialExtend::getBatchNumber, taskStocktakingDTO.getMaterialExtendIdList()));
  156. collect = materialExtendList.stream().map(MaterialExtend::getPosition).collect(Collectors.toList());
  157. List<Long> materialIdList = materialExtendList.stream().map(MaterialExtend::getMaterialId).collect(Collectors.toList());
  158. List<Material> materialList = materialMapper.selectList(new LambdaQueryWrapperX<Material>().in(Material::getId, materialIdList));
  159. List<Long> categoryIdList = materialList.stream().map(Material::getCategoryId).distinct().collect(Collectors.toList());
  160. taskStocktakingDTO.setCategoryCount(categoryIdList.size());
  161. taskStocktakingDTO.setMaterialCount(materialExtendList.size());
  162. }
  163. //处理商品库位范围处理
  164. String positionRange = extractRangePair(collect);
  165. taskStocktakingDTO.setPositionRange(positionRange);
  166. User currentUser = userService.getCurrentUser();
  167. taskStocktakingDTO.setCreateBy(currentUser.getId());
  168. taskStocktakingDTO.setCreateTime(new Date());
  169. taskStocktakingDTO.setTaskStatus(1);
  170. //生成任务
  171. this.updateById(taskStocktakingDTO);
  172. List<Long> taskStocktakingItemIdList = taskStocktakingItemMapper.selectList(new LambdaQueryWrapperX<TaskStocktakingItem>().eq(TaskStocktakingItem::getTaskStocktakingId, taskStocktakingDTO.getId())).stream().map(TaskStocktakingItem::getId).collect(Collectors.toList());
  173. //生成任务明细
  174. List<TaskStocktakingItem> addTaskStocktakingItemList = new ArrayList<>();
  175. materialExtendList.forEach(item -> {
  176. if (!taskStocktakingItemIdList.contains(item.getId())) {
  177. TaskStocktakingItem taskStocktakingItem = new TaskStocktakingItem();
  178. taskStocktakingItem.setTaskStocktakingId(taskStocktakingDTO.getId());
  179. taskStocktakingItem.setMaterialItemId(item.getId());
  180. addTaskStocktakingItemList.add(taskStocktakingItem);
  181. }
  182. });
  183. List<Long> materialExtendIdList = materialExtendList.stream().map(MaterialExtend::getId).collect(Collectors.toList());
  184. taskStocktakingItemIdList.forEach(item -> {
  185. if (!materialExtendIdList.contains(item)) {
  186. TaskStocktakingItem taskStocktakingItem = new TaskStocktakingItem();
  187. taskStocktakingItem.setId(item);
  188. taskStocktakingItem.setDeleteFlag(true);
  189. taskStocktakingItemMapper.updateById(taskStocktakingItem);
  190. }
  191. });
  192. if (addTaskStocktakingItemList.size() > 0) {
  193. taskStocktakingItemMapper.insertBatch(addTaskStocktakingItemList);
  194. }
  195. } catch (Exception e) {
  196. log.error("修改盘点任务失败", e);
  197. return false;
  198. }
  199. return true;
  200. }
  201. /**
  202. * 任务详情-商品明细
  203. * @param taskStocktakingItemQueryDTO 筛选参数
  204. * @return
  205. */
  206. @Override
  207. public List<TaskStocktakingItemVO> listByTaskStocktakingId(TaskStocktakingItemQueryDTO taskStocktakingItemQueryDTO) {
  208. return taskStocktakingItemMapper.listByTaskStocktakingId(taskStocktakingItemQueryDTO);
  209. }
  210. /**
  211. * PDA-盘点任务列表
  212. * @param number 盘点单号或者任务名称
  213. * @param taskStatus 盘点任务状态
  214. * @return
  215. */
  216. @Override
  217. public List<PDATaskStocktakingVO> pdaList(String number , Integer taskStatus) {
  218. return taskStocktakingMapper.pdaList(number , taskStatus);
  219. }
  220. /**
  221. * PDA-盘点任务详情
  222. * @param id 盘点任务ID
  223. * @return
  224. * @throws Exception
  225. */
  226. @Override
  227. public TaskStocktakingVO pdaDetail(Long id) throws Exception{
  228. TaskStocktakingVO detail = detail(id);
  229. List<TaskStocktakingItem> itemList = taskStocktakingItemMapper.selectList(new LambdaQueryWrapper<TaskStocktakingItem>().eq(TaskStocktakingItem::getTaskStocktakingId, id));
  230. //已操作数量
  231. long finishCount = itemList.stream().filter(item -> item.getCreator() != null).count();
  232. //操作人数
  233. long operCount = itemList.stream().filter(item -> item.getCreator() != null).map(TaskStocktakingItem::getCreator).distinct().count();
  234. //商品总数量
  235. long itemCount = itemList.size();
  236. //商品差异条数
  237. long itemDifferenceCount = itemList.stream().filter(item -> item.getCreator() != null
  238. && item.getDifferenceCount() != null
  239. && item.getDifferenceCount() > 0).count();
  240. //差异率
  241. double differenceRate = 0;
  242. //准确率
  243. double accuracyRate = 100;
  244. if (itemDifferenceCount > 0) {
  245. //差异率 = 商品差异条数/商品总数量*100%
  246. differenceRate = BigDecimal.valueOf(itemDifferenceCount)
  247. .divide(BigDecimal.valueOf(itemCount), 4, RoundingMode.HALF_UP)
  248. .multiply(BigDecimal.valueOf(100))
  249. .doubleValue();
  250. //准确数 = 已操作数量-商品差异条数
  251. BigDecimal subtract = BigDecimal.valueOf(finishCount).subtract(BigDecimal.valueOf(itemDifferenceCount));
  252. //准确率 = 准确数/商品总数量*100%
  253. if (!subtract.equals(BigDecimal.ZERO)) {
  254. accuracyRate = subtract.divide(BigDecimal.valueOf(itemCount), 4, RoundingMode.HALF_UP)
  255. .multiply(BigDecimal.valueOf(100))
  256. .doubleValue();
  257. }
  258. }
  259. detail.setItemCount(itemCount);
  260. detail.setDifferenceRate(differenceRate);
  261. detail.setAccuracyRate(accuracyRate);
  262. detail.setFinishCount(finishCount);
  263. detail.setOperCount(operCount);
  264. return detail;
  265. }
  266. @Override
  267. public List<PDATaskStocktakingItemVO> pdaItemList(PDATaskStocktakingItemDTO pdaTaskStocktakingItemDTO) {
  268. return taskStocktakingItemMapper.pdaList(pdaTaskStocktakingItemDTO);
  269. }
  270. /**
  271. * 计算库位范围
  272. * @param data 库位集合
  273. * @return
  274. */
  275. public static String extractRangePair(List<String> data) {
  276. // 用于存储提取的前两部分
  277. List<String> rangeParts = new ArrayList<>();
  278. for (String item : data) {
  279. // 提取前两部分(假设格式固定,以 "-" 分割,取前两部分)
  280. String[] parts = item.split("-");
  281. if (parts.length >= 2) {
  282. String rangePart = parts[0] + "-" + parts[1];
  283. rangeParts.add(rangePart); // 添加到列表
  284. }
  285. }
  286. // 如果范围为空,直接返回空字符串
  287. if (rangeParts.isEmpty()) {
  288. return "";
  289. }
  290. // 找到最小和最大范围
  291. String minRange = Collections.min(rangeParts); // 字典序最小
  292. String maxRange = Collections.max(rangeParts); // 字典序最大
  293. // 返回范围对
  294. return minRange + "——" + maxRange;
  295. }
  296. }