| 3 小时以前 | gongchunyi | ![]() |
| 3 小时以前 | gongchunyi | ![]() |
| 3 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | zss | ![]() |
| 5 小时以前 | zss | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 5 小时以前 | gongchunyi | ![]() |
| 6 小时以前 | gongchunyi | ![]() |
doc/ÄþÏÄ-ÖÐÊ¢½¨²Ä.sql
@@ -510,4 +510,22 @@ KEY `idx_batch_id` (`batch_id`), KEY `idx_product_id` (`product_id`) COMMENT 'æ¹ä¾¿æäº§åæ¥è¯¢å岿æ¬å¯¹æ¯' ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨'; DEFAULT CHARSET = utf8mb4 COMMENT ='çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨'; ALTER TABLE `product-inventory-management-zsjc`.`production_settlement_batches` DROP INDEX `idx_period`; ALTER TABLE `product-inventory-management-zsjc`.`production_settlement_batches` DROP COLUMN `batch_name`, DROP COLUMN `status`; ALTER TABLE `product-inventory-management-zsjc`.`production_settlement_details` DROP COLUMN `actual_qty`, DROP COLUMN `actual_price`, DROP COLUMN `actual_total`, DROP COLUMN `diff_qty`, DROP COLUMN `diff_price`, DROP COLUMN `diff_total`; ALTER TABLE `product-inventory-management-zsjc`.`production_settlement_batches` MODIFY COLUMN `period_time` varchar(255) NULL DEFAULT NULL COMMENT 'æ ¸ç®å½å±å¹´æ' AFTER `id`; src/main/java/com/ruoyi/basic/pojo/Customer.java
@@ -38,14 +38,14 @@ /** * è·è¿ç¨åº¦ */ @Excel(name = "è·è¿ç¨åº¦") // @Excel(name = "è·è¿ç¨åº¦") @TableField(exist = false) private String followUpLevel; /** * è·è¿æ¶é´ */ @Excel(name = "è·è¿æ¶é´") // @Excel(name = "è·è¿æ¶é´") @TableField(exist = false) private LocalDateTime followUpTime; @@ -92,7 +92,7 @@ * ç»´æ¤æ¶é´ */ @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "ç»´æ¤æ¶é´" , width = 30, dateFormat = "yyyy-MM-dd") @Excel(name = "ç»´æ¤æ¶é´", width = 30, dateFormat = "yyyy-MM-dd") private Date maintenanceTime; @TableField(fill = FieldFill.INSERT) src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java
@@ -173,17 +173,17 @@ c.setAddressPhone(address + "(" + phone + ")"); // æ¥è¯¢ææ°çè·è¿è®°å½ CustomerFollowUp followUp = customerFollowUpService.getOne( new LambdaQueryWrapper<CustomerFollowUp>() .eq(CustomerFollowUp::getCustomerId, c.getId()) .orderByDesc(CustomerFollowUp::getFollowUpTime) .last("LIMIT 1") ); if (followUp != null) { c.setFollowUpLevel(followUp.getFollowUpLevel()); c.setFollowUpTime(followUp.getFollowUpTime()); } // CustomerFollowUp followUp = customerFollowUpService.getOne( // new LambdaQueryWrapper<CustomerFollowUp>() // .eq(CustomerFollowUp::getCustomerId, c.getId()) // .orderByDesc(CustomerFollowUp::getFollowUpTime) // .last("LIMIT 1") // ); // // if (followUp != null) { // c.setFollowUpLevel(followUp.getFollowUpLevel()); // c.setFollowUpTime(followUp.getFollowUpTime()); // } }) .collect(Collectors.toList()); src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -342,22 +342,10 @@ return AjaxResult.success(homeService.salesAnalysis(salesDeliveryDto)); } @GetMapping("/salesRanking") @ApiOperation("éå®ç»è®¡çæ¿---ééæ°æ®-æååæ") public AjaxResult salesRanking(SalesDeliveryDto salesDeliveryDto) { return AjaxResult.success(homeService.salesRanking(salesDeliveryDto)); } @GetMapping("/salesAmount") @ApiOperation("éå®ç»è®¡çæ¿---éå®éé¢åæ") public AjaxResult salesAmount(SalesDeliveryDto salesDeliveryDto) { return AjaxResult.success(homeService.salesAmount(salesDeliveryDto)); } @GetMapping("/salesDataRanking") @ApiOperation("éå®ç»è®¡çæ¿---éå®é¢æ°æ®-æååæ") public AjaxResult salesDataRanking(SalesDeliveryDto salesDeliveryDto) { return AjaxResult.success(homeService.salesDataRanking(salesDeliveryDto)); } @GetMapping("/customerTrends") src/main/java/com/ruoyi/home/dto/SalesTotalDetailDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,27 @@ package com.ruoyi.home.dto; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; import java.util.Map; //éå®åºæ°æ®æç» @Data public class SalesTotalDetailDto { //æ¥æ private LocalDate date; //产åç±»å(ç å/æ¿æ) private String type; //éå®åº private String area; //éé(ç«æ¹ç±³)/éå®é¢(å ) private Long salesTotal; } src/main/java/com/ruoyi/home/dto/SalesTotalDto.java
@@ -14,7 +14,7 @@ //æ¶é´åæ private List<LocalDate> dates; //客æ·åºååæ //æ°æ® private List<Map<String,Long>> customerTrends; src/main/java/com/ruoyi/home/service/HomeService.java
@@ -98,13 +98,13 @@ Map<String,Long> total(); String salesAnalysis(SalesDeliveryDto salesDeliveryDto); SalesTotalDto salesAnalysis(SalesDeliveryDto salesDeliveryDto); String salesRanking(SalesDeliveryDto salesDeliveryDto); List<SalesTotalDetailDto> salesRanking(SalesDeliveryDto salesDeliveryDto); String salesAmount(SalesDeliveryDto salesDeliveryDto); SalesTotalDto salesAmount(SalesDeliveryDto salesDeliveryDto); String salesDataRanking(SalesDeliveryDto salesDeliveryDto); List<SalesTotalDetailDto> salesDataRanking(SalesDeliveryDto salesDeliveryDto); SalesTotalDto customerTrends(SalesDeliveryDto salesDeliveryDto); } src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -2523,8 +2523,8 @@ @Override public Map<String, Long> total() { Map<String, Long> map = new HashMap<>(); //æ»éå®éé¢ List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(null); //æ»éå®éé¢ BigDecimal sum = salesDeliveries.stream() .map(item -> item.getPrice() != null ? new BigDecimal(item.getPrice().toString()) : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); @@ -2545,27 +2545,155 @@ } @Override public String salesAnalysis(SalesDeliveryDto salesDeliveryDto) { public SalesTotalDto salesAnalysis(SalesDeliveryDto salesDeliveryDto) { SalesTotalDto salesTotalDto = new SalesTotalDto(); List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays()); return null; List<Map<String, Long>> maps = new ArrayList<>(); List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery() .eq(SalesDelivery::getProductName,salesDeliveryDto.getType())); for (LocalDate date : dates) { LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); if (salesDeliveryDto.getDays().equals("å¹´")){ lastDay = date.with(TemporalAdjusters.lastDayOfYear()); } LocalDate finalLastDay = lastDay; salesDeliveries = salesDeliveries .stream() .filter(delivery -> { LocalDate deliveryDate = delivery.getDeliveryDate(); return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay); }) .collect(Collectors.toList()); Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values()) .collect(Collectors.toMap( AddressRegionEnum::getRegionName, // åºååä½ä¸ºkey enumItem -> 0L // åå§å¼å ¨é¨ä¸º0 )); if (!CollectionUtils.isEmpty(salesDeliveries)) { // æåºååç»ï¼ç»è®¡æ¯ä¸ªåºåçééæ»å regionCountMap = salesDeliveries.stream() .filter(delivery -> delivery.getDeliveryPlace() != null) .collect(Collectors.groupingBy( delivery -> { AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace()); return regionEnum != null ? regionEnum.getRegionName() : null; }, Collectors.summingLong(delivery -> delivery.getVolume() != null ? delivery.getVolume().longValue() : 0L) )); } regionCountMap.put("å ¨é¨", salesDeliveries.stream() .mapToLong(item -> item.getVolume() != null ? item.getVolume().longValue() : 0L) .sum()); maps.add(regionCountMap); } salesTotalDto.setDates(dates); salesTotalDto.setCustomerTrends(maps); return salesTotalDto; } @Override public String salesRanking(SalesDeliveryDto salesDeliveryDto) { public List<SalesTotalDetailDto> salesRanking(SalesDeliveryDto salesDeliveryDto) { List<SalesTotalDetailDto> salesTotalDetailDtos = new ArrayList<>(); List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays()); return null; List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery() .eq(SalesDelivery::getProductName,salesDeliveryDto.getType())); for (LocalDate date : dates) { LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); if (salesDeliveryDto.getDays().equals("å¹´")){ lastDay = date.with(TemporalAdjusters.lastDayOfYear()); } LocalDate finalLastDay = lastDay; salesDeliveries = salesDeliveries .stream() .filter(delivery -> { LocalDate deliveryDate = delivery.getDeliveryDate(); return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay); }) .collect(Collectors.toList()); Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values()) .collect(Collectors.toMap( AddressRegionEnum::getRegionName, // åºååä½ä¸ºkey enumItem -> 0L // åå§å¼å ¨é¨ä¸º0 )); if (!CollectionUtils.isEmpty(salesDeliveries)) { // æåºååç»ï¼ç»è®¡æ¯ä¸ªåºåçééæ»å regionCountMap = salesDeliveries.stream() .filter(delivery -> delivery.getDeliveryPlace() != null) .collect(Collectors.groupingBy( delivery -> { AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace()); return regionEnum != null ? regionEnum.getRegionName() : null; }, Collectors.summingLong(delivery -> delivery.getVolume() != null ? delivery.getVolume().longValue() : 0L) )); } regionCountMap.put("å ¨é¨", salesDeliveries.stream() .mapToLong(item -> item.getVolume() != null ? item.getVolume().longValue() : 0L) .sum()); SalesTotalDetailDto salesTotalDetailDto = new SalesTotalDetailDto(); salesTotalDetailDto.setDate(date); salesTotalDetailDto.setType(salesDeliveryDto.getType()); salesTotalDetailDtos.add(salesTotalDetailDto); } return salesTotalDetailDtos; } @Override public String salesAmount(SalesDeliveryDto salesDeliveryDto) { public SalesTotalDto salesAmount(SalesDeliveryDto salesDeliveryDto) { SalesTotalDto salesTotalDto = new SalesTotalDto(); List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays()); return null; List<Map<String, Long>> maps = new ArrayList<>(); List<SalesDelivery> salesDeliveries = salesDeliveryMapper.selectList(Wrappers.<SalesDelivery>lambdaQuery() .eq(SalesDelivery::getProductName,salesDeliveryDto.getType())); for (LocalDate date : dates) { LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); if (salesDeliveryDto.getDays().equals("å¹´")){ lastDay = date.with(TemporalAdjusters.lastDayOfYear()); } LocalDate finalLastDay = lastDay; salesDeliveries = salesDeliveries .stream() .filter(delivery -> { LocalDate deliveryDate = delivery.getDeliveryDate(); return !deliveryDate.isBefore(firstDay) && !deliveryDate.isAfter(finalLastDay); }) .collect(Collectors.toList()); Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values()) .collect(Collectors.toMap( AddressRegionEnum::getRegionName, // åºååä½ä¸ºkey enumItem -> 0L // åå§å¼å ¨é¨ä¸º0 )); if (!CollectionUtils.isEmpty(salesDeliveries)) { // æåºååç»ï¼ç»è®¡æ¯ä¸ªåºåçééæ»å regionCountMap = salesDeliveries.stream() .filter(delivery -> delivery.getDeliveryPlace() != null) .collect(Collectors.groupingBy( delivery -> { AddressRegionEnum regionEnum = AddressRegionEnum.matchRegion(delivery.getDeliveryPlace()); return regionEnum != null ? regionEnum.getRegionName() : null; }, Collectors.summingLong(delivery -> delivery.getPrice() != null ? delivery.getPrice().longValue() : 0L) )); } regionCountMap.put("å ¨é¨", salesDeliveries.stream() .mapToLong(item -> item.getPrice() != null ? item.getPrice().longValue() : 0L) .sum()); maps.add(regionCountMap); } salesTotalDto.setDates(dates); salesTotalDto.setCustomerTrends(maps); return salesTotalDto; } @Override public String salesDataRanking(SalesDeliveryDto salesDeliveryDto) { public List<SalesTotalDetailDto> salesDataRanking(SalesDeliveryDto salesDeliveryDto) { List<SalesTotalDetailDto> salesTotalDetailDtos = new ArrayList<>(); List<LocalDate> dates = convertDateList(salesDeliveryDto.getDays()); return null; return salesTotalDetailDtos; } @Override @@ -2576,12 +2704,14 @@ for (LocalDate date : dates) { LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); if (salesDeliveryDto.getDays().equals("å¹´")){ lastDay = date.with(TemporalAdjusters.lastDayOfYear()); } Date startDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant()); Date endDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()); List<Customer> customers = customerMapper.selectList(Wrappers.<Customer>lambdaQuery() .between(Customer::getMaintenanceTime, startDate, endDate)); Map<String, Long> regionCountMap = Arrays.stream(AddressRegionEnum.values()) .filter(addressRegionEnum -> addressRegionEnum.getRegionName().equals("SELF_PICKUP")) .collect(Collectors.toMap( AddressRegionEnum::getRegionName, // åºååä½ä¸ºkey enumItem -> 0L // åå§å¼å ¨é¨ä¸º0 @@ -2598,7 +2728,7 @@ Collectors.counting() // è®¡æ° )); } regionCountMap.put("ALLIN",customers.stream().count()); regionCountMap.put("å ¨é¨",customers.stream().count()); maps.add(regionCountMap); } salesTotalDto.setDates(dates); src/main/java/com/ruoyi/production/controller/ProductBomController.java
@@ -12,11 +12,9 @@ import com.ruoyi.production.dto.ProductBomDto; import com.ruoyi.production.pojo.ProcessRoute; import com.ruoyi.production.pojo.ProductBom; import com.ruoyi.production.pojo.ProductProcessRoute; import com.ruoyi.production.pojo.ProductStructure; import com.ruoyi.production.service.ProcessRouteService; import com.ruoyi.production.service.ProductBomService; import com.ruoyi.production.service.ProductProcessRouteService; import com.ruoyi.production.service.ProductStructureService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; @@ -50,9 +48,6 @@ private ProcessRouteService processRouteService; @Autowired private ProductProcessRouteService productProcessRouteService; @Autowired private ProductStructureService productStructureService; @GetMapping("/listPage") @@ -82,8 +77,7 @@ @Log(title = "å é¤", businessType = BusinessType.DELETE) public AjaxResult batchDelete(@RequestBody List<Integer> ids) { List<ProcessRoute> list = processRouteService.list(Wrappers.<ProcessRoute>lambdaQuery().in(ProcessRoute::getBomId, ids)); List<ProductProcessRoute> list2 = productProcessRouteService.list(Wrappers.<ProductProcessRoute>lambdaQuery().in(ProductProcessRoute::getBomId, ids)); if (list.size() > 0 || list2.size() > 0) { if (list.size() > 0) { return AjaxResult.error("该BOMå·²ç»åå¨å¯¹åºçå·¥èºè·¯çº¿,æ æ³è¿è¡å é¤"); } if (CollectionUtils.isEmpty(ids)) { src/main/java/com/ruoyi/production/controller/ProductProcessParamController.java
@@ -1,8 +1,11 @@ package com.ruoyi.production.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 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.production.dto.ProductProcessParamDto; import com.ruoyi.production.dto.ProductProcessParamSortDTO; import com.ruoyi.production.pojo.ProductProcessParam; import com.ruoyi.production.service.ProductProcessParamService; @@ -33,8 +36,9 @@ @GetMapping("/list/{productProcessId}") @Log(title = "æ ¹æ®å·¥åºIDæ¥è¯¢å¯¹åºçåæ°", businessType = BusinessType.OTHER) @ApiOperation("æ ¹æ®å·¥åºIDæ¥è¯¢å¯¹åºçåæ°") public AjaxResult listByProcessId(@PathVariable("productProcessId") Long productProcessId) { return AjaxResult.success(productProcessParamService.listByProcessId(productProcessId)); public AjaxResult listByProcessId(@PathVariable("productProcessId") Long productProcessId, Page<ProductProcessParamDto> page) { IPage<ProductProcessParamDto> list = productProcessParamService.listByProcessId(productProcessId, page); return AjaxResult.success(list); } @PostMapping("/add") src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java
@@ -1,19 +1,22 @@ package com.ruoyi.production.controller; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.production.dto.ProductionSettlementDetailsDto; import com.ruoyi.production.dto.ProductionSettlementDto; import com.ruoyi.production.dto.ProductionSettlementTotalDto; import com.ruoyi.production.dto.SettlementImportDto; import com.ruoyi.production.service.IProductionSettlementBatchesService; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; /** * <p> @@ -33,9 +36,45 @@ @PostMapping("/import") @ApiOperation("å¯¼å ¥çäº§ææ¬æ ¸ç®è¡¨") public AjaxResult importProductionSettlement(@RequestParam("file") MultipartFile file, @RequestParam(required = false) LocalDate periodTime, @RequestParam(required = false) String batchName) { productionSettlementBatchesService.importProductionSettlement(file, periodTime, batchName); public AjaxResult importProductionSettlement(@RequestParam("file") MultipartFile file, ProductionSettlementDto dto) { productionSettlementBatchesService.importProductionSettlement(file, dto); return AjaxResult.success(); } @GetMapping("/downloadTemplate") @ApiOperation("çäº§ææ¬æ ¸ç®å¯¼å ¥æ¨¡æ¿") public void export(HttpServletResponse response) { ExcelUtil<SettlementImportDto> excelUtil = new ExcelUtil<>(SettlementImportDto.class); excelUtil.importTemplateExcel(response, "çäº§ææ¬æ ¸ç®å¯¼å ¥æ¨¡æ¿"); } @GetMapping("/getSettlement") @ApiOperation("è·åçäº§ææ¬æ ¸ç®æ°æ®") public AjaxResult getSettlement(ProductionSettlementDto dto) { Map<String, List<ProductionSettlementDetailsDto>> map = productionSettlementBatchesService.getSettlement(dto); return AjaxResult.success(map); } @GetMapping("/getProductTypes") @ApiOperation("è·åå¯¹åºæä»½å¯¼å ¥ç产åç±»å«") public AjaxResult getProductTypes(ProductionSettlementDto dto) { List<String> list = productionSettlementBatchesService.getProductTypes(dto); return AjaxResult.success(list); } @GetMapping("/getSubjectNames") @ApiOperation("è·åå¯¹åºæä»½å¯¼å ¥çç§ç®ç±»å«") public AjaxResult getSubjectNames(ProductionSettlementDto dto) { List<String> list = productionSettlementBatchesService.getSubjectNames(dto); return AjaxResult.success(list); } @GetMapping("/getTotalCosts") @ApiOperation("è·åææ¬åè®¡æ°æ®") public AjaxResult getTotalCosts(ProductionSettlementDto dto) { ProductionSettlementTotalDto totalCosts = productionSettlementBatchesService.getTotalCosts(dto); return AjaxResult.success(totalCosts); } } src/main/java/com/ruoyi/production/dto/ProductMaterialSkuImportDto.java
@@ -27,6 +27,10 @@ @Excel(name = "è§æ ¼åå·") private String model; @ApiModelProperty("ç©æç¼ç ") @Excel(name = "ç©æç¼ç ") private String materialCode; @ApiModelProperty("ä¾åºæ¹å¼ï¼èªå¶ï¼å¤è´ï¼") @Excel(name = "ä¾åºæ¹å¼") private String supplyType; src/main/java/com/ruoyi/production/dto/ProductionSettlementDetailsDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ package com.ruoyi.production.dto; import com.ruoyi.production.pojo.ProductionSettlementDetails; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import java.math.BigDecimal; /** * <br> * * </br> * * @author deslrey * @version 1.0 * @since 2026/04/01 9:16 */ @Data @EqualsAndHashCode(callSuper = false) public class ProductionSettlementDetailsDto extends ProductionSettlementDetails { @ApiModelProperty(value = "å®é èé") private BigDecimal actualQty; @ApiModelProperty(value = "å®é åä»·") private BigDecimal actualPrice; @ApiModelProperty(value = "å®é æ»ææ¬") private BigDecimal actualTotal; @ApiModelProperty(value = "èéå·®å¼") private String diffQty; @ApiModelProperty(value = "åä»·å·®å¼") private String diffPrice; @ApiModelProperty(value = "æ»ææ¬å·®å¼") private String diffTotal; } src/main/java/com/ruoyi/production/dto/ProductionSettlementDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,31 @@ package com.ruoyi.production.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * <br> * çäº§ææ¬æ ¸ç®æ¥è¯¢åæ°Dto * </br> * * @author deslrey * @version 1.0 * @since 2026/04/01 */ @Data @ApiModel(value = "ProductionSettlementDto", description = "çäº§ææ¬æ ¸ç®æ¥è¯¢åæ°Dto") public class ProductionSettlementDto { @ApiModelProperty("æ ¸ç®ææ¬æ¥æ") private String periodTime; @ApiModelProperty("æ ¸ç®äº§åç±»å") private String productType; @ApiModelProperty("æ ¸ç®ææ¬ç§ç®") private String subjectName; @ApiModelProperty("æ ¸ç®ææ¬ç±»å") private String costType; } src/main/java/com/ruoyi/production/dto/ProductionSettlementTotalDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,33 @@ package com.ruoyi.production.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; /** * <br> * çäº§ææ¬æ ¸ç®åè®¡æ°æ® Dto * </br> * * @author deslrey * @version 1.0 * @since 2026/04/01 */ @Data @ApiModel(value = "ProductionSettlementTotalDto", description = "çäº§ææ¬æ ¸ç®åè®¡æ°æ®") public class ProductionSettlementTotalDto { @ApiModelProperty("æ åææ¬å计") private BigDecimal budgetTotal; @ApiModelProperty("å®é ææ¬å计") private BigDecimal actualTotal; @ApiModelProperty("å·®å¼å计") private BigDecimal diffTotal; @ApiModelProperty("å·®å¼ç") private String diffRate; } src/main/java/com/ruoyi/production/enums/ProductionSettlementEnum.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,42 @@ package com.ruoyi.production.enums; import lombok.Getter; /** * <br> * 产åç±»å-ç§ç®åç§° * </br> * * @author deslrey * @version 1.0 * @since 2026/03/31 */ @Getter public enum ProductionSettlementEnum { MATERIAL_COST("ææææ¬", true), ENERGY_COST("è½èææ¬", false); private final String name; private final boolean requiresProduct; ProductionSettlementEnum(String name, boolean requiresProduct) { this.name = name; this.requiresProduct = requiresProduct; } /** * 夿æ¯å¦ä¸ºææææ¬ * * @param name ç§ç®åç§° * @return boolean */ public static boolean isMaterialCost(String name) { for (ProductionSettlementEnum e : values()) { if (e.getName().equals(name)) { return e.isRequiresProduct(); } } return false; } } src/main/java/com/ruoyi/production/mapper/ProductProcessParamMapper.java
@@ -1,11 +1,12 @@ package com.ruoyi.production.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.ruoyi.production.dto.ProductProcessParamDto; import com.ruoyi.production.pojo.ProductProcessParam; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <br> @@ -18,7 +19,7 @@ */ public interface ProductProcessParamMapper extends BaseMapper<ProductProcessParam> { List<ProductProcessParamDto> selectDtoListByProcessId(@Param("processId") Long processId); IPage<ProductProcessParamDto> selectDtoListByProcessId(@Param("page") IPage<ProductProcessParamDto> page, @Param("processId") Long processId); } src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java
@@ -1,11 +1,11 @@ package com.ruoyi.production.pojo; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.*; import java.time.LocalDate; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -24,7 +24,7 @@ @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("production_settlement_batches") @ApiModel(value="ProductionSettlementBatches对象", description="çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨") @ApiModel(value = "ProductionSettlementBatches对象", description = "çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨") public class ProductionSettlementBatches implements Serializable { private static final long serialVersionUID = 1L; @@ -34,21 +34,17 @@ private Long id; @ApiModelProperty(value = "æ ¸ç®å½å±æä»½") private LocalDate periodTime; @ApiModelProperty(value = "æ¹æ¬¡åç§°") private String batchName; @ApiModelProperty(value = "ç¶æï¼0-ä» é¢ç®ï¼1-ç»ç®è®¡ç®ä¸ï¼2-已宿ç»ç®ï¼3-å·²éå®") private Integer status; private String periodTime; @ApiModelProperty(value = "å¯¼å ¥ç¨æ·") private String createUser; @ApiModelProperty(value = "åå»ºæ¥æ") @TableField(value = "create_time", fill = FieldFill.INSERT) private LocalDateTime createTime; @ApiModelProperty(value = "ç§æ·ID") @TableField(value = "tenant_id", fill = FieldFill.INSERT) private Long tenantId; src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java
@@ -1,10 +1,11 @@ package com.ruoyi.production.pojo; import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.*; import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -23,7 +24,7 @@ @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("production_settlement_details") @ApiModel(value="ProductionSettlementDetails对象", description="çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨") @ApiModel(value = "ProductionSettlementDetails对象", description = "çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨") public class ProductionSettlementDetails implements Serializable { private static final long serialVersionUID = 1L; @@ -56,26 +57,8 @@ @ApiModelProperty(value = "é¢ç®æ»ææ¬") private BigDecimal budgetTotal; @ApiModelProperty(value = "å®é èé") private BigDecimal actualQty; @ApiModelProperty(value = "å®é åä»·") private BigDecimal actualPrice; @ApiModelProperty(value = "å®é æ»ææ¬") private BigDecimal actualTotal; @ApiModelProperty(value = "èéå·®å¼") private BigDecimal diffQty; @ApiModelProperty(value = "åä»·å·®å¼") private BigDecimal diffPrice; @ApiModelProperty(value = "æ»ææ¬å·®å¼") private BigDecimal diffTotal; @ApiModelProperty(value = "ç§æ·ID") @TableField(value = "tenant_id", fill = FieldFill.INSERT) private Long tenantId; } src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java
@@ -1,10 +1,14 @@ package com.ruoyi.production.service; import com.ruoyi.production.dto.ProductionSettlementDetailsDto; import com.ruoyi.production.dto.ProductionSettlementDto; import com.ruoyi.production.dto.ProductionSettlementTotalDto; import com.ruoyi.production.pojo.ProductionSettlementBatches; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; import java.util.List; import java.util.Map; /** * <p> @@ -16,6 +20,13 @@ */ public interface IProductionSettlementBatchesService extends IService<ProductionSettlementBatches> { void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName); void importProductionSettlement(MultipartFile file, ProductionSettlementDto dto); Map<String, List<ProductionSettlementDetailsDto>> getSettlement(ProductionSettlementDto dto); List<String> getProductTypes(ProductionSettlementDto dto); List<String> getSubjectNames(ProductionSettlementDto dto); ProductionSettlementTotalDto getTotalCosts(ProductionSettlementDto dto); } src/main/java/com/ruoyi/production/service/ProductProcessParamService.java
@@ -1,5 +1,7 @@ package com.ruoyi.production.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.production.dto.ProductProcessParamDto; import com.ruoyi.production.dto.ProductProcessParamSortDTO; @@ -18,7 +20,7 @@ */ public interface ProductProcessParamService extends IService<ProductProcessParam> { List<ProductProcessParamDto> listByProcessId(Long processId); IPage<ProductProcessParamDto> listByProcessId(Long processId, Page<ProductProcessParamDto> page); void add(ProductProcessParam productProcessParam); src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
@@ -20,11 +20,7 @@ import org.springframework.web.multipart.MultipartFile; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.*; import java.util.stream.Collectors; /** @@ -153,7 +149,7 @@ ProductMaterial material = productMaterialMapper.selectById(materialId); if (material == null) { throw new ServiceException("ç©æä¸åå¨"); throw new ServiceException("ä¸»ç©æä¿¡æ¯ä¸åå¨"); } ExcelUtil<ProductMaterialSkuImportDto> excelUtil = new ExcelUtil<>(ProductMaterialSkuImportDto.class); @@ -164,70 +160,81 @@ log.error("å¯¼å ¥ç©æè§æ ¼Excelè§£æå¤±è´¥", e); throw new ServiceException("Excelè§£æå¤±è´¥"); } if (importList == null || importList.isEmpty()) { throw new ServiceException("Excelæ²¡ææ°æ®"); throw new ServiceException("Excel䏿ªæ£æµå°æææ°æ®"); } List<Integer> emptyCodeRows = new ArrayList<>(); int currentRow = 1; Map<String, ProductMaterialSkuImportDto> specMap = new LinkedHashMap<>(); for (ProductMaterialSkuImportDto dto : importList) { if (dto == null || StringUtils.isEmpty(dto.getModel())) { currentRow++; if (dto == null) continue; // ç©æç¼ç ä¸è½ä¸ºç©º if (StringUtils.isEmpty(dto.getMaterialCode())) { emptyCodeRows.add(currentRow); continue; } String specification = dto.getModel().trim(); if (specification.isEmpty()) { if (StringUtils.isEmpty(dto.getModel())) { continue; } specMap.putIfAbsent(specification, dto); String modelKey = dto.getModel().trim(); specMap.putIfAbsent(modelKey, dto); } if (!emptyCodeRows.isEmpty()) { throw new ServiceException("å¯¼å ¥å¤±è´¥,以ä¸è¡å·çãç©æç¼ç ã为空ï¼" + emptyCodeRows.toString()); } if (specMap.isEmpty()) { throw new ServiceException("Excelæ²¡æææçè§æ ¼æ°æ®"); throw new ServiceException("Excelæ²¡æææçè§æ ¼åå·æ°æ®"); } Set<String> specifications = specMap.keySet(); Set<String> modelSet = specMap.keySet(); List<ProductMaterialSku> existList = this.list(new LambdaQueryWrapper<ProductMaterialSku>() .eq(ProductMaterialSku::getProductId, materialId) .in(ProductMaterialSku::getModel, specifications)); Map<String, ProductMaterialSku> existMap = existList.stream() .collect(Collectors.toMap(ProductMaterialSku::getModel, sku -> sku, (a, b) -> a)); .in(ProductMaterialSku::getModel, modelSet)); Map<String, ProductMaterialSku> existMap = existList.stream().collect(Collectors.toMap(ProductMaterialSku::getModel, sku -> sku, (a, b) -> a)); LocalDateTime now = LocalDateTime.now(); List<ProductMaterialSku> saveList = new ArrayList<>(); List<ProductMaterialSku> updateList = new ArrayList<>(); for (Map.Entry<String, ProductMaterialSkuImportDto> entry : specMap.entrySet()) { String specification = entry.getKey(); String model = entry.getKey(); ProductMaterialSkuImportDto dto = entry.getValue(); String supplyType = StringUtils.isNotEmpty(dto.getSupplyType()) ? dto.getSupplyType().trim() : null; ProductMaterialSku exist = existMap.get(specification); if (exist == null) { ProductMaterialSku sku = new ProductMaterialSku(); sku.setProductId(materialId); sku.setModel(specification); sku.setSupplyType(supplyType); sku.setCreateTime(now); sku.setUpdateTime(now); saveList.add(sku); String excelMaterialCode = dto.getMaterialCode().trim(); String excelSupplyType = StringUtils.isNotEmpty(dto.getSupplyType()) ? dto.getSupplyType().trim() : null; ProductMaterialSku existSku = existMap.get(model); if (existSku == null) { ProductMaterialSku newSku = new ProductMaterialSku(); newSku.setProductId(materialId); newSku.setModel(model); newSku.setMaterialCode(excelMaterialCode); newSku.setSupplyType(excelSupplyType); newSku.setCreateTime(now); newSku.setUpdateTime(now); saveList.add(newSku); } else { boolean needUpdate = false; if (supplyType != null && !supplyType.equals(exist.getSupplyType())) { exist.setSupplyType(supplyType); if (!Objects.equals(excelMaterialCode, existSku.getMaterialCode())) { existSku.setMaterialCode(excelMaterialCode); needUpdate = true; } if (!Objects.equals(excelSupplyType, existSku.getSupplyType())) { existSku.setSupplyType(excelSupplyType); needUpdate = true; } if (needUpdate) { exist.setUpdateTime(now); updateList.add(exist); existSku.setUpdateTime(now); updateList.add(existSku); } } } if (saveList.isEmpty() && updateList.isEmpty()) { throw new ServiceException("Excelä¸ç°ææ°æ®ä¸è´ï¼æ éå¯¼å ¥"); throw new ServiceException("Excelå 容ä¸ç°ææ°æ®å®å ¨ä¸è´"); } if (!saveList.isEmpty()) { this.saveBatch(saveList); } @@ -235,6 +242,6 @@ this.updateBatchById(updateList); } log.info("ç©æè§æ ¼å¯¼å ¥å®æ materialId={}, æ°å¢{}æ¡ï¼æ´æ°{}æ¡", materialId, saveList.size(), updateList.size()); log.info("ç©æè§æ ¼å¯¼å ¥å®æ! materialId={}, æ°å¢{}æ¡ï¼æ´æ°{}æ¡", materialId, saveList.size(), updateList.size()); } } src/main/java/com/ruoyi/production/service/impl/ProductOrderServiceImpl.java
@@ -1,5 +1,6 @@ package com.ruoyi.production.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; @@ -226,23 +227,11 @@ throw new RuntimeException("åªæãå¾ å¼å§ã已忶ãç¶æç订åæå¯ä»¥å é¤"); } // æ¯å¦å·²ç产 List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().eq(ProductWorkOrder::getProductOrderId, id)); if (!productWorkOrders.isEmpty()) { List<Long> workOrderIds = productWorkOrders.stream() .map(ProductWorkOrder::getId) .collect(Collectors.toList()); List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery().in(ProductionProductMain::getWorkOrderId, workOrderIds)); if (!productionProductMains.isEmpty()) { throw new RuntimeException("ç产订åå·²ç»å¼å§ç产,ä¸è½å é¤"); } // å é¤å·¥å productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().eq(ProductWorkOrder::getProductOrderId, id)); // æ¯å¦ææ¥å·¥æ°æ® List<ProductionProductMain> productMains = productionProductMainMapper.selectList(new LambdaQueryWrapper<ProductionProductMain>().eq(ProductionProductMain::getProductOrderId, id)); if (!productMains.isEmpty()) { throw new RuntimeException("ç产订åå·²ç»å¼å§ç产,ä¸è½å é¤"); } // åéç产计å List<ProductOrderPlan> productOrderPlans = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductOrderId, id)); src/main/java/com/ruoyi/production/service/impl/ProductProcessParamServiceImpl.java
@@ -1,9 +1,10 @@ package com.ruoyi.production.service.impl; 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.basic.mapper.BaseParamMapper; import com.ruoyi.basic.pojo.BaseParam; import com.ruoyi.basic.service.BaseParamService; import com.ruoyi.production.dto.ProductProcessParamDto; import com.ruoyi.production.dto.ProductProcessParamSortDTO; import com.ruoyi.production.mapper.ProductProcessParamMapper; @@ -34,11 +35,11 @@ BaseParamMapper baseParamMapper; @Override public List<ProductProcessParamDto> listByProcessId(Long processId) { public IPage<ProductProcessParamDto> listByProcessId(Long processId, Page<ProductProcessParamDto> page) { if (processId == null) { throw new IllegalArgumentException("å·¥åºIDä¸è½ä¸ºç©º"); } return baseMapper.selectDtoListByProcessId(processId); return baseMapper.selectDtoListByProcessId(page, processId); } @Override src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java
@@ -4,22 +4,35 @@ import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.energy.pojo.Energy; import com.ruoyi.energy.pojo.EnergyConsumptionDetail; import com.ruoyi.energy.service.EnergyConsumptionDetailService; import com.ruoyi.energy.service.EnergyService; import com.ruoyi.production.dto.ProductionSettlementDetailsDto; import com.ruoyi.production.dto.ProductionSettlementDto; import com.ruoyi.production.dto.ProductionSettlementTotalDto; import com.ruoyi.production.dto.SettlementImportDto; import com.ruoyi.production.pojo.ProductionSettlementBatches; import com.ruoyi.production.enums.ProductionSettlementEnum; import com.ruoyi.production.pojo.*; import com.ruoyi.production.mapper.ProductionSettlementBatchesMapper; import com.ruoyi.production.pojo.ProductionSettlementDetails; import com.ruoyi.production.service.IProductionSettlementBatchesService; import com.ruoyi.production.service.*; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.production.service.IProductionSettlementDetailsService; import com.ruoyi.project.system.domain.SysDictData; import com.ruoyi.project.system.mapper.SysDictDataMapper; import com.ruoyi.production.utils.UnitUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** @@ -31,58 +44,453 @@ * @since 2026-03-30 */ @Service @Slf4j public class ProductionSettlementBatchesServiceImpl extends ServiceImpl<ProductionSettlementBatchesMapper, ProductionSettlementBatches> implements IProductionSettlementBatchesService { @Autowired private IProductionSettlementDetailsService productionSettlementDetailsService; @Autowired private ProductMaterialService productMaterialService; @Autowired private ProductMaterialSkuService productMaterialSkuService; @Autowired private ProductionProductMainService productionProductMainService; @Autowired private ProductionProductInputService productionProductInputService; @Autowired private IProductionOrderStructureService productionOrderStructureService; @Autowired private ProductOrderService productOrderService; @Autowired private IProductionOrderRouteService productionOrderRouteService; @Autowired private EnergyService energyService; @Autowired private EnergyConsumptionDetailService energyConsumptionDetailService; @Autowired private SysDictDataMapper sysDictDataMapper; @Override @Transactional(rollbackFor = Exception.class) public void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName) { public void importProductionSettlement(MultipartFile file, ProductionSettlementDto dto) { if (file == null || file.isEmpty()) { throw new ServiceException("å¯¼å ¥å¤±è´¥ï¼æä»¶ä¸è½ä¸ºç©º"); } // æ ¸ç®æä»½ï¼å¦æä¸å¡«åé»è®¤ä¸ºå½åæ String finalPeriodTime = parsePeriodTime(dto != null ? dto.getPeriodTime() : null); List<SettlementImportDto> list; try { ExcelUtil<SettlementImportDto> util = new ExcelUtil<>(SettlementImportDto.class); list = util.importExcel(file.getInputStream()); list = new ExcelUtil<>(SettlementImportDto.class).importExcel(file.getInputStream()); } catch (Exception e) { log.error("å¯¼å ¥çäº§ææ¬æ ¸ç®å¤±è´¥", e); log.error("è§£æExcel失败", e); throw new ServiceException("è§£æExcelæä»¶å¤±è´¥ï¼" + e.getMessage()); } if (StringUtils.isEmpty(list)) { if (list == null || list.isEmpty()) { throw new ServiceException("å¯¼å ¥æ°æ®ä¸è½ä¸ºç©ºï¼"); } // å¦æè¯¥ææ¹æ¬¡å·²åå¨ï¼å æ¸ é¤æ§æ¹æ¬¡åå ¶æç»ï¼åéæ°å¯¼å ¥ ProductionSettlementBatches existBatch = this.lambdaQuery() .eq(ProductionSettlementBatches::getPeriodTime, finalPeriodTime) .one(); if (existBatch != null) { productionSettlementDetailsService.lambdaUpdate() .eq(ProductionSettlementDetails::getBatchId, existBatch.getId()) .remove(); this.removeById(existBatch.getId()); log.info("å·²æ¸ é¤ {} æä»½çæ§æ ¸ç®æ°æ®ï¼æ¹æ¬¡IDï¼{}", finalPeriodTime, existBatch.getId()); } ProductionSettlementBatches batch = new ProductionSettlementBatches(); batch.setBatchName(StringUtils.isNotEmpty(batchName) ? batchName : periodTime + "ææ¬æ ¸ç®å¯¼å ¥"); batch.setPeriodTime(periodTime != null ? periodTime : LocalDate.now()); batch.setStatus(0); batch.setCreateTime(LocalDateTime.now()); batch.setPeriodTime(finalPeriodTime); batch.setCreateUser(SecurityUtils.getUsername()); this.save(batch); List<ProductionSettlementDetails> detailList = list.stream().map(dto -> { String lastProductType = ""; String lastCategory = ""; List<ProductionSettlementDetails> detailList = new ArrayList<>(); int rowIndex = 2; for (SettlementImportDto importDto : list) { ProductionSettlementDetails detail = new ProductionSettlementDetails(); detail.setBatchId(batch.getId()); detail.setProductType(dto.getProductType()); detail.setCategory(dto.getCategory()); detail.setSubjectName(dto.getSubjectName()); detail.setBudgetQty(dto.getBudgetQty()); detail.setBudgetPrice(dto.getBudgetPrice()); detail.setBudgetTotal(dto.getBudgetTotal()); detail.setActualQty(BigDecimal.ZERO); detail.setActualPrice(BigDecimal.ZERO); detail.setActualTotal(BigDecimal.ZERO); detail.setDiffQty(BigDecimal.ZERO); detail.setDiffPrice(BigDecimal.ZERO); detail.setDiffTotal(BigDecimal.ZERO); return detail; }).collect(Collectors.toList()); if (StringUtils.isNotBlank(importDto.getProductType())) { lastProductType = importDto.getProductType(); } if (StringUtils.isNotBlank(importDto.getCategory())) { lastCategory = importDto.getCategory(); } detail.setProductType(lastProductType); detail.setCategory(lastCategory); detail.setSubjectName(importDto.getSubjectName()); detail.setBudgetQty(importDto.getBudgetQty() != null ? importDto.getBudgetQty() : BigDecimal.ZERO); detail.setBudgetPrice(importDto.getBudgetPrice() != null ? importDto.getBudgetPrice() : BigDecimal.ZERO); detail.setBudgetTotal(importDto.getBudgetTotal() != null ? importDto.getBudgetTotal() : BigDecimal.ZERO); if (ProductionSettlementEnum.isMaterialCost(detail.getCategory())) { ProductMaterial product = productMaterialService.lambdaQuery() .eq(ProductMaterial::getProductName, importDto.getSubjectName()) .one(); if (product != null) { detail.setProductId(product.getId()); } else { log.warn("第 {} è¡ï¼æªæ¾å°ç§ç®äº§åï¼{}", rowIndex, importDto.getSubjectName()); } } detailList.add(detail); rowIndex++; } productionSettlementDetailsService.saveBatch(detailList); } @Override public Map<String, List<ProductionSettlementDetailsDto>> getSettlement(ProductionSettlementDto dto) { String finalPeriodTime = parsePeriodTime(dto != null ? dto.getPeriodTime() : null); YearMonth yearMonth = YearMonth.parse(finalPeriodTime, DateTimeFormatter.ofPattern("yyyy-MM")); LocalDate date = yearMonth.atDay(1); ProductionSettlementBatches batch = this.lambdaQuery() .eq(ProductionSettlementBatches::getPeriodTime, finalPeriodTime) .one(); if (batch == null) { return new HashMap<>(); } String filterProductType = dto != null ? dto.getProductType() : null; String filterSubjectName = dto != null ? dto.getSubjectName() : null; String filterCostType = dto != null ? dto.getCostType() : null; List<ProductionSettlementDetails> details = productionSettlementDetailsService.lambdaQuery() .eq(ProductionSettlementDetails::getBatchId, batch.getId()) .eq(StringUtils.isNotBlank(filterProductType), ProductionSettlementDetails::getProductType, filterProductType) .eq(StringUtils.isNotBlank(filterSubjectName), ProductionSettlementDetails::getSubjectName, filterSubjectName) .eq(StringUtils.isNotBlank(filterCostType), ProductionSettlementDetails::getCategory, filterCostType) .list(); List<ProductionSettlementDetailsDto> dtoList = details.stream().map(d -> { ProductionSettlementDetailsDto detailDto = new ProductionSettlementDetailsDto(); detailDto.setBatchId(d.getBatchId()); detailDto.setProductId(d.getProductId()); detailDto.setProductType(d.getProductType()); detailDto.setCategory(d.getCategory()); detailDto.setSubjectName(d.getSubjectName()); detailDto.setBudgetQty(d.getBudgetQty()); detailDto.setBudgetPrice(d.getBudgetPrice()); detailDto.setBudgetTotal(d.getBudgetTotal()); return detailDto; }).collect(Collectors.toList()); LocalDateTime start = date.atStartOfDay(); LocalDateTime end = start.plusMonths(1); // è·å产ååç±» List<SysDictData> sysDictDataList = sysDictDataMapper.selectDictDataByType("product_type"); Map<Long, String> dictCodeMap = sysDictDataList.stream() .collect(Collectors.toMap(SysDictData::getDictCode, SysDictData::getDictLabel, (k1, k2) -> k1)); // è·åç©ææ¶èæ°æ® List<ProductionProductMain> mains = productionProductMainService.lambdaQuery() .ge(ProductionProductMain::getCreateTime, start) .lt(ProductionProductMain::getCreateTime, end) .list(); List<Long> mainIds = mains.stream().map(ProductionProductMain::getId).collect(Collectors.toList()); List<Long> orderIds = mains.stream().map(ProductionProductMain::getProductOrderId).distinct().collect(Collectors.toList()); Map<Long, List<ProductionProductInput>> inputsByMain = new HashMap<>(); Map<Long, ProductOrder> orderMap = new HashMap<>(); Map<Long, ProductionOrderRoute> orderRouteMap = new HashMap<>(); Map<Long, List<ProductionOrderStructure>> structuresByOrder = new HashMap<>(); if (!mainIds.isEmpty()) { inputsByMain = productionProductInputService.lambdaQuery() .in(ProductionProductInput::getProductMainId, mainIds) .list() .stream() .collect(Collectors.groupingBy(ProductionProductInput::getProductMainId)); } if (!orderIds.isEmpty()) { orderMap = productOrderService.lambdaQuery() .in(ProductOrder::getId, orderIds) .list() .stream() .collect(Collectors.toMap(ProductOrder::getId, o -> o)); orderRouteMap = productionOrderRouteService.lambdaQuery() .in(ProductionOrderRoute::getOrderId, orderIds) .list() .stream() .collect(Collectors.toMap(ProductionOrderRoute::getOrderId, r -> r, (k1, k2) -> k1)); structuresByOrder = productionOrderStructureService.lambdaQuery() .in(ProductionOrderStructure::getOrderId, orderIds) .list() .stream() .collect(Collectors.groupingBy(ProductionOrderStructure::getOrderId)); } // è·åè½èæ°æ® LocalDate startDate = date; LocalDate endDate = date.plusMonths(1); List<EnergyConsumptionDetail> energyDetails = energyConsumptionDetailService.lambdaQuery() .ge(EnergyConsumptionDetail::getMeterReadingDate, startDate) .lt(EnergyConsumptionDetail::getMeterReadingDate, endDate) .list(); List<Energy> energies = energyService.list(); Map<String, Energy> energyMap = new HashMap<>(); for (Energy energy : energies) { if (energy.getEnergyName() != null) { energyMap.put(energy.getEnergyName(), energy); } } List<ProductMaterialSku> allSkus = productMaterialSkuService.list(); Map<Long, Long> skuToMaterialMap = allSkus.stream() .filter(sku -> sku.getProductId() != null) .collect(Collectors.toMap(ProductMaterialSku::getId, ProductMaterialSku::getProductId, (k1, k2) -> k1)); // 计ç®å®é å¼ for (ProductionSettlementDetailsDto detail : dtoList) { BigDecimal actualQty = BigDecimal.ZERO; BigDecimal actualTotalCost = BigDecimal.ZERO; if (ProductionSettlementEnum.isMaterialCost(detail.getCategory())) { if (detail.getProductId() != null) { for (ProductionProductMain main : mains) { ProductOrder order = orderMap.get(main.getProductOrderId()); if (order == null) continue; String targetType = detail.getProductType() != null ? detail.getProductType().trim() : ""; boolean typeMatch = "综å".equals(targetType); if (!typeMatch) { ProductionOrderRoute route = orderRouteMap.get(main.getProductOrderId()); if (route != null && route.getDictCode() != null) { String dictLabel = dictCodeMap.get(route.getDictCode()); if (dictLabel != null && dictLabel.trim().equals(targetType)) { typeMatch = true; } } } if (!typeMatch && order.getStrength() != null && order.getStrength().trim().equals(targetType)) { typeMatch = true; } if (typeMatch) { List<ProductionProductInput> mainInputs = inputsByMain.get(main.getId()); if (mainInputs != null) { for (ProductionProductInput input : mainInputs) { Long inputMaterialId = skuToMaterialMap.get(input.getProductId()); if (Objects.equals(inputMaterialId, detail.getProductId())) { BigDecimal rawQty = input.getQuantity() != null ? input.getQuantity() : BigDecimal.ZERO; List<ProductionOrderStructure> orderStructures = structuresByOrder.get(order.getId()); BigDecimal unitPrice = BigDecimal.ZERO; String unit = ""; if (orderStructures != null) { for (ProductionOrderStructure structure : orderStructures) { Long structureMaterialId = skuToMaterialMap.get(structure.getProductModelId()); if (Objects.equals(structureMaterialId, detail.getProductId())) { unitPrice = structure.getUnitPrice() != null ? structure.getUnitPrice() : BigDecimal.ZERO; unit = structure.getUnit(); break; } } } actualTotalCost = actualTotalCost.add(rawQty.multiply(unitPrice)); BigDecimal tonnage = UnitUtils.convertValueToTon(rawQty, unit); actualQty = actualQty.add(tonnage); } } } } } } detail.setActualQty(actualQty); detail.setActualTotal(actualTotalCost); if (actualQty.compareTo(BigDecimal.ZERO) > 0) { detail.setActualPrice(actualTotalCost.divide(actualQty, 15, RoundingMode.HALF_UP)); } else { detail.setActualPrice(BigDecimal.ZERO); } } else if ("è½èææ¬".equals(detail.getCategory())) { Energy energy = energyMap.get(detail.getSubjectName()); if (energy != null) { BigDecimal unitPrice = energy.getUnitPrice() != null ? energy.getUnitPrice() : BigDecimal.ZERO; for (EnergyConsumptionDetail eDetail : energyDetails) { if (Objects.equals(eDetail.getEnergyId(), energy.getId())) { actualQty = actualQty.add(eDetail.getDosage() != null ? eDetail.getDosage() : BigDecimal.ZERO); } } detail.setActualQty(actualQty); detail.setActualPrice(unitPrice); detail.setActualTotal(actualQty.multiply(unitPrice)); } else { detail.setActualQty(BigDecimal.ZERO); detail.setActualPrice(BigDecimal.ZERO); detail.setActualTotal(BigDecimal.ZERO); } } else { detail.setActualQty(BigDecimal.ZERO); detail.setActualPrice(BigDecimal.ZERO); detail.setActualTotal(BigDecimal.ZERO); } // å·®å¼å¼ç¾åæ¯è®¡ç® detail.setDiffQty(calculatePercentage(detail.getActualQty(), detail.getBudgetQty())); detail.setDiffPrice(calculatePercentage(detail.getActualPrice(), detail.getBudgetPrice())); detail.setDiffTotal(calculatePercentage(detail.getActualTotal(), detail.getBudgetTotal())); } return dtoList.stream().collect(Collectors.groupingBy(ProductionSettlementDetailsDto::getCategory)); } @Override public List<String> getProductTypes(ProductionSettlementDto dto) { String finalPeriodTime = parsePeriodTime(dto != null ? dto.getPeriodTime() : null); ProductionSettlementBatches batch = this.lambdaQuery() .eq(ProductionSettlementBatches::getPeriodTime, finalPeriodTime) .one(); if (batch == null) { return new ArrayList<>(); } return productionSettlementDetailsService.lambdaQuery() .eq(ProductionSettlementDetails::getBatchId, batch.getId()) .list() .stream() .map(ProductionSettlementDetails::getProductType) .filter(StringUtils::isNotBlank) .distinct() .collect(Collectors.toList()); } @Override public List<String> getSubjectNames(ProductionSettlementDto dto) { String finalPeriodTime = parsePeriodTime(dto != null ? dto.getPeriodTime() : null); ProductionSettlementBatches batch = this.lambdaQuery() .eq(ProductionSettlementBatches::getPeriodTime, finalPeriodTime) .one(); if (batch == null) { return new ArrayList<>(); } return productionSettlementDetailsService.lambdaQuery() .eq(ProductionSettlementDetails::getBatchId, batch.getId()) .list() .stream() .map(ProductionSettlementDetails::getSubjectName) .filter(StringUtils::isNotBlank) .distinct() .collect(Collectors.toList()); } /** * æ ¸ç®æä»½ï¼ä¸ºç©ºæ¶é»è®¤åå½åæï¼æ ¼å¼ä¸º yyyy-MM */ private String parsePeriodTime(String periodTime) { if (StringUtils.isBlank(periodTime)) { return YearMonth.now().format(DateTimeFormatter.ofPattern("yyyy-MM")); } try { return YearMonth.parse(periodTime, DateTimeFormatter.ofPattern("yyyy-MM")) .format(DateTimeFormatter.ofPattern("yyyy-MM")); } catch (Exception e) { throw new ServiceException("æ¥ææ ¼å¼é误ï¼è¯·ä½¿ç¨ yyyy-MM æ ¼å¼"); } } private String calculatePercentage(BigDecimal actual, BigDecimal budget) { if (budget == null || budget.compareTo(BigDecimal.ZERO) == 0) { return actual.compareTo(BigDecimal.ZERO) > 0 ? "100%" : "0%"; } BigDecimal diff = actual.subtract(budget); BigDecimal percentage = diff.divide(budget, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")); return percentage.stripTrailingZeros().toPlainString() + "%"; } @Override public ProductionSettlementTotalDto getTotalCosts(ProductionSettlementDto dto) { // å¤ç¨ getSettlement è·åå«å®é å¼çæç»å表 Map<String, List<ProductionSettlementDetailsDto>> settlementMap = getSettlement(dto); List<ProductionSettlementDetailsDto> allDetails = settlementMap.values().stream() .flatMap(List::stream) .collect(Collectors.toList()); // æ dto ä¸çå ¶ä½æ¡ä»¶å¨å åä¸è¿æ»¤ if (dto != null) { if (StringUtils.isNotBlank(dto.getProductType())) { String targetType = dto.getProductType().trim(); allDetails = allDetails.stream() .filter(d -> targetType.equals(d.getProductType() != null ? d.getProductType().trim() : "")) .collect(Collectors.toList()); } if (StringUtils.isNotBlank(dto.getSubjectName())) { String targetSubject = dto.getSubjectName().trim(); allDetails = allDetails.stream() .filter(d -> targetSubject.equals(d.getSubjectName() != null ? d.getSubjectName().trim() : "")) .collect(Collectors.toList()); } if (StringUtils.isNotBlank(dto.getCostType())) { String targetCostType = dto.getCostType().trim(); allDetails = allDetails.stream() .filter(d -> targetCostType.equals(d.getCategory() != null ? d.getCategory().trim() : "")) .collect(Collectors.toList()); } } // æ±æ»æ åææ¬ä¸å®é ææ¬ BigDecimal budgetTotal = allDetails.stream() .map(d -> d.getBudgetTotal() != null ? d.getBudgetTotal() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal actualTotal = allDetails.stream() .map(d -> d.getActualTotal() != null ? d.getActualTotal() : BigDecimal.ZERO) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal diffTotal = actualTotal.subtract(budgetTotal); // å·®å¼çï¼å¸¦æ£è´å· String diffRate; if (budgetTotal.compareTo(BigDecimal.ZERO) == 0) { diffRate = actualTotal.compareTo(BigDecimal.ZERO) > 0 ? "+100%" : "0%"; } else { BigDecimal rate = diffTotal.divide(budgetTotal, 4, RoundingMode.HALF_UP) .multiply(new BigDecimal("100")); String sign = rate.compareTo(BigDecimal.ZERO) >= 0 ? "+" : ""; diffRate = sign + rate.stripTrailingZeros().toPlainString() + "%"; } ProductionSettlementTotalDto result = new ProductionSettlementTotalDto(); result.setBudgetTotal(budgetTotal); result.setActualTotal(actualTotal); result.setDiffTotal(diffTotal); result.setDiffRate(diffRate); return result; } } src/main/java/com/ruoyi/productionPlan/service/impl/ProductionPlanServiceImpl.java
@@ -120,6 +120,10 @@ // æ¥è¯¢ä¸»ç产计å List<ProductionPlanDto> plans = productionPlanMapper.selectWithMaterialByIds(productionPlanDto.getIds()); if (plans == null || plans.isEmpty()) { throw new ServiceException("ä¸å失败,ç产计åä¸åå¨"); } // æ ¡éªæ¯å¦åå¨ä¸åç产ååç§° String firstProductName = plans.get(0).getProductName(); if (plans.stream().anyMatch(p -> p.getProductName() == null || !p.getProductName().equals(firstProductName))) { @@ -148,7 +152,7 @@ productOrder.setPlanCompleteTime(productionPlanDto.getPlanCompleteTime()); productOrder.setStatus(ProductOrderStatusEnum.WAIT.getCode()); productOrder.setStrength(productionPlanDto.getStrength()); productOrder.setProductMaterialSkuId(productionPlanDto.getProductMaterialSkuId()); productOrder.setProductMaterialSkuId(plans.get(0).getProductMaterialSkuId()); Long orderId = productOrderService.insertProductOrder(productOrder); @@ -230,9 +234,17 @@ @Override @Transactional(rollbackFor = Exception.class) public boolean update(ProductionPlanDto productionPlanDto) { if (productionPlanDto == null) { throw new ServiceException("ç¼è¾å¤±è´¥,æ°æ®ä¸è½ä¸ºç©º"); } ProductionPlan productionPlan = getById(productionPlanDto.getId()); if (productionPlan == null) { throw new ServiceException("ç¼è¾å¤±è´¥,主ç产计åä¸åå¨"); } // å·²ä¸åç¶æï¼ä¸è½ç¼è¾ if (productionPlanDto.getStatus() != 0) { throw new BaseException("å·²ä¸åæé¨åä¸åç¶æï¼ä¸è½ç¼è¾"); if (productionPlan.getStatus() != 0) { throw new BaseException("ç¼è¾å¤±è´¥,该ç产计åå·²ä¸åæé¨åä¸åç¶æ,ç¦æ¢ç¼è¾"); } // æ¥è¯¢æ¯å¦æå ³è订å boolean hasProductOrderPlan = productOrderPlanMapper.selectList(Wrappers.<ProductOrderPlan>lambdaQuery().eq(ProductOrderPlan::getProductionPlanId, productionPlanDto.getId())).stream().anyMatch(p -> p.getProductOrderId() != null); src/main/java/com/ruoyi/productionPlan/service/impl/SalesDeliveryServiceImpl.java
@@ -7,7 +7,10 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.framework.config.AliDingConfig; import com.ruoyi.framework.util.AliDingUtils; import com.ruoyi.production.pojo.ProductMaterial; import com.ruoyi.production.pojo.ProductMaterialSku; import com.ruoyi.production.service.ProductMaterialService; import com.ruoyi.production.service.ProductMaterialSkuService; import com.ruoyi.productionPlan.enums.DataSourceTypeEnum; import com.ruoyi.productionPlan.pojo.ProductionPlan; import com.ruoyi.productionPlan.pojo.SalesDelivery; @@ -41,6 +44,12 @@ @Autowired private SalesDeliveryMapper salesDeliveryMapper; @Autowired private ProductMaterialSkuService productMaterialSkuService; @Autowired private ProductMaterialService productMaterialService; @Autowired private AliDingConfig aliDingConfig; @@ -125,18 +134,24 @@ salesDelivery.setSalesman(formData.getString("textField_ladnkyu1"));//ä¸å¡å salesDelivery.setDeliveryMethod(formData.getString("radioField_ldoc0027"));//åè´§æ¹å¼ String materialCode = row.getString("textField_l92dg1tc"); // æ ¹æ®ç©æç¼ç æ¥è¯¢ç©æä¿¡æ¯è¡¨ï¼å ³èç©æID // if (StringUtils.isNotEmpty(materialCode)) { // LambdaQueryWrapper<ProductMaterialSku> skuQueryWrapper = new LambdaQueryWrapper<>(); // skuQueryWrapper.eq(ProductMaterialSku::getMaterialCode, materialCode); // ProductMaterialSku sku = productMaterialSkuService.getOne(skuQueryWrapper); // if (sku != null) { // salesDelivery.setProductMaterialSkuId(sku.getId()); // } // } String productName = row.getString("textField_l96srw8x"); String model = row.getString("textField_l9tljfl8"); // 妿åå为空ç¼ç ä¸ä¸ºç©º if (StringUtils.isNotEmpty(materialCode) && StringUtils.isEmpty(productName)) { LambdaQueryWrapper<ProductMaterialSku> skuQueryWrapper = new LambdaQueryWrapper<>(); skuQueryWrapper.eq(ProductMaterialSku::getMaterialCode, materialCode); ProductMaterialSku sku = productMaterialSkuService.getOne(skuQueryWrapper); if (sku != null) { ProductMaterial material = productMaterialService.getById(sku.getProductId()); productName=material.getProductName(); model=sku.getModel(); } }else if (StringUtils.isEmpty(productName) && StringUtils.isEmpty(materialCode)){ continue; } salesDelivery.setMaterialCode(materialCode);//ç©æç¼ç salesDelivery.setProductName(row.getString("textField_l96srw8x"));//产ååç§° salesDelivery.setModel(row.getString("textField_l9tljfl8"));//产åè§æ ¼ salesDelivery.setProductName(productName);//产ååç§° salesDelivery.setModel(model);//产åè§æ ¼ salesDelivery.setVolume(row.getBigDecimal("numberField_kt8b0qsg_value"));//æ¹é salesDelivery.setUnitPrice(row.getBigDecimal("numberField_la0tb2x9_value"));//åä»· salesDelivery.setPrice(row.getBigDecimal("numberField_l9w2piwf"));//ä»·æ ¼ src/main/java/com/ruoyi/productionPlan/task/SalesDeliveryTask.java
@@ -16,7 +16,7 @@ @Autowired private SalesDeliveryService salesDeliveryService; @Scheduled(cron = "0 0 0 * * ?") @Scheduled(cron = "0 22 10 * * ?") public void syncSalesDeliveryJob() { salesDeliveryService.syncSalesDeliveryJob(); }