'Option Explicit
Private Const DEBUG_ON = False

Private Const cenLicenses = 8
Private Const cenUsers = 16
Private Const cenDat = 32
Private Const cenDef = 64
Private Const mblnHasWorkflow = True
Private Const MACRO_CURRENT_USER = "-3"
Private Const MACRO_USER_COMPANY = "-16"
Private Const cenRelatedRecords = 106
Private Const cenPassword = 115
Private Const adBookmarkFirst = 1
Private Const cenDSEnsureOpenConnection = 1
Private Const adLockOptimistic = 3
Private Const adOpenStatic = 3
Private Const SEMI_COLON = ";"

' Parent-Child
Private Const FLD_STATUS = "21" 'Status or Dev Status
Private Const FLD_NAME_CTRLD_BY_PARENT = "nControlledByParent" ' Field for inheriting the values from the parent issue
Private Const FLD_NAME_REL_RECS = "nRelID"  'RelatedIssues
' By default, the status of child issues is controlled by the parent
Private Const STR_VAL_NO = "2"
Private Const FLD_ID = "nID"

' State-Substate
Private Const STATE_CLOSED = 2
Private Const SUB_STATE_NEW = 0
Private Const SUB_STATE_ACTIONS_COMPLETED = 7
Private Const SUB_STATE_ACTIONS_PENDING_ALLOC = 20
Private Const STATE_OPEN = 1

Private Const FLD_ID_STATE = 20
' Const FLD_ID_STATE = 98 'Dev State

Private Const ESC_STATE_ON = 1
Private Const FLD_ESC_STATE = "nEscalationOn"
Private Const FLD_STATE_ID = "nStateID"
Private Const FLD_SUBMITTER_ID = "nSubmitterID"
Private Const FLD_SUBSTATE_ID = "nSubstateID"
Private Const FLD_USER_ID = "nUserID"
Private Const FLD_DRINIT_ID = "DR_Initiated"
Private Const FLD_DEV_STATUS = "Dev_Status"
Private Const FLD_REV_NUM = "nRevisionNumber"
Private Const FLD_UPD_DATE = "dLastUpdateDate"
Private Const FLD_UPD_TIME = "dUpdateTime"
Private Const FLD_ESCALATION_LEVEL = "nEscalationLevel"
Private Const FLD_TARGET_IRT = "dTargetIRT"
Private Const FLD_ACTUAL_IRT_DATE = "dActualIRTDate"
Private Const FLD_ACTUAL_IRT_TIME = "dActualIRTTime"
Private Const FLD_TARGET_CLOSURE_TIME = "dTargetClosureTime"
Private Const FLD_ASSOCIATED_SLA = "nAssociatedSLA"
Private Const FLD_ACT_LOG = "Activity$Log"
Private Const FLD_DESC_LOG = "Description_Log"
Private Const FLD_EMP_STATE = "nStateID"
Private Const FLD_IS_A_PROBLEM = "Is_a_Problem_"
Private Const FLD_PRIMARY_EMP = "nPrimaryEmp"
Private Const FLD_CAN_SEE_ALL_EMPLOYEES = "Can_See_All_Employees_"
Private Const FLD_ASSET_LOCATION = "Asset_Location"
Private Const FLD_ASSET_SUB_STATUS = "Asset_Sub_Status"
Private Const FLD_RETIRED_DATE = "Retired_Date"
Private Const FLD_SHORT_NAME = "Short_Name"
Private Const FLD_CLOSED_BY = "Closed_By"

' License Manager (LM)
Private Const FLD_APPROVED_BY_ID = "Authorized_By"
Private Const FLD_NUMBER_LICENSES = "Units" '520
Private Const FLD_NUMBER_LICENSES_ID = "520"
Private Const FLD_REMAINING_LICENSES = "Left_licenses" '521
Private Const FLD_REMAINING_LICENSES_ID = "521"
Private Const FLD_ALLOCATED_USERS = "Licensees" '523
Private Const FLD_ALLOCATED_USERS_ID = "523" '429
Private Const FLD_ALLOCATED_COMPUTERS = "ComputerName" '524
Private Const FLD_ALLOCATED_COMPUTERS_ID = "66" '66
Private Const FLD_ALLOCATED_TYPE = "Allocation_Type" '525
Private Const FLD_ALLOCATED_TYPE_ID = "525"
Private Const FLD_ALLOCATED_ASSETS_ID = "427"
Private Const FLD_ALLOCATED_ASSETS = "Assigned_Assets"
Private Const FULLY_ALLOCATED  = 15
Private Const PARTIALLY_ALLOCATED = 0
Private Const PENDING_ALLOCATION = 5

Private Const FLD_AUTO_CREATE_ASSETS = "Auto_Create_Assets"
Private Const FLD_AUTO_CREATE_ASSETS_ID = "942"
Private Const FLD_PENDING_PROCESSING = "Process_Pending"
Private Const FLD_PENDING_PROCESSING_ID = "944"
Private Const FLD_SUB_TYPE_ID = "894"

' Time stamps
Private Const FLD_CLOSED_DATE = "dClosedDate"
Private Const FLD_CLOSED_TIME = "dClosedTime"

' ID of Par-Child field, resolved once
Private m_lngFldRelRec
Private m_strFldControlledByPar

Private m_blnEmployeeTerminated
Private m_lngPrimaryEmpID
Private m_dtEndDate
Private m_dtEndTime

Private m_blnCanSeeAllEmps
Private m_blnCanSeeAllEmpsChanged

Private m_lngAssignToUser
Private m_lngAssignToLocation

Private m_lngPrevAssignToUser
Private m_lngPrevAssignToLocation

Private m_blnRetiredDateSet
Private m_blnAssetStatusChanged

Private m_blnLocationNameChanged

Private m_blnAutoCreateAssetsChanged

Private Const CHECK_QA_ITEMS = False

Private Const MQ_TIME_STAMP_TAG = "|*Mq_TimeStamp*|"

Private Const VALUE_YES = 1
Private Const VALUE_NO = 2

' VIT Project Templates
Private Const USERS_TEMPLATE = 8
Private Const LICENSE_MGR_TEMPLATE = 24
Private Const RESOURCES_TEMPLATE = 15
Private Const ROLES_TEMPLATE = 14
Private Const ACTIONS_TEMPLATE = 16
Private Const INVOICES_TEMPLATE = 22

Private Const FLD_PLACE_HOLDER = "<PlaceHolderDontSaveValue>"

Private Const EMP_STATE_INACTIVE = 2
Private Const EMP_STATUS_TERMINATED_VALUE_ID = 3

Private Const TBL_USER_EMPLOYMENT = "tblUser_Employment"
Private Const TBL_USER = "tblUser"

Public Function Mq_OnAddNewRecord(objApp, rs, lngRecordID, lngUserID)

    ' This function will set the default values for fields in a new record.
        
    Const SUB_STATE_NEW = 0
    Const STATE_OPEN = 1
    Const USER_NONE = 0
    Const FLD_ORIGINATOR_ID = "nOriginatorID"
	
	LogMsg "Setting default values on new issue #" & lngRecordID & " created by user ID:" & lngUserID _
		& " . Workflow controlled: " & mblnHasWorkflow
	
    'we add the mblnHasWorkflow constant to the top of the file when we load it in the web class.
    If mblnHasWorkflow = False Then
        Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, SUB_STATE_NEW)
    End If
    
    Call objApp.SetFieldValue(rs, FLD_STATE_ID, STATE_OPEN)
    Call objApp.SetFieldValue(rs, FLD_SUBMITTER_ID, lngUserID)
    Call objApp.SetFieldValue(rs, FLD_ORIGINATOR_ID, lngUserID)
    Call objApp.SetFieldValue(rs, FLD_USER_ID, USER_NONE)
    Call objApp.SetFieldValue(rs, FLD_ESC_STATE, ESC_STATE_ON)
    Call objApp.SetFieldValue(rs, "Requested_By", lngUserID)

    Call SetSubmitDateTimeState(objApp, rs, "")
End Function


Public Function Mq_OnCopyRecord(objApp, rs, lngRecordID, lngUserID, blnCopyAsChild)

    ' This function will set the default values for fields in a copied record.
    
	LogMsg "Setting default values on new copied issue #" & lngRecordID & " created by user ID:" & lngUserID _
		& " ."
		
	Dim lngSubstateControlledByParent
	Dim lngIsAProblem
	
	Const VAL_YES = 1
	Const VAL_NO = 2
	
	If blnCopyAsChild = True Then
		lngSubstateControlledByParent = IfNullL(objApp.GetFieldValue(rs, FLD_NAME_CTRLD_BY_PARENT))
		
		If lngSubstateControlledByParent = VAL_NO Then
		    Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, SUB_STATE_NEW)
			Call objApp.SetFieldValue(rs, FLD_STATE_ID, STATE_OPEN)
	    End If
	    
	    lngIsAProblem = IfNullL(objApp.GetFieldValue(rs, FLD_IS_A_PROBLEM))
	    
	    If lngIsAProblem = VAL_YES Then
		    Call objApp.SetFieldValue(rs, FLD_IS_A_PROBLEM, VAL_NO)
	    End If
    Else
	    Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, SUB_STATE_NEW)
	    Call objApp.SetFieldValue(rs, FLD_STATE_ID, STATE_OPEN)
	End If
    Call objApp.SetFieldValue(rs, FLD_ESC_STATE, ESC_STATE_ON)
    Call objApp.SetFieldValue(rs, FLD_ESCALATION_LEVEL, Null)
    Call objApp.SetFieldValue(rs, FLD_SUBMITTER_ID, lngUserID)
    Call objApp.SetFieldValue(rs, FLD_CLOSED_DATE, Null)
    Call objApp.SetFieldValue(rs, FLD_CLOSED_TIME, Null)
    Call objApp.SetFieldValue(rs, FLD_TARGET_IRT, Null)
    Call objApp.SetFieldValue(rs, FLD_ACTUAL_IRT_DATE, Null)
    Call objApp.SetFieldValue(rs, FLD_ACTUAL_IRT_TIME, Null)
    Call objApp.SetFieldValue(rs, FLD_TARGET_CLOSURE_TIME, Null)
    Call objApp.SetFieldValue(rs, FLD_ASSOCIATED_SLA, Null)
    Call objApp.SetFieldValue(rs, FLD_ACT_LOG, Null)
    Call objApp.SetFieldValue(rs, FLD_DESC_LOG, Null)
    Call objApp.SetFieldValue(rs, FLD_CLOSED_BY, Null)

    Call SetSubmitDateTimeState(objApp, rs, "")
End Function


Public Function Mq_OnValidate(objApp, lngRecord, dctFldVals)
	'this function will allow user to add custom validation before saving the record.
	'here you can do validation specific to your needs.
	Dim strReturn
	
	'strReturn = ValidateParChild(objApp, lngRecord, dctFldVals)
	
	If Len(strReturn) = 0 Then
		strReturn = ValidateUniqueness(objApp, lngRecord, dctFldVals)
	End If

	If Len(strReturn) = 0 Then
		If objApp.CensusApplication.CurrentProject.TemplateID = LICENSE_MGR_TEMPLATE Then
			strReturn = LM_ValidateAllocation(objApp, lngRecord, dctFldVals)
		End If
	End If

	If Len(strReturn) = 0 Then
		If objApp.CensusApplication.CurrentProject.TemplateID = USERS_TEMPLATE Then
			strReturn = ValidateUserHasJob(objApp, lngRecord, dctFldVals)
		End If
	End If
	
	If Len(strReturn) = 0 Then
		If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
			strReturn = ValidateRequiredByWithinTimeConstraints(objApp, lngRecord, dctFldVals)
		End If
	End If
	
	Mq_OnValidate = strReturn
	
End Function

Private Function ValidateUniqueness(objApp, lngRecord, dctFldVals)

	Const FLD_BRIEF_DESCRIPTION_ID = "30"
	Const FLD_RES_USAGE_TYPE = "806"
	Const FLD_EVENT_TYPE = "799"
	Const USAGE_TYPE_TEMPLATE = "2"
	Const FLD_TEMP_RES_ID = "831"
	Const FLD_ROLE_TYPE = "808"
	
	Dim strRet
	Dim strDuplicateMessage
	Dim blnVerifyUniqueness
	Dim objString
	Dim strAddCond
	Dim strUsageType
	Dim strIDs
	Dim lngEventType
	Dim lngTempResID
	Dim lngRoleType
	
	strRet = ""
	strAddCond = ""
	strIDs = ""
	lngTempResID = 0
	
	blnVerifyUniqueness = False
	
	If objApp.CensusApplication.CurrentProject.TemplateID = ACTIONS_TEMPLATE Then
		strDuplicateMessage = "There is already an action with the name %1 in this resource"

		strAddCond = " AND [nUsageType]=" & USAGE_TYPE_TEMPLATE

		If dctFldVals.Exists(FLD_TEMP_RES_ID) Then
			lngTempResID = IfNullL(dctFldVals.Item(FLD_TEMP_RES_ID))
			dctFldVals.Item(FLD_TEMP_RES_ID) = 0
		End If
			
		strIDs = GetActionIDsInRes(lngRecord, lngTempResID, objApp.CensusApplication.CurrentProject.GetAllDataStores(2048))
		
		If Len(strIDs) > 0 Then
			 strAddCond = strAddCond & " AND [nID] IN(" & strIDs & ")"
		
			If dctFldVals.Exists(FLD_EVENT_TYPE) Then
				lngEventType = IfNullL(dctFldVals.Item(FLD_EVENT_TYPE))
				If lngEventType <> 0 Then
					strAddCond = strAddCond & " AND [Event_Type]=" & lngEventType			
				End If
			End If
		
			blnVerifyUniqueness = True
		Else
			blnVerifyUniqueness = False
		End If
		
	ElseIf objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		strDuplicateMessage = "There is already a resource with the name %1"
		strAddCond = " AND [nUsageType]=" & USAGE_TYPE_TEMPLATE
		If dctFldVals.Exists(FLD_RES_USAGE_TYPE) Then
			strUsageType = dctFldVals.Item(FLD_RES_USAGE_TYPE)
			'Only check for unique names if it's a template, not an employee instance
			If strUsageType = USAGE_TYPE_TEMPLATE Then
				blnVerifyUniqueness = True
			End If
		End If
		
	ElseIf objApp.CensusApplication.CurrentProject.TemplateID = ROLES_TEMPLATE Then
		strDuplicateMessage = "There is already a role of this type with the name %1"
		lngRoleType = IfNullL(dctFldVals.Item(FLD_ROLE_TYPE))
		strAddCond = " AND [Role_Type]=" & lngRoleType
		blnVerifyUniqueness = True	
	End If

	If blnVerifyUniqueness Then
		'Validate Brief Description field in templates...
		If dctFldVals.Exists(FLD_BRIEF_DESCRIPTION_ID) Then
			strBriefDescription = dctFldVals.Item(FLD_BRIEF_DESCRIPTION_ID)
			
			
			If ValueAlreadyExistsForField(objApp, FLD_BRIEF_DESCRIPTION_ID, strBriefDescription, lngRecord, strAddCond) Then
				Set objString = CreateObject("Mqsysutils40.CMqString")
	
				objString.InitializeString CStr(strDuplicateMessage)
				strRet = objString.FormatString(strBriefDescription)
			
				Set objString = Nothing
			End If
		End If
	End If
	
	ValidateUniqueness = strRet
	
End Function

Private Function GetActionIDsInRes(lngOneAction, lngTempResID, dsResDat)

	Dim strSQL
	Dim strIDs
	Dim rsActIDs
	Dim rsResID
	Dim lngResID
	strIDs = ""
	
	If lngTempResID = 0 Then
		strSQL = "SELECT [nResID] FROM [tblActRes] WHERE [nActID] = " & lngOneAction
			
		Set rsResID = dsResDat.GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
		If Not rsResID.EOF Then
			lngResID = IfNullL(rsResID.Fields("nResID").Value)
		End If
		
		rsResID.Close
		Set rsResID = Nothing
	
	Else
		lngResID = lngTempResID
	End If
	
	If lngResID <> 0 Then
		strSQL = "SELECT [nActID] FROM [tblActRes] WHERE [nResID] = " & lngResID
		
		Set rsActIDs = dsResDat.GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)

		If Not rsActIDs.EOF Then
		    strIDs = rsActIDs.GetString(, , , ",")
		End If
			        
		If Right(strIDs, 1) = "," Then
			strIDs = Left(strIDs, Len(strIDs) - 1)
		End If
			        
		rsActIDs.Close
		Set rsActIDs = Nothing
	End If
	
	GetActionIDsInRes = strIDs

End Function

Private Function ValueAlreadyExistsForField(objApp, lngFieldID, strValue, lngCurrentRecord, strAddCond)

	Dim blnReturn
	Dim strSQL
	Dim rsValidation
	
	blnReturn = False
	
	If objApp.CensusApplication.CurrentProject.Fields.Exists(CLng(lngFieldID)) Then
		With objApp.CensusApplication.CurrentProject.Fields.Item(CLng(lngFieldID))
			strSQL = "SELECT [nID] FROM [" & .TableName & "] WHERE [" & .FieldName & "]='" & _
						Replace(strValue, "'", "''") & "' AND [nID]<>" & lngCurrentRecord & strAddCond
			Set rsValidation = objApp.CensusApplication.CurrentProject.GetAllDataStores(.TableDSType).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
			
			If Not rsValidation.EOF Then
				'there are others
				blnReturn = True
			End If
			
			rsValidation.Close
			Set rsValidation = Nothing
		End With
	End If
	
	ValueAlreadyExistsForField = blnReturn

End Function

Public Function Mq_OnBeforeSave(objApp, lngRecord, dctFldVals)
    'this function will allow user to add custom code before saving the record.
    'here you can add code specific to your needs.
    
    m_blnEmployeeTerminated = False
    m_blnCanSeeAllEmps = False
	m_blnCanSeeAllEmpsChanged = False
    m_lngPrimaryEmpID = 0
    m_lngAssignToUser = 0
	m_lngAssignToLocation = 0
	m_lngPrevAssignToUser = 0
	m_lngPrevAssignToLocation = 0
	m_blnRetiredDateSet = False
    m_blnAssetStatusChanged = False
	m_blnLocationNameChanged = False
	m_blnAutoCreateAssetsChanged = False
	
    Mq_OnBeforeSave = ""
End Function


Public Function Mq_PrepareServerTimestampFlds(objApp, lngRecord, dctFldVals, strSourceTSFld, strTargetTSFld)
   
   	Dim oTgtFld
   	Dim strTargetTSFldVal

	If dctFldVals.Exists(strSourceTSFld) Then
		Set oTgtFld = objApp.CensusApplication.CurrentProject.Fields.Item(CLng(strTargetTSFld))

        strTargetTSFldVal=GetFldValueFromSaveRS(objApp,oTgtFld, False)

	    dctFldVals.Item(strTargetTSFld)=FormatNewTSEntry(objApp, dctFldVals.Item(strSourceTSFld)) & _
	    								Chr(13) & Chr(10) & strTargetTSFldVal
	    								
	    dctFldVals.Item(strSourceTSFld)=""
	    	    
	    LogMsg "New value of field [" & strTargetTSFld & "]:" & dctFldVals.Item(strTargetTSFld)
	    
	End If
	
    Mq_PrepareServerTimestampFlds= ""
End Function


Private Function FormatNewTSEntry(objApp, strUnformattedValue)
	On Error Resume Next
	
	Dim strUserName
	Dim strCurrentSubstate
	Dim strNewTSText
	Dim oFld

    Set oFld = objApp.CensusApplication.CurrentProject.Fields.Item(CLng(FLD_STATUS))
    
    strCurrentSubstate = GetFldValueFromSaveRS (objApp,oFld, True)
		    		    
    FormatNewTSEntry=MQ_TIME_STAMP_TAG & "                    " & objApp.strCurrentUser & "   (" & strCurrentSubstate & ")" & _
    				Chr(13) & Chr(10) & strUnformattedValue & Chr(13) & Chr(10)
    
End Function


Private Function GetFldValueFromSaveRS(objApp, oFld, bResolveIDToName)
	On Error Resume Next
	
	Dim strTableName 
	Dim rs
	
    If Not oFld Is Nothing Then
    	strTableName = oFld.TableName
		
	    If objApp.DictDtsTablesForSave.Exists(LCase(strTableName)) Then
        	Set rs = objApp.DictDtsTablesForSave(LCase(strTableName)).rs

            GetFldValueFromSaveRS = objApp.GetFieldValue(rs, oFld.FieldName)
            
			LogMsg "Getting the value of field [" & oFld.FieldName & "] from the save recordset. The current value is:" & GetFldValueFromSaveRS 
			
			If bResolveIDToName Then
				If (objApp.DBConnections.Exists(oFld.ValueTableDSType)) Then
				
			        Set oFld.DefinitionsDataStore = objApp.DBConnections.Item(oFld.ValueTableDSType)
			        
			        If IsNumeric(GetFldValueFromSaveRS ) Then
			        
		                If oFld.ChoiceValues.Exists(CLng(GetFldValueFromSaveRS )) Then

		                	GetFldValueFromSaveRS  = oFld.ChoiceValues.Item(CLng(GetFldValueFromSaveRS )).Name

		                End If
			                        
			        End If
			        
				End If
			End If

        End If
        
    End If

	Set rs=Nothing
	
End Function

Public Function Mq_OnFieldSave(objApp, cfield, varCurrentValue, ByRef strChangedFields)
    Dim blnSubStateChanged
    Dim blnOwnerChanged
    Dim blnResult
    Dim varPreviousValue
    Dim rs
    Dim strTableName
    Dim varContent
	Dim lngRecordID
	Dim strLog
	Dim strFilter
	Dim blnDontSave
	Dim lngCopyFileVal
	Dim objStringManip
	Set objStringManip = CreateObject("Mqsysutils40.CMqStringManipulation")
	
	Const FLD_COPY_FILE = "fCopyFile"
	Const FLD_COMPOSITE_ID = "nCompositeID"
	Const DEFAULT_TEMP_PWD = "********"
	
	blnDontSave = False
	'set the reference of the recordset to the current one in the dictionary
    strTableName = cfield.TableName

	lngRecordID = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs.Fields(FLD_ID).Value
	
	If cfield.FieldDataType = cenPassword Then
		If varCurrentValue = DEFAULT_TEMP_PWD Then
			blnDontSave = True
		Else
			varCurrentValue = objStringManip.MqEncrypt(CStr(varCurrentValue))
		End If
	End If
	
	strLog="Reviewing if the field [" & cfield.FieldName & "] will be saved to new value:[" & varCurrentValue & "], for issue #" & lngRecordID
	
	If blnDontSave = False Then
		If strTableName = "tblUser_Employment" And cfield.RelationShipType = 3 Then
			If cfield.fieldName = "End_Date" Then
				m_dtEndDate = varCurrentValue
			End If
			
			If cfield.fieldName = "End_Time" Then
				m_dtEndTime = varCurrentValue
			End If
		End If
		
		If objApp.DictDtsTablesForSave.Exists(LCase(strTableName)) Then
			Set rs = objApp.DictDtsTablesForSave(LCase(strTableName)).rs
					
			strLog= strLog & ". Field is stored in table [" & strTableName & "] with relationship type " & objApp.DictDtsTablesForSave(LCase(strTableName)).lngRelationShipType			
				
	        If objApp.DictDtsTablesForSave(LCase(strTableName)).lngRelationShipType <> 2 Then
				
				If objApp.DictDtsTablesForSave(LCase(strTableName)).lngRelationShipType = 3 Then
					
					strFilter = "[" & FLD_ID & "]=" & lngRecordID & " AND [bPrimary] <> 0"
					
					If rs.Filter <> strFilter Then
						rs.Filter = strFilter
					End If
					
					If (rs.BOF And rs.EOF) Then
	                    rs.AddNew
	                    rs.Fields(FLD_ID).Value = lngRecordID
	                    rs.Fields("bPrimary").Value = True
						m_lngPrimaryEmpID = GetNextMax(strTableName, "nCompositeID", _
												objApp.DBConnections(cenUsers).GetConnection(cenDSEnsureOpenConnection))
						rs.Fields("nCompositeID").Value = m_lngPrimaryEmpID

					Else
						rs.Fields(FLD_ID).Value = lngRecordID
					End If
				Else        
					If (rs.BOF And rs.EOF) Then
					        rs.AddNew
					        rs.Fields(FLD_ID).Value = lngRecordID
					End If
	            End If

	            'get the previous value
	            varPreviousValue = objApp.GetFieldValue(rs, cfield.FieldName)

				strLog=strLog & ". The previous value in the database for the field is:[" & varPreviousValue & "]."
					
	            'check if the previous value is null.
	            If IsNull(varPreviousValue) Then
	                'check the current value. If the current value is not blank then we will save it.
	                If CStr(varCurrentValue) <> "" Then
	                    strLog = strLog & "=> saving the new value."
							blnResult = SaveField(objApp, cfield, rs, varCurrentValue, strChangedFields, varPreviousValue)
	                Else
	                        If cfield.FieldName = FLD_SUBSTATE_ID Then
	                                Call Mq_OnSubStateChange(objApp, cfield, varCurrentValue, rs, strChangedFields)
	                        ElseIf cfield.fieldName = FLD_DEV_STATUS Then
	                                Call OnDevSubStateChange(objApp, cfield, varCurrentValue, rs, strChangedFields)
	                        End If
	                End If

	            Else 'if the previous value is not null
	                ' Check the current value. if it is blank then we have to set the recordset value
	                ' to null
	                If StrComp(CStr(varPreviousValue), CStr(varCurrentValue), vbTextCompare) <> 0 Then
	                    strLog = strLog & "=> saving the new value."
							blnResult = SaveField(objApp, cfield, rs, varCurrentValue, strChangedFields, varPreviousValue)
	                End If
	            End If

	        Else
	            If cfield.FieldDataType = cenRelatedRecords Then
	                SaveRelRec objApp, cfield, varCurrentValue, strChangedFields, rs
				ElseIf cfield.RelationShipType = 1 Then
					SaveParentRec objApp, cfield, varCurrentValue, strChangedFields, rs
	            End If
	        End If
		Else
			strLog="The table [" & strTableName & "] was not found and it is necessary for saving the field [" & cfield.FieldName & "]. The field will not be saved."
        End If
		LogMsg strLog
		   
        Mq_OnFieldSave = blnResult
	End If
	
	Set objStringManip = Nothing
	
End Function


Private Function SaveField(ByVal objApp, ByVal objFld, ByVal rs, ByVal varCurrentValue, ByRef strChangedFields, ByVal varPreviousValue)

    Dim strFieldName
    Dim blnResult
    Dim blnSaveField
    
	LogMsg "Saving value of field " & objFld.FieldName & " into recordset."
	
    'If we pass <PlaceHolderDontSaveValue> as the value of the field,
    'don't save it. It could be used for timestamping fields and making
    'the source field required (so it passes this value if there was a value client side)
    Const FLD_DEV_OWNER = "Dev_Owner"
    Const cenMemo = 12
    
	
    blnResult = False
    blnSaveField = True
    
    If varCurrentValue = FLD_PLACE_HOLDER Then
		LogMsg "Value is timestamp placeholder " & FLD_PLACE_HOLDER & ". Value not to be saved in the database."
        blnResult = True
    Else
    
        If (Not objFld Is Nothing) And (Not objApp Is Nothing) And (Not rs Is Nothing) Then
            strFieldName = objFld.FieldName
      
            If StrComp(strFieldName, FLD_SUBSTATE_ID, vbTextCompare) = 0 Then
                    Call Mq_OnSubStateChange(objApp, objFld, varCurrentValue, rs, strChangedFields)
            ElseIf StrComp(strFieldName, FLD_DEV_STATUS, vbTextCompare) = 0 Then
                    Call OnDevSubStateChange(objApp, objFld, varCurrentValue, rs, strChangedFields)
            ElseIf StrComp(strFieldName, FLD_USER_ID, vbTextCompare) = 0 Then
                    Call OnOwnerChanged(objApp, rs, strChangedFields)
					Call OnAssetOwnerChanged(objApp, varCurrentValue, rs, strChangedFields, varPreviousValue)
	    ElseIf StrComp(strFieldName, FLD_DRINIT_ID, vbTextCompare) = 0 Then
                    Call OnDRInitChanged(objApp, rs, strChangedFields)
            ElseIf StrComp(strFieldName, FLD_DEV_OWNER, vbTextCompare) = 0 Then
                    Call OnDevOwnerChanged(objApp, rs, strChangedFields)
            ElseIf StrComp(strFieldName, FLD_ESC_STATE, vbTextCompare) = 0 Then
                    Call OnEscalationOnChanged(objApp, varCurrentValue, rs, strChangedFields)
            ElseIf StrComp(strFieldName, FLD_EMP_STATE, vbTextCompare) = 0 And _
								objApp.CensusApplication.CurrentProject.TemplateID = USERS_TEMPLATE Then
					Call OnEmployeeStateChanged(objApp, varCurrentValue, rs, strChangedFields)
			ElseIf StrComp(strFieldName, FLD_CAN_SEE_ALL_EMPLOYEES, vbTextCompare) = 0 Then
					Call OnCanSeeEmpsChanged(objApp, varCurrentValue, rs, strChangedFields)	
			ElseIf StrComp(strFieldName, FLD_ASSET_LOCATION, vbTextCompare) = 0 Then
					Call OnAssetLocationChanged(objApp, varCurrentValue, rs, strChangedFields, varPreviousValue)
			ElseIf StrComp(strFieldName, FLD_ASSET_SUB_STATUS, vbTextCompare) = 0 Then
					Call OnAssetSubStatusChanged(objApp, objFld, varCurrentValue, rs, strChangedFields)
			ElseIf StrComp(strFieldName, FLD_RETIRED_DATE, vbTextCompare) = 0 Then
					Call OnAssetRetiredDateChanged(objApp, varCurrentValue, rs, strChangedFields, blnSaveField)
			ElseIf StrComp(strFieldName, FLD_SHORT_NAME, vbTextCompare) = 0 And _
								objApp.CensusApplication.CurrentProject.TemplateID = ROLES_TEMPLATE Then		
					m_blnLocationNameChanged = True
			ElseIf StrComp(strFieldName, FLD_AUTO_CREATE_ASSETS, vbTextCompare) = 0 And _
								objApp.CensusApplication.CurrentProject.TemplateID = INVOICES_TEMPLATE Then
				m_blnAutoCreateAssetsChanged = True
			End If
    
			If objFld.FieldDataType = cenMemo Then
				LogMsg "Field is of Memo type. Checking timestamp tag..."
					If InStr(1, CStr(varCurrentValue), MQ_TIME_STAMP_TAG) > 0 Then
						LogMsg "Timestamp tag found. Replacing with value:" & GetCurrentTimeStamp()
						varCurrentValue = Replace(varCurrentValue, MQ_TIME_STAMP_TAG, GetCurrentTimeStamp())
						
						LogMsg "New value will be " & varCurrentValue 
					End If
			End If
                        
            If objFld.ValueTableDSType = cenUsers Then
                If CStr(varCurrentValue) = MACRO_CURRENT_USER Then
                    varCurrentValue = objApp.CurrentUserID

				ElseIf  CStr(varCurrentValue) = MACRO_USER_COMPANY Then
					' current user's company
					varCurrentValue = GetUserCompanyID( objApp.CensusApplication , objApp.CurrentUserID)

                End If
            End If
            
            'save the current value in the recordset.
            If CStr(varCurrentValue) = "" Then
                varCurrentValue = Null
            End If
            
			LogMsg "Saving value in the recordset via SetFieldValue."
			
			If objFld.ContainerType = 16 Then
				'log field
				'check if it's not an activity type one
				If Not IsActivityLogField(objFld, objApp) Then
					varCurrentValue = varCurrentValue & varPreviousValue
				End If
			End If
			
            If blnSaveField Then
				Call objApp.SetFieldValue(rs, objFld.FieldID, varCurrentValue)
			End If
                
            blnResult = True
        End If
    End If
    
    SaveField = blnResult
End Function

Private Function IsActivityLogField(ByVal objField, ByVal objApp)

	Dim arrLogTypeFieldList
	Dim lngCount 
	Dim blnReturn
	Dim strActFldList
	blnReturn = False
	Const PROPERTY_ACTIVITY_FIELD = 7
	
	strActFldList = GetProjectProperty(PROPERTY_ACTIVITY_FIELD, objApp.DBConnections(cenDef))
	arrLogTypeFieldList = Split(strActFldList, SEMI_COLON)

	For lngCount = LBound(arrLogTypeFieldList) To UBound(arrLogTypeFieldList)
		If IfNullL(arrLogTypeFieldList(lngCount)) = objField.FieldID Then
			blnReturn = True
			Exit For
		End If
	Next
	
	IsActivityLogField = blnReturn
End Function

Private Function GetProjectProperty(ByVal lngPropertyID, ByVal dsDef)

    Dim strSQL
    Dim rsProperty
    
	strSQL = "SELECT [tValue] FROM [tblProperty] WHERE [nID]=" & lngPropertyID

    Set rsProperty = dsDef.GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)

	If Not rsProperty.EOF Then
		GetProjectProperty = IfNull(rsProperty.Fields(0).Value)
    End If
    
	rsProperty.Close
    Set rsProperty = Nothing
    
End Function


Private Function GetCurrentTimeStamp()

    Dim dtNow
    Dim strFormattedDate
    
    Const vbShortDate = 2
    Const vbLongTime = 3
                
    dtNow = Now()
    
    strFormattedDate = FormatDateTime(dtNow, vbShortDate) & " " & FormatDateTime(dtNow, vbLongTime)
    
    GetCurrentTimeStamp = strFormattedDate
    
End Function

Public Function Mq_OnAfterSave(objApp, lngRecord, dctFldVals, ByRef strChangedFields)

    Dim rs
    Dim fNewRecord
	Dim lngPrimaryJobID
	
	Const FLD_SHOW_IN_SUMMARY = "tShowInSummary"
    CONST TBL_ORG_LEVEL = "tbluser_orglevel"
    
    Set rs = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs
    
    fNewRecord = rs.Fields(FLD_REV_NUM).Value

    If fNewRecord = 1 Then
        Call SetSubmitDateTimeState(objApp, rs, strChangedFields)
        Call objApp.SetFieldValue(rs, FLD_SHOW_IN_SUMMARY, "-1")
    End If
    
    Call SetUpdateTimeState(objApp, rs, strChangedFields)
    
    CascadeUpdateParChild FLD_STATUS, Array(), _
                        GetParChildFldID(objApp.FieldCollection), _
                        objApp, lngRecord, dctFldVals

	If objApp.CensusApplication.CurrentProject.TemplateID = ACTIONS_TEMPLATE Then
		HandleActionTypeFields objApp, rs
		
		HandleConditionalActions objApp, rs, lngRecord
		
		HandleFulfillmentStatus objApp, rs, lngRecord
	End If
	
	If objApp.CensusApplication.CurrentProject.TemplateID = USERS_TEMPLATE Then
		
		lngPrimaryJobID = HandlePrimaryEmp(objApp, rs, lngRecord, strChangedFields)
		
		If objApp.DictDtsTablesForSave.Exists(TBL_ORG_LEVEL) Then
			HandleOrgLevel objApp, rs, objApp.DictDtsTablesForSave("tbluser_orglevel").rs
		Else
			LogMsg TBL_ORG_LEVEL & " doesn't exist in the dictionary of tables"
		End If
		
		If m_blnEmployeeTerminated Then
			HandleTerminateEmployee objApp, rs, lngRecord
		End If
		
		SetStartByDateForRes objApp, rs, lngRecord
		
		SetSharedEmploymentFields objApp, rs, lngRecord, lngPrimaryJobID

	End If
	
	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		
		InheritValues objApp, rs, lngRecord
		
		UpdateAssetsFromType objApp, rs, lngRecord
		
	End If

	If objApp.CensusApplication.CurrentProject.TemplateID = LICENSE_MGR_TEMPLATE Then
		Call LM_UpdateAllocation(objApp, lngRecord, dctFldVals, strChangedFields, rs)
	End If
			
	If objApp.CensusApplication.CurrentProject.TemplateID = INVOICES_TEMPLATE Then
	
		If m_blnAutoCreateAssetsChanged Then
			UpdatePendingProcessing objApp, lngRecord, dctFldVals, strChangedFields, rs
		End If
	End if
	
End Function

Public Function Mq_OnAfterCommitSave(objApp, lngRecord)
	Dim rs
    Set rs = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs
	
	'after these changes we should recalculate the totals
	If m_blnAssetStatusChanged Then
		Call CalculateAssetTotals(objApp, rs)
	End If
	
	Const ASSIGN_TYPE_EMPLOYEE = 1
	Const ASSIGN_TYPE_LOCATION = 4
	
	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		
		If m_lngPrevAssignToUser > 0 Then
			Call RevokeAsset(m_lngPrevAssignToUser, lngRecord, objApp.CensusApplication)
		End If

		If m_lngAssignToUser > 0 Then
			Call AssignAsset(m_lngAssignToUser, ASSIGN_TYPE_EMPLOYEE, lngRecord, objApp.CensusApplication)
		End If
		
		If m_lngAssignToLocation > 0 Then
			Call AssignAsset(m_lngAssignToLocation, ASSIGN_TYPE_LOCATION, lngRecord, objApp.CensusApplication)
		End If
		
		If m_lngPrevAssignToLocation > 0 Then
			Call DeprovisionAsset(m_lngPrevAssignToLocation, "tblRoleAsset", "nRoleID", lngRecord, objApp.CensusApplication)
		End If
	End If
	
	
	If objApp.CensusApplication.CurrentProject.TemplateID = INVOICES_TEMPLATE Then
	
		Dim objLMCalc
		Set objLMCalc = CreateObject("MqCensusWeb65.CMqLMCalc")
		
		objLMCalc.Calculate objApp.CensusApplication, lngRecord, 0
	
		Set objLMCalc = Nothing
	End If
	
	If objApp.CensusApplication.CurrentProject.TemplateID = ROLES_TEMPLATE Then
		If m_blnLocationNameChanged Then
			UpdateLocationNames objApp, rs, lngRecord
		End If
	End If
	
End Function

Private Function HandleActionTypeFields(objApp, rs)

	Dim lngActionType
	Dim strRecordInfo
	Dim arrTicketFields
	Dim arrMappedFieldNames
	
	Const FLD_ACTION_TYPE = "Action_Type"
	Const ACTION_TYPE_HD_TICKET = 3
	Const ACTION_TYPE_CM_TICKET = 1
	
	lngActionType = objApp.GetFieldValue(rs, FLD_ACTION_TYPE)

	If lngActionType = ACTION_TYPE_HD_TICKET Then
		
		arrTicketFields = Array("HelpDesk_Workteam", "HelpDesk_Owner", "HelpDesk_Priority", "HelpDesk_Summary", "HelpDesk_Description", "HelpDesk_Contact", "HelpDesk_Submitter")
		arrMappedFieldNames = Array("nAssignedWorkTeam", "nUserID", "nPriorityID", "tBriefDescription", "mDetailedDescription", "nOriginatorID", "nSubmitterID")
		
		strRecordInfo = GetRecordInfo(arrTicketFields, arrMappedFieldNames, objApp, rs)

		Call objApp.SetFieldValue(rs, "Ticket_Default_Values", strRecordInfo)
			
    ElseIf lngActionType = ACTION_TYPE_CM_TICKET Then
		
		arrTicketFields = Array("Change_Ticket_Title", "Change_Ticket_Description", "Change_Ticket_Severity_of_Risk", "Change_Ticket_Probability_of_Risk", "Change_Ticket_Type_of_Change")
		arrMappedFieldNames = Array("tBriefDescription", "Description$Input", "nSeverityID", "Probability_of_Risk", "Type_if_Change")
		
		strRecordInfo = GetRecordInfo(arrTicketFields, arrMappedFieldNames, objApp, rs)
		
		Call objApp.SetFieldValue(rs, "Ticket_Default_Values", strRecordInfo)
		
    End If    
	
End Function

Function GetRecordInfo(arrTicketFields, arrMappedFieldNames, objApp, rs)

	Dim strRecInfo
	Dim lngCount
	Dim strTempValue
	
	strRecInfo = ""
	
	If UBound(arrTicketFields) = UBound(arrMappedFieldNames) Then
	
		For lngCount = LBound(arrTicketFields) To UBound(arrTicketFields)
		
			strTempValue = objApp.GetFieldValue(rs, CStr(arrTicketFields(lngCount)))
		
			strRecInfo = strRecInfo & arrMappedFieldNames(lngCount) & "=" & strTempValue & ";"
			
		Next
	End If

	GetRecordInfo = strRecInfo
	
End Function

Private Function HandleOrgLevel(objApp, rsPrimary, rsOrgLevels)

	Dim strOrgLevelFieldIDs
	Dim strOrgLevelMask
	Dim strOrgLevel
	Dim arrOrgLevelFieldsIDs
	Dim lngCount 
	Dim objSettingMgr
	Dim arrOrgLevelFieldIDGroups
	Set objSettingMgr = CreateObject("MqCenX20.CMqSetting")
	Dim lngRecordID
	Dim strAllOrgLevels
	Dim rsAddEmp
	Dim strSQL
	Dim strUserTable
	
	Const DEPT_HR = 506
	
	strOrgLevelFieldIDs = objSettingMgr.GetSettingValue(objApp.DBConnections(cenLicenses).GetConnection(cenDSEnsureOpenConnection), 317)
	strOrgLevelMask = objSettingMgr.GetSettingValue(objApp.DBConnections(cenLicenses).GetConnection(cenDSEnsureOpenConnection), 318)
	
	strAllOrgLevels = ""
	
	arrOrgLevelFieldIDGroups = Split(strOrgLevelFieldIDs, ";")
	 
    lngRecordID = rsPrimary.Fields(FLD_ID).Value
    
	strUserTable = GetJobTable(objApp)
	
    strSQL = "SELECT * FROM [" & strUserTable & "] WHERE [nID]=" & lngRecordID
    
	Set rsAddEmp = objApp.DBConnections(cenUsers).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)                    
	
	For lngCount = LBound(arrOrgLevelFieldIDGroups) To UBound(arrOrgLevelFieldIDGroups)
		
		arrOrgLevelFieldsIDs = Split(CStr(arrOrgLevelFieldIDGroups(lngCount)), ",")
		
		strOrgLevel = GetOrgLevel(objApp, arrOrgLevelFieldsIDs, strOrgLevelMask, rsPrimary, Nothing)
		
		If Len(strOrgLevel) <> 0 Then
		    AddOrgLevel rsOrgLevels, lngRecordID, strOrgLevel, False, False
		    strAllOrgLevels = strAllOrgLevels & "'" & Replace(CStr(strOrgLevel), "'", "''") & "',"
		End If
		
		If Not rsAddEmp.EOF Then			
			Do While Not rsAddEmp.EOF
				
				strOrgLevel = GetOrgLevel(objApp, arrOrgLevelFieldsIDs, strOrgLevelMask, rsPrimary, rsAddEmp)

				If Len(strOrgLevel) <> 0 Then
				    AddOrgLevel rsOrgLevels, lngRecordID, strOrgLevel, False, False
				    strAllOrgLevels = strAllOrgLevels & "'" & Replace(CStr(strOrgLevel), "'", "''") & "',"
				End If
		
				rsAddEmp.MoveNext
			Loop
			rsAddEmp.MoveFirst
		End If
	Next
	
	'If the employee can see everyone, set it
	If m_blnCanSeeAllEmpsChanged Then
		If m_blnCanSeeAllEmps Then
			AddOrgLevel rsOrgLevels, lngRecordID, "", True, False
		Else
			'delete if there was an all entry before
			objApp.DBConnections(cenUsers).DeleteTableRecords "tblUser_OrgLevel", _
							" [nID]=" & lngRecordID & " AND [fPermanent]<>0 AND [Org_Level]=''"
		End If
	End If
	
	'If the employee works in HR, they can see everyone
	If EmployeeWorksInDept(objApp, lngRecordID, DEPT_HR, rsPrimary) Then
		AddOrgLevel rsOrgLevels, lngRecordID, "", True, False
	End If
	
	If strAllOrgLevels <> "" Then
		'Handle any Org Levels for people the user is a delegate for
		SetDelegateOrgLevels objApp, rsPrimary, rsOrgLevels, lngRecordID
		
		If Right(CStr(strAllOrgLevels), 1) = "," Then
			strAllOrgLevels = Left(CStr(strAllOrgLevels), Len(CStr(strAllOrgLevels)) - 1)
		End If
		
		'delete any that don't apply anymore
		objApp.DBConnections(cenUsers).DeleteTableRecords "tblUser_OrgLevel", _
							" [nID]=" & lngRecordID & " AND [fPermanent]=0 AND [Org_Level] NOT IN (" & strAllOrgLevels & ")"
    
	End If
	
	Set objSettingMgr = Nothing
	rsAddEmp.Close
	
End Function

Private Function EmployeeWorksInDept(ByVal objApp, ByVal lngEmployeeID, ByVal lngDeptID, ByVal rsPrimary)

	Dim strSQL
	Dim rsEmp
	Dim blnReturn 
	Dim strUserTable
	Dim lngUserDept
	Const FLD_NAME_DEPARTMENT = "Department"
	
	blnReturn = False
	strUserTable = GetJobTable(objApp)
	
	If strUserTable = TBL_USER_EMPLOYMENT Then
		strSQL = "SELECT [" & FLD_NAME_DEPARTMENT & "] FROM [" & strUserTable & "] WHERE [nID]=" & lngEmployeeID & " AND [" & FLD_NAME_DEPARTMENT & "]=" & lngDeptID
		Set rsEmp = objApp.DBConnections(cenUsers).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)                    

		If Not rsEmp.EOF Then
			blnReturn = True
		End If
	
		rsEmp.Close                 
	Else
		lngUserDept = objApp.GetFieldValue(rsPrimary, FLD_NAME_DEPARTMENT)
		
		If lngUserDept = lngDeptID Then
			blnReturn = True
		End If
	End If

	EmployeeWorksInDept = blnReturn	
	
End Function

Private Function GetOrgLevel(ByVal objApp, ByVal arrOrgLevelFieldsIDs, ByVal strOrgLevelMask, ByVal rsPrimary, ByVal rsAddEmp)

	Dim lngCount 
	Dim blnAllValuesAreCleared
	Dim objString
	Set objString = CreateObject("Mqsysutils40.CMqString")
	Dim strOrgLevel
	Dim arrOrgLevelValues
	
	blnAllValuesAreCleared = True

	ReDim arrOrgLevelValues(UBound(arrOrgLevelFieldsIDs))

	For lngCount = LBound(arrOrgLevelFieldsIDs) To UBound(arrOrgLevelFieldsIDs)
		If objApp.CensusApplication.CurrentProject.Fields.Exists(CLng(arrOrgLevelFieldsIDs(lngCount))) Then
			With objApp.CensusApplication.CurrentProject.Fields.Item(CLng(arrOrgLevelFieldsIDs(lngCount)))
				If .RelationShipType = 2 And .TableName = TBL_USER_EMPLOYMENT Then '1tM
					If Not rsAddEmp Is Nothing Then
						If Not rsAddEmp.EOF Then
							arrOrgLevelValues(lngCount) = IfNull(rsAddEmp.Fields(CStr(.FieldName)).Value)
						Else
							arrOrgLevelValues(lngCount) = ""
						End If
					Else
						arrOrgLevelValues(lngCount) = ""
					End If
				Else
					arrOrgLevelValues(lngCount) = objApp.GetFieldValue(rsPrimary, CStr(.FieldName))
				End If
			End With
		Else
			arrOrgLevelValues(lngCount) = ""
		End If

		If blnAllValuesAreCleared Then
			If arrOrgLevelValues(lngCount) <> "" Then
				blnAllValuesAreCleared = False
			End If
		End If
	Next	

	If blnAllValuesAreCleared = False Then	
		objString.InitializeString CStr(strOrgLevelMask)
		strOrgLevel = objString.FormatStringVar(arrOrgLevelValues)
	Else
		strOrgLevel = ""
	End If

	GetOrgLevel = strOrgLevel

	Set objString = Nothing
	
End Function

Private Function AddOrgLevel(ByVal rsOrgLevels, ByVal lngRecordID, ByVal strOrgLevel, ByVal blnPermanent, ByVal blnDelegate)
	
	If Not (rsOrgLevels.EOF And rsOrgLevels.BOF) Then
	    ' Verify the record doesn't exist before adding it
	    rsOrgLevels.Filter = "[nID]=" & lngRecordID & " AND [Org_Level]='" & Replace(CStr(strOrgLevel), "'", "''") & "'"
	End If
			                    
	If rsOrgLevels.EOF Then
		'add a new record.
	    rsOrgLevels.AddNew
	    
	    'set the field values
	    rsOrgLevels.Fields(FLD_ID).Value = lngRecordID
	    rsOrgLevels.Fields("Org_Level").Value = strOrgLevel
	    rsOrgLevels.Fields("fPermanent").Value = blnPermanent
		rsOrgLevels.Fields("fDelegate").Value = blnDelegate	                
	    rsOrgLevels.Update
	End If
End Function

Private Function SetDelegateOrgLevels(ByVal objApp, ByVal rsPrimary, ByVal rsOrgLevels, ByVal lngRecordID)

	Dim strDelegateFor
	Dim arrDelegateFor
	Dim lngCount
	Dim lngUserID
	
	Const FLD_NAME_DELEGATE_FOR = "Delegate_For"
	
	
	'delete all Org Levels for delegates
	objApp.DBConnections(cenUsers).DeleteTableRecords "tblUser_OrgLevel", _
                        " [nID]=" & lngRecordID & " AND [fDelegate]<>0"
                        
	strDelegateFor = objApp.GetFieldValue(rsPrimary, FLD_NAME_DELEGATE_FOR)

	If strDelegateFor <> "" Then
		arrDelegateFor = Split(strDelegateFor, SEMI_COLON)
	
		For lngCount = LBound(arrDelegateFor) To UBound(arrDelegateFor)
			
			lngUserID = GetIDByFullName(arrDelegateFor(lngCount), objApp)
			
			If lngUserID > 0 Then
				arrUserOrgLevels = GetOrgLevelsForUser(lngUserID, objApp)
			
				If IsArray(arrUserOrgLevels) Then
					For lngOrgLevelCount = LBound(arrUserOrgLevels) To UBound(arrUserOrgLevels)
						AddOrgLevel rsOrgLevels, lngRecordID, arrUserOrgLevels(lngOrgLevelCount), True, True
					Next
				End If
			End If
		Next
	End If
		
End Function

Private Function GetIDByFullName(strFullName, objApp)
	Dim objUserMgr
    Set objUserMgr = CreateObject("MqCenX20.CMqUserMgr")
    Dim rsUser 
    Dim lngUserID
    
    lngUserID = 0
    
    objUserMgr.InitializeEx objApp.CensusApplication.CurrentProject.GetAllDataStores
    objUserMgr.UniqueFieldName = "tName"
    
    Set rsUser = objUserMgr.GetUserInfo(CStr(strFullName))

    If Not rsUser.EOF Then
        lngUserID = IfNullL(rsUser.Fields("nID").Value)
    End If
    
    GetIDByFullName = lngUserID
    
    Set objUserMgr = Nothing
    rsUser.Close
    Set rsUser = Nothing
    
End Function

Private Function GetOrgLevelsForUser(lngUserID, objApp)

	Dim strSQL 
	Dim rsOrgLevels
	Dim strOrgLevels
	Const PIPE_DELIM = "|"
	
	strSQL = "SELECT [Org_Level] FROM [tblUser_OrgLevel] WHERE [" & FLD_ID & "]=" & lngUserID & " AND [fDelegate]=0"
	
	Set rsOrgLevels = objApp.CensusApplication.CurrentProject.GetAllDataStores(cenUsers).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
	Do While Not rsOrgLevels.EOF
		strOrgLevels = strOrgLevels & IfNull(rsOrgLevels.Fields("Org_Level").Value) & PIPE_DELIM
		rsOrgLevels.MoveNext
	Loop
	
	If Right(strOrgLevels, Len(DELIM)) = PIPE_DELIM Then
		strOrgLevels = Left(strOrgLevels, Len(strOrgLevels) - Len(PIPE_DELIM))
	End If
	
	GetOrgLevelsForUser = Split(strOrgLevels)
	
	rsOrgLevels.Close
    Set rsOrgLevels = Nothing
    
End Function

Private Function InheritValues(objApp, rs, lngRecord)
	Const INHERIT_FIELDS = "tBriefDescription,Item_Level"
	Dim arrInheritedFields
	Dim lngCount
	Dim lngAssetType
	Dim rsParent
	Dim strSQL
	
	
	lngAssetType = IfNullL(rs.Fields("Level_2").Value)

	arrInheritedFields = Split(INHERIT_FIELDS, ",")
	
	If lngAssetType > 0 Then
		'get the values from the parent
		strSQL = "SELECT * FROM [" & objApp.strPrimaryTableName & "] WHERE [" & FLD_ID & "] = " & lngAssetType
                        
        Set rsParent = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		
		If Not rsParent.EOF Then
			For lngCount = LBound(arrInheritedFields) To UBound(arrInheritedFields)
				If IfNull(rs.Fields(arrInheritedFields(lngCount)).Value) = "" Then
					Call objApp.SetFieldValue(rs, arrInheritedFields(lngCount), IfNull(rsParent.Fields(arrInheritedFields(lngCount)).Value))
				End If
			Next
		End If
		
		rsParent.Close
	End If
	
	Set rsParent = Nothing
	
End Function

Private Function UpdateAssetsFromType(objApp, rs, lngRecord)

	Dim lngUsageType
	Dim lngVisible
	Dim strSQL 
	Dim rsAssets
	Dim lngAssetRec
	Dim strVals
	Dim strWhere
	
	lngUsageType = IfNullL(rs.Fields("nUsageType").Value)
	lngVisible = IfNullL(rs.Fields("Visible").Value)
	
	If lngUsageType = 2 And lngVisible <> 0 Then
		'it's an asset type, propogate the visible to any assets
		
		strWhere = "B.Visible <> " & lngVisible 
		
		If lngVisible = 2 Then
			strWhere = strWhere & " OR B.Visible IS NULL"
		End If
		
		strSQL = "SELECT * FROM [tblDts] WHERE Level_2=" & _
					lngRecord & " AND [nUsageType]<>2 AND (" & strWhere & ")"
		
		Set rsAssets = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		
		strVals = "Visible=" & lngVisible
		
		Do While Not rsAssets.EOF
		
			lngAssetRec = IfNullL(rsAssets.Fields("nRelID").Value)
			
			objApp.CensusApplication.CurrentProject.Record.Update CStr(strVals), CLng(lngAssetRec), False, False
		
			rsAssets.MoveNext
		Loop
	
		rsAssets.Close
		Set rsAssets = Nothing
	End If
	
End Function

Private Function SetSubmitDateTimeState(objApp, rs, ByRef strChangedFields)

    Const FLD_ID_SUBMITTED_DATE = 2
    Const FLD_ID_SUBMITTED_TIME = 3
	Const FLD_SUBMITTED_DATE = "dSubmittedDate"
    Const FLD_SUBMITTED_TIME = "dSubmittedTime"
	
    Call objApp.SetFieldValue(rs, FLD_SUBMITTED_DATE, Date)
    Call objApp.SetFieldValue(rs, FLD_SUBMITTED_TIME, Time())
    
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_SUBMITTED_DATE)
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_SUBMITTED_TIME)

End Function

Private Function SetUpdateTimeState(objApp, rs, ByRef strChangedFields)

    Const FLD_ID_UPDATED_DATE = 9
    Const FLD_ID_UPDATED_TIME = 10
    
    Call objApp.SetFieldValue(rs, FLD_UPD_DATE, Date)
    Call objApp.SetFieldValue(rs, FLD_UPD_TIME, Time())
        
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_UPDATED_DATE)
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_UPDATED_TIME)
    
End Function


Private Function Mq_OnSubStateChange(objApp, objField, varSubState, rs, ByRef strChangedFields)

    Const FLD_ID_CLOSED_DATE = 5
    Const FLD_ID_CLOSED_TIME = 6
    
    Dim lngStatusID
    Dim varPreviousValue
	
    If GetDependentValue(objApp, objField, varSubState, lngStatusID) Then
				
				'Get the previous State value...
                varPreviousValue = objApp.GetFieldValue(rs, FLD_STATE_ID)
		
				'If the State actually changed...
				If StrComp(CStr(IfNull(varPreviousValue)), CStr(IfNull(lngStatusID)), vbTextCompare) <> 0 Then
					
	                ' Convert the value to long to pass it by value, not by reference, because
	                ' it could be changed to the equivalent value name (string)
					Call objApp.SetFieldValue(rs, FLD_STATE_ID, CLng(lngStatusID))
	                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_STATE)
				
	                If lngStatusID = STATE_CLOSED Then
						Call objApp.SetFieldValue(rs, FLD_CLOSED_DATE, Date)
						Call objApp.SetFieldValue(rs, FLD_CLOSED_TIME, Time())
					    Call objApp.SetFieldValue(rs, FLD_CLOSED_BY, objApp.CurrentUserID)						
					    						
	                Else          'If lngStatusID = STATE_OPEN Then
	                    Call objApp.SetFieldValue(rs, FLD_CLOSED_DATE, Null)
	                    Call objApp.SetFieldValue(rs, FLD_CLOSED_TIME, Null)
					    Call objApp.SetFieldValue(rs, FLD_CLOSED_BY, Null)	                    
					    	                    
	                End If
					
	                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_CLOSED_DATE)
	                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_CLOSED_TIME)
                End If

        End If

	OnSubStateChange objApp, objField, varSubState, rs, strChangedFields

End Function

Private Function OnDevSubStateChange(objApp, objField, varSubState, rs, ByRef strChangedFields)

    Const FLD_ID_DEV_STATE = 98
    Const FLD_ID_DEV_CLOSED_DATE = 99
    Const FLD_ID_DEV_CLOSED_TIME = 100
    
    Dim lngStatusID
    
    If GetDependentValue(objApp, objField, varSubState, lngStatusID) Then
        
                ' Convert the value to long to pass it by value, not by reference, because
                ' it could be changed to the equivalent value name (string)
                Call objApp.SetFieldValue(rs, "Dev_State", CLng(lngStatusID))
                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DEV_STATE)

                If lngStatusID = STATE_CLOSED Then
                    Call objApp.SetFieldValue(rs, "Dev_Closed_Date", Date)
                    Call objApp.SetFieldValue(rs, "Dev_Closed_Time", Time())
                Else          'If lngStatusID = STATE_OPEN Then
                    Call objApp.SetFieldValue(rs, "Dev_Closed_Date", Null)
                    Call objApp.SetFieldValue(rs, "Dev_Closed_Time", Null)
                End If
                
                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DEV_CLOSED_DATE)
                strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DEV_CLOSED_TIME)
        End If
        
End Function

Private Function GetToken(strFrom, intWhich, strSeparator)
    Dim intPos
    Dim intPos1
    Dim intCount
    intPos = 0
    
    For intCount = 0 To intWhich - 1
        intPos1 = InStr(intPos + 1, strFrom, strSeparator)
        If intPos1 = 0 Then
            intPos1 = Len(strFrom) + 1
        End If
        If intCount <> intWhich - 1 Then
            intPos = intPos1
        End If
    Next
    
    If intPos1 > intPos Then
        Dim intLength
        intLength = intPos1 - intPos - 1
        GetToken = Mid(strFrom, intPos + 1, intLength)
    Else
        GetToken = Null
    End If
End Function


Private Function OnEscalationOnChanged(objApp, varCurrentValue, rs, ByRef strChangedFields)

    Const ESCALATION_PAUSED_VALUE_ID = 3

    If CLng(varCurrentValue) = ESCALATION_PAUSED_VALUE_ID Then
        Dim fieldID
        Dim fieldName
        fieldName = "dEscalationTimestamp"
        fieldID = objApp.CensusApplication.CurrentProject.Fields.FindNextFieldIDByName(CStr(fieldName), CLng(fieldID))
        Call objApp.SetFieldValue(rs, "dEscalationTimestamp", Now())
        strChangedFields = AddFieldToChangedFieldsList(strChangedFields, fieldID)
    End If

End Function


Private Function OnOwnerChanged(objApp, rs, ByRef strChangedFields)

    Const FLD_ID_ASSIGNED_DATE = 7
    Const FLD_ID_ASSIGNED_TIME = 8
    
    Call objApp.SetFieldValue(rs, "dAssignedDate", Date)
    Call objApp.SetFieldValue(rs, "dAssignedTime", Time())
    
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_ASSIGNED_DATE)
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_ASSIGNED_TIME)

End Function

Private Function OnDRInitChanged(objApp, rs, ByRef strChangedFields)

    Const FLD_ID_DR_INIT_DATE = 812
    Const FLD_ID_DR_INIT_TIME = 813
    
    Call objApp.SetFieldValue(rs, "Date_DR_Initiated", Date)
    Call objApp.SetFieldValue(rs, "Time_DR_Initiated", Time())
    
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DR_INIT_DATE)
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DR_INIT_TIME)

End Function

Private Function OnDevOwnerChanged(objApp, rs, ByRef strChangedFields)

    Const FLD_ID_DEV_ASSIGNED_DATE = 95
    Const FLD_ID_DEV_ASSIGNED_TIME = 96
    
    Call objApp.SetFieldValue(rs, "Dev_Owner_Assigned_Date", Date)
    Call objApp.SetFieldValue(rs, "Dev_Owner_Assigned_Time", Time())

    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DEV_ASSIGNED_DATE)
    strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_DEV_ASSIGNED_TIME)
        
End Function

Private Function OnEmployeeStateChanged(objApp, varCurrentValue, rs, ByRef strChangedFields)

    If CLng(varCurrentValue) = EMP_STATE_INACTIVE Then
        m_blnEmployeeTerminated = True
    End If

End Function

Private Function OnCanSeeEmpsChanged(objApp, varCurrentValue, rs, ByRef strChangedFields)

	m_blnCanSeeAllEmpsChanged = True
	
    If CLng(varCurrentValue) = VALUE_YES Then
        m_blnCanSeeAllEmps = True
    End If

End Function

Private Function IsSpecialCaseLinkFile(strPath)
	
	Dim blnReturn
	Const VIEW_FILE_PREFIX = "viewfile.asp?FN="
	
	blnReturn = False
	
	'in the cases where we have the file linked from another one, 
	'like the display pic icons, it looks like: viewfile.asp?FN=documentimg.png&FP=%5CDisplayPic%5C315%5C&CT=&Proj=15
	'so keep it as a linked file and not an upload, even though it's not the usual format for a linked file 
	
	If Left(strPath, Len(VIEW_FILE_PREFIX)) = VIEW_FILE_PREFIX Then
		blnReturn = True
	End If
	
	IsSpecialCaseLinkFile = blnReturn
	
End Function

Private Sub LogMsg(strMsg)
    Dim moEventLogger

	If DEBUG_ON Then
        'This "IF" is in case we make the variable private to the module and we do not create it and destroy it every call
        'If moEventLogger is Nothing then
            Set moEventLogger = CreateObject("MqSysutils40.CMqEventLogger")
        
            moEventLogger.InitializeEventLogger
        'End If

        If Not IsNull(strMsg) Then
                moEventLogger.LogEvent CStr(strMsg)
        End If
	End If
End Sub

Private Function GetDependentValue(ByVal objApp, ByVal objField, ByVal varValue, ByRef lngDependentValueID)

    Dim blnReturn
        
        blnReturn = False
        
    If (Not objApp Is Nothing) And (Not objField Is Nothing) Then
                
                If (objApp.DBConnections.Exists(objField.ValueTableDSType)) Then
                
                        Set objField.DefinitionsDataStore = objApp.DBConnections.Item(objField.ValueTableDSType)
                        
                        If IsNumeric(varValue) Then
                        
                                If objField.ChoiceValues.Exists(CLng(varValue)) Then
                                
                                        lngDependentValueID = objField.ChoiceValues.Item(CLng(varValue)).DependentFieldID
                                                
                                        blnReturn = True
                                                
                                End If
                                        
                        End If
                        
                End If
                
        End If
        
        GetDependentValue = blnReturn
        
End Function

Private Function AddFieldToChangedFieldsList(strFieldsList, strFieldID)
    
    Const COMMA_DELIM = ","
    
    AddFieldToChangedFieldsList = strFieldsList & strFieldID & COMMA_DELIM

End Function

Private Function Validate_103_ParChildRules(lngParentFldId, _
        arrValsToValidate, _
        lngRelRecFldId, _
        lngChildFldId, _
        lngValidChildVal, _
        objApp, _
        lngRecord, _
        dctFldVals)

        Const MSG_LST_DELIM = ", "
        
        Dim strRelRecs
        Dim strSQL
        Dim rs
        Dim strRet
        Dim lngNewVal
        Dim objRelRecFld
        Dim objField
        Dim strMatch
        Dim objArrMgr
        Dim strParFldCaption
        Dim strChldValue
        Dim strChldFldCaption
        Dim strParValue
        Dim objChildField
        Dim objString
                                
        strRet = ""
        strRelRecs = ""

        ' Verify if field is changed
        If dctFldVals.Exists(lngParentFldId) Then
        
            ' If changed, check if it changed to one of the values
            ' that are to trigger the rules.
            lngNewVal = dctFldVals.Item(lngParentFldId)
            
            Set objArrMgr = CreateObject("MqSysUtils40.CMqArrayMgr")
            
            If objArrMgr.IsValueInArray(CStr(lngNewVal), arrValsToValidate) Then
                Set objRelRecFld = objApp.FieldCollection.Item(CLng(lngRelRecFldId))
                            
                strRelRecs = GetRelatedRecs(lngRelRecFldId, objRelRecFld, dctFldVals, objApp)
            
                If Len(strRelRecs) <> 0 Then
                    Set objField = objApp.FieldCollection.Item(CLng(lngParentFldId))
                    Set objChildField = objApp.FieldCollection.Item(CLng(lngChildFldId))
                        
                        strSQL = "SELECT [" & FLD_ID & "] FROM [" & objApp.strPrimaryTableName & "] AS D" & _
                            " WHERE (D.[" & objChildField.fieldName & "]<>" & lngValidChildVal & _
                            " OR D.[" & objChildField.fieldName & "] Is Null) AND D.[" & FLD_ID & "] IN (" & strRelRecs & ")"
                        
                        Set rs = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
                        If Not rs.EOF Then
                            Set objField.DefinitionsDataStore = objApp.DBConnections.Item(objField.ValueTableDSType)
                            strMatch = rs.GetString(, , , MSG_LST_DELIM)
                            
                                ' Load the choice values in the field object
                                Set objChildField.DefinitionsDataStore = objApp.DBConnections.Item(objChildField.ValueTableDSType)
                                
                                strParFldCaption = objField.LabelCaption
                                strChldValue = objChildField.ChoiceValues.GetNameFromID(CLng(lngValidChildVal))
                                strChldFldCaption = objChildField.LabelCaption
                                strParValue = objField.ChoiceValues.GetNameFromID(CLng(lngNewVal))
                                
                                Set objString = CreateObject("Mqsysutils40.CMqString")
					
								objString.InitializeString CStr("You cannot change the %1 to %2 until all the %3 have the %4 %5.%6Issue Numbers that do not have %7  %8 : %9 .")
								strRet = objString.FormatString(strParFldCaption, cStr(strParValue), objRelRecFld.LabelCaption, _
																strChldFldCaption, cStr(strChldValue), Chr(13) & Chr(10) & Chr(13) & Chr(10), _
																strChldFldCaption, cStr(strChldValue), Left(strMatch, Len(strMatch) - Len(MSG_LST_DELIM)))															
								
                                'You cannot change the %1 to %2 until all the %3 have the %4 %5.%6
								'Issue Numbers that do not have %7  %8 : %9 .
                        End If
                    
                        rs.Close
                End If
            End If
        End If

        Validate_103_ParChildRules = strRet
        
        Set rs = Nothing
        Set objRelRecFld = Nothing
        Set objField = Nothing
        Set objArrMgr = Nothing
        Set objString = Nothing
End Function

Private Function SaveRelRec(objApp, cfield, varCurrentValue, ByRef strChangedFields, rs)

    Dim lngRecordID
    Dim intQ
    Dim arrVals
    Dim strAddWhere
    Dim varContent

    lngRecordID = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs.Fields(FLD_ID).Value

    'LogMsg "Saving Field:" + cfield.FieldName + "," + varCurrentValue
    If Len(varCurrentValue) <> 0 Then
        strAddWhere = " AND [" & cfield.fieldName & "] NOT IN (" & _
                                    Replace(varCurrentValue, SEMI_COLON, ",") & ")"
    Else
        strAddWhere = ""
    End If

    'first we have to delete all the records from the table that are not in the value anymore.
    objApp.DBConnections(cenDat).DeleteTableRecords cfield.TableName, _
                        " nID = " & lngRecordID & strAddWhere

    'we do a requery
    rs.Requery
    'we create an array from the current value because the value is a ";" seperated string.
    arrVals = Split(CStr(varCurrentValue), SEMI_COLON)

    If IsArray(arrVals) Then

        For intQ = 0 To UBound(arrVals)
            varContent = Trim(arrVals(intQ))
            If Len(varContent) <> 0 Then
                    
                If Not (rs.EOF And rs.BOF) Then
                        ' Verify the record doesn't exist before adding it
                        rs.Find "[" & cfield.fieldName & "]=" & varContent, , , adBookmarkFirst
                End If
                        
                If rs.EOF Then
                    'add a new record.
                    rs.AddNew
                    'set the field values
                    rs.Fields(FLD_ID).Value = lngRecordID
                    'LogMsg "SetFieldValue:" + cfield.FieldName + "," + varContent
                    Call objApp.SetFieldValue(rs, cfield.fieldName, varContent)
                    
                    rs.Update
                End If
                            
            End If
        Next
                
     End If
  
End Function


Private Function SaveParentRec(objApp, cfield, varCurrentValue, ByRef strChangedFields, rs)

    Dim lngRecordID
    Dim strAliasSrcTable
    Dim strTgtField
	Dim arrAliasFields
	
	lngRecordID = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs.Fields(FLD_ID).Value

    'LogMsg "Saving Field:" + cfield.FieldName + "," + varCurrentValue
    If Len(varCurrentValue) <> 0 Then        
		strAliasSrcTable = cfield.AliasSourceTable
		
		If strAliasSrcTable <> "" Then
			arrAliasFields = Split(strAliasSrcTable, ";")
			
			If UBound(arrAliasFields) >= 1 Then
				strTgtField = arrAliasFields(1)
				
				If Len(strTgtField) <> 0 Then
					If Not (rs.EOF And rs.BOF) Then
							' Verify the record doesn't exist before adding it
							rs.Find "[" & FLD_ID & "]=" & varCurrentValue, , , adBookmarkFirst
					End If
							
					If rs.EOF Then
						'add a new record.
						rs.AddNew
						'set the field values
						rs.Fields(strTgtField).Value = lngRecordID
						'LogMsg "SetFieldValue:" + FLD_ID + "," + varCurrentValue
						Call objApp.SetFieldValue(rs, FLD_ID, varCurrentValue)
						
						rs.Update
					End If
				End If
			End If
		End If
					
	End If

	End Function


Private Function CascadeUpdateParChild(ByVal lngFldId, _
        ByVal arrValsToValidate, _
        ByVal lngRelRecFldId, _
        ByVal objApp, _
        ByVal lngRecord, _
        ByVal dctFldVals)

        Const MSG_LST_DELIM = ", "       
		
        Dim strRelRecs
        Dim strSQL
        Dim rs
        Dim lngNewVal
        Dim objRelRecFld
        Dim objField
        Dim strMatch
        Dim objArrMgr
        Dim strFldName
        Dim varPrevValue
        Dim lngNewRevision
        Dim objRecsMgr
        Dim rsRevision
        Dim lngRecordID
        Dim blnDoCascadeUpdate
        Dim objDepFld
        Dim strComment
        Dim lngDepFldID

        strRelRecs = ""

        ' Verify if field is changed
        If dctFldVals.Exists(lngFldId) Then

            lngNewVal = dctFldVals.Item(lngFldId)
            Set objField = objApp.FieldCollection.Item(CLng(lngFldId))
            
            ' Do a cascade update if the field has changed
            blnDoCascadeUpdate = True
            
            ' Remove comment if only some values are to trigger the cascade.
            'Set objArrMgr=CreateObject("MqSysUtils40.CMqArrayMgr")
            'blnDoCascadeUpdate=objArrMgr.IsValueInArray(CStr(lngNewVal),arrValsToValidate)
            
        Else
                ' Do a cascade update also if new child issues were added, to ensure these ones
                ' are in sync.
                blnDoCascadeUpdate = dctFldVals.Exists(lngRelRecFldId)
                
                If blnDoCascadeUpdate Then
                        
                    ' Get the value of the cascaded field from the db
                    Set objField = objApp.FieldCollection.Item(CLng(lngFldId))
                    Set rs = objApp.DictDtsTablesForSave(LCase(objField.TableName)).rs
    
                    If Not rs Is Nothing Then
                        If Not (rs.BOF And rs.EOF) Then
                                lngNewVal = rs.Fields(objField.fieldName).Value
                        End If
                        Set rs = Nothing
                    End If
                End If
                                
        End If

        If blnDoCascadeUpdate Then
                
            Set objRelRecFld = objApp.FieldCollection.Item(CLng(lngRelRecFldId))

            strRelRecs = GetRelatedRecs(lngRelRecFldId, objRelRecFld, dctFldVals, objApp)

            If Len(strRelRecs) <> 0 Then

                    ' Determine if we need to update related fields per record
                    lngDepFldID = objField.RelatedField
                    
                    If objApp.FieldCollection.Exists(CLng(lngDepFldID)) Then
                            
                            Set objDepFld = objApp.FieldCollection.Item(CLng(lngDepFldID))
                            ' If we have a related/dependent field, we need to include it in the recordset
                            strSQL = ",[" & objDepFld.fieldName & "]"
                    End If
                        
                    strFldName = objField.fieldName

                    strSQL = "SELECT [" & FLD_ID & "],[" & FLD_REV_NUM & "],[" & strFldName & _
                            "],[" & FLD_UPD_DATE & "],[" & FLD_UPD_TIME & "] " & strSQL & _
                                " FROM [" & objApp.strPrimaryTableName & "] AS D" & _
                            " WHERE (D.[" & strFldName & "]<>" & lngNewVal & " OR D.[" & strFldName & "] IS NULL)" & _
                            " AND D.[" & FLD_ID & "] IN (" & strRelRecs & ") AND D.[" & FLD_ID & "]<>" & lngRecord & " AND ([" & _
                            FLD_NAME_CTRLD_BY_PARENT & "]<>" & STR_VAL_NO & " OR [" & _
                                                                FLD_NAME_CTRLD_BY_PARENT & "] IS NULL) "
                        
                    Set rs = CreateObject("ADODB.Recordset")

                    With rs
                        .Source = strSQL
                        Set .ActiveConnection = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection)
                        .LockType = adLockOptimistic
                        .CursorType = adOpenStatic
                        .Open

                        Set objRecsMgr = CreateRecordsMgr(objApp)
                        Set rsRevision = GetRevisionHistoryRecordset(objApp)

                        Do Until .EOF
                            '********************************************************
                            ' - Update the value of the field
                            ' - Increase Revision Number
                                ' - Update dependent fields
                            ' - Save history (flds changed and record)
                                '********************************************************
							
							' - Update the value of the field
							' - Increase Revision Number
							varPrevValue = IfNullL(.Fields(strFldName).Value)
							.Fields(strFldName).Value = lngNewVal
                            
							lngNewRevision = IfNullL(.Fields(FLD_REV_NUM).Value)
							lngNewRevision = lngNewRevision + 1
							.Fields(FLD_REV_NUM).Value = lngNewRevision
                            
							' Set update date/time fields
							.Fields(FLD_UPD_DATE).Value = Date
							.Fields(FLD_UPD_TIME).Value = Time()

							' - Update dependent fields
							lngRecordID = IfNullL(.Fields(FLD_ID).Value)
								            
							strComment = "Automatic Update from Parent Issue " & lngRecord

							Call ChangeDependentFld(lngRecordID, lngNewRevision, _
							                                lngNewVal, objField, objDepFld, _
							                                rs, rsRevision, _
							                                objApp, strComment)

							.Update
                            
							' - Save history (flds changed and record)
							UpdateRevisionHistoryTable lngRecordID, lngNewRevision, _
							                            lngNewVal, varPrevValue, _
							                            objField, rsRevision, objApp, _
							                            strComment

							objRecsMgr.CreateHistoryRecord CLng(lngRecordID)
                            
                            .MoveNext
                        Loop
  
                    End With

                    rsRevision.Close
                    rs.Close
            End If
        End If

        CascadeUpdateParChild = True
        
        Set objRecsMgr = Nothing
        Set rsRevision = Nothing
        Set rs = Nothing
        Set objRelRecFld = Nothing
        Set objField = Nothing
        Set objArrMgr = Nothing
        Set objDepFld = Nothing
End Function

Private Function GetRelatedRecs(ByVal lngRelRecFldId, _
        ByVal objRelRecFld, _
        ByVal dctFldVals, _
        ByVal objApp)
        
    Const LIST_DELIM = ","
    Dim strRelRecs
    Dim rs
        
    strRelRecs = ""
    ' Check if the related records field has been updated so we take them
    ' from the query string and not from the db
    If dctFldVals.Exists(lngRelRecFldId) Then
        strRelRecs = dctFldVals.Item(lngRelRecFldId)
        strRelRecs = Replace(strRelRecs, SEMI_COLON, LIST_DELIM)
    Else
        ' Get it from the DB otherwise
        If Not objRelRecFld Is Nothing Then
			If objApp.DictDtsTablesForSave.Exists(LCase(objRelRecFld.TableName)) Then
				Set rs = objApp.DictDtsTablesForSave(LCase(objRelRecFld.TableName)).rs
				
				If Not rs Is Nothing Then
					If (rs.BOF And rs.EOF) Then
							strRelRecs = ""
					Else
						rs.MoveFirst
						Do Until rs.EOF
							If Len(strRelRecs) <> 0 Then
								strRelRecs = strRelRecs & LIST_DELIM
							End If
							strRelRecs = strRelRecs & rs.Fields(objRelRecFld.fieldName).Value
							rs.MoveNext
						Loop
						' Leave it in the first record for the saving
						rs.MoveFirst
						
					End If
						
					Set rs = Nothing
				End If
            End If
		End If
	End If
    GetRelatedRecs = strRelRecs
End Function

Private Function CreateRecordsMgr(ByVal objApp)
    On Error Resume Next
    Dim objCurPrj
    Dim oRecordsMgr

    ' Create a history record to be able to send notifications properly.
    Set oRecordsMgr = CreateObject("MqCenX20.CMqRecordsMgr")
        
    'initialize the record mgr object just once in a session.
    With objApp
        Set objCurPrj = .CensusApplication.CurrentProject
        oRecordsMgr.Initialize .DBConnections, .FieldCollection, _
                             objCurPrj.ProjectName, _
                             objCurPrj.DataFilesLocation
    End With
    
    Set CreateRecordsMgr = oRecordsMgr
    Set objCurPrj = Nothing
    Set oRecordsMgr = Nothing
    
End Function

Private Function GetRevisionHistoryRecordset(ByVal objApp)
    
    Dim rsRevision

    Set rsRevision = CreateObject("ADODB.Recordset")
    
    With rsRevision
        ' Open the recordset for no valid record ID, so that it's fast, because we don't need
        ' to update any record values.
        .Source = "SELECT * FROM [tblRevisionHistory] WHERE nRecordID =-1 "
        Set .ActiveConnection = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection)
        .LockType = adLockOptimistic
        .CursorType = adOpenStatic
        .Open
    End With
    
    Set GetRevisionHistoryRecordset = rsRevision
    Set rsRevision = Nothing
    
End Function


Public Sub UpdateRevisionHistoryTable(ByVal lngRecordID, _
                                ByVal lngNewRevisionNumber, _
                                ByVal varCurrentValue, _
                                ByVal varPreviousValue, _
                                ByVal objField, _
                                ByVal rstRevision, _
                                ByVal objApp, _
                                ByVal strComment)
    On Error Resume Next
    Const FIELD_NAME = "tName"
    Const FLD_REV_NUMBER = "nRevisionNumber"
    Const FLD_MODIFED_FLD_ID = "nModifiedDtsFieldID"
    Const FLD_PREV_VAL = "tPreviousValue"
    Const FLD_CURR_VAL = "tCurrentValue"
    Const FLD_REC_ID = "nRecordID"
    Const FLD_DATE = "dDate"
    Const FLD_TIME = "dTime"
    Const FLD_COMMENT = "tComment"
    Const cenSingleChoice = 103
        
    Dim lngDataType

    ' Check if there a need to change the revision
    ' history table for this field
    If varCurrentValue <> varPreviousValue Then

            lngDataType = objField.FieldDataType

        If lngDataType = cenSingleChoice Then
            
                ' Convert the value from the ID to the value name
            Set objField.DefinitionsDataStore = objApp.DBConnections.Item(objField.ValueTableDSType)
            
            If Not IsNull(varPreviousValue) Then
                varPreviousValue = objField.ChoiceValues.GetNameFromID(CLng(varPreviousValue))
            End If
            
            If Not IsNull(varCurrentValue) Then
                varCurrentValue = objField.ChoiceValues.GetNameFromID(CLng(varCurrentValue))
            End If
        End If

        With rstRevision
            .AddNew

            .Fields(FLD_REC_ID).Value = lngRecordID
            

            .Fields(FLD_DATE).Value = Date
            

            .Fields(FLD_TIME).Value = Time()
            

            ' Save the current logged in username
            .Fields(FIELD_NAME).Value = objApp.strCurrentUser
            

            .Fields(FLD_MODIFED_FLD_ID).Value = objField.fieldID
            

            .Fields(FLD_PREV_VAL).Value = varPreviousValue
            

            .Fields(FLD_CURR_VAL).Value = varCurrentValue
            

            .Fields(FLD_REV_NUMBER).Value = lngNewRevisionNumber

            .Fields(FLD_COMMENT).Value = strComment
                        
            .Update
        End With
    End If
        
End Sub

Private Function IfNull(varField)
On Error Resume Next
    If IsNull(varField) Or IsEmpty(varField) Then
        IfNull = ""
    Else
        IfNull = CStr(varField)
    End If

End Function

Private Function IfNullL(varField)
On Error Resume Next
    If IsNull(varField) Or IsEmpty(varField) Then
        IfNullL = 0
    Else
        IfNullL = CLng(varField)
    End If

End Function

Private Function IfNullDbl(varField)
On Error Resume Next
    If IsNull(varField) Or IsEmpty(varField) Then
        IfNullDbl = 0
    Else
        IfNullDbl = CDbl(varField)
    End If

End Function

Private Function GetParentRec(ByVal lngChildRecId, _
    ByVal lngRelRecFldId, _
    ByVal objApp)
    
    Dim objRelRecFld
    Dim strSQL
    Dim strRet
    Dim rs
    
    strRet = ""
    Set objRelRecFld = objApp.FieldCollection.Item(CLng(lngRelRecFldId))
    
    If Not objRelRecFld Is Nothing Then
    
        ' Get it from the DB
        strSQL = "SELECT [" & FLD_ID & "] FROM [" & objRelRecFld.TableName & "] WHERE [" & _
                        objRelRecFld.fieldName & "]=" & lngChildRecId
        Set rs = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
            
        If Not rs Is Nothing Then
            If Not (rs.BOF And rs.EOF) Then
                If Not IsNull(rs.Fields(FLD_ID).Value) Then
                    strRet = rs.Fields(FLD_ID).Value
                End If
            End If
            
            rs.Close
            Set rs = Nothing
        End If
        
    End If
    
    GetParentRec = strRet
End Function

Private Function ChangeDependentFld(lngRecordID, lngNewRevision, _
    varNewValue, objField, objDepFld, rs, rsRevision, objApp, _
    strComment)
    
    Dim varDependentValue
    Dim blnKeepHist
        
    If Not objDepFld Is Nothing Then
        If GetDependentValue(objApp, objField, varNewValue, varDependentValue) Then
                    
            ' Change temporarily the KeepHistory property in order to skip the
            ' adding of revision history when calling SetFieldValue.
            ' We need to skip it because it is only adding the history for the
            ' current record (global variable) and not necessarily to the one specified
            ' in the argument.
            blnKeepHist = objDepFld.KeepHistory
            objDepFld.KeepHistory = False
                    
            Call objApp.SetFieldValue(rs, objDepFld.fieldName, varDependentValue)
                    
            ' Put back the original value not to affect the rest
            objDepFld.KeepHistory = blnKeepHist
                    
            ' - Save history (flds changed and record)
            UpdateRevisionHistoryTable lngRecordID, lngNewRevision, _
                    varDependentValue, 0, _
                    objDepFld, rsRevision, objApp, _
                    strComment

            ' Special case for state
            If objField.fieldID = FLD_ID_STATE Then
            
                If varDependentValue = STATE_CLOSED Then
                    Call objApp.SetFieldValue(rs, FLD_CLOSED_DATE, Date)
                    Call objApp.SetFieldValue(rs, FLD_CLOSED_TIME, Time())
				    Call objApp.SetFieldValue(rs, FLD_CLOSED_BY, objApp.CurrentUserID)	                                        
                
                Else          'If lngStatusID = STATE_OPEN Then
                    Call objApp.SetFieldValue(rs, FLD_CLOSED_DATE, Null)
                    Call objApp.SetFieldValue(rs, FLD_CLOSED_TIME, Null)
					Call objApp.SetFieldValue(rs, FLD_CLOSED_BY, Null)	                    
					                        
                End If
                    
            End If
        End If
    End If
        
End Function

Private Function ValidateParChild(objApp, lngRecord, dctFldVals)
    Const FLD_QA_ITEMS = "196"  'QAItems
    Const DEV_STATUS_CLOSED = 16
    Const FLD_QA_STATUS = "198" 'QA Status
    Const QA_STATUS_CLOSED = 3
                
    Dim strRet

    strRet = ValidateParChild_DependOnParent(objApp, lngRecord, dctFldVals)

    If Len(strRet) = 0 Then
        If CHECK_QA_ITEMS Then
            strRet = Validate_103_ParChildRules(FLD_STATUS, Array(DEV_STATUS_CLOSED), _
                        FLD_QA_ITEMS, FLD_QA_STATUS, QA_STATUS_CLOSED, objApp, _
                        lngRecord, dctFldVals)
        End If
    End If
                
        ValidateParChild = strRet
End Function

Private Function ValidateParChild_DependOnParent(objApp, lngRecord, dctFldVals)
                
    Dim strParRec
    Dim strRet
    Dim objFld
    Dim strFldControlledByPar
    Dim lngFldRelRec
    Dim fControlledByParent
	Dim objString
	
    strRet = ""
	Set objString = CreateObject("Mqsysutils40.CMqString")

    ' By default, the status of child issues is controlled by the parent
    fControlledByParent = True

        ' Status can be dependent or independent of the parent child.
        ' If the record has nControlledByParent=True, then Dev Status is dependent
        ' and shall not be changed on the child issue.
    If objApp.FieldCollection.Exists(FLD_STATUS) Then
    
        Set objFld = objApp.FieldCollection.Item(FLD_STATUS)
      
        If IsFieldChanged(objFld, objApp, dctFldVals) Then

            strFldControlledByPar = GetControlledByParentFldID(objApp.FieldCollection)
            If strFldControlledByPar > 0 Then
				If dctFldVals.Exists(strFldControlledByPar) Then
					If dctFldVals.Item(strFldControlledByPar) = STR_VAL_NO Then
						fControlledByParent = False
					End If
                End If
            Else
				fControlledByParent = False
            End If

            If fControlledByParent Then
                    ' This is an issue that should be controlled by the parent (if a child),
                ' so we shouldn't change the
                    ' status here but in the parent issue
                lngFldRelRec = GetParChildFldID(objApp.FieldCollection)

                If objApp.FieldCollection.Exists(CLng(lngFldRelRec)) Then
                            strParRec = GetParentRec(lngRecord, lngFldRelRec, objApp)
                End If

                If Len(strParRec) > 0 Then
	                
					objString.InitializeString CStr("Cannot update the %1. The %2 is controlled by the parent issue # %3.")
					strRet = objString.FormatString(objFld.LabelCaption, objFld.LabelCaption, strParRec) 
					' Cannot update the %1. The %2 is controlled by the parent issue # %3.
                End If

            End If

        End If
      
    End If
    
    Set objString = Nothing
    
    ValidateParChild_DependOnParent = strRet
End Function

Private Function IsFieldChanged(ByVal objFld, ByVal objApp, ByVal dctFldVals)
        Dim strTableName
        Dim rs
        Dim strFldId
        
        IsFieldChanged = False
        
        strFldId = CStr(objFld.fieldID)
        
        If dctFldVals.Exists(strFldId) Then
        strTableName = LCase(objFld.TableName)

    If objApp.DictDtsTablesForSave.Exists(strTableName) Then
        Set rs = objApp.DictDtsTablesForSave(strTableName).rs
                        
        If Not rs Is Nothing Then
        	If Not rs.EOF Then
				IsFieldChanged = IfNull(rs.Fields(objFld.fieldName).Value) <> dctFldVals.Item(strFldId)
			End if
        End If
                        
        End If
        End If
        
        'LogMsg "IsFieldChanged:" & IsFieldChanged
End Function

Private Function GetParChildFldID(oFldCol)

    If IfNullL(m_lngFldRelRec) = 0 Then
        m_lngFldRelRec = oFldCol.FindNextFieldIDByName(FLD_NAME_REL_RECS, 0)
    End If
    GetParChildFldID = m_lngFldRelRec

End Function

Private Function GetControlledByParentFldID(oFldCol)

    If Len(IfNull(m_strFldControlledByPar)) = 0 Then
        m_strFldControlledByPar = CStr(oFldCol.FindNextFieldIDByName(FLD_NAME_CTRLD_BY_PARENT, 0))
    End If
    GetControlledByParentFldID = m_strFldControlledByPar

End Function


Private Function HandleTerminateEmployee(objApp, rs, lngEmployeeID)
	
	HandleTerminateJobs objApp, rs, lngEmployeeID
	HandleTerminationActions objApp, rs, lngEmployeeID
	
End Function

Private Function HandleTerminateJobs(objApp, rs, lngEmployeeID)

	If IsDate(m_dtEndDate) Then
		Dim strJobTable
		strJobTable = GetJobTable(objApp)
		
		strSQL = "SELECT * FROM [" & strJobTable & "] WHERE [nID]=" & lngEmployeeID & _
					" AND ([Employment_Status] IS NULL OR [Employment_Status] <>" & EMP_STATUS_TERMINATED_VALUE_ID & ")"

		Set rsAddEmp = CreateObject("ADODB.Recordset")
		With rsAddEmp
			.Source = strSQL
			Set .ActiveConnection = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection)
			.LockType = adLockOptimistic
			.CursorType = adOpenStatic
			.Open
			If Not .EOF Then		
				Do While Not .EOF
					
					If IsNull(.Fields("End_Date").Value) Then
						.Fields("End_Date").Value = m_dtEndDate
						.Fields("End_Time").Value = m_dtEndTime
					End If

					.Fields("Employment_Status").Value = EMP_STATUS_TERMINATED_VALUE_ID
					
					.Update
					
					.MoveNext
				Loop
				.MoveFirst
			End If
		End With
	End If
	
End Function

Private Function HandleTerminationActions(objApp, rs, lngEmployeeID)
	'Turn the actions off in some cases
	
	Dim arrActionTemplates
	Dim arrTerminationFields
	Dim lngCount
	Dim lngValue
	Dim lngActionCount
	Dim arrActions
	
	arrTerminationFields = Array("Email_Termination", "Access_Control__file_network_applications_")
	
	arrActionTemplates = Array(Array(25,27,26), Array(6,65))
	
	For lngCount = LBound(arrTerminationFields) To UBound(arrTerminationFields)
	
		lngValue = objApp.GetFieldValue(rs, CStr(arrTerminationFields(lngCount)))
	
		arrActions = arrActionTemplates(lngCount)
		
		If IsArray(arrActions) Then
			
			For lngActionCount = LBound(arrActions) To UBound(arrActions)
			
				If lngActionCount + 1 = lngValue Then
					'it's the one to keep
				Else
					'turn off this action
					TurnOffActionForEmployee objApp, lngEmployeeID, IfNullL(arrActions(lngActionCount))
				End If
			Next
		End If
	Next
End Function

Private Function TurnOffActionForEmployee(objApp, lngEmployeeID, lngActionTemplateID)
	
	Dim strSQL
	Dim rsActions
	
	'set the state to 2 so that it's disabled
	
	strSQL = "UPDATE [tblDts] SET [Action_State]=2 WHERE [Based_On]=" & lngActionTemplateID & _
				" AND [Employee_ID]=" & lngEmployeeID
	
	objApp.CensusApplication.CurrentProject.GetAllDataStores(8192).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)

End Function

Private Function HandleConditionalActions(objApp, rs, lngRecordID)
	
	'Turn the actions off in some cases
	
	Dim lngExecWhen
	Dim strSQL
	
	Const FLD_EXEC_WHEN = "Execute_When"
	Const EXEC_ALWAYS = 1
	Const EXEC_CONDITIONAL = 2
	
	lngExecWhen = objApp.GetFieldValue(rs, FLD_EXEC_WHEN)
	
	If lngExecWhen = EXEC_CONDITIONAL Then
		'turn off this action. The condition will turn it back on if it's met.
		strSQL = "UPDATE [tblDts] SET [Action_State]=2 WHERE [nID]=" & lngRecordID
		objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	End If
		
End Function

Private Function SetStartByDateForRes(objApp, rs, lngEmployeeID)

	Dim dtStartDate
	Dim rsEmpRes
	Dim strSQL
	Dim rsRes
	Dim rsAct
	Dim strAct
	Const COMMA_DELIM = ","
	
	Const FLD_START_DATE = "Start_Date"
	Const FLD_COMPLETE_PROVISIONING_BY = "Complete_Provisioning_By"
	
	dtStartDate = objApp.GetFieldValue(rs, CStr(FLD_START_DATE))
	
	If dtStartDate <> "" Then
		strSQL = "SELECT [nResID] FROM [tblEmpRes] LEFT JOIN [tblDts] ON [tblEmpRes].[nResID]=[tblDts].[nID] WHERE [nEmpID]=" & lngEmployeeID & _
					" AND [tblDts].[" & FLD_COMPLETE_PROVISIONING_BY & "] IS NULL"
	
		Set rsRes = objApp.CensusApplication.CurrentProject.GetAllDataStores(2048).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
		UpdateCompleteProvisioningBy rsRes, FLD_COMPLETE_PROVISIONING_BY, dtStartDate, RESOURCES_TEMPLATE, objApp.CensusApplication

		rsRes.Close
		Set rsRes = Nothing

		strSQL = "SELECT [nActID] FROM [tblActRes] LEFT JOIN [tblEmpRes] ON [tblEmpRes].[nResID]=[tblActRes].[nRESID] WHERE [nEmpID]=" & lngEmployeeID
	
		Set rsAct = objApp.CensusApplication.CurrentProject.GetAllDataStores(2048).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
		If Not rsAct.EOF Then
			strAct = rsAct.GetString(, , , COMMA_DELIM)
				        
			If Right(strAct, 1) = COMMA_DELIM Then
				strAct = Left(strAct, Len(strAct) - Len(COMMA_DELIM))
			End If
			
			rsAct.Close
			Set rsAct = Nothing
		
			If strAct <> "" Then
				strSQL = "SELECT [nID] FROM [tblDts] WHERE [nID] IN (" & strAct & ") AND [" & FLD_COMPLETE_PROVISIONING_BY & "] IS NULL"
				
				Set rsAct = objApp.CensusApplication.CurrentProject.GetAllDataStores(8192).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
				UpdateCompleteProvisioningBy rsAct, FLD_COMPLETE_PROVISIONING_BY, dtStartDate, ACTIONS_TEMPLATE, objApp.CensusApplication
			End If
			
		End If
		
		rsAct.Close
		Set rsAct = Nothing
	End If
		
End Function

Private Function UpdateCompleteProvisioningBy(rsIDs, strField, dtDate, lngProjectID, objCenApp)

	Dim blnProjOpened
	blnProjOpened = False
	Dim objRecMgr
	Dim lngCurrProj 
	
	lngCurrProj = objCenApp.CurrentProject.ProjectID
	
	If objCenApp.Projects(CLng(lngProjectID)).State = 0 Then
		objCenApp.Projects.Item(CLng(lngProjectID)).OpenProject
		blnProjOpened = True
	End If
	
	Set objRecMgr = objCenApp.Projects.Item(CLng(lngProjectID)).Record
	
	If Not objRecMgr Is Nothing Then
		Do While Not rsIDs.EOF
		
			objRecMgr.Update strField & "=" & dtDate, CLng(rsIDs.Fields(0).Value), False, False
			
			rsIDs.MoveNext
		Loop
	End If
	
	If blnProjOpened Then
		objCenApp.Projects.Item(CLng(lngProjectID)).CloseProject
	End If
	objCenApp.OpenProject lngCurrProj
	
	Set objRecMgr = Nothing
	
End Function

Public Function LM_ValidateAllocation(objApp, lngRecord, dctFldVals)
On Error Resume Next
  	Dim lngRemainingLicenses
        Dim strMessage

        strMessage = ""

        lngRemainingLicenses = LM_GetRemainingLicenses(objApp, lngRecord, dctFldVals)
       

        If lngRemainingLicenses < 0 Then
                    strMessage = "You allocated more Licenses than you have available."			
        End If
               	
        LM_ValidateAllocation = strMessage 

End Function

Private Function LM_UpdateAllocation(objApp, lngRecord, dctFldVals, ByRef strChangedFields, rsMainTbl)

	Dim lngRemainingLicenses
	Dim lngAllocationType
	
	Const ALLOCATION_TYPE_NONE = 3
	
	If Not dctFldVals Is Nothing Then
		If dctFldVals.Exists(FLD_ALLOCATED_TYPE_ID) Then
			lngAllocationType = dctFldVals.Item(FLD_ALLOCATED_TYPE_ID)
		End If
		
		If IfNullL(lngAllocationType) <> ALLOCATION_TYPE_NONE Then

			lngRemainingLicenses = LM_GetRemainingLicenses(objApp, lngRecord, dctFldVals)    
			Call objApp.SetFieldValue(rsMainTbl, FLD_REMAINING_LICENSES, lngRemainingLicenses)

			strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_REMAINING_LICENSES_ID)
		End If
	End If
	
    'Call LM_SetStatus(objApp, lngRecord, dctFldVals, strChangedFields, lngRemainingLicenses)


End Function

Private Function LM_SetStatus(objApp, lngRecord, dctFldVals, ByRef strChangedFields, lngRemainingLicenses)

	Dim fieldValue
	Dim rs
	Dim lngNumberOfLicenses 
     
	
	Set rs = objApp.DictDtsTablesForSave(objApp.strPrimaryTableName).rs

	If objApp.FieldCollection.Exists(FLD_NUMBER_LICENSES_ID) Then
    
		lngNumberOfLicenses = objApp.GetFieldValue(rs, FLD_NUMBER_LICENSES)
		fieldValue = objApp.GetFieldValue(rs, FLD_SUBSTATE_ID)
	
		If (lngRemainingLicenses = 0) Then
			Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, FULLY_ALLOCATED )
			strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_SUBSTATE_ID)
			
		ElseIf (lngRemainingLicenses <> lngNumberOfLicenses) Then
		
			If (fieldValue = PENDING_ALLOCATION ) Then
				Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, PARTIALLY_ALLOCATED)
				strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_SUBSTATE_ID)
			              
			End If
		End If
	End If


	
End Function

Private Function LM_GetRemainingLicenses(objApp, lngRecord, dctFldVals)
   	Dim lngRemainingLicenses       
	Dim lngNumberOfLicenses
	Dim strSQL
	Dim rsLic
	Dim lngNumberAllocated
	
	lngNumberOfLicenses = 0
	lngNumberAllocated = 0
	
	 If Not dctFldVals Is Nothing Then
	
	 	If dctFldVals.Exists(FLD_NUMBER_LICENSES_ID) Then
			lngNumberOfLicenses = dctFldVals.Item(FLD_NUMBER_LICENSES_ID)
		End If
	
		strSQL = "SELECT COUNT(*) FROM [tblAllocation] WHERE [nID]=" & lngRecord & _
					" AND ((NOT [Allocated_to_User] IS NULL) OR (NOT [Allocated_to_Computer] IS NULL))"

		Set rsLic = objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		
		If Not rsLic.EOF Then
			lngNumberAllocated = IfNullL(rsLic.Fields(0).Value)
		End If
		
		lngRemainingLicenses = lngNumberOfLicenses - lngNumberAllocated
		
		rsLic.Close
		Set rsLic = Nothing
			                    
	End If

	LM_GetRemainingLicenses = lngRemainingLicenses

End Function

Private Function GetNextMax(strTableName, strFieldName, cnConnection)
	Dim strSQL
    Dim recMaxID

    strSQL = "SELECT MAX(" & strFieldName & ") FROM [" & strTableName & "]"
   
    Set recMaxID = cnConnection.Execute(strSQL)

    GetNextMax = IfNullL(recMaxID(0)) + 1

    recMaxID.Close
	Set recMaxID = Nothing

End Function

Private Function HandlePrimaryEmp(objApp, rs, lngEmpID, ByRef strChangedFields)

	Const FLD_ID_PRIMARY_EMP = 160
	Const FLD_NAME_PRIMARY_EMP = "nPrimaryEmp"
	
	Dim lngCurrentPrimary
	Dim lngNewPrimary
	Dim lngPrimaryJob
	
	lngPrimaryJob = 0
	lngCurrentPrimary = IfNullL(objApp.GetFieldValue(rs, FLD_NAME_PRIMARY_EMP))
	
	If lngCurrentPrimary = 0 Then
		
		lngNewPrimary = GetPrimaryJob(lngEmpID, objApp)
		
		If lngNewPrimary > 0 Then
			Call objApp.SetFieldValue(rs, FLD_PRIMARY_EMP, lngNewPrimary)
					
			strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_PRIMARY_EMP)
			lngPrimaryJob = lngNewPrimary
		End If
	Else
		lngPrimaryJob = lngCurrentPrimary
	End If
	
	HandlePrimaryEmp = lngPrimaryJob
End Function

Private Function GetPrimaryJob(lngEmpID, objApp)

	Dim strSQL
	Dim rsEmpJobs
	Dim lngPrimaryJob
	
	lngPrimaryJob = 0
	
	strSQL = "SELECT * FROM [" & TBL_USER_EMPLOYMENT & "] WHERE [nID]=" & lngEmpID
	
	Set rsEmpJobs = CreateObject("ADODB.Recordset")
	
	With rsEmpJobs
		.Source = strSQL
		Set .ActiveConnection = objApp.DBConnections(cenDat).GetConnection(cenDSEnsureOpenConnection)
		.LockType = adLockOptimistic
		.CursorType = adOpenStatic
		.Open
		
		If Not .EOF Then		
			.Filter = "bPrimary<>0"
			If Not .EOF Then
				lngPrimaryJob = IfNullL(.Fields("nCompositeID").Value)
			Else
				.Filter = ""
				lngPrimaryJob = IfNullL(.Fields("nCompositeID").Value)
			End If
		End If
		
		.Close
	End With

	GetPrimaryJob = lngPrimaryJob
	
	Set rsEmpJobs = Nothing
	
End Function

Private Function SetSharedEmploymentFields(objApp, rs, lngEmployeeID, lngPrimaryID)

	Dim rsPrimaryEmp
	Dim arrSrcFields
	Dim arrTgtFields
	Dim lngCount
	Dim blnFieldSet
	Dim strTgtFieldName
	Const FLD_PRIMARY_EMP = "nPrimaryEmp"
	
	arrSrcFields = Array("tEmailName", "tUserName", "nCompanyName", "tWorkPhone", "nCategoryID", "Employee_ID")
	arrTgtFields = Array("tEmailName", "tUserName", "nCompanyName", "tWorkPhone", "Category", "Employee_ID")
	
	blnFieldSet = False
	If lngPrimaryID > 0 Then
	
		strSQL = "SELECT * FROM [" & TBL_USER_EMPLOYMENT & "] WHERE [nID]=" & lngEmployeeID & " AND [nCompositeID]=" & lngPrimaryID
    	Set rsPrimaryEmp = CreateObject("ADODB.Recordset")

		With rsPrimaryEmp
			.Source = strSQL
			Set .ActiveConnection = objApp.DBConnections(cenUsers).GetConnection(cenDSEnsureOpenConnection)
			.LockType = adLockOptimistic
			.CursorType = adOpenStatic
			.Open
			
			If Not .EOF Then
				For lngCount = LBound(arrSrcFields) To UBound(arrSrcFields)
					strTgtFieldName = arrTgtFields(lngCount)
					If IsNull(.Fields(strTgtFieldName).Value) Or IfNull(.Fields(strTgtFieldName).Value)= "" Then
	
						.Fields(strTgtFieldName).Value = objApp.GetFieldValue(rs, CStr(arrSrcFields(lngCount)))
						blnFieldSet = True
					End If
				Next
				
				If CBool(IfNullL(.Fields("bPrimary").Value)) <> True Then
					.Fields("bPrimary").Value = True
					blnFieldSet = True
				End If
				
				If blnFieldSet Then
					.Update
				End If
			End If
			
			.Close
		End With
		Set rsUser = Nothing
	End If
End Function
 '

Private Function AssignAsset(lngID, lngAssignType, lngAssetID, objCenApp)
	
	Dim objAsset
	Set objAsset = CreateObject("MqCensusWeb65.CMqAsset")
	
	objAsset.Initialize objCenApp
	
	objAsset.Assign CLng(lngAssetID), CLng(lngAssignType), CLng(lngID)
	
	Set objAsset = Nothing
	
End Function

Private Function RevokeAsset(ByVal lngRevokeFromUserID, ByVal lngAssetID, ByVal objCenApp)

	Const ASSIGN_TYPE_EMPLOYEE = 1

	RevokeAsset = CBool(CallWebService("RevokeAsset", "AssetID=" & lngAssetID & "&AssignType=" & ASSIGN_TYPE_EMPLOYEE & _
                "&RevokeFrom=" & lngRevokeFromUserID, objCenApp))
				
End Function


Private Function CallWebService(ByVal strOperation, ByVal strPostData, ByVal objCenApp)

	Dim objHTTPReq							
    Set objHTTPReq = CreateObject("MSXML2.ServerXMLHTTP")
	Dim objStringManip
	Set objStringManip = CreateObject("Mqsysutils40.CMqStringManipulation")
	
    Dim strURL
    
	strURL = "http://localhost/connect/webapi/assetservice.asmx/" & strOperation & "?" & _
                    "Username=" & objStringManip.URLEncode(objCenApp.User) & _
                    "&Password=" & objStringManip.URLEncode(objStringManip.MqEncrypt(objCenApp.Password)) & _
                    "&pwdIsEncrypted=True&" & strPostData
    
	objHTTPReq.Open "GET", CStr(strURL)
    
    objHTTPReq.send
    
    CallWebService = objHTTPReq.responseXML.Text
    
    Set objHTTPReq = Nothing
    Set objStringManip = Nothing

End Function


Private Function DeprovisionAsset(lngID, strTable, strIDField, lngAssetID, objCenApp)
	
	objCenApp.CurrentProject.GetAllDataStores(cenDat).DeleteTableRecords CStr(strTable), _
								"[" & strIDField & "]=" & lngID & _
								" AND nResID=" & lngAssetID
								
End Function

Private Function OnAssetLocationChanged(objApp, varCurrentValue, rs, ByRef strChangedFields, ByVal varPreviousVal)

	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		If IfNullL(varPreviousVal) > 0 Then
			m_lngPrevAssignToLocation = IfNullL(varPreviousVal)
		End If
		
		If IfNullL(varCurrentValue) > 0 Then
			m_lngAssignToLocation = IfNullL(varCurrentValue)
		End If
	End If
	
End Function

Private Function OnAssetOwnerChanged(objApp, varCurrentValue, rs, ByRef strChangedFields, ByVal varPreviousVal)

	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		If IfNullL(varPreviousVal) > 0 Then
			m_lngPrevAssignToUser = IfNullL(varPreviousVal)
		End If
		
		If IfNullL(varCurrentValue) > 0 Then
			m_lngAssignToUser = IfNullL(varCurrentValue)
		End If
	End If

	End Function
	
Private Function OnAssetSubStatusChanged(objApp, objField, varCurrentValue, rs, ByRef strChangedFields)

	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		Const FLD_ID_RETIRED_DATE = 848
		Const FLD_ID_PROV_STATUS = 801
		Const STATUS_LOST = 4
		Const STATUS_RETIRED = 3
		Const STATUS_ASSIGNED = 1
				
		Dim lngStateID
		Dim varPreviousValue
		
		If GetDependentValue(objApp, objField, varCurrentValue, lngStateID) Then
		
			'Get the previous State value...
            varPreviousValue = objApp.GetFieldValue(rs, FLD_STATE_ID)
		
			'If the State actually changed...
			If StrComp(CStr(IfNull(varPreviousValue)), CStr(IfNull(lngStateID)), vbTextCompare) <> 0 Then		
				' Convert the value to long to pass it by value, not by reference, because
				' it could be changed to the equivalent value name (string)
				Call objApp.SetFieldValue(rs, FLD_STATE_ID, CLng(lngStateID))
				strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_STATE)
			End If
		End If
		
		If CLng(varCurrentValue) = STATUS_RETIRED Or CLng(varCurrentValue) = STATUS_LOST Then
			Call objApp.SetFieldValue(rs, FLD_ID_RETIRED_DATE, Date)
		Else          
			Call objApp.SetFieldValue(rs, FLD_ID_RETIRED_DATE, Null)
			
			If CLng(varCurrentValue) = STATUS_ASSIGNED Then
				'set the provisioning status to requested
				Call objApp.SetFieldValue(rs, FLD_ID_PROV_STATUS, 1)
			End If
		End If
		
		m_blnRetiredDateSet = True
		m_blnAssetStatusChanged = True
		
		strChangedFields = AddFieldToChangedFieldsList(strChangedFields, FLD_ID_RETIRED_DATE)
	End If
End Function

Private Function OnAssetRetiredDateChanged(objApp, varCurrentValue, rs, ByRef strChangedFields, ByRef blnSaveField)

	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		If m_blnRetiredDateSet Then
			blnSaveField = False
		End If
	End If

End Function

Private Function CalculateAssetTotals(objApp, rs)
	If objApp.CensusApplication.CurrentProject.TemplateID = RESOURCES_TEMPLATE Then
		
		'when the status changes, re-calculate the asset defintion totals
		Dim objAssetCalc
		Dim lngAssetType
		
		lngAssetType = IfNullL(rs.Fields("Level_2").Value)
		If lngAssetType > 0 Then
			Set objAssetCalc = CreateObject("MqCensusWeb65.CMqAssetCalc")
			
			objAssetCalc.Initialize objApp.CensusApplication.CurrentProject
			objAssetCalc.Calculate CLng(lngAssetType), True
			
			Set objAssetCalc = Nothing
		End If
	End If
End Function

Private Function ValidateUserHasJob(objApp, lngRecord, dctFldVals)
	
	Dim strSQL
	Dim rsEmp
	Dim strEmployeeID
	Dim strReturn
	Dim lngJobCount
	
	strReturn = ""
	Const FLD_EMPLOYMENT_ID = "114"
		
	If dctFldVals.Exists(FLD_EMPLOYMENT_ID) Then
		strEmployeeID = IfNull(dctFldVals.Item(FLD_EMPLOYMENT_ID))
		
		If strEmployeeID = "" Then
			strEmployeeID = IfNull(lngRecord)
		End If
		
		If strEmployeeID <> "" Then
			strSQL = "SELECT COUNT(*) FROM [" & TBL_USER_EMPLOYMENT & "] WHERE [nID]=" & strEmployeeID
			
			Set rsEmp = objApp.DBConnections(cenUsers).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		
			If Not rsEmp.EOF Then
				lngJobCount = IfNullL(rsEmp.Fields(0).Value)
			End If
			
			rsEmp.Close
			Set rsEmp = Nothing
		Else
			lngJobCount = 0
		End If
		
		If lngJobCount = 0 Then
			strReturn = "An employment is required for the employee."
		End If
	End If
	
	ValidateUserHasJob = strReturn

End Function

Private Function GetJobTable(objApp)
	Dim objSettingMgr
	Set objSettingMgr = CreateObject("MqCenX20.CMqSetting")
	Dim strJobMode
	
	Const EMP_JOB_MODE_SINGLE = "1"
	
	strJobMode = objSettingMgr.GetSettingValue(objApp.DBConnections(cenLicenses).GetConnection(cenDSEnsureOpenConnection), 319)
	
	If strJobMode = EMP_JOB_MODE_SINGLE Then
		strUserTable = TBL_USER
	Else
		strUserTable = TBL_USER_EMPLOYMENT
	End If
	
	GetJobTable = strUserTable
	
	Set objSettingMgr = Nothing
	
End Function

Private Function GetUserCompanyID(oCensusApplication, strUserID)

    Dim rstCompany
    Dim strSQL
    
    Const TABLE_USER = "tblUser"
    Const FLD_COMPANY_NAME = "nCompanyName"
    Const FLD_NAME = "tName"
                        
    strSQL = "SELECT [" & FLD_COMPANY_NAME & "] FROM [" & TABLE_USER & _
                "] WHERE [nID] =" & strUserID 

    Set rstCompany = oCensusApplication.DataStores.Item(CLng(cenUsers)).GetConnection( _
                        CLng(cenDSEnsureOpenConnection)).Execute(strSQL)

    If Not rstCompany.EOF Then
        If Not IsNull(rstCompany.Fields(FLD_COMPANY_NAME).Value) Then
            GetUserCompanyID = CLng(rstCompany.Fields(FLD_COMPANY_NAME).Value)
        End If
    End If
    
    If Not rstCompany Is Nothing Then
        rstCompany.Close
        Set rstCompany = Nothing
    End If

End Function

Private Function HandleFulfillmentStatus(objApp, rs, lngRecordID)

	Dim lngStatus
	Dim lngNumNeeded
	Dim lngNumFulfilled
	
	lngStatus = IfNullL(objApp.GetFieldValue(rs, FLD_SUBSTATE_ID))
	
	If lngStatus = SUB_STATE_ACTIONS_PENDING_ALLOC Then
		lngNumNeeded = 0
		lngNumFulfilled = 1 'stop
		If lngNumFulfilled = lngNumNeeded Then
			'if all that were needed are set, change status to completes
			Call objApp.SetFieldValue(rs, FLD_SUBSTATE_ID, SUB_STATE_ACTIONS_COMPLETED)
			Call objApp.SetFieldValue(rs, FLD_STATE_ID, STATE_CLOSED)
		End If
	End If
	
End Function

Private Function ValidateRequiredByWithinTimeConstraints(objApp, lngRecord, dctFldVals)

	Dim lngMinAllocHours
	Dim strReqByDate
	Dim strReqByTime
	Dim dtReqByDateFull
	Dim strMsg
	Dim lngAssetType
	Dim strAdditionalMsg
	
	Const FLD_REQ_BY_DATE_ID = "<F.ID:Request Required By Date>"
	Const FLD_REQ_BY_TIME_ID = "<F.ID:Request Required By Time>"
	Const FLD_REQ_ASSET_TYPE_ID = "<F.ID:Asset Type>"
	strMsg = ""
	lngAssetType = 0
	
	If FLD_REQ_BY_DATE_ID <> "" And FLD_REQ_BY_TIME_ID <> "" And FLD_REQ_ASSET_TYPE_ID <> "" Then
		If dctFldVals.Exists(FLD_REQ_BY_DATE_ID) And dctFldVals.Exists(FLD_REQ_BY_TIME_ID) And dctFldVals.Exists(FLD_REQ_ASSET_TYPE_ID) Then
		
			strReqByDate = IfNull(dctFldVals.Item(FLD_REQ_BY_DATE_ID))
			strReqByTime = IfNull(dctFldVals.Item(FLD_REQ_BY_TIME_ID))
			
			If strReqByDate <> "" And strReqByTime = "" Then
				strMsg = "You've indicated a required by date but not a time. Please enter both if you need this asset for a specific time."
			ElseIf strReqByTime <> "" And strReqByDate = "" Then
				strMsg = "You've indicated a required by time but not a date. Please enter both if you need this asset for a specific time."
			ElseIf strReqByDate <> "" And strReqByTime <> "" Then
			
				lngAssetType = IfNullL(dctFldVals.Item(FLD_REQ_ASSET_TYPE_ID))
			
				lngMinAllocHours = GetMinAllocHoursForAssetType(lngAssetType, objApp)
			
				dtReqByDateFull = CDate(strReqByDate & " " & strReqByTime)
				If DatePart("h", dtReqByDateFull) < 8 Or DatePart("h", dtReqByDateFull) > 17 Then
					strMsg = "You've indicated a delivery time before 8:00 AM or after 5:00 PM. A delivery time must be within the specified hours."	
				ElseIf DateDiff("n", DateAdd("h", lngMinAllocHours, Now), dtReqByDateFull) < 0 Then
					strMsg = "The minimum time needed to allocate this asset is " & lngMinAllocHours & " hours. You've indicated that you need it before that."
				End If
				
				If strMsg <> "" Then
					strAdditionalMsg = GetAssetTypeAdditionalMsg(lngAssetType, objApp)
					
					If strAdditionalMsg <> "" Then
						strMsg = strMsg & vbCrLf & vbCrLf & strAdditionalMsg
					End If
				End If
			End If
		End If
	End If
	
	ValidateRequiredByWithinTimeConstraints = strMsg
End Function

Private Function GetMinAllocHoursForAssetType(lngAssetType, objApp)
	
	Dim strSQL
	Dim lngMinHours
	Dim rsAT
	
	lngMinHours = 0 
	Const FLD_MIN_PROV_TIME = "Minimum_Provisioning_Time"
	
	If lngAssetType > 0 Then
		strSQL = "SELECT [" & FLD_MIN_PROV_TIME & "] FROM [tblDts] WHERE [nID]=" & lngAssetType
			
		Set rsAT = objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
		If Not rsAT.EOF Then
			lngMinHours = IfNullDbl(rsAT.Fields(FLD_MIN_PROV_TIME).Value)
		End If
		
		rsAT.Close
		Set rsAT = Nothing
	
	End If
	
	GetMinAllocHoursForAssetType = lngMinHours
	
End Function

Private Function GetAssetTypeAdditionalMsg(lngAssetType, objApp)
	
	Dim strSQL
	Dim strAdditionalMsg
	Dim rsAT
	
	strAdditionalMsg = ""
	Const FLD_ADDITIONAL_MSG = "Request_Warning_Message"
	
	If lngAssetType > 0 Then
		strSQL = "SELECT [" & FLD_ADDITIONAL_MSG & "] FROM [tblDts] WHERE [nID]=" & lngAssetType
			
		Set rsAT = objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
	
		If Not rsAT.EOF Then
			strAdditionalMsg = IfNull(rsAT.Fields(FLD_ADDITIONAL_MSG).Value)
		End If
		
		rsAT.Close
		Set rsAT = Nothing
	
	End If
	
	GetAssetTypeAdditionalMsg = strAdditionalMsg
	
End Function

Private Function UpdateLocationNames(objApp, rs, lngRecord)
	
	'if the name of a location changed, update all the dependent ones
	Dim strSQL 
	Dim strWhere
	Dim strLevelField
	Dim lngItemLevel
	lngItemLevel = IfNullL(rs.Fields("Item_Level").Value)
	
	If lngItemLevel > 0 Then
	
		strLevelField = "Level_" & lngItemLevel
	
		strWhere = " AND A.[" & strLevelField & "]=" & lngRecord
	
		If lngItemLevel < 2 Then
			strSQL = "UPDATE A SET tBriefDescription = B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & " FROM tblDts A LEFT JOIN tblDts B " & _
						"ON A.Level_1=B.nID WHERE A.Item_Level = 2 AND A.tBriefDescription <> B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & strWhere
			objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		End If

		If lngItemLevel < 3 Then
			strSQL = "UPDATE A SET tBriefDescription = B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & " FROM tblDts A LEFT JOIN tblDts B " & _
						"ON A.Level_2=B.nID WHERE A.Item_Level = 3 AND A.tBriefDescription <> B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & strWhere
			objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		End If

		If lngItemLevel < 4 Then
			strSQL = "UPDATE A SET tBriefDescription = B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & " FROM tblDts A LEFT JOIN tblDts B " & _
						"ON A.Level_3=B.nID WHERE A.Item_Level = 4 AND A.tBriefDescription <> B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & strWhere
			objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		End If

		If lngItemLevel < 5 Then
			strSQL = "UPDATE A SET tBriefDescription = B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & " FROM tblDts A LEFT JOIN tblDts B " & _
						"ON A.Level_4=B.nID WHERE A.Item_Level = 5 AND A.tBriefDescription <> B.tBriefDescription + ' \ ' + A." & FLD_SHORT_NAME & strWhere
			objApp.CensusApplication.CurrentProject.GetAllDataStores(cenDat).GetConnection(cenDSEnsureOpenConnection).Execute(strSQL)
		End If
		
	End If
	

End Function

Private Function UpdatePendingProcessing(objApp, lngRecord, dctFldVals, ByRef strChangedFields, rsMainTbl)
	
	Const VAL_YES = 1
	Const VAL_NO = 2
	
	Const SUB_TYPE_NEW_LIC = 1
	Const SUB_TYPE_SUBSCRIPTION = 6
	Const SUB_TYPE_ASSET = 8
	
	Dim lngSubType
	Dim blnAutoCreateAssets
	
	If Not dctFldVals Is Nothing Then
		If dctFldVals.Exists(FLD_SUB_TYPE_ID) Then
			lngSubType = IfNullL(dctFldVals.Item(FLD_SUB_TYPE_ID))
		Else
			lngSubType = 0
		End If
		
		If dctFldVals.Exists(FLD_AUTO_CREATE_ASSETS_ID) Then
			blnAutoCreateAssets = CBool(IfNull(dctFldVals.Item(FLD_AUTO_CREATE_ASSETS_ID)))
		Else
			blnAutoCreateAssets = False
		End If
		
		If blnAutoCreateAssets Then
			'if the auto create changed and it's one of the supported sub types, then set the pending processing
			If lngSubType = SUB_TYPE_NEW_LIC Or lngSubType = SUB_TYPE_SUBSCRIPTION Or lngSubType = SUB_TYPE_ASSET Then
				'Set the pending processing to true
				Call objApp.SetFieldValue(rsMainTbl, FLD_PENDING_PROCESSING, VAL_YES)
				strChangedFields = AddFieldToChangedFieldsList(strChangedFields, IfNullL(FLD_PENDING_PROCESSING_ID))
			Else
				'Set the auto create to false and the pending processing to false
				Call objApp.SetFieldValue(rsMainTbl, FLD_PENDING_PROCESSING, VAL_NO)
				strChangedFields = AddFieldToChangedFieldsList(strChangedFields, IfNullL(FLD_PENDING_PROCESSING_ID))
				
				Call objApp.SetFieldValue(rsMainTbl, FLD_AUTO_CREATE_ASSETS, 0)
				strChangedFields = AddFieldToChangedFieldsList(strChangedFields, IfNullL(FLD_AUTO_CREATE_ASSETS_ID))
			End If
		Else
			'it was turned off, set pending processing to false
			Call objApp.SetFieldValue(rsMainTbl, FLD_PENDING_PROCESSING, VAL_NO)
			strChangedFields = AddFieldToChangedFieldsList(strChangedFields, IfNullL(FLD_PENDING_PROCESSING_ID))
		End If
	End If
	
End Function
