Compile function NCR_Services(@Service, @Params) #pragma precomp SRP_PreCompiler /*********************************************************************************************************************** Name : NCR_Services Description : Handler program for all NCR services. Notes : Application errors should be logged using the Error Services module. There are a few methodological assumptions built into way errors are managed which are important to understand in order to properly work with Error Services: - The term 'top' refers to the originating procedure of a call stack and the term 'bottom' refers to the last routine (or the current routine) within a call stack. Within the OpenInsight Debugger this will appear backwards since the originating procedure always appears at the bottom of the list and the current routine appears at the top of the list. We are using this orientation because it is common to refer to the process of calling other procedures as 'drilling down'. - The reason for defining the orientation of the call stack is because Error_Services allows for multiple error conditions to be appended to an original error. In most cases this will happen when a procedure at the bottom of the stack generates an error condition and then returns to its calling procedure. This higher level procedure can optionally add more information relevant to itself. This continues as the call stack 'bubbles' its way back to the top to where the originating procedure is waiting. - Native OpenInsight commands that handle errors (e.g., Set_Status, Set_FSError, Set_EventStatus) preserve their error state until explicitly cleared. This can hinder the normal execution of code since subsequent procedures (usually SSPs) will fail if a pre-existing error condition exists. Our philosophy is that error conditions should automatically be cleared before a new procedure is executed to avoid this problem. However, the nature of Basic+ does not make this easy to automate for any given stored procedure. Therefore, if a stored procedure wants to conform to our philosophy then it should include a call into the 'Clear' service request at the top of the program. Alternatively this can be done through a common insert (see SERVICE_SETUP for example.) - Service modules will use the SERVICE_SETUP insert and therefore automatically clear out any error conditions that were set before. Parameters : Service [in] -- Name of the service being requested Param1-10 [in/out] -- Additional request parameter holders Response [out] -- Response to be sent back to the Controller (MCP) or requesting procedure Metadata : History : (Date, Initials, Notes) 08/29/24 djm Add ProcessScanData service and Service header. ***********************************************************************************************************************/ $insert APP_INSERTS $Insert SERVICE_SETUP $Insert NCR_EQUATES $Insert REACTOR_EQUATES Declare subroutine Set_Status, Logging_Services, Error_Services, Obj_Notes, Set_Property, Obj_Wo_Mat, Hold_Services Declare subroutine Btree.Extract, SRP_JSon Declare function Environment_Services, Logging_Services, SRP_Datetime, Utility, Scan_Services, Error_Services Declare function Database_Services, Signature_Services, Epipro_Services, Rds_Services, Memberof, Datetime Declare function Get_Property, SRP_Json, obj_ncr EQU COL$RDS_NO TO 1 EQU COL$REACTOR TO 2 EQU COL$REJ_CNT TO 3 GoToService Return Response or "" //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Service Parameter Options //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Options SCAN_TYPES = 'CASSETTE_1', 'CASSETTE_2', 'WM_IN_1', 'WM_IN_2' //---------------------------------------------------------------------------------------------------------------------- // SERVICES //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // ProcessScanData // // ScanData - [Required] // ScanType - [Required] // FirstCassID - [Required] // OperatorID - [Required] // // Returns the current stage of a lot. Replaces CURR_STAGE calculated column. //---------------------------------------------------------------------------------------------------------------------- Service ProcessScanData(ScanData, ScanType = SCAN_TYPES, FirstCassID, OperatorID) If (ScanData NE '') then Convert @Lower.Case to @Upper.Case in ScanData // Code 3of9 encodes the asterisk and underscore characters. These need to be decoded. ScanData = Scan_Services('DecodeScanData', ScanData) If Error_Services('NoError') then ColumnIndex = '' ColumnValue = '' // Identify the scan data based on the data identifier prefix (if any). Otherwise, assume this is a // type of cassette ID (i.e., RDS or WMO). Begin Case Case ScanType EQ 'WM_IN_1' ValidCassID = False$ cnt = Count(ScanData, '|') if cnt NE 0 then Error_Services('Add', 'Wrong label - Scan 2D Top Label') return end else CassetteID = ScanData Swap 'FDI' with '' in CassetteID Swap '^FS' with '' in CassetteID Swap 'I' with '' in CassetteID Convert '.' to '*' in CassetteID WMIRow = Database_Services('ReadDataRow', 'WM_IN', CassetteID) If Error_Services('NoError') then ValidCassID = True$ end ScanData = CassetteID If ScanData NE FirstCassID then Error_Services('Add', 'Lot Label does not match the expected lot in OI. | Please correct this issue and then retry.') end end If ValidCassID EQ False$ then Error_Services('Add', 'Unrecognized scan data: ':ScanData) end Response = ScanData Case ScanType EQ 'WM_IN_2' ValidCassID = False$ ScanMismatch = False$ cnt = Count(ScanData, '|') if cnt NE 0 then Error_Services('Add', 'Wrong label - Scan 2D Bottom Label') return end else CassetteID = ScanData Swap 'FDI' with '' in CassetteID Swap '^FS' with '' in CassetteID Swap 'I' with '' in CassetteID Convert '.' to '*' in CassetteID WMIRow = Database_Services('ReadDataRow', 'WM_IN', CassetteID) If Error_Services('NoError') then ValidCassID = True$ end ScanData = CassetteID If ScanData NE FirstCassID then ScanMismatch = True$ end end If ScanMismatch EQ True$ then ValidCassID = False$ If (RowExists('WM_IN', FirstCassID) EQ True$) And (RowExists('WM_IN', CassetteID) EQ True$) then // Place first cassette on hold WONo = Field(FirstCassID, '*', 1, 1) CassNo = Field(FirstCassID, '*', 3, 1) HoldEntity = 'WM_IN' HoldEntityID = FirstCassID WOMatKey = WONo:'*':CassNo CtrlEntID = 'NCR_SERVICES' ;* Control checked/unchecked OriginFlag = '' ;* Flag to indicate a hold initiated from the packagaing form HoldData = '' HoldData<1> = OperatorID HoldData<2> = 'Lot placed on hold due to NCR Barcode verification mismatch.' HoldData<3> = False$ Hold_Services('OnHold', WOMatKey, HoldEntity, HoldEntityID, 'HOLD', HoldData, OperatorID) // Place Second cassette on hold WONo = Field(CassetteID, '*', 1, 1) CassNo = Field(CassetteID, '*', 3, 1) HoldEntity = 'WM_IN' HoldEntityID = CassetteID WOMatKey = WONo:'*':CassNo CtrlEntID = 'NCR_SERVICES' ;* Control checked/unchecked OriginFlag = '' ;* Flag to indicate a hold initiated from the packagaing form HoldData = '' HoldData<1> = OperatorID HoldData<2> = 'Lot placed on hold due to NCR Barcode verification mismatch.' HoldData<3> = False$ Hold_Services('OnHold', WOMatKey, HoldEntity, HoldEntityID, 'HOLD', HoldData, OperatorID) Message = 'NCR Label verification failed due to mismatched barcodes. Both cassettes placed on hold - Supervisor, Lead, or Engineering disposition required.':CRLF$ | : 'WM_IN Label #1: ':FirstCassID:CRLF$ | : 'WM_IN Label #2: ':CassetteID:CRLF$ | : 'Operator: ':OperatorID Error_Services('Add', Message) end else Error_Services('Add', 'Unrecognized scan data: ':ScanData) end end If ValidCassID EQ False$ then Error_Services('Add', 'Unrecognized scan data: ':ScanData) end Response = ScanData Case ScanType EQ 'CASSETTE_1' // Assume this is intended to be a Cassette ID scan (either WMO or RDS). Only if this is a // non-existent carrier will the scan data be considered invalid. cnt = DCount(ScanData, '|') if cnt NE 8 then CassetteID = 0 Error_Services('Add', 'Wrong label - Scan 2D Top Label') return end else // RDS should be 3rd position CassetteID = Field(ScanData, '|', 3) Seq1 = Field(ScanData, '|', 8) end // Strip '1T', 'I', and 'O' prefixes. If CassetteID[1, 2] EQ '1T' then CassetteID[1, 2] = '' If ((CassetteID[1, 1] EQ 'O') or (CassetteID[1, 1] EQ 'I')) then CassetteID[1, 1] = '' end If ( (CassetteID[1, 1] EQ 'O') or (CassetteID[1, 1] EQ 'I') ) then CassetteID[1, 1] = '' ValidCassID = False$ ; // Assume Cassette ID is not valid for now. RDSCass = Count(CassetteID, '.') EQ 0 AND Num(CassetteID) GaNCass = Count(CassetteID, '.') EQ 1 AND not(RDSCass) EPPCass = Count(CassetteID, '.') EQ 2 AND not(RDSCass) AND not(GaNCass) Begin Case Case GaNCass Convert '.' to '*' in CassetteID WOMatRow = Database_Services('ReadDataRow', 'WO_MAT', CassetteID) If Error_Services('NoError') then ValidCassID = True$ end Case EPPCass Convert '.' to '*' in CassetteID WMOutRow = Database_Services('ReadDataRow', 'WM_OUT', CassetteID) If Error_Services('NoError') then ValidCassID = True$ end Case RDSCass RDSRow = Database_Services('ReadDataRow', 'RDS', CassetteID) If Error_Services('NoError') then ValidCassID = True$ end End Case If ( (Seq1 EQ 'SEQ1') or (Seq1 EQ 'SEQ2') ) then Set_Property(@Window, '@SEQ1', Seq1) end else Error_Services('Add', 'Error reading sequence information') end If ValidCassID EQ False$ then Error_Services('Add', 'Unrecognized scan data: ':ScanData) end ScanData = CassetteID If ScanData NE FirstCassID then Error_Services('Add', 'Lot Label does not match the expected lot in OI. | Please correct this issue and then retry.') end Response = ScanData Case ScanType EQ 'CASSETTE_2' // Assume this is intended to be a Cassette ID scan (either WMO or RDS). Only if this is a // non-existent carrier will the scan data be considered invalid. cnt = DCount(ScanData, '|') if cnt NE 8 then CassetteID = 0 Error_Services('Add', 'Wrong label - Scan 2D Bottom Label') return end else // RDS should be 3rd position SecondCassID = Field(ScanData, '|', 3) Seq2 = Field(ScanData, '|', 8) end // Strip '1T', 'I', and 'O' prefixes. If SecondCassID[1, 2] EQ '1T' then SecondCassID[1, 2] = '' If ( (SecondCassID[1, 1] EQ 'O') or (SecondCassID[1, 1] EQ 'I') ) then SecondCassID[1, 1] = '' end If ( (SecondCassID[1, 1] EQ 'O') or (SecondCassID[1, 1] EQ 'I') ) then SecondCassID[1, 1] = '' ValidCassID = False$ ; // Assume Cassette ID is not valid for now. ScanMismatch = False$ SeqMismatch = False$ SeqError = False$ Convert '*' to '.' in FirstCassID If Error_Services('NoError') then ValidCassID = True$ If (SecondCassID NE FirstCassID) then ScanMismatch = True$ end else Seq1 = Get_Property(@Window, '@SEQ1') Begin Case Case ( (Seq2 NE 'SEQ1') and (Seq2 NE 'SEQ2') ) SeqError = True$ Case (Seq2 EQ Seq1) SeqMismatch = True$ End Case end end If ValidCassID EQ False$ then Error_Services('Add', 'Unrecognized scan data: ':ScanData) If (ScanMismatch EQ True$) AND (ValidCassID EQ True$) then // Check if first cassette ID is a valid RDS or WM_OUT key Convert '.' to '*' in FirstCassID ValidCassID = False$ Begin Case Case ( RowExists('RDS', FirstCassID) EQ True$ ) ValidCassID = True$ WONo = Xlate('RDS', FirstCassID, 'WO', 'X') CassNo = Xlate('RDS', FirstCassID, 'CASS_NO', 'X') HoldEntity = 'RDS' Case ( RowExists('WM_OUT', FirstCassID) EQ True$ ) ValidCassID = True$ WONo = Field(FirstCassID, '*', 1, 1) CassNo = Field(FirstCassID, '*', 3, 1) HoldEntity = 'WM_OUT' Case ( RowExists('WM_IN', FirstCassID) EQ True$ ) ValidCassID = True$ WONo = Field(FirstCassID, '*', 1, 1) CassNo = Field(FirstCassID, '*', 3, 1) HoldEntity = 'WM_IN' Case ( RowExists('WO_MAT', FirstCassID) EQ True$ ) ValidCassID = True$ WONo = Field(FirstCassID, '*', 1, 1) CassNo = Field(FirstCassID, '*', 2, 1) HoldEntity = 'WO_MAT' Case Otherwise$ Null End Case HoldEntityID = FirstCassID // Place first cassette on hold WOMatKey = WONo:'*':CassNo CtrlEntID = 'NCR_SERVICES' ;* Control checked/unchecked OriginFlag = '' ;* Flag to indicate a hold initiated from the packagaing form HoldData = '' HoldData<1> = OperatorID HoldData<2> = 'Lot placed on hold due to NCR Barcode verification mismatch.' HoldData<3> = False$ Hold_Services('OnHold', WOMatKey, HoldEntity, HoldEntityID, 'HOLD', HoldData, OperatorID) // Check if second cassette ID is a valid RDS or WM_OUT key Convert '.' to '*' in SecondCassID ValidCassID = False$ Begin Case Case ( RowExists('RDS', SecondCassID) EQ True$ ) ValidCassID = True$ WONo = Xlate('RDS', SecondCassID, 'WO', 'X') CassNo = Xlate('RDS', SecondCassID, 'CASS_NO', 'X') HoldEntity = 'RDS' ValidCassID = True$ Case ( RowExists('WM_OUT', SecondCassID) EQ True$ ) ValidCassID = True$ WONo = Field(SecondCassID, '*', 1, 1) CassNo = Field(SecondCassID, '*', 3, 1) HoldEntity = 'WM_OUT' Case ( RowExists('WM_IN', SecondCassID) EQ True$ ) WONo = Field(SecondCassID, '*', 1, 1) CassNo = Field(SecondCassID, '*', 3, 1) HoldEntity = 'WM_IN' ValidCassID = True$ Case ( RowExists('WO_MAT', SecondCassID) EQ True$ ) WONo = Field(SecondCassID, '*', 1, 1) CassNo = Field(SecondCassID, '*', 2, 1) HoldEntity = 'WO_MAT' ValidCassID = True$ Case Otherwise$ Null End Case If ValidCassID EQ True$ then HoldEntityID = SecondCassID WOMatKey = WONo:'*':CassNo // Place second cassette on hold CtrlEntID = 'NCR_SERVICES' ;* Control checked/unchecked OriginFlag = '' ;* Flag to indicate a hold initiated from the packagaing form HoldData = '' HoldData<1> = OperatorID HoldData<2> = 'Lot placed on hold due to NCR Barcode verification mismatch.' HoldData<3> = False$ Hold_Services('OnHold', WOMatKey, HoldEntity, HoldEntityID, 'HOLD', HoldData, OperatorID) end Message = 'NCR Label verification failed due to mismatched barcodes. Both cassettes placed on hold - Supervisor, Lead, or Engineering disposition required.':CRLF$ | : 'Cassette Label #1: ':FirstCassID:CRLF$ | : 'Cassette Label #2: ':SecondCassID:CRLF$ | : 'Operator: ':OperatorID Error_Services('Add', Message) end else if (SeqMismatch EQ True$) then //do sequence mismatch stuff here Message = 'NCR Label verification failed due to operator double-scanning barcode.':CRLF$ | : 'Cassette: ':FirstCassID:CRLF$ | : 'Operator: ':OperatorID Error_Services('Add', Message) end else if (SeqError EQ True$) then Error_Services('Add', 'Error reading sequence information') end ScanData = '' ScanData = SecondCassID Response = ScanData End Case end end else Error_Services('Add', 'ScanData argument was missing in the ' : Service : ' service.') end end service Service SendToSPC(NCRNo, RDSList, ReactorType, PSNo, DeptResp, LossCode, LossDesc, LossStage, LossBy, ACCode, ACDesc) Headers = 'Logging DTM' : @FM : 'Machine' : @FM : 'Level' : @FM : 'Log' ColumnWidths = 20 : @FM : 12 : @FM : 7 : @FM : 500 Machine = Environment_Services('GetServer') LogPath = Environment_Services('GetApplicationRootPath') : '\LogFiles\NCR' makeDirSuccess = Utility("MAKEDIR", LogPath) LogDate = Oconv(Date(), 'D4/') LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : '_NcrSendToSpc.csv' objLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ' ', Headers, ColumnWidths, False$, False$) RdsNos = '' RdsCount = 0 ReactorList = '' ReactorCount = 0 RejCntList = '' RejCntCount = 0 RDSCnt = DCOUNT(RDSList<1>,@VM) If RDSCnt GT 0 then FOR I = 1 TO RDSCnt If RdsNos NE '' then RdsNos := ', ' end RdsNos := RDSList RdsCount += Num(RDSList) If ReactorList NE '' then ReactorList := ', ' end ReactorList := RDSList ReactorCount += Num(RDSList) If RejCntList NE '' then RejCntList := ', ' end RejCntList := RDSList RejCntCount += Num(RDSList) Next I end LogMessage = 'Attempting to send NCR data to SPC. Data: {' LogMessage := 'NCR No: ' : NCRNo LogMessage := ', RDS Nos: ' : RdsNos LogMessage := ', Reactors: ' : ReactorList LogMessage := ', Reject Counts: ' : RejCntList LogMessage := ', Reactor Type: ' : ReactorType LogMessage := ', PSN: ' : PSNo LogMessage := ', Responsible Dept: ' : DeptResp LogMessage := ', Loss Code: ' : LossCode LogMessage := ', Loss Desc: ' : LossDesc LogMessage := ', Loss Stage: ' : LossStage LogMessage := ', Loss By: ' : LossBy LogMessage := ', AC Code: ' : ACCode LogMessage := ', AC Desc: ' : ACDesc LogMessage := '}' LogDate = Oconv(Date(), 'D4/') LogData = '' LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM LogData<2> = Machine LogData<3> = 'INFO' LogData<4> = LogMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) ArgsNotNull = NCRNo NE '' and RDSList NE '' and ReactorType NE '' and PSNo NE '' ArgsNotNull = ArgsNotNull EQ True$ and DeptResp NE '' and LossCode NE '' ArgsNotNull = ArgsNotNull EQ True$ and LossDesc NE '' and LossStage NE '' ArgsNotNull = ArgsNotNull EQ True$ and LossBy NE '' and ACCode NE '' and ACDesc NE '' RdsListCountsAtLeastOne = RdsCount GE 1 and ReactorCount GE 1 and RejCntCount GE 1 RdsListCountsEqual = RdsCount EQ ReactorCount and ReactorCount EQ RejCntCount If ArgsNotNull EQ True$ and RdsListCountsAtLeastOne NE False$ and RdsListCountsEqual NE False$ then DataLines = '' FOR I = 1 TO RDSCnt DataLine = QUOTE(NCRNo):TAB$ DataLine := QUOTE(RDSList):TAB$ IF ReactorType = 'P' OR ReactorType = 'EPP' THEN DataLine := QUOTE('EP':RDSList):TAB$ ;* EpiPRO reactors in SPC have "EP" on the front. END ELSE DataLine := QUOTE(RDSList):TAB$ END DataLine := QUOTE(RDSList):TAB$ DataLine := QUOTE(PSNo):TAB$ DataLine := QUOTE(DeptResp):TAB$ DataLine := QUOTE(LossCode):TAB$ DataLine := QUOTE(LossDesc):TAB$ DataLine := QUOTE(LossStage):TAB$ DataLine := QUOTE(LossBy):TAB$ DataLine := QUOTE(ACCode):TAB$ DataLine := QUOTE(ACDesc):TAB$ DataLines := DataLine:CRLF$ NEXT I DateTime = SRP_Datetime("Now") Year = SRP_Datetime("Year", DateTime) Month = SRP_Datetime("Month", DateTime) Day = SRP_Datetime("Day", DateTime) FileName = NCRNo : '_NCR_Data_' : Year : Month : Day : '.txt' Path = Environment_Services('GetSPCDataPath') DOSFile = Path : '\' : FileName Set_Status(0) OSRead DOSRecord FROM DOSFile ELSE ErrCode = Status() IF ErrCode = 4 THEN DOSRecord = '' ;* File doesn't exist END ELSE * ErrMsg('Unable to read DOS file "SPC_Data.TXT" for update. ':ErrCode:' Please try again.') ;* Remarked out per Chad Becker request - dkk 12/9/14 RETURN END END DOSRecord := DataLines OSWrite DOSRecord ON DOSFile ErrCode = Status() ErrorMessage = '' Begin Case Case ErrCode EQ 1 ErrorMessage = 'Bad filename.' Case ErrCode EQ 2 ErrorMessage = 'Cannot write to file. Access denied.' Case ErrCode EQ 3 ErrorMessage = 'Disk or directory full.' Case ErrCode EQ 4 ErrorMessage = 'File does not exist.' Case ErrCode EQ 5 ErrorMessage = 'Unknown error.' Case ErrCode EQ 6 ErrorMessage = 'Attempt to write to a read-only file.' End Case LogDate = Oconv(Date(), 'D4/') LogData = '' LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM LogData<2> = Machine If ErrorMessage NE '' then ErrorMessage = 'Error in ' : Service : '. When attempting to write the NCR data to a file the following error occurred. ' : ErrorMessage LogData<3> = 'ERROR' LogData<4> = ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end else LogData<3> = 'INFO' LogData<4> = 'Sucessfully sent NCR ' : NCRNo : ' data to SPC in file ' : DOSFile : '.' Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) end end else ErrorMessage = 'Error in ' : Service : '. One or more arguments were null or malformed.' LogDate = Oconv(Date(), 'D4/') LogData = '' LogData<1> = Oconv(Date(), 'D4/') : ' ' : Oconv(Time(), 'MTS') ; // Logging DTM LogData<2> = Machine LogData<3> = 'ERROR' LogData<4> = ErrorMessage Logging_Services('AppendLog', objLog, LogData, @RM, @FM, False$) Error_Services('Add', ErrorMessage) end end service Service GetOpenNCRKeys() table = "NCR" ErrorMessage = '' RDSRecords = '' Open "DICT ":table To @DICT Else ErrorMessage = 'Error opening NCR dictionary' End If ErrorMessage EQ '' then srch_strng = "STATUS":@VM:'O':@FM option = "" flag = "" Btree.Extract(srch_strng, table, @DICT, RDSRecords, option, flag) If Flag NE 0 then ErrorMessage = 'Error performing BTree Extract on NCR table.' end end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end Response = RDSRecords end service Service ConvertRecordToJson(NCRId) NCRJson = '' ErrorMessage = '' If RowExists('NCR', NCRId) then NCRRecord = Database_Services('ReadDataRow', 'NCR', NCRId, True$, 0, False$) If Error_Services('NoError') then objNCR = '' If SRP_JSON(objNCR, 'New', 'Object') then SRP_JSON(objNCR, 'SetValue', 'NCRId', NCRId) ThisNCREntryDate = NCRRecord ThisNCREntryTime = NCRRecord If ThisNCREntryTime EQ '' then ThisNCREntryTime = 0 ThisNCREntryDateTime = OConv(SRP_DateTime('Combine', ThisNCREntryDate, ThisNCREntryTime), 'DT') SRP_JSON(objNCR, 'SetValue', 'EntryDateTime', ThisNCREntryDateTime, 'String') SRP_JSON(objNCR, 'SetValue', 'Shift', NCRRecord) ThisNCRReactorNo = NCRRecord SRP_JSON(objNCR, 'SetValueArray', 'Reactor', ThisNCRReactorNo, @VM);//This needs to be a list to support EpiPro ThisNCRCassId = '' ThisNCRReactorType = Xlate('REACTOR', ThisNCRReactorNo, REACTOR_REACT_TYPE$, 'X') If ThisNCRReactorType NE 'EPP' then ThisNCRCassId = NCRRecord end else ThisNCRWONo = NCRRecord ThisNCRStepNo = NCRRecord ThisNCRCassNo = NCRRecord ThisNCRCassId = ThisNCRWONo : '-' : ThisNCRStepNo : '-' : ThisNCRCassNo end SRP_JSON(objNCR, 'SetValueArray', 'CassetteId', ThisNCRCassId, @VM) SRP_JSON(objNCR, 'SetValue', 'LossStage', NCRRecord) ThisNCRRejectCount = 0 ThisNCRRejectCount = Obj_Ncr('RejQty', NCRId:@RM:NCRRecord) SRP_JSON(objNCR, 'SetValueArray', 'TotalRejected', ThisNCRRejectCount, @VM) SRP_JSON(objNCR, 'SetValue', 'LossComments', NCRRecord) NCRJson = SRP_JSON(objNCR, 'Stringify', 'Styled') SRP_JSON(objNCR, 'Release') end else ErrorMessage = 'Error creating NCR Json Object' end end else ErrorMessage = Error_Services('GetMessage') end end else ErrorMessage = 'Non-existent NCR Id passed to routine' end If ErrorMessage NE '' then Error_Services('Add', ErrorMessage) end Response = NCRJson end service