main-business/src/main/java/com/ruoyi/business/controller/OfficialInventoryController.java
@@ -3,10 +3,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.business.dto.OfficialInventoryDto; import com.ruoyi.business.dto.SalesRecordDto; import com.ruoyi.business.entity.OfficialInventory; import com.ruoyi.business.service.OfficialInventoryService; import com.ruoyi.business.vo.OfficialInventoryVo; import com.ruoyi.common.core.domain.R; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; @@ -79,4 +81,12 @@ public R<List<OfficialInventoryDto>> coalBlendingList() { return R.ok(officialInventoryService.coalBlendingList()); } /** * æ£å¼åºè®°å½è¡¨å¯¼åº */ @PostMapping("/export") public void officialInventoryExport(HttpServletResponse response, OfficialInventoryDto officialInventoryDto) { officialInventoryService.officialInventoryExport(response, officialInventoryDto); } } main-business/src/main/java/com/ruoyi/business/controller/SalesRecordController.java
@@ -2,10 +2,12 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.basic.dto.SupplyDto; import com.ruoyi.business.dto.SalesRecordDto; import com.ruoyi.business.entity.SalesRecord; import com.ruoyi.business.service.SalesRecordService; import com.ruoyi.common.core.domain.R; import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -49,4 +51,12 @@ public R remove(@RequestBody Long[] ids) { return R.ok(salesRecordService.delByIds(ids)); } /** * éå®è®°å½è¡¨å¯¼åº */ @PostMapping("/export") public void salesRecordExport(HttpServletResponse response, SalesRecordDto salesRecordDto) { salesRecordService.salesRecordExport(response, salesRecordDto); } } main-business/src/main/java/com/ruoyi/business/dto/OfficialInventoryDto.java
@@ -24,4 +24,7 @@ private List<Map<String, String>> coalValues; //åªè´¨æ¹æ¡åæ®µå¼ private List<Long> exportIds;//导åºéä¸çid } main-business/src/main/java/com/ruoyi/business/dto/SalesRecordDto.java
@@ -3,8 +3,12 @@ import com.ruoyi.business.entity.SalesRecord; import lombok.Data; import java.util.List; @Data public class SalesRecordDto extends SalesRecord { private String coal; private List<Long> exportIds;//导åºéä¸çid } main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java
@@ -76,4 +76,9 @@ */ @TableField(value = "purchase_price") private BigDecimal purchasePrice; /** * æ¯å¦èæç±» */ @TableField(value = "is_consumables") private boolean isConsumables; } main-business/src/main/java/com/ruoyi/business/entity/EquipmentUsageRecord.java
@@ -44,10 +44,10 @@ @TableField(value = "department_id") private Long departmentId; /** * 设å¤ç¶æï¼ä½¿ç¨ä¸ï¼å·²å½è¿ï¼ * 设å¤ç¶æï¼1使ç¨ä¸ï¼2å·²å½è¿ï¼ */ @TableField(value = "equipment_status") private String equipmentStatus; private Integer equipmentStatus; /** * 使ç¨å¼å§æ¶é´ */ main-business/src/main/java/com/ruoyi/business/entity/InspectionTask.java
@@ -61,4 +61,9 @@ */ @TableField(value = "frequency_type") private String frequencyType; /** * æ¶é´ç»è */ @TableField(value = "frequency_detail") private String frequencyDetail; } main-business/src/main/java/com/ruoyi/business/entity/SalesRecord.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.core.domain.MyBaseEntity; import lombok.Data; @@ -33,6 +34,7 @@ */ @TableField(value = "sale_date") @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "é宿¥æ") private LocalDate saleDate; /** * 客æ·id @@ -120,4 +122,9 @@ @TableField(value = "registration_date") @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate registrationDate; /** * æ¯å¦æ·»å è³å¾ è¡¥åº */ @TableField(value = "is_add") private boolean isAdd; } main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java
@@ -6,6 +6,7 @@ import com.ruoyi.business.entity.OfficialInventory; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.business.vo.OfficialInventoryVo; import jakarta.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.List; @@ -34,4 +35,6 @@ Map<String, BigDecimal> selectOfficialAllInfo(); List<OfficialInventoryDto> coalBlendingList(); void officialInventoryExport(HttpServletResponse response, OfficialInventoryDto officialInventoryDto); } main-business/src/main/java/com/ruoyi/business/service/SalesRecordService.java
@@ -6,6 +6,7 @@ import com.ruoyi.business.dto.SalesRecordDto; import com.ruoyi.business.dto.YearlyQueryDto; import com.ruoyi.business.entity.SalesRecord; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import java.util.Map; @@ -29,4 +30,6 @@ Map<String, Object> selectAllInfo(); Map<String, Object> getYearlyMonthlySales(@Valid YearlyQueryDto query); void salesRecordExport(HttpServletResponse response, SalesRecordDto salesRecordDto); } main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java
@@ -70,7 +70,8 @@ // æ¥è¯¢è¯¥è®¾å¤çä½¿ç¨æ»éï¼usageQuantityï¼ LambdaQueryWrapper<EquipmentUsageRecord> usageQueryWrapper = new LambdaQueryWrapper<>(); usageQueryWrapper.eq(EquipmentUsageRecord::getEquipmentId, entity.getId()); usageQueryWrapper.eq(EquipmentUsageRecord::getEquipmentId, entity.getId()) .eq(EquipmentUsageRecord::getEquipmentStatus, 1); // è®¡ç®æ»ä½¿ç¨é Integer totalUsage = equipmentUsageRecordMapper.selectList(usageQueryWrapper).stream() main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentUsageRecordServiceImpl.java
@@ -85,7 +85,6 @@ } return dto; }).toList(); dtoPage.setRecords(dtoRecords); return dtoPage; } @@ -125,46 +124,54 @@ // 设置使ç¨å¼å§æ¶é´ä¸ºå½åæ¶é´ equipmentUsageRecord.setUsageStartTime(LocalDate.now()); // å¦æç¶æä¸º1(å·²å½è¿)ï¼åè®¾ç½®ç»ææ¶é´ if ("1".equals(equipmentUsageRecordDto.getEquipmentStatus())) { equipmentUsageRecord.setUsageEndTime(LocalDate.now()); } return equipmentUsageRecordMapper.insert(equipmentUsageRecord); } // æ´æ°è®°å½é»è¾ else { // 1. æ¥è¯¢åé¢ç¨è®°å½ } else { // ç¼è¾è®°å½é»è¾ EquipmentUsageRecord originalRecord = equipmentUsageRecordMapper.selectById(equipmentUsageRecordDto.getId()); if (originalRecord == null) { throw new RuntimeException("é¢ç¨è®°å½ä¸åå¨"); } // 2. 计ç®åºåååéï¼æ°æ°é - æ§æ°éï¼ int quantityDelta = newUsageQuantity - originalRecord.getUsageQuantity(); // å¤çå½è¿é»è¾ if (equipmentUsageRecordDto.getEquipmentStatus() == 2) { // æ£æ¥å½è¿æ°éæ¯å¦åæ³ if (newUsageQuantity > originalRecord.getUsageQuantity()) { throw new RuntimeException("å½è¿æ°éä¸è½è¶ è¿åé¢ç¨æ°é"); } if (quantityDelta != 0) { // 3. æ£æ¥è°æ´ååºåæ¯å¦å è¶³ int newInventory = equipment.getQuantity() - quantityDelta; // 计ç®å®é å½è¿æ°éï¼åé¢ç¨æ°é - æ°é¢ç¨æ°éï¼ int returnedQuantity = originalRecord.getUsageQuantity() - newUsageQuantity; // æ¢å¤é¨ååºå equipment.setQuantity(equipment.getQuantity() + returnedQuantity); equipmentManagementMapper.updateById(equipment); // å¦æå ¨é¨å½è¿ï¼è®¾ç½®å½è¿æ¶é´ if (newUsageQuantity == 0) { equipmentUsageRecord.setUsageEndTime(LocalDate.now()); } return equipmentUsageRecordMapper.updateById(equipmentUsageRecord); } // å¤çæ®éç¼è¾é»è¾ï¼éå½è¿ç¶æï¼ if (!newUsageQuantity.equals(originalRecord.getUsageQuantity())) { // 计ç®åºåååéï¼æ§æ°é - æ°æ°éï¼ int quantityDelta = originalRecord.getUsageQuantity() - newUsageQuantity; // æ£æ¥è°æ´ååºåæ¯å¦å è¶³ int newInventory = equipment.getQuantity() + quantityDelta; if (newInventory < 0) { throw new RuntimeException("åºåä¸è¶³ï¼è°æ´ååºåå°ä¸ºï¼" + newInventory); } // 4. è°æ´åºå // è°æ´åºå equipment.setQuantity(newInventory); if (equipmentManagementMapper.updateById(equipment) == 0) { throw new RuntimeException("åºåæ´æ°å¤±è´¥ï¼å¯è½å·²è¢«å ¶ä»æä½ä¿®æ¹"); } } // 5. å¦æç¶æå为1(å·²å½è¿)ï¼åè®¾ç½®ç»ææ¶é´ä¸ºå½åæ¶é´ if ("1".equals(equipmentUsageRecordDto.getEquipmentStatus()) && (originalRecord.getEquipmentStatus() == null || !"1".equals(originalRecord.getEquipmentStatus()))) { equipmentUsageRecord.setUsageEndTime(LocalDate.now()); } // 6. æ´æ°é¢ç¨è®°å½ // æ´æ°é¢ç¨è®°å½ return equipmentUsageRecordMapper.updateById(equipmentUsageRecord); } } main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java
@@ -15,16 +15,24 @@ import com.ruoyi.basic.mapper.CoalValueMapper; import com.ruoyi.basic.mapper.SupplyMapper; import com.ruoyi.business.dto.OfficialInventoryDto; import com.ruoyi.business.dto.SalesRecordDto; import com.ruoyi.business.entity.OfficialInventory; import com.ruoyi.business.entity.SalesRecord; import com.ruoyi.business.mapper.OfficialInventoryMapper; import com.ruoyi.business.service.OfficialInventoryService; import com.ruoyi.business.utils.DynamicExcelUtil; import com.ruoyi.business.vo.OfficialInventoryExportVo; import com.ruoyi.business.vo.OfficialInventoryVo; import com.ruoyi.business.vo.SalesRecordExportVo; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.mapper.SysUserMapper; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -43,6 +51,7 @@ * @since 2025-06-04 */ @Service @Slf4j @RequiredArgsConstructor public class OfficialInventoryServiceImpl extends ServiceImpl<OfficialInventoryMapper, OfficialInventory> implements OfficialInventoryService { @@ -355,6 +364,160 @@ } @Override public void officialInventoryExport(HttpServletResponse response, OfficialInventoryDto officialInventoryDto) { try { // è·åç ¤è´¨åæ®µé ç½® List<CoalField> allCoalFields = coalFieldMapper.selectList(null); List<String> dynamicHeaders = allCoalFields.stream() .map(CoalField::getFieldName) .collect(Collectors.toList()); // è·åæ°æ® List<OfficialInventory> list = officialInventoryDto.getExportIds() != null && !officialInventoryDto.getExportIds().isEmpty() ? officialInventoryMapper.selectByIds(officialInventoryDto.getExportIds()) : officialInventoryMapper.selectList(null); // 转æ¢ä¸ºå¯¼åºVO List<OfficialInventoryExportVo> exportData = convertToExportVo(list, allCoalFields); // 使ç¨å¢å¼ºçExcelå·¥å ·å¯¼åº DynamicExcelUtil<OfficialInventoryExportVo> util = new DynamicExcelUtil<>(OfficialInventoryExportVo.class, dynamicHeaders); // 导åºExcel util.exportExcel(response, exportData, "åºåæ°æ®"); } catch (Exception e) { log.error("åºå导åºå¤±è´¥", e); // å¯ä»¥èèè¿åæ´å好çé误信æ¯ç»å端 throw new RuntimeException("导åºå¤±è´¥: " + e.getMessage()); } } private List<OfficialInventoryExportVo> convertToExportVo(List<OfficialInventory> list, List<CoalField> coalFields) { if (CollectionUtils.isEmpty(list)) { return Collections.emptyList(); } // æ¶éææéè¦æ¥è¯¢çID Set<Long> coalIds = list.stream() .map(OfficialInventory::getCoalId) .filter(Objects::nonNull) .collect(Collectors.toSet()); Set<Long> supplierIds = list.stream() .map(OfficialInventory::getSupplierId) .filter(Objects::nonNull) .collect(Collectors.toSet()); Set<Long> registrantIds = list.stream() .map(OfficialInventory::getRegistrantId) .filter(Objects::nonNull) .collect(Collectors.toSet()); Set<Long> planIds = list.stream() .map(OfficialInventory::getCoalPlanId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // æ¹éæ¥è¯¢å ³èæ°æ® Map<Long, CoalInfo> coalInfoMap = getCoalInfoMap(coalIds); Map<Long, Supply> supplyMap = getSupplyMap(supplierIds); Map<Long, SysUser> userMap = getUserMap(registrantIds); Map<Long, List<CoalValue>> coalValuesMap = getCoalValuesMap(planIds); // æå»ºå段IDå°å段åç§°çæ å°ï¼æé«æ¥æ¾æç Map<String, String> fieldIdToNameMap = coalFields.stream() .collect(Collectors.toMap(CoalField::getFields, CoalField::getFieldName)); // è½¬æ¢æ°æ® return list.stream().map(record -> { OfficialInventoryExportVo vo = new OfficialInventoryExportVo(); vo.initDynamicFields(); // åå§å // 设置åºç¡å±æ§ BeanUtils.copyProperties(record, vo); // è®¾ç½®å ³èä¿¡æ¯ setCoalInfo(vo, record.getCoalId(), coalInfoMap); setSupplierInfo(vo, record.getSupplierId(), supplyMap); setUserMapInfo(vo, record.getRegistrantId(), userMap); // 卿忮µå¤ç if (record.getCoalPlanId() != null) { List<CoalValue> values = coalValuesMap.getOrDefault(record.getCoalPlanId(), Collections.emptyList()); setDynamicFields(vo, values, fieldIdToNameMap); } return vo; }).collect(Collectors.toList()); } private void setCoalInfo(OfficialInventoryExportVo vo, Long coalId, Map<Long, CoalInfo> coalInfoMap) { if (coalId != null && coalInfoMap.containsKey(coalId)) { vo.setCoal(coalInfoMap.get(coalId).getCoal()); } } private void setSupplierInfo(OfficialInventoryExportVo vo, Long supplierId, Map<Long, Supply> supplyMap) { if (supplierId != null && supplyMap.containsKey(supplierId)) { vo.setSupplierName(supplyMap.get(supplierId).getSupplierName()); } } private void setUserMapInfo(OfficialInventoryExportVo vo, Long registrantId, Map<Long, SysUser> userMap) { if (registrantId != null && userMap.containsKey(registrantId)) { vo.setRegistrant(userMap.get(registrantId).getNickName()); } } private void setDynamicFields(OfficialInventoryExportVo vo, List<CoalValue> values, Map<String, String> fieldIdToNameMap) { for (CoalValue value : values) { String fieldName = fieldIdToNameMap.get(value.getFields()); if (fieldName != null) { vo.getCoalQualityProperties().put(fieldName, value.getCoalValue()); } } } private Map<Long, List<CoalValue>> getCoalValuesMap(Set<Long> planIds) { if (CollectionUtils.isEmpty(planIds)) { return Collections.emptyMap(); } List<CoalValue> allValues = coalValueMapper.selectList( new LambdaQueryWrapper<CoalValue>() .in(CoalValue::getPlanId, planIds)); return allValues.stream() .collect(Collectors.groupingBy(CoalValue::getPlanId)); } private Map<Long, CoalInfo> getCoalInfoMap(Set<Long> coalIds) { if (CollectionUtils.isEmpty(coalIds)) { return Collections.emptyMap(); } return coalInfoMapper.selectByIds(coalIds).stream() .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); } private Map<Long, Supply> getSupplyMap(Set<Long> supplierIds) { if (CollectionUtils.isEmpty(supplierIds)) { return Collections.emptyMap(); } return supplyMapper.selectByIds(supplierIds).stream() .collect(Collectors.toMap(Supply::getId, Function.identity())); } private Map<Long, SysUser> getUserMap(Set<Long> registrantIds) { if (CollectionUtils.isEmpty(registrantIds)) { return Collections.emptyMap(); } return sysUserMapper.selectBatchIds(registrantIds).stream() .collect(Collectors.toMap(SysUser::getUserId, Function.identity())); } @Override public List<OfficialInventoryDto> coalBlendingList() { // 1. æ¥è¯¢åºç¡åºåæ°æ® List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null); @@ -369,16 +532,33 @@ planIds.add(inventory.getCoalPlanId()); }); // 3. æ¹éæ¥è¯¢å ³èæ°æ® Map<Long, CoalInfo> coalInfoMap = coalInfoMapper.selectByIds(coalIds).stream() .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); Map<Long, CoalInfo> coalInfoMap; if (!coalIds.isEmpty()) { coalInfoMap = coalInfoMapper.selectByIds(coalIds).stream() .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); } else { coalInfoMap = new HashMap<>(); } Map<Long, Supply> supplyMap = supplyMapper.selectByIds(supplierIds).stream() .collect(Collectors.toMap(Supply::getId, Function.identity())); Map<Long, Supply> supplyMap; if (!supplierIds.isEmpty()) { supplyMap = supplyMapper.selectByIds(supplierIds).stream() .collect(Collectors.toMap(Supply::getId, Function.identity())); } else { supplyMap = new HashMap<>(); log.warn("supplierIds 为空ï¼è·³è¿æ¥è¯¢ Supply"); } Map<Long, List<CoalValue>> coalValuesMap = coalValueMapper.selectList( new LambdaQueryWrapper<CoalValue>().in(CoalValue::getPlanId, planIds)) .stream() .collect(Collectors.groupingBy(CoalValue::getPlanId)); Map<Long, List<CoalValue>> coalValuesMap; if (!planIds.isEmpty()) { coalValuesMap = coalValueMapper.selectList( new LambdaQueryWrapper<CoalValue>().in(CoalValue::getPlanId, planIds)) .stream() .collect(Collectors.groupingBy(CoalValue::getPlanId)); } else { coalValuesMap = new HashMap<>(); log.warn("planIds 为空ï¼è·³è¿æ¥è¯¢ CoalValue"); } // 4. ç»è£ DTO return officialInventories.stream() .map(inventory -> { main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java
@@ -4,10 +4,12 @@ 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.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.entity.CoalInfo; import com.ruoyi.basic.entity.Customer; import com.ruoyi.basic.entity.Supply; import com.ruoyi.basic.mapper.CoalInfoMapper; import com.ruoyi.basic.mapper.CustomerMapper; import com.ruoyi.business.dto.SalesRecordDto; @@ -17,12 +19,16 @@ import com.ruoyi.business.mapper.OfficialInventoryMapper; import com.ruoyi.business.mapper.SalesRecordMapper; import com.ruoyi.business.service.SalesRecordService; import com.ruoyi.business.vo.SalesRecordExportVo; 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.common.utils.poi.ExcelUtil; import com.ruoyi.system.mapper.SysUserMapper; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -51,6 +57,7 @@ * @since 2025-06-11 */ @Service @Slf4j @RequiredArgsConstructor public class SalesRecordServiceImpl extends ServiceImpl<SalesRecordMapper, SalesRecord> implements SalesRecordService { @@ -155,7 +162,10 @@ throw new BaseException("é宿°éä¸è½å¤§äºåºåæ°é"); } officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(salesRecordDto.getSaleQuantity())); officialInventory.setPendingReplenishment(salesRecordDto.getSaleQuantity()); if (salesRecordDto.isAdd()){ officialInventory.setPendingReplenishment(salesRecordDto.getSaleQuantity()); } officialInventoryMapper.updateById(officialInventory); // æå»ºéå®è®°å½å®ä½ @@ -193,7 +203,7 @@ if (registrant == null) { throw new BaseException("ç»è®°äººä¿¡æ¯ä¸åå¨"); } record.setRegistrant(registrant.getUserName()); record.setRegistrant(registrant.getNickName()); // 设置客æ·ä¿¡æ¯ Customer customer = customerMapper.selectById(dto.getCustomerId()); @@ -255,6 +265,59 @@ } @Override public void salesRecordExport(HttpServletResponse response, SalesRecordDto salesRecordDto) { List<Long> ids = salesRecordDto.getExportIds(); List<SalesRecord> list; if (ids != null && !ids.isEmpty()) { list = salesRecordMapper.selectByIds(ids); } else { list = salesRecordMapper.selectList(null); } List<SalesRecordExportVo> exportData = convertToExportVo(list); ExcelUtil<SalesRecordExportVo> util = new ExcelUtil<>(SalesRecordExportVo.class); util.exportExcel(response, exportData, "éå®åºåºæ°æ®"); } private List<SalesRecordExportVo> convertToExportVo(List<SalesRecord> list) { // 1. æåæ¶éææéè¦æ¥è¯¢çcoalIdï¼é¿å N+1æ¥è¯¢é®é¢ Set<Long> coalIds = list.stream() .filter(Objects::nonNull) .map(SalesRecord::getCoalId) .filter(Objects::nonNull) .collect(Collectors.toSet()); // 2. æ¹éæ¥è¯¢coalInfoæ°æ® Map<Long, CoalInfo> coalInfoMap = CollectionUtils.isEmpty(coalIds) ? Collections.emptyMap() : coalInfoMapper.selectByIds(coalIds).stream() .filter(Objects::nonNull) .collect(Collectors.toMap(CoalInfo::getId, Function.identity())); // 3. è½¬æ¢æ°æ® return list.stream() .filter(Objects::nonNull) .map(record -> { try { SalesRecordExportVo vo = new SalesRecordExportVo(); // æ·è´åºç¡å±æ§ BeanUtils.copyProperties(record, vo); // è®¾ç½®å ³èçcoalä¿¡æ¯ Optional.ofNullable(record.getCoalId()) .map(coalInfoMap::get) .ifPresent(coalInfo -> vo.setCoal(coalInfo.getCoal())); return vo; } catch (Exception e) { log.error("转æ¢éå®è®°å½VOå¼å¸¸ï¼è®°å½ID: {}", record.getId(), e); return null; } }) .filter(Objects::nonNull) .collect(Collectors.toList()); } @Override public Map<String, Object> getYearlyMonthlySales(YearlyQueryDto query) { // 1. å¤çé»è®¤æ¥è¯¢ï¼ä¸ä¼ åæ°æ¶ï¼ if (query == null || query.getTimeRange() == null || query.getTimeRange().length == 0) { main-business/src/main/java/com/ruoyi/business/task/TimingTaskJob.java
@@ -60,6 +60,7 @@ inspectionTask.setRemarks("èªå¨çæèªå®æ¶ä»»å¡ID: " + timingTask.getId()); inspectionTask.setRegistrantId(timingTask.getRegistrantId()); inspectionTask.setFrequencyType(timingTask.getFrequencyType()); inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); return inspectionTask; } main-business/src/main/java/com/ruoyi/business/utils/DynamicExcelUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,200 @@ package com.ruoyi.business.utils; import com.ruoyi.business.vo.OfficialInventoryExportVo; import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import java.lang.reflect.Field; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Slf4j public class DynamicExcelUtil<T> extends ExcelUtil<T> { private final List<String> dynamicHeaders; private final List<Field> fields; public DynamicExcelUtil(Class<T> clazz, List<String> dynamicHeaders) { super(clazz); this.dynamicHeaders = dynamicHeaders; this.fields = getAllFields(clazz); } private List<Field> getAllFields(Class<?> clazz) { List<Field> fields = new ArrayList<>(); Class<?> currentClass = clazz; while (currentClass != null) { fields.addAll(Arrays.asList(currentClass.getDeclaredFields())); currentClass = currentClass.getSuperclass(); } return fields; } @Override public void exportExcel(HttpServletResponse response, List<T> list, String sheetName) { try { String validSheetName = StringUtils.isBlank(sheetName) ? "Sheet1" : sheetName; // Create workbook directly instead of using parent's createWorkbook Workbook workbook = new SXSSFWorkbook(); Sheet sheet = workbook.createSheet(validSheetName); // Create styles createCustomStyles(workbook); // Create dynamic header createDynamicHeader(sheet, workbook); // Fill data fillDynamicData(sheet, list); // Set response response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(validSheetName + ".xlsx", "UTF-8")); workbook.write(response.getOutputStream()); } catch (Exception e) { log.error("导åºExcel失败", e); throw new RuntimeException("导åºExcel失败: " + e.getMessage(), e); } } private void createCustomStyles(Workbook workbook) { // Create basic styles similar to parent class if needed CellStyle headerStyle = workbook.createCellStyle(); Font headerFont = workbook.createFont(); headerFont.setBold(true); headerStyle.setFont(headerFont); headerStyle.setAlignment(HorizontalAlignment.CENTER); headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); } /** * åå»ºå¨æè¡¨å¤´ï¼ç¶è¡¨å¤´"ç ¤è´¨" + åè¡¨å¤´ï¼ */ private void createDynamicHeader(Sheet sheet, Workbook workbook) { // 主表头ï¼ç¬¬1è¡ï¼åå表头ï¼ç¬¬2è¡ï¼ Row mainHeaderRow = sheet.createRow(0); Row subHeaderRow = sheet.createRow(1); // åå»ºè¡¨å¤´æ ·å¼ï¼å± ä¸ + å ç²ï¼ CellStyle headerStyle = workbook.createCellStyle(); Font headerFont = workbook.createFont(); headerFont.setBold(true); headerStyle.setFont(headerFont); headerStyle.setAlignment(HorizontalAlignment.CENTER); headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); int colIndex = 0; // éåææåæ®µï¼åºå®å段 + 卿忮µï¼ for (Field field : fields) { Excel excel = field.getAnnotation(Excel.class); if (excel != null) { // 1. å¦ææ¯ "ç ¤è´¨" åæ®µï¼è·³è¿ï¼åé¢åç¬å¤çï¼ if (excel.name().equals("ç ¤è´¨")) { continue; } // 2. å¤çæ®éåæ®µï¼é "ç ¤è´¨" çåï¼ // 2.1 å¨ä¸»è¡¨å¤´ï¼ç¬¬1è¡ï¼è®¾ç½®å段å Cell mainHeaderCell = mainHeaderRow.createCell(colIndex); mainHeaderCell.setCellValue(excel.name()); mainHeaderCell.setCellStyle(headerStyle); // 2.2 å¨å表头ï¼ç¬¬2è¡ï¼ç空ï¼ä½åå¹¶åå æ ¼ä½¿å ¶å æ®ä¸¤è¡é«åº¦ Cell subHeaderCell = subHeaderRow.createCell(colIndex); subHeaderCell.setCellStyle(headerStyle); // ä¿ææ ·å¼ä¸è´ // 2.3 åå¹¶å½ååç第1è¡å第2è¡ï¼åç´åå¹¶ï¼ sheet.addMergedRegion(new CellRangeAddress( 0, 1, // ä»ç¬¬1è¡å°ç¬¬2è¡ colIndex, colIndex // å½åå )); colIndex++; // ç§»å¨å°ä¸ä¸å } } // 3. å¤ç卿忮µï¼"ç ¤è´¨" ä¸çåè¡¨å¤´ï¼ if (!dynamicHeaders.isEmpty()) { // 3.1 å¨ä¸»è¡¨å¤´ï¼ç¬¬1è¡ï¼è®¾ç½® "ç ¤è´¨" 大æ é¢ï¼æ¨ªååå¹¶ï¼ Cell coalHeaderCell = mainHeaderRow.createCell(colIndex); coalHeaderCell.setCellValue("ç ¤è´¨"); coalHeaderCell.setCellStyle(headerStyle); // 横ååå¹¶ï¼ç¬¬1è¡ï¼è·¨è¶å¤åï¼ sheet.addMergedRegion(new CellRangeAddress( 0, 0, // ä» ç¬¬1è¡ colIndex, colIndex + dynamicHeaders.size() - 1 // è·¨è¶å¤å )); // 3.2 å¨å表头ï¼ç¬¬2è¡ï¼è®¾ç½®å¨æå段ï¼å¦ "ç°å"ã"ç¡«å"ï¼ for (int i = 0; i < dynamicHeaders.size(); i++) { Cell subCell = subHeaderRow.createCell(colIndex + i); subCell.setCellValue(dynamicHeaders.get(i)); subCell.setCellStyle(headerStyle); } } } /** * å¡«å æ°æ®ï¼åºå®å段 + 卿忮µï¼ */ private void fillDynamicData(Sheet sheet, List<T> list) { int rowIndex = 2; // Data starts from row 3 CellStyle dataStyle = sheet.getWorkbook().createCellStyle(); dataStyle.setAlignment(HorizontalAlignment.CENTER); for (T item : list) { Row row = sheet.createRow(rowIndex++); int colIndex = 0; // Fill fixed fields for (Field field : fields) { Excel excel = field.getAnnotation(Excel.class); if (excel != null && !excel.name().equals("ç ¤è´¨")) { try { field.setAccessible(true); Object value = field.get(item); Cell cell = row.createCell(colIndex++); cell.setCellStyle(dataStyle); setCellValue(cell, value); } catch (Exception e) { log.error("å¡«å åºå®å段失败", e); row.createCell(colIndex++).setCellValue("-"); } } } // Fill dynamic fields if (item instanceof OfficialInventoryExportVo vo) { for (String header : dynamicHeaders) { Cell cell = row.createCell(colIndex++); cell.setCellStyle(dataStyle); cell.setCellValue(vo.getDynamicProperty(header)); } } } } /** * 设置åå æ ¼å¼ */ private void setCellValue(Cell cell, Object value) { if (value == null) { cell.setCellValue("-"); } else if (value instanceof Number) { cell.setCellValue(((Number) value).doubleValue()); } else { cell.setCellValue(value.toString()); } } } main-business/src/main/java/com/ruoyi/business/vo/OfficialInventoryExportVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,94 @@ package com.ruoyi.business.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.util.HashMap; import java.util.Map; @Data public class OfficialInventoryExportVo { /** * ä¾è´§å */ @Excel(name = "ä¾è´§å") private String supplierName; /** * ç ¤ç§ */ @Excel(name = "ç ¤ç§") private String coal; /** * åä½ */ @Excel(name = "åä½") private String unit; /** * åºåæ°é */ @Excel(name = "åºåæ°é") private BigDecimal inventoryQuantity; /** * åä»·ï¼å«ç¨ï¼ */ @Excel(name = "åä»·ï¼å«ç¨ï¼") private BigDecimal priceIncludingTax; /** * æ»ä»·ï¼å«ç¨ï¼ */ @Excel(name = "æ»ä»·ï¼å«ç¨ï¼") private BigDecimal totalPriceIncludingTax; /** * ä¸å«ç¨åä»· */ @Excel(name = "ä¸å«ç¨åä»·") private BigDecimal priceExcludingTax; /** * ä¸å«ç¨æ»ä»· */ @Excel(name = "ä¸å«ç¨æ»ä»·") private BigDecimal totalPriceExcludingTax; /** * å¾ è¡¥åº */ @Excel(name = "å¾ è¡¥åº") private BigDecimal pendingReplenishment; /** * ç»è®°äºº */ @Excel(name = "ç»è®°äºº") private String registrant; /** * ç»è®°æ¥æ */ @Excel(name = "ç»è®°æ¥æ") @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate registrationDate; /** * å¨æç ¤è´¨å±æ§ï¼å卿æç ¤è´¨åè¡¨å¤´æ°æ®ï¼ */ // 卿忮µå®¹å¨ï¼ä¸åä¸å¯¼åºï¼ private transient Map<String, String> coalQualityProperties; // 卿忮µè®¿é®æ¹æ³ public String getDynamicProperty(String fieldName) { return coalQualityProperties != null ? coalQualityProperties.getOrDefault(fieldName, "-") : "-"; } // åå§åæ¹æ³ï¼å¨convertToExportVoä¸è°ç¨ï¼ public void initDynamicFields() { // ç¡®ä¿mapä¸ä¸ºnull if (this.coalQualityProperties == null) { this.coalQualityProperties = new HashMap<>(); } } } main-business/src/main/java/com/ruoyi/business/vo/SalesRecordExportVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,94 @@ package com.ruoyi.business.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; @Data public class SalesRecordExportVo { /** * é宿¥æ */ @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "é宿¥æ") private LocalDate saleDate; /** * å®¢æ· */ @Excel(name = "客æ·") private String customer; /** * ç ¤ç§ */ @Excel(name = "ç ¤ç§") private String coal; /** * åä½ */ @Excel(name = "åä½") private String unit; /** * åä»·ï¼å«ç¨ï¼ */ @Excel(name = "åä»·ï¼å«ç¨ï¼") private BigDecimal priceIncludingTax; /** * åºåæ°é */ @Excel(name = "åºåæ°é") private BigDecimal inventoryQuantity; /** * é宿°é */ @Excel(name = "é宿°é") private BigDecimal saleQuantity; /** * éå®åä»· (å«ç¨) */ @Excel(name = "éå®åä»· (å«ç¨)") private BigDecimal salePrice; /** * é宿»ä»· (å«ç¨) */ @Excel(name = "é宿»ä»· (å«ç¨)") private BigDecimal totalAmount; /** * è´éç ¤ç¨ç13% */ @Excel(name = "è´éç ¤ç¨ç (13%)") private String taxCoal; /** * è¿è¾ç¨ç9% */ @Excel(name = "è¿è¾ç¨ç (9%)") private String taxTrans; /** * æ¯å©æ¶¦ */ @Excel(name = "æ¯å©æ¶¦") private BigDecimal grossProfit; /** * å婿¶¦ */ @Excel(name = "å婿¶¦") private BigDecimal netProfit; /** * è¿è´¹ */ @Excel(name = "è¿è´¹") private BigDecimal freight; /** * ç»è®°äºº */ @Excel(name = "ç»è®°äºº") private String registrant; /** * ç»è®°æ¥æ */ @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "ç»è®°æ¥æ") private LocalDate registrationDate; } main-business/src/main/resources/db/migration/postgresql/V20250611160300__create_table_sales_record.sql
@@ -20,6 +20,7 @@ registrant_id BIGINT, -- ç»è®°äººid registrant VARCHAR(255) , -- ç»è®°äºº registration_date DATE , -- ç»è®°æ¥æ is_add BOOLEAN NOT NULL DEFAULT FALSE, -- æ¯å¦æ·»å è³å¾ è¡¥åº create_time TIMESTAMP WITHOUT TIME ZONE, -- ä¸ä¼ æ¶é´ï¼é»è®¤å½åæ¶é´ update_time TIMESTAMP WITHOUT TIME ZONE, -- æåæ´æ°æ¶é´ï¼é»è®¤å½åæ¶é´ @@ -50,6 +51,7 @@ COMMENT ON COLUMN sales_record.registrant IS 'ç»è®°äºº'; COMMENT ON COLUMN sales_record.registrant_id IS 'ç»è®°äººid'; COMMENT ON COLUMN sales_record.registration_date IS 'ç»è®°æ¥æ'; COMMENT ON COLUMN sales_record.is_add IS 'æ¯å¦æ·»å è³å¾ è¡¥åº'; COMMENT ON COLUMN sales_record.deleted IS '软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤'; COMMENT ON COLUMN sales_record.create_by IS 'å建该记å½çç¨æ·'; main-business/src/main/resources/db/migration/postgresql/V20250614134700__create_table_inspection_task.sql
@@ -10,6 +10,7 @@ registrant VARCHAR(100), -- ç»è®°äººå frequency_type VARCHAR(100), -- 颿¬¡ inspection_location VARCHAR(255), -- å·¡æ£å°ç¹è¯¦ç»æè¿° frequency_detail VARCHAR(255), -- æ¶é´ç»è deleted INT NOT NULL DEFAULT 0, -- 软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤ create_by VARCHAR(255), -- åå»ºäººç¨æ·å @@ -36,6 +37,8 @@ ON COLUMN inspection_task.frequency_type IS '颿¬¡'; COMMENT ON COLUMN inspection_task.inspection_location IS 'å·¡æ£å°ç¹è¯¦ç»æè¿°'; COMMENT ON COLUMN inspection_task.frequency_detail IS 'æ¶é´ç»è'; COMMENT ON COLUMN inspection_task.deleted IS '软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤'; main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql
@@ -13,6 +13,7 @@ storage_location VARCHAR(100) NOT NULL, -- åæ¾ä½ç½® purchase_date DATE, -- éè´æ¥æ purchase_price DECIMAL(10, 2), -- éè´ä»·æ ¼ is_consumables BOOLEAN NOT NULL DEFAULT FALSE, -- æ¯å¦èæç±» deleted INT NOT NULL DEFAULT 0, -- 软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤ create_by VARCHAR(255), -- åå»ºäººç¨æ·å @@ -46,6 +47,8 @@ ON COLUMN equipment_management.purchase_date IS ' éè´æ¥æ '; COMMENT ON COLUMN equipment_management.purchase_price IS ' éè´ä»·æ ¼ '; COMMENT ON COLUMN equipment_management.is_consumables IS ' æ¯å¦èæç±» '; COMMENT ON COLUMN inspection_task.deleted IS '软å 餿 å¿ï¼0=æªå é¤ï¼1=å·²å é¤'; main-business/src/main/resources/db/migration/postgresql/V20250707155600__create_table_equipment_usage_record.sql
@@ -6,7 +6,7 @@ usage_quantity INT NOT NULL, -- ä½¿ç¨æ°éï¼ä¸å 许为空 user_id BIGINT NOT NULL, -- 使ç¨äººIDï¼å ³èç¨æ·è¡¨ï¼ä¸å 许为空 department_id BIGINT , -- é¨é¨IDï¼å ³èé¨é¨è¡¨ï¼ä¸å 许为空 equipment_status VARCHAR(50) NOT NULL, -- 设å¤ç¶æï¼å¦ï¼æ£å¸¸ãæ éãç»´ä¿®ä¸ï¼ï¼ä¸å 许为空 equipment_status BIGINT NOT NULL, -- 设å¤ç¶æ:1.使ç¨ä¸ 2.å·²å½è¿ usage_start_time TIMESTAMP NOT NULL, -- 使ç¨å¼å§æ¶é´ï¼ä¸å 许为空 usage_end_time TIMESTAMP, -- 使ç¨ç»ææ¶é´ï¼å¯ä¸ºç©ºï¼æªå½è¿æ¶ï¼ remarks VARCHAR(1000), -- 夿³¨ä¿¡æ¯ï¼å¯ä¸ºç©º @@ -27,7 +27,7 @@ COMMENT ON COLUMN equipment_usage_record.usage_quantity IS 'ä½¿ç¨æ°é'; COMMENT ON COLUMN equipment_usage_record.user_id IS '使ç¨äººID'; COMMENT ON COLUMN equipment_usage_record.department_id IS 'é¨é¨ID'; COMMENT ON COLUMN equipment_usage_record.equipment_status IS '设å¤ç¶æï¼æ£å¸¸/æ é/ç»´ä¿®ä¸ï¼'; COMMENT ON COLUMN equipment_usage_record.equipment_status IS '设å¤ç¶æ:1.使ç¨ä¸ 2.å·²å½è¿'; COMMENT ON COLUMN equipment_usage_record.usage_start_time IS '使ç¨å¼å§æ¶é´'; COMMENT ON COLUMN equipment_usage_record.usage_end_time IS '使ç¨ç»ææ¶é´'; COMMENT ON COLUMN equipment_usage_record.remarks IS '夿³¨ä¿¡æ¯'; ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -114,7 +114,7 @@ /** * å·¥ä½è¡¨åç§° */ private String sheetName; protected String sheetName; /** * 导åºç±»åï¼EXPORT:å¯¼åºæ°æ®ï¼IMPORTï¼å¯¼å ¥æ¨¡æ¿ï¼