已添加14个文件
已修改23个文件
911 ■■■■■ 文件已修改
.gitignore 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/controller/EnterpriseFixedAssetsController.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/mapper/EnterpriseFixedAssetsMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/pojo/EnterpriseFixedAssets.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/EnterpriseFixedAssetsService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/impl/EnterpriseFixedAssetsServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/EnterpriseInfoController.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/SupplierManageController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/EnterpriseInfoMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/Customer.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/EnterpriseInfo.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/SupplierManage.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IEnterpriseInfoService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/StorageBlobService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/EnterpriseInfoServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/controller/TempFileController.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/DiscountTypeEnum.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/Details.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementUpdateDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/SimplePP.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/common/CommonController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/EnterpriseFixedAssetsMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/EnterpriseInfoMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/SupplierManageMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -24,6 +24,8 @@
*.iws
*.iml
*.ipr
### vscode ###
.vscode
### JRebel ###
rebel.xml
src/main/java/com/ruoyi/account/controller/EnterpriseFixedAssetsController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,49 @@
package com.ruoyi.account.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.account.pojo.EnterpriseFixedAssets;
import com.ruoyi.account.service.EnterpriseFixedAssetsService;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@AllArgsConstructor
@RequestMapping("/enterpriseFixedAssets")
@Api(value = "EnterpriseFixedAssets", tags = "固定资产")
public class EnterpriseFixedAssetsController {
    private EnterpriseFixedAssetsService enterpriseFixedAssetsservice;
    @GetMapping("/listPage")
    @ApiOperation("分页查询所有")
    public AjaxResult listPage(Page page, EnterpriseFixedAssets enterpriseFixedAssets) {
        IPage<EnterpriseFixedAssets> listPage = enterpriseFixedAssetsservice.listPage(page, enterpriseFixedAssets);
        return AjaxResult.success(listPage);
    }
    @PostMapping("/add")
    @ApiOperation("新增")
    public AjaxResult add(@RequestBody EnterpriseFixedAssets enterpriseFixedAssets) {
        return AjaxResult.success(enterpriseFixedAssetsservice.save(enterpriseFixedAssets));
    }
    @PostMapping("/update")
    @ApiOperation("修改")
    public AjaxResult update(@RequestBody EnterpriseFixedAssets enterpriseFixedAssets) {
        return AjaxResult.success(enterpriseFixedAssetsservice.updateById(enterpriseFixedAssets));
    }
    @DeleteMapping("/delete")
    @ApiOperation("删除")
    public AjaxResult delete(@RequestBody List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("请传入要删除的ID");
        return AjaxResult.success(enterpriseFixedAssetsservice.removeBatchByIds(ids));
    }
}
src/main/java/com/ruoyi/account/mapper/EnterpriseFixedAssetsMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.ruoyi.account.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.account.pojo.EnterpriseFixedAssets;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EnterpriseFixedAssetsMapper extends BaseMapper<EnterpriseFixedAssets> {
}
src/main/java/com/ruoyi/account/pojo/EnterpriseFixedAssets.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.ruoyi.account.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("enterprise_fixed_assets")
@ApiModel(description="")
public class EnterpriseFixedAssets implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
    *
    */
    @ApiModelProperty(value="")
    private Long id;
    /**
    * åç§°
    */
    @ApiModelProperty(value="名称")
    private String name;
    /**
    * åž‹å·
    */
    @ApiModelProperty(value="型号")
    private String model;
    /**
    * ä»·æ ¼
    */
    @ApiModelProperty(value="ä»·æ ¼")
    private BigDecimal price;
    /**
    * åœ°å€
    */
    @ApiModelProperty(value="地址")
    private String address;
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @ApiModelProperty(value = "修改时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
}
src/main/java/com/ruoyi/account/service/EnterpriseFixedAssetsService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.ruoyi.account.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.account.pojo.EnterpriseFixedAssets;
public interface EnterpriseFixedAssetsService extends IService<EnterpriseFixedAssets> {
    IPage<EnterpriseFixedAssets> listPage(Page<EnterpriseFixedAssets> page, EnterpriseFixedAssets enterpriseFixedAssets);
}
src/main/java/com/ruoyi/account/service/impl/EnterpriseFixedAssetsServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.ruoyi.account.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.account.mapper.EnterpriseFixedAssetsMapper;
import com.ruoyi.account.pojo.EnterpriseFixedAssets;
import com.ruoyi.account.service.EnterpriseFixedAssetsService;
import com.ruoyi.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EnterpriseFixedAssetsServiceImpl extends ServiceImpl<EnterpriseFixedAssetsMapper, EnterpriseFixedAssets> implements EnterpriseFixedAssetsService {
    private final EnterpriseFixedAssetsMapper enterpriseFixedAssetsmapper;
    @Override
    public IPage<EnterpriseFixedAssets> listPage(Page<EnterpriseFixedAssets> page, EnterpriseFixedAssets enterpriseFixedAssets) {
        LambdaQueryWrapper<EnterpriseFixedAssets> queryWrapper = new LambdaQueryWrapper<>();
        if (enterpriseFixedAssets != null && StringUtils.isNotBlank(enterpriseFixedAssets.getName())) {
            queryWrapper.like(EnterpriseFixedAssets::getName, enterpriseFixedAssets.getName());
        }
        return enterpriseFixedAssetsmapper.selectPage(page, queryWrapper);
    }
}
src/main/java/com/ruoyi/basic/controller/EnterpriseInfoController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
package com.ruoyi.basic.controller;
import com.ruoyi.basic.pojo.EnterpriseInfo;
import com.ruoyi.basic.service.IEnterpriseInfoService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.service.TempFileService;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
@RequestMapping("/system/enterpriseInfo")
@AllArgsConstructor
public class EnterpriseInfoController {
    private final IEnterpriseInfoService enterpriseInfoService;
    private final TempFileService tempFileService;
    /**
     * èŽ·å–ä¼ä¸šä¿¡æ¯
     */
    @GetMapping("/getInfo")
    public AjaxResult getInfo() {
        return AjaxResult.success(enterpriseInfoService.getEnterpriseInfo());
    }
    /**
     * ä¿å­˜æˆ–更新企业信息
     */
    @PostMapping("/save")
    public AjaxResult save(@RequestBody EnterpriseInfo enterpriseInfo) {
        boolean result = enterpriseInfoService.saveOrUpdateInfo(enterpriseInfo);
        if (result) {
            return AjaxResult.success("保存成功");
        }
        return AjaxResult.error("保存失败");
    }
    /**
     * ä¸Šä¼ ä¼ä¸šLogo
     */
    @PostMapping("/uploadLogo")
    @ApiOperation(value = "上传企业Logo")
    public AjaxResult uploadLogo(@RequestParam("file") MultipartFile file) {
        try {
            return AjaxResult.success(tempFileService.uploadFile(file, 0));
        } catch (IOException e) {
            return AjaxResult.error("上传失败:" + e.getMessage());
        }
    }
    /**
     * ä¸Šä¼ äºŒç»´ç 
     */
    @PostMapping("/uploadQrCode")
    @ApiOperation(value = "上传二维码")
    public AjaxResult uploadQrCode(@RequestParam("file") MultipartFile file) {
        try {
            return AjaxResult.success(tempFileService.uploadFile(file, 1));
        } catch (IOException e) {
            return AjaxResult.error("上传失败:" + e.getMessage());
        }
    }
}
src/main/java/com/ruoyi/basic/controller/SupplierManageController.java
@@ -1,8 +1,8 @@
package com.ruoyi.basic.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.dto.SupplierManageDto;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.basic.service.ISupplierService;
import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -118,6 +118,7 @@
     */
    @GetMapping("/getOptions")
    public AjaxResult getOptions() {
        return AjaxResult.success(supplierService.list());
        return AjaxResult.success(supplierService.list(new LambdaQueryWrapper<SupplierManage>()
                .eq(SupplierManage::getIsWhite, 0)));
    }
}
src/main/java/com/ruoyi/basic/mapper/EnterpriseInfoMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
package com.ruoyi.basic.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.basic.pojo.EnterpriseInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EnterpriseInfoMapper extends BaseMapper<EnterpriseInfo> {
}
src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -1,7 +1,10 @@
package com.ruoyi.basic.pojo;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -31,6 +34,10 @@
     */
    @Excel(name = "客户名称")
    private String customerName;
    /** å®¢æˆ·åˆ†ç±»ï¼šé›¶å”®å®¢æˆ·ï¼Œè¿›é”€å•†å®¢æˆ· */
    @Excel(name = "客户分类")
    private String customerType;
    /**
     * çº³ç¨Žäººè¯†åˆ«å·
@@ -95,4 +102,31 @@
    @ApiModelProperty(value = "开户行号")
    @Excel(name = "开户行号")
    private String bankCode;
    @ApiModelProperty(value = "客户偏好")
    private String preferences;
    @ApiModelProperty(value = "是否价格敏感")
    @Excel(name = "是否价格敏感")
    private Boolean isPriceSensitive;
    @ApiModelProperty(value = "是否会员")
    @Excel(name = "是否会员")
    private Boolean isVip;
    @TableField(exist = false)
    @ApiModelProperty(value = "购买次数")
    private Integer purchaseCount;
    @TableField(exist = false)
    @ApiModelProperty(value = "平均金额")
    private BigDecimal averageAmount;
    @TableField(exist = false)
    @ApiModelProperty(value = "最近购买时间")
    private LocalDate latestPurchaseTime;
    @TableField(exist = false)
    @ApiModelProperty(value = "常购产品")
    private List<String> topProducts;
}
src/main/java/com/ruoyi/basic/pojo/EnterpriseInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.ruoyi.basic.pojo;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@TableName("enterprise_info")
public class EnterpriseInfo implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ä¸»é”®ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;
    /**
     * å…¬å¸åç§°
     */
    @ApiModelProperty(value = "公司名称")
    private String companyName;
    /**
     * å…¬å¸Logo
     */
    @ApiModelProperty(value = "公司Logo")
    private String companyLogo;
    /**
     * å…¬å¸ç®€ä»‹
     */
    @ApiModelProperty(value = "公司简介")
    private String companyIntro;
    /**
     * äº§å“ä»‹ç»
     */
    @ApiModelProperty(value = "产品介绍")
    private String productIntro;
    /**
     * è®¾å¤‡ä»‹ç»
     */
    @ApiModelProperty(value = "设备介绍")
    private String equipmentIntro;
    /**
     * è”系人
     */
    @ApiModelProperty(value = "联系人")
    private String contactPerson;
    /**
     * è”系电话
     */
    @ApiModelProperty(value = "联系电话")
    private String contactPhone;
    /**
     * å…¬å¸åœ°å€
     */
    @ApiModelProperty(value = "公司地址")
    private String companyAddress;
    /**
     * å…¬å¸ç½‘ç«™
     */
    @ApiModelProperty(value = "公司网站")
    private String website;
    /**
     * äºŒç»´ç 
     */
    @ApiModelProperty(value = "二维码")
    private String qrCode;
    /**
     * åˆ›å»ºè€…
     */
    @TableField(fill = FieldFill.INSERT)
    private String createUser;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    /**
     * æ›´æ–°è€…
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateUser;
    /**
     * æ›´æ–°æ—¶é—´
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    /**
     * ç§Ÿæˆ·ID
     */
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
}
src/main/java/com/ruoyi/basic/pojo/SupplierManage.java
@@ -76,4 +76,7 @@
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "是否白名单(0是 1否)")
    private Long isWhite;
}
src/main/java/com/ruoyi/basic/service/IEnterpriseInfoService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.ruoyi.basic.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.basic.pojo.EnterpriseInfo;
public interface IEnterpriseInfoService extends IService<EnterpriseInfo> {
    /**
     * èŽ·å–ä¼ä¸šä¿¡æ¯ï¼ˆå•æ¡ï¼‰
     */
    EnterpriseInfo getEnterpriseInfo();
    /**
     * ä¿å­˜æˆ–更新企业信息
     */
    boolean saveOrUpdateInfo(EnterpriseInfo enterpriseInfo);
}
src/main/java/com/ruoyi/basic/service/StorageBlobService.java
@@ -28,6 +28,8 @@
    List<StorageBlobDTO> updateStorageBlobs(List<MultipartFile> files, String bucketName,Long type);
    List<StorageBlobDTO> updateStorageBlob(MultipartFile file, String bucketName, Long type);
    /**
     * æ‰¹é‡åˆ é™¤æ–‡ä»¶
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -17,17 +17,17 @@
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@@ -42,6 +42,7 @@
@Slf4j
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {
    private final SalesLedgerMapper salesLedgerMapper;
    private final SalesLedgerProductMapper salesLedgerProductMapper;
    private CustomerMapper customerMapper;
    /**
@@ -74,8 +75,12 @@
        // 2. æž„建查询条件(增强空值安全)
        LambdaQueryWrapper<Customer> queryWrapper = new LambdaQueryWrapper<>();
        String customerName = customer.getCustomerName();
        String customerType = customer.getCustomerType();
        if (StringUtils.isNotBlank(customerName)) {
            queryWrapper.like(Customer::getCustomerName, customerName);
        }
        if (StringUtils.isNotBlank(customerType)) {
            queryWrapper.like(Customer::getCustomerType, customerType);
        }
        // 3. æ‰§è¡Œåˆ†é¡µæŸ¥è¯¢ï¼ˆä¿ç•™åˆ†é¡µå…ƒæ•°æ®ï¼‰
@@ -89,6 +94,71 @@
                    String address = StringUtils.defaultString(c.getCompanyAddress(), "");
                    String phone = StringUtils.defaultString(c.getCompanyPhone(), "");
                    c.setAddressPhone(address + "(" + phone + ")"); // ä¼˜åŒ–字符串拼接
                    // æŸ¥è¯¢è¯¥å®¢æˆ·å…³è”的销售台账中,购买次数、平均金额、最近购买时间
                    List<SalesLedger> salesLedgers = salesLedgerMapper.selectList(new QueryWrapper<SalesLedger>().lambda().eq(SalesLedger::getCustomerId, c.getId()));
                    if (!CollectionUtils.isEmpty(salesLedgers)) {
                        // è®¡ç®—购买次数
                        int purchaseCount = salesLedgers.size();
                        c.setPurchaseCount(purchaseCount);
                        // è®¡ç®—平均金额
                        if (purchaseCount > 0) {
                            BigDecimal totalAmount = salesLedgers.stream()
                                    .map(SalesLedger::getContractAmount)
                                    .filter(Objects::nonNull)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            BigDecimal averageAmount = totalAmount.divide(BigDecimal.valueOf(purchaseCount), 2, BigDecimal.ROUND_HALF_UP);
                            c.setAverageAmount(averageAmount);
                        } else {
                            c.setAverageAmount(BigDecimal.ZERO);
                        }
                        // è®¡ç®—最近购买时间
                        SalesLedger latestLedger = salesLedgers.stream()
                                .max((l1, l2) -> l1.getExecutionDate().compareTo(l2.getExecutionDate()))
                                .orElse(null);
                        if (latestLedger != null) {
                            c.setLatestPurchaseTime(latestLedger.getExecutionDate());
                        }
                        // è®¡ç®—常购产品(top 3)
                        List<SalesLedgerProduct> allProducts = new ArrayList<>();
                        for (SalesLedger ledger : salesLedgers) {
                            List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(
                                    new QueryWrapper<SalesLedgerProduct>().lambda()
                                            .eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId())
                            );
                            if (!CollectionUtils.isEmpty(products)) {
                                allProducts.addAll(products);
                            }
                        }
                        if (!CollectionUtils.isEmpty(allProducts)) {
                            // æŒ‰äº§å“ç±»åˆ«å’Œè§„格型号分组,统计购买次数
                            Map<String, Long> productCountMap = allProducts.stream()
                                    .collect(Collectors.groupingBy(
                                            p -> p.getProductCategory() + "-" + p.getSpecificationModel(),
                                            Collectors.counting()
                                    ));
                            // æŽ’序并取前3
                            List<String> topProducts = productCountMap.entrySet().stream()
                                    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                                    .limit(3)
                                    .map(Map.Entry::getKey)
                                    .collect(Collectors.toList());
                            c.setTopProducts(topProducts);
                        } else {
                            c.setTopProducts(new ArrayList<>());
                        }
                    } else {
                        // æ²¡æœ‰é”€å”®è®°å½•时设置默认值
                        c.setPurchaseCount(0);
                        c.setAverageAmount(BigDecimal.ZERO);
                        c.setLatestPurchaseTime(null);
                        c.setTopProducts(new ArrayList<>());
                    }
                })
                .collect(Collectors.toList());
src/main/java/com/ruoyi/basic/service/impl/EnterpriseInfoServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package com.ruoyi.basic.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.basic.mapper.EnterpriseInfoMapper;
import com.ruoyi.basic.pojo.EnterpriseInfo;
import com.ruoyi.basic.service.IEnterpriseInfoService;
import org.springframework.stereotype.Service;
@Service
public class EnterpriseInfoServiceImpl extends ServiceImpl<EnterpriseInfoMapper, EnterpriseInfo>
        implements IEnterpriseInfoService {
    @Override
    public EnterpriseInfo getEnterpriseInfo() {
        LambdaQueryWrapper<EnterpriseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(EnterpriseInfo::getId).last("LIMIT 1");
        EnterpriseInfo info = this.getOne(wrapper);
        if (info == null) {
            info = new EnterpriseInfo();
        }
        return info;
    }
    @Override
    public boolean saveOrUpdateInfo(EnterpriseInfo enterpriseInfo) {
        if (enterpriseInfo.getId() == null) {
            return this.save(enterpriseInfo);
        }
        return this.updateById(enterpriseInfo);
    }
}
src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java
@@ -26,6 +26,7 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@@ -110,6 +111,11 @@
        return storageBlobDTOs;
    }
    @Override
    public List<StorageBlobDTO> updateStorageBlob(MultipartFile file, String bucketName, Long type) {
        return updateStorageBlobs(Collections.singletonList(file), bucketName, type);
    }
    private StorageBlobDTO buildStorageBlobDTO(MultipartFile file, MinioResult res, String bucketName, Long type) {
        StorageBlobDTO dto = new StorageBlobDTO();
        dto.setContentType(file.getContentType());
src/main/java/com/ruoyi/other/controller/TempFileController.java
@@ -1,18 +1,25 @@
package com.ruoyi.other.controller;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.other.service.TempFileService;
import com.ruoyi.purchase.dto.ProductRecordDto;
import com.ruoyi.purchase.dto.TicketRegistrationDto;
import com.ruoyi.purchase.service.ITicketRegistrationService;
import com.ruoyi.purchase.service.impl.TicketRegistrationServiceImpl;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
@@ -45,4 +52,51 @@
        return AjaxResult.success();
    }
    /**
     * å›¾ç‰‡é¢„览(根据磁盘路径)
     */
    @GetMapping("/preview")
    @ApiOperation(value = "图片预览")
    public void previewImage(String url, HttpServletResponse response) {
        if (!StringUtils.hasText(url)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }
        try {
            Path filePath = Paths.get(url);
            if (!Files.exists(filePath) || !Files.isRegularFile(filePath)) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            String filename = filePath.getFileName().toString();
            String ext = filename.contains(".") ? filename.substring(filename.lastIndexOf('.') + 1).toLowerCase() : "";
            MediaType mediaType;
            switch (ext) {
                case "png":
                    mediaType = MediaType.IMAGE_PNG;
                    break;
                case "gif":
                    mediaType = MediaType.IMAGE_GIF;
                    break;
                case "bmp":
                    mediaType = MediaType.parseMediaType("image/bmp");
                    break;
                case "webp":
                    mediaType = MediaType.parseMediaType("image/webp");
                    break;
                case "jpg":
                case "jpeg":
                    mediaType = MediaType.IMAGE_JPEG;
                    break;
                default:
                    mediaType = MediaType.APPLICATION_OCTET_STREAM;
            }
            response.setContentType(mediaType.toString());
            response.setHeader(HttpHeaders.CACHE_CONTROL, "max-age=3600");
            Files.copy(filePath, response.getOutputStream());
        } catch (IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }
}
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;
    }
}
src/main/java/com/ruoyi/procurementrecord/dto/Details.java
@@ -13,4 +13,15 @@
    private Integer id;
    private BigDecimal inboundQuantity;
    private BigDecimal warnNum;
    /**
     * ç¼ºè´§æ•°é‡
     */
    private BigDecimal outStockQuantity;
    /**
     * ç¼ºè´§æƒ…况
     */
    private String shortageDescription;
}
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java
@@ -151,4 +151,14 @@
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate endDate;
    /**
     * ç¼ºè´§æ•°é‡
     */
    private BigDecimal outStockQuantity;
    /**
     * ç¼ºè´§æƒ…况
     */
    private String shortageDescription;
}
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementUpdateDto.java
@@ -20,4 +20,14 @@
    private List<Integer> ids;
    /**
     * ç¼ºè´§æ•°é‡
     */
    private BigDecimal outStockQuantity;
    /**
     * ç¼ºè´§æƒ…况
     */
    private String shortageDescription;
}
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;
/**
 * ç”¨äºŽè‡ªåŠ¨ç”Ÿæˆé‡‡è´­ä»·æ ¼ç®¡ç†çš„ç®€å•DTO
 * ä¸€ä¸‹
 * @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;
}
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;
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java
@@ -46,6 +46,16 @@
//    private BigDecimal minStock;
    /**
     * ç¼ºè´§æ•°é‡
     */
    private BigDecimal outStockQuantity;
    /**
     * ç¼ºè´§æƒ…况
     */
    private String shortageDescription;
    /**
     * å…¥åº“用户
     */
    private String createBy;
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;
}
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 {
        // æ ¹æ®ä¾›åº”商id äº§å“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);
    }
}
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java
@@ -106,6 +106,8 @@
        procurementRecordStorageById.setWarnNum(procurementDto.getWarnNum());
        procurementRecordStorageById.setUpdateUser(SecurityUtils.getLoginUser().getUserId());
        procurementRecordStorageById.setUpdateTime(LocalDateTime.now());
        procurementRecordStorageById.setOutStockQuantity(procurementDto.getOutStockQuantity());
        procurementRecordStorageById.setShortageDescription(procurementDto.getShortageDescription());
        return procurementRecordMapper.updateById(procurementRecordStorageById);
    }
@@ -350,6 +352,8 @@
                    .inboundBatches(aLong.equals(0L) ? "第1批次" : "第"+ (aLong + 1) + "批次")
                    .inboundNum(detail.getInboundQuantity())
                    .warnNum(detail.getWarnNum())
                    .outStockQuantity(detail.getOutStockQuantity())
                    .shortageDescription(detail.getShortageDescription())
                    .createTime(LocalDateTime.now())
                    .createUser(loginUser.getUserId())
                    .updateTime(LocalDateTime.now())
src/main/java/com/ruoyi/project/common/CommonController.java
@@ -90,6 +90,16 @@
    }
    /**
     * minio通用上传请求(单个)
     */
    @PostMapping("/minioUpload")
    @ApiOperation(value = "minio通用上传请求")
    public AjaxResult minioUploadFile(MultipartFile file, String bucketName, Long type) throws Exception
    {
        return AjaxResult.success(storageBlobService.updateStorageBlob(file, bucketName,type));
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚(单个)
     */
    @PostMapping("/upload")
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)
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -29,7 +29,6 @@
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@@ -278,7 +277,7 @@
    public AjaxResult getProductInventory(SalesLedgerProduct salesLedgerProduct){
        List<SalesLedgerProduct> list = salesLedgerProductService.selectSalesLedgerProductList(salesLedgerProduct);
        if(CollectionUtils.isEmpty(list)){
            return AjaxResult.error("该产品不存在");
            throw new RuntimeException("该产品不存在");
        }
        List<ProcurementPageDto> procurementPageDtoList = new ArrayList<>();
        list.forEach(item -> {
@@ -289,7 +288,7 @@
            procurementPageDtoList.addAll(procurementPageDtoIPage.getRecords());
        });
        if(!CollectionUtils.isEmpty(procurementPageDtoList)){
            return AjaxResult.error("该产品库存不存在");
            throw new RuntimeException("该产品库存不存在");
        }
        AtomicInteger num = new AtomicInteger();
        list.forEach(item -> {
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java
@@ -2,11 +2,13 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.sales.pojo.CommonFile;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
@@ -40,6 +42,13 @@
    @TableField(exist = false)
    private String createUser;
    /**
     * åˆåŒé‡‘额(产品含税总价)
     */
    @ApiModelProperty(name = "合同金额")
    private BigDecimal contractAmount;
    private Boolean hasChildren = false;
    private List<SalesLedgerProduct> productData;
src/main/resources/mapper/account/EnterpriseFixedAssetsMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
<?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.account.mapper.EnterpriseFixedAssetsMapper">
    <resultMap id="BaseResultMap" type="com.ruoyi.account.pojo.EnterpriseFixedAssets">
        <id column="id" property="id" />
                <result column="name" property="name" />
                <result column="model" property="model" />
                <result column="price" property="price" />
                <result column="address" property="address" />
                <result column="create_time" property="createTime" />
                <result column="update_time" property="updateTime" />
                <result column="tenant_id" property="tenantId" />
    </resultMap>
</mapper>
src/main/resources/mapper/basic/EnterpriseInfoMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
<?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.basic.mapper.EnterpriseInfoMapper">
</mapper>
src/main/resources/mapper/basic/SupplierManageMapper.xml
@@ -22,6 +22,7 @@
        T1.update_time,
        T1.update_user,
        T1.tenant_id,
        T1.is_white,
        T2.nick_name AS maintainUserName
        FROM supplier_manage T1
        LEFT JOIN sys_user T2 ON T1.maintain_user_id = T2.user_id
@@ -29,6 +30,9 @@
            <if test="supplierManageDto.supplierName != null and supplierManageDto.supplierName != '' ">
                AND T1.supplier_name LIKE CONCAT('%',#{supplierManageDto.supplierName},'%')
            </if>
            <if test="supplierManageDto.isWhite != null and supplierManageDto.isWhite.toString() != '' ">
                AND T1.is_white LIKE CONCAT('%',#{supplierManageDto.isWhite},'%')
            </if>
        </where>
    </select>
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>
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml
@@ -48,7 +48,9 @@
        t1.create_time,
        t1.update_time,
        t1.create_by,
        t2.warn_num
        t2.warn_num,
        t1.out_stock_quantity as outStockQuantity,
        t1.shortage_description as shortageDescription
        from  procurement_record_storage t1
                  left join sales_ledger_product t2 on t2.id = t1.sales_ledger_product_id
                  left join purchase_ledger t3 on t3.id = t2.sales_ledger_id