From 16500befda17ad48812e7a14a972c08321ff6475 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 29 四月 2026 14:03:29 +0800
Subject: [PATCH] feat(purchase): 新增企业采购智能助理功能

---
 src/main/java/com/ruoyi/sales/controller/BusinessOpportunityController.java |    3 
 src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerMapper.java            |    7 
 src/main/java/com/ruoyi/basic/pojo/Customer.java                            |    4 
 src/main/java/com/ruoyi/sales/service/BidWinningLedgerService.java          |   29 +++
 src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerRecordMapper.java      |    7 
 src/main/java/com/ruoyi/common/enums/FileNameType.java                      |   21 +-
 src/main/java/com/ruoyi/sales/pojo/BidWinningLedgerRecord.java              |   63 +++++++
 src/main/java/com/ruoyi/sales/controller/BidWinningLedgerController.java    |   83 +++++++++
 src/main/java/com/ruoyi/sales/pojo/BidWinningLedger.java                    |  101 +++++++++++
 src/main/java/com/ruoyi/sales/service/impl/BidWinningLedgerServiceImpl.java |  152 ++++++++++++++++
 doc/add.sql                                                                 |   38 ++++
 src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java         |    5 
 12 files changed, 500 insertions(+), 13 deletions(-)

diff --git a/doc/add.sql b/doc/add.sql
index 8902911..06f1900 100644
--- a/doc/add.sql
+++ b/doc/add.sql
@@ -130,3 +130,41 @@
 ALTER TABLE storage_blob MODIFY bucket_filename VARCHAR(255) COMMENT '瀛樺偍妗朵腑鏂囦欢鍚�';
 ALTER TABLE storage_blob MODIFY bucket_name VARCHAR(255) COMMENT '瀛樺偍妗跺悕';
 ALTER TABLE storage_blob MODIFY byte_size BIGINT COMMENT '璧勬簮灏哄(瀛楄妭)';
+DROP TABLE IF EXISTS bid_winning_ledger;
+CREATE TABLE bid_winning_ledger
+(
+    id                  BIGINT AUTO_INCREMENT PRIMARY KEY,
+    status              VARCHAR(100)   NULL COMMENT '鐘舵��',
+    province            VARCHAR(100)   NULL COMMENT '鐪佷唤',
+    city                VARCHAR(100)   NULL COMMENT '鍩庡競',
+    customer_name       VARCHAR(255)   NOT NULL COMMENT '瀹㈡埛鍚嶇О',
+    contract_amount     DECIMAL(18, 2) NULL COMMENT '鍚堝悓閲戦',
+    bid_bond            DECIMAL(18, 2) NULL COMMENT '鎶曟爣淇濊瘉閲�',
+    winning_service_fee DECIMAL(18, 2) NULL COMMENT '涓爣鏈嶅姟璐�',
+    industry            VARCHAR(100)   NULL COMMENT '琛屼笟',
+    business_source     VARCHAR(100)   NULL COMMENT '鍟嗘満鏉ユ簮',
+    remark              VARCHAR(1000)  NULL COMMENT '澶囨敞',
+    entry_person        VARCHAR(100)   NULL COMMENT '褰曞叆浜�',
+    entry_date          DATETIME       NULL COMMENT '褰曞叆鏃ユ湡',
+    create_time         DATETIME       NULL COMMENT '鍒涘缓鏃堕棿',
+    create_user         INT            NULL COMMENT '鍒涘缓鐢ㄦ埛',
+    update_time         DATETIME       NULL COMMENT '鏇存柊鏃堕棿',
+    update_user         INT            NULL COMMENT '鏇存柊鐢ㄦ埛',
+    tenant_id           BIGINT         NULL COMMENT '绉熸埛id'
+) COMMENT = '涓爣鍙拌处';
+
+DROP TABLE IF EXISTS bid_winning_ledger_record;
+CREATE TABLE bid_winning_ledger_record
+(
+    id                    BIGINT AUTO_INCREMENT PRIMARY KEY,
+    bid_winning_ledger_id BIGINT        NOT NULL COMMENT '涓爣鍙拌处id',
+    status                VARCHAR(100)  NULL COMMENT '鐘舵��',
+    description           VARCHAR(2000) NULL COMMENT '璁板綍鍐呭',
+    entry_person          VARCHAR(100)  NULL COMMENT '褰曞叆浜�',
+    entry_date            DATETIME      NULL COMMENT '褰曞叆鏃ユ湡',
+    create_time           DATETIME      NULL COMMENT '鍒涘缓鏃堕棿',
+    create_user           INT           NULL COMMENT '鍒涘缓鐢ㄦ埛',
+    update_time           DATETIME      NULL COMMENT '鏇存柊鏃堕棿',
+    update_user           INT           NULL COMMENT '鏇存柊鐢ㄦ埛',
+    tenant_id             BIGINT        NULL COMMENT '绉熸埛id'
+) COMMENT = '涓爣鍙拌处璁板綍';
diff --git a/src/main/java/com/ruoyi/basic/pojo/Customer.java b/src/main/java/com/ruoyi/basic/pojo/Customer.java
index d68b918..b7700bf 100644
--- a/src/main/java/com/ruoyi/basic/pojo/Customer.java
+++ b/src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -26,6 +26,10 @@
     @TableId(type = IdType.AUTO)
     private Long id;
 
+    @ApiModelProperty(value = "瀹㈡埛绫诲瀷 1-鏅�氬鎴� 2-涓皬瀹㈡埛")
+    @Excel(name = "瀹㈡埛绫诲瀷 1-鏅�氬鎴� 2-涓皬瀹㈡埛", readConverterExp = "1=鏅�氬鎴�,2=涓皬瀹㈡埛")
+    private Integer customerType;
+
     /**
      * 瀹㈡埛鍚嶇О
      */
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 899e21f..1b89779 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -175,6 +175,11 @@
     public List<Map<String, Object>> customerList(Customer customer) {
         LambdaQueryWrapper<Customer> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.select(Customer::getId, Customer::getCustomerName, Customer::getTaxpayerIdentificationNumber);
+        if(customer != null){
+            if(customer.getCustomerType() != null){
+                queryWrapper.eq(Customer::getCustomerType, customer.getCustomerType());
+            }
+        }
 
         // 鑾峰彇鍘熷鏌ヨ缁撴灉
         List<Map<String, Object>> result = customerMapper.selectMaps(queryWrapper);
diff --git a/src/main/java/com/ruoyi/common/enums/FileNameType.java b/src/main/java/com/ruoyi/common/enums/FileNameType.java
index 16d51f6..1ec712b 100644
--- a/src/main/java/com/ruoyi/common/enums/FileNameType.java
+++ b/src/main/java/com/ruoyi/common/enums/FileNameType.java
@@ -1,17 +1,17 @@
 package com.ruoyi.common.enums;
 
-import com.ruoyi.approve.pojo.ApproveProcess;
-
 public enum FileNameType {
 
-    SALE(1),      // 閿�鍞�
-    PURCHASE(2),  // 閲囪喘
-    INVOICE(3),     //鍙戠エ
+    SALE(1),
+    PURCHASE(2),
+    INVOICE(3),
     PURCHASELEDGER(4),
-    MEASURING(5),  //璁¢噺鍣ㄥ叿鍙拌处
-    MEASURINGRecord(6),//璁¢噺鍣ㄥ叿鍙拌处璁板綍
-    ApproveNode(7),  //鍗忓悓瀹℃壒鑺傜偣瀹℃牳
-    ApproveProcess(8);  //鍗忓悓瀹℃壒涓绘暟鎹�
+    MEASURING(5),
+    MEASURINGRecord(6),
+    ApproveNode(7),
+    ApproveProcess(8),
+    BUSINESS_OPPORTUNITY(9),
+    BID_WINNING_LEDGER(10);
 
     private final int value;
 
@@ -21,10 +21,8 @@
 
     public int getValue() {
         return value;
-
     }
 
-    // 鏍规嵁鏁存暟鍊艰幏鍙栧搴旂殑鏋氫妇鍊�
     public static FileNameType fromValue(int value) {
         for (FileNameType type : FileNameType.values()) {
             if (type.getValue() == value) {
@@ -34,4 +32,3 @@
         throw new IllegalArgumentException("Invalid value: " + value);
     }
 }
-
diff --git a/src/main/java/com/ruoyi/sales/controller/BidWinningLedgerController.java b/src/main/java/com/ruoyi/sales/controller/BidWinningLedgerController.java
new file mode 100644
index 0000000..a032c8b
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/controller/BidWinningLedgerController.java
@@ -0,0 +1,83 @@
+package com.ruoyi.sales.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+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.sales.pojo.BidWinningLedger;
+import com.ruoyi.sales.pojo.BidWinningLedgerRecord;
+import com.ruoyi.sales.service.BidWinningLedgerService;
+import io.jsonwebtoken.lang.Collections;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/sales/bidWinningLedger")
+@Api(tags = "涓爣鍙拌处")
+public class BidWinningLedgerController extends BaseController {
+
+    private final BidWinningLedgerService bidWinningLedgerService;
+
+    @GetMapping("/getProvinceList")
+    @ApiOperation("鑾峰彇鐪佺骇鍒楄〃")
+    public AjaxResult getProvinceList() {
+        return AjaxResult.success(bidWinningLedgerService.getProvinceList());
+    }
+
+    @GetMapping("/getCityList")
+    @ApiOperation("鏍规嵁鐪佷唤鑾峰彇鍩庡競鍒楄〃")
+    public AjaxResult getCityList(@RequestParam("provinceId") Integer provinceId) {
+        return AjaxResult.success(bidWinningLedgerService.getCityList(provinceId));
+    }
+
+    @GetMapping("/listPage")
+    @ApiOperation("涓爣鍙拌处鍒嗛〉")
+    public AjaxResult listPage(Page page, BidWinningLedger bidWinningLedger) {
+        IPage<BidWinningLedger> result = bidWinningLedgerService.listPage(page, bidWinningLedger);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/detail")
+    @ApiOperation("涓爣鍙拌处璇︽儏")
+    public AjaxResult detail(@RequestParam("id") Long id) {
+        return AjaxResult.success(bidWinningLedgerService.getDetail(id));
+    }
+
+    @PostMapping("/add")
+    @ApiOperation("鏂板涓爣鍙拌处")
+    @Log(title = "涓爣鍙拌处-鏂板", businessType = BusinessType.INSERT)
+    public AjaxResult add(@RequestBody BidWinningLedger bidWinningLedger) throws Exception {
+        return bidWinningLedgerService.addLedger(bidWinningLedger) ? success() : error();
+    }
+
+    @PostMapping("/update")
+    @ApiOperation("淇敼涓爣鍙拌处")
+    @Log(title = "涓爣鍙拌处-淇敼", businessType = BusinessType.UPDATE)
+    public AjaxResult update(@RequestBody BidWinningLedger bidWinningLedger) throws Exception {
+        return bidWinningLedgerService.updateLedger(bidWinningLedger) ? success() : error();
+    }
+
+    @PostMapping("/addRecord")
+    @ApiOperation("娣诲姞涓爣鍙拌处璁板綍")
+    @Log(title = "涓爣鍙拌处-娣诲姞璁板綍", businessType = BusinessType.INSERT)
+    public AjaxResult addRecord(@RequestBody BidWinningLedgerRecord bidWinningLedgerRecord) {
+        return bidWinningLedgerService.addRecord(bidWinningLedgerRecord) ? success() : error();
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("鍒犻櫎涓爣鍙拌处")
+    @Log(title = "涓爣鍙拌处-鍒犻櫎", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        if (Collections.isEmpty(ids)) {
+            return error("璇烽�夋嫨瑕佸垹闄ょ殑涓爣鍙拌处");
+        }
+        return bidWinningLedgerService.removeLedgerBatchByIds(ids) ? success() : error();
+    }
+}
diff --git a/src/main/java/com/ruoyi/sales/controller/BusinessOpportunityController.java b/src/main/java/com/ruoyi/sales/controller/BusinessOpportunityController.java
index 82944fc..b59da95 100644
--- a/src/main/java/com/ruoyi/sales/controller/BusinessOpportunityController.java
+++ b/src/main/java/com/ruoyi/sales/controller/BusinessOpportunityController.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.enums.FileNameType;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -69,7 +70,7 @@
     public AjaxResult listPage(Page page, BusinessOpportunity businessOpportunity) {
         IPage<BusinessOpportunity> businessOpportunityIPage = businessOpportunityService.listPage(page, businessOpportunity);
         businessOpportunityIPage.getRecords().forEach(item -> {
-            item.setBusinessCommonFiles(commonFileService.getFileList(item.getId(),9));
+            item.setBusinessCommonFiles(commonFileService.getFileList(item.getId(), FileNameType.BUSINESS_OPPORTUNITY.getValue()));
             item.setBusinessDescription(businessDescriptionMapper.selectList(Wrappers.lambdaQuery(BusinessDescription.class)
                     .eq(BusinessDescription::getBusinessOpportunityId, item.getId())
                     .orderByDesc(BusinessDescription::getCreateTime)));
diff --git a/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerMapper.java b/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerMapper.java
new file mode 100644
index 0000000..c34683e
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerMapper.java
@@ -0,0 +1,7 @@
+package com.ruoyi.sales.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.sales.pojo.BidWinningLedger;
+
+public interface BidWinningLedgerMapper extends BaseMapper<BidWinningLedger> {
+}
diff --git a/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerRecordMapper.java b/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerRecordMapper.java
new file mode 100644
index 0000000..91c5297
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/mapper/BidWinningLedgerRecordMapper.java
@@ -0,0 +1,7 @@
+package com.ruoyi.sales.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.sales.pojo.BidWinningLedgerRecord;
+
+public interface BidWinningLedgerRecordMapper extends BaseMapper<BidWinningLedgerRecord> {
+}
diff --git a/src/main/java/com/ruoyi/sales/pojo/BidWinningLedger.java b/src/main/java/com/ruoyi/sales/pojo/BidWinningLedger.java
new file mode 100644
index 0000000..b1d73d1
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/pojo/BidWinningLedger.java
@@ -0,0 +1,101 @@
+package com.ruoyi.sales.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.dto.DateQueryDto;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@TableName("bid_winning_ledger")
+@ApiModel("涓爣鍙拌处")
+public class BidWinningLedger extends DateQueryDto {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableField(exist = false)
+    @ApiModelProperty("闄勪欢")
+    private List<CommonFile> commonFiles;
+
+    @TableField(exist = false)
+    @ApiModelProperty("涓存椂鏂囦欢id")
+    private List<String> tempFileIds;
+
+    @TableField(exist = false)
+    @ApiModelProperty("鍙拌处璁板綍")
+    private List<BidWinningLedgerRecord> recordList;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("鐘舵��")
+    private String status;
+
+    @ApiModelProperty("鐪佷唤")
+    private String province;
+
+    @ApiModelProperty("鍩庡競")
+    private String city;
+
+    @ApiModelProperty("瀹㈡埛鍚嶇О")
+    private String customerName;
+
+    @ApiModelProperty("鍚堝悓閲戦")
+    private BigDecimal contractAmount;
+
+    @ApiModelProperty("鎶曟爣淇濊瘉閲�")
+    private BigDecimal bidBond;
+
+    @ApiModelProperty("涓爣鏈嶅姟璐�")
+    private BigDecimal winningServiceFee;
+
+    @ApiModelProperty("琛屼笟")
+    private String industry;
+
+    @ApiModelProperty("鍟嗘満鏉ユ簮")
+    private String businessSource;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("褰曞叆浜�")
+    private String entryPerson;
+
+    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date entryDate;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",shape = JsonFormat.Shape.STRING)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",shape = JsonFormat.Shape.STRING)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @ApiModelProperty("绉熸埛ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+}
diff --git a/src/main/java/com/ruoyi/sales/pojo/BidWinningLedgerRecord.java b/src/main/java/com/ruoyi/sales/pojo/BidWinningLedgerRecord.java
new file mode 100644
index 0000000..c1dc170
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/pojo/BidWinningLedgerRecord.java
@@ -0,0 +1,63 @@
+package com.ruoyi.sales.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@TableName("bid_winning_ledger_record")
+@ApiModel("涓爣鍙拌处璁板綍")
+public class BidWinningLedgerRecord {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("涓爣鍙拌处ID")
+    private Long bidWinningLedgerId;
+
+    @ApiModelProperty("鐘舵��")
+    private String status;
+
+    @ApiModelProperty("璁板綍鍐呭")
+    private String description;
+
+    @ApiModelProperty("褰曞叆浜�")
+    private String entryPerson;
+
+    @ApiModelProperty("褰曞叆鏃ユ湡")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private Date entryDate;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @ApiModelProperty("绉熸埛ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+}
diff --git a/src/main/java/com/ruoyi/sales/service/BidWinningLedgerService.java b/src/main/java/com/ruoyi/sales/service/BidWinningLedgerService.java
new file mode 100644
index 0000000..48a9a02
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/BidWinningLedgerService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.sales.service;
+
+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.sales.pojo.Area;
+import com.ruoyi.sales.pojo.BidWinningLedger;
+import com.ruoyi.sales.pojo.BidWinningLedgerRecord;
+
+import java.util.List;
+
+public interface BidWinningLedgerService extends IService<BidWinningLedger> {
+
+    IPage<BidWinningLedger> listPage(Page page, BidWinningLedger bidWinningLedger);
+
+    BidWinningLedger getDetail(Long id);
+
+    boolean addLedger(BidWinningLedger bidWinningLedger) throws Exception;
+
+    boolean updateLedger(BidWinningLedger bidWinningLedger) throws Exception;
+
+    boolean addRecord(BidWinningLedgerRecord bidWinningLedgerRecord);
+
+    boolean removeLedgerBatchByIds(List<Long> ids);
+
+    List<Area> getProvinceList();
+
+    List<Area> getCityList(Integer provinceId);
+}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/BidWinningLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/BidWinningLedgerServiceImpl.java
new file mode 100644
index 0000000..62a2b6a
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/service/impl/BidWinningLedgerServiceImpl.java
@@ -0,0 +1,152 @@
+package com.ruoyi.sales.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.enums.FileNameType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.sales.mapper.AreaMapper;
+import com.ruoyi.sales.mapper.BidWinningLedgerMapper;
+import com.ruoyi.sales.mapper.BidWinningLedgerRecordMapper;
+import com.ruoyi.sales.mapper.CommonFileMapper;
+import com.ruoyi.sales.pojo.Area;
+import com.ruoyi.sales.pojo.BidWinningLedger;
+import com.ruoyi.sales.pojo.BidWinningLedgerRecord;
+import com.ruoyi.sales.pojo.CommonFile;
+import com.ruoyi.sales.service.BidWinningLedgerService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class BidWinningLedgerServiceImpl extends ServiceImpl<BidWinningLedgerMapper, BidWinningLedger> implements BidWinningLedgerService {
+
+    private final BidWinningLedgerMapper bidWinningLedgerMapper;
+    private final BidWinningLedgerRecordMapper bidWinningLedgerRecordMapper;
+    private final CommonFileMapper commonFileMapper;
+    private final AreaMapper areaMapper;
+    private final CommonFileServiceImpl commonFileService;
+
+    @Override
+    public IPage<BidWinningLedger> listPage(Page page, BidWinningLedger bidWinningLedger) {
+        LambdaQueryWrapper<BidWinningLedger> queryWrapper = new LambdaQueryWrapper<>();
+        if (bidWinningLedger != null) {
+            if (StringUtils.isNotEmpty(bidWinningLedger.getCustomerName())) {
+                queryWrapper.like(BidWinningLedger::getCustomerName, bidWinningLedger.getCustomerName());
+            }
+            if (StringUtils.isNotEmpty(bidWinningLedger.getProvince())) {
+                queryWrapper.eq(BidWinningLedger::getProvince, bidWinningLedger.getProvince());
+            }
+            if (StringUtils.isNotEmpty(bidWinningLedger.getCity())) {
+                queryWrapper.eq(BidWinningLedger::getCity, bidWinningLedger.getCity());
+            }
+            if (StringUtils.isNotEmpty(bidWinningLedger.getEntryPerson())) {
+                queryWrapper.like(BidWinningLedger::getEntryPerson, bidWinningLedger.getEntryPerson());
+            }
+            if (StringUtils.isNotEmpty(bidWinningLedger.getStatus())) {
+                queryWrapper.eq(BidWinningLedger::getStatus, bidWinningLedger.getStatus());
+            }
+            if (StringUtils.isNotEmpty(bidWinningLedger.getEntryDateStart()) && StringUtils.isNotEmpty(bidWinningLedger.getEntryDateEnd())) {
+                queryWrapper.ge(BidWinningLedger::getEntryDate, bidWinningLedger.getEntryDateStart())
+                        .le(BidWinningLedger::getEntryDate, bidWinningLedger.getEntryDateEnd());
+            }
+        }
+        queryWrapper.orderByDesc(BidWinningLedger::getUpdateTime)
+                .orderByDesc(BidWinningLedger::getEntryDate);
+        return bidWinningLedgerMapper.selectPage(page, queryWrapper);
+    }
+
+    @Override
+    public BidWinningLedger getDetail(Long id) {
+        BidWinningLedger bidWinningLedger = bidWinningLedgerMapper.selectById(id);
+        if (bidWinningLedger == null) {
+            return null;
+        }
+        bidWinningLedger.setCommonFiles(commonFileService.getFileList(id, FileNameType.BID_WINNING_LEDGER.getValue()));
+        bidWinningLedger.setRecordList(bidWinningLedgerRecordMapper.selectList(new LambdaQueryWrapper<BidWinningLedgerRecord>()
+                .eq(BidWinningLedgerRecord::getBidWinningLedgerId, id)
+                .orderByDesc(BidWinningLedgerRecord::getCreateTime)));
+        return bidWinningLedger;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean addLedger(BidWinningLedger bidWinningLedger) throws IOException {
+        fillDefaultFields(bidWinningLedger);
+        boolean saved = save(bidWinningLedger);
+        if (saved) {
+            commonFileService.migrateTempFilesToFormal(bidWinningLedger.getId(), bidWinningLedger.getTempFileIds());
+        }
+        return saved;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateLedger(BidWinningLedger bidWinningLedger) throws IOException {
+        fillDefaultFields(bidWinningLedger);
+        boolean updated = updateById(bidWinningLedger);
+        if (updated) {
+            commonFileService.migrateTempFilesToFormal(bidWinningLedger.getId(), bidWinningLedger.getTempFileIds());
+        }
+        return updated;
+    }
+
+    @Override
+    public boolean addRecord(BidWinningLedgerRecord bidWinningLedgerRecord) {
+        if (StringUtils.isEmpty(bidWinningLedgerRecord.getEntryPerson())) {
+            bidWinningLedgerRecord.setEntryPerson(SecurityUtils.getLoginUser().getUser().getNickName());
+        }
+        if (bidWinningLedgerRecord.getEntryDate() == null) {
+            bidWinningLedgerRecord.setEntryDate(new Date());
+        }
+        int inserted = bidWinningLedgerRecordMapper.insert(bidWinningLedgerRecord);
+        if (inserted > 0 && bidWinningLedgerRecord.getBidWinningLedgerId() != null) {
+            BidWinningLedger updateEntity = new BidWinningLedger();
+            updateEntity.setId(bidWinningLedgerRecord.getBidWinningLedgerId());
+            updateEntity.setStatus(bidWinningLedgerRecord.getStatus());
+            bidWinningLedgerMapper.updateById(updateEntity);
+            return true;
+        }
+        return inserted > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean removeLedgerBatchByIds(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        bidWinningLedgerRecordMapper.delete(new LambdaQueryWrapper<BidWinningLedgerRecord>()
+                .in(BidWinningLedgerRecord::getBidWinningLedgerId, ids));
+        commonFileMapper.delete(new LambdaQueryWrapper<CommonFile>()
+                .in(CommonFile::getCommonId, ids)
+                .eq(CommonFile::getType, FileNameType.BID_WINNING_LEDGER.getValue()));
+        return removeByIds(ids);
+    }
+
+    @Override
+    public List<Area> getProvinceList() {
+        return areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getLevel, 1).eq(Area::getParentId, 0));
+    }
+
+    @Override
+    public List<Area> getCityList(Integer provinceId) {
+        return areaMapper.selectList(new LambdaQueryWrapper<Area>().eq(Area::getLevel, 2).eq(Area::getParentId, provinceId));
+    }
+
+    private void fillDefaultFields(BidWinningLedger bidWinningLedger) {
+        if (StringUtils.isEmpty(bidWinningLedger.getEntryPerson())) {
+            bidWinningLedger.setEntryPerson(SecurityUtils.getLoginUser().getUser().getNickName());
+        }
+        if (bidWinningLedger.getEntryDate() == null) {
+            bidWinningLedger.setEntryDate(new Date());
+        }
+    }
+}

--
Gitblit v1.9.3