From fb7f1be781366330b8cd2c5ac11258119ecc403f Mon Sep 17 00:00:00 2001
From: buhuazhen <hua100783@gmail.com>
Date: 星期六, 28 三月 2026 15:36:21 +0800
Subject: [PATCH] feat(procurement): 新增采购价格管理模块及自动价格变更处理
---
src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml | 7 +
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java | 95 +++++++++++++++++++++++
src/main/java/com/ruoyi/procurementrecord/DiscountTypeEnum.java | 23 +++++
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java | 22 +++++
src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java | 9 ++
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java | 29 +++++++
src/main/java/com/ruoyi/procurementrecord/dto/SimplePP.java | 37 +++++++++
7 files changed, 216 insertions(+), 6 deletions(-)
diff --git a/src/main/java/com/ruoyi/procurementrecord/DiscountTypeEnum.java b/src/main/java/com/ruoyi/procurementrecord/DiscountTypeEnum.java
new file mode 100644
index 0000000..9ca3845
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/DiscountTypeEnum.java
@@ -0,0 +1,23 @@
+package com.ruoyi.procurementrecord;
+
+import lombok.Getter;
+
+/**
+ * @author buhuazhen
+ * @date 2026/3/28
+ * @email 3038525872@qq.com
+ */
+@Getter
+public enum DiscountTypeEnum{
+ DISCOUNT_TYPE_NONE("", "鏃犳姌鎵�"),
+ DISCOUNT_TYPE_PERCENTAGE("percentage", "鐧惧垎姣旀姌鎵�"),
+ DISCOUNT_TYPE_FIXED("fixed", "鍥哄畾閲戦");
+
+ private final String code;
+ private final String description;
+
+ DiscountTypeEnum(String code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/dto/SimplePP.java b/src/main/java/com/ruoyi/procurementrecord/dto/SimplePP.java
new file mode 100644
index 0000000..3fb9b13
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/dto/SimplePP.java
@@ -0,0 +1,37 @@
+package com.ruoyi.procurementrecord.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 鐢ㄤ簬鑷姩鐢熸垚閲囪喘浠锋牸绠$悊鐨勭畝鍗旸TO
+ * 涓�涓�
+ * @author buhuazhen
+ * @date 2026/3/28
+ * @email 3038525872@qq.com
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class SimplePP implements Serializable {
+
+ private String productName;
+ private Long productId;
+ private String specification;
+ private String supplierName;
+ private Long supplierId;
+
+
+ private String remark;
+
+ private String unit;
+
+
+ // 鏈�缁堜环鏍� 瑕佹眰涓嶅惈绋庣殑鍗曚环
+ private BigDecimal finalPrice;
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
index 08c9d21..9d8091d 100644
--- a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java
@@ -8,6 +8,8 @@
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
+import java.io.Serializable;
+import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
@@ -18,7 +20,7 @@
@Data
@TableName("procurement_price_management")
@ApiModel
-public class ProcurementPriceManagement {
+public class ProcurementPriceManagement implements Serializable {
private static final long serialVersionUID = 1L;
/**
@@ -31,8 +33,14 @@
@Excel(name = "鍟嗗搧鍚嶇О")
private String productName;
+ @TableField(value = "product_id")
+ private Long productId;
+
+ /**
+ * 鏃犳晥瀛楁 鍙互浣滀负鍐椾綑瀛楁浣跨敤
+ */
@ApiModelProperty(value = "鍟嗗搧缂栫爜")
- @Excel(name = "鍟嗗搧缂栫爜")
+// @Excel(name = "鍟嗗搧缂栫爜")
private String productCode;
@ApiModelProperty(value = "瑙勬牸鍨嬪彿")
@@ -43,9 +51,17 @@
@Excel(name = "渚涘簲鍟嗗悕绉�")
private String supplierName;
+ @TableField(value = "supplier_id")
+ private Long supplierId;
+
@ApiModelProperty(value = "鍩虹浠锋牸")
@Excel(name = "鍩虹浠锋牸")
private String basePrice;
+
+ @ApiModelProperty(value = "瀹為檯浠锋牸")
+ @TableField(value = "actually_price")
+ @Excel
+ private BigDecimal actuallyPrice;
@ApiModelProperty(value = "鐘舵��")
@TableField(exist = false)
@@ -76,6 +92,8 @@
@Excel(name = "鏈�楂樹环鏍�")
private String maxPrice;
+
+
@ApiModelProperty(value = "棰勮闃堝��(%)")
private String warningThreshold;
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
index fc26ab6..1021f46 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java
@@ -3,9 +3,12 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.procurementrecord.dto.SimplePP;
import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
/**
* @author :yys
@@ -23,4 +26,10 @@
IPage<ProcurementPriceManagement> listPage(Page page, ProcurementPriceManagement procurementPriceManagement);
void export(HttpServletResponse response);
+
+ /**
+ * 鑷姩鐢熸垚浠锋牸绠$悊骞朵笖瀵规瘮涓婁竴娆′环鏍兼暟鎹�
+ * @param simplePP 閲岄潰瀛楁绂佹涓虹┖
+ */
+ void autoCreateRecord(@NotNull SimplePP simplePP) throws ServiceException;
}
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
index e90a7a2..707f829 100644
--- a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java
@@ -1,19 +1,27 @@
package com.ruoyi.procurementrecord.service.impl;
+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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ruoyi.common.utils.excel.ExcelUtils;
+import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.procurementrecord.dto.ProcurementPageDto;
+import com.ruoyi.procurementrecord.DiscountTypeEnum;
+import com.ruoyi.procurementrecord.dto.SimplePP;
import com.ruoyi.procurementrecord.mapper.ProcurementPriceManagementMapper;
import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
import com.ruoyi.procurementrecord.service.ProcurementPriceManagementService;
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.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
/**
@@ -74,5 +82,86 @@
}
}
ExcelUtil<ProcurementPriceManagement> util = new ExcelUtil<ProcurementPriceManagement>(ProcurementPriceManagement.class);
- util.exportExcel(response, procurementPriceManagements, "閲囪喘浠锋牸绠$悊");}
+ util.exportExcel(response, procurementPriceManagements, "閲囪喘浠锋牸绠$悊");
+ }
+
+ @Override
+ @Transactional
+ public void autoCreateRecord(SimplePP simplePP) throws ServiceException {
+ // 鏍规嵁渚涘簲鍟唅d 浜у搧id 鏌ヨ鍑烘渶杩戜慨鏀圭殑涓�鏉¤褰曡繘琛屾瘮瀵�
+ ProcurementPriceManagement insertPriceManagement = new ProcurementPriceManagement();
+ BeanUtils.copyProperties(simplePP, insertPriceManagement);
+ LambdaQueryWrapper<ProcurementPriceManagement> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.eq(ProcurementPriceManagement::getSupplierId, simplePP.getSupplierId())
+ .eq(ProcurementPriceManagement::getProductId, simplePP.getProductId())
+ .orderByDesc(ProcurementPriceManagement::getUpdateTime).last("limit 1");
+ ProcurementPriceManagement lastRecord = procurementPriceManagementMapper.selectOne(queryWrapper);
+
+
+ insertPriceManagement.setActuallyPrice(simplePP.getFinalPrice());
+ insertPriceManagement.setDiscountType(DiscountTypeEnum.DISCOUNT_TYPE_NONE.getCode());
+ insertPriceManagement.setDiscountValue("0");
+ // 浣跨敤 Calendar 璁剧疆杩滄湡鏃ユ湡 (9999-12-31)
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2099, Calendar.DECEMBER, 31);
+ insertPriceManagement.setDiscountEndTime(calendar.getTime());
+ insertPriceManagement.setEffectiveTime(new Date());
+ insertPriceManagement.setExpireTime(calendar.getTime());
+ insertPriceManagement.setReason("other");
+ // 杩涜鍒嗗埆鎯呭喌
+ BigDecimal currentPrice = simplePP.getFinalPrice();
+
+ if (lastRecord == null) {
+ insertPriceManagement.setBasePrice(currentPrice.toString());
+
+ insertPriceManagement.setMinPrice(null);
+ insertPriceManagement.setMaxPrice(null);
+ procurementPriceManagementMapper.insert(insertPriceManagement);
+ return;
+ }
+
+ int compareTo = lastRecord.getActuallyPrice().compareTo(currentPrice);
+ if (compareTo == 0) {
+ log.info("浠锋牸鏈彉鍖栵紝鏃犻渶鍒涘缓璁板綍");
+ return;
+ }
+
+ // 馃憠 浠锋牸鍙樺寲閫昏緫
+ insertPriceManagement.setBasePrice(String.valueOf(lastRecord.getActuallyPrice()));
+ insertPriceManagement.setMaxPrice(lastRecord.getMaxPrice());
+ insertPriceManagement.setMinPrice(lastRecord.getMinPrice());
+
+ // 璁$畻鎶樻墸
+// if(compareTo > 0){
+ BigDecimal basePrice = new BigDecimal(insertPriceManagement.getBasePrice());
+ BigDecimal actuallyPrice = insertPriceManagement.getActuallyPrice();
+ // 闃叉闄�0
+ if (basePrice.compareTo(BigDecimal.ZERO) == 0) {
+ insertPriceManagement.setDiscountValue("0");
+ return;
+ }
+
+ // 鎶樻墸 = (鍘熶环 - 鐜颁环) / 鍘熶环
+ BigDecimal discount = basePrice.subtract(actuallyPrice)
+ .divide(basePrice, 8, RoundingMode.HALF_UP);
+ if(discount.compareTo(new BigDecimal("0.01")) < 0 && discount.compareTo(new BigDecimal("0")) > 0){
+ // 杞负鍥哄畾閲戦
+ insertPriceManagement.setDiscountValue(String.valueOf(basePrice.subtract(actuallyPrice)));
+ insertPriceManagement.setDiscountType(DiscountTypeEnum.DISCOUNT_TYPE_FIXED.getCode());
+ }else {
+ insertPriceManagement.setDiscountType(DiscountTypeEnum.DISCOUNT_TYPE_PERCENTAGE.getCode());
+ // 杞櫨鍒嗘瘮锛埫�100锛�
+ BigDecimal percent = discount.multiply(new BigDecimal("100"));
+
+ // 淇濈暀2浣嶅皬鏁�
+ percent = percent.setScale(2, RoundingMode.HALF_UP);
+
+ // 璁剧疆鍊硷紙姣斿锛�20.00%锛�
+ insertPriceManagement.setDiscountValue(String.valueOf(percent));
+ }
+// }
+
+ // final insert
+ procurementPriceManagementMapper.insert(insertPriceManagement);
+ }
}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index 7305a75..f69bfd9 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -27,6 +27,8 @@
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.other.mapper.TempFileMapper;
import com.ruoyi.other.pojo.TempFile;
+import com.ruoyi.procurementrecord.dto.SimplePP;
+import com.ruoyi.procurementrecord.service.ProcurementPriceManagementService;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
@@ -53,6 +55,7 @@
import java.io.IOException;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -102,6 +105,8 @@
private final StringRedisTemplate redisTemplate;
private final IApproveProcessService approveProcessService;
+
+ private final ProcurementPriceManagementService procurementPriceManagementService;
@Value("${file.upload-dir}")
private String uploadDir;
@@ -212,7 +217,7 @@
if (products == null || products.isEmpty()) {
throw new BaseException("浜у搧淇℃伅涓嶅瓨鍦�");
}
-
+ PurchaseLedger ledger = purchaseLedgerMapper.selectById(salesLedgerId);
// 鎻愬墠鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑ID
Set<Long> productIds = products.stream()
.map(SalesLedgerProduct::getProductId)
@@ -279,6 +284,28 @@
}
}
+ updateList.addAll(insertList);
+ updateList.forEach(it->{
+ SimplePP simplePP = new SimplePP();
+ simplePP.setProductId(it.getProductId());
+ simplePP.setSupplierName(ledger.getSupplierName());
+ simplePP.setSupplierId(ledger.getSupplierId());
+ simplePP.setUnit(it.getUnit());
+ simplePP.setProductName(it.getProductCategory());
+ simplePP.setSpecification(it.getSpecificationModel());
+ simplePP.setFinalPrice(it.getTaxInclusiveUnitPrice().divide(
+ BigDecimal.ONE.add(it.getTaxRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP)),
+ 2, // 淇濈暀4浣嶏紙鍙牴鎹笟鍔¤皟鏁达級
+ RoundingMode.HALF_UP
+ ));
+ simplePP.setRemark(
+ "绯荤粺鏍规嵁閲囪喘鎻愪氦鑷姩鐢熸垚銆傞噰璐悎鍚屽彿涓�:" + purchaseLedger.getPurchaseContractNumber() + "銆�"
+ );
+ procurementPriceManagementService.autoCreateRecord(simplePP);
+ });
+
+
+
// 璁$畻鎬诲惈绋庨噾棰�
BigDecimal totalTaxInclusiveAmount = products.stream()
.map(SalesLedgerProduct::getTaxInclusiveTotalPrice)
diff --git a/src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml b/src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml
index 196adfa..8804ebf 100644
--- a/src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml
+++ b/src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml
@@ -11,6 +11,13 @@
<if test="req.supplierName != null and req.supplierName != ''">
AND supplier_name = #{req.supplierName}
</if>
+ <if test="req.supplierId != null">
+ AND supplier_id = #{req.supplierId}
+ </if>
+ <if test="req.productId != null">
+ AND product_id = #{req.productId}
+ </if>
</where>
+ order by update_time desc
</select>
</mapper>
\ No newline at end of file
--
Gitblit v1.9.3