|
@@ -1,23 +1,61 @@
|
|
|
package com.sd.business.service.check.impl;
|
|
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.fjhx.file.entity.FileInfo;
|
|
|
+import com.fjhx.file.entity.ObsFile;
|
|
|
+import com.fjhx.file.service.FileInfoService;
|
|
|
+import com.fjhx.file.utils.ObsFileUtil;
|
|
|
+import com.ruoyi.common.constant.StatusConstant;
|
|
|
+import com.ruoyi.common.core.domain.BaseIdPo;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
+import com.ruoyi.common.utils.SecurityUtils;
|
|
|
import com.ruoyi.common.utils.wrapper.IWrapper;
|
|
|
+import com.sd.business.entity.bom.po.BomSpec;
|
|
|
import com.sd.business.entity.check.dto.CheckDto;
|
|
|
+import com.sd.business.entity.check.dto.CheckImportDataDto;
|
|
|
import com.sd.business.entity.check.dto.CheckSelectDto;
|
|
|
import com.sd.business.entity.check.po.Check;
|
|
|
import com.sd.business.entity.check.po.CheckBom;
|
|
|
+import com.sd.business.entity.check.vo.CheckBomVo;
|
|
|
+import com.sd.business.entity.check.vo.CheckImportDataVo;
|
|
|
import com.sd.business.entity.check.vo.CheckVo;
|
|
|
+import com.sd.business.entity.department.constant.DepartmentConstant;
|
|
|
+import com.sd.business.entity.in.dto.InOutStorageDto;
|
|
|
+import com.sd.business.entity.in.emums.InDetailTypeEnum;
|
|
|
+import com.sd.business.entity.in.emums.InOutTypeEnum;
|
|
|
+import com.sd.business.entity.in.emums.OutDetailTypeEnum;
|
|
|
+import com.sd.business.entity.in.po.InOutStorageBom;
|
|
|
+import com.sd.business.entity.inventory.dto.InventorySelectDto;
|
|
|
+import com.sd.business.entity.inventory.po.Inventory;
|
|
|
+import com.sd.business.entity.inventory.vo.InventoryVo;
|
|
|
import com.sd.business.entity.warehouse.po.Warehouse;
|
|
|
import com.sd.business.mapper.check.CheckMapper;
|
|
|
+import com.sd.business.service.bom.BomSpecService;
|
|
|
import com.sd.business.service.check.CheckBomService;
|
|
|
import com.sd.business.service.check.CheckService;
|
|
|
+import com.sd.business.service.in.InOutStorageService;
|
|
|
+import com.sd.business.service.inventory.InventoryService;
|
|
|
+import com.sd.business.service.warehouse.WarehouseService;
|
|
|
+import com.sd.business.upload.ObsUploadService;
|
|
|
+import com.sd.business.util.CodeEnum;
|
|
|
+import com.sd.framework.util.Assert;
|
|
|
+import com.sd.framework.util.excel.util.ExcelUtil;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
-import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
-import java.util.List;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -34,12 +72,30 @@ public class CheckServiceImpl extends ServiceImpl<CheckMapper, Check> implements
|
|
|
@Autowired
|
|
|
private CheckBomService checkBomService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private InventoryService inventoryService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private BomSpecService bomSpecService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WarehouseService warehouseService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private InOutStorageService inOutStorageService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FileInfoService fileInfoService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ObsUploadService obsUploadService;
|
|
|
+
|
|
|
@Override
|
|
|
public Page<CheckVo> getPage(CheckSelectDto dto) {
|
|
|
IWrapper<Check> wrapper = getWrapper();
|
|
|
wrapper.orderByDesc("c", Check::getId);
|
|
|
wrapper.eq("c", Check::getDepartmentId, dto.getDepartmentId());
|
|
|
- wrapper.like("w", Warehouse::getName, dto.getWarehouseName());
|
|
|
+ wrapper.eq("w", Warehouse::getId, dto.getWarehouseId());
|
|
|
wrapper.eq("c", Check::getStatus, dto.getStatus());
|
|
|
wrapper.ge("c", Check::getCreateTime, dto.getBeginTime());
|
|
|
wrapper.le("c", Check::getCreateTime, dto.getEndTime());
|
|
@@ -48,30 +104,176 @@ public class CheckServiceImpl extends ServiceImpl<CheckMapper, Check> implements
|
|
|
return page;
|
|
|
}
|
|
|
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
+ @DSTransactional
|
|
|
@Override
|
|
|
public void add(CheckDto checkDto) {
|
|
|
long checkId = IdWorker.getId();
|
|
|
checkDto.setId(checkId);
|
|
|
+ checkDto.setCode(CodeEnum.CHECK_CODE.getCode());
|
|
|
checkDto.setStatus(0);
|
|
|
|
|
|
List<CheckBom> checkBomList = checkDto.getCheckBomList();
|
|
|
for (CheckBom checkBom : checkBomList) {
|
|
|
checkBom.setCheckId(checkId);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CheckBom> checkShortagesBomList = checkBomList.stream().filter(item -> Objects.equals(item.getStatus(), 3)).collect(Collectors.toList());
|
|
|
+ if (ObjectUtil.isNotEmpty(checkShortagesBomList)) {
|
|
|
+ List<InOutStorageBom> outStorageBomList = checkShortagesBomList.stream().map(item -> {
|
|
|
+ InOutStorageBom inOutStorageBom = new InOutStorageBom();
|
|
|
+ inOutStorageBom.setBomSpecId(item.getBomSpecId());
|
|
|
+ inOutStorageBom.setQuantity(item.getSurplusStock().subtract(item.getCheckQuantity()));
|
|
|
+ return inOutStorageBom;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ // 出库盘亏数据
|
|
|
+ InOutStorageDto OutStorageDto = new InOutStorageDto();
|
|
|
+ OutStorageDto.setType(InOutTypeEnum.OUT.getKey());
|
|
|
+ OutStorageDto.setDetailType(OutDetailTypeEnum.INVENTORY_LOSS.getKey());
|
|
|
+ OutStorageDto.setWarehouseId(checkDto.getWarehouseId());
|
|
|
+ OutStorageDto.setDepartmentId(checkDto.getDepartmentId());
|
|
|
+ OutStorageDto.setApplicant(checkDto.getCheckTaker());
|
|
|
+ OutStorageDto.setLockStorage(StatusConstant.NO);
|
|
|
+ OutStorageDto.setInOutStorageBomList(outStorageBomList);
|
|
|
+ inOutStorageService.add(OutStorageDto);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 筛选出盘盈和盘亏数据
|
|
|
+ List<CheckBom> checkProfitBomList = checkBomList.stream().filter(item -> Objects.equals(item.getStatus(), 2)).collect(Collectors.toList());
|
|
|
+ if (ObjectUtil.isNotEmpty(checkProfitBomList)) {
|
|
|
+ List<InOutStorageBom> inStorageBomList = checkProfitBomList.stream().map(item -> {
|
|
|
+ InOutStorageBom inOutStorageBom = new InOutStorageBom();
|
|
|
+ inOutStorageBom.setBomSpecId(item.getBomSpecId());
|
|
|
+ inOutStorageBom.setQuantity(item.getCheckQuantity().subtract(item.getSurplusStock()));
|
|
|
+ return inOutStorageBom;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ // 入库盘盈数据
|
|
|
+ InOutStorageDto inStorageDto = new InOutStorageDto();
|
|
|
+ inStorageDto.setType(InOutTypeEnum.IN.getKey());
|
|
|
+ inStorageDto.setDetailType(InDetailTypeEnum.CHECK.getKey());
|
|
|
+ inStorageDto.setWarehouseId(checkDto.getWarehouseId());
|
|
|
+ inStorageDto.setDepartmentId(checkDto.getDepartmentId());
|
|
|
+ inStorageDto.setApplicant(checkDto.getCheckTaker());
|
|
|
+ inStorageDto.setInOutStorageBomList(inStorageBomList);
|
|
|
+ inOutStorageService.add(inStorageDto);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 新增盘点数据
|
|
|
+ this.save(checkDto);
|
|
|
+ checkBomService.saveBatch(checkBomList);
|
|
|
+ // 保存附件
|
|
|
+ ObsFileUtil.saveFile(checkDto.getExcelFile(), checkDto.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ @DSTransactional
|
|
|
+ @Override
|
|
|
+ public CheckImportDataVo checkImportData(MultipartFile file) {
|
|
|
+ List<CheckImportDataDto> list = ExcelUtil.read(file, CheckImportDataDto.class);
|
|
|
+ validatedImportData(list);
|
|
|
+ // 保存盘点单
|
|
|
+ CheckImportDataVo vo = new CheckImportDataVo();
|
|
|
+ vo.setStatus(0);
|
|
|
+ vo.setCheckTaker(SecurityUtils.getLoginUser().getUser().getNickName());
|
|
|
+ vo.setDepartmentId(DepartmentConstant.SD_SPORTS);
|
|
|
+ // 查询仓库
|
|
|
+ List<Warehouse> warehouseList = warehouseService.list();
|
|
|
+ String warehouseName = list.get(0).getWarehouseName();
|
|
|
+ Warehouse warehouse = warehouseList.stream().filter(item -> item.getName().equals(warehouseName)).findAny().orElse(null);;
|
|
|
+ if (warehouse == null) {
|
|
|
+ throw new ServiceException("未知仓库:" + warehouseName);
|
|
|
+ }
|
|
|
+ vo.setWarehouseId(warehouse.getId());
|
|
|
+
|
|
|
+ List<String> bomSpecCodes = list.stream().map(CheckImportDataDto::getBomSpecCode).collect(Collectors.toList());
|
|
|
+ Map<String, BomSpec> bomSpecMap = bomSpecService.mapKEntity(BomSpec::getCode, q -> q.in(BomSpec::getCode, bomSpecCodes));
|
|
|
+ List<Long> bomSpecIds = bomSpecMap.values().stream().map(BaseIdPo::getId).collect(Collectors.toList());
|
|
|
+ Map<Long, Inventory> inventoryMap = inventoryService.mapKEntity(Inventory::getBomSpecId,
|
|
|
+ q -> q.eq(Inventory::getDepartmentId, DepartmentConstant.SD_SPORTS)
|
|
|
+ .eq(Inventory::getWarehouseId, warehouse.getId())
|
|
|
+ .in(Inventory::getBomSpecId, bomSpecIds));
|
|
|
+ List<CheckBomVo> checkBomList = new ArrayList<>();
|
|
|
+ for (CheckImportDataDto dto : list) {
|
|
|
+ BomSpec bomSpec = bomSpecMap.get(dto.getBomSpecCode());
|
|
|
+ if (bomSpec == null) {
|
|
|
+ throw new ServiceException("未知bom品号:" + dto.getBomSpecCode());
|
|
|
+ }
|
|
|
+ Inventory inventory = inventoryMap.get(bomSpec.getId());
|
|
|
+ BigDecimal lockQuantity = inventory.getLockQuantity() == null ? BigDecimal.ZERO : inventory.getLockQuantity();
|
|
|
+ if (dto.getRealityQuantity().compareTo(lockQuantity) < 0) {
|
|
|
+ throw new ServiceException("导入失败,bom品号:" + dto.getBomSpecCode()+ ",锁定库存大于实际库存,请确认库存是否正常!");
|
|
|
+ }
|
|
|
+
|
|
|
+ CheckBomVo checkBom = new CheckBomVo();
|
|
|
+ checkBom.setBomSpecId(bomSpec.getId());
|
|
|
+ checkBom.setBomSpecCode(bomSpec.getCode());
|
|
|
+ checkBom.setBomSpecName(bomSpec.getName());
|
|
|
+ checkBom.setWarehouseName(warehouse.getName());
|
|
|
+ checkBom.setDepartmentName("胜德体育");
|
|
|
+ checkBom.setBalanceUnitPrice(inventory.getBalanceUnitPrice());
|
|
|
+ checkBom.setSurplusStock(inventory.getQuantity().add(lockQuantity));
|
|
|
+ checkBom.setCheckQuantity(dto.getRealityQuantity());
|
|
|
+
|
|
|
+ // 判断盘点状态
|
|
|
int compareTo = checkBom.getCheckQuantity().compareTo(checkBom.getSurplusStock());
|
|
|
if (compareTo == 0) {
|
|
|
checkBom.setStatus(1);
|
|
|
} else if (compareTo > 0) {
|
|
|
checkBom.setStatus(2);
|
|
|
- checkDto.setStatus(1);
|
|
|
+ vo.setStatus(1);
|
|
|
} else {
|
|
|
checkBom.setStatus(3);
|
|
|
- checkDto.setStatus(1);
|
|
|
+ vo.setStatus(1);
|
|
|
}
|
|
|
+ checkBomList.add(checkBom);
|
|
|
}
|
|
|
+ vo.setCheckBomList(checkBomList);
|
|
|
|
|
|
- this.save(checkDto);
|
|
|
- checkBomService.saveBatch(checkBomList);
|
|
|
+ // 保存上传文件
|
|
|
+ ByteArrayInputStream bis = null;
|
|
|
+ try {
|
|
|
+ bis = new ByteArrayInputStream(file.getBytes());
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ String fileName = file.getOriginalFilename();
|
|
|
+ String fileUrl = obsUploadService.uploadFileByte(bis, fileName);
|
|
|
+ // 保存文件
|
|
|
+ FileInfo fileInfo = new FileInfo();
|
|
|
+ fileInfo.setFileUrl(fileUrl);
|
|
|
+ fileInfo.setFileName(fileName);
|
|
|
+ fileInfoService.save(fileInfo);
|
|
|
+ // 新增附件列表
|
|
|
+ ObsFile obsFile = new ObsFile();
|
|
|
+ obsFile.setId(fileInfo.getId());
|
|
|
+ vo.setExcelFile(obsFile);
|
|
|
+
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void inventoryExportExcel(HttpServletResponse response, Long warehouseId) {
|
|
|
+ InventorySelectDto dto = new InventorySelectDto();
|
|
|
+ dto.setPageNum(1);
|
|
|
+ dto.setPageSize(999999999);
|
|
|
+ dto.setDepartmentId(DepartmentConstant.SD_SPORTS);
|
|
|
+ dto.setWarehouseId(warehouseId);
|
|
|
+ Page<InventoryVo> page = inventoryService.getPage(dto, "inventory");
|
|
|
+ List<InventoryVo> list = page.getRecords();
|
|
|
+ List<CheckImportDataDto> dataList = BeanUtil.copyToList(list, CheckImportDataDto.class);
|
|
|
+ ExcelUtil.export(response, DateUtil.format(new Date(), "yyyy-MM-dd盘点库存数据"), "库存数据", dataList, CheckImportDataDto.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validatedImportData(List<CheckImportDataDto> list) {
|
|
|
+ Assert.notEmpty(list, "盘点明细不能为空");
|
|
|
+ String warehouseName = null;
|
|
|
+ for (CheckImportDataDto checkImportDataDto : list) {
|
|
|
+ Assert.notNull(checkImportDataDto.getWarehouseName(), "盘点仓库名称不能为空");
|
|
|
+ if (warehouseName == null) {
|
|
|
+ warehouseName = checkImportDataDto.getWarehouseName();
|
|
|
+ }
|
|
|
+ Assert.eqTrue(warehouseName.equals(checkImportDataDto.getWarehouseName()), "盘点仓库名称不一致");
|
|
|
+ Assert.notNull(checkImportDataDto.getBomSpecCode(), "bom品号不能为空");
|
|
|
+ Assert.gtZero(checkImportDataDto.getRealityQuantity(), "实际库存数量不能为空或负数");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|