| 2026-03-28 | yuan | ![]() |
| 2026-03-28 | yuan | ![]() |
| 2026-03-28 | yuan | ![]() |
| 2026-03-28 | yuan | ![]() |
| 2026-03-28 | buhuazhen | ![]() |
| 2026-03-28 | gongchunyi | ![]() |
| 2026-03-28 | gongchunyi | ![]() |
| 2026-03-28 | huminmin | ![]() |
| 2026-03-28 | huminmin | ![]() |
| 2026-03-28 | huminmin | ![]() |
| 2026-03-28 | huminmin | ![]() |
| 2026-03-28 | chenhj | ![]() |
| 2026-03-28 | huminmin | ![]() |
| 2026-03-28 | chenhj | ![]() |
.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