Compile function Transaction_Services(@Service, @Params)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from Infineon Technologies.

    Name        :   Transaction_Services

    Description :   Handler program for all module related services.

    Notes       :   Service module to support environmental state issues. Environmental refers to the state of the
                    operating system, which includes version, client vs. server, and path to critical systems.

    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 requesting procedure

    Metadata    :

    History     :   (Date, Initials, Notes)
        06/24/25    djs     Original programmer.

***********************************************************************************************************************/
#pragma precomp SRP_PreCompiler

$Insert SERVICE_SETUP
$Insert APP_INSERTS
$Insert TRANSACTION_QUEUE_EQUATES
$Insert RLIST_EQUATES

EQU COMMA$ to ','

Declare function   Datetime, RTI_CreateGuid, Error_Services, SRP_Encode, SRP_Decode, Database_Services
Declare function   Environment_Services, Logging_Services
Declare subroutine Database_Services, Error_Services, Logging_Services

GoToService

Return Response or ""

//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------

Service PostWriteFieldTransaction(Table, Key, FieldNo, FieldVal, MvPos)
	
	ErrorMsg = ''
	Begin Case
		Case (Table EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Table passed into service.'
		Case (Key EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Key passed into service.'
		Case (FieldNo EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Table passed into service.'
		Case Not(Num(FieldNo))
			ErrorMsg = 'Error in ':Service:' service. FieldNo ':FieldNo:' is not a number.'
		Case ( (MvPos NE '') and Not(Num(MvPos)) )
		    ErrorMsg = 'Error in ':Service:' service. MvPos ':MvPos:' is not a number.'
		Case Otherwise$
			TransKey                                     = RTI_CreateGuid()
			TransRec                                     = ''
			TransRec<TRANSACTION_QUEUE.TRANSACTION_DTM$> = Datetime()
			TransRec<TRANSACTION_QUEUE.ACTION$>          = 'WRITE_FIELD'
			TransRec<TRANSACTION_QUEUE.TABLE$>           = Table
			TransRec<TRANSACTION_QUEUE.KEY$>             = Key
			TransRec<TRANSACTION_QUEUE.COLUMN$>          = FieldNo
			TransRec<TRANSACTION_QUEUE.VALUE$>           = FieldVal
			TransRec<TRANSACTION_QUEUE.MV_POS$>          = Int(MvPos)
			Database_Services('WriteDataRow', 'TRANSACTION_QUEUE', TransKey, TransRec)
			If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')			
	End Case
	
	If ErrorMsg EQ '' then
		Response = True$
	end else
		Error_Services('Add', ErrorMsg)
		Response = False$
	end
	
end service


Service PostWriteRecordTransaction(Table, Key, Record)
	
	ErrorMsg = ''
	Begin Case
		Case (Table EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Table passed into service.'
		Case (Key EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Key passed into service.'
		Case (Record EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Record passed into service.'
		Case Otherwise$
			TransKey                                     = RTI_CreateGuid()
			TransRec                                     = ''
			TransRec<TRANSACTION_QUEUE.TRANSACTION_DTM$> = Datetime()
			TransRec<TRANSACTION_QUEUE.ACTION$>          = 'WRITE_RECORD'
			TransRec<TRANSACTION_QUEUE.TABLE$>           = Table
			TransRec<TRANSACTION_QUEUE.KEY$>             = Key
			TransRec<TRANSACTION_QUEUE.RECORD$>          = SRP_Encode(Record, 'BASE64')
			Database_Services('WriteDataRow', 'TRANSACTION_QUEUE', TransKey, TransRec)
			If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')
	End Case
	
	If ErrorMsg EQ '' then
		Response = True$
	end else
		Error_Services('Add', ErrorMsg)
		Response = False$
	end
	
end service


Service PostDeleteRecordTransaction(Table, Key)
	
	ErrorMsg = ''
	Begin Case
		Case (Table EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Table passed into service.'
		Case (Key EQ '')
			ErrorMsg = 'Error in ':Service:' service. Null Key passed into service.'
		Case Otherwise$
			TransKey                                     = RTI_CreateGuid()
			TransRec                                     = ''
			TransRec<TRANSACTION_QUEUE.TRANSACTION_DTM$> = Datetime()
			TransRec<TRANSACTION_QUEUE.ACTION$>          = 'DELETE_RECORD'
			TransRec<TRANSACTION_QUEUE.TABLE$>           = Table
			TransRec<TRANSACTION_QUEUE.KEY$>             = Key
			Database_Services('WriteDataRow', 'TRANSACTION_QUEUE', TransKey, TransRec)
			If Error_Services('HasError') then ErrorMsg = Error_Services('GetMessage')			
	End Case
	
	If ErrorMsg EQ '' then
		Response = True$
	end else
		Error_Services('Add', ErrorMsg)
		Response = False$
	end
	
end service


Service ProcessTransactionQueue()
	
	hSysLists = Database_Services('GetTableHandle', 'SYSLISTS')
	Lock hSysLists, ServiceKeyID then
		LogPath      = Environment_Services('GetApplicationRootPath') : '\LogFiles\Transaction'
		LogDate      = Oconv(Date(), 'D4/')
		LogTime      = Oconv(Time(), 'MTS')
		LogFileName  = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' Transaction Queue Log.csv'
		Headers      = 'Logging DTM':@FM:'Result':@FM:'Action':@FM:'Table':@FM:'Key':@FM:'Base64Record'
		Headers     := @FM:'Column':@FM:'Value':@FM:'MvPos'
		objQueueLog  = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, COMMA$, Headers, '', False$, False$)
		LoggingDTM   = LogDate : ' ' : LogTime   ; // Logging DTM
		
		GoSub ClearCursors
		
		Query   = 'SELECT TRANSACTION_QUEUE BY TRANSACTION_DTM'
		RList(Query, TARGET_ACTIVELIST$, '', '', '')
		ErrCode = ''
		If Not(Get_Status(ErrCode)) then
			EOF = False$
			Loop
				LogData 	= ''
				DeleteTrans = False$
				ErrorMsg    = ''
				ReadNext TransId else EOF = True$
			Until EOF
				TransRec = Database_Services('ReadDataRow', 'TRANSACTION_QUEUE', TransId)
				If Error_Services('NoError') then
					Action     = TransRec<TRANSACTION_QUEUE.ACTION$>
					Table      = TransRec<TRANSACTION_QUEUE.TABLE$>
					Key        = TransRec<TRANSACTION_QUEUE.KEY$>
					MvPos      = TransRec<TRANSACTION_QUEUE.MV_POS$>
					LogData<3> = Action
					LogData<4> = Table
					LogData<5> = Key
					HaveLock   = Database_Services('GetKeyIDLock', Table, Key)
					If HaveLock then 
						Begin Case
							Case Action EQ 'WRITE_FIELD'
								FieldNo    = TransRec<TRANSACTION_QUEUE.COLUMN$>
								FieldVal   = TransRec<TRANSACTION_QUEUE.VALUE$>
								LogData<7> = FieldNo
								LogData<8> = FieldVal
								LogData<9> = MvPos
								Open Table to hTable then
								    If MvPos NE '' then
								        ReadV Col from hTable, Key, FieldNo then
								            Col<0, MvPos> = FieldVal
								            WriteV Col on hTable, Key, FieldNo then
								                DeleteTrans = True$
								            end else
                                                ErrorMsg  = 'Error in ':Service:' service. Error calling WriteV. '
                                                ErrorMsg := 'File error: ':@File_Error								                
								            end
								        end else
								            ErrorMsg  = 'Error in ':Service:' service. Error reading column ':Col:' from table ':Table:'. '
								            ErrorMsg := 'File error: ':@File_Error
								        end
								    end else 
                                        WriteV FieldVal on hTable, Key, FieldNo then
                                            DeleteTrans = True$
                                        end else
                                            ErrorMsg  = 'Error in ':Service:' service. Error calling WriteV. '
                                            ErrorMsg := 'File error: ':@File_Error
                                        end
                                    end
								end else
									ErrorMsg = 'Error in ':Service:' service. Error opening ':Table:'.'
								end
							Case Action EQ 'WRITE_RECORD'
								Record     = SRP_Decode(TransRec<TRANSACTION_QUEUE.RECORD$>, 'BASE64')
								LogData<6> = Record
								Database_Services('WriteDataRow', Table, Key, Record, True$, False$, False$)
								If Error_Services('NoError') then
									DeleteTrans = True$
								end else
									ErrorMsg = Error_Services('GetMessage')
								end
							Case Action EQ 'DELETE_RECORD'
								Database_Services('DeleteDataRow', Table, Key, True$, False$)
								If Error_Services('NoError') then
									DeleteTrans = True$
								end else
									ErrorMsg = Error_Services('GetMessage')
								end
							Case Otherwise$
								DeleteTrans = True$
								ErrorMsg  = 'Error in ':Service:' service. Invalid Action ':Action:'.'
						End Case
						Database_Services('ReleaseKeyIDLock', Table, Key)
						If DeleteTrans then Database_Services('DeleteDataRow', 'TRANSACTION_QUEUE', TransId)
					end else
						ErrorMsg = 'Error in ':Service:' service. Failed to get lock on ':Table:' ':Key:'.'
					end
				end else
					ErrorMsg = Error_Services('GetMessage')
				end
				LogData<1> = OConv(Datetime(), 'DT2/^H')
				If ErrorMsg EQ '' then
					// Log success
					LogData<2> = 'Successfully processed transaction ':TransId:'.'
				end else
					// Log failure
					LogData<2> = 'Failed to process transaction ':TransId:'. Error message: ':ErrorMsg
				end
				Logging_Services('AppendLog', objQueueLog, LogData, @RM, @FM)
			Repeat			
		end

		Unlock hSysLists, ServiceKeyID else Null
	end
	
end service


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Internal GoSubs
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ClearCursors:
	
	For counter = 0 to 8
		ClearSelect counter
	Next counter
	
return

