src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -17,8 +17,6 @@ import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.service.ISalesLedgerProductService; import com.ruoyi.sales.service.ISalesLedgerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; @@ -143,4 +141,14 @@ ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class); excelUtil.importTemplateExcel(response, "产品规格导入模板"); } /** * 向下复制型号等 */ @Log(title = "向下复制型号等", businessType = BusinessType.INSERT) @PostMapping("/downCopy") public AjaxResult downCopy(@RequestBody ProductModelDto productModelDto) { return toAjax(productModelService.downCopy(productModelDto)); } } src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
@@ -9,4 +9,10 @@ @Data public class ProductModelDto extends ProductModel { private List<ProductStructureDto> productStructureList; //复制的目标产品id private Long targetProductId; //型号list private List<Long> modelListId; } src/main/java/com/ruoyi/basic/service/IProductModelService.java
@@ -35,4 +35,6 @@ IPage<ProductModel> modelListPage(Page page , ProductDto productDto); AjaxResult importProductModel(MultipartFile file, Integer productId); int downCopy(ProductModelDto productModelDto); } src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -155,4 +155,60 @@ throw new ServiceException("导入失败"); } } @Override @Transactional(rollbackFor = Exception.class) public int downCopy(ProductModelDto productModelDto) { if (productModelDto == null || productModelDto.getProductId() == null || productModelDto.getTargetProductId() == null) { throw new ServiceException("源产品ID和目标产品ID不能为空"); } Long sourceProductId = productModelDto.getProductId(); Long targetProductId = productModelDto.getTargetProductId(); List<Long> modelListId = productModelDto.getModelListId(); if (sourceProductId.equals(targetProductId)) { throw new ServiceException("源产品和目标产品不能相同"); } Product sourceProduct = productMapper.selectById(sourceProductId); if (sourceProduct == null) { throw new ServiceException("源产品不存在"); } Product targetProduct = productMapper.selectById(targetProductId); if (targetProduct == null) { throw new ServiceException("目标产品不存在"); } LambdaQueryWrapper<ProductModel> queryWrapper = new LambdaQueryWrapper<ProductModel>() .eq(ProductModel::getProductId, sourceProductId) .orderByAsc(ProductModel::getId); Set<Long> selectedModelIds = null; if (CollectionUtils.isNotEmpty(modelListId)) { selectedModelIds = new LinkedHashSet<>(modelListId); queryWrapper.in(ProductModel::getId, selectedModelIds); } List<ProductModel> sourceModels = productModelMapper.selectList(queryWrapper); if (CollectionUtils.isEmpty(sourceModels)) { throw new ServiceException("源产品下没有可复制的型号"); } if (selectedModelIds != null && sourceModels.size() != selectedModelIds.size()) { throw new ServiceException("部分型号不存在或不属于源产品"); } List<ProductModel> copyList = new ArrayList<>(); for (ProductModel sourceModel : sourceModels) { ProductModel copy = new ProductModel(); BeanUtils.copyProperties(sourceModel, copy); copy.setId(null); copy.setProductId(targetProductId); copy.setTenantId(null); copyList.add(copy); } saveBatch(copyList); return copyList.size(); } } src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -88,5 +88,5 @@ private String batchNo; @ApiModelProperty(value = "产品结构投入数量") private BigDecimal bomInputQty; private BigDecimal inputWeight; } src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -1,5 +1,8 @@ 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; @@ -52,6 +55,8 @@ 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; @@ -98,7 +103,10 @@ BigDecimal reportQty = dto.getQuantity(); BigDecimal scrapQty = dto.getScrapQty() == null ? BigDecimal.ZERO : dto.getScrapQty(); BigDecimal bomInputQty = dto.getBomInputQty(); BigDecimal bomInputQty = dto.getInputWeight(); if (bomInputQty == null) { bomInputQty = resolveInputWeight(dto.getOtherData()); } if (reportQty == null || reportQty.compareTo(BigDecimal.ZERO) <= 0) { throw new ServiceException("报工数量必须大于0"); } @@ -345,7 +353,7 @@ 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); @@ -761,4 +769,87 @@ 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; } } src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java
@@ -1,32 +1,22 @@ package com.ruoyi.sales.controller; import javax.servlet.http.HttpServletResponse; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.procurementrecord.dto.ProcurementPageDto; import com.ruoyi.procurementrecord.dto.ProcurementPageDtoCopy; import com.ruoyi.procurementrecord.service.ProcurementRecordService; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.sales.dto.SalesLedgerProductDto; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.service.ISalesLedgerProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.page.TableDataInfo; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.List; @@ -38,8 +28,7 @@ */ @RestController @RequestMapping("/sales/product") public class SalesLedgerProductController extends BaseController { public class SalesLedgerProductController extends BaseController { @Autowired private ISalesLedgerProductService salesLedgerProductService; @Autowired @@ -53,7 +42,7 @@ */ @GetMapping("/listPageSalesLedger") public AjaxResult listPage(Page page, SalesLedgerProductDto salesLedgerProduct) { IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPage(page,salesLedgerProduct); IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPage(page, salesLedgerProduct); return AjaxResult.success(list); } @@ -63,7 +52,7 @@ */ @GetMapping("/listPagePurchaseLedger") public AjaxResult listPagePurchaseLedger(Page page, SalesLedgerProductDto salesLedgerProduct) { IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPagePurchaseLedger(page,salesLedgerProduct); IPage<SalesLedgerProductDto> list = salesLedgerProductService.listPagePurchaseLedger(page, salesLedgerProduct); return AjaxResult.success(list); } @@ -104,8 +93,7 @@ */ @Log(title = "产品信息", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, SalesLedgerProduct salesLedgerProduct) { public void export(HttpServletResponse response, SalesLedgerProduct salesLedgerProduct) { List<SalesLedgerProduct> list = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct); ExcelUtil<SalesLedgerProduct> util = new ExcelUtil<SalesLedgerProduct>(SalesLedgerProduct.class); util.exportExcel(response, list, "产品信息数据"); @@ -115,8 +103,7 @@ * 获取产品信息详细信息 */ @GetMapping(value = "/{id}") public AjaxResult getInfo(@PathVariable("id") Long id) { public AjaxResult getInfo(@PathVariable("id") Long id) { return success(salesLedgerProductService.selectSalesLedgerProductById(id)); } @@ -124,9 +111,8 @@ * 新增修改产品信息 */ @Log(title = "产品信息", businessType = BusinessType.INSERT) @PostMapping ("/addOrUpdateSalesLedgerProduct") public AjaxResult add(@RequestBody SalesLedgerProduct salesLedgerProduct) { @PostMapping("/addOrUpdateSalesLedgerProduct") public AjaxResult add(@RequestBody SalesLedgerProduct salesLedgerProduct) { return toAjax(salesLedgerProductService.addOrUpdateSalesLedgerProduct(salesLedgerProduct)); } @@ -134,9 +120,8 @@ * 删除产品信息 */ @Log(title = "产品信息", businessType = BusinessType.DELETE) @DeleteMapping("/delProduct") public AjaxResult remove(@RequestBody Long[] ids) { @DeleteMapping("/delProduct") public AjaxResult remove(@RequestBody Long[] ids) { if (ids == null || ids.length == 0) { return AjaxResult.error("请传入要删除的ID"); } @@ -146,6 +131,11 @@ //根据产品id获取bom判断库存是否充足 @GetMapping("/judgmentInventory") public R judgmentInventory(SalesLedgerProduct salesLedgerProduct) { return salesLedgerProductService.judgmentInventory(salesLedgerProduct); return salesLedgerProductService.judgmentInventory(salesLedgerProduct); } @GetMapping("/getById") public R getById(SalesLedgerProduct salesLedgerProduct) { return R.ok(salesLedgerProductService.getById(salesLedgerProduct)); } } src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -1,12 +1,9 @@ package com.ruoyi.sales.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.approve.mapper.ApproveProcessMapper; import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl; import com.ruoyi.approve.vo.ApproveProcessVO; import com.ruoyi.common.enums.FileNameType; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; @@ -15,22 +12,14 @@ import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.other.service.impl.TempFileServiceImpl; import com.ruoyi.procurementrecord.utils.StockUtils; import com.ruoyi.sales.dto.ShippingInfoDto; import com.ruoyi.sales.mapper.ShipmentApprovalMapper; import com.ruoyi.sales.mapper.ShippingInfoMapper; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.pojo.ShipmentApproval; import com.ruoyi.sales.pojo.ShippingInfo; import com.ruoyi.sales.service.ISalesLedgerProductService; import com.ruoyi.sales.service.ISalesLedgerService; import com.ruoyi.sales.service.ShippingInfoService; import com.ruoyi.sales.service.impl.CommonFileServiceImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; @@ -64,7 +53,7 @@ @GetMapping("/listPage") @ApiOperation("发货信息列表") public AjaxResult listPage(Page page, ShippingInfo req) { IPage<ShippingInfoDto> listPage = shippingInfoService.listPage(page,req); IPage<ShippingInfoDto> listPage = shippingInfoService.listPage(page, req); return AjaxResult.success(listPage); } @@ -79,10 +68,13 @@ ApproveProcessVO approveProcessVO = new ApproveProcessVO(); approveProcessVO.setApproveType(7); approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId()); approveProcessVO.setApproveReason(req.getType() + ":" +sh); approveProcessVO.setApproveReason(req.getType() + ":" + sh); approveProcessVO.setApproveUserIds(req.getApproveUserIds()); approveProcessVO.setApproveUser(loginUser.getUserId()); approveProcessVO.setApproveTime(LocalDate.now().toString()); if (req.getSalesLedgerProductId() != null) { approveProcessVO.setRecordId(req.getSalesLedgerProductId()); } approveProcessService.addApprove(approveProcessVO); // 添加发货消息 req.setShippingNo(sh); @@ -96,7 +88,7 @@ @Transactional(rollbackFor = Exception.class) @Log(title = "发货信息管理", businessType = BusinessType.UPDATE) public AjaxResult deductStock(@RequestBody ShippingInfoDto req) throws IOException { return shippingInfoService.deductStock( req) ? AjaxResult.success() : AjaxResult.error(); return shippingInfoService.deductStock(req) ? AjaxResult.success() : AjaxResult.error(); } @PostMapping("/update") src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
@@ -1,10 +1,8 @@ package com.ruoyi.sales.dto; import com.baomidou.mybatisplus.annotation.TableField; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import com.ruoyi.sales.pojo.CommonFile; import com.ruoyi.sales.pojo.ShippingInfo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -263,6 +263,11 @@ @Override @Transactional(rollbackFor = Exception.class) public Boolean subtractStockInventory(StockInventoryDto stockInventoryDto) { if (stockInventoryDto.getQualitity() != null && stockInventoryDto.getQualitity().compareTo(BigDecimal.ZERO) == 0) { return true; } StockOutRecordDto stockOutRecordDto = new StockOutRecordDto(); stockOutRecordDto.setRecordId(stockInventoryDto.getRecordId()); stockOutRecordDto.setRecordType(stockInventoryDto.getRecordType()); @@ -298,7 +303,7 @@ throw new RuntimeException("产品库存不存在"); } BigDecimal remainingQty = stockInventoryDto.getQualitity(); BigDecimal remainingQty = stockInventoryDto.getQualitity() == null ? BigDecimal.ZERO : stockInventoryDto.getQualitity(); for (StockInventory stockInventory : stockInventories) { BigDecimal lockedQty = defaultDecimal(stockInventory.getLockedQuantity()); BigDecimal availableQty = defaultDecimal(stockInventory.getQualitity()).subtract(lockedQty); src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
@@ -89,7 +89,7 @@ </if> </where> GROUP BY slpa.scheduling_user_name GROUP BY slpa.scheduling_user_id, slpa.scheduling_user_name </select> src/main/resources/mapper/quality/QualityInspectMapper.xml
@@ -48,7 +48,7 @@ <if test="qualityInspect.entryDateEnd != null and qualityInspect.entryDateEnd != '' "> AND qi.check_time <= DATE_FORMAT(#{qualityInspect.entryDateEnd},'%Y-%m-%d') </if> ORDER BY qi.check_time DESC ORDER BY qi.create_time DESC </select> <select id="qualityInspectExport" resultType="com.ruoyi.quality.pojo.QualityInspect"> src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -203,6 +203,7 @@ </if> </where> group by product_model_id, model, unit, product_name, product_id, unQualifiedBatchNo, materialCode, processCategory, voltage having SUM(qualifiedQuantity) > 0 or SUM(unQualifiedQuantity) > 0 </select> <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData"> @@ -296,6 +297,7 @@ </if> </where> group by product_model_id, model, unit, product_name, unQualifiedBatchNo, materialCode, processCategory, voltage having SUM(qualifiedQuantity) > 0 or SUM(unQualifiedQuantity) > 0 </select> <select id="stockInventoryPage" resultType="com.ruoyi.stock.dto.StockInRecordDto"> select sir.*,si.qualitity as current_stock,