From f5c9d4c54da8d60d8b798f67679263a8aec1607f Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期三, 15 四月 2026 11:16:48 +0800
Subject: [PATCH] feat: 库存区分产品大类
---
src/main/resources/mapper/basic/ProductModelMapper.xml | 43 ++++++++++++--
src/main/java/com/ruoyi/basic/controller/ProductController.java | 14 ++++
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java | 45 +++++++++++----
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java | 7 ++
src/main/java/com/ruoyi/basic/pojo/ProductModel.java | 6 ++
src/main/java/com/ruoyi/basic/service/IProductModelService.java | 4 +
doc/河南鹤壁天沐钢化玻璃厂.sql | 9 ++
7 files changed, 108 insertions(+), 20 deletions(-)
diff --git "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql" "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
index 863106f..190bcec 100644
--- "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
+++ "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
@@ -90,4 +90,11 @@
ADD COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細0-鏈彂璐э紝1-宸插彂璐�' AFTER `delivery_date`;
ALTER TABLE `product-inventory-management-hbtmblc`.`sales_ledger`
- MODIFY COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐�' AFTER `delivery_date`;
\ No newline at end of file
+ MODIFY COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐�' AFTER `delivery_date`;
+
+ALTER TABLE `product-inventory-management-hbtmblc`.`sales_ledger_product`
+ MODIFY COLUMN `quantity` decimal(18, 2) NULL COMMENT '鏁伴噺' AFTER `unit`,
+ MODIFY COLUMN `tax_rate` decimal(5, 0) NULL COMMENT '绋庣巼' AFTER `min_stock`,
+ MODIFY COLUMN `tax_inclusive_unit_price` decimal(18, 2) NULL COMMENT '鍚◣鍗曚环' AFTER `tax_rate`,
+ MODIFY COLUMN `tax_inclusive_total_price` decimal(18, 2) NULL COMMENT '鍚◣鎬讳环' AFTER `tax_inclusive_unit_price`,
+ MODIFY COLUMN `tax_exclusive_total_price` decimal(18, 2) NULL COMMENT '涓嶅惈绋庢�讳环' AFTER `tax_inclusive_total_price`;
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/controller/ProductController.java b/src/main/java/com/ruoyi/basic/controller/ProductController.java
index 252ab4d..2d211b7 100644
--- a/src/main/java/com/ruoyi/basic/controller/ProductController.java
+++ b/src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -7,6 +7,7 @@
import com.ruoyi.basic.dto.ProductModelDto;
import com.ruoyi.basic.dto.ProductModelExportDto;
import com.ruoyi.basic.dto.ProductTreeDto;
+import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.service.IProductModelService;
import com.ruoyi.basic.service.IProductService;
@@ -38,6 +39,7 @@
private IProductModelService productModelService;
@Autowired
private ISalesLedgerProductService salesLedgerProductService;
+
/**
* 鏌ヨ浜у搧
*/
@@ -85,7 +87,7 @@
LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SalesLedgerProduct::getProductId, ids);
List<SalesLedgerProduct> salesLedgerProductList = salesLedgerProductService.list(queryWrapper);
- if (salesLedgerProductList.size() > 0) {
+ if (!salesLedgerProductList.isEmpty()) {
return AjaxResult.error("璇ヤ骇鍝佸瓨鍦ㄩ攢鍞�/閲囪喘璁板綍锛屼笉鑳藉垹闄�");
}
return toAjax(productService.delProductByIds(ids));
@@ -143,4 +145,14 @@
ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class);
excelUtil.importTemplateExcel(response, "浜у搧瑙勬牸瀵煎叆妯℃澘");
}
+
+ /**
+ * 鑾峰彇浜у搧澶х被
+ */
+ @GetMapping("/getParentNames")
+ @ApiOperation("鑾峰彇浜у搧澶х被")
+ public AjaxResult getParentNames() {
+ List<Product> list = productModelService.getParentNames();
+ return AjaxResult.success(list);
+ }
}
diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index 7369e19..7aa975f 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -69,4 +69,10 @@
@TableField(exist = false)
private LocalDateTime createTime;
+
+ @TableField(exist = false)
+ private Long parentId;
+
+ @TableField(exist = false)
+ private String parentName;
}
diff --git a/src/main/java/com/ruoyi/basic/service/IProductModelService.java b/src/main/java/com/ruoyi/basic/service/IProductModelService.java
index dd268d6..f752566 100644
--- a/src/main/java/com/ruoyi/basic/service/IProductModelService.java
+++ b/src/main/java/com/ruoyi/basic/service/IProductModelService.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.basic.dto.ProductDto;
import com.ruoyi.basic.dto.ProductModelDto;
+import com.ruoyi.basic.pojo.Product;
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.framework.web.domain.AjaxResult;
import org.springframework.web.multipart.MultipartFile;
@@ -35,4 +36,7 @@
IPage<ProductModel> modelListPage(Page page , ProductDto productDto);
AjaxResult importProductModel(MultipartFile file, Integer productId);
+
+ List<Product> getParentNames();
+
}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
index 9382134..15ecd8e 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -151,4 +151,11 @@
throw new ServiceException("瀵煎叆澶辫触");
}
}
+
+ @Override
+ public List<Product> getParentNames() {
+ LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.isNull(Product::getParentId).select(Product::getId, Product::getProductName);
+ return productMapper.selectList(queryWrapper);
+ }
}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
index fdf2dd3..9c3cf89 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -89,27 +89,48 @@
@Override
public int addOrEditProduct(ProductDto productDto) {
+ checkDuplicateName(productDto);
if (productDto.getId() == null) {
- // 鏂板浜у搧閫昏緫
- if (productDto.getParentId() == null) {
- // 鑻ユ湭鎸囧畾鐖惰妭鐐癸紝榛樿涓烘牴鑺傜偣锛坧arentId 璁句负 null锛�
- productDto.setParentId(null);
- } else {
- // 妫�鏌ョ埗鑺傜偣鏄惁瀛樺湪锛堝彲閫夛紝鏍规嵁涓氬姟闇�姹傦級
+ if (productDto.getParentId() != null) {
Product parent = productMapper.selectById(productDto.getParentId());
if (parent == null) {
- throw new IllegalArgumentException("鐖惰妭鐐逛笉瀛樺湪锛屾棤娉曟坊鍔犲瓙浜у搧");
+ throw new IllegalArgumentException("鐖惰妭鐐逛笉瀛樺湪");
}
}
- return productMapper.insert(productDto);
+ Product product = new Product();
+ BeanUtils.copyProperties(productDto, product);
+ return productMapper.insert(product);
} else {
- // 缂栬緫浜у搧閫昏緫
- // 妫�鏌ヤ骇鍝佹槸鍚﹀瓨鍦紙鍙�夛紝鏍规嵁涓氬姟闇�姹傦級
Product existingProduct = productMapper.selectById(productDto.getId());
if (existingProduct == null) {
- throw new IllegalArgumentException("瑕佺紪杈戠殑浜у搧涓嶅瓨鍦�");
+ throw new IllegalArgumentException("浜у搧涓嶅瓨鍦�");
}
- return productMapper.updateById(productDto);
+ Product product = new Product();
+ BeanUtils.copyProperties(productDto, product);
+ return productMapper.updateById(product);
+ }
+ }
+
+ /**
+ * 鏍¢獙鍚岀骇鐩綍涓嬫槸鍚﹀瓨鍦ㄩ噸澶嶅悕绉�
+ */
+ private void checkDuplicateName(ProductDto productDto) {
+ LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
+
+ if (productDto.getParentId() == null) {
+ queryWrapper.isNull(Product::getParentId);
+ } else {
+ queryWrapper.eq(Product::getParentId, productDto.getParentId());
+ }
+
+ queryWrapper.eq(Product::getProductName, productDto.getProductName());
+
+ if (productDto.getId() != null) {
+ queryWrapper.ne(Product::getId, productDto.getId());
+ }
+
+ if (productMapper.selectCount(queryWrapper) > 0) {
+ throw new IllegalArgumentException("鍦ㄨ灞傜骇涓嬪凡瀛樺湪鍚嶄负 [" + productDto.getProductName() + "] 鐨勪骇鍝�");
}
}
diff --git a/src/main/resources/mapper/basic/ProductModelMapper.xml b/src/main/resources/mapper/basic/ProductModelMapper.xml
index b0c493e..cb80816 100644
--- a/src/main/resources/mapper/basic/ProductModelMapper.xml
+++ b/src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -15,20 +15,51 @@
<result column="product_name" property="productName" />
<result column="product_id" property="productId" />
</resultMap>
+
<select id="listPageProductModel" resultType="com.ruoyi.basic.pojo.ProductModel">
- select pm.*,p.product_name
- from product_model pm
- left join product p on pm.product_id = p.id
+ WITH RECURSIVE product_tree AS (
+ SELECT
+ id,
+ product_name,
+ id AS top_id,
+ product_name AS top_name
+ FROM product
+ WHERE parent_id IS NULL OR parent_id = 0
+
+ UNION ALL
+
+ SELECT
+ p.id,
+ p.product_name,
+ t.top_id,
+ t.top_name
+ FROM product p
+ INNER JOIN product_tree t ON p.parent_id = t.id
+ )
+ SELECT
+ pm.*,
+ pt.product_name AS productName,
+ pt.top_name AS parentName
+ FROM product_model pm
+ LEFT JOIN product_tree pt ON pm.product_id = pt.id
<where>
+ <if test="c.parentId != null">
+ AND pt.top_id = #{c.parentId}
+ </if>
+
<if test="c.model != null and c.model != ''">
- and pm.model like concat('%',#{c.model},'%')
+ AND pm.model LIKE CONCAT('%', #{c.model}, '%')
</if>
<if test="c.productName != null and c.productName != ''">
- and p.product_name like concat('%',#{c.productName},'%')
+ AND pt.product_name LIKE CONCAT('%', #{c.productName}, '%')
+ </if>
+ <if test="c.parentName != null and c.parentName != ''">
+ AND pt.top_name LIKE CONCAT('%', #{c.parentName}, '%')
</if>
</where>
- order by pm.id
+ ORDER BY pm.id DESC
</select>
+
<select id="selectLatestRecord" resultType="com.ruoyi.basic.pojo.ProductModel">
SELECT * FROM product_model
ORDER BY create_time DESC, id DESC
--
Gitblit v1.9.3