package com.foreverwin.mesnac.integration.service.impl;

import com.alibaba.fastjson.JSON;
import com.foreverwin.mesnac.common.constant.Constants;
import com.foreverwin.mesnac.common.constant.CustomFieldConstant;
import com.foreverwin.mesnac.common.dto.LabelPrintDto;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.model.PrintLog;
import com.foreverwin.mesnac.common.service.PrintLogService;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.mesnac.dispatch.model.ItemBatch;
import com.foreverwin.mesnac.dispatch.service.ItemBatchService;
import com.foreverwin.mesnac.integration.dto.*;
import com.foreverwin.mesnac.integration.service.InterfaceService;
import com.foreverwin.mesnac.meapi.model.*;
import com.foreverwin.mesnac.meapi.service.*;
import com.foreverwin.modular.core.exception.BusinessException;
import com.foreverwin.modular.core.meext.MEServices;
import com.sap.me.common.CustomValue;
import com.sap.me.common.MaterialType;
import com.sap.me.common.ObjectReference;
import com.sap.me.common.ProcurementType;
import com.sap.me.demand.*;
import com.sap.me.productdefinition.RouterStep;
import com.sap.me.productdefinition.*;
import com.sap.me.production.ChangeProductionServiceInterface;
import com.visiprise.globalization.DateGlobalizationServiceInterface;
import com.visiprise.globalization.GlobalizationService;
import com.visiprise.model.BOMType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 *
 * @author Leon
 * @date 2021-06-16
 *
 * 接口服务类
 *
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class InterfaceServiceImpl implements InterfaceService {

    @Autowired
    private BomService bomService;
    @Autowired
    private ItemService itemService;
    @Autowired
    private RouterService routerService;
    @Autowired
    private ResrceService resrceService;
    @Autowired
    private PrintLogService printLogService;
    @Autowired
    private ShopOrderService shopOrderService;
    @Autowired
    private ItemBatchService itemBatchService;
    @Autowired
    private OperationService operationService;
    @Autowired
    private CustomFieldsService customFieldsService;



    @Override
    public void itemSync(String site, ItemSyncRequest itemSyncRequest) throws Exception{
        //物料
        String item = itemSyncRequest.getITEM();
        //版本:MES物料只有一个版本：A
        String revision = "A";
        //revision = StringUtil.notBlank(revision) ? revision : "A";
        //物料描述
        String itemDescription = itemSyncRequest.getMAKTX();
        //计量单位
        String unitOfMeasure = itemSyncRequest.getUNIT_OF_MEASURE();

        //状态
        String status = itemSyncRequest.getSTATUS();
        if (!"201".equals(status) && !"202".equals(status) && !"203".equals(status) && !"204".equals(status) && !"205".equals(status)) {
            throw BusinessException.build("物料状态可维护的值为：201(可下达)、202(冻结)、203(作废)、204(保留)、205(新建)");
        }
        String statusBo = HandleEnum.STATUS.getHandle(site, status);

        /**
         * Modify by Leon - 20210920
         * 物料类型-根据物料编码来判断，CAPP传过来为空（编码05开头为原始，02/03/06开头的为半成品）
         */
        String itemType = null;
        String procurementType = null;
        if (item.startsWith("02") || item.startsWith("03") || item.startsWith("06")) {
            itemType = "HALB";
            procurementType = "B";
        } else {
            itemType = "ROH";
            procurementType = "P";
        }

        //批次大小
        String lotSize = itemSyncRequest.getLOT_SIZE();
        lotSize = StringUtil.notBlank(lotSize) ? lotSize : "999999";

        //物料标准API
        ItemConfigurationServiceInterface itemServiceInterFace = MEServices.create("com.sap.me.productdefinition", "ItemConfigurationService", site);

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //物料是否存在
        String itemBo = HandleEnum.ITEM.getHandle(site, item, revision);
        Item itemModel = itemService.getById(itemBo);
        if (itemModel == null){
            //创建物料
            ItemConfiguration itemConfiguration = new ItemConfiguration();
            itemConfiguration.setItem(item);
            itemConfiguration.setRevision(revision);
            itemConfiguration.setProcurementType(ProcurementType.fromValue(procurementType));
            itemConfiguration.setLotSize(new BigDecimal(lotSize));
            itemConfiguration.setRef(itemBo);
            itemConfiguration.setCurrentRevision(true);
            itemConfiguration.setUnitOfMeasurement(unitOfMeasure);
            itemConfiguration.setMaterialType(MaterialType.fromValue(itemType));

            String dataTypeBo = "DataTypeBO:" +site+ ",ASSEMBLY,INV_NAC";
            itemConfiguration.setInventoryAssemblyDataTypeRef(dataTypeBo);
            //物料描述赋值
            List<ItemTranslation> itemTranslationList = new ArrayList<>();
            ItemTranslation itemTranslation = new ItemTranslation();
            itemTranslation.setLocale("zh");
            itemTranslation.setDescription(itemDescription);
            itemTranslationList.add(itemTranslation);
            itemConfiguration.setItemTranslationList(itemTranslationList);
            itemConfiguration.setStatusRef(statusBo);

            //数量限制为任意整数
            itemConfiguration.setQuantityRestriction(QuantityRestriction.ANY_NUMBER);

            //创建物料
            itemServiceInterFace.createItem(itemConfiguration);
        } else {
            //更新物料
            ObjectReference itemReference = new ObjectReference();
            itemReference.setRef(itemBo);
            ItemFullConfiguration itemFullConfiguration = itemServiceInterFace.readItem(itemReference);


            //物料描述赋值
            ItemFullConfiguration updateItem = itemFullConfiguration;
            updateItem.setUnitOfMeasurement(unitOfMeasure);
            updateItem.setMaterialType(MaterialType.fromValue(itemType));
            updateItem.setProcurementType(ProcurementType.fromValue(procurementType));
            updateItem.setLotSize(new BigDecimal(lotSize));
            updateItem.setStatusRef(statusBo);

            List<ItemTranslation> itemTranslationList = new ArrayList<>();
            ItemTranslation itemTranslation = new ItemTranslation();
            Locale locale = LocaleContextHolder.getLocale();
            itemTranslation.setLocale(locale.getLanguage());
            itemTranslation.setDescription(itemDescription);
            itemTranslationList.add(itemTranslation);
            updateItem.setItemTranslationList(itemTranslationList);

            //更新物料
            itemServiceInterFace.updateItem(updateItem);
        }

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        List<CustomFields> customFieldsList = new ArrayList<>();

        CustomFields customFields = null;
        //辅料类型：ACCESSORY_TYPE
        String accessoryType = itemSyncRequest.getACCESSORY_TYPE();
        if (StringUtil.notBlank(accessoryType)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_ACCESSORY_TYPE);
            customFields.setValue(accessoryType);
            customFieldsList.add(customFields);
        }

        //规格
        String spec = itemSyncRequest.getMAT_SPEC();
        if (StringUtil.notBlank(spec)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_MAT_SPEC);
            customFields.setValue(spec);
            customFieldsList.add(customFields);
        }

        //材质
        String texture = itemSyncRequest.getTEXTTURE();
        if (StringUtil.notBlank(texture)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_TEXTTURE);
            customFields.setValue(texture);
            customFieldsList.add(customFields);
        }

        //图号
        String drawing = itemSyncRequest.getDWG_NO();
        if (StringUtil.notBlank(drawing)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_DWG_NO);
            customFields.setValue(drawing);
            customFieldsList.add(customFields);
        }

        //每米重
        String perMeter = itemSyncRequest.getPER_METER();
        if (StringUtil.notBlank(perMeter)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_PER_METER);
            customFields.setValue(perMeter);
            customFieldsList.add(customFields);
        }

        //每平米重
        String perSquareMeter = itemSyncRequest.getPER_SQUARE_METER();
        if (StringUtil.notBlank(perSquareMeter)) {
            customFields = new CustomFields();
            customFields.setHandle(itemBo);
            customFields.setAttribute(CustomFieldConstant.ITEM_PER_SQUARE_METER);
            customFields.setValue(perSquareMeter);
            customFieldsList.add(customFields);
        }

        //自定义数据保存
        if (customFieldsList != null && customFieldsList.size() > 0) {
            customFieldsService.saveOrUpdateCustomFields(customFieldsList);
        }
    }

    @Override
    public void disRouterSync(String site, DisRouterSyncRequest disRouterSyncRequest) throws Exception {
        //获取工艺路线标准服务
        RouterConfigurationServiceInterface routerConfigurationService = MEServices.create("com.sap.me.productdefinition", "RouterConfigurationService", site);

        //工单编号作为工艺路线编号
        String router = disRouterSyncRequest.getROUTER();
        if (StringUtil.isBlank(router)) {
            throw BusinessException.build("工艺路线编号不能为空");
        }

        //工艺路线步骤是否有值
        List<DisRouterStepDto> routerStepDtoList = disRouterSyncRequest.getOPERATION_LIST();
        if (routerStepDtoList == null || routerStepDtoList.size() <= 0) {
            throw BusinessException.build("工艺路线步骤不能为空");
        }
        //工艺路线BO
        Float revision = new Float(1.0);
        String routerType = RouterType.SPECIAL.value();
        String routerBo = HandleEnum.ROUTER.getHandle(site, router, routerType, revision.toString());

        //查询工艺路线是否存在, 不存在版本默认为1.0，存在最大版本+1最为当前版本
        Router routerModel = routerService.getMaxRevisionRouter(site, router);
        if (routerModel != null) {
            Float currentRevision = new Float(routerModel.getRevision());
            revision = currentRevision + 1;
            routerBo = HandleEnum.ROUTER.getHandle(site, router, routerType, revision.toString());
        }

        //工艺路线参数组装
        RouterConfiguration routerConfiguration = new RouterConfiguration();
        routerConfiguration.setRef(routerBo);
        routerConfiguration.setRouter(router);
        routerConfiguration.setDescription(router);
        routerConfiguration.setRevision(revision.toString());
        routerConfiguration.setRouterType(com.sap.me.common.RouterType.SPECIAL);
        routerConfiguration.setCurrentRevision(true);
        routerConfiguration.setStatus(RouterStatus.Releasable);

        //入口步骤
        String entryRouterStep = null;
        //工艺路线步骤集合
        List<RouterStep> routerStepList = new ArrayList<>();

        //自定义字段集合
        List<CustomFields> customFieldsList = new ArrayList<>();
        //工艺路线步骤
        for (int i = 0; i < routerStepDtoList.size(); i++) {
            DisRouterStepDto routerStepDto = routerStepDtoList.get(i);
            String stepId = "90" + routerStepDto.getSTEP_ID();
            if (StringUtil.isBlank(entryRouterStep)) {
                entryRouterStep = stepId;
            }

            //上一步骤添加当前步骤为下一步骤
            if (i > 0) {
                RouterNextStep routerNextStep = new RouterNextStep();
                routerNextStep.setNextStepId(stepId);
                routerStepList.get(i-1).getRouterNextStepList().add(routerNextStep);
            }


            String resource = routerStepDto.getRESRCE();
            /*String operation = routerStepDto.getOPERATION();
            String _revision = routerStepDto.getREVISION();
            _revision = StringUtil.notBlank(_revision) ? _revision : "1.0";
            String description = routerStepDto.getOPERATION_DESCRIPTION();
            Operation operationModel = this.createResourceOfOperation(site, resource, operation, description, _revision);
            String operationBo = operationModel.getHandle();*/
            Operation operationModel = operationService.queryOperationByErpWorkCenter(site, resource);
            if (operationModel == null) {
                throw BusinessException.build("步骤标识【" + stepId + "】下【" + resource + "】对应的MES工序未维护");
            }
            String operation = operationModel.getOperation();
            String operationBo = operationModel.getHandle();

            //工艺路线步骤
            RouterStep routerStep = new RouterStep();
            routerStep.setSequence(new BigDecimal(i+1));
            routerStep.setStepId(stepId);
            routerStep.setDescription(operation);
            routerStep.setRework(true);
            routerStep.setQueueDecisionType(QueueDecisionType.COMPLETING_OPERATOR);

            //工艺路线步骤工序 RouterComponentContext
            RouterComponentContext routerComponentContext = new RouterComponentContext();
            RouterOperation routerOperation = new RouterOperation();
            //工艺路线步骤工序默认当前版本
            routerOperation.setOperationRef(operationBo);
            routerOperation.setStepType(RouterStepType.NORMAL);
            routerComponentContext.setRouterOperation(routerOperation);
            routerStep.setRouterComponentContext(routerComponentContext);

            //步骤入仓
            routerStepList.add(routerStep);

            //自定义字段
            String routerOperationBO = HandleEnum.ROUTER_OPERATION.getHandle(routerBo, stepId);
            CustomFields customFields = new CustomFields();
            customFields.setHandle(routerOperationBO);
            customFields.setAttribute(CustomFieldConstant.ROUTER_OP_PROD_TIME);
            customFields.setValue(routerStepDto.getPROD_TIME());
            customFieldsList.add(customFields);

            customFields = new CustomFields();
            customFields.setHandle(routerOperationBO);
            customFields.setAttribute(CustomFieldConstant.ROUTER_OP_OUT_SOURCE);
            customFields.setValue(routerStepDto.getOUT_SOURCE());
            customFieldsList.add(customFields);
        }//end for


        String lastStepId = "9999";
        if (router.endsWith("FX")) {
            //工艺路线编号“FX”结尾，标识返修工艺路线，添加返回原始工序步骤
            RouterStep routerStep = new RouterStep();
            routerStep.setSequence(new BigDecimal(lastStepId));
            RouterComponentContext routerComponentContext = new RouterComponentContext();
            RouterReturnStep routerReturnStep = new RouterReturnStep();
            routerReturnStep.setReturnType(ReturnType.ORIGINAL_OPERATION);
            routerReturnStep.setCompleteOriginal(true);
            routerComponentContext.setRouterReturnStep(routerReturnStep);
            routerStep.setRouterComponentContext(routerComponentContext);
            routerStep.setStepId(lastStepId);
            routerStepList.add(routerStep);
        } else {
            //添加完成工序
            RouterStep routerDoneStep = new RouterStep();
            routerDoneStep.setSequence(new BigDecimal(lastStepId));
            routerDoneStep.setStepId(lastStepId);
            RouterComponentContext routerDoneStepComponentContext = new RouterComponentContext();
            routerDoneStepComponentContext.setRouterDoneStep(true);
            routerDoneStep.setRouterComponentContext(routerDoneStepComponentContext);
            routerStepList.add(routerDoneStep);
        }

        //完成工序添加到下一步骤
        RouterNextStep routerNextStep = new RouterNextStep();
        routerNextStep.setNextStepId(lastStepId);
        routerStepList.get(routerStepList.size()-2).getRouterNextStepList().add(routerNextStep);


        routerConfiguration.setEntryRouterStep(entryRouterStep);
        routerConfiguration.setRouterStepList(routerStepList);
        //工艺路线创建
        routerConfigurationService.createRouter(routerConfiguration);

        //自定义数据保存
        if (customFieldsList != null && customFieldsList.size() > 0) {
            customFieldsService.saveOrUpdateCustomFields(customFieldsList);
        }
    }

    @Override
    public void bomSync(String site, BomSyncRequest bomSyncRequest) throws Exception {
        //获取物料清单标准服务
        BOMConfigurationServiceInterface bomConfigurationService = MEServices.create("com.sap.me.productdefinition", "BOMConfigurationService", site);
        //获取更改生产标准服务
        ChangeProductionServiceInterface changeProductionService = MEServices.create("com.sap.me.production", "ChangeProductionService", site);

        //工单编号作为工艺路线编号
        String shopOrder = bomSyncRequest.getSHOP_ORDER();
        String bom = shopOrder;
        if (StringUtil.isBlank(bom)) {
            throw BusinessException.build("工单编号不能为空");
        }

        //物料清单BO
        Float revision = new Float(1);
        String bomBo = HandleEnum.BOM.getHandle(site, bom, revision.toString(), BOMType._H);

        //物料清单组件清单是否有值
        List<BomComponentDto> bomComponentDtoList = bomSyncRequest.getBOM_LIST();
        if (bomComponentDtoList == null || bomComponentDtoList.size() <= 0) {
            throw BusinessException.build("物料清单组件不能为空");
        }
        bomComponentDtoList.sort((a,b) -> Float.compare(a.getSEQ().floatValue(), b.getSEQ().floatValue()));

        //查询工艺路线是否存在, 不存在版本默认为1.0，存在最大版本+1最为当前版本
        Bom bomModel = bomService.getMaxRevisionBom(site, bom);
        if (bomModel != null) {
            Float currentRevision = new Float(bomModel.getRevision());
            revision = currentRevision + 1;
            bomBo = HandleEnum.BOM.getHandle(site, bom, revision.toString(), BOMType._H);
        }

        //物料清单可下达状态：201
        String status201Bo = HandleEnum.STATUS.getHandle(site, "201");
        //物料清单数据组装
        BOMConfiguration bomConfiguration = new BOMConfiguration();
        bomConfiguration.setRef(bomBo);
        bomConfiguration.setBomType(BomType.SHOPORDERBOM);
        bomConfiguration.setBom(bom);
        bomConfiguration.setRevision(revision.toString());
        bomConfiguration.setCurrentRevision(true);
        bomConfiguration.setStatusRef(status201Bo);

        List<BOMComponentConfiguration> componentConfigurationList = new ArrayList<>();
        //物料清单组件
        for (int i = 0; i < bomComponentDtoList.size(); i++) {
            BomComponentDto componentDto = bomComponentDtoList.get(i);
            String componentGbo = HandleEnum.ITEM.getHandle(site, componentDto.getMATNR(), "A");

            /**
             * 工序参数说明：
             * 1.接口传过来的参数是ERP工作中心
             * 2.MES资源类型=生产车间_ERP工作中心
             * 3.MES资源类型=MES工序
             */
            String stepId = componentDto.getSTEP_ID();
            if (StringUtil.isBlank(stepId)) {
                throw BusinessException.build("步骤标示不能为空！");
            }
            Operation operationModel =  operationService.getOperationByRouterStepId(site, bom, stepId);
            if (operationModel == null) {
                throw BusinessException.build("步骤标识【"+stepId+"】在工艺路线【"+bom+"】未到对应的工序");
            }
            String operationBo = operationModel.getHandle();

            //BOMComponentConfiguration
            BOMComponentConfiguration componentConfiguration = new BOMComponentConfiguration();
            componentConfiguration.setBomRef(bomBo);
            componentConfiguration.setSequence(componentDto.getSEQ());
            componentConfiguration.setComponentContext(componentGbo);
            componentConfiguration.setQuantity(componentDto.getQTY());
            componentConfiguration.setBomComponentType(BomComponentTypeEnum.NORMAL);
            componentConfiguration.setOperationRef(operationBo);

            //组件自定义数据
            CustomValue customValue = new CustomValue();
            customValue.setName(CustomFieldConstant.BOM_COM_STEP_ID);
            customValue.setValue(componentDto.getSTEP_ID());
            componentConfiguration.getCustomData().add(customValue);

            componentConfigurationList.add(componentConfiguration);
        }

        bomConfiguration.setBomComponentList(componentConfigurationList);
        //物料清单保存
        bomConfigurationService.createBOM(bomConfiguration);
    }

    @Override
    public void routerSync(String site, RouterSyncRequest routerSyncRequest) throws Exception {
        //获取工艺路线标准服务
        RouterConfigurationServiceInterface routerConfigurationService = MEServices.create("com.sap.me.productdefinition", "RouterConfigurationService", site);
        //获取更改生产标准服务
        ChangeProductionServiceInterface changeProductionService = MEServices.create("com.sap.me.production", "ChangeProductionService", site);

        //工单编号作为工艺路线编号
        String shopOrder = routerSyncRequest.getSHOP_ORDER().trim();
        String router = shopOrder;
        if (StringUtil.isBlank(router)) {
            throw BusinessException.build("工单编号不能为空");
        }

        //工艺路线步骤是否有值
        List<RouterStepDto> routerStepDtoList = routerSyncRequest.getOPERATION_LIST();
        if (routerStepDtoList == null || routerStepDtoList.size() <= 0) {
            throw BusinessException.build("工艺路线步骤不能为空");
        }
        routerStepDtoList.sort((a,b) -> Integer.compare(Integer.parseInt(a.getSTEP_ID()), Integer.parseInt(b.getSTEP_ID())));

        //工艺路线BO
        Float revision = new Float(1.0);
        String routerType = RouterType.SHOPORDER_SPECIFIC.value();
        String routerBo = HandleEnum.ROUTER.getHandle(site, router, routerType, revision.toString());

        //查询工艺路线是否存在, 不存在版本默认为1.0，存在最大版本+1最为当前版本
        Router routerModel = routerService.getMaxRevisionRouter(site, router);
        if (routerModel != null) {
            Float currentRevision = new Float(routerModel.getRevision());
            revision = currentRevision + 1;
            routerBo = HandleEnum.ROUTER.getHandle(site, router, routerType, revision.toString());
        }

        //工艺路线参数组装
        RouterConfiguration routerConfiguration = new RouterConfiguration();
        routerConfiguration.setRef(routerBo);
        routerConfiguration.setRouter(router);
        routerConfiguration.setDescription(router);
        routerConfiguration.setRevision(revision.toString());
        routerConfiguration.setRouterType(com.sap.me.common.RouterType.SHOPORDER_SPECIFIC);
        routerConfiguration.setCurrentRevision(true);
        routerConfiguration.setStatus(RouterStatus.Releasable);

        //入口步骤
        String entryRouterStep = null;
        //工艺路线步骤集合
        List<RouterStep> routerStepList = new ArrayList<>();

        //自定义字段集合
        List<CustomFields> customFieldsList = new ArrayList<>();
        //工艺路线步骤
        for (int i = 0; i < routerStepDtoList.size(); i++) {
            RouterStepDto routerStepDto = routerStepDtoList.get(i);
            String stepId = routerStepDto.getSTEP_ID();
            String erpWorkCenter = routerStepDto.getOPERATION();

            if (StringUtil.isBlank(entryRouterStep)) {
                entryRouterStep = stepId;
            }

            //上一步骤添加当前步骤为下一步骤
            if (i > 0) {
                RouterNextStep routerNextStep = new RouterNextStep();
                routerNextStep.setNextStepId(stepId);
                routerStepList.get(i - 1).getRouterNextStepList().add(routerNextStep);
            }

            String operation = null;
            String operationBo = null;
            if (StringUtil.isBlank(erpWorkCenter) || "null".equals(erpWorkCenter)) {
                operation =  Constants.OP_WX_6106GX;
                Operation operationModel = operationService.getCurrentRevisionRef(site, operation);
                if (operationModel == null) {
                    throw BusinessException.build("工序编号【" +operation+ "】不存在");
                }
                operation = operationModel.getOperation();
                operationBo = operationModel.getHandle();
            } else {
                /**
                 * 工序参数说明：
                 * 1.接口传过来的参数是ERP工作中心
                 * 2.MES资源类型=生产车间_ERP工作中心
                 * 3.MES资源类型=MES工序
                 */
                Operation operationModel = operationService.queryOperationByErpWorkCenter(site, erpWorkCenter);
                if (operationModel == null) {
                    throw BusinessException.build("步骤标识【" + stepId + "】下ERP工作中心【" + erpWorkCenter + "】对应的MES工序未维护");
                }
                operation = operationModel.getOperation();
                operationBo = operationModel.getHandle();
            }

            //工艺路线步骤
            RouterStep routerStep = new RouterStep();
            routerStep.setSequence(new BigDecimal(i+1));
            routerStep.setStepId(stepId);
            routerStep.setDescription(operation);
            routerStep.setRework(false);
            routerStep.setQueueDecisionType(QueueDecisionType.COMPLETING_OPERATOR);

            //工艺路线步骤工序 RouterComponentContext
            RouterComponentContext routerComponentContext = new RouterComponentContext();
            RouterOperation routerOperation = new RouterOperation();
            //工艺路线步骤工序默认当前版本
            routerOperation.setOperationRef(operationBo);
            routerOperation.setStepType(RouterStepType.NORMAL);
            routerComponentContext.setRouterOperation(routerOperation);
            routerStep.setRouterComponentContext(routerComponentContext);

            //步骤入仓
            routerStepList.add(routerStep);

            //自定义字段
            String routerOperationBO = HandleEnum.ROUTER_OPERATION.getHandle(routerBo, stepId);
            CustomFields customFields = new CustomFields();
            customFields.setHandle(routerOperationBO);
            customFields.setAttribute(CustomFieldConstant.ROUTER_OP_PROD_TIME);
            customFields.setValue(routerStepDto.getPROD_TIME());
            customFieldsList.add(customFields);

            customFields = new CustomFields();
            customFields.setHandle(routerOperationBO);
            customFields.setAttribute(CustomFieldConstant.ROUTER_OP_OUT_SOURCE);
            customFields.setValue(routerStepDto.getOUT_SOURCE());
            customFieldsList.add(customFields);
        }//end for

        //添加完成工序
        String completeStepId = "9999";
        RouterStep routerDoneStep = new RouterStep();
        routerDoneStep.setSequence(new BigDecimal(completeStepId));
        routerDoneStep.setStepId(completeStepId);
        RouterComponentContext routerDoneStepComponentContext = new RouterComponentContext();
        routerDoneStepComponentContext.setRouterDoneStep(true);
        routerDoneStep.setRouterComponentContext(routerDoneStepComponentContext);
        routerStepList.add(routerDoneStep);

        //完成工序添加到下一步骤
        RouterNextStep routerNextStep = new RouterNextStep();
        routerNextStep.setNextStepId(completeStepId);
        routerStepList.get(routerStepList.size()-2).getRouterNextStepList().add(routerNextStep);


        routerConfiguration.setEntryRouterStep(entryRouterStep);
        routerConfiguration.setRouterStepList(routerStepList);
        //工艺路线创建
        routerConfigurationService.createRouter(routerConfiguration);

        //自定义数据保存
        if (customFieldsList != null && customFieldsList.size() > 0) {
            customFieldsService.saveOrUpdateCustomFields(customFieldsList);
        }
    }

    @Override
    public void shopOrderSync(String site, ShopOrderSyncRequest shopOrderSyncRequest) throws Exception {
        //获取工单标准服务
        ShopOrderServiceInterface shopOrderMeService = MEServices.create("com.sap.me.demand", "ShopOrderService", site);
        DateGlobalizationServiceInterface dateService = GlobalizationService.getInvariantService("com.visiprise.globalization.DateGlobalizationService");

        String shopOrder = shopOrderSyncRequest.getSHOP_ORDER();
        if (StringUtil.isBlank(shopOrder)) {
            throw BusinessException.build("工单编号不能为空");
        }
        String shopOrderBo = HandleEnum.SHOP_ORDER.getHandle(site, shopOrder);

        //工单状态校验
        String status = shopOrderSyncRequest.getSTATUS();
        if (!"501".equals(status) && !"504".equals(status)) {
            throw BusinessException.build("未定义的工单状态,定义值为:501|可下达，504|已关闭");
        }

        //工单时间时间处理
        String startDateTime = shopOrderSyncRequest.getPLANNED_START_DATE();
        String completeDateTime = shopOrderSyncRequest.getPLANNED_COMP_DATE();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //查询工单是否存在
        ShopOrder shopOrderModel = shopOrderService.getById(shopOrderBo);
        if (shopOrderModel == null) {
            //工单不存在新建
            CreateShopOrderRequest request = new CreateShopOrderRequest();
            request.setShopOrderRef(shopOrderBo);
            request.setShopOrder(shopOrder);
            request.setStatus(ShopOrderStatus.fromValue(status));
            //订单类型：默认为生产
            request.setShopOrderType(ShopOrderType.PRODUCTION);

            //校验计划物料不能为空
            String plannedItem = shopOrderSyncRequest.getPLANNED_ITEM();
            String plannedBom = shopOrderSyncRequest.getPLANNED_BOM();
            plannedBom = StringUtil.notBlank(plannedBom) ? plannedBom : shopOrder;
            String plannedRouter = shopOrderSyncRequest.getPLANNED_ROUTER();
            plannedRouter = StringUtil.notBlank(plannedRouter) ? plannedRouter : shopOrder;

            //计划BOM类型，默认为工单BOM：H
            String bomType = BomType.SHOPORDERBOM.value();
            String routerType = RouterType.SHOPORDER_SPECIFIC.value();

            if (StringUtil.isBlank(plannedItem)) {
                throw BusinessException.build("工单的计划物料不能拿为空");
            }

            //查询物料清单和工艺路线
            Bom bomModel = bomService.getMaxRevisionBom(site, plannedBom);
            if (bomModel == null) {
                throw BusinessException.build("工单【" +shopOrder+ "】的物料清单未同步！");
            }

            Router routerModel = routerService.getMaxRevisionRouter(site, plannedRouter);
            if (routerModel == null) {
                throw BusinessException.build("工单【" +shopOrder+ "】的工艺路线未同步！");
            }

            String plannedItemBo = HandleEnum.ITEM.getHandle(site, plannedItem, "A");
            String plannedBomBo = HandleEnum.BOM.getHandle(site, plannedBom, bomType, "#");
            String plannedRouterBo = HandleEnum.ROUTER.getHandle(site, plannedRouter, routerType, "#");

            request.setPlannedItemRef(plannedItemBo);
            request.setPlannedBomRef(plannedBomBo);
            request.setPlannedRouterRef(plannedRouterBo);
            request.setPriority(shopOrderSyncRequest.getPRIORITY());
            request.setQuantityOrdered(shopOrderSyncRequest.getORDER_QTY());
            request.setQuantityToBuild(shopOrderSyncRequest.getPROD_QTY());


            if (StringUtil.notBlank(startDateTime)) {
                request.setPlannedStartDate(dateService.createDateTime(simpleDateFormat.parse(startDateTime).getTime()));
            }
            if (StringUtil.notBlank(completeDateTime)) {
                request.setPlannedCompletionDate(dateService.createDateTime(simpleDateFormat.parse(completeDateTime).getTime()));
            }
            //工单创建
            shopOrderMeService.createShopOrder(request);
        } else {
            //工单存在更新或者关闭
            if ("504".equals(status)) {
                CloseShopOrderRequest request = new CloseShopOrderRequest();
                request.setShopOrderRef(shopOrderBo);
                request.setStatus(CloseShopOrderStatus.Closed);
                //request.setCloseSubassembly(true);
                shopOrderMeService.closeShopOrder(request);
                return;
            }

            //工单更新
            ObjectReference shopOrderObj = new ObjectReference();
            shopOrderObj.setRef(shopOrderBo);
            ShopOrderFullConfiguration shopOrderFull = shopOrderMeService.readShopOrder(shopOrderObj);
            if (shopOrderFull == null) {
                throw BusinessException.build("查询工单信息失败");
            }
            shopOrderFull.setQuantityOrdered(shopOrderSyncRequest.getORDER_QTY());
            shopOrderFull.setQuantityToBuild(shopOrderSyncRequest.getPROD_QTY());
            shopOrderFull.setModifiedDateTime(dateService.createDateTime());
            if (StringUtil.notBlank(startDateTime)) {
                shopOrderFull.setPlannedStartDate(dateService.createDateTime(simpleDateFormat.parse(startDateTime).getTime()));
            }
            if (StringUtil.notBlank(completeDateTime)) {
                shopOrderFull.setPlannedCompletionDate(dateService.createDateTime(simpleDateFormat.parse(completeDateTime).getTime()));
            }

            //工单最后修改时间
            shopOrderFull.setModifiedDateTime(dateService.createDateTime(shopOrderModel.getModifiedDateTime().getTime()));
            shopOrderMeService.updateShopOrder(shopOrderFull);
        }

        //工单自定义字段
        List<CustomFields> customFieldsList = new ArrayList<>();
        CustomFields customFields = new CustomFields();
        if (StringUtil.notBlank(shopOrderSyncRequest.getFACTORY())) {
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_FACTORY);
            customFields.setValue(shopOrderSyncRequest.getFACTORY());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getWORK_ORDER())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_WORK_ORDER);
            customFields.setValue(shopOrderSyncRequest.getWORK_ORDER());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getITEM_NUMBER())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_ITEM_NUMBER);
            customFields.setValue(shopOrderSyncRequest.getITEM_NUMBER());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getSHOP_ORDER_TYPE())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_SHOP_ORDER_TYPE);
            customFields.setValue(shopOrderSyncRequest.getSHOP_ORDER_TYPE());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getPRODUCT_CATEGORY())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_PRODUCT_CATEGORY);
            customFields.setValue(shopOrderSyncRequest.getPRODUCT_CATEGORY());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getCOMMENTS())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_COMMENTS);
            customFields.setValue(shopOrderSyncRequest.getCOMMENTS());
            customFieldsList.add(customFields);
        }

        if (StringUtil.notBlank(shopOrderSyncRequest.getSTART_PRODUCT())) {
            customFields = new CustomFields();
            customFields.setHandle(shopOrderBo);
            customFields.setAttribute(CustomFieldConstant.SO_START_PRODUCT);
            customFields.setValue(shopOrderSyncRequest.getSTART_PRODUCT());
            customFieldsList.add(customFields);
        }


        //自定义字段保存
        if (customFieldsList != null && customFieldsList.size() > 0) {
            customFieldsService.saveOrUpdateCustomFields(customFieldsList);
        }
    }

    @Override
    public void saveItemBatch(String site, ItemBatchReceiveRequest itemBatchReceiveRequest) {
        List<ItemBatchDto> itemBatchDtoList = itemBatchReceiveRequest.getPURCHASE_ORDER_LIST();
        if (itemBatchDtoList == null || itemBatchDtoList.size() <= 0) {
            throw BusinessException.build("接口参数【PURCHASE_ORDER_LIST】不能为空");
        }

        String supplier = itemBatchReceiveRequest.getSUPPLIER();
        LocalDateTime now = LocalDateTime.now();


        //循环处理 物料批次
        for (int i = 0; i < itemBatchDtoList.size(); i++) {
            ItemBatchDto itemBatchDto = itemBatchDtoList.get(i);
            String item = itemBatchDto.getITEM();
            if (StringUtil.isBlank(item)) {
                throw BusinessException.build("物料参数不能为空！");
            }
            Item itemModel = itemService.selectCurrent(site, item);
            if (itemModel == null) {
                throw BusinessException.build("物料【" +item+ "】没有维护当前版本！");
            }

            String spec = itemBatchDto.getSPEC();
            String texture = itemBatchDto.getTEXTURE();
            String batch = itemBatchDto.getBATCH();
            if (StringUtil.isBlank(item)) {
                throw BusinessException.build("批次号不能为空");
            }
            String factory = itemBatchDto.getFACTORY();

            String inventory = item + "*" + batch;
            //查询物料和批次是否已经存在记录
            List<ItemBatch> itemBatchList = itemBatchService.findItemBatch(site, item, batch);
            if (itemBatchList != null && itemBatchList.size() > 0) {
                //更新时间
                ItemBatch itemBatch = itemBatchList.get(0);
                itemBatch.setSpec(spec);
                itemBatch.setTexture(texture);
                itemBatch.setModifyUser(Constants.SITE_ADMIN);
                itemBatch.setModifiedDateTime(now);
                itemBatchService.updateById(itemBatch);
            } else {
                //新增物料批次数据
                ItemBatch itemBatch = new ItemBatch();
                itemBatch.setHandle(HandleEnum.ITEM_BATCH.getHandle(site, item, batch));
                itemBatch.setSite(site);
                itemBatch.setFactory(factory);
                itemBatch.setItem(item);
                itemBatch.setBatch(batch);
                itemBatch.setSpec(spec);
                itemBatch.setTexture(texture);
                itemBatch.setSupplier(supplier);
                itemBatch.setLabel(inventory);
                itemBatch.setIsPrint("false");
                itemBatch.setCreateUser(Constants.SITE_ADMIN);
                itemBatch.setCreatedDateTime(now);
                itemBatchService.save(itemBatch);

                //打印模板参数
                List<LabelPrintDto> labelPrintDtoList = new ArrayList<>();
                LabelPrintDto labelPrintDto = new LabelPrintDto();
                labelPrintDto.setSite(site);
                labelPrintDto.setPrintTemplate(Constants.PRINT_TYPE_INV);
                labelPrintDto.setItem(item);
                labelPrintDto.setItemDescription(itemModel.getDescription());
                labelPrintDto.setSupplier(supplier);
                //labelPrintDto.setBatch(inventory);
                labelPrintDto.setBatch(batch);
                labelPrintDto.setLabel(inventory);
                labelPrintDtoList.add(labelPrintDto);

                //记录打印数据
                PrintLog printLog = new PrintLog();
                printLog.setHandle(UUID.randomUUID().toString());
                printLog.setSite(site);
                printLog.setCategory(Constants.PRINT_TYPE_INV);
                printLog.setPrintName("");
                printLog.setPrintTemplate(Constants.PRINT_TYPE_INV);
                printLog.setPrintParam(JSON.toJSONString(labelPrintDtoList));
                printLog.setInventory(inventory);
                printLog.setItemBo(itemModel.getHandle());
                printLog.setIsPrint("false");
                printLog.setPrintNum(0);
                printLog.setCreateUser("SITE_ADMIN");
                printLog.setCreatedDateTime(LocalDateTime.now());
                printLogService.save(printLog);

            }

        }

    }

    /**
     * 资源对应的工序创建
     *
     */
    Operation createResourceOfOperation(String site, String resource, String operation, String description, String revision) {
        String resourceBo = HandleEnum.RESOURCE.getHandle(site, resource);
        Resrce resourceModel =  resrceService.getById(resourceBo);
        if (resourceModel == null) {
            throw BusinessException.build("设备【" +resource+ "】不存在！");
        }
        String operationBo = HandleEnum.OPERATION.getHandle(site, operation, revision);

        //查询设备所属类型以及对应工序
        List<Map<String, Object>> mapList = resrceService.getResourceOperation(resourceBo);
        if (mapList == null || mapList.size() <= 0) {
            throw BusinessException.build("设备【" +resource+ "】不存在！");
        }
        Map<String, Object> map = mapList.get(0);
        String _operationBo = (String) map.get("OPERATION_BO");
        String resourceType = (String) map.get("RESOURCE_TYPE");
        if (StringUtil.isBlank(resourceType)) {
            throw BusinessException.build("设备【" +resource+ "】没有维护设备类型！");
        }

        //查询工序是否存在
        Operation queryOperation = operationService.getById(operationBo);
        if (queryOperation != null) {
            if (operationBo.equals(_operationBo)) {
                return  queryOperation;
            } else {
                throw BusinessException.build("工序【" + operation + " 】已经存在！");
            }
        }

        String status201Bo = HandleEnum.STATUS.getHandle(site, "201");
        String resourceTypeBo = HandleEnum.RESOURCE_TYPE.getHandle(site, resourceType);
        //创建工序
        Operation operationModel = new Operation();
        operationModel.setHandle(operationBo);
        operationModel.setSite(site);
        operationModel.setOperation(operation);
        operationModel.setRevision(revision);
        operationModel.setDescription(description);
        operationModel.setCurrentRevision("true");
        operationModel.setStatusBo(status201Bo);
        operationModel.setType("N");
        operationModel.setResourceTypeBo(resourceTypeBo);
        operationModel.setCreatedDateTime(LocalDateTime.now());
        operationService.save(operationModel);

        return operationModel;
    }
}
