From 705c8e5c67e823b531c432afea95dcf5d0f0d258 Mon Sep 17 00:00:00 2001 From: maxiangong <298222784@qq.com> Date: Fri, 8 May 2026 14:47:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=96=E5=8D=8F=E7=BB=93=E7=AE=97=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oem/OemStatementTaskProcessor.java | 33 + .../desk/oem/feign/IOemStatementClient.java | 18 + .../oem/pojo/entity/OemStatementEntity.java | 3 + .../entity/OemStatementTaskLogEntity.java | 30 + .../desk/oem/pojo/vo/StatementVO.java | 15 + .../springblade/desk/util/PriceMatcher.java | 11 + .../desk/oem/feign/OemStatementClient.java | 19 + .../desk/oem/mapper/OemStatementMapper.java | 8 + .../desk/oem/mapper/OemStatementMapper.xml | 80 ++ .../oem/mapper/OemStatementTaskLogMapper.java | 18 + .../oem/mapper/OemStatementTaskLogMapper.xml | 23 + .../oem/service/IOemStatementService.java | 5 + .../service/IOemStatementTaskLogService.java | 24 + .../service/impl/OemStatementServiceImpl.java | 901 ++++++++++++++---- .../impl/OemStatementTaskLogServiceImpl.java | 26 + 15 files changed, 1044 insertions(+), 170 deletions(-) create mode 100644 blade-ops/blade-job/src/main/java/org/springblade/job/processor/oem/OemStatementTaskProcessor.java create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/feign/IOemStatementClient.java create mode 100644 blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementTaskLogEntity.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/oem/feign/OemStatementClient.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.xml create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementTaskLogService.java create mode 100644 blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementTaskLogServiceImpl.java diff --git a/blade-ops/blade-job/src/main/java/org/springblade/job/processor/oem/OemStatementTaskProcessor.java b/blade-ops/blade-job/src/main/java/org/springblade/job/processor/oem/OemStatementTaskProcessor.java new file mode 100644 index 00000000..feeaecfa --- /dev/null +++ b/blade-ops/blade-job/src/main/java/org/springblade/job/processor/oem/OemStatementTaskProcessor.java @@ -0,0 +1,33 @@ +package org.springblade.job.processor.oem; + +import jakarta.annotation.Resource; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springblade.desk.oem.feign.IOemStatementClient; +import org.springframework.stereotype.Component; +import tech.powerjob.worker.core.processor.ProcessResult; +import tech.powerjob.worker.core.processor.TaskContext; +import tech.powerjob.worker.core.processor.sdk.BasicProcessor; + +/** + * 外协结算单生成定时任务 + * + * @author BladeX + * @since 2026-05-08 + */ +@Component +@Data +@Slf4j +public class OemStatementTaskProcessor implements BasicProcessor { + + @Resource + private IOemStatementClient oemStatementClient; + + @Override + public ProcessResult process(TaskContext taskContext) throws Exception { + log.info("========== 开始外协结算单生成定时任务 =========="); + oemStatementClient.generateSettlement(); + log.info("========== 结束外协结算单生成定时任务 =========="); + return new ProcessResult(true); + } +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/feign/IOemStatementClient.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/feign/IOemStatementClient.java new file mode 100644 index 00000000..4d960190 --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/feign/IOemStatementClient.java @@ -0,0 +1,18 @@ +package org.springblade.desk.oem.feign; + +import org.springblade.core.launch.constant.AppConstant; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient( + value = AppConstant.APPLICATION_DESK_NAME +) +public interface IOemStatementClient { + + String API_PREFIX = "/feign/client/oem-statement"; + String GENERATE_SETTLEMENT = API_PREFIX + "/generate-settlement"; + + @GetMapping(GENERATE_SETTLEMENT) + void generateSettlement(); + +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementEntity.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementEntity.java index 465a8cb1..a61b4ed2 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementEntity.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementEntity.java @@ -134,4 +134,7 @@ public class OemStatementEntity extends BaseEntity { @Schema(description = "备注") private String memo; + @Schema(description = "标准工序代码") + private String standardProcessCode; + } diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementTaskLogEntity.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementTaskLogEntity.java new file mode 100644 index 00000000..3d7b6f7e --- /dev/null +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/entity/OemStatementTaskLogEntity.java @@ -0,0 +1,30 @@ +package org.springblade.desk.oem.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.core.mp.base.BaseEntity; + +import java.io.Serial; +import java.util.Date; + +/** + * 外协结算任务日志 实体类 + * + * @author maxg + * @since 2026-05-08 + */ +@Data +@TableName("MES_OEM_STATEMENT_TASK_LOG") +@Schema(description = "OemStatementTaskLog对象") +@EqualsAndHashCode(callSuper = true) +public class OemStatementTaskLogEntity extends BaseEntity { + + @Serial + private static final long serialVersionUID = 1L; + + @Schema(description = "镀后入库时间") + private Date putStoreTime; + +} diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/vo/StatementVO.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/vo/StatementVO.java index 70a39970..b78d202f 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/vo/StatementVO.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/oem/pojo/vo/StatementVO.java @@ -107,4 +107,19 @@ public class StatementVO extends OemStatementEntity { * 同外协厂家下有效期内的全部该工序报价 */ private List priceSheetList; + + @Schema(description = "需结算工艺能力") + private String craftIds; + + @Schema(description = "返工单号") + private String reworkCode; + + @Schema(description = "返工顺序") + private String reworkNo; + + @Schema(description = "计划部门") + private String planDeptcode; + + @Schema(description = "工艺能力类型") + private String wxLimit; } diff --git a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/util/PriceMatcher.java b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/util/PriceMatcher.java index 6a5de8b5..82f3f4be 100644 --- a/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/util/PriceMatcher.java +++ b/blade-service-api/blade-desk-api/src/main/java/org/springblade/desk/util/PriceMatcher.java @@ -97,4 +97,15 @@ public class PriceMatcher { .filter(remark -> containsPrice(remark, targetPrice)) .collect(Collectors.toSet()); } + + /** + * 判断价格是否匹配 + * + * @param remark + * @param targetPrice + * @return + */ + public static boolean isContainsPrice(String remark, BigDecimal targetPrice) { + return containsPrice(remark, targetPrice); + } } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/feign/OemStatementClient.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/feign/OemStatementClient.java new file mode 100644 index 00000000..dc6213a1 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/feign/OemStatementClient.java @@ -0,0 +1,19 @@ +package org.springblade.desk.oem.feign; + +import io.swagger.v3.oas.annotations.Hidden; +import jakarta.annotation.Resource; +import org.springblade.desk.oem.service.IOemStatementService; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Hidden +public class OemStatementClient implements IOemStatementClient { + + @Resource + private IOemStatementService oemStatementService; + + @Override + public void generateSettlement() { + oemStatementService.generateSettlement(); + } +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.java index 7f087e2d..7c2758d2 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.java @@ -37,4 +37,12 @@ public interface OemStatementMapper extends BaseMapper { */ List exportOemStatement(@Param("ew") Wrapper queryWrapper); + /** + * 获取未结算计划订单 + * + * @param query + * @return + */ + List selectUnsettled(StatementQuery query); + } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.xml index 47831eb6..6e1cef59 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.xml +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementMapper.xml @@ -86,6 +86,12 @@ + + + + + + + + diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.java new file mode 100644 index 00000000..98707634 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.java @@ -0,0 +1,18 @@ +package org.springblade.desk.oem.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springblade.desk.oem.pojo.entity.OemStatementTaskLogEntity; + +import java.util.Date; + +/** + * 外协结算任务日志 Mapper 接口 + * + * @author maxg + * @since 2026-05-08 + */ +public interface OemStatementTaskLogMapper extends BaseMapper { + + Date getLastMaxPutStoreTime(); + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.xml b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.xml new file mode 100644 index 00000000..07cf9ed1 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/mapper/OemStatementTaskLogMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementService.java index 467f4815..18e0f1aa 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementService.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementService.java @@ -84,4 +84,9 @@ public interface IOemStatementService extends BaseService { */ R notNeedSettlement(List list); + /** + * 生成结算数据 + */ + void generateSettlement(); + } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementTaskLogService.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementTaskLogService.java new file mode 100644 index 00000000..a1241e5e --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/IOemStatementTaskLogService.java @@ -0,0 +1,24 @@ +package org.springblade.desk.oem.service; + +import org.springblade.core.mp.base.BaseService; +import org.springblade.desk.oem.pojo.entity.OemStatementTaskLogEntity; + +import java.util.Date; + +public interface IOemStatementTaskLogService extends BaseService { + + /** + * 获取最大镀后入库时间 + * + * @return + */ + Date getLastMaxPutStoreTime(); + + /** + * 保存最大镀后入库时间 + * + * @param putStoreTime + */ + void saveMaxPutStoreTime(Date putStoreTime); + +} diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementServiceImpl.java index 570fd313..9160ec86 100644 --- a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementServiceImpl.java +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementServiceImpl.java @@ -2,37 +2,46 @@ package org.springblade.desk.oem.service.impl; import cn.hutool.core.bean.BeanUtil; import com.alibaba.nacos.common.utils.CollectionUtils; +import com.alibaba.nacos.shaded.com.google.common.collect.Lists; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import jakarta.annotation.Resource; +import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.mp.support.Query; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.Func; +import org.springblade.desk.oem.mapper.OemStatementMapper; import org.springblade.desk.oem.mapper.PlatingTypeRulesMapper; +import org.springblade.desk.oem.pojo.entity.OemStandardProcessEntity; import org.springblade.desk.oem.pojo.entity.OemStatementEntity; import org.springblade.desk.oem.pojo.entity.PlatingTypeRulesEntity; import org.springblade.desk.oem.pojo.excel.OemStatementExcel; import org.springblade.desk.oem.pojo.request.OemSettleAccountsApproval; import org.springblade.desk.oem.pojo.request.PriceSheetQuery; import org.springblade.desk.oem.pojo.request.StatementQuery; -import org.springblade.desk.oem.mapper.OemStatementMapper; import org.springblade.desk.oem.pojo.vo.PriceSheetVO; import org.springblade.desk.oem.pojo.vo.StatementVO; +import org.springblade.desk.oem.service.IOemStandardProcessService; import org.springblade.desk.oem.service.IOemStatementService; +import org.springblade.desk.oem.service.IOemStatementTaskLogService; import org.springblade.desk.util.PriceMatcher; import org.springblade.erpdata.feign.IErpDataOemClient; +import org.springblade.system.feign.IDictBizClient; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import org.springblade.core.mp.base.BaseServiceImpl; import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; @@ -53,6 +62,19 @@ public class OemStatementServiceImpl extends BaseServiceImpl selectOemStatementPage(IPage page, StatementQuery mesOemStatement) { return page.setRecords(baseMapper.selectOemStatementPage(page, mesOemStatement)); @@ -74,9 +96,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> groupedMap = statementVOS.stream() - .filter(vo -> vo.getPutStoreTime() != null && !vo.getPutStoreTime().trim().isEmpty()) - .collect(Collectors.groupingBy(StatementVO::getPutStoreTime)); + Map> groupedMap = statementVOS.stream().filter(vo -> vo.getPutStoreTime() != null && !vo.getPutStoreTime().trim().isEmpty()).collect(Collectors.groupingBy(StatementVO::getPutStoreTime)); groupedMap.entrySet().forEach(stringListEntry -> { R result = oemSettleAccounts(stringListEntry.getValue(), price, LocalDate.parse(stringListEntry.getKey())); @@ -101,10 +121,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl statementVOS, BigDecimal price, LocalDate putStoreDate) { @@ -118,8 +135,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> listEntry : oemAndStatementMap.entrySet()) { CompletableFuture future = CompletableFuture.runAsync(() -> { try { - processOemStatements(listEntry.getKey(), listEntry.getValue(), price, putStoreDate, - countSuccess, countError); + processOemStatements(listEntry.getKey(), listEntry.getValue(), price, putStoreDate, countSuccess, countError); } catch (Exception e) { log.error(String.format("处理外协厂商{}的结算单时发生异常", listEntry.getKey()), e); } @@ -133,10 +149,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> listEntry : oemAndStatementMap.entrySet()) { //外协厂商下全部需要结算的结算单 List statementVOList = listEntry.getValue(); @@ -328,20 +341,11 @@ public class OemStatementServiceImpl extends BaseServiceImpl - Map> priceSheetMap = priceSheetAllList.stream() - .collect(Collectors.groupingBy( - PriceSheetVO::getGxinfo, - () -> new TreeMap<>(Collections.reverseOrder()), // 按键的倒序排序 - Collectors.collectingAndThen( - Collectors.toList(), - list -> { - // 对每个分组内的列表按生效日期倒序排序 - return list.stream() - .sorted(Comparator.comparing(PriceSheetVO::getStartdat).reversed()) - .collect(Collectors.toList()); - } - ) - )); + Map> priceSheetMap = priceSheetAllList.stream().collect(Collectors.groupingBy(PriceSheetVO::getGxinfo, () -> new TreeMap<>(Collections.reverseOrder()), // 按键的倒序排序 + Collectors.collectingAndThen(Collectors.toList(), list -> { + // 对每个分组内的列表按生效日期倒序排序 + return list.stream().sorted(Comparator.comparing(PriceSheetVO::getStartdat).reversed()).collect(Collectors.toList()); + }))); //3.为每个结算单匹配报价集合 statementVOList.forEach(statementVO -> { try { @@ -397,9 +401,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl statementVOList, - BigDecimal price, LocalDate putStoreDate, - AtomicInteger countSuccess, AtomicInteger countError) { + private void processOemStatements(String oemName, List statementVOList, BigDecimal price, LocalDate putStoreDate, AtomicInteger countSuccess, AtomicInteger countError) { // 1. 查询报价单 // List priceSheetAllList = getPriceSheets(oemName, putStoreDate); //假数据测试用 @@ -474,8 +476,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl - Map> priceSheetMap = priceSheetAllList.stream() - .collect(Collectors.groupingBy(PriceSheetVO::getGxinfo)); + Map> priceSheetMap = priceSheetAllList.stream().collect(Collectors.groupingBy(PriceSheetVO::getGxinfo)); // 3. 为每个结算单匹配报价集合 statementVOList.forEach(statementVO -> { @@ -520,21 +521,19 @@ public class OemStatementServiceImpl extends BaseServiceImpl saves = statementVOList.stream() - .map(statementVO -> { - // 统计数量 - if (Objects.equals(OemStatementEntity.IN_SETTLEMENT, statementVO.getRosStatus())) { - countSuccess.incrementAndGet(); - } else if (Objects.equals(OemStatementEntity.ERR_SETTLEMENT, statementVO.getRosStatus())) { - countError.incrementAndGet(); - } - OemStatementEntity entity = new OemStatementEntity(); - BeanUtils.copyProperties(statementVO, entity); - entity.setUpdateTime(new Date()); - entity.setIsDeleted(0); - return entity; - }) - .collect(Collectors.toList()); + List saves = statementVOList.stream().map(statementVO -> { + // 统计数量 + if (Objects.equals(OemStatementEntity.IN_SETTLEMENT, statementVO.getRosStatus())) { + countSuccess.incrementAndGet(); + } else if (Objects.equals(OemStatementEntity.ERR_SETTLEMENT, statementVO.getRosStatus())) { + countError.incrementAndGet(); + } + OemStatementEntity entity = new OemStatementEntity(); + BeanUtils.copyProperties(statementVO, entity); + entity.setUpdateTime(new Date()); + entity.setIsDeleted(0); + return entity; + }).collect(Collectors.toList()); // 批量插入或更新 if (!saves.isEmpty()) { @@ -553,28 +552,13 @@ public class OemStatementServiceImpl extends BaseServiceImpl list) { if (null != list && list.size() > 0) { - List saves = list.stream() - .map(statementVO -> { - OemStatementEntity entity = new OemStatementEntity(); - BeanUtils.copyProperties(statementVO, entity); - entity.setApprovalStatus(OemStatementEntity.APPROVAL_STATUS_VIA); - entity.setRosStatus(OemStatementEntity.NOT_NEED_SETTLEMENT); - entity.setMemo("无需结算"); - entity.setTotalPrice(null); - entity.setUnitPrice(null); - entity.setQuotation(""); - entity.setUpdateTime(new Date()); - return entity; - }) - .collect(Collectors.toList()); + List saves = list.stream().map(statementVO -> { + OemStatementEntity entity = new OemStatementEntity(); + BeanUtils.copyProperties(statementVO, entity); + entity.setApprovalStatus(OemStatementEntity.APPROVAL_STATUS_VIA); + entity.setRosStatus(OemStatementEntity.NOT_NEED_SETTLEMENT); + entity.setMemo("无需结算"); + entity.setTotalPrice(null); + entity.setUnitPrice(null); + entity.setQuotation(""); + entity.setUpdateTime(new Date()); + return entity; + }).collect(Collectors.toList()); // baseMapper.insertOrUpdate(saves); // 逐条处理 @@ -608,14 +590,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl wrapper = Wrappers.lambdaUpdate(); - wrapper.set(OemStatementEntity::getTotalPrice, entity.getTotalPrice()) - .set(OemStatementEntity::getUnitPrice, entity.getUnitPrice()) - .set(OemStatementEntity::getQuotation, entity.getQuotation()) - .set(OemStatementEntity::getApprovalStatus, entity.getApprovalStatus()) - .set(OemStatementEntity::getRosStatus, entity.getRosStatus()) - .set(OemStatementEntity::getMemo, entity.getMemo()) - .set(OemStatementEntity::getUpdateTime, entity.getUpdateTime()) - .eq(OemStatementEntity::getId, entity.getId()); + wrapper.set(OemStatementEntity::getTotalPrice, entity.getTotalPrice()).set(OemStatementEntity::getUnitPrice, entity.getUnitPrice()).set(OemStatementEntity::getQuotation, entity.getQuotation()).set(OemStatementEntity::getApprovalStatus, entity.getApprovalStatus()).set(OemStatementEntity::getRosStatus, entity.getRosStatus()).set(OemStatementEntity::getMemo, entity.getMemo()).set(OemStatementEntity::getUpdateTime, entity.getUpdateTime()).eq(OemStatementEntity::getId, entity.getId()); baseMapper.update(null, wrapper); } @@ -655,7 +630,6 @@ public class OemStatementServiceImpl extends BaseServiceImpl getPriceSheets(String oemName) { PriceSheetQuery query = new PriceSheetQuery(); query.setOcName(oemName); - R> pageR = erpDataOemClient.priceSheetData(query, new Query() {{ setSize(99999); }}); @@ -688,20 +662,16 @@ public class OemStatementServiceImpl extends BaseServiceImpl priceSheetList = statementVO.getPriceSheetList(); //取出匹配车间订单号的报价和无车间订单号的报价 - Map> woNoPriceSheetMap = priceSheetList.stream() - .collect(Collectors.groupingBy( - priceSheet -> { - String wono = priceSheet.getWono(); - return wono == null || wono.trim().isEmpty() ? "EMPTY_WONO" : wono; - }, - Collectors.toList() - )); + Map> woNoPriceSheetMap = priceSheetList.stream().collect(Collectors.groupingBy(priceSheet -> { + String wono = priceSheet.getWono(); + return wono == null || wono.trim().isEmpty() ? "EMPTY_WONO" : wono; + }, Collectors.toList())); //匹配车间订单号报价 if (woNoPriceSheetMap.containsKey(statementVO.getWoCode())) { List woNoPriceSheetList = woNoPriceSheetMap.get(statementVO.getWoCode()); @@ -750,10 +720,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl priceSheetList = statementVO.getPriceSheetList(); //报价单判断同时满足物料名称和质量等级 || 为空 - priceSheetList = priceSheetList.stream() - .filter(priceSheet -> matchesCondition1(priceSheet, statementVO)) - .filter(priceSheet -> matchesCondition2(priceSheet, statementVO)) - .collect(Collectors.toList()); + priceSheetList = priceSheetList.stream().filter(priceSheet -> matchesCondition1(priceSheet, statementVO)).filter(priceSheet -> matchesCondition2(priceSheet, statementVO)).collect(Collectors.toList()); //无报价单【结算异常】 if (priceSheetList.size() < 1) { //结算异常:无报价记录结算结果 @@ -778,15 +745,10 @@ public class OemStatementServiceImpl extends BaseServiceImpl 0 && 零件镀层物料编码不为空,则需匹配规则 if (price.compareTo(BigDecimal.ZERO) > 0 && !StringUtils.isEmpty(plateGoodsCode)) { //取出所有备注 - Map> remarkPriceSheetMap = priceSheetList.stream() - .filter(priceSheet -> { - String remark = priceSheet.getRemark(); - return remark != null && !remark.trim().isEmpty(); - }) - .collect(Collectors.groupingBy( - PriceSheetVO::getRemark, - Collectors.toList() - )); + Map> remarkPriceSheetMap = priceSheetList.stream().filter(priceSheet -> { + String remark = priceSheet.getRemark(); + return remark != null && !remark.trim().isEmpty(); + }).collect(Collectors.groupingBy(PriceSheetVO::getRemark, Collectors.toList())); Set remarksByPrice = PriceMatcher.findRemarksByPriceStream(remarkPriceSheetMap.keySet(), price); if (remarksByPrice.size() < 1) { //结算异常:无报价记录结算结果 @@ -795,8 +757,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl priceSheetVOList = remarkPriceSheetMap.entrySet().stream() - .filter(entry -> remarksByPrice.contains(entry.getKey())) // 过滤key在keys中的条目 + List priceSheetVOList = remarkPriceSheetMap.entrySet().stream().filter(entry -> remarksByPrice.contains(entry.getKey())) // 过滤key在keys中的条目 .flatMap(entry -> entry.getValue().stream()) // 将List扁平化为PriceSheetVO流 .collect(Collectors.toList()); statementVO.setPriceSheetList(priceSheetVOList); @@ -810,7 +771,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> prtnoPriceSheetMap = priceSheetList.stream() - .filter(priceSheet -> { - String prtno = priceSheet.getPrtno(); - return prtno != null && !prtno.trim().isEmpty() && ("涂色标".equals(prtno) || "涂色带".equals(prtno) || "涂箭头".equals(prtno)); - }) - .collect(Collectors.groupingBy( - PriceSheetVO::getPrtno, - Collectors.toList() - )); + Map> coatingDescPriceSheetMap = priceSheetList.stream().filter(priceSheet -> { + String coatingDesc = priceSheet.getCoating_desc(); + return coatingDesc != null && !coatingDesc.trim().isEmpty() && ("涂色标".equals(coatingDesc) || "涂色带".equals(coatingDesc) || "涂箭头".equals(coatingDesc)); + }).collect(Collectors.groupingBy(PriceSheetVO::getCoating_desc, Collectors.toList())); // 如果没有任何报价记录 - if (prtnoPriceSheetMap.isEmpty()) { + if (coatingDescPriceSheetMap.isEmpty()) { //结算异常:无报价记录结算结果 statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); statementVO.setMemo(String.format("外协厂商【%s】,工序内容【%s】涂色标、涂色带、涂箭头-未找到报价", statementVO.getOcName(), statementVO.getPartName())); @@ -848,8 +804,8 @@ public class OemStatementServiceImpl extends BaseServiceImpl 0 && prtnoPriceSheetMap.containsKey("涂箭头")) { - List tjtPriceSheetList = prtnoPriceSheetMap.get("涂箭头"); + if (tjtNum > 0 && coatingDescPriceSheetMap.containsKey("涂箭头")) { + List tjtPriceSheetList = coatingDescPriceSheetMap.get("涂箭头"); if (tjtPriceSheetList.size() > 1 && flag) { //结算异常:多条报价记录结算结果 statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); @@ -862,8 +818,8 @@ public class OemStatementServiceImpl extends BaseServiceImpl 0 && prtnoPriceSheetMap.containsKey("涂色带")) { - List tsdPriceSheetList = prtnoPriceSheetMap.get("涂色带"); + if (tsdNum > 0 && coatingDescPriceSheetMap.containsKey("涂色带")) { + List tsdPriceSheetList = coatingDescPriceSheetMap.get("涂色带"); if (tsdPriceSheetList.size() > 1 && flag) { //结算异常:多条报价记录结算结果 statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); @@ -876,8 +832,8 @@ public class OemStatementServiceImpl extends BaseServiceImpl 0 && prtnoPriceSheetMap.containsKey("涂色标")) { - List tsbPriceSheetList = prtnoPriceSheetMap.get("涂色标"); + if (tsbNum > 0 && coatingDescPriceSheetMap.containsKey("涂色标")) { + List tsbPriceSheetList = coatingDescPriceSheetMap.get("涂色标"); if (tsbPriceSheetList.size() > 1 && flag) { //结算异常:多条报价记录结算结果 statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); @@ -961,8 +917,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> map = priceSheetList.stream() - .filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 + Map> map = priceSheetList.stream().filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 .collect(Collectors.groupingBy(PriceSheetVO::getPrtno)); //1.精确匹配,完整的镀种 if (map.containsKey(plate)) { @@ -971,8 +926,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl queryWrapper = new LambdaQueryWrapper(); - queryWrapper.apply("ROWNUM = 1").eq(PlatingTypeRulesEntity::getOrderPlat, plate) - .orderByDesc(PlatingTypeRulesEntity::getCreateTime); + queryWrapper.apply("ROWNUM = 1").eq(PlatingTypeRulesEntity::getOrderPlat, plate).orderByDesc(PlatingTypeRulesEntity::getCreateTime); PlatingTypeRulesEntity platingTypeRulesEntity = platingTypeRulesMapper.selectOne(queryWrapper); if (platingTypeRulesEntity == null || StringUtils.isBlank(platingTypeRulesEntity.getQuotationPlat())) { return false; @@ -997,8 +951,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> map = priceSheetList.stream() - .filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 + Map> map = priceSheetList.stream().filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 .collect(Collectors.groupingBy(PriceSheetVO::getPrtno)); //1.精确匹配,完整的零件号 if (map.containsKey(partCode)) { @@ -1006,15 +959,9 @@ public class OemStatementServiceImpl extends BaseServiceImpl> newMap = map.entrySet().stream() - .filter(entry -> entry.getKey().contains("-%")) - .collect(Collectors.toMap( - entry -> entry.getKey().split("-%")[0], // 只保留%之前的部分 - Map.Entry::getValue - )); - List priceSheetVOList = newMap.entrySet().stream() - .filter(entry -> partCode.startsWith(entry.getKey())) - .flatMap(entry -> entry.getValue().stream()) // 将 List 扁平化为 Stream + Map> newMap = map.entrySet().stream().filter(entry -> entry.getKey().contains("-%")).collect(Collectors.toMap(entry -> entry.getKey().split("-%")[0], // 只保留%之前的部分 + Map.Entry::getValue)); + List priceSheetVOList = newMap.entrySet().stream().filter(entry -> partCode.startsWith(entry.getKey())).flatMap(entry -> entry.getValue().stream()) // 将 List 扁平化为 Stream .collect(Collectors.toList()); //匹配成功,保存报价集合 if (null != priceSheetVOList && !priceSheetVOList.isEmpty()) { @@ -1037,8 +984,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl> map = priceSheetList.stream() - .filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 + Map> map = priceSheetList.stream().filter(vo -> vo.getPrtno() != null) // 过滤掉prtno为null的对象 .collect(Collectors.groupingBy(PriceSheetVO::getPrtno)); //镀层厚度值相等,保存报价集合 if (map.containsKey(plateThickness)) { @@ -1052,7 +998,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl 1) { - List priceSheetVOList = priceSheetVOS.stream() - .filter(vo -> { - //现场数据库里lower是上限,upper反而是下限 - double lower = Double.parseDouble(vo.getLower()); - double upper = Double.parseDouble(vo.getUpper()); - return ypAreaValue >= upper && ypAreaValue <= lower; - }).collect(Collectors.toList()); + List priceSheetVOList = priceSheetVOS.stream().filter(vo -> { + //现场数据库里lower是上限,upper反而是下限 + double lower = Double.parseDouble(vo.getLower()); + double upper = Double.parseDouble(vo.getUpper()); + return ypAreaValue >= upper && ypAreaValue <= lower; + }).collect(Collectors.toList()); if (null != priceSheetVOList && priceSheetVOList.size() > 1 && flag) { statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); statementVO.setMemo(String.format("外协厂商【%s】,工序内容【%s】,阶梯价【%s】-报价不唯一", statementVO.getOcName(), statementVO.getPartName(), "单批阶梯价(按单件面积)")); @@ -1168,13 +1113,12 @@ public class OemStatementServiceImpl extends BaseServiceImpl 1) { - List priceSheetVOList = priceSheetVOS.stream() - .filter(vo -> { - //现场数据库里lower是上限,upper反而是下限 - double lower = Double.parseDouble(vo.getLower()); - double upper = Double.parseDouble(vo.getUpper()); - return totalAreaValue >= upper && totalAreaValue <= lower; - }).collect(Collectors.toList()); + List priceSheetVOList = priceSheetVOS.stream().filter(vo -> { + //现场数据库里lower是上限,upper反而是下限 + double lower = Double.parseDouble(vo.getLower()); + double upper = Double.parseDouble(vo.getUpper()); + return totalAreaValue >= upper && totalAreaValue <= lower; + }).collect(Collectors.toList()); if (null != priceSheetVOList && priceSheetVOList.size() > 1 && flag) { statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); statementVO.setMemo(String.format("外协厂商【%s】,工序内容【%s】,阶梯价【%s】-报价不唯一", statementVO.getOcName(), statementVO.getPartName(), "单批阶梯价(按单批面积)")); @@ -1210,9 +1154,7 @@ public class OemStatementServiceImpl extends BaseServiceImpl statementVOS = baseMapper.selectUnsettled(query); + if (CollectionUtils.isEmpty(statementVOS)) { + return; + } + List settlementVOs = new ArrayList<>(); + for (StatementVO statementVO : statementVOS) { + boolean isRework = !StringUtils.isEmpty(statementVO.getReworkCode()) && !StringUtils.isEmpty(statementVO.getReworkNo()); + boolean isFj = statementVO.getWoCode() != null && statementVO.getWoCode().startsWith("FJ"); + // TODO 如果是返工订单,审理单对应责任部门为3400,不结算 + if (isRework && DEPT_CODE_REWORK.equals(statementVO.getPlanDeptcode())) { + continue; + } + // 工序加工单位非外协厂家,不结算 + if (statementVO.getOcId() == null) { + continue; + } + // 工序对应工艺能力不需结算,不结算 + Long caId = statementVO.getCaId(); + String craftIds = statementVO.getCraftIds(); + boolean isContain = false; + if (caId != null && craftIds != null && !craftIds.isBlank()) { + String temp = "," + craftIds + ","; + isContain = temp.contains("," + caId + ","); + } + if (!isContain) { + continue; + } + // TODO 如果工序为【浸保护剂、除镀层、清洗(返工)】:只计算返工订单 或 计划单号以“FJ”开头的订单(即:既不是返工单也不是以FJ开头的订单,不结算) + if ("浸保护剂".equals(statementVO.getPsName()) || "除镀层".equals(statementVO.getPsName()) || "清洗(返工)".equals(statementVO.getPsName())) { + boolean isNormalOrder = !isRework && !isFj; + if (isNormalOrder) { + continue; + } + } + // TODO 如果车间订单为【返工订单】并且工序对应工艺能力类型包含“镀金”、“镀银”,不结算 + if (isRework) { + if (!StringUtils.isEmpty(statementVO.getWxLimit())) { + R processCapabilityType = dictBizClient.getValue("ProcessCapabilityType", statementVO.getWxLimit()); + String type = processCapabilityType.getData(); + if (type.contains("镀金") || type.contains("镀银")) { + continue; + } + } + } + statementVO.setRosStatus(OemStatementEntity.NO_SETTLEMENT); + settlementVOs.add(statementVO); + } + // 匹配标准工序代码 + if (CollectionUtils.isNotEmpty(settlementVOs)) { + // 根据工序Id分组 + Map> groupByPsId = settlementVOs.stream().collect(Collectors.groupingBy(StatementVO::getPsId)); + Set psIds = groupByPsId.keySet(); + final int batchSize = 500; + List allStandardList = new ArrayList<>(); + List> splitPsIds = Lists.partition(new ArrayList<>(psIds), batchSize); + for (List subPsIds : splitPsIds) { + List batchList = oemStandardProcessService.list(new LambdaQueryWrapper().in(OemStandardProcessEntity::getProcessId, subPsIds)); + allStandardList.addAll(batchList); + } + Map> standardMap = allStandardList.stream().collect(Collectors.groupingBy(OemStandardProcessEntity::getProcessId)); + for (Map.Entry> entry : groupByPsId.entrySet()) { + Long psId = entry.getKey(); + List standardProcessList = standardMap.getOrDefault(psId, Collections.emptyList()); + for (StatementVO statementVO : entry.getValue()) { + OemStandardProcessEntity oemStandardProcessEntity = matchStandardProcess(standardProcessList, statementVO); + if (oemStandardProcessEntity != null) { + statementVO.setStandardProcessCode(oemStandardProcessEntity.getStandardProcessCode()); + } + } + } + Map> groupByManual = settlementVOs.stream().collect(Collectors.groupingBy(StatementVO::getManual)); + List saves = new ArrayList<>(); + for (Map.Entry> entry : groupByManual.entrySet()) { + String manual = entry.getKey(); + // 自动结算 + if (MANUAL_AUTO.equals(manual)) { + List autoStatementVOS = autoSettlement(entry.getValue()); + for (StatementVO statementVO : autoStatementVOS) { + OemStatementEntity entity = new OemStatementEntity(); + BeanUtils.copyProperties(statementVO, entity); + entity.setUpdateTime(new Date()); + entity.setIsDeleted(0); + saves.add(entity); + } + } else { + for (StatementVO statementVO : entry.getValue()) { + OemStatementEntity entity = new OemStatementEntity(); + BeanUtils.copyProperties(statementVO, entity); + entity.setUpdateTime(new Date()); + entity.setIsDeleted(0); + saves.add(entity); + } + } + } + if (CollectionUtils.isNotEmpty(saves)) { + Date maxPutStoreTimeDate = getMaxPutStoreTimeDate(settlementVOs); + this.saveBatch(saves); + oemStatementTaskLogService.saveMaxPutStoreTime(maxPutStoreTimeDate); + } + } + } + + /** + * 匹配标准工序代码 + * + * @param allStandardList + * @param statementVO + * @return + */ + private OemStandardProcessEntity matchStandardProcess(List allStandardList, StatementVO statementVO) { + if (CollectionUtils.isEmpty(allStandardList)) { + return null; + } + // ====================== 规则1:仅【工序】,其他全为null ====================== + for (OemStandardProcessEntity s : allStandardList) { + boolean rule1 = Objects.equals(s.getProcessId(), statementVO.getPsId()) && StringUtils.isEmpty(s.getPlate()) && StringUtils.isEmpty(s.getPlateThickness()) && StringUtils.isEmpty(s.getPartName()); + + if (rule1) return s; + } + // ====================== 规则2:仅【工序+镀种】,其他null ====================== + for (OemStandardProcessEntity s : allStandardList) { + boolean rule2 = Objects.equals(s.getProcessId(), statementVO.getPsId()) && StringUtils.equals(s.getPlate(), statementVO.getPlate()) && StringUtils.isEmpty(s.getPlateThickness()) && StringUtils.isEmpty(s.getPartName()); + + if (rule2) return s; + } + // ====================== 规则3:仅【工序+镀层厚度】,其他null ====================== + for (OemStandardProcessEntity s : allStandardList) { + boolean rule3 = Objects.equals(s.getProcessId(), statementVO.getPsId()) && StringUtils.isEmpty(s.getPlate()) && StringUtils.equals(s.getPlateThickness(), statementVO.getPlateThickness()) && StringUtils.isEmpty(s.getPartName()); + if (rule3) return s; + } + // ====================== 规则4:仅【工序+零件名】,其他null ====================== + for (OemStandardProcessEntity s : allStandardList) { + boolean rule4 = Objects.equals(s.getProcessId(), statementVO.getPsId()) && StringUtils.isEmpty(s.getPlate()) && StringUtils.isEmpty(s.getPlateThickness()) && StringUtils.equals(s.getPartName(), statementVO.getPartName()); + + if (rule4) return s; + } + + // ====================== 规则5:【工序+镀层厚度+零件名】,镀种null ====================== + for (OemStandardProcessEntity s : allStandardList) { + boolean rule5 = Objects.equals(s.getProcessId(), statementVO.getPsId()) && StringUtils.isEmpty(s.getPlate()) && StringUtils.equals(s.getPlateThickness(), statementVO.getPlateThickness()) && StringUtils.equals(s.getPartName(), statementVO.getPartName()); + if (rule5) return s; + } + return null; + } + + /** + * 自动结算 + * + * @param statementVOS + * @return + */ + private List autoSettlement(List statementVOS) { + // 1.以外协厂商分组的Map<厂家名称, 待结算工序结算单列表> + Map> oemAndStatementMap = statementVOS.stream().collect(Collectors.groupingBy(StatementVO::getOcName)); + for (Map.Entry> listEntry : oemAndStatementMap.entrySet()) { + //外协厂商下全部需要结算的结算单 + List statementVOList = listEntry.getValue(); + //2.以外协名称查出的全部报价单 + String oemName = listEntry.getKey(); + List priceSheetAllList = getPriceSheets(oemName); + if (priceSheetAllList.isEmpty()) { + //【结算异常】 + statementVOList.forEach(statementVO -> { + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + }); + } else { + //工序分组Map<工序, 报价列表> + Map> priceSheetMap = priceSheetAllList.stream().collect(Collectors.groupingBy(PriceSheetVO::getGxinfo, () -> new TreeMap<>(Collections.reverseOrder()), // 按键的倒序排序 + Collectors.collectingAndThen(Collectors.toList(), list -> { + // 对每个分组内的列表按生效日期倒序排序 + return list.stream().sorted(Comparator.comparing(PriceSheetVO::getStartdat).reversed()).collect(Collectors.toList()); + }))); + //3.为每个结算单匹配报价集合 + for (StatementVO statementVO : statementVOList) { + try { + List matchedPriceSheets = matchTheQuotationsWithCondition(statementVO, priceSheetMap); + if (null == matchedPriceSheets || matchedPriceSheets.isEmpty()) { + continue; + } + statementVO.setPriceSheetList(matchedPriceSheets); + // 4.匹配规则,过滤出唯一报价 + // (1) 供应商代码 + 工序 + 零件号 + 生产标识 + 计划单号 + 现执行价格 + if (rule1(statementVO, BigDecimal.ZERO)) { + continue; + } + // (2) 供应商代码 + 工序 + 零件号 + 生产标识 + 现执行价格 + if (rule2(statementVO, BigDecimal.ZERO)) { + continue; + } + // (3) 供应商代码 + 生产标识 + 计划单号 + 标准工序代码 + if (rule3(statementVO)) { + continue; + } + // (4) 供应商代码 + 生产标识 + 标准工序代码 + if (rule4(statementVO)) { + continue; + } + // (5) 供应商代码 + 标准工序代码 + 现执行价格 + if (rule5(statementVO, BigDecimal.ZERO)) { + continue; + } + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + } catch (Exception e) { + log.error("结算单处理异常", e); + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("结算处理异常: " + e.getMessage()); + } + } + } + } + return statementVOS; + } + + /** + * 匹配报价单 + * + * @param statementVO + * @param priceSheetMap + * @return + */ + private List matchTheQuotationsWithCondition(StatementVO statementVO, Map> priceSheetMap) { + String psName = statementVO.getPsName(); + if (!priceSheetMap.containsKey(psName)) { + //【结算异常】 + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + return null; + } + List result = new ArrayList<>(); + //获得外协厂商该工序下报价单列表 + for (PriceSheetVO priceSheetVO : priceSheetMap.get(psName)) { + if (isValid(statementVO, priceSheetVO)) { + result.add(priceSheetVO); + } + } + if (CollectionUtils.isEmpty(result)) { + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + return null; + } + return result; + } + + /** + * 报价单是否有效 + * + * @param statementVO + * @param priceSheetVO + * @return + */ + private boolean isValid(StatementVO statementVO, PriceSheetVO priceSheetVO) { + if (!"工序协作".equals(priceSheetVO.getPricetype())) { + return false; + } + if (!"有效".equals(priceSheetVO.getValidflag()) && !"无效".equals(priceSheetVO.getValidflag())) { + return false; + } + String startTime = priceSheetVO.getStartdat(); + String validTime = priceSheetVO.getValiddat(); + String putStoreTime = statementVO.getPutStoreTime(); + if (startTime == null || validTime == null || putStoreTime == null) { + return false; + } + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + try { + LocalDate startDate = LocalDate.parse(startTime, fmt); + LocalDate validDate = LocalDate.parse(validTime, fmt); + LocalDate putStoreDate = LocalDate.parse(putStoreTime, fmt); + return !putStoreDate.isBefore(startDate) && !putStoreDate.isAfter(validDate); + } catch (Exception e) { + return false; + } + } + + /** + * 匹配规则1 : 供应商代码 + 工序 + 零件号 + 生产标识 + 计划单号 + 现执行价格 + * + * @param statementVO + * @param price + * @return + */ + private boolean rule1(StatementVO statementVO, BigDecimal price) { + // 涂色标跳过 + if (hasColorCount(statementVO)) { + return false; + } + List priceSheetList = statementVO.getPriceSheetList(); + if (CollectionUtils.isEmpty(priceSheetList)) { + return false; + } + // 结算单字段 + String ocCode = statementVO.getOcCode(); + String psName = statementVO.getPsName(); + String partCode = statementVO.getPartCode(); + String prodIdent = statementVO.getProdIdent(); + String woCode = statementVO.getWoCode(); + for (PriceSheetVO sheet : priceSheetList) { + boolean match = StringUtils.equals(sheet.getSplycode(), ocCode) && StringUtils.equals(sheet.getGxinfo(), psName) && StringUtils.equals(sheet.getPrtno(), partCode) && StringUtils.equals(sheet.getPrtlotno(), prodIdent) && StringUtils.equals(sheet.getWono(), woCode); + if (match && price != null && price.compareTo(BigDecimal.ZERO) != 0) { + // TODO 金银价格字段缺失 + match = PriceMatcher.isContainsPrice(sheet.getRemark(), price); + } + if (match && ruleTieredPricing(statementVO, sheet)) { + return setSettlementInfo(statementVO, sheet); + } + } + return false; + } + + /** + * 匹配规则2 : 供应商代码 + 工序 + 零件号 + 生产标识 + 现执行价格 + * + * @param statementVO + * @param price + * @return + */ + private boolean rule2(StatementVO statementVO, BigDecimal price) { + // 涂色标跳过 + if (hasColorCount(statementVO)) { + return false; + } + List priceSheetList = statementVO.getPriceSheetList(); + if (CollectionUtils.isEmpty(priceSheetList)) { + return false; + } + // 结算单字段 + String ocCode = statementVO.getOcCode(); + String psName = statementVO.getPsName(); + String partCode = statementVO.getPartCode(); + String prodIdent = statementVO.getProdIdent(); + for (PriceSheetVO sheet : priceSheetList) { + boolean match = StringUtils.equals(sheet.getSplycode(), ocCode) && StringUtils.equals(sheet.getGxinfo(), psName) && StringUtils.equals(sheet.getPrtno(), partCode) && StringUtils.equals(sheet.getPrtlotno(), prodIdent); + if (match && price != null && price.compareTo(BigDecimal.ZERO) != 0) { + // TODO 金银价格字段缺失 + match = PriceMatcher.isContainsPrice(sheet.getRemark(), price); + } + if (match && ruleTieredPricing(statementVO, sheet)) { + return setSettlementInfo(statementVO, sheet); + } + } + return false; + } + + /** + * 匹配规则3 : 供应商代码 + 生产标识 + 计划单号 + 标准工序代码 + * + * @param statementVO + * @return + */ + private boolean rule3(StatementVO statementVO) { + // 涂色标跳过 + if (hasColorCount(statementVO)) { + return false; + } + List priceSheetList = statementVO.getPriceSheetList(); + if (CollectionUtils.isEmpty(priceSheetList)) { + return false; + } + // 结算单字段 + String ocCode = statementVO.getOcCode(); + String prodIdent = statementVO.getProdIdent(); + String woCode = statementVO.getWoCode(); + String standardProcessCode = statementVO.getStandardProcessCode(); + for (PriceSheetVO sheet : priceSheetList) { + boolean match = StringUtils.equals(sheet.getSplycode(), ocCode) && StringUtils.equals(sheet.getPrtlotno(), prodIdent) && StringUtils.equals(sheet.getWono(), woCode) + // TODO 报价单标准工艺代码没加 + // && StringUtils.equals(sheet.getWono(), standardProcessCode) + ; + if (match && ruleTieredPricing(statementVO, sheet)) { + return setSettlementInfo(statementVO, sheet); + } + } + return false; + } + + /** + * 匹配规则4 : 供应商代码 + 生产标识 + 标准工序代码 + * + * @param statementVO + * @return + */ + private boolean rule4(StatementVO statementVO) { + // 涂色标跳过 + if (hasColorCount(statementVO)) { + return false; + } + List priceSheetList = statementVO.getPriceSheetList(); + if (CollectionUtils.isEmpty(priceSheetList)) { + return false; + } + // 结算单字段 + String ocCode = statementVO.getOcCode(); + String prodIdent = statementVO.getProdIdent(); + String standardProcessCode = statementVO.getStandardProcessCode(); + for (PriceSheetVO sheet : priceSheetList) { + boolean match = StringUtils.equals(sheet.getSplycode(), ocCode) && StringUtils.equals(sheet.getPrtlotno(), prodIdent) + // TODO 报价单标准工艺代码没加 + // && StringUtils.equals(sheet.getWono(), standardProcessCode) + ; + if (match && ruleTieredPricing(statementVO, sheet)) { + return setSettlementInfo(statementVO, sheet); + } + } + return false; + } + + /** + * 匹配规则5 : 供应商代码 + 标准工序代码 + 现执行价格 + * + * @param statementVO + * @param price + * @return + */ + private boolean rule5(StatementVO statementVO, BigDecimal price) { + List priceSheetList = statementVO.getPriceSheetList(); + if (CollectionUtils.isEmpty(priceSheetList)) { + return false; + } + List colorPriceSheetVOS = new ArrayList<>(); + // 结算单字段 + String ocCode = statementVO.getOcCode(); + String standardProcessCode = statementVO.getStandardProcessCode(); + for (PriceSheetVO sheet : priceSheetList) { + boolean match = StringUtils.equals(sheet.getSplycode(), ocCode) + // TODO 报价单标准工艺代码没加 + // && StringUtils.equals(sheet.getWono(), standardProcessCode) + ; + if (match && price != null && price.compareTo(BigDecimal.ZERO) != 0) { + // TODO 金银价格字段缺失 + match = PriceMatcher.isContainsPrice(sheet.getRemark(), price); + } + if (match) { + if (hasColorCount(statementVO)) { + colorPriceSheetVOS.add(sheet); + } else if (ruleTieredPricing(statementVO, sheet)) { + return setSettlementInfo(statementVO, sheet); + } + + } + } + if (hasColorCount(statementVO)) { + statementVO.setPriceSheetList(colorPriceSheetVOS); + return ruleColor(statementVO, colorPriceSheetVOS); + } + return false; + } + + /** + * 结算单报价信息 + * + * @param statementVO + * @param sheet + * @return + */ + private boolean setSettlementInfo(StatementVO statementVO, PriceSheetVO sheet) { + try { + BigDecimal unitPrice = new BigDecimal(sheet.getPrice().trim()); + BigDecimal qty = new BigDecimal(statementVO.getMakeQty() == null ? "0" : statementVO.getMakeQty().trim()); + BigDecimal totalArea = new BigDecimal(statementVO.getTotalArea() == null ? "0" : statementVO.getTotalArea().trim()); + BigDecimal totalPrice; + if ("平方分米".equals(sheet.getPrtum())) { + totalPrice = unitPrice.multiply(totalArea); + } else { + totalPrice = unitPrice.multiply(qty); + } + statementVO.setRosStatus(StatementVO.IN_SETTLEMENT); + statementVO.setApprovalStatus(StatementVO.APPROVAL_STATUS_UNDER); + statementVO.setUnitPrice(unitPrice); + statementVO.setUnit(sheet.getPrtum()); + statementVO.setTotalPrice(totalPrice); + statementVO.setMemo("结算中"); + statementVO.setQuotation(sheet.getSeqid()); + return true; + } catch (Exception e) { + return false; + } + } + + /** + * 匹配涂色标 + * + * @param statementVO + * @param priceSheetList + * @return + */ + private boolean ruleColor(StatementVO statementVO, List priceSheetList) { + //结算单色标色带箭头数量>0,需要匹配报价里色标色带箭头 + //如果结算单没有数量,直接返回false进入下个规则 + if (!hasColorCount(statementVO)) { + //结束当前规则匹配,进入下一规则匹配 + return false; + } + //涂色标、涂色带、涂箭头的报价集合 + Map> coatingDescPriceSheetMap = priceSheetList.stream().filter(priceSheet -> { + String coatingDesc = priceSheet.getCoating_desc(); + return coatingDesc != null && !coatingDesc.trim().isEmpty() && ("涂色标".equals(coatingDesc) || "涂色带".equals(coatingDesc) || "涂箭头".equals(coatingDesc)); + }).collect(Collectors.groupingBy(PriceSheetVO::getCoating_desc, Collectors.toList())); + // 如果没有任何报价记录 + if (coatingDescPriceSheetMap.isEmpty()) { + //结算异常:无报价记录结算结果 + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + return true; + } + //总价 + BigDecimal totalPrice = BigDecimal.ZERO; + //涂箭头 + Integer tjtNum = StringUtils.isNotEmpty(statementVO.getTjtNum()) ? Integer.valueOf(statementVO.getTjtNum()) : 0; + //涂色标 + Integer tsbNum = StringUtils.isNotEmpty(statementVO.getTsbNum()) ? Integer.valueOf(statementVO.getTsbNum()) : 0; + //涂色带 + Integer tsdNum = StringUtils.isNotEmpty(statementVO.getTsdNum()) ? Integer.valueOf(statementVO.getTsdNum()) : 0; + //报价单号 + String quotation = ""; + if (tjtNum > 0 && coatingDescPriceSheetMap.containsKey("涂箭头")) { + List tjtPriceSheetList = coatingDescPriceSheetMap.get("涂箭头"); + BigDecimal unitPrice = new BigDecimal(tjtPriceSheetList.get(0).getPrice()); + BigDecimal itemTotalPrice = unitPrice.multiply(BigDecimal.valueOf(tjtNum)); + totalPrice = totalPrice.add(itemTotalPrice); + quotation = tjtPriceSheetList.get(0).getSeqid(); + } + if (tsdNum > 0 && coatingDescPriceSheetMap.containsKey("涂色带")) { + List tsdPriceSheetList = coatingDescPriceSheetMap.get("涂色带"); + BigDecimal unitPrice = new BigDecimal(tsdPriceSheetList.get(0).getPrice()); + BigDecimal itemTotalPrice = unitPrice.multiply(BigDecimal.valueOf(tsdNum)); + totalPrice = totalPrice.add(itemTotalPrice); + quotation = tsdPriceSheetList.get(0).getSeqid(); + } + if (tsbNum > 0 && coatingDescPriceSheetMap.containsKey("涂色标")) { + List tsbPriceSheetList = coatingDescPriceSheetMap.get("涂色标"); + //唯一使用此报价单**结算** + BigDecimal unitPrice = new BigDecimal(tsbPriceSheetList.get(0).getPrice()); + BigDecimal itemTotalPrice = unitPrice.multiply(BigDecimal.valueOf(tsbNum)); + totalPrice = totalPrice.add(itemTotalPrice); + quotation = tsbPriceSheetList.get(0).getSeqid(); + } + //如总价大于0,则报价成功 + if (totalPrice.compareTo(BigDecimal.ZERO) > 0) { + statementVO.setRosStatus(StatementVO.IN_SETTLEMENT); + statementVO.setApprovalStatus(StatementVO.APPROVAL_STATUS_UNDER); + statementVO.setTotalPrice(totalPrice); + statementVO.setMemo("结算中"); + statementVO.setQuotation(quotation); + return true; + } else { + //结算异常:无报价记录结算结果 + statementVO.setRosStatus(StatementVO.ERR_SETTLEMENT); + statementVO.setMemo("未找到报价单"); + return true; + } + } + + /** + * 按阶梯价匹配 + * + * @param statementVO + * @param priceSheet + * @return + */ + private boolean ruleTieredPricing(StatementVO statementVO, PriceSheetVO priceSheet) { + //匹配阶梯价 + if (priceSheet.getStairflag().equals("单批阶梯价(按件数)")) { + double makeQty = Double.parseDouble(statementVO.getMakeQty()); + double lower = Double.parseDouble(priceSheet.getLower()); + double upper = Double.parseDouble(priceSheet.getUpper()); + return makeQty >= upper && makeQty <= lower; + } else if (priceSheet.getStairflag().equals("单批阶梯价(按单件面积)")) { + double ypArea = Double.parseDouble(statementVO.getYpArea()); + double lower = Double.parseDouble(priceSheet.getLower()); + double upper = Double.parseDouble(priceSheet.getUpper()); + return ypArea >= upper && ypArea <= lower; + } else if (priceSheet.getStairflag().equals("单批阶梯价(按单批面积)")) { + double totalArea = Double.parseDouble(statementVO.getTotalArea()); + double lower = Double.parseDouble(priceSheet.getLower()); + double upper = Double.parseDouble(priceSheet.getUpper()); + return totalArea >= upper && totalArea <= lower; + } else { + return true; + } + } + + /** + * 获取最大镀后入库时间 + * + * @param list + * @return + */ + public static Date getMaxPutStoreTimeDate(List list) { + SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd"); + if (list == null || list.isEmpty()) { + return null; + } + return list.stream() + .map(StatementVO::getPutStoreTime) + .filter(Objects::nonNull) + .filter(s -> !s.isBlank()) + .map(s -> { + try { + return SDF.parse(s); + } catch (ParseException e) { + return null; + } + }) + .filter(Objects::nonNull) + .max(Date::compareTo) + .orElse(null); + } + } diff --git a/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementTaskLogServiceImpl.java b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementTaskLogServiceImpl.java new file mode 100644 index 00000000..421435b4 --- /dev/null +++ b/blade-service/blade-desk/src/main/java/org/springblade/desk/oem/service/impl/OemStatementTaskLogServiceImpl.java @@ -0,0 +1,26 @@ +package org.springblade.desk.oem.service.impl; + +import org.springblade.core.mp.base.BaseServiceImpl; +import org.springblade.desk.oem.mapper.OemStatementTaskLogMapper; +import org.springblade.desk.oem.pojo.entity.OemStatementTaskLogEntity; +import org.springblade.desk.oem.service.IOemStatementTaskLogService; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class OemStatementTaskLogServiceImpl extends BaseServiceImpl implements IOemStatementTaskLogService { + + @Override + public Date getLastMaxPutStoreTime() { + return baseMapper.getLastMaxPutStoreTime(); + } + + @Override + public void saveMaxPutStoreTime(Date putStoreTime) { + OemStatementTaskLogEntity entity = new OemStatementTaskLogEntity(); + entity.setPutStoreTime(putStoreTime); + this.save(entity); + } + +}