From f6f57ba70679a0b050031f3cdf81b5bf5d4cbd60 Mon Sep 17 00:00:00 2001 From: liding <756868258@qq.com> Date: 星期五, 11 七月 2025 15:28:37 +0800 Subject: [PATCH] 1.生产加工优化 2.销售,库存查询优化 --- main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 339 insertions(+), 0 deletions(-) diff --git a/main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java b/main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java index 46d6e5b..145cf5b 100644 --- a/main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java +++ b/main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java @@ -1,6 +1,7 @@ package com.ruoyi.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -10,6 +11,7 @@ import com.ruoyi.basic.mapper.CoalInfoMapper; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.business.dto.SalesRecordDto; +import com.ruoyi.business.dto.YearlyQueryDto; import com.ruoyi.business.entity.OfficialInventory; import com.ruoyi.business.entity.SalesRecord; import com.ruoyi.business.mapper.OfficialInventoryMapper; @@ -17,18 +19,28 @@ import com.ruoyi.business.service.SalesRecordService; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.base.BaseException; +import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.system.mapper.SysUserMapper; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; import java.time.LocalDate; +import java.time.YearMonth; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAdjusters; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.*; /** * <p> @@ -56,6 +68,32 @@ public IPage<SalesRecordDto> selectSalesRecordList(Page<SalesRecord> page, SalesRecordDto salesRecordDto) { // 1. 鍒涘缓鏌ヨ鏉′欢锛屾寜鍒涘缓鏃堕棿鍊掑簭鎺掑簭 LambdaQueryWrapper<SalesRecord> queryWrapper = new LambdaQueryWrapper<>(); + + if (StringUtils.isNotBlank(salesRecordDto.getSearchAll())) { + String searchValue = salesRecordDto.getSearchAll(); + // 1. 鍏堝皾璇曚綔涓烘棩鏈熸煡璇� + try { + LocalDate saleDate = LocalDate.parse(searchValue); + queryWrapper.eq(SalesRecord::getSaleDate, saleDate); + } catch (DateTimeParseException e) { + // 2. 濡傛灉涓嶆槸鏃ユ湡锛屽垯浣滀负鐓ょ鍚嶇О鏌ヨ + LambdaQueryWrapper<CoalInfo> coalQueryWrapper = new LambdaQueryWrapper<>(); + coalQueryWrapper.like(CoalInfo::getCoal, searchValue); + List<CoalInfo> coalInfos = coalInfoMapper.selectList(coalQueryWrapper); + if (!coalInfos.isEmpty()) { + // 鎻愬彇鎵�鏈夊尮閰嶇殑鐓ょID + List<Long> coalIds = coalInfos.stream() + .map(CoalInfo::getId) + .collect(Collectors.toList()); + // 浣跨敤in鏌ヨ鍖归厤浠绘剰涓�涓叅绉岻D + queryWrapper.in(SalesRecord::getCoalId, coalIds); + } else { + // 3. 濡傛灉鎵句笉鍒扮叅绉嶏紝鍙互杩斿洖绌虹粨鏋� + queryWrapper.eq(SalesRecord::getCoalId, "-1"); // 浣跨敤涓嶅彲鑳藉瓨鍦ㄧ殑ID + } + } + } + queryWrapper.orderByDesc(SalesRecord::getCreateTime); // 2. 鑾峰彇鍒嗛〉鐨勯攢鍞褰� @@ -218,4 +256,305 @@ // 鎵ц鎵归噺閫昏緫鍒犻櫎 return salesRecordMapper.update(null, updateWrapper); } + + @Override + public Map<String, Object> getYearlyMonthlySales(YearlyQueryDto query) { + // 1. 澶勭悊榛樿鏌ヨ锛堜笉浼犲弬鏁版椂锛� + if (query == null || query.getTimeRange() == null || query.getTimeRange().length == 0) { + query = getDefaultQuery(); + } + + // 2. 瑙f瀽鏃堕棿鑼冨洿 + LocalDate[] dateRange = parseAndValidateDateRange(query.getTimeRange()); + LocalDate startDate = dateRange[0]; + LocalDate endDate = dateRange[1]; + + // 3. 鏌ヨ鏁版嵁 + List<SalesRecord> records = salesRecordMapper.findByDateRange( + startDate.withDayOfMonth(1), + endDate.withDayOfMonth(1).with(TemporalAdjusters.lastDayOfMonth()) + ); + + // 4. 鏋勫缓鍝嶅簲 + return buildResponse(query.getTimeRange(), records, startDate, endDate); + } + + // 鑾峰彇榛樿鏌ヨ锛堝綋鍓嶅勾搴︽渶杩�6涓湀锛� + private YearlyQueryDto getDefaultQuery() { + LocalDate now = LocalDate.now(); + LocalDate startDate = now.minusMonths(5).withDayOfMonth(1); + + String[] timeRange = { + startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")), + now.format(DateTimeFormatter.ofPattern("yyyy-MM")) + }; + + YearlyQueryDto defaultQuery = new YearlyQueryDto(); + defaultQuery.setTimeRange(timeRange); + return defaultQuery; + } + + // 瑙f瀽骞堕獙璇佹棩鏈熻寖鍥� + private LocalDate[] parseAndValidateDateRange(String[] timeRange) { + if (timeRange == null || timeRange.length != 2) { + throw new IllegalArgumentException("鏃堕棿鑼冨洿鍙傛暟鏍煎紡涓嶆纭�"); + } + + LocalDate startDate = parseDate(timeRange[0]); + LocalDate endDate = parseDate(timeRange[1]); + + if (startDate.isAfter(endDate)) { + throw new IllegalArgumentException("寮�濮嬫棩鏈熶笉鑳芥櫄浜庣粨鏉熸棩鏈�"); + } + + return new LocalDate[]{startDate, endDate}; + } + + // 瑙f瀽鏃ユ湡锛堟牸寮忥細yyyy-MM锛� + private LocalDate parseDate(String dateStr) { + try { + return YearMonth.parse(dateStr).atDay(1); + } catch (DateTimeParseException e) { + throw new IllegalArgumentException("鏃ユ湡鏍煎紡涓嶆纭紝搴斾负 yyyy-MM", e); + } + } + + // 鏋勫缓鍝嶅簲鏁版嵁 + private Map<String, Object> buildResponse(String[] timeRange, + List<SalesRecord> records, + LocalDate startDate, + LocalDate endDate) { + Map<String, Object> response = new LinkedHashMap<>(); + response.put("timeRange", timeRange); + response.put("data", formatMonthlyData(records, startDate, endDate)); + response.put("isDefaultQuery", timeRange.equals(getDefaultQuery().getTimeRange())); + return response; + } + + // 鏍煎紡鍖栨湀搴︽暟鎹� + private Map<String, Integer> formatMonthlyData(List<SalesRecord> records, + LocalDate startDate, + LocalDate endDate) { + // 棰勫畾涔夋牸寮忓寲鍣� + DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); + + // 浣跨敤 TreeMap 鑷姩鎸夐敭鎺掑簭 + Map<String, Integer> monthlyData = records.stream() + .collect(Collectors.groupingBy( + r -> r.getSaleDate().format(monthFormatter), + TreeMap::new, + // 鍏抽敭淇敼锛氬鐞� saleQuantity 涓� null 鐨勬儏鍐碉紝榛樿鎸� 0 璁$畻 + Collectors.summingInt(r -> { + BigDecimal quantity = r.getSaleQuantity(); + return quantity != null ? quantity.intValue() : 0; // 涓夌洰杩愮畻绗﹀垽鏂� + }) + )); + + // 濉厖缂哄け鏈堜唤 + YearMonth start = YearMonth.from(startDate); + YearMonth end = YearMonth.from(endDate); + + for (YearMonth month = start; !month.isAfter(end); month = month.plusMonths(1)) { + String monthKey = month.format(monthFormatter); + monthlyData.putIfAbsent(monthKey, 0); + } + + return monthlyData; + } + + @Override + public Map<String, Object> selectAllInfo() { + Map<String, Object> result = new LinkedHashMap<>(); + + //钀ユ敹閲戦 + LocalDate today = LocalDate.now(); + LocalDate yesterday = today.minusDays(1); + + BigDecimal revenueAmount; + List<SalesRecord> salesRecords = salesRecordMapper.selectList(null); + revenueAmount = salesRecords.stream() + .map(SalesRecord::getTotalAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + //浠婃棩钀ユ敹 + BigDecimal todayRevenue = salesRecords.stream() + .filter(record -> today.equals(record.getSaleDate())) + .map(SalesRecord::getTotalAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + //鏄ㄦ棩钀ユ敹 + BigDecimal yesterdayRevenue = salesRecords.stream() + .filter(record -> yesterday.equals(record.getSaleDate())) + .map(SalesRecord::getTotalAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + // 璁$畻澧為暱鐧惧垎姣� + BigDecimal increases = BigDecimal.ZERO; + String trend = "+"; + + if (yesterdayRevenue.compareTo(BigDecimal.ZERO) != 0) { + increases = todayRevenue.subtract(yesterdayRevenue) + .divide(yesterdayRevenue, 4, RoundingMode.HALF_UP) + .multiply(new BigDecimal(100)); + + if (increases.compareTo(BigDecimal.ZERO) > 0) { + trend = "+"; + } else if (increases.compareTo(BigDecimal.ZERO) < 0) { + trend = "鈥�"; + } + } + + // 6. 鏍煎紡鍖栫櫨鍒嗘瘮鏄剧ず + DecimalFormat formatNo = new DecimalFormat("0.00%"); + String changeRate = formatNo.format(increases.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)); + + //渚涘簲閲� + BigDecimal saleQuantity = salesRecords.stream() + .map(SalesRecord::getSaleQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + //浠婃棩渚涘簲閲� + BigDecimal todaySaleQuantity = salesRecords.stream() + .filter(record -> today.equals(record.getSaleDate())) + .map(SalesRecord::getSaleQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + //鏄ㄦ棩渚涘簲閲� + BigDecimal yesterdaySaleQuantity = salesRecords.stream() + .filter(record -> yesterday.equals(record.getSaleDate())) + .map(SalesRecord::getSaleQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + // 璁$畻澧為暱鐧惧垎姣� + BigDecimal increasesQuantity = BigDecimal.ZERO; + String trendQuantity = "+"; + + if (yesterdaySaleQuantity.compareTo(BigDecimal.ZERO) != 0) { + increasesQuantity = todaySaleQuantity.subtract(yesterdaySaleQuantity) + .divide(yesterdaySaleQuantity, 4, RoundingMode.HALF_UP) + .multiply(new BigDecimal(100)); + + if (increasesQuantity.compareTo(BigDecimal.ZERO) > 0) { + trendQuantity = "+"; + } else if (increasesQuantity.compareTo(BigDecimal.ZERO) < 0) { + trendQuantity = "鈥�"; + } + } + + // 鏍煎紡鍖栨暟閲忕櫨鍒嗘瘮鏄剧ず + DecimalFormat formatNoQuantity = new DecimalFormat("0.00%"); + String saleQuantityRate = formatNoQuantity.format(increasesQuantity.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP)); + + //钀ユ敹鍒嗗竷 + //鑾峰彇鎵�鏈夌叅绉嶄俊鎭�(id鍜屽悕绉扮殑鏄犲皠) + Map<Long, String> coalIdToNameMap = coalInfoMapper.selectList(null).stream() + .collect(Collectors.toMap( + CoalInfo::getId, + CoalInfo::getCoal + )); + + // 3. 鎸夌叅绉岻D缁熻鎬婚噾棰� + Map<Long, BigDecimal> revenueByCoalId = salesRecords.stream() + .collect(Collectors.groupingBy( + SalesRecord::getCoalId, + Collectors.reducing( + BigDecimal.ZERO, + SalesRecord::getTotalAmount, + BigDecimal::add + ) + )); + + // 鐓ょ閿�鍞垎甯冿紙鍗曠嫭浣滀负涓�涓瓙Map锛� + Map<String, BigDecimal> revenueDistribution = new LinkedHashMap<>(); + coalIdToNameMap.forEach((id, name) -> { + BigDecimal amount = revenueByCoalId.getOrDefault(id, BigDecimal.ZERO) + .setScale(2, RoundingMode.HALF_UP); + if (amount.compareTo(BigDecimal.ZERO) > 0) { + revenueDistribution.put(name, amount); + } + }); + + //閿�鍞暟鎹� + // 鎸塩oalId鍒嗙粍骞跺悎骞舵暟閲忓拰閲戦 + Map<Long, Map<String, Object>> resultMap = new LinkedHashMap<>(); + + for (SalesRecord record : salesRecords) { + Long coalId = record.getCoalId(); + + // 灏嗘暟閲忓拰閲戦杞崲涓築igDecimal + BigDecimal quantity = record.getInventoryQuantity(); + BigDecimal amount = record.getTotalAmount(); + + if (resultMap.containsKey(coalId)) { + Map<String, Object> existing = resultMap.get(coalId); + + // 鑾峰彇鐜版湁鐨凚igDecimal鍊� + BigDecimal existingQuantity = (BigDecimal) existing.get("inventoryQuantity"); + BigDecimal existingAmount = (BigDecimal) existing.get("totalAmount"); + + // 浣跨敤BigDecimal杩涜鍔犳硶杩愮畻 + existing.put("inventoryQuantity", existingQuantity.add(quantity)); + existing.put("totalAmount", existingAmount.add(amount)); + } else { + Map<String, Object> newRecord = new HashMap<>(); + newRecord.put("coalId", coalId); + newRecord.put("inventoryQuantity", quantity); + newRecord.put("totalAmount", amount); + resultMap.put(coalId, newRecord); + } + } + + // 3. 鑾峰彇鎵�鏈夋秹鍙婄殑coalId + List<Long> coalIds = new ArrayList<>(resultMap.keySet()); + + // 4. 鎵归噺鏌ヨ鐓ょ淇℃伅骞跺~鍏呭埌缁撴灉涓� + if (!coalIds.isEmpty()) { + List<CoalInfo> coalInfos = coalInfoMapper.selectByIds(coalIds); + for (CoalInfo coalInfo : coalInfos) { + Map<String, Object> record = resultMap.get(coalInfo.getId()); + if (record != null) { + record.put("coalName", coalInfo.getCoal()); + } + } + } + + List<Map<String, Object>> results = new ArrayList<>(resultMap.values()); + + //鏈堝害鏁版嵁 + //鏌ヨ鎵�鏈夌叅绉嶄俊鎭� + List<CoalInfo> allCoalTypes = coalInfoMapper.selectList( + new QueryWrapper<CoalInfo>().orderByAsc("id") + ); + //棰勮绠楅攢閲忥細鎸塩oalId鍒嗙粍缁熻鎬婚攢閲� + Map<Long, BigDecimal> salesByCoalId = salesRecords.stream() + .collect(Collectors.groupingBy( + SalesRecord::getCoalId, + Collectors.reducing( + BigDecimal.ZERO, + SalesRecord::getSaleQuantity, + BigDecimal::add + ) + )); + + // 2. 鍒涘缓 resultMouth锛屽瓨鍌ㄧ叅绉嶅強鍏堕攢閲忥紙Map 缁撴瀯锛� + Map<String, BigDecimal> resultMouthMap = new LinkedHashMap<>(); + for (CoalInfo coal : allCoalTypes) { + resultMouthMap.put( + coal.getCoal(), // 鐓ょ鍚嶇О锛堝 "鏃犵儫鐓�"锛� + salesByCoalId.getOrDefault(coal.getId(), BigDecimal.valueOf(0)) // 閿�閲� + ); + } + + result.put("revenueAmount", revenueAmount.setScale(2, RoundingMode.HALF_UP)); + result.put("changeRate", changeRate); + result.put("trend", trend); + result.put("saleQuantity", saleQuantity); + result.put("saleQuantityRate", saleQuantityRate); + result.put("trendQuantity", trendQuantity); + result.put("revenueDistribution", revenueDistribution); + result.put("salesResults", results); + result.put("resultMouth", resultMouthMap); + + return result; + } } -- Gitblit v1.9.3