Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
30 kB
2
Indexable
Never
public with sharing class MergeAccountsService {
    
    static final String ACCOUNT_STATUS_DEACTIVED = 'Desativado';
    private static Map<String, Schema.RecordTypeInfo> recordTypesMap = Schema.SObjectType.Account.getRecordTypeInfosByName();
    private static Id pbShopSA = [SELECT Id FROM Account WHERE Name = 'PBSHOP S.A'].Id;
    private static String cnpjPbShopSA = [SELECT CNPJ_Sem_Formatacao__c FROM Account WHERE Name = 'PBSHOP S.A'].CNPJ_Sem_Formatacao__c;
    private static Id userPbShopIntegracao = [SELECT Id FROM User WHERE Name = 'Portobello Shop Integração'].Id;
    private static Id recTypeIdEspec = recordTypesMap.get('Especificador').getRecordTypeId();

    public static void execute(List<Account> duplicateAccounts) {

        Set<Id> accountMasterIds = new Set<Id>();
        Set<Id> duplicateAccountIds = new Set<Id>();


        for(Account duplicate: duplicateAccounts){
            accountMasterIds.add(duplicate.Golden_Record__c);
            duplicateAccountIds.add(duplicate.Id);
        }        

        List<User> usersEnabled = [SELECT Account.Id FROM User WHERE IsPortalEnabled = true AND Account.Id IN :duplicateAccountIds];
        Set<Id> accountsActiveCommunityIds = new Set<Id>();

        for(User user: usersEnabled)
            accountsActiveCommunityIds.add(user.Account.Id);

        List<Account> accountsDuplicatedEnabled = AccountSelector.selectAccountByActiveCommunity(accountsActiveCommunityIds);

        Map<Id, Account> mapAccountsMaster = createMapAccountsMaster(accountMasterIds);

        Map<Id, List<ContactPointPhone>> mapDuplicateAccountIdListContatctPointPhone = createContactPointPhoneMapByAccountId(duplicateAccountIds);

        Map<Id, List<ContactPointEmail>> mapDuplicateAccountIdListContatctPointEmail = createContactPointEmailMapByAccountId(duplicateAccountIds);

        Set<Id> masterAndDuplicateAccountIds = new Set<Id>(accountMasterIds);
        masterAndDuplicateAccountIds.addAll(duplicateAccountIds);

        List<Account> masterAndDuplicateAccounts = new List<Account>(duplicateAccounts);
        masterAndDuplicateAccounts.addAll(mapAccountsMaster.values());

        Map<Id, List<AccountContactRelation>> mapAccountContact = getAccountContactRelationMap(duplicateAccounts);
        Map<Id, List<Contact>> mapContacts = getContactRelatedToAccounts(duplicateAccounts);

        deleteAccountContactRelation(mapContacts, mapAccountContact, masterAndDuplicateAccounts);

        Map<Id, List<Account>> mapDuplicates = createMapDuplicates(duplicateAccounts);
        Map<Id, Account> mapStores = getStoresForMerge(masterAndDuplicateAccounts);

        if (!accountsDuplicatedEnabled.isEmpty())
              changeAccountMaster(mapAccountsMaster,mapDuplicates,accountsDuplicatedEnabled);

        Map<String, AccountLoja__c> accountStores = createAccountStores(mapAccountsMaster.values(), mapDuplicates, mapStores);
        List<AccountEscritorio__c> accountOffices = createAccountOffices(mapAccountsMaster.values(), mapDuplicates);

        if (!accountOffices.isEmpty())
            insert accountOffices;

       if (!accountStores.isEmpty()){
            SkipTrigger.setDoesNotRunTrigger();
            upsert accountStores.values() External_Id__c;
            SkipTrigger.setRunTrigger();
        }

        List<Order> orders = OrderSelector.selectOrdersByAccountId(masterAndDuplicateAccountIds);
        Map<Id, List<Order>> mapOrdersByAccountId = createOrdersMapByAccountId(orders);

        mergeAccounts(mapAccountsMaster.values(),
            mapDuplicates,
            mapOrdersByAccountId,
            mapDuplicateAccountIdListContatctPointPhone,
            mapDuplicateAccountIdListContatctPointEmail);

        List<ContactPointPhone> phones = new List<ContactPointPhone>();
        for(List<ContactPointPhone> phoneList: mapDuplicateAccountIdListContatctPointPhone.values())
            for(ContactPointPhone phone: phoneList)
                phones.add(phone);


        List<ContactPointEmail> emails = new List<ContactPointEmail>();
        for(List<ContactPointEmail> emailList: mapDuplicateAccountIdListContatctPointEmail.values())
            for(ContactPointEmail email: emailList)
                emails.add(email);

        if (!phones.isEmpty()) {
            SkipTrigger.setDoesNotRunTrigger();
            upsert phones;
            SkipTrigger.setRunTrigger();
        }
        if (!emails.isEmpty()) {
            SkipTrigger.setDoesNotRunTrigger();
            upsert emails;
            SkipTrigger.setRunTrigger();
        }
        
    }

    public static void mergeAccountFields(
        Account masterAccount,
        List<Account> accountsToMerge,
        Map<Id, List<Order>> orders,
        Map<Id, List<ContactPointPhone>> mapDuplicateAccountIdListContatctPointPhone,
        Map<Id, List<ContactPointEmail>> mapDuplicateAccountIdListContatctPointEmail
        ) {
        System.debug('Merging Account Fields');

        if (accountsToMerge.isEmpty())
            return;

        List<Account> allAccounts = new List<Account>(accountsToMerge);

        allAccounts.add(masterAccount);

        for (Account dupAccount : allAccounts) {
            
            mergeDadosPessoaisFields(masterAccount, dupAccount, orders);
            
            mergeTelefoneFields(masterAccount, dupAccount, mapDuplicateAccountIdListContatctPointPhone);
            
            mergeEmailFields(masterAccount, dupAccount, mapDuplicateAccountIdListContatctPointEmail);

            // Código comentado pois não será necessário alterar após a demanda de múltiplos endereços
            // mergeEnderecoFields(masterAccount, dupAccount);
            mergeDadosBancariosFields(masterAccount, dupAccount);
        }
    }

    public static void databaseMerge(Account masterAccount, List<Account> duplicates) {
        System.debug('Merging In Database Account');
        Account updatedMasterAccount = removerCamposDaContaMestre(masterAccount);
        updatedMasterAccount.loja__c = pbShopSA;
        updatedMasterAccount.cnpj_loja__c = cnpjPbShopSA;
        updatedMasterAccount.OwnerId = userPbShopIntegracao;
        if(updatedMasterAccount.External_Id__c != null){
            List<String> cliCodLinx = updatedMasterAccount.External_Id__c.split('|');
            updatedMasterAccount.External_Id__c = String.format('{0}|{1}',new List<String>{cliCodLinx[0], cnpjPbShopSA});
        }


        List<Account> duplicatesVerified = new List<Account>();
        for(Account duplicate: duplicates)
            if (masterAccount.RecordTypeId == duplicate.RecordTypeId)
                duplicatesVerified.add(duplicate);

        if (!duplicatesVerified.isEmpty()){
            SkipTrigger.setDoesNotRunTrigger();
            Database.MergeResult[] results = Database.merge(updatedMasterAccount, duplicatesVerified, false);
            SkipTrigger.setRunTrigger();
    
            for (Database.MergeResult result : results) {
                if (result.isSuccess()) {
                    System.debug('Master record ID: ' + result.getId());
                    System.debug('IDs of merged records: ' + result.getMergedRecordIds());
                    System.debug('Reparented record ID: ' + result.getUpdatedRelatedIds());
                } else {
                    for (Database.Error err : result.getErrors()) {
                        System.debug('Error merging accounts');
                        System.debug(err.getMessage());
                    }
                }
            }
        } else {
            System.debug('Não foi encontrada nenhum conta duplicada possível de ser mergeada!');
        }

        
    }

    public static Set<ID> appendList(ID recordId, Set<ID> recordIdSet) {
        if (!String.isBlank(recordId)) {
            recordIdSet.add(recordId);
        }

        return recordIdSet;
    }

    public static Boolean isValidDate(Date dateValue) {
        if (dateValue == null || Date.today().year() - dateValue.year() > 100)
            return false;

        return true;
    }

    private static Map<Id, Account> createMapAccountsMaster(Set<Id> masterIds){
        Map<Id, Account> mapMaster = new Map<Id, Account>();

        List<Account> accounts = AccountSelector.selectAccountFromMergeById(masterIds);

        for(Account account: accounts)
            mapMaster.put(account.Id, account);
        

        return mapMaster;
    }

    private static Map<Id, List<Contact>> getContactRelatedToAccounts(
        List<Account> duplicates
    ) {
        Map<Id, List<Contact>> contactsMap = new Map<Id, List<Contact>>();

        Set<Id> accountIds = filterAccountIdsFromDuplicateAccounts(duplicates);
        List<Contact> contactsRelatedToAccounts = MergeAccountsSelector.selectContactsByAccountId(accountIds);
        
        for (Contact contato : contactsRelatedToAccounts) {
            if (!contactsMap.containsKey(contato.AccountId)) 
                contactsMap.put(contato.AccountId, new List<Contact>());
            
            contactsMap.get(contato.AccountId).add(contato);
        }
        
        return contactsMap;
    }

    private static Set<Id> filterAccountIdsFromDuplicateAccounts(
        List<Account> duplicates
    ) {
        Set<Id> accountIds = new Set<Id>();

        for (Account duplicate : duplicates)
            accountIds.add(duplicate.Id);
        
        return accountIds;
    }

    private static void mergeTelefoneFields(
        Account masterAccount,
        Account dupAccount,
        Map<Id, List<ContactPointPhone>> mapDuplicateAccountIdListContatctPointPhone
        ) {
        if (
            String.isBlank(masterAccount.Celular__c) &&
            !String.isBlank(dupAccount.Celular__c) &&
            StringUtils.validatePhone(dupAccount.Celular__c)
        ) {
            masterAccount.Celular__c = StringUtils.noSpecialChar(dupAccount.Celular__c);
        }

        if (
            String.isBlank(masterAccount.Telefone_Comercial__c) &&
            !String.isBlank(dupAccount.Telefone_Comercial__c) &&
            StringUtils.validatePhone(dupAccount.Telefone_Comercial__c)
        ) {
            masterAccount.Telefone_Comercial__c = StringUtils.noSpecialChar(
                dupAccount.Telefone_Comercial__c
            );
        }

        if(masterAccount.RecordTypeId == dupAccount.RecordTypeId)
            if(!mapDuplicateAccountIdListContatctPointPhone.values().isEmpty()){
                if (mapDuplicateAccountIdListContatctPointPhone.get(dupAccount.Id) != null){
                    List<ContactPointPhone> dupAccountContactPointPhones = mapDuplicateAccountIdListContatctPointPhone.get(dupAccount.Id);
                    for (ContactPointPhone contactPointPhone : dupAccountContactPointPhones) 
                        if (StringUtils.validatePhone(contactPointPhone.telephonenumber)) 
                            contactPointPhone.ParentId = masterAccount.Id;
                }
            }
    }

    private static void mergeEmailFields(
        Account masterAccount,
        Account dupAccount,
        Map<Id, List<ContactPointEmail>> mapDuplicateAccountIdListContatctPointEmail
        ) {
        if (
            String.isBlank(masterAccount.Email__c) &&
            !String.isBlank(dupAccount.Email__c) &&
            StringUtils.isValidEmail(dupAccount.Email__c)
        ) {
            masterAccount.Email__c = dupAccount.Email__c;
        }

        if(masterAccount.RecordTypeId == dupAccount.RecordTypeId)
            if(!mapDuplicateAccountIdListContatctPointEmail.values().isEmpty()){
                if (mapDuplicateAccountIdListContatctPointEmail.get(dupAccount.Id) != null){
                    List<ContactPointEmail> dupAccountContactPointEmail = mapDuplicateAccountIdListContatctPointEmail.get(dupAccount.Id);
                    for (ContactPointEmail contactPointEmail : dupAccountContactPointEmail)
                        if (StringUtils.isValidEmail(contactPointEmail.EmailAddress)) 
                            contactPointEmail.ParentId = masterAccount.Id;
                }
            }
    }

    private static void mergeDadosBancariosFields(Account masterAccount, Account dupAccount) {
        if (
            String.isBlank(masterAccount.Conta_bancaria__c) &&
            !String.isBlank(dupAccount.Conta_bancaria__c)
        ) {
            masterAccount.Conta_bancaria__c = dupAccount.Conta_bancaria__c;
        }

        if (
            String.isBlank(masterAccount.Agencia_bancaria__c) &&
            !String.isBlank(dupAccount.Agencia_bancaria__c)
        ) {
            masterAccount.Agencia_bancaria__c = dupAccount.Agencia_bancaria__c;
        }

        if (String.isBlank(masterAccount.Banco__c) && !String.isBlank(dupAccount.Banco__c)) {
            masterAccount.Banco__c = dupAccount.Banco__c;
        }

        if (
            String.isBlank(masterAccount.Tipo_conta_bancaria__c) &&
            !String.isBlank(dupAccount.Tipo_conta_bancaria__c)
        ) {
            masterAccount.Tipo_conta_bancaria__c = dupAccount.Tipo_conta_bancaria__c;
        }

        if (
            String.isBlank(masterAccount.Favorecido_da_conta_bancaria__c) &&
            !String.isBlank(dupAccount.Favorecido_da_conta_bancaria__c)
        ) {
            masterAccount.Favorecido_da_conta_bancaria__c = dupAccount.Favorecido_da_conta_bancaria__c;
        }
    }

    private static Map<Id, List<AccountContactRelation>> getAccountContactRelationMap(
        List<Account> duplicates
    ) {
        Map<Id, List<AccountContactRelation>> accountContactRelationMap = new Map<Id, List<AccountContactRelation>>();

        if (duplicates == null || duplicates.isEmpty())
            return accountContactRelationMap;

        Set<Id> accountIds = filterAccountIdsFromDuplicateAccounts(duplicates);
        List<AccountContactRelation> accountContactList = MergeAccountsSelector.selectAccountContactRelationByAccountId(
            accountIds
        );
      
        for (AccountContactRelation accountContact : accountContactList) {
            if (!accountContactRelationMap.containsKey(accountContact.ContactId))
                accountContactRelationMap.put(
                    accountContact.ContactId, 
                    new List<AccountContactRelation>()
                );
            
            accountContactRelationMap.get(accountContact.ContactId).add(accountContact);
        }
        
        return accountContactRelationMap;
    }

    private static Map<String, AccountLoja__c> createAccountLojaRelationships(
        Account account,
        Account duplicada,
        Set<Account> lojas,
        Map<String, AccountLoja__c> accountStores
    ) {

        for (Account loja : lojas) {
            AccountLoja__c accLoja = AccountLojaService.criarAccountLoja(account, duplicada,loja);


            if (accLoja != null && !accountStores.containsKey(accLoja.External_Id__c)) {
                accountStores.put(accLoja.External_Id__c, accLoja);
            }
        }
		
        return accountStores;
    }

    private static void mergeDadosPessoaisFields(Account masterAccount, Account dupAccount, Map<Id, List<Order>> orders) {
        if (AccountLojaService.verificarTipoRegistroCliente(masterAccount) && 
            AccountLojaService.verificarTipoRegistroCliente(dupAccount)) {

            if (masterAccount.CPF__c == null && dupAccount.CPF__c != null){
                masterAccount.CPF__c = dupAccount.CPF__c;
            }
            
            if (masterAccount.CPF__c != dupAccount.CPF__c) {
				List<Order> pedidosMaster = orders.get(masterAccount.Id);
                List<Order> pedidosDup = orders.get(dupAccount.Id);
                
                if (pedidosDup != null && !pedidosDup.isEmpty() && (pedidosMaster == null || pedidosMaster.isEmpty()))
                    masterAccount.CPF__c = dupAccount.CPF__c;
            }
        }

        if (AccountLojaService.verificarTipoRegistroClientePJ(masterAccount) && 
            AccountLojaService.verificarTipoRegistroClientePJ(dupAccount)) {
            if (masterAccount.CNPJ__c == null && dupAccount.CNPJ__c != null){
                masterAccount.CNPJ__c = dupAccount.CNPJ__c;
            }

           	if (masterAccount.CNPJ__c != dupAccount.CNPJ__c)  {
            	List<Order> pedidosMaster = orders.get(masterAccount.Id);
                List<Order> pedidosDup = orders.get(dupAccount.Id);
                
                if (pedidosDup != null && !pedidosDup.isEmpty() && (pedidosMaster == null || pedidosMaster.isEmpty())){
                    masterAccount.CNPJ__c = dupAccount.CNPJ__c;
                }
            }
        }

        if (
            masterAccount.Data_Nascimento__c == null &&
            dupAccount.Data_Nascimento__c != null &&
            isValidDate(dupAccount.Data_Nascimento__c)
        ) {
            masterAccount.Data_Nascimento__c = dupAccount.Data_Nascimento__c;
        }
    }

    private static Account removerCamposDaContaMestre(Account conta) {
        Account contaAtualizada;
        Map<String, Object> camposContaMap = (Map<String, Object>) JSON.deserializeUntyped( JSON.serialize(conta) );

        if (conta.RecordTypeId == recTypeIdEspec){
            camposContaMap.remove('Name');
        }
        camposContaMap.remove('Escritorio_Especificador__r');
        camposContaMap.remove('Owner');
        camposContaMap.remove('Loja__r');
        camposContaMap.remove('Golden_Record__r');
        camposContaMap.remove('RecordType');
        
        contaAtualizada = (Account) JSON.deserialize(JSON.serialize(camposContaMap), Account.class);

        return contaAtualizada;
    }

    private static List<AccountEscritorio__c> createAccountOffices(
        List<Account> masters, 
        Map<Id,List<Account>> duplicates) {
            List<AccountEscritorio__c> accountOffices = new List<AccountEscritorio__c>();

        if (masters == null)
            return new List<AccountEscritorio__c>();

        for (Account master: masters){
            Boolean masterPossuiEscritorio = master.Escritorio_Especificador__c != null;

            if (masterPossuiEscritorio){
                accountOffices.addAll(
                    createAccountOfficeRelationships(
                        master, 
                        new Set<Id> { master.Escritorio_Especificador__c })
                );
            }

            if (duplicates.get(master.Id) == null)
                continue;
    
            for (Account conta: duplicates.get(master.Id)) {
                Boolean duplicadaPossuiEscritorio = conta.Escritorio_Especificador__c != null;
    
                if (duplicadaPossuiEscritorio)
                    accountOffices.addAll(
                        createAccountOfficeRelationships(
                            master, 
                            new Set<Id> { conta.Escritorio_Especificador__c })
                    );
            }
        }
        return accountOffices;
    }

    private static Map<String, AccountLoja__c> createAccountStores(
        List<Account> masters, 
        Map<Id, List<Account>> duplicates,
        Map<Id, Account> storeMap) {
        
        Map<String, AccountLoja__c> accountStores = new Map<String, AccountLoja__c>();
        for(Account master: masters){
            Boolean masterPossuiLoja = master.loja__c != null;
        
            if (masterPossuiLoja)
                createAccountLojaRelationships(
                    master,
                    null,
                    new Set<Account> { storeMap.get(master.loja__c) },
                    accountStores);

            if(duplicates.get(master.Id) == null)
                continue;

            for (Account conta: duplicates.get(master.Id)) {
                Boolean duplicadaPossuiLoja = conta.Loja__c != null;
    
                if (duplicadaPossuiLoja)
                    createAccountLojaRelationships(
                        master,
                        conta,
                        new Set<Account> { storeMap.get(conta.Loja__c) },
                        accountStores);
                
            }
        }
        return accountStores;
    }

    private static List<AccountEscritorio__c> createAccountOfficeRelationships(
        Account account,
        Set<Id> escritoriosId
    ) {
        List<AccountEscritorio__c> escritorios = new List<AccountEscritorio__c>();

        for (ID escritorioId : escritoriosId) {
            escritorios.add(
                new AccountEscritorio__c(
                    AccountId__c = account.Id,
                    AccountEscritorioId__c = escritorioId
                )
            );
        }

        return escritorios;
    }

    private static Map<Id, List<Order>> createOrdersMapByAccountId(List<Order> orders){
        Map<Id, List<Order>> accountsWithOrders = new Map<Id, List<Order>>();
        for(Order order: orders){
            if(!accountsWithOrders.containsKey(order.AccountId))
                accountsWithOrders.put(order.AccountId, new List<Order>());
            accountsWithOrders.get(order.AccountId).add(order);
        }
        return accountsWithOrders;
    }

    private static Map<Id, List<ContactPointPhone>> createContactPointPhoneMapByAccountId(Set<Id> parentId){

        Map<Id, List<ContactPointPhone>> mapIdListContatctPointPhone = new Map<Id,List<ContactPointPhone>>();
        List<ContactPointPhone> listContactPointPhone = ContactPointPhoneSelector.selectByParentId(parentId);
        for (ContactPointPhone contactPointPhone : listContactPointPhone) {
            if (!mapIdListContatctPointPhone.containsKey(contactPointPhone.ParentId))
                mapIdListContatctPointPhone.put(contactPointPhone.parentId, new List<ContactPointPhone>{contactPointPhone});
            else
                mapIdListContatctPointPhone.get(contactPointPhone.parentId).add(contactPointPhone);
            
        }
        return mapIdListContatctPointPhone;
    }

    private static Map<Id, List<ContactPointEmail>> createContactPointEmailMapByAccountId(Set<Id> parentId){

        Map<Id, List<ContactPointEmail>> mapIdListContatctPointEmail = 
        new Map<Id,List<ContactPointEmail>>();
        List<ContactPointEmail> listContactPointEmail= ContactPointEmailSelector.selectByParentId(parentId);
        for (ContactPointEmail contactPointEmail : listContactPointEmail) {
            if (!mapIdListContatctPointEmail.containsKey(contactPointEmail.ParentId)) 
                mapIdListContatctPointEmail.put(contactPointEmail.parentId, new List<ContactPointEmail>{contactPointEmail});
            else 
                mapIdListContatctPointEmail.get(contactPointEmail.parentId).add(contactPointEmail);
            
        }
        return mapIdListContatctPointEmail;
    }

    private static Map<Id, List<Account>> createMapDuplicates(List<Account> duplicates) {
        Map<Id, List<Account>> mapDuplicate = new Map<Id,List<Account>>();

        for (Account account: duplicates) {
            if (!mapDuplicate.containsKey(account.Golden_Record__c))
                mapDuplicate.put(account.Golden_Record__c, new List<account>());
            
            mapDuplicate.get(account.Golden_Record__c).add(account);
        }

        return mapDuplicate;
    }

    private static Map<Id, Account> getStoresForMerge(List<Account> accounts) {
        if (accounts == null || accounts.isEmpty())
            return new Map<Id, Account>();

        Set<Id> storeIds = filterStoreIdsFromAccounts(accounts);
        return MergeAccountsSelector.selectStoresByAccountId(storeIds);
    }

    private static Set<Id> filterStoreIdsFromAccounts(List<Account> accounts) {
        Set<Id> storeIds = new Set<Id>();
        
        if (accounts == null)
            return storeIds;

        for (Account account : accounts)
            if (!String.isBlank(account.Loja__c))
                storeIds.add(account.Loja__c);

        return storeIds;
    }

    private static void deleteAccountContactRelation(
        Map<Id, List<Contact>> contactsMap,
        Map<Id, List<AccountContactRelation>> accountContactMap,
        List<Account> accounts
    ) {
        List<AccountContactRelation> accountContactRelationToDelete = new List<AccountContactRelation>();
        for (Account account: accounts) {
            List<Contact> contactsRelated = contactsMap.get(account.Id);
    
            if (contactsRelated != null && !contactsRelated.isEmpty()) {
                 for (Contact contact : contactsRelated) {
                    List<AccountContactRelation> accountContactRelations = accountContactMap.get(contact.Id);    
                
                    if (
                        accountContactRelations != null && 
                        !accountContactRelations.isEmpty() && 
                        accountContactRelations.size() > 1
                    ) {
                        for (AccountContactRelation accountContact : accountContactRelations) {
                            if (!accountContact.IsDirect)
                                accountContactRelationToDelete.add(accountContact);
                        }
                    }
                }
            }
        }
        
        if (!accountContactRelationToDelete.isEmpty())
            delete accountContactRelationToDelete;
    }

    private static void changeAccountMaster(
        Map<Id, Account> mapAccountsMaster,
        Map<Id, List<Account>> mapDuplicates,
        List<Account> duplicadasEnableCommunity
    ) {

        for(Account duplicada: duplicadasEnableCommunity)
            if (mapAccountsMaster.containsKey(duplicada.Golden_Record__c)){

                Account account = mapAccountsMaster.get(duplicada.Golden_Record__c);
                account.Golden_Record__c = duplicada.Id;

                duplicada.Status_Deduplicacao__c = account.Status_Deduplicacao__c;
                duplicada.Preenchimento_Deduplicacao__c = account.Preenchimento_Deduplicacao__c;
                duplicada.Campos_Preenchidos_Deduplicacao__c = account.Campos_Preenchidos_Deduplicacao__c;
                duplicada.Metodo_Deduplicacao__c = account.Metodo_Deduplicacao__c;
                duplicada.Data_Ultima_Deduplicacao__c = account.Data_Ultima_Deduplicacao__c;

                mapAccountsMaster.remove(duplicada.Golden_Record__c);
                mapAccountsMaster.put(duplicada.Id,duplicada);

                List<Account> accountsDuplicates = mapDuplicates.get(duplicada.Golden_Record__c);
                accountsDuplicates.add(account);

                mapDuplicates.remove(duplicada.Golden_Record__c);
                for(Account accountDuplicate : accountsDuplicates){
                    if (!mapDuplicates.containsKey(duplicada.Id))
                        mapDuplicates.put(duplicada.Id, new List<Account>());

                    if (accountDuplicate.Id == duplicada.Id)
                        continue;

                    mapDuplicates.get(duplicada.Id).add(accountDuplicate);
                }
                duplicada.Golden_Record__c = null;
            }

    }

    private static void mergeAccounts(
        List<Account> masters,
        Map<Id, List<Account>> mapDuplicateAccounts,
        Map<Id, List<Order>> mapOrdersByAccountId,
        Map<Id, List<ContactPointPhone>> mapDuplicateAccountIdListContatctPointPhone,
        Map<Id, List<ContactPointEmail>> mapDuplicateAccountIdListContatctPointEmail
        ) {
        for (Account master: masters) {
            Boolean contaPossuiDuplicada = mapDuplicateAccounts.containsKey(master.Id);

            if (contaPossuiDuplicada) {
                List<Account> duplicateAccounts = mapDuplicateAccounts.get(master.Id);
                List<Account> accountsToMerge = new List<Account>();
                Boolean manyAccounts = duplicateAccounts.size() > 2;


                for (Integer i = 0; i <= duplicateAccounts.size(); i++) {
                    accountsToMerge.add(duplicateAccounts[0]);
                    duplicateAccounts.remove(0);

                    Boolean mergeLimitReached = accountsToMerge.size() == 2;

                    if (mergeLimitReached) {
                        mergeAccountFields(master, accountsToMerge, mapOrdersByAccountId, mapDuplicateAccountIdListContatctPointPhone, mapDuplicateAccountIdListContatctPointEmail);
                        databaseMerge(master, accountsToMerge);
                        accountsToMerge.clear();
                    }

                    Boolean lastElement = duplicateAccounts.size() == 0 && manyAccounts && !accountsToMerge.isEmpty();

                    if (lastElement) {
                        mergeAccountFields(master, accountsToMerge, mapOrdersByAccountId, mapDuplicateAccountIdListContatctPointPhone, mapDuplicateAccountIdListContatctPointEmail);
                        databaseMerge(master, accountsToMerge);
                    }

                    Boolean onlyDuplicate = duplicateAccounts.size() == 0 && !manyAccounts && !accountsToMerge.isEmpty();

                    if (onlyDuplicate){
                        mergeAccountFields(master, accountsToMerge, mapOrdersByAccountId, mapDuplicateAccountIdListContatctPointPhone, mapDuplicateAccountIdListContatctPointEmail);
                        databaseMerge(master, accountsToMerge);
                    }

                    i = 0;
            
                }
            }
        }
    }
}
Leave a Comment