From cb635802bd0187fd2874c8ad3d6664d4c7aa8555 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期五, 09 五月 2025 15:09:04 +0800
Subject: [PATCH] 1.销售台账合同号生成 2.关联产品新增删除 3.采购台账
---
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java | 2
src/main/resources/mapper/sales/SalesLedgerMapper.xml | 12 +
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java | 23 ++
src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java | 15 +
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java | 44 ++++
src/main/java/com/ruoyi/common/config/MyBaseMapper.java | 20 ++
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java | 8
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java | 2
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java | 38 +++
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java | 4
src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java | 7
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 157 +++++++++++++++-
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java | 73 ++++++++
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java | 4
src/main/resources/application.yml | 2
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java | 97 ++++++++++
16 files changed, 480 insertions(+), 28 deletions(-)
diff --git a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
index 3dd42a9..3c12a6f 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -17,6 +17,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
@@ -113,9 +114,40 @@
}
@Override
- public List customerList(Customer customer) {
+ public List<Map<String, Object>> customerList(Customer customer) {
LambdaQueryWrapper<Customer> queryWrapper = Wrappers.lambdaQuery();
- queryWrapper.select(Customer::getId, Customer::getCustomerName);
- return customerMapper.selectMaps(queryWrapper);
+ queryWrapper.select(Customer::getId, Customer::getCustomerName,Customer::getTaxpayerIdentificationNumber);
+
+ // 鑾峰彇鍘熷鏌ヨ缁撴灉
+ List<Map<String, Object>> result = customerMapper.selectMaps(queryWrapper);
+
+ // 灏嗕笅鍒掔嚎鍛藉悕杞崲涓洪┘宄板懡鍚�
+ return result.stream().map(map -> map.entrySet().stream()
+ .collect(Collectors.toMap(
+ entry -> underlineToCamel(entry.getKey()),
+ Map.Entry::getValue))
+ ).collect(Collectors.toList());
+ }
+
+ /**
+ * 涓嬪垝绾垮懡鍚嶈浆椹煎嘲鍛藉悕
+ */
+ private String underlineToCamel(String param) {
+ if (param == null || "".equals(param.trim())) {
+ return "";
+ }
+ int len = param.length();
+ StringBuilder sb = new StringBuilder(len);
+ for (int i = 0; i < len; i++) {
+ char c = param.charAt(i);
+ if (c == '_') {
+ if (++i < len) {
+ sb.append(Character.toUpperCase(param.charAt(i)));
+ }
+ } else {
+ sb.append(Character.toLowerCase(c));
+ }
+ }
+ return sb.toString();
}
}
diff --git a/src/main/java/com/ruoyi/common/config/MyBaseMapper.java b/src/main/java/com/ruoyi/common/config/MyBaseMapper.java
new file mode 100644
index 0000000..7f39c5e
--- /dev/null
+++ b/src/main/java/com/ruoyi/common/config/MyBaseMapper.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.config;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+public interface MyBaseMapper<T> extends BaseMapper<T> {
+
+ /**
+ * 鎵归噺鎻掑叆锛堜粎鎻掑叆闈炵┖瀛楁锛�
+ * @param list 瀹炰綋鍒楄〃
+ * @return 鎻掑叆鎴愬姛鐨勮褰曟暟
+ */
+ int insertBatchSomeColumn(List<T> list);
+
+ /**
+ * 鎵归噺鏇存柊锛堜粎鏇存柊闈炵┖瀛楁锛�
+ */
+ int updateBatchSomeColumn(List<T> list);
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
new file mode 100644
index 0000000..7f0fb01
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java
@@ -0,0 +1,73 @@
+package com.ruoyi.purchase.controller;
+
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.service.IPurchaseLedgerService;
+import lombok.AllArgsConstructor;
+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.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 java.util.List;
+
+/**
+ * 閲囪喘鍙拌处Controller
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+@RestController
+@RequestMapping("/system/ledger")
+@AllArgsConstructor
+public class PurchaseLedgerController extends BaseController {
+ private IPurchaseLedgerService purchaseLedgerService;
+
+ /**
+ * 鏌ヨ閲囪喘鍙拌处鍒楄〃
+ */
+ @GetMapping("/list")
+ public TableDataInfo list(PurchaseLedger purchaseLedger) {
+ startPage();
+ List<PurchaseLedger> list = purchaseLedgerService.selectPurchaseLedgerList(purchaseLedger);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭閲囪喘鍙拌处鍒楄〃
+ */
+ @Log(title = "閲囪喘鍙拌处", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, PurchaseLedger purchaseLedger) {
+ List<PurchaseLedger> list = purchaseLedgerService.selectPurchaseLedgerList(purchaseLedger);
+ ExcelUtil<PurchaseLedger> util = new ExcelUtil<PurchaseLedger>(PurchaseLedger.class);
+ util.exportExcel(response, list, "銆愯濉啓鍔熻兘鍚嶇О銆戞暟鎹�");
+ }
+
+ /**
+ * 鏂板淇敼閲囪喘鍙拌处
+ */
+ @Log(title = "閲囪喘鍙拌处", businessType = BusinessType.INSERT)
+ @PostMapping ("/addOrEditPurchase")
+ public AjaxResult addOrEditPurchase(@RequestBody PurchaseLedger purchaseLedger) {
+ return toAjax(purchaseLedgerService.addOrEditPurchase(purchaseLedger));
+ }
+
+ /**
+ * 鍒犻櫎閲囪喘鍙拌处
+ */
+ @Log(title = "閲囪喘鍙拌处", businessType = BusinessType.DELETE)
+ @DeleteMapping("/delPurchase")
+ public AjaxResult remove(@RequestBody Long[] ids) {
+ return toAjax(purchaseLedgerService.deletePurchaseLedgerByIds(ids));
+ }
+}
diff --git a/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java b/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java
new file mode 100644
index 0000000..1328588
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.purchase.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+
+/**
+ * 閲囪喘鍙拌处Mapper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+public interface PurchaseLedgerMapper extends BaseMapper<PurchaseLedger> {
+
+}
diff --git a/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
new file mode 100644
index 0000000..02cdab9
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -0,0 +1,97 @@
+package com.ruoyi.purchase.pojo;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+
+/**
+ * 閲囪喘鍙拌处瀵硅薄 purchase_ledger
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+@TableName("purchase_ledger")
+@Data
+public class PurchaseLedger {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鑷涓婚敭ID
+ */
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 閲囪喘鍚堝悓鍙�
+ */
+ @Excel(name = "閲囪喘鍚堝悓鍙�")
+ private String purchaseContractNumber;
+
+ /**
+ * 渚涘簲鍟嗗悕绉�
+ */
+ @Excel(name = "渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+ /**
+ * 褰曞叆浜哄鍚�
+ */
+ @Excel(name = "褰曞叆浜哄鍚�")
+ private String recorderName;
+
+ /**
+ * 閿�鍞悎鍚屽彿
+ */
+ @Excel(name = "閿�鍞悎鍚屽彿")
+ private String salesContractNo;
+
+ /**
+ * 椤圭洰鍚嶇О
+ */
+ @Excel(name = "椤圭洰鍚嶇О")
+ private String projectName;
+
+ /**
+ * 褰曞叆鏃ユ湡
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "褰曞叆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd")
+ private Date entryDate;
+
+ /**
+ * 澶囨敞
+ */
+ @Excel(name = "澶囨敞")
+ private String remarks;
+
+ /**
+ * 闄勪欢鏉愭枡璺緞鎴栧悕绉�
+ */
+ @Excel(name = "闄勪欢鏉愭枡璺緞鎴栧悕绉�")
+ private String attachmentMaterials;
+
+ /**
+ * 璁板綍鍒涘缓鏃堕棿
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "璁板綍鍒涘缓鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd")
+ private Date createdAt;
+
+ /**
+ * 璁板綍鏈�鍚庢洿鏂版椂闂�
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "璁板綍鏈�鍚庢洿鏂版椂闂�", width = 30, dateFormat = "yyyy-MM-dd")
+ private Date updatedAt;
+
+ /**
+ * 鍏宠仈閿�鍞彴璐︿富琛ㄤ富閿�
+ */
+ private Long salesLedgerId;
+
+}
diff --git a/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
new file mode 100644
index 0000000..120c15c
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.purchase.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+
+import java.util.List;
+
+/**
+ * 閲囪喘鍙拌处Service鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+public interface IPurchaseLedgerService extends IService<PurchaseLedger> {
+
+ List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger);
+
+ int addOrEditPurchase(PurchaseLedger purchaseLedger);
+
+ int deletePurchaseLedgerByIds(Long[] ids);
+
+}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
new file mode 100644
index 0000000..a209ccb
--- /dev/null
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -0,0 +1,44 @@
+package com.ruoyi.purchase.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
+import com.ruoyi.purchase.pojo.PurchaseLedger;
+import com.ruoyi.purchase.service.IPurchaseLedgerService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 閲囪喘鍙拌处Service涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2025-05-09
+ */
+@Service
+@AllArgsConstructor
+public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService {
+
+ private PurchaseLedgerMapper purchaseLedgerMapper;
+
+ @Override
+ public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) {
+ return purchaseLedgerMapper.selectList(new LambdaQueryWrapper<>());
+ }
+
+ @Override
+ public int addOrEditPurchase(PurchaseLedger purchaseLedger) {
+ if (purchaseLedger.getId() == null) {
+ return purchaseLedgerMapper.insert(purchaseLedger);
+ } else {
+ return purchaseLedgerMapper.updateById(purchaseLedger);
+ }
+ }
+
+ @Override
+ public int deletePurchaseLedgerByIds(Long[] ids) {
+ return purchaseLedgerMapper.deleteBatchIds(Arrays.asList(ids));
+ }
+}
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index 3c93788..3f325b1 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -82,9 +82,9 @@
*/
@Log(title = "閿�鍞彴璐�", businessType = BusinessType.INSERT)
@PostMapping ("/addOrUpdateSalesLedger")
- public AjaxResult add(@RequestBody SalesLedger salesLedger)
+ public AjaxResult add(@RequestBody SalesLedgerDto salesLedgerDto)
{
- return toAjax(salesLedgerService.addOrUpdateSalesLedger(salesLedger));
+ return toAjax(salesLedgerService.addOrUpdateSalesLedger(salesLedgerDto));
}
/**
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
index cc2bcf4..d1a5c9c 100644
--- a/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
@@ -22,5 +22,5 @@
private String remarks;
private String attachmentMaterials;
private Boolean hasChildren = false;
- private List<SalesLedgerProduct> children;
+ private List<SalesLedgerProduct> productData;
}
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
index 9980acc..c188733 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -3,6 +3,7 @@
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.sales.pojo.SalesLedger;
+import org.apache.ibatis.annotations.Param;
/**
@@ -12,4 +13,10 @@
* @date 2025-05-08
*/
public interface SalesLedgerMapper extends BaseMapper<SalesLedger> {
+ /**
+ * 鏌ヨ鎸囧畾鏃ユ湡鐨勬墍鏈夊悎鍚屽簭鍒楀彿
+ * @param datePart 鏃ユ湡閮ㄥ垎锛堟牸寮忥細yyyyMMdd锛�
+ * @return 搴忓垪鍙峰垪琛�
+ */
+ List<Integer> selectSequencesByDate(@Param("datePart") String datePart);
}
diff --git a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
index 145bf38..69b2b7b 100644
--- a/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
+++ b/src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java
@@ -1,6 +1,6 @@
package com.ruoyi.sales.mapper;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.config.MyBaseMapper;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
/**
@@ -9,5 +9,5 @@
* @author ruoyi
* @date 2025-05-08
*/
-public interface SalesLedgerProductMapper extends BaseMapper<SalesLedgerProduct> {
+public interface SalesLedgerProductMapper extends MyBaseMapper<SalesLedgerProduct> {
}
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index bb4f237..b6eaf67 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -1,5 +1,6 @@
package com.ruoyi.sales.pojo;
+import java.math.BigDecimal;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.*;
@@ -81,11 +82,16 @@
/**
* 闄勪欢鏉愭枡锛屽瓨鍌ㄦ枃浠跺悕绛夌浉鍏充俊鎭�
*/
- @Excel(name = "闄勪欢鏉愭枡锛屽瓨鍌ㄦ枃浠跺悕绛夌浉鍏充俊鎭�")
private String attachmentMaterials;
@TableField(fill = FieldFill.INSERT)
private Long tenantId;
+
+ /**
+ * 鍚堝悓閲戦锛堜骇鍝佸惈绋庢�讳环锛�
+ */
+ @Excel(name = "绋庣巼")
+ private BigDecimal contractAmount;
}
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index 7ee8c1f..a716de3 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -20,7 +20,7 @@
int deleteSalesLedgerByIds(Long[] ids);
- int addOrUpdateSalesLedger(SalesLedger salesLedger);
+ int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto);
List<SalesLedgerDto> getSalesLedgerWithProducts();
}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 5048386..a1f884d 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.sales.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.pojo.Customer;
@@ -12,12 +13,16 @@
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.sales.service.ISalesLedgerService;
import lombok.AllArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -35,6 +40,12 @@
private CustomerMapper customerMapper;
private SalesLedgerProductMapper salesLedgerProductMapper;
+
+ private static final String LOCK_PREFIX = "contract_no_lock:";
+ private static final long LOCK_WAIT_TIMEOUT = 10; // 閿佺瓑寰呰秴鏃舵椂闂达紙绉掞級
+ private static final long LOCK_EXPIRE_TIME = 30; // 閿佽嚜鍔ㄨ繃鏈熸椂闂达紙绉掞級
+
+ private final RedisTemplate<String, String> redisTemplate;
@Override
public List<SalesLedger> selectSalesLedgerList(SalesLedger salesLedger) {
@@ -55,7 +66,7 @@
List<SalesLedgerProduct> ledgerProducts = productMap.getOrDefault(ledger.getId(), Collections.emptyList());
if (!ledgerProducts.isEmpty()) {
dto.setHasChildren(true);
- dto.setChildren(ledgerProducts);
+ dto.setProductData(ledgerProducts);
}
return dto;
}).collect(Collectors.toList());
@@ -67,27 +78,139 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public int deleteSalesLedgerByIds(Long[] ids) {
- return salesLedgerMapper.deleteBatchIds(Arrays.asList(ids));
+ List<Long> idList = Arrays.stream(ids)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ if (CollectionUtils.isEmpty(idList)) {
+ return 0;
+ }
+ // 1. 鍏堝垹闄ゅ瓙琛ㄦ暟鎹�
+ LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>();
+ productWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList);
+ salesLedgerProductMapper.delete(productWrapper);
+
+ // 2. 鍐嶅垹闄や富琛ㄦ暟鎹�
+ return salesLedgerMapper.deleteBatchIds(idList);
}
- public int addOrUpdateSalesLedger(SalesLedger salesLedger) {
- LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(Customer::getId, salesLedger.getCustomerId());
- Customer customer = customerMapper.selectOne(queryWrapper);
+ @Transactional(rollbackFor = Exception.class)
+ public int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto) {
+ // 1. 鏍¢獙瀹㈡埛淇℃伅
+ Customer customer = customerMapper.selectById(salesLedgerDto.getCustomerId());
if (customer == null) {
- throw new BaseException("鏈煡璇㈠埌瀵瑰簲鐨� Customer 淇℃伅");
+ throw new BaseException("瀹㈡埛涓嶅瓨鍦�");
}
+
+ // 2. DTO杞珽ntity
+ SalesLedger salesLedger = convertToEntity(salesLedgerDto);
salesLedger.setCustomerName(customer.getCustomerName());
salesLedger.setTenantId(customer.getTenantId());
- return saveOrUpdates(salesLedger);
+
+ // 3. 鏂板鎴栨洿鏂颁富琛�
+ if (salesLedger.getId() == null) {
+ // 鐢熸垚鍚堝悓缂栧彿
+ String contractNo = generateSalesContractNo();
+ salesLedger.setSalesContractNo(contractNo);
+ salesLedgerMapper.insert(salesLedger);
+ } else {
+ salesLedgerMapper.updateById(salesLedger);
+ }
+
+ // 4. 澶勭悊瀛愯〃鏁版嵁
+ if (salesLedgerDto.getProductData() != null && !salesLedgerDto.getProductData().isEmpty()) {
+ handleSalesLedgerProducts(salesLedger.getId(), salesLedgerDto.getProductData());
+ }
+
+ return 1; // 鎿嶄綔鎴愬姛杩斿洖1
}
- private int saveOrUpdates(SalesLedger salesLedger) {
- if (salesLedger.getId() == null) {
- return salesLedgerMapper.insert(salesLedger);
- } else {
- return salesLedgerMapper.updateById(salesLedger);
+ private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products) {
+ // 鎸塈D鍒嗙粍锛屽尯鍒嗘柊澧炲拰鏇存柊鐨勮褰�
+ Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream()
+ .peek(p -> p.setSalesLedgerId(salesLedgerId))
+ .collect(Collectors.partitioningBy(p -> p.getId() != null));
+
+ List<SalesLedgerProduct> updateList = partitionedProducts.get(true);
+ List<SalesLedgerProduct> insertList = partitionedProducts.get(false);
+
+ // 鎵ц鏇存柊鎿嶄綔
+ if (!updateList.isEmpty()) {
+ salesLedgerProductMapper.updateBatchSomeColumn(updateList);
}
+ // 鎵ц鎻掑叆鎿嶄綔
+ if (!insertList.isEmpty()) {
+ salesLedgerProductMapper.insertBatchSomeColumn(insertList);
+ }
+ }
+
+ private SalesLedger convertToEntity(SalesLedgerDto dto) {
+ SalesLedger entity = new SalesLedger();
+ BeanUtils.copyProperties(dto, entity);
+ return entity;
+ }
+
+ @Transactional(readOnly = true)
+ public String generateSalesContractNo() {
+ LocalDate currentDate = LocalDate.now();
+ String datePart = currentDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+ String lockKey = LOCK_PREFIX + datePart;
+ String lockValue = Thread.currentThread().getId() + "-" + System.nanoTime(); // 鍞竴鏍囪瘑閿佹寔鏈夎��
+
+ try {
+ // 1. 灏濊瘯鑾峰彇鍒嗗竷寮忛攣锛堝惊鐜洿鍒拌秴鏃讹級
+ long startWaitTime = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startWaitTime < LOCK_WAIT_TIMEOUT * 1000) {
+ // SET key value NX PX 30000锛氫粎褰撻攣涓嶅瓨鍦ㄦ椂鑾峰彇锛岃缃�30绉掕繃鏈�
+ Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
+ if (Boolean.TRUE.equals(locked)) {
+ break; // 鎴愬姛鑾峰彇閿�
+ }
+ // 鐭殏浼戠湢閬垮厤蹇欑瓑寰�
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("鑾峰彇閿佹椂琚腑鏂�", e);
+ }
+ }
+
+ if (!redisTemplate.hasKey(lockKey)) {
+ throw new RuntimeException("鑾峰彇鍚堝悓缂栧彿鐢熸垚閿佸け璐ワ細瓒呮椂");
+ }
+
+ // 2. 鏌ヨ褰撳ぉ宸插瓨鍦ㄧ殑搴忓垪鍙凤紙涓庡師閫昏緫涓�鑷达級
+ List<Integer> existingSequences = salesLedgerMapper.selectSequencesByDate(datePart);
+ int nextSequence = findFirstMissingSequence(existingSequences);
+
+ return datePart + String.format("%02d", nextSequence);
+ } finally {
+ // 3. 閲婃斁閿侊紙浣跨敤Lua鑴氭湰淇濊瘉鍘熷瓙鎬э紝閬垮厤璇垹鍏朵粬绾跨▼鐨勯攣锛�
+ String luaScript = "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end";
+ redisTemplate.execute(
+ new DefaultRedisScript<>(luaScript, Long.class),
+ Collections.singletonList(lockKey),
+ lockValue // 鍙湁鎸佹湁鐩稿悓鍊肩殑绾跨▼鎵嶈兘鍒犻櫎閿�
+ );
+ }
+ }
+
+ private int findFirstMissingSequence(List<Integer> sequences) {
+ if (sequences.isEmpty()) {
+ return 1;
+ }
+ // 鎺掑簭鍚庢煡鎵剧涓�涓己澶辩殑姝f暣鏁帮紙涓庡師閫昏緫涓�鑷达級
+ sequences.sort(Integer::compareTo);
+ int next = 1;
+ for (int seq : sequences) {
+ if (seq == next) {
+ next++;
+ } else if (seq > next) {
+ break;
+ }
+ }
+ return next;
}
}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 1a89bcf..2154aae 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -100,7 +100,7 @@
# MyBatis Plus閰嶇疆
mybatis-plus:
# 鎼滅储鎸囧畾鍖呭埆鍚� 鏍规嵁鑷繁鐨勯」鐩潵
- typeAliasesPackage: com.ruoyi.basic.**.pojo
+ typeAliasesPackage: com.ruoyi.**.pojo
# 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
new file mode 100644
index 0000000..16ba140
--- /dev/null
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.sales.mapper.SalesLedgerMapper">
+
+ <select id="selectSequencesByDate" resultType="java.lang.Integer">
+ SELECT CAST(SUBSTR(sales_contract_no, 9, 2) AS SIGNED)
+ FROM sales_ledger
+ WHERE SUBSTR(sales_contract_no, 1, 8) = #{datePart}
+ </select>
+</mapper>
\ No newline at end of file
--
Gitblit v1.9.3