WorkOrderManagerImpl.java

package com.mycim.server.workorder.manager.impl;

import com.fa.sesa.exception.Assert;
import com.fa.sesa.exception.Errors;
import com.fa.sesa.exception.SystemIllegalArgumentException;
import com.fa.sesa.threadlocal.LocalContext;
import com.mycim.framework.jdbc.Page;
import com.mycim.framework.oid.IDGenerators;
import com.mycim.framework.oid.type.IDNames;
import com.mycim.framework.oid.type.SequenceNames;
import com.mycim.framework.utils.beans.BeanUtils;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.CollectionUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.lang.math.NumberUtils;
import com.mycim.framework.utils.lang.time.DateUtils;
import com.mycim.server.asm.manager.MaterialManager;
import com.mycim.server.asm.manager.WarehouseManager;
import com.mycim.server.base.manager.NamedObjectManager;
import com.mycim.server.base.manager.TransactionLogManager;
import com.mycim.server.prp.manager.OperationManager;
import com.mycim.server.system.manager.ReferenceFileManager;
import com.mycim.server.workorder.dao.WorkOrderDao;
import com.mycim.server.workorder.manager.WorkOrderManager;
import com.mycim.valueobject.ObjectList;
import com.mycim.valueobject.bas.NamedObject;
import com.mycim.valueobject.bas.TransactionLog;
import com.mycim.valueobject.consts.AsmConst;
import com.mycim.valueobject.consts.ReferenceDetailNames;
import com.mycim.valueobject.consts.ReferenceFileConst;
import com.mycim.valueobject.consts.TransactionNames;
import com.mycim.valueobject.erp.workOrder.SdsWorkOrderInfo;
import com.mycim.valueobject.erp.workOrder.SdsWorkOrderMaterialInfo;
import com.mycim.valueobject.erp.workOrder.WorkOrderImpSourceWaferDb;
import com.mycim.valueobject.inv.LotInventoryDO;
import com.mycim.valueobject.inv.MaterialDO;
import com.mycim.valueobject.inv.WarehouseTransBO;
import com.mycim.valueobject.inv.value.WarehouseNames;
import com.mycim.valueobject.prp.Operation;
import com.mycim.valueobject.prp.WorkOrder;
import com.mycim.valueobject.prp.WorkOrderLine;
import com.mycim.valueobject.wip.Lot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

@Service
@Transactional
public class WorkOrderManagerImpl implements WorkOrderManager {

    @Autowired
    private WorkOrderDao workOrderDao;

    @Autowired
    private TransactionLogManager transactionLogManager;

    @Autowired
    private NamedObjectManager objectManager;

    @Autowired
    private MaterialManager materialManager;

    @Autowired
    private NamedObjectManager namedObjectManager;

    @Autowired
    private ReferenceFileManager referenceFileManager;

    @Autowired
    private WarehouseManager warehouseManager;

    @Autowired
    private OperationManager operationManager;

    @Override
    public WorkOrder getWorkOrderById(String orderId) {
        return workOrderDao.getWorkOrderById(orderId);
    }

    @Override
    public WorkOrder insertWorkOrder(WorkOrder workOrder) {

        TransactionLog transactionLog = transactionLogManager
                .startTransactionLog(workOrder.getTransPerformedby(), workOrder.getTransId());
        long transRrn = transactionLog.getTransRrn();
        long objectRrn = objectManager.insertNamedObject(workOrder, transRrn);

        workOrder.setWorkorderRrn(objectRrn);
        workOrder.setCreatedUserId(workOrder.getCreateUser());// 创建者
        workOrder.setStatus("ACTIVE");
        workOrder.setComments(workOrder.getComments());
        workOrderDao.insertWorkOrder(workOrder);

        List<WorkOrderLine> workOrderLines = workOrder.getWorkOrderLines();

        if (CollectionUtils.isNotEmpty(workOrderLines)) {
            for (WorkOrderLine workOrderLine : workOrderLines) {
                Long workOrderLineRrn = Long
                        .parseLong(IDGenerators.get(IDNames.SEQUENCE).generateId(SequenceNames.MODULE_SEQ_OBJECT_RRN));
                workOrderLine.setWorkorderLineRrn(workOrderLineRrn);
                workOrderLine.setWorkorderRrn(workOrder.getWorkorderRrn());
            }

            workOrderDao.insertWorkOrderLines(workOrderLines);
        }

        return workOrder;
    }

    @Override
    public void updateWorkOrder(WorkOrder workOrder) {
        workOrderDao.updateWorkOrder(workOrder);
    }

    @Override
    public List<WorkOrder> getWorkOrderByIdLike(String orderId) {
        return workOrderDao.getWorkOrderByIdLike(orderId);
    }

    @Override
    public Page getWorkOrderImpDBByOrderRrn(Page page, long orderRrn) {
        return workOrderDao.getWorkOrderImpDBByOrderRrn(page, orderRrn);
    }

    @Override
    public WorkOrderImpSourceWaferDb getImportWkByImpRrn(String importRrn) {
        return workOrderDao.getImportWkByImpRrn(importRrn);
    }

    @Override
    public WorkOrder getWorkOrderByRrn(Long workOrderRrn) {
        return workOrderDao.getWorkOrderByRrn(workOrderRrn);
    }

    @Override
    public List<WorkOrder> getWorkOrderByCondition(Map<String, Object> condition) {
        return workOrderDao.getWorkOrderByCondition(condition);
    }

    @Override
    public void workOrderImpCreateLotSuccess(List<WorkOrderImpSourceWaferDb> list, Lot lot, Long workOrderRrn) {
        String carrierId = objectManager.getInstanceId(lot.getCarrierRrn());
        for (WorkOrderImpSourceWaferDb db : list) {
            db.setLotRrn(lot.getLotRrn());
            db.setLotId(lot.getLotId());
            db.setCarrierRrn(lot.getCarrierRrn());
            db.setCarrierId(carrierId);
        }
        workOrderDao.workOrderImpCreateLotSuccess(list);
        //对比完成数量,更改workorder状态
        //package完成后才算完成
		/*int compleWf = workOrderDao.getCompleteDieQtyByWorkOrderRrn(workOrderRrn);
		WorkOrder workOrderByRrn = workOrderDao.getWorkOrderByRrn(workOrderRrn);
		if(compleWf >= workOrderByRrn.getOrderDieQty()) {
			workOrderDao.completeWorkOrder(workOrderRrn);
		}*/

    }

    @Override
    public int getCompleteDieQtyByWorkOrderRrn(Long workOrderRrn) {
        return workOrderDao.getCompleteDieQtyByWorkOrderRrn(workOrderRrn);
    }

    @Override
    public void completeWorkOrder(Long workOrderRrn) {
        workOrderDao.completeWorkOrder(workOrderRrn);
    }

    @Override
    public List<String> getMesProductIdBySdsProductId(String sdsProductId) {
        return workOrderDao.getMesProductIdBySdsProductId(sdsProductId);
    }

    @Override
    public boolean checkMesProSdsProMapping(String productId, String sdsProductId) {
        return workOrderDao.checkMesProSdsProMapping(productId, sdsProductId);
    }

    @Override
    public void insertProductMapping(String productId, String sdsProductId, String userId) {
        Assert.isFalse(checkMesProSdsProMapping(productId, sdsProductId),
                       Errors.create().content("{} mapping to {} exists!").build());
        workOrderDao.insertProductMapping(productId, sdsProductId, userId);
    }

    @Override
    public List<SdsWorkOrderInfo> getSdsWorkOrderInfoByWorkOrderId(String workorderId) {
        return workOrderDao.getSdsWorkOrderInfoByWorkOrderId(workorderId);
    }

    @Override
    public List<Map> getSdsMesMappingInfoByProductId(String productId) {
        return workOrderDao.getSdsMesMappingInfoByProductId(productId);
    }

    @Override
    public boolean checkAreadySdsProReceive(String deleteProductMapping) {
        int count = workOrderDao.getAreadySdsProReceiveCount(deleteProductMapping);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void deleteProductMapping(String mesproduct, String sdsproduct) {
        workOrderDao.deleteProductMapping(mesproduct, sdsproduct);
    }

    @Override
    public List<SdsWorkOrderMaterialInfo> getSdsMaterialInfoByWorkOrderId(long workorderRrn) {
        return workOrderDao.getSdsMaterialInfoByWorkOrderId(workorderRrn);
    }

    @Override
    public void mappingReceive(List<HashMap> workorderIds) {
        if (CollectionUtils.isNotEmpty(workorderIds)) {
            Set<WorkOrderImpSourceWaferDb> dataSet = new HashSet<WorkOrderImpSourceWaferDb>();
            for (HashMap workorderMap : workorderIds) {
                String workorderId = MapUtils.getString(workorderMap, "workorderId");
                String mesProduct = MapUtils.getString(workorderMap, "mesProduct");
                long workorderRrn = MapUtils.getLong(workorderMap, "workorderRrn", 0L);
                checkReceiveList(dataSet, workorderRrn, workorderId, mesProduct);
            }
            List<WorkOrderImpSourceWaferDb> dataList = new ArrayList<WorkOrderImpSourceWaferDb>(dataSet);
            storeMaterInfo(dataList);
            workOrderDao.storeWorkOrderImpDBList(dataList);
        }
    }

    @Override
    public void addShipQty4WorkOrder(WorkOrder workOrder, int qty) {
        TransactionLog transactionLog = transactionLogManager
                .startTransactionLog(workOrder.getTransPerformedby(), TransactionNames.ADD_WO_SHIPQTY);

        Integer shippedQty = workOrder.getShippedQty() == null ? 0 : workOrder.getShippedQty();

        workOrderDao.updateShipQty4WorkOrder(workOrder.getWorkorderRrn(), shippedQty + qty);

        transactionLogManager.markTransactionLog(transactionLog);
    }

    @Override
    public int getWorkorderAvalibleShipQty(String workorderId) {
        WorkOrder workOrder = this.getWorkOrderById(workorderId);

        Integer planQty = workOrder.getPlannedYield() == null ? 0 : workOrder.getPlannedYield();
        Integer shippedQty = workOrder.getShippedQty() == null ? 0 : workOrder.getShippedQty();

        return planQty - shippedQty;
    }

    @Override
    public void addStartQty4WorkOrder(WorkOrder workOrder, int qty) {
        TransactionLog transactionLog = transactionLogManager
                .startTransactionLog(workOrder.getTransPerformedby(), TransactionNames.ADD_WO_STARTQTY);

        Integer startQty = workOrder.getStartQty() == null ? 0 : workOrder.getStartQty();

        workOrderDao.updateStartQty4WorkOrder(workOrder.getWorkorderRrn(), startQty + qty);

        transactionLogManager.markTransactionLog(transactionLog);

    }

    @Override
    public int getWorkorderAvalibleStartQty(String workorderId) {
        WorkOrder workOrder = this.getWorkOrderById(workorderId);

        Integer planQty = workOrder.getPlannedYield() == null ? 0 : workOrder.getPlannedYield();
        Integer startQty = workOrder.getShippedQty() == null ? 0 : workOrder.getStartQty();

        return planQty - startQty;
    }

    private void checkReceiveList(Set<WorkOrderImpSourceWaferDb> dataList, long sdsWorkorderRrn, String sdsworkorderId,
                                  String mesProductId) {
        //检查fabid
        long fab_rrn = LocalContext.getFacilityRrn();
        // 根据workorderid 获取sds workorder info 一条数据
        SdsWorkOrderInfo sdsWorkOrderInfo = workOrderDao.getNotReceiveSdsWorkOrderByWorkOrderRrn(sdsWorkorderRrn);
        Assert.notNull(sdsWorkOrderInfo, Errors.create().content("workOrder error: {}").args(sdsworkorderId).build());
        // sds product 与mes product 映射校验
        Assert.isFalse(StringUtils.isBlank(mesProductId), Errors.create().content(
                "MESPRODUCT-SDSPRODUCT mapping not " + "exists:workorderId:{} ,SDSPRODUCT:{}")
                                                                .args(sdsworkorderId, sdsWorkOrderInfo.getSdsProduct())
                                                                .build());
        NamedObject product = namedObjectManager
                .getNamedObject(mesProductId, LocalContext.getFacilityRrn(), ObjectList.PRODUCT_KEY);
        Assert.isFalse(product == null || product.getInstanceRrn() == 0L,
                       Errors.create().content("productId not exist: {}").args(mesProductId).build());

        //改变t_sds_workorder_info 表中receive_status 状态,修正为1,则表示已重新接收
        workOrderDao.updateProductMappingStatus(sdsWorkOrderInfo.getWorkorderRrn(), "1");
        WorkOrder workOrder = getWorkOrderById(sdsWorkOrderInfo.getWorkorderId());
        if (workOrder == null) {
            workOrder = new WorkOrder();
            workOrder.setWorkorderId(sdsWorkOrderInfo.getWorkorderId());
            workOrder.setObject(ObjectList.WORKORDER);
            workOrder.setNamedSpace(namedObjectManager.getNamedSpace(fab_rrn, ObjectList.WORKORDER));
            workOrder.setInstanceId(sdsWorkOrderInfo.getWorkorderId());
            workOrder.setTransPerformedby(LocalContext.getUserId());
            workOrder.setTransId("CREATE");

            workOrder.setWorkorderPriority(sdsWorkOrderInfo.getWorkorderPriority());
            workOrder.setProductId(mesProductId);
            workOrder.setOrderDieQty(sdsWorkOrderInfo.getOrderDieQty());
            workOrder.setStartDay(StringUtils.isEmpty(sdsWorkOrderInfo.getStartDayStr()) ? null : new Timestamp(
                    DateUtils.parse(sdsWorkOrderInfo.getStartDayStr(), DateUtils.DATE_FORMAT4DAY).getTime()));
            workOrder.setRequireDay(StringUtils.isEmpty(sdsWorkOrderInfo.getRequireDayStr()) ? null : new Timestamp(
                    DateUtils.parse(sdsWorkOrderInfo.getRequireDayStr(), DateUtils.DATE_FORMAT4DAY).getTime()));
            workOrder.setDayDay(StringUtils.isEmpty(sdsWorkOrderInfo.getDayStr()) ? null : new Timestamp(
                    DateUtils.parse(sdsWorkOrderInfo.getDayStr(), DateUtils.DATE_FORMAT4DAY).getTime()));
            workOrder.setDueDate(StringUtils.isEmpty(sdsWorkOrderInfo.getDueDateStr()) ? null : new Timestamp(
                    DateUtils.parse(sdsWorkOrderInfo.getDueDateStr(), DateUtils.DATE_FORMAT4DAY).getTime()));
            workOrder = insertWorkOrder(workOrder);
        } else {
            String productId = workOrder.getProductId();
            if (StringUtils.isEmpty(productId)) {
                workOrder.setProductId(mesProductId);
                updateWorkOrder(workOrder);
            } else if (StringUtils.isNotEmpty(productId) && !StringUtils.equals(mesProductId, productId)) {
                throw new SystemIllegalArgumentException(Errors.create().content("Sds product miss match").build());
            }
        }

        //获取source wafer 信息
        List<SdsWorkOrderMaterialInfo> sourceWafer = workOrderDao
                .getSdsWorkOrderMaterialInfoByWorkOrderRrn(sdsWorkOrderInfo.getWorkorderRrn());
        //sds可能在设置mapping对应前传多次,需要根据wafer号去除已经有的
        List<String> workOrderImpWaferByWaferId = workOrderDao.getWorkOrderImpWaferByWaferId(
                sourceWafer.stream().map(sdsMInfo -> sdsMInfo.getSourceWaferId()).collect(Collectors.toList()));

        for (SdsWorkOrderMaterialInfo sdsWorkOrderMaterialInfo : sourceWafer) {
            if (workOrderImpWaferByWaferId.contains(sdsWorkOrderMaterialInfo.getSourceWaferId())) {
                continue;
            }
            WorkOrderImpSourceWaferDb db = new WorkOrderImpSourceWaferDb();
            BeanUtils.copyProperties(sdsWorkOrderMaterialInfo, db);
            db.setSdsProduct(sdsWorkOrderInfo.getSdsProduct());
            db.setUniqueNum(db.getSourceWaferId());
            db.setWorkorderRrn(workOrder.getWorkorderRrn());
            db.setStatus(WorkOrderImpSourceWaferDb.ACTIVE);
            dataList.add(db);
        }
    }

    private void storeMaterInfo(List<WorkOrderImpSourceWaferDb> dataList) {
        long facilityRrn = LocalContext.getFacilityRrn();
        Operation warehouse = operationManager.getOperation("WAFER_BANK", facilityRrn);
        Map<String, List<WorkOrderImpSourceWaferDb>> materMapList = dataList.stream().collect(
                Collectors.groupingBy(db -> db.getMaterialId()));

        for (Entry<String, List<WorkOrderImpSourceWaferDb>> entrySet : materMapList.entrySet()) {
            MaterialDO material = new MaterialDO(entrySet.getKey(),
                                                 namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ITEM_KEY),
                                                 ObjectList.ITEM_KEY);
            material = materialManager.getMaterial(material);
            if (material == null || material.getInstanceRrn() < 1) {
                material = new MaterialDO(entrySet.getKey(),
                                          namedObjectManager.getNamedSpace(facilityRrn, ObjectList.ITEM_KEY),
                                          ObjectList.ITEM_KEY);
                material.setExpirationLength(28);
                material.setObjectType("MATERIAL");
                material.setObjectSubtype("WAFER");
                material.setTransId("create");
                materialManager.insertMaterial(material);
                material = materialManager.getMaterial(material);
            }

            String refFileValue = referenceFileManager
                    .getRefFileValue(ReferenceDetailNames.UNIT_OF_MEASURE_FOR_BANK, material.getStoreUom(),
                                     ReferenceFileConst.DATA_1_VALUE);
            Map<String, List<WorkOrderImpSourceWaferDb>> materLotMapList = entrySet.getValue().stream().collect(
                    Collectors.groupingBy(db -> db.getMaterialLotNum()));
            List<Map<String, String>> receiptList = new ArrayList<Map<String, String>>();
            for (Entry<String, List<WorkOrderImpSourceWaferDb>> entryLot : materLotMapList.entrySet()) {
                String materLotNum = entryLot.getKey();
                Integer count = entryLot.getValue().size();

                Map<String, String> result = new HashMap<>();
                result.put(AsmConst.MATERIAL_RRN, Long.toString(material.getInstanceRrn()));
                result.put(AsmConst.MATERIAL_ID, material.getInstanceId());
                result.put(AsmConst.MATERIAL_DESC,
                           material.getInstanceDesc() == null ? "" : material.getInstanceDesc());
                result.put(AsmConst.LOT_NUMBER, materLotNum);
                result.put(AsmConst.QTY, count.toString());
                result.put(AsmConst.STORE_UOM, StringUtils.trimToEmpty(refFileValue));
				/*result.put(AsmConst.SUPPLIER_ID, theform.getSupplierId());
				result.put(AsmConst.MANUFACTURER_ID, theform.getManufacturerId());
				result.put(AsmConst.EXPIRATION_DATE, theform.getExpirationDate());
				result.put(AsmConst.PRODUCTION_DATE, theform.getProductionDate());
				result.put(AsmConst.INCOMING_DATE, theform.getIncomingDate());
				result.put(AsmConst.CHECK_DATE, theform.getCheckDate());
				result.put(AsmConst.CHECK_USER, userInfo);
				result.put(AsmConst.CHECK_RESULT, theform.getCheckResult());
				result.put(AsmConst.COMMENTS, theform.getComments());*/
                receiptList.add(result);
            }
            List<WarehouseTransBO> receiveTrans = new ArrayList<>();
            WarehouseTransBO warehouseTrans;

            for (Map<String, String> map : receiptList) {
                warehouseTrans = new WarehouseTransBO();
                buildWarehouseTrans(warehouseTrans, warehouse, material, map);

                receiveTrans.add(warehouseTrans);
            }

            warehouseManager.saveReceivedMaterialToWarehouse(facilityRrn, "ERP", receiveTrans);

        }


    }

    private void buildWarehouseTrans(WarehouseTransBO warehouseTrans, Operation warehouse, MaterialDO material,
                                     Map<String, String> map) {
        warehouseTrans.setTransQty(NumberUtils.toDouble(MapUtils.getString(map, AsmConst.QTY)));
        warehouseTrans.setTransComments(MapUtils.getString(map, AsmConst.COMMENTS));

        LotInventoryDO lotInventory = warehouseTrans.getLotInventoryDO();

        lotInventory.setLotNumber(MapUtils.getString(map, AsmConst.LOT_NUMBER));
        lotInventory.setItemRrn(material.getInstanceRrn());
        lotInventory.setWarehouseRrn(warehouse.getInstanceRrn());
        lotInventory.setWarehouseId(warehouse.getInstanceId());
        lotInventory.setMaterialType(material.getObjectSubtype());

        lotInventory.setReceiptDate(new Timestamp(System.currentTimeMillis()));
        lotInventory.setExpirationDate(DateUtils.stringToTimestamp(MapUtils.getString(map, AsmConst.EXPIRATION_DATE)));
        lotInventory.setProductionDate(DateUtils.stringToTimestamp(MapUtils.getString(map, AsmConst.PRODUCTION_DATE)));
        lotInventory.setIncomingDate(DateUtils.stringToTimestamp(MapUtils.getString(map, AsmConst.INCOMING_DATE)));
        lotInventory.setCheckDate(DateUtils.stringToTimestamp(MapUtils.getString(map, AsmConst.CHECK_DATE)));
        lotInventory.setCheckUser(MapUtils.getString(map, AsmConst.CHECK_USER));
        lotInventory.setCheckResult(MapUtils.getString(map, AsmConst.CHECK_RESULT));

        warehouseManager.setExpirationDateForReceive(material.getExpirationLength(), lotInventory);

        lotInventory.setAttributeData1(MapUtils.getString(map, AsmConst.SUPPLIER_ID));
        lotInventory.setAttributeData2(MapUtils.getString(map, AsmConst.MANUFACTURER_ID));

        lotInventory.setStatus(WarehouseNames.ACTIVE_STATUS);
    }
}