Skip to end of metadata
Go to start of metadata

Overview

The scripting required to schedule production runs based on work order information, usually necessary with an ERP interface, is shown in an example below.  This can function as a starting point for an ERP interface given a payload with dispatch information.

Applies To and Version Info

This feature applies to OEE 2.0 and is available in 2.9.1 and later.

Details

There are four script examples here, a main processing script, and three helper functions that are referenced in the main body.  The three helper functions may be utilized as common code for other aspects of an ERP interface, for example, processing Material lists, etc.

Scripting

In the following script example, the OEE 2.0 script functions for creating Material Process Segments, associating Work Orders with Schedule Objects, and setting Production Settings (such as Standard Rate for OEE Performance Factor calculation) are demonstrated.

ERP Script Example
xmlString = "Some ERP payload"
if xmlString:
	
	ds = shared.ERP.parseXML(xmlString)
	ppList = [] ##This is the list of column names in the dataset from the ERP payload.
	
	##Loop through each row in the ERP payload, which represents one production order.
	##Column names are fictitious in order to indicate the data retrieved.
	for i in range(ds.getRowCount()):

		woName = ds.getValueAt(i, 'WONUMBER')
		matName = ds.getValueAt(i, 'MATNR')
		erpLine = ds.getValueAt(i, 'WORKCENTER')		
		qty = float(ds.getValueAt(i, 'ORDERQTY'))
		schedWOUUID = 0
		matClass = ds.getValueAt(i, 'MaterialClass')
		
		##Check to ensure the material definition exists (which should have been done 
		##when the material was introduced with a new Material Master payload).
		matUUID = shared.OEE_V2.Utils.checkMaterialDef(matName, matClass)
		##mat = system.mes.loadMESObject(matUUID)
		matLink = system.mes.getMESObjectLinkByName('MaterialDef', matName)

		##Check the line as indicated in the ERP field 'WORKCENTER'
		lineUUID = shared.OEE_V2.Utils.checkLineForERP(erpLine)
		line = system.mes.loadMESObject(lineUUID)
		eqPath = line.getEquipmentPath()
		
		#get scheduled entries against the line
		begin = system.date.addDays(system.date.now(), 0)
		end = system.date.addDays(system.date.now(), 10)
		category = 'Active' ##Note, this is the default category for scheduling.
		eqSchedList = system.mes.getEquipmentScheduleEntries(eqPath, begin, end, category, False)
		woUUID = shared.OEE_V2.Utils.checkWorkOrder(woName, matName)
			
		##Given the line and material, we can ensure the OEE Run related operation is present:
		##If it is not present, we must create the changeover and production Operations.
		operList = system.mes.oee.getMaterialOperationsSegments(matLink, '*' + line.getName() + '*')
		if operList.size() < 1:
			newOpList = system.mes.oee.createMaterialProcessSegment(matLink, eqPath)
			system.mes.saveMESObjects(newOpList)
	
		##Get the operations associated with the line and material in order to update any 
		##relevant production settings based on ERP:
		operList = system.mes.getAvailableOperations(eqPath, '*' + matName + '*', True, True)

		for operLink in operList:
			operDef = operLink.getMESObject()

			##Get the Operations Segment based on the dependency of the Operation Definition:
			opSegDependency = operDef.getComplexProperty('SegmentDependency', 'Production Dependency')
			opSegUUID = opSegDependency.getSegmentRefUUID()
			opSeg = system.mes.loadMESObject(opSegUUID)
			opSegName = opSeg.getName()
			
			count = opSeg.getComplexPropertyCount('ProductionSettings')

			for complexPropNum in range(count):
				productionSettings = opSeg.getComplexProperty('ProductionSettings', complexPropNum)
				
				##Example Response Segment Production Settings Complex Property Set Functions:			
				productionSettings.setModeRefUUID(equipModeToSet.UUID)
				productionSettings.setModeRefType('EquipmentMode')
				productionSettings.setOEERate(runrate)
				productionSettings.setPackageCount(packageCount)
				opSeg.setPropertyValue('ProductionSettings', productionSettings)
			
			# Set the Material complex properties
			count = opSeg.getComplexPropertyCount('Material')
			for materialPropNum in range(count):
				materialSettings = opSeg.getComplexProperty('Material', materialPropNum)
				materialSettings.setRatePeriod('Min')
				materialSettings.setRate(efficiency * (runrate/100))
				opSeg.setPropertyValue('Material', materialSettings)


			system.mes.saveMESObject(opSeg)
			
		##The work order from the ERP Payload is checked, and if not already present, created.
		
		woObj = system.mes.loadMESObject(woUUID)
		woObj.setMaterialRef(mat)
		woObj.setWorkOrderQuantity(qty)    
		date = ds.getValueAt(i, 'DUEDATE').split('-')
		dueTime = ds.getValueAt(i, 'DUETIME').split(':')
		dueDate = system.date.getDate(int(date[0]), int(date[1])-1, int(date[2]))
		dueDate = system.date.setTime(dueDate, int(dueTime[0]), int(dueTime[1]), int(dueTime[2]))
		woObj.setDueDate(dueDate)
		system.mes.saveMESObject(woObj)
		row = [ds.getValueAt(i, k) for k in range(ds.getColumnCount())] # Load custom properties into a list per row
		##This script function is given below in a code block.
		shared.OEE_V2.Utils.updateCustomProperties(woObj.getName(), woObj.getMESObjectTypeName(), ppList, row) # Helper sets properties and saves
				
		
		schedule = system.mes.createSchedule(operDef) 
 
		for ndx in range(schedule.size()): 
			scheduleOperations = schedule.get(ndx)
			print scheduleOperations
			objTypeName = scheduleOperations.getMESObjectType().getName()
			
			##Sort the schedule items in the list by their object type.
			##Set the schedule production count on the Operations Schedule object (top level)
			if objTypeName == 'OperationsSchedule':
				scheduleOperations.setScheduleProductionCount(qty)
		   	
			##Set the reference to the Work Order on the Operations Request
			elif objTypeName == 'OperationsRequest':
				scheduleOperations.setPropertyValue('WorkOrderRefUUID', woObj.getUUID())
		   		
			##Set the Material Qty on the Production Request Segment
			elif objTypeName == 'RequestSegment' and (scheduleOperations.getComplexPropertyCount('ResponseMaterial') > 0):
				if scheduleOperations.getAvailableMaterialOptions('Material Out').size() > 0:
					scheduleOperations.setMaterial('Material Out', matName, eqPath, qty) 
					print 'set work order scheduled qty', scheduleOperations
 
		startDateList = ds.getValueAt(i, 'STARTDATE').split('-')
		startTime = ds.getValueAt(i, 'STARTTIME').split(':')
		startDate = system.date.getDate(int(startDateList[0]), int(startDateList[1])-1, int(startDateList[2]))		  
		startDate = system.date.setTime(startDate, int(startTime[0]), int(startTime[1]), int(startTime[2])) 			
		scheduleList = system.mes.scheduleOperations(schedule, startDate, dueDate, True, 'Active')
			
		system.mes.saveSchedule(scheduleList)
Update Custom Properties Function
def updateCustomProperties(name, objType, fieldList, row):
	obj = system.mes.loadMESObject(name, objType)
	newDict = {}
	for i in range(len(fieldList)):
		newDict.update({fieldList[i]:row[i]})
	
	cp = obj.getCustomPropertiesFull()	
	for key in newDict.keys():
		if cp.has_key(key):
			obj.setPropertyValue(key, newDict[key])
		else:
			obj.addCustomProperty(key, 'String', newDict[key], 'text', True, False)
			obj.setPropertyValue(key, newDict[key])
			  
	system.mes.saveMESObject(obj)
Check Material Definitions Function
def checkMaterialDef(matName, className):      
    def checkMaterialClass(name):
        filter = system.mes.object.filter.createFilter()
        filter.setMESObjectTypeName('MaterialClass')
        filter.setMESObjectNamePattern(name)
        list = system.mes.searchMESObjects(filter)
         
        if list.size() == 0:
            obj = system.mes.createMESObject('MaterialClass')
            obj.setPropertyValue('Name', name)
            obj.addParent(system.mes.getMESObjectLinkByName('MaterialRoot', 'Material Root'))
            system.mes.saveMESObject(obj)
            link = system.mes.object.link.create(obj)
        else:
            link = list.get(0)
             
        return link
     
    classLink = checkMaterialClass(className)
    matList = system.mes.oee.getMaterialItems(classLink, matName)
         
    if matList.size() == 0:
        print 'create new mat def'
        matClassObj = system.mes.loadMESObject(className, 'MaterialClass')
        obj = system.mes.createMESObject('MaterialDef')
        obj.setPropertyValue('Name', matName)
        obj.addParent(matClassObj)
        system.mes.saveMESObject(obj)
        matUUID = obj.getUUID()
     
    elif matList.size() > 0:
        matUUID = matList.get(0).getMESObject().getUUID()
     
    return matUUID
Check Work Order Function
def checkWorkOrder(woName, matName):
	filter = system.mes.object.filter.createFilter()
	filter.setMESObjectTypeName('WorkOrder')
	filter.setMESObjectNamePattern(woName)
	list = system.mes.searchMESObjects(filter)
		
	if list.size() == 0:
		matLink = system.mes.getMESObjectLinkByName('MaterialDef', matName)
		obj = system.mes.workorder.createMESWorkOrder(woName, matLink)
		system.mes.saveMESObject(obj)
	else:
		woObj = list.get(0).getMESObject()
		matObj = system.mes.loadMESObject(matName, 'MaterialDef')
		if woObj.getMaterialRef().getMESObject() != matObj:
			woObj.setMaterialRef(matObj)	
			system.mes.saveMESObject(woObj)
		
	return system.mes.workorder.getMESWorkOrder(woName)



Keywords

OEE, ERP, Scheduling, ERP Interface, Production Settings, Work Order

    Created By   Mark French Created Date  May 13, 2017 00:35 Last Modified By   Mark French Last Modifed Date   Jan 24, 2019 00:16


  • No labels