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.Collection; import java.util.Collections; 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 同步(云仓通知单、无订单组托等共用)。 * 副库读无事务({@link CusBarcodeSyncViewQueryService} {@code NOT_SUPPORTED}),主库写 {@link CusBarcodeSyncMatnrApplyService} {@code REQUIRES_NEW}。 */ @Service @Slf4j public class CusBarcodeSyncMatnrService { @Autowired private CusBarcodeSyncViewQueryService cusBarcodeSyncViewQueryService; @Autowired private MatnrService matnrService; @Autowired private ConfigService configService; @Autowired private CusBarcodeSyncMatnrApplyService cusBarcodeSyncMatnrApplyService; /** 与云仓通知单同步:按明细 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); } } cusBarcodeSyncMatnrApplyService.applyFromViewRows(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 { cusBarcodeSyncMatnrApplyService.applyFromViewRows(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, ""); } }