Memos About Salesforce

Salesforceにハマってたこと!

Salesforce パートナーユーザ コミュニティユーザ 作成 MIXED_DML_OPERATION FIELD_INTEGRITY_EXCEPTION

こんにちは、管理人の@Salesforce.Zです。

パートナーコミュニティやカスタマーコミュニティを聞いたことがあるでしょう

実際に活用し、開発すると、まだいろいろ新鮮ですよ。

今回、パートナーコミュニティやカスタマーコミュニティのユーザを作成し、テストクラスを書く場合のエラーを共有し、およびその解消方法を公開します。

読んだら得ること

★ 外部ユーザをテストクラスで作成する方法

目次

外部ユーザ作成手順

  • 外部取引先の所有者の用意

  • 取引先を用意(上記のユーザを所有者にする)

  • 上記の取引先の取引先責任者を用意する

  • 外部ユーザを用意する(ロール設定しない、上記の取引先責任者とリレーションする)

外部ユーザをテストクラスで作成する

    //Create portal account owner
    UserRole portalRole = [Select Id From UserRole Where PortalType = 'None' Limit 1];
    Profile profile1 = [Select Id from Profile where name = 'System Administrator'];
    User portalAccountOwner1 = new User(
        UserRoleId = portalRole.Id,
        ProfileId = profile1.Id,
        Username = System.now().millisecond() + 'test2@test.com',
        Alias = 'batman',
        Email='bruce.wayne@wayneenterprises.com',
        EmailEncodingKey='UTF-8',
        Firstname='Bruce',
        Lastname='Wayne',
        LanguageLocaleKey='en_US',
        LocaleSidKey='en_US',
        TimeZoneSidKey='America/Chicago'
    );
    Database.insert(portalAccountOwner1);

    System.runAs (portalAccountOwner1){
        //Create account
        Account portalAccount1 = new Account(
            Name = 'TestAccount',
            OwnerId = portalAccountOwner1.Id
        );
        Database.insert(portalAccount1);
                
        //Create contact
        Contact contact1 = new Contact(
            FirstName = 'Test',
                Lastname = 'McTesty',
            AccountId = portalAccount1.Id,
                Email = System.now().millisecond() + 'test@test.com'
        );
        Database.insert(contact1);
                
        //Create user
        Profile portalProfile = [SELECT Id FROM Profile WHERE Name LIKE '%Portal User%' Limit 1];
        User user1 = new User(
            Username = System.now().millisecond() + 'test12345@test.com',
            ContactId = contact1.Id,
            ProfileId = portalProfile.Id,
            Alias = 'test123',
            Email = 'test12345@test.com',
            EmailEncodingKey = 'UTF-8',
            LastName = 'McTesty',
            CommunityNickname = 'test12345',
            TimeZoneSidKey = 'America/Los_Angeles',
            LocaleSidKey = 'en_US',
            LanguageLocaleKey = 'en_US'
        );
        Database.insert(user1);
    }

あったエラー

MIXED_DML_OPERATION

MIXED_DML_OPERATION:DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): CustomObject__c, original object: User:  非設定オブジェクトを更新した後の設定オブジェクト上のDML操作(またはその逆)、許可されません

System.runAs()で囲んで、非設定オブジェクトのDMLを操作を行えば、解消できる

非設定オブジェクトはAccount、Contactである

設定オブジェクトはUser、PermissionSet、PermissionSetAssignmentなど

下記は幾つ例の設定オブジェクトです: ・ObjectPermissions ・PermissionSet ・PermissionSetAssignment ・QueueSObject ・Territory ・UserTerritory ・UserRole ・User fields: UserRoleId, IsActive, ForecastEnabled, IsPortalEnabled, Username, ProfileId

設定(Setup)と非設定(non-setup)オブジェクトを1つトランザクションで同時にDML操作をかけると、このエラーが発生します。

FIELD_INTEGRITY_EXCEPTION

FIELD_INTEGRITY_EXCEPTION: role type must match user type: 外部ユーザを作成時にロールを設定したら、起こるもん

例:

   User u = new User();
    u.UserRoleId = portalRole.Id;
    u.ProfileId = profile1.Id;
    u.Username = System.now().millisecond() + 'test2@test.com';
    u.Alias = 'batman';
    u.Email='bruce.wayne@wayneenterprises.com';
    u.EmailEncodingKey='UTF-8';
    u.Firstname='Bruce';
    u.Lastname='Wayne';
    u.LanguageLocaleKey='en_US';
    u.LocaleSidKey='en_US';
    u.TimeZoneSidKey='America/Chicago';

u.UserRoleId = portalRole.Id;外部ユーザを作成時にロールを設定せんでいいやんで、設定したら、エラーになるんやで。

最後に

ソリューションとして2つです。

1:@futureメッソドの使用でMIXED_DML_OPERATION エラーを解消する

2:System.runAs()で設定オブジェクトの操作を囲んで、実行する