doc/ÄþÏÄ-ÖÐÊ¢½¨²Ä.sql
@@ -468,4 +468,46 @@ KEY `idx_order_id` (`order_id`) USING BTREE ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT ='ç产订åç»å®çå·¥èºè·¯çº¿è¡¨'; COLLATE = utf8mb4_0900_ai_ci COMMENT ='ç产订åç»å®çå·¥èºè·¯çº¿è¡¨'; CREATE TABLE `production_settlement_batches` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', `period_time` date DEFAULT NULL COMMENT 'æ ¸ç®å½å±æä»½', `batch_name` varchar(255) DEFAULT NULL COMMENT 'æ¹æ¬¡åç§°', `status` int DEFAULT '0' COMMENT 'ç¶æï¼0-ä» é¢ç®ï¼1-ç»ç®è®¡ç®ä¸ï¼2-已宿ç»ç®ï¼3-å·²éå®', `create_user` varchar(255) DEFAULT NULL COMMENT 'å¯¼å ¥ç¨æ·', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'åå»ºæ¥æ', `tenant_id` bigint DEFAULT NULL COMMENT 'ç§æ·ID', PRIMARY KEY (`id`), KEY `idx_period` (`period_time`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨'; CREATE TABLE `production_settlement_details` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®ID', `batch_id` bigint NOT NULL COMMENT 'å ³èæ ¸ç®æ¹æ¬¡è¡¨ID', `product_id` bigint DEFAULT NULL COMMENT '产åID', `product_type` varchar(100) DEFAULT NULL COMMENT '产åç±»ååç§°', `category` varchar(100) DEFAULT NULL COMMENT 'è´¹ç¨ç±»å«', `subject_name` varchar(100) DEFAULT NULL COMMENT 'ç§ç®åç§°', `budget_qty` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'é¢ç®èé', `budget_price` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'é¢ç®åä»·', `budget_total` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'é¢ç®æ»ææ¬', `actual_qty` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'å®é èé', `actual_price` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'å®é åä»·', `actual_total` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'å®é æ»ææ¬', `diff_qty` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'èéå·®å¼', `diff_price` decimal(20, 15) DEFAULT '0.000000000000000' COMMENT 'åä»·å·®å¼', `diff_total` DECIMAL(20, 15) DEFAULT '0.000000000000000' COMMENT 'æ»ææ¬å·®å¼', `tenant_id` bigint DEFAULT NULL COMMENT 'ç§æ·ID', PRIMARY KEY (`id`), KEY `idx_batch_id` (`batch_id`), KEY `idx_product_id` (`product_id`) COMMENT 'æ¹ä¾¿æäº§åæ¥è¯¢å岿æ¬å¯¹æ¯' ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT ='çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨'; src/main/java/com/ruoyi/production/controller/ProductionSettlementBatchesController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ package com.ruoyi.production.controller; import com.ruoyi.framework.web.domain.AjaxResult; 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.multipart.MultipartFile; import java.time.LocalDate; /** * <p> * çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ å端æ§å¶å¨ * </p> * * @author deslrey * @since 2026-03-30 */ @RestController @RequestMapping("/productionSettlementBatches") @ApiModel(value = "ProductionSettlementBatchesControllerç±»", description = "çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ å端æ§å¶å¨") public class ProductionSettlementBatchesController { @Autowired private IProductionSettlementBatchesService productionSettlementBatchesService; @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); return AjaxResult.success(); } } src/main/java/com/ruoyi/production/controller/ProductionSettlementDetailsController.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,22 @@ package com.ruoyi.production.controller; import io.swagger.annotations.ApiModel; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * <p> * çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ å端æ§å¶å¨ * </p> * * @author deslrey * @since 2026-03-30 */ @RestController @RequestMapping("/production-settlement-details") @ApiModel(value = "ProductionSettlementDetailsControllerç±»", description = "çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ å端æ§å¶å¨") public class ProductionSettlementDetailsController { } src/main/java/com/ruoyi/production/dto/SettlementImportDto.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ package com.ruoyi.production.dto; import com.ruoyi.framework.aspectj.lang.annotation.Excel; 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/03/30 */ @Data @ApiModel(value = "SettlementImportDto", description = "çäº§ææ¬æ ¸ç®å¯¹æ¯æä»¶å¯¼å ¥Dto") public class SettlementImportDto { @Excel(name = "产åç±»å") @ApiModelProperty("产åç±»å") private String productType; @Excel(name = "ç§ç®åç§°") @ApiModelProperty("ç§ç®åç§°") private String category; @Excel(name = "ç§ç®") @ApiModelProperty("ç§ç®") private String subjectName; @Excel(name = "ææ¬é¢ç®") @ApiModelProperty("ææ¬é¢ç®") private BigDecimal budgetTotal; @Excel(name = "èéé¢ç®") @ApiModelProperty("èéé¢ç®") private BigDecimal budgetQty; @Excel(name = "åä»·é¢ç®") @ApiModelProperty("åä»·é¢ç®") private BigDecimal budgetPrice; } src/main/java/com/ruoyi/production/mapper/ProductionSettlementBatchesMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.production.mapper; import com.ruoyi.production.pojo.ProductionSettlementBatches; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * <p> * çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ Mapper æ¥å£ * </p> * * @author deslrey * @since 2026-03-30 */ public interface ProductionSettlementBatchesMapper extends BaseMapper<ProductionSettlementBatches> { } src/main/java/com/ruoyi/production/mapper/ProductionSettlementDetailsMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.production.mapper; import com.ruoyi.production.pojo.ProductionSettlementDetails; import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * <p> * çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ Mapper æ¥å£ * </p> * * @author deslrey * @since 2026-03-30 */ public interface ProductionSettlementDetailsMapper extends BaseMapper<ProductionSettlementDetails> { } src/main/java/com/ruoyi/production/pojo/ProductionSettlementBatches.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,55 @@ package com.ruoyi.production.pojo; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; 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; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * <p> * çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ * </p> * * @author deslrey * @since 2026-03-30 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("production_settlement_batches") @ApiModel(value="ProductionSettlementBatches对象", description="çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨") public class ProductionSettlementBatches implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "主é®ID") @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty(value = "æ ¸ç®å½å±æä»½") private LocalDate periodTime; @ApiModelProperty(value = "æ¹æ¬¡åç§°") private String batchName; @ApiModelProperty(value = "ç¶æï¼0-ä» é¢ç®ï¼1-ç»ç®è®¡ç®ä¸ï¼2-已宿ç»ç®ï¼3-å·²éå®") private Integer status; @ApiModelProperty(value = "å¯¼å ¥ç¨æ·") private String createUser; @ApiModelProperty(value = "åå»ºæ¥æ") private LocalDateTime createTime; @ApiModelProperty(value = "ç§æ·ID") private Long tenantId; } src/main/java/com/ruoyi/production/pojo/ProductionSettlementDetails.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,81 @@ 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 java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * <p> * çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ * </p> * * @author deslrey * @since 2026-03-30 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("production_settlement_details") @ApiModel(value="ProductionSettlementDetails对象", description="çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨") public class ProductionSettlementDetails implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "主é®ID") @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty(value = "å ³èæ ¸ç®æ¹æ¬¡è¡¨ID") private Long batchId; @ApiModelProperty(value = "产åID") private Long productId; @ApiModelProperty(value = "产åç±»ååç§°") private String productType; @ApiModelProperty(value = "è´¹ç¨ç±»å«") private String category; @ApiModelProperty(value = "ç§ç®åç§°") private String subjectName; @ApiModelProperty(value = "é¢ç®èé") private BigDecimal budgetQty; @ApiModelProperty(value = "é¢ç®åä»·") private BigDecimal budgetPrice; @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") private Long tenantId; } src/main/java/com/ruoyi/production/service/IProductionSettlementBatchesService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,21 @@ package com.ruoyi.production.service; import com.ruoyi.production.pojo.ProductionSettlementBatches; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; /** * <p> * çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ æå¡ç±» * </p> * * @author deslrey * @since 2026-03-30 */ public interface IProductionSettlementBatchesService extends IService<ProductionSettlementBatches> { void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName); } src/main/java/com/ruoyi/production/service/IProductionSettlementDetailsService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ package com.ruoyi.production.service; import com.ruoyi.production.pojo.ProductionSettlementDetails; import com.baomidou.mybatisplus.extension.service.IService; /** * <p> * çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ æå¡ç±» * </p> * * @author deslrey * @since 2026-03-30 */ public interface IProductionSettlementDetailsService extends IService<ProductionSettlementDetails> { } src/main/java/com/ruoyi/production/service/impl/ProductionCostServiceImpl.java
@@ -179,12 +179,24 @@ private <T> IPage<T> getMemoryPage(Page<T> page, List<T> list) { int total = list.size(); int size = (int) page.getSize(); int current = (int) page.getCurrent(); int fromIndex = (current - 1) * size; int toIndex = Math.min(fromIndex + size, total); long size = page.getSize(); long current = page.getCurrent(); List<T> subList = (fromIndex < total && fromIndex >= 0) ? list.subList(fromIndex, toIndex) : new ArrayList<>(); if (size == -1 || current == -1) { page.setTotal(total); page.setRecords(list); return page; } int fromIndex = (int) ((current - 1) * size); int toIndex = Math.min(fromIndex + (int) size, total); List<T> subList; if (fromIndex >= 0 && fromIndex < total) { subList = list.subList(fromIndex, toIndex); } else { subList = new ArrayList<>(); } page.setTotal(total); page.setRecords(subList); src/main/java/com/ruoyi/production/service/impl/ProductionSettlementBatchesServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,88 @@ package com.ruoyi.production.service.impl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.production.dto.SettlementImportDto; import com.ruoyi.production.pojo.ProductionSettlementBatches; import com.ruoyi.production.mapper.ProductionSettlementBatchesMapper; import com.ruoyi.production.pojo.ProductionSettlementDetails; import com.ruoyi.production.service.IProductionSettlementBatchesService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.production.service.IProductionSettlementDetailsService; 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.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; /** * <p> * çäº§ææ¬æ ¸ç®æ¹æ¬¡ä¸»è¡¨ æå¡å®ç°ç±» * </p> * * @author deslrey * @since 2026-03-30 */ @Service public class ProductionSettlementBatchesServiceImpl extends ServiceImpl<ProductionSettlementBatchesMapper, ProductionSettlementBatches> implements IProductionSettlementBatchesService { @Autowired private IProductionSettlementDetailsService productionSettlementDetailsService; @Override @Transactional(rollbackFor = Exception.class) public void importProductionSettlement(MultipartFile file, LocalDate periodTime, String batchName) { if (file == null || file.isEmpty()) { throw new ServiceException("å¯¼å ¥å¤±è´¥ï¼æä»¶ä¸è½ä¸ºç©º"); } List<SettlementImportDto> list; try { ExcelUtil<SettlementImportDto> util = new ExcelUtil<>(SettlementImportDto.class); list = util.importExcel(file.getInputStream()); } catch (Exception e) { log.error("å¯¼å ¥çäº§ææ¬æ ¸ç®å¤±è´¥", e); throw new ServiceException("è§£æExcelæä»¶å¤±è´¥ï¼" + e.getMessage()); } if (StringUtils.isEmpty(list)) { throw new ServiceException("å¯¼å ¥æ°æ®ä¸è½ä¸ºç©ºï¼"); } 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.setCreateUser(SecurityUtils.getUsername()); this.save(batch); List<ProductionSettlementDetails> detailList = list.stream().map(dto -> { 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()); productionSettlementDetailsService.saveBatch(detailList); } } src/main/java/com/ruoyi/production/service/impl/ProductionSettlementDetailsServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.ruoyi.production.service.impl; import com.ruoyi.production.pojo.ProductionSettlementDetails; import com.ruoyi.production.mapper.ProductionSettlementDetailsMapper; import com.ruoyi.production.service.IProductionSettlementDetailsService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * çäº§ææ¬æ ¸ç®å¯¹æ¯æç»è¡¨ æå¡å®ç°ç±» * </p> * * @author deslrey * @since 2026-03-30 */ @Service public class ProductionSettlementDetailsServiceImpl extends ServiceImpl<ProductionSettlementDetailsMapper, ProductionSettlementDetails> implements IProductionSettlementDetailsService { } src/main/resources/mapper/production/ProductionSettlementBatchesMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.production.mapper.ProductionSettlementBatchesMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionSettlementBatches"> <id column="id" property="id" /> <result column="period_time" property="periodTime" /> <result column="batch_name" property="batchName" /> <result column="status" property="status" /> <result column="create_user" property="createUser" /> <result column="create_time" property="createTime" /> <result column="tenant_id" property="tenantId" /> </resultMap> </mapper> src/main/resources/mapper/production/ProductionSettlementDetailsMapper.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,25 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.production.mapper.ProductionSettlementDetailsMapper"> <!-- éç¨æ¥è¯¢æ å°ç»æ --> <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionSettlementDetails"> <id column="id" property="id" /> <result column="batch_id" property="batchId" /> <result column="product_id" property="productId" /> <result column="product_type" property="productType" /> <result column="category" property="category" /> <result column="subject_name" property="subjectName" /> <result column="budget_qty" property="budgetQty" /> <result column="budget_price" property="budgetPrice" /> <result column="budget_total" property="budgetTotal" /> <result column="actual_qty" property="actualQty" /> <result column="actual_price" property="actualPrice" /> <result column="actual_total" property="actualTotal" /> <result column="diff_qty" property="diffQty" /> <result column="diff_price" property="diffPrice" /> <result column="diff_total" property="diffTotal" /> <result column="tenant_id" property="tenantId" /> </resultMap> </mapper>