• Asel Vazir 1
  • NEWBIE
  • 10 Points
  • Member since 2020

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 10
    Questions
  • 4
    Replies
Please give me an example of the trigger that checks if the attachment is uploaded when the picklist value on the custom object is "Yes". 
Need help to resolve the issue. The trigger doesn't create a new record with updated fields when checkbox on Opp object is true. Also, the new record on custom object should show the Amount resulted due to subtraction on Opp fields.
 
public static void createGLTransaction(List<Opportunity> oppList2) {

    List<Id> GLIds = new List<Id>();

    for (Opportunity opp : oppList2) {
        if (opp.Fee_Applied__c == true) {
            GLIds.add(opp.Id);
        }

        Map<Id, GL_Transaction__c> mapGl = new Map<Id, GL_Transaction__c>
                ([SELECT Id, Transaction__c, Amount__c
                  FROM GL_Transaction__c
                  WHERE Id IN : GLIds]);

        List<GL_Transaction__c> glTransactions = new List<GL_Transaction__c>();

        for (Opportunity oppt : oppList2){
            if(oppt.Fee_Applied__c == true && mapGl.containsKey(oppt.Id)){
                GL_Transaction__c gl = mapGl.get(oppt.Id);
                gl.Amount__c = oppt.Amount_Received__c -= oppt.Exchange_Fee__c;
                gl.Transaction__c = 'Phase One Exchange Fee';
                glTransactions.add(gl);
            }
           insert glTransactions;
            update glTransactions;
        }
    }
}


trigger ExchangeTriggers on Opportunity (before insert, before update, after update) {

if (Trigger.isInsert || Trigger.isUpdate){
    PrimaryEmailOnExchange.createGLTransaction(Trigger.new);
}

 
I looked for similar topics and used some best answers to modify my code, but it is still not populating the custom fields on Opportunity every time the custom fields on related list Property are entered. Please help me to resolve the issue.
Here is the class:
public with sharing class PropertyEscrowContactOnExchange {
public static void copyPropertyEscrowAddressOnExchange(List<Property__c> propList) {

    Set<String> oppIds = new Set<String>();

    for (Property__c prop : propList) {
        oppIds.add(prop.Id);
    }
    List<Opportunity> opportunities = [SELECT Id, Name, Escrow_Company__c, Escrow_Address__c, Escrow_City__c, Escrow_State__c, Escrow_Zip_Code__c
                                        FROM Opportunity WHERE Id IN : oppIds];

    Map<String, Opportunity> oppByStrings = new Map<String, Opportunity>();
    for(Opportunity o : opportunities){
        oppByStrings.put(o.Escrow_Company__c + o.Escrow_Address__c + o.Escrow_City__c + o.Escrow_State__c+ o.Escrow_Zip_Code__c, o);
    }

    for (Property__c p : propList) {
        Opportunity o = oppByStrings.get(p.Id);
        if (o == null && oppByStrings.containsKey(p.Id) && oppByStrings.get(p.Id).Properties__r.size()>0) {
            p.Escrow_Company__c = o.Escrow_Company__c;
            p.Escrow_Address__c = o.Escrow_Address__c;
            p.Escrow_City__c = o.Escrow_City__c;
            p.Escrow_State__c = o.Escrow_State__c;
            p.Escrow_Zip_Code__c = o.Escrow_Zip_Code__c;
        }
    }
}

And my trigger:
 
trigger copyPropEscrowAddressOnExchange on Property__c (after insert, after update) {
if (Trigger.isInsert || Trigger.isUpdate){
    PropertyEscrowContactOnExchange.copyPropertyEscrowAddressOnExchange(Trigger.new);
}

​​​​​​​
The below code works fine when I insert a new Contact with email. But when I update the Exchange Contact field on Opportunity it still keeps the email of the previous Contact. Please help me to resolve the issue.
 
public with sharing class PrimaryEmailOnExchange {
    public static void populatePrimaryEmailOnExchange(List<Opportunity> oppList) {

        Set<Id> conIds = new Set<Id>();

        for (Opportunity oppt : oppList) {
            if(oppt.Exchange_Contact__c != null){
                conIds.add(oppt.Exchange_Contact__c);
            }

        }

        Map<Id, Contact> mapCont = new Map<Id, Contact>([
                SELECT Id, Email FROM Contact WHERE Id IN : conIds
        ]);

        for (Opportunity oppt : oppList) {
            if (oppt.Exchange_Contact__c != null && oppt.Primary_Email__c == null) {
                    if (mapCont.containsKey(oppt.Exchange_Contact__c)) {
                        Contact c = mapCont.get(oppt.Exchange_Contact__c);
                        oppt.Primary_Email__c = c.Email;
                        oppt.ContactId = c.Id;

                    }
                }
            }
        }
    }
Here is the Trigger:
trigger populatePrimaryEmailOnExchange on Opportunity (before insert, before update, after update) {

    if (Trigger.isBefore || Trigger.isInsert || Trigger.isUpdate) {
        PrimaryEmailOnExchange.populatePrimaryEmailOnExchange(Trigger.new);
    }
}

 
Please help me to resolve my issue. I've created a trigger handler that populates the Primary_Contact__c checkbox when inserting a new Contact on the Account without contacts. But when I try to create another Contact it continues to mark it as Primary. And I need the next Contact to be inserted without populated PrimaryContact checkbox:
public with sharing class PrimaryContactOnAccount {
public static void createFirstContactAsPrimaryContact(List<Contact> newContacts) {
    List<Account> accountsWithoutContacts = [SELECT Id, Name FROM Account WHERE Id NOT IN (SELECT AccountId FROM Contact)];

    for (Contact con : newContacts) {
        for (Account act : accountsWithoutContacts) {
            con.Primary_Contact__c = true;


                }
            }
        }
 
trigger ContactTrigger on Contact (after update,before insert, before update){
        if (Trigger.isBefore && Trigger.isInsert) {
            PrimaryContactOnAccount.createFirstContactAsPrimaryContact(Trigger.new);
    }

 
Here is my method that should create another missing related opportunity if the account is updated and have only one opportunity. 
public static void missingOpp(List<Account> acctList3) {

        List<Opportunity> oppList3 = new List<Opportunity>();
        List <Account> acctsTypeProspect = new List<Account>(
        [
                SELECT Id, Name, OwnerId, Type
                FROM Account
                WHERE Type = 'Prospect' AND Id IN (SELECT AccountId FROM Opportunity) AND Id IN :acctList3
        ]);
        for (Account acct : acctsTypeProspect) {
            for (Opportunity oppt : acct.Opportunities) {
                if (oppt.Name == 'Default Residential Opp') {
                }
                Opportunity opp1 = new Opportunity();
                opp1.Name = 'Default Commercial Opp';
                opp1.AccountId = acct.Id;
                opp1.CloseDate = System.today().addMonths(1);
                opp1.StageName = 'Prospecting';
                oppList3.add(opp1);

                if (oppt.Name == 'Default Commercial Opp') {
                }
                Opportunity opp2 = new Opportunity();
                opp2.Name = 'Default Residential Opp';
                opp2.AccountId = acct.Id;
                opp2.CloseDate = System.today().addMonths(1);
                opp2.StageName = 'Prospecting';
                oppList3.add(opp2);
            }
            insert oppList3;
        }
    }

 
Help me to figure out why when I try to update the Account without Opps it doesn't create two new Opps as per below logic.
Here is my helper class
public with sharing class AccountWithTwoDefaultOpp {
    public static void addTwoDefaultOpptToAcct(List<Account> acctList) {

        List<Opportunity> oppList = new List<Opportunity>();

        for (Account acct : acctList) {

            Opportunity opp = new Opportunity();
            opp.Name = acct.Name + ' Default Residential Opp';
            opp.StageName = 'Prospecting';
            opp.CloseDate = System.today().addMonths(1);
            opp.AccountId = acct.Id;
            oppList.add(opp);

            Opportunity opp2 = new Opportunity();
            opp2.Name = acct.Name + 'Default Commercial Opp';
            opp2.StageName = 'Prospecting';
            opp2.CloseDate = System.today().addMonths(1);
            opp2.AccountId = acct.Id;
            oppList.add(opp2);
        }
        insert oppList;
    }
    public static void updateAccount(List<Account> acctList2) {

        List<Opportunity> oppList2 = new List<Opportunity>();

        Map<Id, Account> acctsTypeProspect = new Map<Id, Account>(
        [
                SELECT Id, Name, Type
                FROM Account
                WHERE Type = 'Prospect'
                AND Id NOT IN (SELECT AccountId FROM Opportunity) AND Id IN :acctList2
        ]);

        for (Account account : acctList2) {
            if(account.Type == 'Prospect'){
        }
            for (Opportunity opp : oppList2) {

                if (acctsTypeProspect.get(account.Id).Opportunities.isEmpty()) {

                    Opportunity opp1 = new Opportunity();
                    opp1.Name = 'Default Residential Opp';
                    opp1.AccountId = account.Id;
                    opp1.CloseDate = System.today().addMonths(1);
                    opp1.StageName = 'Prospecting';
                    oppList2.add(opp1);

                    Opportunity opp2 = new Opportunity();
                    opp2.Name = 'Default Commercial Opp';
                    opp2.AccountId = account.Id;
                    opp2.CloseDate = System.today().addMonths(1);
                    opp2.StageName = 'Prospecting';
                    oppList2.add(opp2);
                }

            }
            if(oppList2.size()>0){
                insert oppList2;

            }
        }

    }
}
And Trigger 
trigger AddTwoOppToNewAccount on Account (after insert, after update) {
    if (Trigger.isInsert && Trigger.isAfter){
        AccountWithTwoDefaultOpp.addTwoDefaultOpptToAcct(Trigger.new);
    }

    if  (Trigger.isUpdate) {
        AccountWithTwoDefaultOpp.updateAccount(Trigger.new);
    }
}

 
My test class covers only 76% of the trigger that creates Opportunity to the newly inserted Account. 
Here is my trigger and test class. Please help me to cover 100%.
trigger AddRelatedRecord on Account (after insert, after update) {
    if (Trigger.isInsert) {
        for (Account a : Trigger.new) {
            Opportunity opp = new Opportunity();
            opp.Name = a.Name + ' Opportunity';
            opp.StageName = 'Prospecting';
            opp.CloseDate = System.today().addMonths(1);
            opp.AccountId = a.Id;
            insert opp;

        }
    }

    if (Trigger.isUpdate) {
        List<Opportunity> oppList = new List<Opportunity>();

        List<Account> accountsWithoutOppsAndGotUpdated = [
                SELECT Id, Name
                FROM Account
                WHERE Id NOT IN (SELECT AccountId FROM Opportunity) AND Id IN :Trigger.new
        ];

        for (Account a : accountsWithoutOppsAndGotUpdated) {
            oppList.add(new Opportunity(Name = a.Name + ' Opportunity',
                    StageName = 'Prospecting',
                    CloseDate = System.today().addMonths(1),
                    AccountId = a.Id));
        }
        update oppList;
    }
}
 
@IsTest
private class AddRelatedRecordTest {

    @IsTest public static void addRelatedRecordTestonInsert() {

        Account testAcc = new Account();
        testAcc.Name = 'My Account Test';
        insert testAcc;
        update testAcc;

        System.assert(true, 'Opp Created');

    }

}

 
Please help me to finish my Test Class for the following Batch Job generating Invoice creation.

Batch Job
global class InvoiceGenerateBatchJob implements Database.Batchable<SObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {


        return Database.getQueryLocator([
                SELECT Name, Id, Rent_Due_Date__c, Monthly_Rate__c, Property__c
                FROM Tenant__c
                WHERE Rent_Due_Date__c = TODAY
        ]);
    }

    global void execute(Database.BatchableContext BC, List<Tenant__c> tenants) {

        List<Invoice__c> invoices = new List<Invoice__c>();

        for (Tenant__c tenant : tenants) {
            for(Invoice__c invoice : invoices){

                invoice.Bill_To_Tenant__c = tenant.Name;
                invoice.Due_Date__c = tenant.Rent_Due_Date__c;
                invoices.add(invoice);
            }
        }
        insert invoices;
    }

    global void finish(Database.BatchableContext BC) {

        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,TotalJobItems, CreatedBy.Email
                            FROM AsyncApexJob
                            WHERE Id = :BC.getJobId()];
    }

}
Scheduler Class For Batch Apex
global class InvoiceGenerateBatchScheduled implements Schedulable {
    global void execute(SchedulableContext sc) {
        InvoiceGenerateBatchJob invBatch = new InvoiceGenerateBatchJob();
        Database.executeBatch(invBatch, 200);

    }
}

​​​​​​Testing Batch Apex Job and Scheduler Classes:
@IsTest
private class InvoiceGenerateBatchTest {

    @TestSetup
    static void setupData() {

        Property__c property = new Property__c();
        property.Name = 'Prop1';
        property.Business__c = 'Gov';
        insert property;

        List<Tenant__c> tenants = new List<Tenant__c>();
        for (Integer i = 1; i < 5; i++);{

            try {
                Tenant__c t = new Tenant__c();
                t.Name = 'TenOne';
                t.Property__c = [
                        SELECT Id
                        FROM Property__c
                        WHERE Name = 'Prop1'
                        LIMIT 5
                ].Id;
                tenants.add(t);
            } catch (Exception e) {

                insert tenants;
            }
        }
    }

    @IsTest
     static void testInvoiceGenerateBatch() {

     String CRON_EXP = '0 0 22 30 3 ?';
     Date dueDate = Date.today();

     Test.startTest();

     String jobId = System.schedule('CreateInvoice', CRON_EXP, new InvoiceGenerateBatchScheduled());
     Database.executeBatch(new InvoiceGenerateBatchJob());

     Test.stopTest();

     System.assertEquals(5, [SELECT COUNT() FROM Invoice__c WHERE Bill_To_Tenant__r.Name = 'TenOne']);

        }
    }

 
public with sharing class FieldnotEmptycontrl {

    public static Property__c field {get; set;}

    public FieldnotEmptycontrl(){
    field = new Property__c();

    }

    public static void fieldNotEmpty(List<Property__c> prop){

        if(field.Business__c == null || field.Contact__c == null){

            field.Business__c.addError('You must enter a value!');
            field.Contact__c.addError('You must enter a value!');

        if(field.Business__c != null && field.Contact__c != null){

            field.Business__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
            field.Contact__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
        }

        }
    }
}
Here is the Trigger calling the above class and method, but it shows the error • triggers/fieldNotEmpty.trigger: ERROR at line 1, column 1 - Must specify the metadata file 
trigger fieldNotEmpty on Property__c (before insert, before update, after insert) {

    if (Trigger.isBefore) {
        if(Trigger.isInsert){

            FieldnotEmptycontrl.fieldNotEmpty(Trigger.new);
          
        }
    }
}
Please help me to resolve the issue
 
Please help me to finish my Test Class for the following Batch Job generating Invoice creation.

Batch Job
global class InvoiceGenerateBatchJob implements Database.Batchable<SObject> {

    global Database.QueryLocator start(Database.BatchableContext BC) {


        return Database.getQueryLocator([
                SELECT Name, Id, Rent_Due_Date__c, Monthly_Rate__c, Property__c
                FROM Tenant__c
                WHERE Rent_Due_Date__c = TODAY
        ]);
    }

    global void execute(Database.BatchableContext BC, List<Tenant__c> tenants) {

        List<Invoice__c> invoices = new List<Invoice__c>();

        for (Tenant__c tenant : tenants) {
            for(Invoice__c invoice : invoices){

                invoice.Bill_To_Tenant__c = tenant.Name;
                invoice.Due_Date__c = tenant.Rent_Due_Date__c;
                invoices.add(invoice);
            }
        }
        insert invoices;
    }

    global void finish(Database.BatchableContext BC) {

        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed,TotalJobItems, CreatedBy.Email
                            FROM AsyncApexJob
                            WHERE Id = :BC.getJobId()];
    }

}
Scheduler Class For Batch Apex
global class InvoiceGenerateBatchScheduled implements Schedulable {
    global void execute(SchedulableContext sc) {
        InvoiceGenerateBatchJob invBatch = new InvoiceGenerateBatchJob();
        Database.executeBatch(invBatch, 200);

    }
}

​​​​​​Testing Batch Apex Job and Scheduler Classes:
@IsTest
private class InvoiceGenerateBatchTest {

    @TestSetup
    static void setupData() {

        Property__c property = new Property__c();
        property.Name = 'Prop1';
        property.Business__c = 'Gov';
        insert property;

        List<Tenant__c> tenants = new List<Tenant__c>();
        for (Integer i = 1; i < 5; i++);{

            try {
                Tenant__c t = new Tenant__c();
                t.Name = 'TenOne';
                t.Property__c = [
                        SELECT Id
                        FROM Property__c
                        WHERE Name = 'Prop1'
                        LIMIT 5
                ].Id;
                tenants.add(t);
            } catch (Exception e) {

                insert tenants;
            }
        }
    }

    @IsTest
     static void testInvoiceGenerateBatch() {

     String CRON_EXP = '0 0 22 30 3 ?';
     Date dueDate = Date.today();

     Test.startTest();

     String jobId = System.schedule('CreateInvoice', CRON_EXP, new InvoiceGenerateBatchScheduled());
     Database.executeBatch(new InvoiceGenerateBatchJob());

     Test.stopTest();

     System.assertEquals(5, [SELECT COUNT() FROM Invoice__c WHERE Bill_To_Tenant__r.Name = 'TenOne']);

        }
    }

 
public with sharing class FieldnotEmptycontrl {

    public static Property__c field {get; set;}

    public FieldnotEmptycontrl(){
    field = new Property__c();

    }

    public static void fieldNotEmpty(List<Property__c> prop){

        if(field.Business__c == null || field.Contact__c == null){

            field.Business__c.addError('You must enter a value!');
            field.Contact__c.addError('You must enter a value!');

        if(field.Business__c != null && field.Contact__c != null){

            field.Business__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
            field.Contact__c.addError('Cannot use two fields at the same time. Please choose only one field Business or Contact');
        }

        }
    }
}
Here is the Trigger calling the above class and method, but it shows the error • triggers/fieldNotEmpty.trigger: ERROR at line 1, column 1 - Must specify the metadata file 
trigger fieldNotEmpty on Property__c (before insert, before update, after insert) {

    if (Trigger.isBefore) {
        if(Trigger.isInsert){

            FieldnotEmptycontrl.fieldNotEmpty(Trigger.new);
          
        }
    }
}
Please help me to resolve the issue