Search for:
HDL – Convert Contingent Workers to Workers

There are scenario’s where customers want to convert their non permanent staff to permanent staff in bulk or vice versa. In HCM terminology, this causes changes in system person type of a person. Let us take an example where a customer wants to hire all the contingent workers working in the company as permanent staff.

As mentioned earlier, converting a contingent worker into worker/employee person type will change the system person type of the person. This is a two step process:

  1. Terminate all the CWK records.
  2. Rehire them as workers.

Performing these steps manually for 100+ records will be a tough task and is error prone process. So, it is better to use HDL for this.

First, we will terminate CWK records. Below is the sample file for same:

METADATA|WorkRelationship|PeriodOfServiceId|LegalEmployerName|DateStart|PersonId|WorkerType|ActualTerminationDate|ActionCode|TerminateWorkRelationshipFlag

MERGE|WorkRelationship|300012012120031|Test Legal Employer|2023/01/01|30001212121223|C|2024/05/08|TERMINATE_PLACEMENT|Y

Below sample SQL can be used to get the various IDs:

SELECT PERIOD_OF_SERVICE_ID, PERSON_ID,DATE_START, PERIOD_TYPE, LEGAL_ENTITY_ID
  FROM PER_PERIODS_OF_SERVICE

Once the termination file is loaded successully, we need to rehire the persons as Worker. Sample file for REHIRE:

METADATA|WorkRelationship|PersonNumber|LegalEmployerName|PrimaryFlag|DateStart|WorkerType
MERGE|WorkRelationship|1234|Test Legal Employer|Y|2024/05/09|E

METADATA|WorkTerms|ActionCode|EffectiveStartDate|EffectiveEndDate|EffectiveSequence|EffectiveLatestChange|AssignmentStatusTypeCode|AssignmentType|BusinessUnitShortCode|PrimaryWorkTermsFlag|LegalEmployerName|PersonNumber|DateStart|WorkerType|AssignmentNumber
MERGE|WorkTerms|REHIRE|2024/05/09|4712/12/31|1|Y|ACTIVE_PROCESS|ET|Test BU|Y|Test Legal Employer|1234|2024/05/09|E|ET1234

METADATA|Assignment|ActionCode|EffectiveStartDate|EffectiveEndDate|EffectiveSequence|EffectiveLatestChange|AssignmentStatusTypeCode|AssignmentType|BusinessUnitShortCode|PrimaryAssignmentFlag|PersonNumber|AssignmentCategory|DateStart|WorkerType|LegalEmployerName|AssignmentNumber|WorkTermsNumber
MERGE|Assignment|REHIRE|2024/05/09|4712/12/31|1|Y|ACTIVE_PROCESS|E|Test BU|Y|1234|FR|2024/05/09|E|Test Legal Employer|E1234|ET1234

Please note for rehire, only Work Relationship, Work Terms and Assignment METADATA are required.

HDL – Sample file to upload Department DFF attributes

Sample file to upload/update/correct DFF values on department using User Keys:

METADATA|Organization|Name|ClassificationName|EffectiveStartDate|EffectiveEndDate|FLEX:PER_ORGANIZATION_UNIT_DFF|testAttribute(PER_ORGANIZATION_UNIT_DFF=Global Data Elements)

MERGE|Organization|Test Organization|Department|1951/01/01|4712/12/31|Global Data Elements|Xyz

METADATA|OrgUnitClassification|OrganizationName|ClassificationName|SetCode|EffectiveStartDate|EffectiveEndDate

MERGE|OrgUnitClassification|Test Organization|Department|COMMON|1951/01/01|4712/12/31
HDL – Update Assignment Attributes with User Keys

Below is an example of updating assignment category using only user keys:

METADATA|WorkTerms|AssignmentNumber|PersonNumber|LegalEmployerName|DateStart|WorkerType|ActionCode|ReasonCode|EffectiveStartDate|EffectiveEndDate|EffectiveLatestChange|EffectiveSequence
MERGE|WorkTerms|ET000123|000123|US Inc Legal Employer|2014/04/07|E|LOCATION_CHANGE||2023/04/28|4712/12/31|Y|1

METADATA|Assignment|AssignmentNumber|PersonNumber|LegalEmployerName|DateStart|WorkerType|ActionCode|ReasonCode|WorkTermsNumber|EffectiveStartDate|EffectiveEndDate|EffectiveLatestChange|EffectiveSequence|AssignmentCategory
MERGE|Assignment|E000123|000123|US Inc Legal Employer|2014/04/07|E|LOCATION_CHANGE||ET000123|2023/04/28|4712/12/31|Y|1|FR

If you want to use surrogate IDs/ integration keys, then you can check the below post:

BIP – Query to get Job Profile Details
SELECT pjf.job_code
      ,hpb.profile_code
      ,hpt.description profile_desc
      ,hpt.summary
      ,hpeiv.DESCRIPTION
      ,hpeiv.RESPONSIBILITIES
      ,hpeiv.QUALIFICATIONS
  FROM HRT_PROFILE_ITEMS hpi
      ,HRT_PROFILES_B hpb
      ,HRT_PROFILES_TL hpt
      ,HRT_PROFILE_RELATIONS hpr
      ,HRT_PROFILE_EXTRA_INFO_VL hpeiv
      ,PER_JOBS_F pjf
 WHERE hpi.profile_id = hpb.profile_id
   AND hpb.profile_usage_code = 'M'
   AND hpi.profile_id = hpr.profile_id
   AND hpi.profile_id = hpt.profile_id
   AND hpi.profile_id = hpeiv.profile_id
   AND pjf.job_id = hpr.object_id
   AND trunc(sysdate) between pjf.effective_start_date and pjf.effective_end_Date
   AND pjf.job_code= '1099'
   AND hpt.language = 'US'
BIP – Extract Job details with Job Family and Job Function details
SELECT pjf.job_id
     , pjf.job_code
     , pjft.name
     , pjffv.job_family_name
     , pjf.effective_start_date
     , pjf.job_function_code
     , hikm.source_system_id
     , hikm.source_system_owner
  FROM per_jobs_f pjf
     , per_jobs_f_tl pjft
     , per_job_family_f_vl pjffv
     , hrc_integration_key_map hikm
 WHERE pjf.job_id = hikm.surrogate_id
   AND pjft.job_id = pjf.job_id
   AND trunc(sysdate) between pjf.effective_start_date and pjf.effective_end_date
   AND trunc(sysdate) between pjft.effective_start_date and pjft.effective_end_date
   AND trunc(sysdate) between pjffv.effective_start_date and pjffv.effective_end_date
   AND pjft.language = 'US'
   AND pjffv.job_family_id = pjf.job_family_id

List of all job families not associated with a Job:

SELECT *
  FROM per_job_family_f_vl pjffv
 WHERE 1=1
   AND NOT EXISTS (SELECT 1
                     FROM per_jobs_f pjf
		    WHERE pjffv.job_family_id = pjf.job_family_id)
HDL – Sample file to load Licenses and Certifications to employee profile

Sample file to load licenses and certifications to employee profile:

METADATA|TalentProfile|ProfileCode|PersonNumber|ProfileId|SourceSystemOwner|SourceSystemId
MERGE|TalentProfile|PERS_300000123456789|1234|300000123456789|HRC_SQLLOADER|PERS_300000123456789

METADATA|ProfileItem|ProfileId|ProfileCode|SectionId|ContentTypeId|ContentItem|DateFrom|DateTo|RatingModelCode1|RatingLevelCode1|RatingModelCode2|RatingLevelCode2|RatingModelCode3|RatingLevelCode3|ItemText301|ItemText302|ItemText303|SourceSystemOwner|SourceSystemId
MERGE|ProfileItem|300000123456789|PERS_300000123456789|9989|103|Oracle Global HR|2024/07/01|||||||||||HRC_SQLLOADER|HRC_SQLLOADER_PERS_300000123456789_Oracle Global HR

Sample useful queries:

Query to get source system ID and owner details for existing profiles:

select hrb.profile_id
     , hikm.source_system_id 
	 , hikm.source_system_owner 
  from HRT_PROFILES_ITEMS hrb,
       HRC_INTEGRATION_KEP_MAP hikm
 where hrb.profile_id = hikm.surrogate_id

Query to get profile id for a worker:

select papf.person_number
     , hrb.profile_id  
     , hrb.profile_code 
  from HRT_PROFILES_B hrb,
       PER_ALL_PEOPLE_F papf
 where papf.PERSON_ID =  hrb.PERSON_ID
   and TRUNC(SYSDATE) BETWEEN papf.EFFECTIVE_START_DATE AND papf.EFFECTIVE_END_DATE
   and papf.person_number = <>
Security – Deactivating Users in Bulk

With the security concerns regarding access to Oracle HCM applications, I have seen many customers asking for a way to restrict access to a particular DEV/TEST environment having unmasked data. One option in such scenario’s is to keep only the admin user accounts active in the particular environment and deactivate all other user accounts. This way, the user roles data is kept intact and access is restricted to only a set of limited users.

Let us now understand, the kind of users which can exist in Fusion HCM environment. There can be system users (seeded), service accounts, worker accounts (users tied to a person), standalone user accounts (for vendors/ SI partners). So, it is really important to filter the right set of user accounts which should be deactivated. Also, the method of deactivation can vary depending upon the type of user.

Bulk deactivation of users can be performed using either HDL or by using SCIM REST API. While HDL is bulk data upload tool but it has its own set of limitations. HDL can’t be used to deactivate standalone users i.e. the users which don’t have an associated person record. To deactivate standalone users, REST API should be used.

I will discuss both the approaches in details. Let us first find a way to store the admin user accounts which should remain active. My preferred way of doing this is to create a Common Lookup and add the details (user names) in this lookup. This is because lookup values can be updated easily using a spreadsheet loader.

Below is the sample lookup (XX_ACTIVE_USER_ACCOUNTS) which I created to store the admin user names:

Next step is to add the user accounts in the meaning attribute:

Two user accounts – [email protected] and [email protected] have been added. The next steps will be to filter these record from the deactivation steps.

Let us now discuss the first approach which is to deactive user accounts using HDL. Below SQL query can be used to get a list of all required active user accounts in User.dat HDL format:

SELECT 'METADATA|User|UserId|Suspended' datarow
      ,1 seq
  FROM DUAl
 UNION
SELECT 'MERGE|User|'
       || pu.user_id
       || '|Y' datarow
      ,2 seq 
  FROM per_users pu
 WHERE pu.person_id IS NOT NULL
   AND pu.created_by NOT IN ('anonymous')
   AND pu.username NOT LIKE 'FUSION%APPS%'
   AND pu.username NOT IN ('AIACS_AIAPPS_LHR_STAGE_APPID','FAAdmin','FAWService','FAWService_APPID','FIISUSER','HCMSI-98f0f163a79a46c58fa4572e41fac8ed_scim_client_APPID','IDROUser','IDRWUser',						'OCLOUD9_osn_APPID','PSCR_PROXY_USER','PUBLIC','app_monitor1','app_monitor',						  'em_monitoring2','fa_monitor','faoperator','oamAdminUser','puds.pscr.anonymous.user','weblogic_idm','anonymous'
)						   
  AND pu.suspended = 'N'
  AND lower(pu.username) NOT IN (SELECT lower(flv.meaning)
                                    FROM fnd_lookup_values flv
                                   WHERE flv.lookup_type = 'XX_ACTIVE_USER_ACCOUNTS'
                                     AND flv.language = 'US'
                                     AND flv.enabled_flag = 'Y'
                                  )									 
ORDER BY seq

So, the above query will return only those active user accounts which are attached to a person record and don’t exist in the custom lookup XX_ACTIVE_USER_ACCOUNTS.

**Suspended Flag in PER_USERS table indicate if the user is active (N) or inactive (Y).

Next step is to create a BIP data model and a report and save the output data in excel format. From excel, copy the data in a Notepad and save the file as User.dat.

Sample Output in excel format:

Copy the data except for “DATAROW” and paste it in a Notepad. Save the file as User.dat:

zip the User.dat file and upload it in HCM using Data Exchange -> Import and Load.

Once the load is successful, please run – ‘Send Pending LDAP Requests’ ESS job. This should deactivate all the extracted users.

You can run quick queries on per_users to make sure that the user accounts have been deactivated.

Second approach is to use SCIM REST API to bulk deactivate user accounts. I recommend to use this approach only for those users where no person record is attached to the user account.

Please check below MOS note for details on the step by step instructions on SCIM REST API:

Fusion Security: Using SCIM REST API (Doc ID 2346455.1)

Please note that in order to run this REST API, the user should have – IT Security Manager role.

Sample url to bulk deactivate users :-

https://fa-abcdef-dev-saasfaprod1.fa.ocs.oraclecloud.com/hcmRestApi/scim/Bulk
Sample Payload:

{
"Operations":[
{
"method":"PATCH",
"path":"/Users/0453A72EE08D419BE0631078680AA831",
"bulkId":"100000001",
"data":{
"schemas":[
"urn:scim:schemas:core:2.0:User"
],
"active":false
}
},
{
"method":"PATCH",
"path":"/Users/0453A72EE08D419BE0631078612AA832",
"bulkId":"100000001",
"data":{
"schemas":[
"urn:scim:schemas:core:2.0:User"
],
"active":false
}
}
]
}

Please note (taken from above Oracle note):

The bulkId attribute value should be set to UNIQUE value, while creating user accounts in BULK. This is required as per IETF SCIM Specifications while creating new resources using POST method. You may use a common value for the bulkId attribute while using PATCH, DELETE, PUT methods in a Bulk operation.

The main challenge with this approach is to get the correct JSON Payload for multiple users from system. I have created a BIP report for this which will generate the output data in required JSON format. Below is the sample code:

SELECT '{
"Operations":['
 data_row, 1 seq 
  FROM DUAL
UNION
SELECT 
'{
"method":"PATCH",
"path":"/Users/'
||pu.user_guid||
'",
"bulkId":"1000000000001",
"data":{
"schemas":[
"urn:scim:schemas:core:2.0:User"
],
"active":false
}
},' data_row, 2 seq
 FROM per_users pu
 WHERE pu.person_id IS NOT NULL
   AND pu.created_by NOT IN ('anonymous')
   AND pu.username NOT LIKE 'FUSION%APPS%'
   AND pu.username NOT IN ('AIACS_AIAPPS_LHR_STAGE_APPID','FAAdmin','FAWService','FAWService_APPID','FIISUSER',
                           'HCMSI-98f0f163a79a46c58fa4572e41fac8ed_scim_client_APPID','IDROUser','IDRWUser',
						   'OCLOUD9_osn_APPID','PSCR_PROXY_USER','PUBLIC','app_monitor1','app_monitor',
						   'em_monitoring2','fa_monitor','faoperator','oamAdminUser','puds.pscr.anonymous.user',
						   'weblogic_idm','anonymous'
						   )						   
   AND pu.suspended = 'N'
   AND lower(pu.username) NOT IN (SELECT lower(flv.meaning)
                                    FROM fnd_lookup_values flv
                                   WHERE flv.lookup_type = 'XX_ACTIVE_USER_ACCOUNTS'
                                     AND flv.language = 'US'
                                     AND flv.enabled_flag = 'Y'
                                  )									 
UNION
SELECT '
]
}' data_row, 3 seq
  FROM dual
ORDER BY seq

You can create a BIP data model and report to get data from this query. Extract the data in excel format and copy it to a notepad. Then you need to remove the highlighted comma in order for this JSON payload to work.

You can use SOAP UI/Postman to run the REST API and provide the output from Notepad as JSON input. Once the API runs successfully, the suspended flag will get changed to Y in per_users table.