Showing posts with label Trigger. Show all posts
Showing posts with label Trigger. Show all posts

Friday, November 1, 2013

Winter 2014 - give me back my Code Coverage!!! (PART 2 - a follow-up)

Just noticed there is a new blog post that addresses my last topic here at http://kingkoo-salesforce.blogspot.com/2013/09/winter-2014-give-me-back-my-code.html on the code coverage since Winter 14 was introduced.

I urge you to go take a good look.

By now I am used to going to Eclipse or Developer Console to view the code coverage.  I still missed the fact I cannot see the information from my Apex Class page, but I think I am slowly understanding the reason behind it.

This blog was written by Josh Kaplan - he is the Product Manager for Apex at Salesforce.com

http://blogs.developerforce.com/engineering/2013/11/code-coverage-and-the-force-com-developer-console.html

Enjoy!

Thursday, September 19, 2013

Winter 2014 - give me back my Code Coverage!!!

Winter 14 is coming and for some it has already arrived.

While I was exploring some of the new exciting features of Winter 14, I was devastated to find that something has gone missing.

I have been writing a bit of Apex classes lately and as you may already know, Salesforce requires each Apex class to have accompanying test classes to test the code to ensure you have tested your code thoroughly before you deploy the code to production.

In the past, checking how well you have covered your code was a bliss.  All you needed to do was to go to App Setup -> Develop -> Apex Classes and the information would be right there, under the "Code Coverage" column, such as this:


In Winter 14, however, the page becomes this instead:

What?  The invaluable "Code Coverage" column has gone missing.  What is going on??!?

I have submitted a Case, and the reply I received was that it is indeed a new "feature".

For now the only workaround I can think of is to make use of Developer Console, so all is not lost.

All you have to do is to open your Developer Console, click the "Tests" tab at the bottom - NOTE not the "Test" tab (singular) at the top, but the "Tests" tab (plural) at the bottom.  A list of classes and the code coverage should be listed inside the right hand pane.

If you do not know where to find Developer Console, all you have to do is to click your name at the top left corner of the screen, and a pull down menu should pop up.  Developer Console should be one of the options.  Once you click it, a brand new window will appear.

Lastly, if you have any new development regarding this Code Coverage column, please drop me a note too!




Monday, October 29, 2012

Trigger to disallow deleting parent if children exist

Whenever you have a master-detail relationship, and you try to delete a parent record using the standard Salesforce interface, Salesforce will delete that record and any associated children records.


Let's say you have a parent "Invoice" object and the child is "Line Item".  Each invoice record may have zero or more Line Item child records.


If you want to not let users delete that record, then you'll need to write a trigger.  There are two ways to do that.

If you have been writing stored procedures forever like myself, my normal approach would be to do an SQL like that:

SELECT i.Id, Count(li.Id) AS Counter FROM Invoice__c i INNER JOIN
    Line_Item__c li ON i.Id = li.InvoiceId

Basically what you want to do is to go through each invoice in the parameter list and do a count of how many line items there are.  Unfortunately in SOQL you cannot include aggregate functions in sub-queries (aggregate functions can only be at the root-query level).

So, the next best thing is to just do a list of each Invoice record and associated Line Item records.  The trigger code looks like:


trigger DeleteInvoice on Invoice__c (before delete) 
{
    List<Invoice__c> invoices = [select id, (select name from line_items__r) 
        from invoice__c where
        id in :Trigger.old];

    for (Invoice__c inv: invoices)
    {
        if (!inv.line_items__r.isempty())
        {
            Trigger.oldMap.get(inv.id).addError('error goes here');
        }
    }
}


So what the above does is to first get a list of invoices and associated line items.  Then go through each invoice and see if there are any related line items.  If there are, then provide an error to that invoice.

What I found out is that I might be able to simplify that  little.  Instead of going through the Invoice__c first, I can go through Line_Item__c first, as this following trigger shows:


trigger DeleteInvoice on Invoice__c (before delete) 
{
    List<Line_item__c> lis = [select invoice__c from line_item__c 
        where invoice__c in :Trigger.oldMap.keyset()];

    for (line_item__c li : lis)
    {
          trigger.oldmap.get(li.invoice__c).adderror('error goes here');
    }
}


What this second trigger does is to simplify look at the child table and find those line items where the invoice id matches the invoice ids in the parameter list.  The invoices associated with these line items retrieved are the ones that you do not want to allow deletion.

It looks to me that the second trigger is shorter because it does not have to have the "if" statement.  I don't know if there is any substantial performance improvement, but the code looks somewhat cleaner.

What do you think?