| | |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto; |
| | | import com.ruoyi.production.dto.ProcessSchedulingDto; |
| | | import com.ruoyi.production.dto.ProductionDispatchAddDto; |
| | | import com.ruoyi.production.dto.SalesLedgerSchedulingDto; |
| | | import com.ruoyi.production.dto.SalesLedgerSchedulingProcessDto; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.production.dto.*; |
| | | import com.ruoyi.production.mapper.SalesLedgerSchedulingMapper; |
| | | import com.ruoyi.production.mapper.SalesLedgerWorkMapper; |
| | | import com.ruoyi.production.mapper.SpeculativeTradingInfoMapper; |
| | | import com.ruoyi.production.pojo.SalesLedgerScheduling; |
| | | import com.ruoyi.production.pojo.SalesLedgerWork; |
| | | import com.ruoyi.production.pojo.SpeculativeTradingInfo; |
| | | import com.ruoyi.production.service.SalesLedgerSchedulingService; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.sales.mapper.LossMapper; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.sales.pojo.Loss; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.concurrent.atomic.AtomicReference; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | |
| | | .filter(j -> j.getSalesLedgerProductId().equals(i.getSalesLedgerProductId())) |
| | | .map(SalesLedgerWork::getFinishedNum) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | // 状态 = 数量和完工数量比较 |
| | | if(i.getSchedulingNum().compareTo(new BigDecimal(0)) == 0){ |
| | | i.setStatus("未完成"); |
| | | } else if(i.getSchedulingNum().compareTo(i.getSuccessNum()) == 0){ |
| | | i.setStatus("已完成"); |
| | | }else{ |
| | | i.setStatus("生产中"); |
| | | } |
| | | // 计算生产总量 = 规格 * 数量 / 1000 |
| | | String[] split = i.getSpecificationModel().split("\\*"); |
| | | if(split.length == 2 && isNumeric(split[0]) && isNumeric(split[1])){ |
| | | BigDecimal multiply = new BigDecimal(split[0]) |
| | | .multiply(new BigDecimal(split[1]) |
| | | .multiply(i.getQuantity()).divide(new BigDecimal(1000),2, RoundingMode.CEILING)); |
| | | i.setTotalProduction(multiply); |
| | | } |
| | | |
| | | }); |
| | | return list; |
| | | } |
| | | |
| | | public static boolean isNumeric(String str) { |
| | | if (str == null || str.isEmpty()) { |
| | | return false; |
| | | } |
| | | // 遍历字符串的每个字符,检查是否为数字 |
| | | for (int i = 0; i < str.length(); i++) { |
| | | if (!Character.isDigit(str.charAt(i))) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | |
| | | |
| | | private final SysUserMapper sysUserMapper; |
| | | |
| | | private final SpeculativeTradingInfoMapper speculativeTradingInfoMapper; |
| | | |
| | | @Override |
| | | public int productionDispatch(ProductionDispatchAddDto productionDispatchAddDto) { |
| | | SysUser sysUser = sysUserMapper.selectUserById(productionDispatchAddDto.getSchedulingUserId()); |
| | | if(sysUser == null) throw new RuntimeException("排产人不存在"); |
| | | SalesLedgerScheduling salesLedgerScheduling = SalesLedgerScheduling.builder() |
| | | .salesLedgerId(productionDispatchAddDto.getSalesLedgerId()) |
| | | .salesLedgerProductId(productionDispatchAddDto.getSalesLedgerProductId()) |
| | | .schedulingUserId(productionDispatchAddDto.getSchedulingUserId()) |
| | | .schedulingUserName(sysUser.getNickName()) |
| | | .schedulingNum(productionDispatchAddDto.getSchedulingNum()) |
| | | .schedulingDate(LocalDate.parse(productionDispatchAddDto.getSchedulingDate(), DateTimeFormatter.ISO_LOCAL_DATE)) |
| | | .status(1) |
| | | .build(); |
| | | return salesLedgerSchedulingMapper.insert(salesLedgerScheduling); |
| | | public String productionDispatch(List<ProductionDispatchAddDto> productionDispatchAddDtoList) { |
| | | int i = 0; |
| | | int successNum = 0; |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | for (ProductionDispatchAddDto productionDispatchAddDto : productionDispatchAddDtoList) { |
| | | SysUser sysUser = sysUserMapper.selectUserById(productionDispatchAddDto.getSchedulingUserId() == null ? loginUser.getUser().getUserId() : productionDispatchAddDto.getSchedulingUserId()); |
| | | if(sysUser == null){ |
| | | i++; |
| | | continue; |
| | | } |
| | | // 获取空余炒机 |
| | | String[] split = productionDispatchAddDto.getSpeculativeTradingName().split(","); |
| | | if(split != null && split.length == 0){ |
| | | i++; |
| | | continue; |
| | | } |
| | | List<SpeculativeTradingInfo> speculativeTradingInfos = speculativeTradingInfoMapper.selectList(new LambdaQueryWrapper<SpeculativeTradingInfo>() |
| | | .in(SpeculativeTradingInfo::getName, Arrays.asList(split)) |
| | | .orderByAsc(SpeculativeTradingInfo::getSort)); |
| | | if(CollectionUtils.isEmpty(speculativeTradingInfos)){ |
| | | i++; |
| | | continue; |
| | | } |
| | | AtomicReference<String> name = new AtomicReference<>(""); //需要绑定的炒机 |
| | | //通过规格型号和排产数量计算本次生产产量 |
| | | String[] split1 = productionDispatchAddDto.getSpecificationModel().split("\\*"); |
| | | if(split1.length != 2){ |
| | | i++; |
| | | continue; |
| | | } |
| | | // 本次生产产量 |
| | | BigDecimal productionNum = new BigDecimal(split1[0]) |
| | | .multiply(new BigDecimal(split1[1]).multiply(productionDispatchAddDto.getSchedulingNum())); |
| | | // 多个炒机情况 |
| | | if(speculativeTradingInfos.size() > 1){ |
| | | for (SpeculativeTradingInfo speculativeTradingInfo : speculativeTradingInfos) { |
| | | // 获取该炒机正在排产量 |
| | | BigDecimal schedulingNumBySpeculativeTradingName = getSchedulingNumBySpeculativeTradingName(speculativeTradingInfo.getName()); |
| | | // 如果该炒机总量(单位kg需要乘1000) - 正在排产量 >=本次生产产量就分配此炒机 |
| | | if(speculativeTradingInfo.getWorkLoad().multiply(new BigDecimal(1000)).subtract(schedulingNumBySpeculativeTradingName).compareTo(productionNum) >= 0){ |
| | | name.set(speculativeTradingInfo.getName()); |
| | | break; |
| | | } |
| | | } |
| | | }else{ |
| | | // 单个炒机情况 |
| | | name.set(speculativeTradingInfos.get(0).getName()); |
| | | } |
| | | if(name.get().isEmpty()){ |
| | | i++; |
| | | continue; |
| | | } |
| | | SalesLedgerScheduling salesLedgerScheduling = SalesLedgerScheduling.builder() |
| | | .salesLedgerId(productionDispatchAddDto.getSalesLedgerId()) |
| | | .salesLedgerProductId(productionDispatchAddDto.getSalesLedgerProductId()) |
| | | .speculativeTradingName(name.get()) |
| | | .schedulingUserId(sysUser.getUserId()) |
| | | .schedulingUserName(sysUser.getNickName()) |
| | | .schedulingNum(productionDispatchAddDto.getSchedulingNum()) |
| | | .schedulingDate(productionDispatchAddDto.getSchedulingDate() == null ? LocalDate.now() : LocalDate.parse(productionDispatchAddDto.getSchedulingDate(), DateTimeFormatter.ofPattern("yyyy-MM-dd"))) |
| | | .status(1) |
| | | .build(); |
| | | salesLedgerSchedulingMapper.insert(salesLedgerScheduling); |
| | | successNum++; |
| | | } |
| | | |
| | | return "派工成功数量" + successNum + ",失败数量" + i; |
| | | } |
| | | |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | |
| | | /** |
| | | *通过炒机名称获取当天正在排产量 |
| | | * @return |
| | | */ |
| | | public BigDecimal getSchedulingNumBySpeculativeTradingName(String speculativeTradingName){ |
| | | LambdaQueryWrapper<SalesLedgerScheduling> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(SalesLedgerScheduling::getSpeculativeTradingName, speculativeTradingName) |
| | | .eq(SalesLedgerScheduling::getSchedulingDate, LocalDate.now()); |
| | | List<SalesLedgerScheduling> salesLedgerSchedulings = salesLedgerSchedulingMapper.selectList(queryWrapper); |
| | | if(CollectionUtils.isEmpty(salesLedgerSchedulings)){ |
| | | return BigDecimal.ZERO; |
| | | } |
| | | List<Long> collect = salesLedgerSchedulings.stream().map(SalesLedgerScheduling::getSalesLedgerProductId).collect(Collectors.toList()); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>() |
| | | .in(SalesLedgerProduct::getId, collect)); |
| | | if(CollectionUtils.isEmpty(salesLedgerProducts)) return BigDecimal.ZERO; |
| | | AtomicInteger totalNum = new AtomicInteger(0); //总数 |
| | | salesLedgerSchedulings.forEach(item ->{ |
| | | List<SalesLedgerProduct> collect1 = salesLedgerProducts.stream() |
| | | .filter(j -> j.getId().equals(item.getSalesLedgerProductId())) |
| | | .collect(Collectors.toList()); |
| | | if(!CollectionUtils.isEmpty(collect1)){ |
| | | SalesLedgerProduct salesLedgerProduct = collect1.get(0); |
| | | // 根据产品规格 * 排产数量 获取本次生产产量并累计 |
| | | String[] split = salesLedgerProduct.getSpecificationModel().split("\\*"); |
| | | BigDecimal productionNum = new BigDecimal(split[0]) |
| | | .multiply(new BigDecimal(split[1]).multiply(item.getSchedulingNum())); |
| | | totalNum.addAndGet(productionNum.intValue()); |
| | | } |
| | | }); |
| | | // 需要 / 损耗率 |
| | | Loss loss = lossMapper.selectOne(new LambdaQueryWrapper<Loss>().last("limit 1")); |
| | | BigDecimal lossNum = loss == null ? new BigDecimal(6) : loss.getRate(); //没有损耗率则默认为6 |
| | | |
| | | return new BigDecimal(totalNum.get()).multiply(new BigDecimal(100)).divide(lossNum, 2,RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | private final LossMapper lossMapper; |
| | | |
| | | |
| | | /** |
| | | *通过批量炒机名称获取当天正在排产量 |
| | | * @return |
| | | */ |
| | | public BigDecimal getSchedulingNumBySpeculativeTradingNameList(List<String> speculativeTradingName){ |
| | | LambdaQueryWrapper<SalesLedgerScheduling> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.in(SalesLedgerScheduling::getSpeculativeTradingName, speculativeTradingName) |
| | | .eq(SalesLedgerScheduling::getSchedulingDate, LocalDate.now()); |
| | | List<SalesLedgerScheduling> salesLedgerSchedulings = salesLedgerSchedulingMapper.selectList(queryWrapper); |
| | | if(CollectionUtils.isEmpty(salesLedgerSchedulings)){ |
| | | return BigDecimal.ZERO; |
| | | } |
| | | List<Long> collect = salesLedgerSchedulings.stream().map(SalesLedgerScheduling::getSalesLedgerProductId).collect(Collectors.toList()); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>() |
| | | .in(SalesLedgerProduct::getId, collect)); |
| | | if(CollectionUtils.isEmpty(salesLedgerProducts)) return BigDecimal.ZERO; |
| | | AtomicInteger totalNum = new AtomicInteger(0); //总数 |
| | | salesLedgerSchedulings.forEach(item ->{ |
| | | List<SalesLedgerProduct> collect1 = salesLedgerProducts.stream() |
| | | .filter(j -> j.getId().equals(item.getSalesLedgerProductId())) |
| | | .collect(Collectors.toList()); |
| | | if(!CollectionUtils.isEmpty(collect1)){ |
| | | SalesLedgerProduct salesLedgerProduct = collect1.get(0); |
| | | // 根据产品规格 * 排产数量 获取本次生产产量并累计 |
| | | String[] split = salesLedgerProduct.getSpecificationModel().split("\\*"); |
| | | BigDecimal productionNum = new BigDecimal(split[0]) |
| | | .multiply(new BigDecimal(split[1]).multiply(item.getSchedulingNum())); |
| | | totalNum.addAndGet(productionNum.intValue()); |
| | | } |
| | | }); |
| | | return new BigDecimal(totalNum.get()); |
| | | } |
| | | |
| | | @Override |
| | |
| | | // salesLedgerWorkLambdaQueryWrapper.in(SalesLedgerWork::getSalesLedgerSchedulingId, collect) |
| | | // .ne(SalesLedgerWork::getStatus, 1); |
| | | // List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper); |
| | | // list.getRecords().forEach(i -> { |
| | | // // 获取完成数量 |
| | | // i.setSuccessNum(salesLedgerWorks |
| | | // .stream() |
| | | // .filter(j -> j.getSalesLedgerSchedulingId().equals(i.getId())) |
| | | // .map(SalesLedgerWork::getFinishedNum) |
| | | // .reduce(BigDecimal.ZERO, BigDecimal::add)); |
| | | // }); |
| | | list.getRecords().forEach(i -> { |
| | | // 计算生产总量 = 规格 * 数量 / 1000 |
| | | String[] split = i.getSpecificationModel().split("\\*"); |
| | | if(split.length == 2 && isNumeric(split[0]) && isNumeric(split[1])){ |
| | | BigDecimal multiply = new BigDecimal(split[0]) |
| | | .multiply(new BigDecimal(split[1]) |
| | | .multiply(i.getSuccessNum()).divide(new BigDecimal(1000),2, RoundingMode.CEILING)); |
| | | i.setTotalProduction(multiply); |
| | | } |
| | | }); |
| | | return list; |
| | | } |
| | | |
| | |
| | | SysUser sysUser = sysUserMapper.selectUserById(processSchedulingDto.getSchedulingUserId()); |
| | | if(sysUser == null) throw new RuntimeException("排产人不存在"); |
| | | salesLedgerScheduling.setFinishedNum(salesLedgerScheduling.getFinishedNum().add(processSchedulingDto.getSchedulingNum())); |
| | | LambdaQueryWrapper<SalesLedgerWork> salesLedgerWorkLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerWorkLambdaQueryWrapper.eq(SalesLedgerWork::getSalesLedgerSchedulingId, salesLedgerScheduling.getId()) |
| | | .ne(SalesLedgerWork::getStatus, 1); |
| | | List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper); |
| | | // LambdaQueryWrapper<SalesLedgerWork> salesLedgerWorkLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | // salesLedgerWorkLambdaQueryWrapper.eq(SalesLedgerWork::getSalesLedgerSchedulingId, salesLedgerScheduling.getId()) |
| | | // .ne(SalesLedgerWork::getStatus, 1); |
| | | // List<SalesLedgerWork> salesLedgerWorks = salesLedgerWorkMapper.selectList(salesLedgerWorkLambdaQueryWrapper); |
| | | if(salesLedgerScheduling.getSchedulingNum().compareTo(salesLedgerScheduling.getFinishedNum()) < 0){ |
| | | throw new RuntimeException("当前排产数量大于待排产数量,请仔细核对!"); |
| | | } |
| | |
| | | SalesLedgerWork.SalesLedgerWorkBuilder salesLedgerWorkBuilder = SalesLedgerWork.builder() |
| | | .salesLedgerSchedulingId(salesLedgerScheduling.getId()) |
| | | .salesLedgerId(salesLedgerScheduling.getSalesLedgerId()) |
| | | .remark(processSchedulingDto.getRemark()) |
| | | .type(processSchedulingDto.getType()) |
| | | .loss(processSchedulingDto.getLoss()) |
| | | .receive(processSchedulingDto.getReceive()) |
| | | .salesLedgerProductId(salesLedgerScheduling.getSalesLedgerProductId()) |
| | | .schedulingUserId(salesLedgerScheduling.getSchedulingUserId()) |
| | | .schedulingUserName(sysUser.getNickName()) |
| | |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Override |
| | | public void exportOne(HttpServletResponse response) { |
| | | List<SalesLedgerSchedulingDto> list = salesLedgerSchedulingMapper.list(); |
| | | if(CollectionUtils.isEmpty(list)){ |
| | | throw new RuntimeException("无导出数据"); |
| | | } |
| | | List<DaiDto> dais = new ArrayList<>(); |
| | | list.forEach(i -> { |
| | | DaiDto daiDto = new DaiDto(); |
| | | BeanUtils.copyProperties(i, daiDto); |
| | | // 获取待排产数量 |
| | | daiDto.setDaiNum(daiDto.getQuantity().subtract(i.getSchedulingNum())); |
| | | dais.add(daiDto); |
| | | }); |
| | | ExcelUtil<DaiDto> util = new ExcelUtil<>(DaiDto.class); |
| | | util.exportExcel(response, dais, "生产派工"); |
| | | } |
| | | } |