| | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.ai.assistant.Assistant; |
| | | import com.ruoyi.approve.mapper.ApprovalInstanceMapper; |
| | | import com.ruoyi.approve.pojo.ApprovalInstance; |
| | | import com.ruoyi.approve.service.ApprovalInstanceService; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.basic.pojo.SupplierManage; |
| | | import com.ruoyi.basic.service.ICustomerService; |
| | | import com.ruoyi.basic.service.ISupplierService; |
| | | import com.ruoyi.common.enums.ReviewStatusEnum; |
| | | import com.ruoyi.mock.dto.DataGenerateRequest; |
| | | import com.ruoyi.mock.prompt.MockDataPrompt; |
| | | import com.ruoyi.mock.service.DataGenerateService; |
| | |
| | | import com.ruoyi.production.service.ProductionOrderService; |
| | | import com.ruoyi.production.service.ProductionPlanService; |
| | | import com.ruoyi.purchase.dto.PurchaseLedgerDto; |
| | | import com.ruoyi.purchase.pojo.PurchaseLedger; |
| | | import com.ruoyi.purchase.service.IPurchaseLedgerService; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.quality.pojo.QualityTestStandard; |
| | | import com.ruoyi.quality.pojo.QualityTestStandardBinding; |
| | | import com.ruoyi.quality.service.IQualityInspectService; |
| | | import com.ruoyi.quality.service.IQualityTestStandardService; |
| | | import com.ruoyi.quality.service.QualityTestStandardBindingService; |
| | | import com.ruoyi.sales.dto.SalesLedgerDto; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.sales.service.ISalesLedgerService; |
| | | import com.ruoyi.stock.dto.StockInventoryDto; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Slf4j |
| | |
| | | private final ProductionPlanService productionPlanService; |
| | | private final ProductionOrderService productionOrderService; |
| | | private final StockInventoryService stockInventoryService; |
| | | |
| | | // 采购完整流程需要的service |
| | | private final ApprovalInstanceService approvalInstanceService; |
| | | private final ApprovalInstanceMapper approvalInstanceMapper; |
| | | private final IQualityInspectService qualityInspectService; |
| | | private final StockInRecordService stockInRecordService; |
| | | |
| | | @Override |
| | | public DataGenerateResult generate(DataGenerateRequest request) { |
| | |
| | | totalGenerated += s.getSuccessCount(); |
| | | } |
| | | if (grouped.containsKey("purchaseLedger")) { |
| | | ModuleSummary s = createPurchaseLedgers(grouped.get("purchaseLedger"), supplierNameToId); |
| | | ModuleSummary s = createPurchaseLedgers(grouped.get("purchaseLedger"), supplierNameToId, |
| | | request.getAdditionalInfo(), request.getDateEnd()); |
| | | summaries.add(s); |
| | | totalGenerated += s.getSuccessCount(); |
| | | } |
| | |
| | | return summary("sales", "销售台账", items.size(), success, fail); |
| | | } |
| | | |
| | | private ModuleSummary createPurchaseLedgers(List<JSONObject> items, Map<String, Long> supplierNameToId) { |
| | | private ModuleSummary createPurchaseLedgers(List<JSONObject> items, Map<String, Long> supplierNameToId, |
| | | String additionalInfo, String dateEnd) { |
| | | // 是否需要质检,从补充信息判断,默认不需要 |
| | | boolean needQualityInspect = additionalInfo != null |
| | | && (additionalInfo.contains("质检") || additionalInfo.contains("需要检验")); |
| | | int success = 0, fail = 0; |
| | | for (JSONObject item : items) { |
| | | try { |
| | |
| | | dto.setProjectName(item.getString("projectName")); |
| | | dto.setContractAmount(item.getBigDecimal("contractAmount")); |
| | | dto.setPaymentMethod(item.getString("paymentMethod")); |
| | | |
| | | String entryDateStr = item.getString("entryDate"); |
| | | LocalDate entryDate = null; |
| | | if (item.containsKey("entryDate")) { |
| | | dto.setEntryDate(java.sql.Date.valueOf(item.getString("entryDate"))); |
| | | entryDate = LocalDate.parse(entryDateStr); |
| | | dto.setEntryDate(java.sql.Date.valueOf(entryDateStr)); |
| | | } |
| | | if (item.containsKey("executionDate")) { |
| | | dto.setExecutionDate(java.sql.Date.valueOf(item.getString("executionDate"))); |
| | |
| | | slp.setTaxRate(pd.getBigDecimal("taxRate")); |
| | | slp.setUnit(pd.getString("unit")); |
| | | slp.setType(2); |
| | | // 是否质检:从补充信息判断,默认不需要 |
| | | slp.setIsChecked(needQualityInspect); |
| | | if (pd.containsKey("taxExclusiveTotalPrice")) { |
| | | slp.setTaxExclusiveTotalPrice(pd.getBigDecimal("taxExclusiveTotalPrice")); |
| | | } else if (pd.getBigDecimal("taxInclusiveTotalPrice") != null && pd.getBigDecimal("taxRate") != null) { |
| | |
| | | dto.setProductData(products); |
| | | } |
| | | purchaseLedgerService.addOrEditPurchase(dto); |
| | | // 通过合同号找到刚创建的采购台账 |
| | | PurchaseLedger savedLedger = purchaseLedgerService.getOne( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<PurchaseLedger>() |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, dto.getPurchaseContractNumber()) |
| | | .last("limit 1")); |
| | | if (savedLedger != null) { |
| | | // 走完整流程:审核通过 → 质检(可选) → 入库 + 入库审核通过 |
| | | processPurchaseFullFlow(savedLedger, needQualityInspect, entryDate, dateEnd); |
| | | } |
| | | success++; |
| | | } catch (Exception e) { |
| | | log.warn("创建采购台账失败: {}", e.getMessage()); |
| | |
| | | return summary("purchase", "采购台账", items.size(), success, fail); |
| | | } |
| | | |
| | | /** |
| | | * 采购完整流程: 审核通过 → 质检(可选) → 入库审核通过 |
| | | */ |
| | | private void processPurchaseFullFlow(PurchaseLedger purchaseLedger, boolean needQualityInspect, |
| | | LocalDate entryDate, String dateEnd) { |
| | | try { |
| | | // 1. 审批自动通过 |
| | | ApprovalInstance approvalInstance = approvalInstanceMapper.selectOne( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalInstance>() |
| | | .eq(ApprovalInstance::getBusinessId, purchaseLedger.getId()) |
| | | .eq(ApprovalInstance::getBusinessType, 5L) |
| | | .eq(ApprovalInstance::getDeleted, 0) |
| | | .orderByDesc(ApprovalInstance::getId) |
| | | .last("limit 1")); |
| | | if (approvalInstance != null) { |
| | | // 结算审批开始时间:基于录入日期,随机推0-3天 |
| | | LocalDate baseDate = entryDate != null ? entryDate : LocalDate.now(); |
| | | LocalDate approveDate = baseDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4)); |
| | | // 使用autoApprove完成审批 |
| | | approvalInstanceService.autoApprove(approvalInstance.getId()); |
| | | log.info("采购台账[{}]审批通过, 审批日期: {}", purchaseLedger.getPurchaseContractNumber(), approveDate); |
| | | } |
| | | |
| | | // 2. 质检流程(如果需要质检) |
| | | if (needQualityInspect) { |
| | | processQualityInspect(purchaseLedger, entryDate, dateEnd); |
| | | } |
| | | |
| | | // 3. 入库审批通过 |
| | | processStockInApprove(purchaseLedger, dateEnd); |
| | | |
| | | } catch (Exception e) { |
| | | log.warn("采购完整流程处理失败[{}]: {}", purchaseLedger.getPurchaseContractNumber(), e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 质检: 找到采购关联的质检单,自动提交为合格 |
| | | */ |
| | | private void processQualityInspect(PurchaseLedger purchaseLedger, LocalDate entryDate, String dateEnd) { |
| | | try { |
| | | List<QualityInspect> inspectList = qualityInspectService.list( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<QualityInspect>() |
| | | .eq(QualityInspect::getPurchaseLedgerId, purchaseLedger.getId())); |
| | | for (QualityInspect qi : inspectList) { |
| | | if (qi.getInspectState() == null || qi.getInspectState() == 0) { |
| | | qualityInspectService.autoSubmit(qi.getId()); |
| | | log.info("采购台账[{}]质检单[{}]自动提交合格", purchaseLedger.getPurchaseContractNumber(), qi.getId()); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("质检流程处理失败[{}]: {}", purchaseLedger.getPurchaseContractNumber(), e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 入库审核: 找到入库记录并审批通过 |
| | | */ |
| | | private void processStockInApprove(PurchaseLedger purchaseLedger, String dateEnd) { |
| | | try { |
| | | List<com.ruoyi.stock.pojo.StockInRecord> stockRecords = stockInRecordService.list( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>() |
| | | .eq(com.ruoyi.stock.pojo.StockInRecord::getRecordId, purchaseLedger.getId()) |
| | | .eq(com.ruoyi.stock.pojo.StockInRecord::getRecordType, |
| | | String.valueOf(com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode()))); |
| | | // 如果按PURCHASE_STOCK_IN找不到,尝试CUSTOMIZATION_UNSTOCK_OUT(质检合格入库) |
| | | if (stockRecords.isEmpty()) { |
| | | stockRecords = stockInRecordService.list( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>() |
| | | .eq(com.ruoyi.stock.pojo.StockInRecord::getRecordId, purchaseLedger.getId()) |
| | | .eq(com.ruoyi.stock.pojo.StockInRecord::getRecordType, |
| | | String.valueOf(com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()))); |
| | | } |
| | | // 也尝试按质检单ID查找(质检单的recordId是质检单ID) |
| | | for (QualityInspect qi : qualityInspectService.list( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<QualityInspect>() |
| | | .eq(QualityInspect::getPurchaseLedgerId, purchaseLedger.getId()))) { |
| | | List<com.ruoyi.stock.pojo.StockInRecord> qiRecords = stockInRecordService.list( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>() |
| | | .eq(com.ruoyi.stock.pojo.StockInRecord::getRecordId, qi.getId())); |
| | | stockRecords.addAll(qiRecords); |
| | | } |
| | | // 去重 |
| | | stockRecords = stockRecords.stream() |
| | | .collect(Collectors.toMap(com.ruoyi.stock.pojo.StockInRecord::getId, r -> r, (a, b) -> a)) |
| | | .values().stream().collect(Collectors.toList()); |
| | | |
| | | if (!stockRecords.isEmpty()) { |
| | | List<Long> recordIds = stockRecords.stream() |
| | | .filter(r -> r.getApprovalStatus() == null || r.getApprovalStatus() == 0) |
| | | .map(com.ruoyi.stock.pojo.StockInRecord::getId) |
| | | .collect(Collectors.toList()); |
| | | if (!recordIds.isEmpty()) { |
| | | stockInRecordService.batchApprove(recordIds, ReviewStatusEnum.APPROVED.getCode()); |
| | | log.info("采购台账[{}]入库审批通过, 入库记录数: {}", purchaseLedger.getPurchaseContractNumber(), recordIds.size()); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("入库审批失败[{}]: {}", purchaseLedger.getPurchaseContractNumber(), e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | private ModuleSummary createProductionPlans(List<JSONObject> items) { |
| | | int success = 0, fail = 0; |
| | | for (JSONObject item : items) { |