| | |
| | | package com.ruoyi.production.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | |
| | | private static final String PROCESS_VOLTAGE_SORT = "电压分选"; |
| | | private static final String PROCESS_OPTICAL_INSPECTION = "光检外观"; |
| | | private static final String PROCESS_PACKAGING = "包装"; |
| | | private static final String INPUT_WEIGHT_PARAMETER = "投入重量"; |
| | | private static final String INPUT_WEIGHT_FIELD = "inputWeight"; |
| | | private static final Object PRODUCT_MAIN_NO_LOCK = new Object(); |
| | | |
| | | private IQualityInspectService qualityInspectService; |
| | |
| | | |
| | | BigDecimal reportQty = dto.getQuantity(); |
| | | BigDecimal scrapQty = dto.getScrapQty() == null ? BigDecimal.ZERO : dto.getScrapQty(); |
| | | BigDecimal bomInputQty = dto.getInputWeight(); |
| | | if (bomInputQty == null) { |
| | | bomInputQty = resolveInputWeight(dto.getOtherData()); |
| | | } |
| | | if (reportQty == null || reportQty.compareTo(BigDecimal.ZERO) <= 0) { |
| | | throw new ServiceException("报工数量必须大于0"); |
| | | } |
| | |
| | | } |
| | | if (scrapQty.compareTo(reportQty) > 0) { |
| | | throw new ServiceException("报废数量不能大于报工数量"); |
| | | } |
| | | if (bomInputQty == null || bomInputQty.compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("产品结构投入数量不能小于0"); |
| | | } |
| | | |
| | | // 第二步:加载当前工序、工单、工艺路线和订单数据,并校验基础关联关系 |
| | |
| | | .collect(Collectors.toMap(ProductStructureDto::getId, Function.identity(), (a, b) -> a)); |
| | | } |
| | | |
| | | // 第七步-1:投入数量强制取前端传入的 bomInputQty |
| | | BigDecimal inputBaseQty = bomInputQty; |
| | | |
| | | for (ProductStructureDto productStructureDto : productStructureDtos) { |
| | | if (productStructureDto.getProductModelId() == null) { |
| | | throw new ServiceException("投入物料产品型号不能为空"); |
| | |
| | | throw new ServiceException("父级物料用量必须大于0"); |
| | | } |
| | | |
| | | BigDecimal needQty = childQty |
| | | .divide(parentQty, 6, RoundingMode.HALF_UP) |
| | | .multiply(reportQty); |
| | | BigDecimal needQty = inputBaseQty; |
| | | |
| | | ProductionProductInput productionProductInput = new ProductionProductInput(); |
| | | productionProductInput.setProductModelId(productStructureDto.getProductModelId()); |
| | | productionProductInput.setQuantity(needQty); |
| | | productionProductInput.setQuantity(needQty == null ? BigDecimal.ZERO : needQty); |
| | | productionProductInput.setProductMainId(productionProductMain.getId()); |
| | | productionProductInputMapper.insert(productionProductInput); |
| | | |
| | |
| | | needQty, |
| | | StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), |
| | | productionProductMain.getId(), |
| | | null, |
| | | null |
| | | ); |
| | | } |
| | |
| | | |
| | | return productionProductMainDtos; |
| | | } |
| | | |
| | | private BigDecimal resolveInputWeight(String otherData) { |
| | | if (StringUtils.isBlank(otherData)) { |
| | | return null; |
| | | } |
| | | Object parsed; |
| | | try { |
| | | parsed = JSON.parse(otherData); |
| | | } catch (Exception ex) { |
| | | throw new ServiceException("报工参数格式错误,无法解析投入重量"); |
| | | } |
| | | String inputWeight = StringUtils.trim(findParameterValue(parsed, INPUT_WEIGHT_PARAMETER)); |
| | | if (StringUtils.isBlank(inputWeight)) { |
| | | inputWeight = StringUtils.trim(findFieldValue(parsed, INPUT_WEIGHT_FIELD)); |
| | | } |
| | | if (StringUtils.isBlank(inputWeight)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return new BigDecimal(inputWeight); |
| | | } catch (NumberFormatException ex) { |
| | | throw new ServiceException("报工参数中的投入重量格式错误"); |
| | | } |
| | | } |
| | | |
| | | private String findParameterValue(Object node, String parameterItem) { |
| | | if (node instanceof JSONArray) { |
| | | JSONArray array = (JSONArray) node; |
| | | for (Object item : array) { |
| | | String value = findParameterValue(item, parameterItem); |
| | | if (StringUtils.isNotBlank(value)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | if (node instanceof JSONObject) { |
| | | JSONObject object = (JSONObject) node; |
| | | if (parameterItem.equals(StringUtils.trim(object.getString("parameterItem")))) { |
| | | String value = StringUtils.trim(object.getString("value")); |
| | | if (StringUtils.isNotBlank(value)) { |
| | | return value; |
| | | } |
| | | } |
| | | for (Object value : object.values()) { |
| | | String matched = findParameterValue(value, parameterItem); |
| | | if (StringUtils.isNotBlank(matched)) { |
| | | return matched; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private String findFieldValue(Object node, String fieldName) { |
| | | if (node instanceof JSONArray) { |
| | | JSONArray array = (JSONArray) node; |
| | | for (Object item : array) { |
| | | String value = findFieldValue(item, fieldName); |
| | | if (StringUtils.isNotBlank(value)) { |
| | | return value; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | if (node instanceof JSONObject) { |
| | | JSONObject object = (JSONObject) node; |
| | | Object fieldValue = object.get(fieldName); |
| | | if (fieldValue != null) { |
| | | String value = StringUtils.trim(String.valueOf(fieldValue)); |
| | | if (StringUtils.isNotBlank(value)) { |
| | | return value; |
| | | } |
| | | } |
| | | for (Object value : object.values()) { |
| | | String matched = findFieldValue(value, fieldName); |
| | | if (StringUtils.isNotBlank(matched)) { |
| | | return matched; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |