Нужна помощь по написанию триггера создания контакта

Добрый день. Я имею модальное окно для создания контакта с полями имя, фамилия, номер телефона, емаил и аккаунт, все поля сделаны обычными инпутами. Мне требуется создать триггер при создании контакта в письменном виде указывается имя аккаунта без всяких лукапов, если он есть - триггер привязывает к нему, если нет - триггер создает новый аккаунт и привязывает к нему. Подскажите пожалуйста как это сделать.

Вот пример моего кода модалки:

Component:

<aura:component description="modalCreateContact" controller="contactDataTableController">

    <aura:attribute name="accForm" type="Account" default="{'sobjectType' : 'Account', 'Name': ''}"/>
    <aura:attribute name="conForm" type="Contact" default="{'sobjectType' : 'Contact', 'FirstName': '',
                    'LastName': '',
                    'Email': '',
                    'Phone': ''}"/>


    <aura:method name="submitDR" action="{!c.openModal}">
        <aura:attribute name="showModalCreateContact" type="string"/>
        <aura:attribute name="darkModalBackdrop" type="String"/>
    </aura:method>

    <section role="dialog" class="slds-modal slds-fade" aura:id="modalCreateContact">
        <div class="slds-modal__container" style="width: 70vh;">
            <div class="slds-modal__header">
                <h2 class="slds-text-heading--medium">NEW CONTACT</h2>
                <lightning:buttonIcon iconName="utility:close"
                                      onclick="{!c.closeModal}"
                                      alternativeText="close"
                                      variant="bare-inverse"
                                      class="slds-modal__close"/>
            </div>
            <div class="slds-modal__content slds-p-around--medium">
                <div class="form-element__group">
                    <div class="slds-form-element__row">
                        <div class="slds-form-element ">
                            <lightning:input label="First Name" name="FirstName" value="{!v.conForm.FirstName}"/>
                        </div>
                        <div class="slds-form-element">
                            <lightning:input label="Last Name" name="LastName" required="true"
                                             value="{!v.conForm.LastName}"/>
                        </div>
                        <div class="slds-form-element">
                            <lightning:input label="Email" name="Email" required="true" value="{!v.conForm.Email}"/>
                        </div>
                        <div class="slds-form-element">
                            <lightning:input label="Mobile Phone" name="Mobile Phone" value="{!v.conForm.Phone}"/>
                        </div>
                        <div class="slds-form-element">
                            <lightning:input label="Account" name="Account" value="{!v.accForm.Name}"/>
                        </div>
                    </div>
                </div>
            </div>
            <div class="slds-modal__footer">
                <lightning:button label="Save" onclick="{!c.saveModal}"/>
                <lightning:button label="Close" onclick="{!c.closeModal}"/>
            </div>
        </div>
    </section>
    <div aura:id="modalBackdrop" class="slds-backdrop"></div>
</aura:component>

Controller

({
    openModal: function (component, event, helper) {
        var modalFade = component.find('modalCreateContact');
        var modalBackdrop = component.find('modalBackdrop');

        $A.util.addClass(modalFade, 'slds-fade-in-open');
        $A.util.addClass(modalBackdrop, 'slds-backdrop_open');
    },

    closeModal: function (component, event, helper) {
        var modalFade = component.find('modalCreateContact');
        var modalBackdrop = component.find('modalBackdrop');

        $A.util.removeClass(modalFade, 'slds-fade-in-open');
        $A.util.removeClass(modalBackdrop, 'slds-backdrop_open');
    },

    saveModal: function (component, event, helper) {

        var contactFormSave = component.get("v.conForm", "v.accForm");
        var action = component.get("c.saveNewContact");
        action.setParams({contactForm: contactFormSave});
        action.setCallback(this, function (response) {

            var state = response.getState();
            if (state === "SUCCESS") {

                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Success!",
                    "message": "Contact create",
                    "type ": "success"
                });

                toastEvent.fire();
                $A.get('e.force:refreshView').fire();
                var modalFade = component.find('modalCreateContact');
                var modalBackdrop = component.find('modalBackdrop');
                $A.util.removeClass(modalFade, 'slds-fade-in-open');
                $A.util.removeClass(modalBackdrop, 'slds-backdrop_open');


            } else if (state === "ERROR") {

                var errorMsg = '';
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        errorMsg = errors[0].message;
                    }
                }

                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({
                    "title": "Error!",
                    "message": "Contact not created",
                    "type ": "error"
                });

                toastEvent.fire();
            }
        });
        $A.enqueueAction(action);
    },

});

Apex controller:

    @AuraEnabled
    public static Contact saveNewContact(Contact contactForm) {

        upsert contactForm;
        return contactForm;
    }

@AuraEnabled
public static void saveNewContact(Contact contactFormSave, Account accountFormSave) {

    List<Account> acc = [
        SELECT Id
        FROM Account
        WHERE LastName = :accountFormSave.LastName AND FirstName = :accountFormSave.FirstName
        LIMIT 1
    ];

    if (ListUtil.isNullOrEmpty(acc)) {
        //если аккаунт уже существует
        contactFormSave.AccountId = accountFormSave.Id; 
        Database.update(contactFormSave, true);
    } else {
        //если аккаунта нет
        Database.insert(accountFormSave, true);
        contact.AccountId = accountFormSave.Id;
        Database.update(contactFormSave, true);
    }
}

public static Boolean isNullOrEmpty(final List<Object> objects) {
    return objects == null || objects.isEmpty();
}

//// JavaScript в методе saveModal

saveModal: function (component, event,helper) {
    const contactFormSave = component.get("v.conForm", "v.accForm");
    const action = component.get("c.saveNewContact");
    action.setParams({contactForm: contactFormSave, accountForm: accountFormSave});
    action.setCallback(this, function (response) {

все var нужно поменять на const и let. var старый вариант javascript

Метод isNullOrEmpty можно поместить в класс Util или ListUtil и каждый раз вызывать в коде, где нужна проверка листа на ноль или наполненость.

Тут немного возникнет нюанс, ибо LastName и FirstName в стандартном объекте Account у нас по моему нет, там только Name, но то такое, потом в строке:

public static void saveNewContact(Contact **contactFormSave**, Account **accountFormSave**)

contactFormSave и accountFormSave не используется в методе же у нас получается.

Вот этот метод поместил в ListUtil с ним всё вроде ок:

public static Boolean isNullOrEmpty(final List<Object> objects) {
    return objects == null || objects.isEmpty();
}

Но на методе saveNewContact бьёт ошибки:

Error:(29, 29) Invalid bind expression type of Schema.SObjectField for column of type String
Error:(38, 21) A value cannot be stored to AccountId in type Contact
Error:(39, 29) Variable does not exist: contact
Error:(42, 29) Variable does not exist: account
Error:(43, 21) A value cannot be stored to AccountId in type Contact
Error:(44, 29) Variable does not exist: contact

Вот по этому я думаю, что надо всё же триггер использовать, вместо класса Apex

И да в методе JS я добавил строку const accountFormSave = component.get(“v.accForm”) ибо у нас получалось в сеттере, что accountFormSave неопределённый остался

сейчас поправлю код, я исправил уже на лету названия констант в javascript и потом еще и в классе. Поэтому их не определяет. Тригер здесь не нужен

Исправил в добавленном коде. Если у вас какие то поля не используются, ищите аккаунт по полям, которые используются. По имени или email. Там по ходу разберётесь

Переделал, но не работает, тут уже просто error creation contact. Компоненту я не трогал, может и там где косяк. В контроллере JS вот

saveModal: function (component, event, helper) {

        const contactFormSave = component.get("v.conForm");
        const accountFormSave = component.get("v.accForm");
        const action = component.get("c.saveNewContact");
        action.setParams({contactForm: contactFormSave, accountForm: accountFormSave});
        action.setCallback(this, function (response) {

В контроллере Apex вот:

    @AuraEnabled
    public static void saveNewContact(Contact contactForm, Account accountForm) {

        List<Account> acc = [
                SELECT Id, Name
                FROM Account
                WHERE Name = :accountForm.Name
                LIMIT 1
        ];

        if (ListUtil.isNullOrEmpty(acc)) {
            //если аккаунт уже существует
            contactForm.AccountId = accountForm.Id;
            Database.update(contactForm, true);
        } else {
            //если аккаунта нет
            Database.insert(accountForm, true);
            contactForm.AccountId = accountForm.Id;
            Database.update(contactForm, true);
        }
    }

Поменял contactFormSave и accountFormSave, на contactForm и accountForm, ибо у нас же в сет парамсе идёт определение для contactFormSave и accountFormSave или я не прав? Но в принципе, что так как я сделал, что как вы написали не хочет просто контакт создавать и всё. По ходу надо console.log применять уже))

Просмотрите, что в контакте стоит. Может отсутствует обязательное поле Name. Короче нужно посмотреть, что приходит из компоненты.

На счет дибагинга. То лучше сразу написать тестовый класс к апексу, включить дебаг и посмотреть пошагово, что стоит в переменных.
Или использовать debug в апексе
System.debug(JSON.serializePretty(contact));
а в javascript console.log(’’ + JSON.stringify(contact));

тогда вам будут показываться объекты целиком.

в какой среде разработки пишете код ?

На WebStorm через IlluminatedCloud пишу.
Заметил ща одно, если Database.update(contactForm, true); поменять на Database.upsert(contactForm, true);, то контакт сохраняется и если существующий аккаунт написать, то он его применяет, а если новый аккаунт вписываешь, то он его просто не создаёт. Ща что-то ещё подумаю

Ну и посидев поразбиравшись между делом, то получается что код, после else не выполняется, ибо скорее всего что-то с условием не так. И вот всё равно интересно, как бы это выглядело в виде триггера)

Вот сдался вам этот триггер.

  1. У вас передаются параметры из компоненты для контакта и аккаунта.
  2. из этих данных вы уже лепите объекты контакт и аккаунт
  3. И сохраняете эти обьекты или делаете update этих обьектов.

Как вы эти данные собираетесь в триггер передавать ?

Триггер реагирует на создание, изменение, удаление обьекта.

Т.е у вас сохраняется объект контакт.
Вы его получаете в триггере и можете с ним работать.
Можете посмотреть так же, есть ли к контакту аккаунт.

Но вам же всё равно нужно для начала сохранить, изменить объект, чтобы триггер сработал.

Так лучше же просто взять и сохранить прямо в методе класаа @auraenabled. И все дела.

У вас teams есть ?