Mass create Worker-User relations in AX 2012

A relation between the worker and the system user records (System administration > Common > Users > User relations) is necessary to approve BOMs, enter timesheets or expense reports in Dynamics AX. The user records can be easily imported from the Active Directory, the Employee records can be migrated from a legacy ERP or a 3rd party system through the DIXF interface.

The DIXF in Dynamics AX CU9/CU10 can also fill the missing link between the two, but a simple idempotent X++ job can also be a viable solution to mass create missing DirPersonUser relations. The below script tries to match the users by the e-mail address, then by the First-Last name, then by the Last-First name etc.

 // Align the users and the workers by the e-mail address first, and the name second
public static void generateDirPersonUser()
{
    DirPersonUser               dirPersonUser, dirPersonUser2;
    UserInfo                    userInfo;
    SysUserInfo                 sysUserInfo;
    HcmWorker                   hcmWorker;
    LogisticsElectronicAddress  electronicAddress;
    DirPerson                   dirPerson;
    Name                        rearrangedName;
    DirNameSequence             dirNameSequence;
    DirPersonName               dirPersonName;
    while select userInfo
        join sysUserInfo
            where sysUserInfo.Id == userInfo.id
        notexists join dirPersonUser2
            where dirPersonUser2.User == userInfo.id
    {
        dirPerson.clear();
        if (sysUserInfo.Email) // 1st attempt
        {
            select firstonly hcmWorker
                join dirPerson
                    where dirPerson.RecId == hcmWorker.Person
                join electronicAddress
                    where electronicAddress.Locator == sysUserInfo.Email
                       && electronicAddress.RecId == dirPerson.(DirPartyTable::electronicAddressType2primaryFieldId(LogisticsElectronicAddressMethodType::Email);
        }
        if (! dirPerson && strAlpha(userInfo.name))
        {
            dirPersonName.clear(); 
            [dirPersonName.FirstName,
             dirPersonName.MiddleName,
             dirPersonName.LastName] = str2con(strReplace(userInfo.name, '.,', ' '), ' ');
            while select dirNameSequence // 2nd, 3rd etc. attempt
            {    
                rearrangedName = dirPerson.name(dirPersonName,  DirNameSequence.DisplayAs);         
                select firstonly hcmWorker
                    join dirPerson
                        where dirPerson.RecId == hcmWorker.Person
                           && dirPerson.Name  == rearrangedName;
                if (dirPerson)
                    break;
            }
        }
        if (dirPerson && hcmWorker::getMaxEmploymentEndDate(hcmWorker.RecId) > DateTimeUtil::utcNow())
        {
            dirPersonUser.clear();
            dirPersonUser.initValue();
            dirPersonUser.PersonParty = dirPerson.RecId;
            dirPersonUser.User = userInfo.id;
            dirPersonUser.ValidFrom = hcmWorker::getMinEmploymentStartDate(hcmWorker.RecId);
            dirPersonUser.ValidTo = hcmWorker::getMaxEmploymentEndDate(hcmWorker.RecId);
            if (dirPersonUser.validateWrite())
            {
                dirPersonUser.insert();
            }
        }
    }
}