Work Orders | Editing Work Order Counts

Edit Work Order Counts

Editing work order counts involves editing raw counts, updating an operation associated with those counts, and refreshing the work order object.

The OEE Module will constantly collect and increment counts in the database ensuring data is not missed during production periods. 

You can find more information about how counters work on the Production Counters documentation page.

Attached to this KB is an example screen with count adjustments where all counters exist on a line.  Pay careful attention to your configuration as you will want to adjust Infeed/Outfeed counters as defined by the Material Production settings for the operation linked to the work order.

See Below:


Functions touched in the example screen:

ObjectDescription
Analysis ScriptRetrieving all work orders executed over a period of time for a given Line.
Work Order ObjectsThe actual quantity produced against a work order and remaining quantity is calculated based on the sum of quantities from operations associated with the work order ref UUID.
Operations ResponseHolds basic information about an executed operation, including a link to a work order.
Response SegmentHolds actual production information such as quantity.
Tag Collector TypesProduction values such as equipment modes, states, and counts.  
Equipment ObjectsUsed to retrieve counter definitions via complex property objects.

Modifying counts involves understanding what operations were executed for a given work order.  There can be more than one operation executed for a work order.  A work order links to all operations executed.  Each operation holds count information.  

By finding the operation begin and end times, we can determine which timestamped tag collector values we should modify.

Find more information about modifying raw count information here: Adjusting Production Run Data

Operation count information may be calculated based on your counter configuration.  For example, you have an Infeed and Reject counter; Outfeed is calculated.  Decreasing the calculated Outfeed in this scenario can be achieved by either decreasing Infeed or increasing Rejects.

Scripts from the provided screen:

Refresh Button

Python
def runAction(self, event):

def executeWOSummaryAnalysis(eqPath, startDate, endDate):

analysisSetting = system.mes.analysis.createMESAnalysisSettings('workorders')
datapoints = [
"Work Order"
]
analysisSetting.setDataPoints(datapoints)
analysisSetting.addParameter('Path')
analysisSetting.setFilterExpression("Equipment Path = @Path AND Work Order != ''")
analysisSetting.setGroupBy("Work Order")
params = {'Path':eqPath}
results = system.mes.analysis.executeAnalysis(startDate, endDate, analysisSetting, params)
return results.getDataset()

endDate = self.parent.custom.endDate
startDate = self.parent.custom.startDate

eqPath = self.getSibling("mesObjectSelector").props.selectedMESObject.equipmentPath
ds = executeWOSummaryAnalysis(eqPath, startDate, endDate)

data = []

for row in range(ds.getRowCount()):
woName = ds.getValueAt(row,'Work Order')
try:
woObj = system.mes.workorder.getMESWorkOrder(woName)
quantity = woObj.getActualQuantity()
if not woObj.isClosed():
data.append({'work order':woName,'quantity':quantity})
except:
continue

self.getSibling("workOrders").props.data = data
self.getSibling("segments").props.data = []
self.getSibling("counters").props.data = []

Work Order - onRowClick

Python
def runAction(self, event):

woName = event.value['work order']
woObj = system.mes.workorder.getMESWorkOrder(woName)
opResponses = woObj.getOperationsResponses()

data = []
for opResp in opResponses:
for resSeg in opResp.getMESObject().getResponseSegments():
resObj = resSeg.getMESObject()
if '_CO' not in resObj.getName():
segBeg = resObj.getPropertyValue('BeginDateTime')
segEnd = resObj.getPropertyValue('EndDateTime')
data.append({'Begin Operation':segBeg, 'End Operation':segEnd, 'UUID':resObj.getUUID()})
self.getSibling("segments").props.data = data
self.getSibling("segments").custom.workOrder = woName

Segments - onRowClick

Python
def runAction(self, event):
startDate = system.date.parse(event.value['Begin Operation'], 'E MMM d yyyy HH:mm:ss')
if not event.value['End Operation']:
#do not edit current running work orders
return
endDate = system.date.parse(event.value['End Operation'], 'E MMM d yyyy HH:mm:ss')

self.getSibling("counters").custom.startDate = startDate
self.getSibling("counters").custom.endDate = endDate
self.getSibling("counters").custom.respSegUUID = event.value['UUID']

eqPath = self.getSibling("mesObjectSelector").props.selectedMESObject.equipmentPath

eqObj = system.mes.loadMESObjectByEquipmentPath(eqPath)
complexPropCount = eqObj.getComplexPropertyCount('Counter')
data = []
for i in range(complexPropCount):
counterProp = eqObj.getComplexProperty('Counter',i)
counterName = counterProp.getName()
counterKind = counterProp.getCountKind().getName()
counterMode = counterProp.getCountMode()
counterValue = system.mes.getTagCollectorDeltaValue(eqPath, 'Equipment Count', counterName, startDate, endDate)
data.append({
'counterName':counterName,
'counterKind':counterKind,
'counterValue':counterValue,
'counterMode':counterMode
})

self.getSibling("counters").props.data = data

Counters - onRowClick

Python
def runAction(self, event):
self.custom.oldValue = event.value['counterValue']

Counters - onEditCellCommit

Python

def executeWOSummaryAnalysis(eqPath, startDate, endDate):
analysisSetting = system.mes.analysis.createMESAnalysisSettings('workorders')
datapoints = [
"Work Order"
]
analysisSetting.setDataPoints(datapoints)
analysisSetting.addParameter('Path')
analysisSetting.setFilterExpression("Equipment Path = @Path AND Work Order != ''")
analysisSetting.setGroupBy("Work Order")
params = {'Path':eqPath}
results = system.mes.analysis.executeAnalysis(startDate, endDate, analysisSetting, params)
return results.getDataset()
####END executeWOSummaryAnalysis####

def updateWorkOrder(respSegUUID, workOrderName, counterKind, oldVal, newVal):
seg = system.mes.loadMESObject(self.custom.respSegUUID)
lotProp = seg.getLot('Material Out')

#Get previous work order quantity value
oldlotPropVal = seg.getMaterialActualQuantity('Material Out')
newQuantity = 0
infeedOutfeed = ['Infeed','Outfeed']
changed = False

#Decrease reject OR Increase Infeed OR Increase Outfeed
if (counterKind == 'Reject' and oldVal > newVal) or (counterKind in infeedOutfeed and oldVal < newVal):
newQuantity = oldlotPropVal + abs(newVal-oldVal)
changed = True
#Increase Reject OR Decrease Infeed OR Decrease Outfeed
elif (counterKind == 'Reject' and oldVal < newVal) or (counterKind in infeedOutfeed and oldVal > newVal):
newQuantity = oldlotPropVal - abs(newVal-oldVal)
if newQuantity < 0:
newQuantity = 0
changed = True

if changed:
lotProp.setQuantity(newQuantity)
system.mes.saveMESObject(seg)
woObj = system.mes.workorder.getMESWorkOrder(self.custom.workOrderName)
woObj.updateQuantities()
####END updateWorkOrder####

equipmentPath = self.getSibling("mesObjectSelector").props.selectedMESObject.equipmentPath
respSegUUID = self.custom.respSegUUID
workOrderName = self.custom.workOrderName
counter = self.props.data[event.rowIndex]['counterName']
endDate = self.custom.endDate
startDate = self.custom.startDate
newVal = int(event.value)
oldVal = int(self.custom.oldValue)
counterKind = self.props.data[event.rowIndex]['counterKind']
counterMode = self.props.data[event.rowIndex]['counterMode']
val = system.mes.getTagCollectorPreviousValue(equipmentPath, 'Equipment Count', counter, endDate)
origTS = system.mes.getTagCollectorPreviousTimeStamp(equipmentPath, 'Equipment Count', counter, endDate)

if origTS:
if system.date.isBetween(origTS, startDate, endDate):
newTagCollectorValue = val + (newVal - oldVal)
system.mes.updateTagCollectorValue(equipmentPath, 'Equipment Count', counter, origTS, newTagCollectorValue)
updateWorkOrder(respSegUUID, workOrderName, counterKind, oldVal, newVal)

else:
#last entry not within date range, need to account for it
newTagCollectorValue = val + (newVal - val)
updateWorkOrder(respSegUUID, workOrderName, counterKind, oldVal, newVal)

else:
#no previous entry exists
if counterMode == 'POSITIVE_CHANGE':
system.mes.addTagCollectorValue(equipmentPath, 'Equipment Count', counter, startDate, 1)
newVal = newVal + 1
system.mes.addTagCollectorValue(equipmentPath, 'Equipment Count', counter, system.date.addSeconds(startDate,+1), newVal)
updateWorkOrder(respSegUUID, workOrderName, counterKind, oldVal, newVal)

#Update work order display
ds = executeWOSummaryAnalysis(equipmentPath, startDate, endDate)
data = []
for row in range(ds.getRowCount()):
woName = ds.getValueAt(row,'Work Order')
try:
woObj = system.mes.workorder.getMESWorkOrder(woName)
quantity = woObj.getActualQuantity()
if not woObj.isClosed():
data.append({'work order':woName,'quantity':quantity})
except:
continue

self.getSibling("workOrders").props.data = data
self.props.data[event.rowIndex]['counterValue'] = event.value


WorkOrder Adjustment Screen

WorkOrderAdjustment.zip

Preview: