package com.vincent.rsf.server.manager.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.vincent.rsf.framework.exception.CoolException; import com.vincent.rsf.server.api.controller.erp.params.SyncOrdersItem; import com.vincent.rsf.server.manager.entity.Matnr; import com.vincent.rsf.server.manager.enums.CusItemSyncMode; import com.vincent.rsf.server.system.constant.GlobalConfigCode; import com.vincent.rsf.server.system.entity.Config; import com.vincent.rsf.server.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; /** * cus_barcode_sync_view 与 man_matnr 同步(云仓通知单、无订单组托等共用) */ @Service @Slf4j public class CusBarcodeSyncMatnrService { @Autowired private CusBarcodeSyncViewQueryService cusBarcodeSyncViewQueryService; @Autowired private MatnrService matnrService; @Autowired private ConfigService configService; /** 与云仓通知单同步:按明细 matnr 查视图并写入/更新物料 */ public void syncFromOrderItems(List orderItems, Long loginUserId) { if (orderItems == null || orderItems.isEmpty()) { return; } List matnrCodes = orderItems.stream() .map(SyncOrdersItem::getMatnr) .filter(StringUtils::isNotBlank) .map(String::trim) .distinct() .collect(Collectors.toList()); if (matnrCodes.isEmpty()) { return; } syncAlignedWithBarcodeView(matnrCodes, buildOrderItemByMatnrCode(orderItems), loginUserId); } /** 无订单组托等:仅按物料号(与视图 barcode 一致)走同一套视图策略 */ public void syncFromMatnrCodes(Collection matnrCodes, Long loginUserId) { if (matnrCodes == null || matnrCodes.isEmpty()) { return; } List codes = matnrCodes.stream() .map(StringUtils::trimToNull) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (codes.isEmpty()) { return; } syncAlignedWithBarcodeView(codes, Collections.emptyMap(), loginUserId); } private static Map buildOrderItemByMatnrCode(List orderItems) { Map map = new LinkedHashMap<>(); if (orderItems == null) { return map; } for (SyncOrdersItem item : orderItems) { if (StringUtils.isBlank(item.getMatnr())) { continue; } String key = StringUtils.trimToNull(item.getMatnr().trim()); if (key == null) { continue; } map.putIfAbsent(key, item); } return map; } private CusItemSyncMode resolveCusItemSyncMode() { Config c = configService.getOne(new LambdaQueryWrapper() .eq(Config::getFlag, GlobalConfigCode.CUS_ITEM_SYNC_MODE) .eq(Config::getDeleted, 0), false); if (c == null) { return CusItemSyncMode.NONE; } return CusItemSyncMode.fromConfig(c.getVal()); } private void syncAlignedWithBarcodeView(List matnrCodes, Map orderItemByCode, Long loginUserId) { CusItemSyncMode mode = resolveCusItemSyncMode(); if (mode == CusItemSyncMode.NONE) { syncMatnrNonForceFromView(matnrCodes, orderItemByCode, loginUserId); return; } List> viewItems = cusBarcodeSyncViewQueryService.listByItemNos(matnrCodes); for (String code : matnrCodes) { if (!CusBarcodeSyncViewQueryService.orderMatnrHitsBarcodeView(code, viewItems)) { throw new CoolException("物料未在视图 cus_barcode_sync_view 中:" + code); } } applyCusBarcodeSyncViewRowsToMatnr(viewItems, orderItemByCode, loginUserId); } private void syncMatnrNonForceFromView(List matnrCodes, Map orderItemByCode, Long loginUserId) { List> viewItems = null; try { viewItems = cusBarcodeSyncViewQueryService.listByItemNos(matnrCodes); } catch (Exception ex) { log.warn("查询 cus_barcode_sync_view 失败,将仅按物料表校验:{}", ex.getMessage()); } if (viewItems != null && !viewItems.isEmpty()) { try { applyCusBarcodeSyncViewRowsToMatnr(viewItems, orderItemByCode, loginUserId); } catch (Exception ex) { log.warn("按条码视图写入物料主数据失败:{}", ex.getMessage()); } } for (String code : matnrCodes) { if (CusBarcodeSyncViewQueryService.orderMatnrHitsBarcodeView(code, viewItems)) { continue; } Matnr m = findLocalMatnrForOrderCode(code); if (m == null) { throw new CoolException("物料不存在:" + code); } } } private Matnr findLocalMatnrForOrderCode(String orderMatnr) { String t = StringUtils.trimToNull(orderMatnr); if (t == null) { return null; } return matnrService.getOneByCodeAndBatch(t, ""); } private static SyncOrdersItem resolveSyncOrderItem(Map orderItemByCode, String matCode) { return matCode == null ? null : orderItemByCode.get(matCode); } private static List> dedupeCusBarcodeViewRows(List> viewItems) { Map> firstByCode = new LinkedHashMap<>(); if (viewItems == null) { return Collections.emptyList(); } for (Map row : viewItems) { String matCode = CusBarcodeSyncViewQueryService.matnrCodeFromBarcode(Objects.toString(row.get("barcode"), null)); if (matCode == null) { continue; } firstByCode.putIfAbsent(matCode, row); } return new ArrayList<>(firstByCode.values()); } private void applyCusBarcodeSyncViewRowsToMatnr(List> viewItems, Map orderItemByCode, Long loginUserId) { if (viewItems == null || viewItems.isEmpty()) { return; } for (Map row : dedupeCusBarcodeViewRows(viewItems)) { String matCode = CusBarcodeSyncViewQueryService.matnrCodeFromBarcode(Objects.toString(row.get("barcode"), null)); if (matCode == null) { continue; } SyncOrdersItem syncItem = resolveSyncOrderItem(orderItemByCode, matCode); String viewSpec = StringUtils.trimToEmpty(Objects.toString(row.get("item_spec"), "")); String viewUnit = StringUtils.trimToNull(Objects.toString(row.get("unit_no"), null)); String viewItemName = StringUtils.trimToNull(Objects.toString(row.get("item_name"), null)); String incomingName = syncItem == null ? null : StringUtils.trimToNull(syncItem.getMaktx()); Matnr local = matnrService.getOneByCodeAndBatch(matCode, ""); if (local == null) { Matnr matnr = new Matnr(); matnr.setCode(matCode) .setBatch("") .setName(incomingName != null ? incomingName : (viewItemName != null ? viewItemName : matCode)) .setSpec(viewSpec) .setUnit(viewUnit) .setStockUnit(viewUnit) .setStatus(1) .setCreateBy(loginUserId) .setUpdateBy(loginUserId) .setCreateTime(new Date()) .setUpdateTime(new Date()); matnrService.save(matnr); continue; } boolean nameDiff = incomingName != null && !StringUtils.equals(StringUtils.trimToEmpty(local.getName()), incomingName); boolean specDiff = !StringUtils.equals(StringUtils.trimToEmpty(local.getSpec()), viewSpec); boolean unitDiff = viewUnit != null && (!StringUtils.equals(StringUtils.trimToEmpty(local.getUnit()), viewUnit) || !StringUtils.equals(StringUtils.trimToEmpty(local.getStockUnit()), viewUnit)); if (!nameDiff && !specDiff && !unitDiff) { continue; } Matnr update = new Matnr(); update.setId(local.getId()); if (nameDiff) { update.setName(incomingName); } if (specDiff) { update.setSpec(viewSpec); } if (unitDiff) { update.setUnit(viewUnit).setStockUnit(viewUnit); } update.setUpdateBy(loginUserId).setUpdateTime(new Date()); matnrService.updateById(update); } } }