doc/20260522_²ÆÎñÖúÊÖÌáÎÊÓÅ»¯Ç°¶Ë±ä¸üÎĵµ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,59 @@ # è´¢å¡å©ææé®ä¼ååç«¯åæ´ææ¡£ æ´æ°æ¶é´ï¼2026-05-22 éç¨æ¨¡åï¼è´¢å¡æºè½å©æï¼`/financial-ai`ï¼ ## 1. èæ¯ å½åé¦é¡µè´¢å¡å©æå¿«æ·æé®ä¸ºï¼ 1. `çææ¬å¨ç»è¥å¨æ¥` 2. `为ä»ä¹å©æ¶¦ä¸é` 3. `åªä¸ªå®¢æ·æèµé±` é®é¢ç¹ï¼ - 第 3 æ¡é®æ³å¨é¨ååºæ¯ä¸æå¾å½ä¸ä¸ç¨³å®ï¼å®¹æèµ°æ®éææ¬åçï¼å¯¼è´å¾è¡¨é¾æ¥ä»¥åå§ Markdown ææ¬å±ç¤ºï¼å¦ ``ï¼ã - å¿«æ·æé®ç¼ºå°æ¶é´èå´ååæç®æ ï¼ç»æç¨³å®æ§ä¸å¯è§£éæ§è¾å¼±ã ## 2. åç«¯å¿«æ·æé®ææ¡ä¼åï¼å¿ æ¹ï¼ 建议å°é»è®¤ä¸æ¡å¿«æ·æé®è°æ´ä¸ºï¼ 1. `çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼` 2. `åææ¬æå©æ¶¦ä¸éåå ` 3. `è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«` 说æï¼ - 䏿¡é®æ³å带æ¶é´èå´æåæç®æ ï¼å端å½ä¸æ´ç¨³å®ã - 第 3 æ¡ä¸âæèµé±å®¢æ·âè¯ä¹ä¸è´ï¼ä½â婿¶¦è´¡ç®æé«âæ´æç¡®ï¼éåç´æ¥é©±å¨å©æ¶¦åæç»æé¡µã ## 3. ä¸å端è½åæ å° | å¿«æ·æé® | 颿å½ä¸è½å | 颿 `type` | | --- | --- | --- | | çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼ | ç»è¥æ¥åçæ | `financial_operation_report` | | åææ¬æå©æ¶¦ä¸éåå | 订å婿¶¦åæ | `financial_order_profit_analysis` | | è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé« | 订å婿¶¦åæ | `financial_order_profit_analysis` | åç«¯å·²åæ¥å¢å¼ºâæèµé±å®¢æ·/客æ·å©æ¶¦æé«/婿¶¦è´¡ç®æé«âçåä¹é®æ³è¯å«ï¼å端æä»¥ä¸ææ¡æ¹é åå¯ç´æ¥èè°ã ## 4. è天å 容渲æå åºï¼å»ºè®®æ¹ï¼ é对è天è¿åææ¬ä¸åºç°çå¾è¡¨ Markdown 龿¥ï¼`https://local/generate_chart?options=...`ï¼ï¼å»ºè®®å端å¢å å åºå¤çï¼ 1. è¯å« Markdown å¾çè¯æ³ä¸ç `local/generate_chart` 龿¥ã 2. è§£æ `options` åæ°å¹¶è½¬æ¢ä¸º ECharts `option` 忏²æå¾è¡¨ç»ä»¶ã 3. è§£æå¤±è´¥æ¶ä¸å±ç¤ºåå§é¿é¾æ¥ææ¬ï¼å±ç¤ºç»ä¸ç©ºææç¤ºã ## 5. èè°å彿¸ å 1. ç¹å»å¿«æ·æé® `çææ¬å¨ç»è¥å¨æ¥ï¼å©æ¶¦ä¸ç°éæµï¼` - æ ¡éªè¿å `type=financial_operation_report`ï¼å¹¶æ£å¸¸æ¸²ææè¦/建议/å¾è¡¨ã 2. ç¹å»å¿«æ·æé® `åææ¬æå©æ¶¦ä¸éåå ` - æ ¡éªè¿å `type=financial_order_profit_analysis`ï¼å¹¶å±ç¤ºäºæè®¢åä¸å®¢æ·å©æ¶¦æè¡ã 3. ç¹å»å¿«æ·æé® `è¿30天åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«` - æ ¡éªè¿å `type=financial_order_profit_analysis`ï¼`summary.topCustomerByProfit` æå¼ã 4. æå·¥è¾å ¥ `åªä¸ªå®¢æ·æèµé±`ã`åªä¸ªå®¢æ·å©æ¶¦æé«` - æ ¡éªä»å½ä¸ `financial_order_profit_analysis`ï¼ä¸ååºç°åå§å¾è¡¨ Markdown 龿¥ç´åºã src/main/java/com/ruoyi/account/bean/vo/AccountReportVo.java
@@ -4,6 +4,7 @@ import lombok.Data; import java.math.BigDecimal; import java.util.List; @Data @@ -16,13 +17,50 @@ @Schema(description = "æ»æ¯åº") private BigDecimal totalExpense; @Schema(description = "æ»æ¶å ¥ç¬æ°") private Integer incomeNumber; @Schema(description = "åºæ¶è´¦æ¬¾") private BigDecimal accountsReceivable; @Schema(description = "æ»æ¯åºç¬æ°") private Integer expenseNumber; @Schema(description = "åºä»è´¦æ¬¾") private BigDecimal accountsPayable; @Schema(description = "åæ¶å ¥") private BigDecimal netRevenue; // --- æçº¿å¾ï¼æåº¦è¶å¿æ°æ® --- @Schema(description = "æåº¦è¶å¿æ°æ®å表") private List<MonthlyTrendVO> monthlyTrendList; // --- æ±ç¶å¾ï¼åºæ¶åºä»æåº¦æ°æ® --- @Schema(description = "åºæ¶åºä»æåº¦æ°æ®å表") private List<ReceivablePayableVO> receivablePayableList; @Data @Schema(description = "æåº¦è¶å¿VOï¼æçº¿å¾ç¨ï¼") public static class MonthlyTrendVO { @Schema(description = "æä»½ï¼æ ¼å¼ï¼yyyy-MM") private String month; @Schema(description = "å½æè¥æ¶") private BigDecimal income; @Schema(description = "彿æ¯åº") private BigDecimal expense; @Schema(description = "彿å婿¶¦") private BigDecimal profit; } @Data @Schema(description = "åºæ¶åºä»æåº¦VOï¼æ±ç¶å¾ç¨ï¼") public static class ReceivablePayableVO { @Schema(description = "æä»½ï¼æ ¼å¼ï¼yyyy-MM") private String month; @Schema(description = "åºæ¶è´¦æ¬¾éé¢") private BigDecimal receivable; @Schema(description = "åºä»è´¦æ¬¾éé¢") private BigDecimal payable; } } src/main/java/com/ruoyi/account/controller/AccountingController.java
@@ -50,8 +50,8 @@ /*****************************************è´¢å¡æ¥è¡¨******************************************************************************/ @GetMapping("/accountStatementDetailsByMonth") @Log(title = "ç»è®¡æ»åºæ¶+æ»æ¯åº+æ»æ¶å ¥ç¬æ°+æ»æ¯åºç¬æ°+åæ¶å ¥", businessType = BusinessType.OTHER) @Operation(summary = "è´¢å¡æ¥è¡¨--ç»è®¡æ»åºæ¶+æ»æ¯åº+æ»æ¶å ¥ç¬æ°+æ»æ¯åºç¬æ°+åæ¶å ¥") @Log(title = "è´¢å¡æ¥è¡¨", businessType = BusinessType.OTHER) @Operation(summary = "è´¢å¡æ¥è¡¨") public R getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) { return R.ok(accountingService.getAccountStatementDetailsByMonth(accountReportDto)); } src/main/java/com/ruoyi/account/mapper/AccountStatementMapper.java
@@ -6,6 +6,7 @@ import com.ruoyi.account.bean.dto.StatementAccountDto; import com.ruoyi.account.bean.vo.StatementAccountVo; import com.ruoyi.account.pojo.AccountStatement; import com.ruoyi.purchase.dto.VatDto; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -22,4 +23,6 @@ IPage<StatementAccountVo> listPageAccountStatement(Page page, @Param("req") StatementAccountDto statementAccountDto); IPage<VatDto> selectVatDtoPage(Page page, @Param("month") String month); } src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -8,7 +8,15 @@ import com.ruoyi.account.bean.dto.AccountReportDto; import com.ruoyi.account.bean.dto.DeviceTypeDetail; import com.ruoyi.account.bean.dto.DeviceTypeDistributionVO; import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto; import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto; import com.ruoyi.account.bean.dto.sales.SalesOutboundDto; import com.ruoyi.account.bean.dto.sales.SalesReturnDto; import com.ruoyi.account.bean.vo.AccountReportVo; import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo; import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo; import com.ruoyi.account.bean.vo.sales.SalesOutboundVo; import com.ruoyi.account.bean.vo.sales.SalesReturnVo; import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper; import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper; import com.ruoyi.account.pojo.purchase.AccountPurchasePayment; @@ -20,16 +28,22 @@ import com.ruoyi.procurementrecord.mapper.CustomStorageMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper; import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper; import com.ruoyi.procurementrecord.pojo.CustomStorage; import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut; import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; import com.ruoyi.stock.mapper.StockInRecordMapper; import com.ruoyi.stock.mapper.StockOutRecordMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Year; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -49,6 +63,10 @@ private final ProcurementRecordOutMapper procurementRecordOutMapper; private final AccountSalesCollectionMapper accountSalesCollectionMapper; private final AccountPurchasePaymentMapper accountPurchasePaymentMapper; private final StockOutRecordMapper stockOutRecordMapper; private final ReturnManagementMapper returnManagementMapper; private final StockInRecordMapper stockInRecordMapper; private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper; @Override @@ -285,20 +303,155 @@ @Override public AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) { AccountReportVo accountReportVo = new AccountReportVo(); //æ»è¥æ¶=æ¶æ¬¾åæ»éé¢ //æ»æ¶å ¥ç¬æ°=æ¶æ¬¾åæ»ç¬æ° List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(Wrappers.<AccountSalesCollection>lambdaQuery() .between(AccountSalesCollection::getCollectionDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd())); accountReportVo.setTotalIncome(accountSalesCollections.stream().map(AccountSalesCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); accountReportVo.setIncomeNumber(accountSalesCollections.size()); //æ»æ¯åº=仿¬¾åæ»éé¢ //æ»æ¯åºç¬æ°=仿¬¾åæ»ç¬æ° List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery() .between(AccountPurchasePayment::getPaymentDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd())); accountReportVo.setTotalExpense(accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); accountReportVo.setExpenseNumber(accountPurchasePayments.size()); //å婿¶¦=æ»è¥æ¶-æ»æ¯åº accountReportVo.setNetRevenue(accountReportVo.getTotalIncome().subtract(accountReportVo.getTotalExpense())); LocalDate start = accountReportDto.getEntryDateStart(); LocalDate end = accountReportDto.getEntryDateEnd(); DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // ========== 1. é¡¶é¨å¡çæ°æ® ========== // 1.1 æ»è¥æ¶ = æ¶æ¬¾åæ»éé¢ List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList( Wrappers.<AccountSalesCollection>lambdaQuery() .between(AccountSalesCollection::getCollectionDate, start, end) ); BigDecimal totalIncome = Optional.of( accountSalesCollections.stream() .map(AccountSalesCollection::getCollectionAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setTotalIncome(totalIncome); // 1.2 æ»æ¯åº = 仿¬¾åæ»éé¢ List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList( Wrappers.<AccountPurchasePayment>lambdaQuery() .between(AccountPurchasePayment::getPaymentDate, start, end) ); BigDecimal totalExpense = Optional.of( accountPurchasePayments.stream() .map(AccountPurchasePayment::getPaymentAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setTotalExpense(totalExpense); // 1.3 åºæ¶è´¦æ¬¾ = éå®åºåºéé¢å计 - éå®éè´§éé¢å计 SalesOutboundDto salesOutboundDto = new SalesOutboundDto(); salesOutboundDto.setStartDate(accountReportDto.getEntryDateStart()); salesOutboundDto.setEndDate(accountReportDto.getEntryDateEnd()); List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords(); BigDecimal salesOutAmount = Optional.of( salesOutboundVos.stream() .map(SalesOutboundVo::getOutboundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); SalesReturnDto salesReturnDto = new SalesReturnDto(); salesReturnDto.setStartDate(accountReportDto.getEntryDateStart()); salesReturnDto.setEndDate(accountReportDto.getEntryDateEnd()); List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords(); BigDecimal salesReturnAmount = Optional.of( salesReturnVos.stream() .map(SalesReturnVo::getRefundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setAccountsReceivable(salesOutAmount.subtract(salesReturnAmount)); // 1.4 åºä»è´¦æ¬¾ = éè´å ¥åºéé¢å计 - éè´éè´§éé¢å计 PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto(); purchaseInboundDto.setStartDate(accountReportDto.getEntryDateStart()); purchaseInboundDto.setEndDate(accountReportDto.getEntryDateEnd()); List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords(); BigDecimal purchaseInAmount = Optional.of( purchaseInboundVos.stream() .map(PurchaseInboundVo::getInboundAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto(); purchaseReturnDto.setStartDate(accountReportDto.getEntryDateStart()); purchaseReturnDto.setEndDate(accountReportDto.getEntryDateEnd()); List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords(); BigDecimal purchaseReturnAmount = Optional.of( purchaseReturnVos.stream() .map(PurchaseReturnVo::getTotalAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add) ).orElse(BigDecimal.ZERO); accountReportVo.setAccountsPayable(purchaseInAmount.subtract(purchaseReturnAmount)); // 1.5 å婿¶¦ = æ»è¥æ¶ - æ»æ¯åº BigDecimal netProfit = totalIncome.subtract(totalExpense); accountReportVo.setNetRevenue(netProfit); // ========== 2. æçº¿å¾ï¼æåº¦è¥æ¶/æ¯åº/å婿¶¦è¶å¿ ========== Map<String, BigDecimal> monthIncomeMap = new HashMap<>(); Map<String, BigDecimal> monthExpenseMap = new HashMap<>(); // æåº¦è¥æ¶ accountSalesCollections.forEach(item -> { String month = item.getCollectionDate().format(monthFormatter); monthIncomeMap.put(month, monthIncomeMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getCollectionAmount()).orElse(BigDecimal.ZERO))); }); // æåº¦æ¯åº accountPurchasePayments.forEach(item -> { String month = item.getPaymentDate().format(monthFormatter); monthExpenseMap.put(month, monthExpenseMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getPaymentAmount()).orElse(BigDecimal.ZERO))); }); // çæè¿ç»æä»½å表 List<String> monthList = new ArrayList<>(); LocalDate current = start.withDayOfMonth(1); while (!current.isAfter(end.withDayOfMonth(1))) { monthList.add(current.format(monthFormatter)); current = current.plusMonths(1); } // ç»è£ è¶å¿æ°æ® List<AccountReportVo.MonthlyTrendVO> trendList = new ArrayList<>(); for (String month : monthList) { BigDecimal income = monthIncomeMap.getOrDefault(month, BigDecimal.ZERO); BigDecimal expense = monthExpenseMap.getOrDefault(month, BigDecimal.ZERO); AccountReportVo.MonthlyTrendVO trend = new AccountReportVo.MonthlyTrendVO(); trend.setMonth(month); trend.setIncome(income); trend.setExpense(expense); trend.setProfit(income.subtract(expense)); trendList.add(trend); } accountReportVo.setMonthlyTrendList(trendList); // ========== 3. æ±ç¶å¾ï¼æåº¦åºæ¶/åºä»æ°æ® ========== Map<String, BigDecimal> monthReceivableMap = new HashMap<>(); Map<String, BigDecimal> monthPayableMap = new HashMap<>(); // æåº¦åºæ¶ï¼éå®åºåº-éè´§ï¼ salesOutboundVos.forEach(item -> { String month = item.getShippingDate().format(monthFormatter); monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getOutboundAmount()).orElse(BigDecimal.ZERO))); }); salesReturnVos.forEach(item -> { String month = item.getMakeTime().format(monthFormatter); monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO) .subtract(Optional.ofNullable(item.getRefundAmount()).orElse(BigDecimal.ZERO))); }); // æåº¦åºä»ï¼éè´å ¥åº-éè´§ï¼ purchaseInboundVos.forEach(item -> { String month = item.getInboundDate().format(monthFormatter); monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO) .add(Optional.ofNullable(item.getInboundAmount()).orElse(BigDecimal.ZERO))); }); purchaseReturnVos.forEach(item -> { String month = item.getPreparedAt().format(monthFormatter); monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO) .subtract(Optional.ofNullable(item.getTotalAmount()).orElse(BigDecimal.ZERO))); }); // ç»è£ åºæ¶åºä»æ°æ® List<AccountReportVo.ReceivablePayableVO> rpList = new ArrayList<>(); for (String month : monthList) { AccountReportVo.ReceivablePayableVO rp = new AccountReportVo.ReceivablePayableVO(); rp.setMonth(month); rp.setReceivable(monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)); rp.setPayable(monthPayableMap.getOrDefault(month, BigDecimal.ZERO)); rpList.add(rp); } accountReportVo.setReceivablePayableList(rpList); return accountReportVo; } } src/main/java/com/ruoyi/ai/assistant/FinancialIntentExecutor.java
@@ -45,7 +45,8 @@ if (containsAny(text, "ææ¬æ ¸ç®", "äº§åææ¬", "å·¥åºææ¬", "äººå·¥ææ¬", "ææ§", "æææè")) { return financialAgentTools.calculateIntelligentCost(memoryId, startDate, endDate, timeRange, keyword, limit); } if (containsAny(text, "婿¶¦åæ", "订å婿¶¦", "äºæè®¢å", "ä½å©æ¶¦", "æèµé±å®¢æ·", "婿¶¦ä¸é")) { if (containsAny(text, "婿¶¦åæ", "订å婿¶¦", "äºæè®¢å", "ä½å©æ¶¦", "æèµé±å®¢æ·", "åªä¸ªå®¢æ·æèµé±", "å®¢æ·æèµé±", "婿¶¦æé«å®¢æ·", "婿¶¦è´¡ç®æé«å®¢æ·", "婿¶¦ä¸é")) { return financialAgentTools.analyzeOrderProfit(memoryId, startDate, endDate, timeRange, keyword, limit); } if (containsAny(text, "åºåèµé", "åºå积å", "åæ»åºå", "èµéå ç¨", "å¨è½¬ç", "åºåå¨è½¬")) { @@ -86,6 +87,15 @@ } if ("为ä»ä¹å©æ¶¦ä¸é".equals(normalized)) { DateRange range = monthRange(); return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20); } if ("åªä¸ªå®¢æ·æèµé±".equals(normalized) || "æè¿åªä¸ªå®¢æ·æèµé±".equals(normalized) || "æ¬æåªä¸ªå®¢æ·æèµé±".equals(normalized) || "è¿30天åªä¸ªå®¢æ·æèµé±".equals(normalized) || "åªä¸ªå®¢æ·å©æ¶¦æé«".equals(normalized) || "åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«".equals(normalized)) { DateRange range = extractDateRange(text); return financialAgentTools.analyzeOrderProfit(memoryId, range.startDate(), range.endDate(), range.label(), null, 20); } return null; @@ -216,6 +226,16 @@ .replace("请", "") .replace("ä¸ä¸", "") .replace("为ä»ä¹", "") .replace("åªä¸ªå®¢æ·æèµé±", "") .replace("æè¿åªä¸ªå®¢æ·æèµé±", "") .replace("æ¬æåªä¸ªå®¢æ·æèµé±", "") .replace("è¿30天åªä¸ªå®¢æ·æèµé±", "") .replace("æèµé±å®¢æ·", "") .replace("å®¢æ·æèµé±", "") .replace("åªä¸ªå®¢æ·å©æ¶¦æé«", "") .replace("婿¶¦æé«å®¢æ·", "") .replace("åªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«", "") .replace("婿¶¦è´¡ç®æé«å®¢æ·", "") .replace("æ¬æ", "") .replace("æ¬å¨", "") .replace("æ¬å¹´", "") src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -297,19 +297,35 @@ queryWrapper.ge(QualityInspect::getCheckTime, monthStart.toString()) .le(QualityInspect::getCheckTime, monthEnd.toString()); List<QualityInspect> monthInspects = qualityStatisticsMapper.selectList(queryWrapper); // ç»è®¡æ»æ°éï¼åæ ¼æ°é + ä¸åæ ¼æ°éï¼ BigDecimal reduce = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); supplierNum = supplierNum.add(reduce); BigDecimal reduce1 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); processNum = processNum.add(reduce1); BigDecimal reduce2 = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2)) .map(QualityInspect::getQuantity) .map(inspect -> { BigDecimal qualified = inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = inspect.getUnqualifiedQuantity() != null ? inspect.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); factoryNum = factoryNum.add(reduce2); @@ -319,25 +335,22 @@ // 1. ä¾åºåæ£éªï¼ç±»å0ï¼- åæ ¼æ°é BigDecimal supplierQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(0) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(0)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setSupplierNum(supplierQualified); // 2. å·¥åºæ£éªï¼ç±»å1ï¼- åæ ¼æ°é BigDecimal processQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(1) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(1)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setProcessNum(processQualified); // 3. 工忣éªï¼ç±»å2ï¼- åæ ¼æ°é BigDecimal factoryQualified = monthInspects.stream() .filter(inspect -> inspect.getInspectType().equals(2) && "åæ ¼".equals(inspect.getCheckResult())) .map(QualityInspect::getQuantity) .filter(inspect -> inspect.getInspectType().equals(2)) .map(inspect -> inspect.getQualifiedQuantity() != null ? inspect.getQualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); item.setFactoryNum(factoryQualified); @@ -1712,11 +1725,8 @@ BigDecimal unqualifiedCount = BigDecimal.ZERO; for (QualityInspect item : list) { if ("åæ ¼".equals(item.getCheckResult())) { qualifiedCount = qualifiedCount.add(item.getQuantity()); } else { unqualifiedCount = unqualifiedCount.add(item.getQuantity()); } qualifiedCount = qualifiedCount.add(item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO); unqualifiedCount = unqualifiedCount.add(item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO); } BigDecimal totalCount = qualifiedCount.add(unqualifiedCount); @@ -1985,13 +1995,11 @@ continue; } BigDecimal quantity = item.getQuantity(); BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; if ("åæ ¼".equals(item.getCheckResult())) { dto.setQualifiedCount(dto.getQualifiedCount().add(quantity)); } else { dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity)); } dto.setQualifiedCount(dto.getQualifiedCount().add(qualifiedQty)); dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(unqualifiedQty)); } // 计ç®åæ ¼ç @@ -2032,14 +2040,12 @@ BigDecimal unqualifiedCount = BigDecimal.ZERO; for (QualityInspect item : items) { BigDecimal qty = item.getQuantity(); totalCount = totalCount.add(qty); BigDecimal qualifiedQty = item.getQualifiedQuantity() != null ? item.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualifiedQty = item.getUnqualifiedQuantity() != null ? item.getUnqualifiedQuantity() : BigDecimal.ZERO; if ("åæ ¼".equals(item.getCheckResult())) { qualifiedCount = qualifiedCount.add(qty); } else { unqualifiedCount = unqualifiedCount.add(qty); } totalCount = totalCount.add(qualifiedQty.add(unqualifiedQty)); qualifiedCount = qualifiedCount.add(qualifiedQty); unqualifiedCount = unqualifiedCount.add(unqualifiedQty); } if (totalCount.compareTo(BigDecimal.ZERO) == 0) { @@ -2168,13 +2174,17 @@ dto.setProcessNum(sumQuantity(qualityInspectList, 1)); // è¿ç¨ dto.setFactoryNum(sumQuantity(qualityInspectList, 2)); // åºå // å设 qualityInspectList æ¯ä¸ä¸ª List<QualityInspect> ç±»åçéå Map<String, List<QualityInspect>> groupedByCheckResult = qualityInspectList.stream() .collect(Collectors.groupingBy(QualityInspect::getCheckResult)); List<QualityInspect> qualityInspects = groupedByCheckResult.get("ä¸åæ ¼"); if (ObjectUtils.isNull(qualityInspects) || qualityInspects.size() == 0) { return null; // æ ¹æ® unqualifiedQuantity > 0 çéä¸åæ ¼è®°å½ List<QualityInspect> qualityInspects = qualityInspectList.stream() .filter(i -> i.getUnqualifiedQuantity() != null && i.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) .collect(Collectors.toList()); if (ObjectUtils.isEmpty(qualityInspects)) { // å³ä½¿æ²¡æä¸åæ ¼è®°å½ï¼ä¹åºè¯¥è¿åç»è®¡æ°æ®ï¼åªæ¯å¾è¡¨é¡¹ä¸ºç©º dto.setItem(new ArrayList<>()); return dto; } // 4. å¤çå¾è¡¨é¡¹ (Item) List<QualityStatisticsItem> itemList = new ArrayList<>(); @@ -2217,8 +2227,11 @@ private BigDecimal sumQuantity(List<QualityInspect> list, Integer type) { return list.stream() .filter(i -> i.getInspectType().equals(type)) .map(QualityInspect::getQuantity) .filter(Objects::nonNull) .map(i -> { BigDecimal qualified = i.getQualifiedQuantity() != null ? i.getQualifiedQuantity() : BigDecimal.ZERO; BigDecimal unqualified = i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO; return qualified.add(unqualified); }) .reduce(BigDecimal.ZERO, BigDecimal::add); } @@ -2226,11 +2239,18 @@ QualityStatisticsItem item = new QualityStatisticsItem(); item.setDate(dateLabel); item.setSupplierNum(list.stream().filter(i -> i.getInspectType() == 0).map(QualityInspect::getQuantity) // ç»è®¡æ¯ç§æ£éªç±»åçä¸åæ ¼æ°é item.setSupplierNum(list.stream() .filter(i -> i.getInspectType() == 0) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); item.setProcessNum(list.stream().filter(i -> i.getInspectType() == 1).map(QualityInspect::getQuantity) item.setProcessNum(list.stream() .filter(i -> i.getInspectType() == 1) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); item.setFactoryNum(list.stream().filter(i -> i.getInspectType() == 2).map(QualityInspect::getQuantity) item.setFactoryNum(list.stream() .filter(i -> i.getInspectType() == 2) .map(i -> i.getUnqualifiedQuantity() != null ? i.getUnqualifiedQuantity() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add)); return item; src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -120,10 +120,7 @@ List<SysRole> roles = roleService.selectRoleAll(); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll()); SysUserDeptVo sysUserDeptVo = new SysUserDeptVo(); sysUserDeptVo.setUserId(userId); List<SysUserDeptVo> sysUserDeptVos = userDeptService.userLoginFacotryList(sysUserDeptVo); ajax.put("deptIds",sysUserDeptVos.stream().map(SysUserDeptVo::getDeptId).collect(Collectors.toList())); ajax.put("deptIds", userService.selectDeptIdsByUserId(userId)); return ajax; } src/main/java/com/ruoyi/project/system/service/ISysUserService.java
@@ -217,4 +217,11 @@ * @return */ int bindUserDept(SysUser user); /** * æ ¹æ®ç¨æ·IDæ¥è¯¢ææå ³èçé¨é¨ID * @param userId * @return */ List<Long> selectDeptIdsByUserId(Long userId); } src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java
@@ -560,4 +560,11 @@ } return user.getDeptIds().length; } @Override public List<Long> selectDeptIdsByUserId(Long userId) { LambdaQueryWrapper<SysUserDept> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SysUserDept::getUserId, userId); return sysUserDeptMapper.selectList(queryWrapper).stream().map(SysUserDept::getDeptId).collect(Collectors.toList()); } } src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java
@@ -2,10 +2,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.service.ISupplierService; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.R; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.service.PurchaseReportService; import com.ruoyi.purchase.vo.PurchaseReportVo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; @@ -15,6 +18,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @Tag(name = "éè´æ¥è¡¨") @RequestMapping("/purchase/report") @@ -22,31 +27,38 @@ public class AccountingReportController { private final ISupplierService supplierService; private final PurchaseReportService purchaseReportService; @GetMapping("/list") @Log(title = "éè´æ¥è¡¨-项ç®å©æ¶¦", businessType = BusinessType.OTHER) public AjaxResult list(Page page) { return AjaxResult.success(); public R list(Page page, String customerName) { return R.ok(purchaseReportService.list(page,customerName)); } @Log(title = "éè´æ¥è¡¨-项ç®å©æ¶¦å¯¼åº", businessType = BusinessType.EXPORT) @PostMapping("/export") @Operation(summary = "éè´æ¥è¡¨-项ç®å©æ¶¦å¯¼åº") public void export(HttpServletResponse response) { public void export(HttpServletResponse response, String customerName) { List<PurchaseReportVo> list = purchaseReportService.list(new Page(1,-1),customerName).getRecords(); ExcelUtil<PurchaseReportVo> util = new ExcelUtil<>(PurchaseReportVo.class); util.exportExcel(response, list , "项ç®å©æ¶¦"); } @Log(title = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹", businessType = BusinessType.OTHER) @GetMapping("/listVat") public AjaxResult listVat(Page page,String month) { return AjaxResult.success(); public R listVat(Page page,String month) { return R.ok(purchaseReportService.listVat(page,month)); } @Log(title = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹", businessType = BusinessType.EXPORT) @PostMapping("/exportTwo") @Operation(summary = "éè´æ¥è¡¨-å¢å¼ç¨æ¯å¯¹") public void exportTwo(HttpServletResponse response) { public void exportTwo(HttpServletResponse response,String month) { List<VatDto> list = purchaseReportService.listVat(new Page(1,-1),month).getRecords(); ExcelUtil<VatDto> util = new ExcelUtil<>(VatDto.class); util.exportExcel(response, list , "å¢å¼ç¨æ¯å¯¹"); } @GetMapping("/supplierTransactions") src/main/java/com/ruoyi/purchase/dto/VatDto.java
@@ -1,27 +1,30 @@ package com.ruoyi.purchase.dto; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; @Data @Schema(name = "VatDto", description = "管ç驾驶è±--å¢å¼ç¨æ¯å¯¹åæ°") @ExcelIgnoreUnannotated public class VatDto { //æä»½ @Excel(name = "æä»½") @Schema(description = "æä»½") private String month ; //è¿é¡¹ç¨ @Excel(name = "è¿é¡¹ç¨é¢") @Excel(name = "é项ç¨é¢") @Schema(description = "é项ç¨é¢") private BigDecimal jTaxAmount; //éé¡¹ç¨ @Excel(name = "é项ç¨é¢") @Excel(name = "è¿é¡¹ç¨é¢") @Schema(description = "è¿é¡¹ç¨é¢") private BigDecimal xTaxAmount; @Excel(name = "é-è¿") @Schema(description = "é-è¿") private BigDecimal taxAmount; } src/main/java/com/ruoyi/purchase/service/PurchaseReportService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,14 @@ package com.ruoyi.purchase.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.vo.PurchaseReportVo; public interface PurchaseReportService { IPage<PurchaseReportVo> list(Page page, String customerName); IPage<VatDto> listVat(Page page, String month); } src/main/java/com/ruoyi/purchase/service/impl/PurchaseReportServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,32 @@ package com.ruoyi.purchase.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.account.mapper.AccountStatementMapper; import com.ruoyi.purchase.dto.VatDto; import com.ruoyi.purchase.service.PurchaseReportService; import com.ruoyi.purchase.vo.PurchaseReportVo; import com.ruoyi.sales.mapper.SalesLedgerMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor public class PurchaseReportServiceImpl implements PurchaseReportService { private final SalesLedgerMapper salesLedgerMapper; private final AccountStatementMapper accountStatementMapper; @Override public IPage<PurchaseReportVo> list(Page page, String customerName) { return salesLedgerMapper.selectPurchaseReportVoPage(page, customerName); } @Override public IPage<VatDto> listVat(Page page, String month) { return accountStatementMapper.selectVatDtoPage(page, month); } } src/main/java/com/ruoyi/purchase/vo/PurchaseReportVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,44 @@ package com.ruoyi.purchase.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.math.BigDecimal; @Data @Schema(name = "PurchaseReportVo", description = "管ç驾驶è±--项ç®å©æ¶¦åæ°") @ExcelIgnoreUnannotated public class PurchaseReportVo { @Schema(description = "éå®ååå·") @Excel(name = "éå®ååå·") private String customerContractNo; @Schema(description = "客æ·åç§°") @Excel(name = "客æ·åç§°") private String customerName; @Schema(description = "项ç®åç§°") @Excel(name = "项ç®åç§°") private String projectName; @Excel(name = "ååéé¢") @Schema(description = "ååéé¢") private BigDecimal contractAmount; @Excel(name = "éè´éé¢") @Schema(description = "éè´éé¢") private BigDecimal purchaseAmount; @Schema(description = "婿¶¦") @Excel(name = "婿¶¦") private BigDecimal balance; @Schema(description = "婿¶¦ç") @Excel(name = "婿¶¦ç") private BigDecimal balanceRatio; } src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.home.dto.IncomeExpenseAnalysisDto; import com.ruoyi.purchase.vo.PurchaseReportVo; import com.ruoyi.sales.dto.SalesLedgerDto; import com.ruoyi.sales.dto.SalesTrendDto; import com.ruoyi.sales.dto.StatisticsTableDto; @@ -86,4 +87,7 @@ List<SalesTrendDto> statisticsTable(@Param("statisticsTableDto")StatisticsTableDto statisticsTableDto); IPage<SalesLedgerDto> listSalesLedgerAndShipped(Page page, @Param("ew") SalesLedgerDto salesLedgerDto); IPage<PurchaseReportVo> selectPurchaseReportVoPage(Page page, @Param("customerName") String customerName); } src/main/resources/application.yml
@@ -3,7 +3,7 @@ main: allow-circular-references: true profiles: active: dev active: dev-pro langchain4j: mcp: # MCP æå¡ç«¯å°åï¼æ ¹æ®å®é é¨ç½²ç MCP æå¡è°æ´ï¼ src/main/resources/financial-agent-prompt.txt
@@ -6,6 +6,6 @@ 2. å½ä¸ææ¬ã婿¶¦ãåºåèµéãç°éæµãé¢è¦ã驾驶è±ãæ¥æ¥å¨æ¥åºæ¯æ¶ï¼ä¼å è°ç¨å¯¹åºå·¥å ·ã 3. å·¥å ·è¿å JSON æ¶ï¼ç´æ¥è¾åºåå§ JSON å符串ï¼ä¸è¦é¢å¤å 裹 Markdownï¼ä¹ä¸è¦å¨åå追å è§£éææ¬ã 4. å½ç¨æ·é®é¢ç¼ºå°æ¶é´èå´æ¶ï¼é»è®¤ä½¿ç¨å·¥å ·å ç½®å£å¾ï¼å¦è¿30å¤©ãæ¬æãè¿90天ï¼ï¼å¹¶å¨åç»å¯æéç¨æ·è¡¥å èå´ã 5. ç¨æ·é®â为ä»ä¹å©æ¶¦ä¸éââåªä¸ªè®¢åäºæââåªä¸ªå®¢æ·æèµé±ââåªä¸ªè½¦é´/å·¥åºææ¬æé«âçé®é¢æ¶ï¼ä¼å åºäºè®¢å婿¶¦ä¸å·¥åºææ¬åæå·¥å ·ä½çã 5. ç¨æ·é®â为ä»ä¹å©æ¶¦ä¸éââåªä¸ªè®¢åäºæââåªä¸ªå®¢æ·æèµé±ââåªä¸ªå®¢æ·å©æ¶¦è´¡ç®æé«ââåªä¸ªè½¦é´/å·¥åºææ¬æé«âçé®é¢æ¶ï¼ä¼å åºäºè®¢å婿¶¦ä¸å·¥åºææ¬åæå·¥å ·ä½çã 6. åçå¿ é¡»ä½¿ç¨ä¸æï¼è¥æ°æ®ä¸è¶³ä»¥å¾åºç»è®ºï¼æç¡®æåºç¼ºå°åªäºå ³é®å段æç鿡件ã 7. ç¨æ·æå°âä»å¹´/æ¬æ/ä»å¤©/æè¿/䏿/å»å¹´âçç¸å¯¹æ¶é´æ¶ï¼å¿ é¡»ä¸¥æ ¼åºäºâå½åæ¥æâæ¢ç®ï¼ç¦æ¢èªè¡å设年份ã src/main/resources/mapper/account/AccountStatementMapper.xml
@@ -40,4 +40,39 @@ </if> ORDER BY lj.statement_month DESC </select> <select id="selectVatDtoPage" resultType="com.ruoyi.purchase.dto.VatDto"> SELECT month, jTaxAmount, xTaxAmount, (jTaxAmount - xTaxAmount) AS taxAmount FROM ( SELECT month, SUM(IF(type = 'purchase', tax_price, 0)) AS xTaxAmount, SUM(IF(type = 'sales', tax_price, 0)) AS jTaxAmount FROM ( SELECT DATE_FORMAT(issue_date, '%Y-%m') AS month, tax_price, 'sales' AS type FROM account_sales_invoice WHERE status != 1 UNION ALL SELECT DATE_FORMAT(issue_date, '%Y-%m') AS month, tax_price, 'purchase' AS type FROM account_purchase_invoice WHERE status != 1 ) AS all_data GROUP BY month ) AS TT <where> <if test="month != null"> and TT.month = #{month} </if> </where> ORDER BY TT.month </select> </mapper> src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -121,5 +121,21 @@ </if> order by sl.execution_date desc </select> <select id="selectPurchaseReportVoPage" resultType="com.ruoyi.purchase.vo.PurchaseReportVo"> select sl.sales_contract_no customerContractNo, c.customer_name, sl.project_name, sl.contract_amount contractAmount, pl.contract_amount purchaseAmount, sl.contract_amount-pl.contract_amount balance, (sl.contract_amount-pl.contract_amount)/sl.contract_amount balanceRatio from sales_ledger sl left join purchase_ledger pl on sl.id = pl.sales_ledger_id left join customer c on sl.customer_id = c.id where 1=1 <if test="customerName != null and customerName != '' "> and c.customer_name like concat('%',#{customerName},'%') </if> </select> </mapper>