You need to sign in to do that
Don't have an account?
Automatically set picklist
Hi there,
I am very new to Apex triggers....so new that this is the first one I have attempted that isn't from a workbook. Everyone has to start somewhere though I guess.
I assume that this will be quite simple and so I will describe my situation as best I can and hopefully, someone will have an idea on how I can solve my problem.
I have a custom object (Destiny products and services), this custom object has a lookup field to another custom object (product). When creating a new 'destiny product and service" I have made formula fields which autopopulate fields from the Product object, relating to which product the record creator chose from the Product lookup field.
This has all worked fine as I just needed a simple formula field, however the products and services have differing stages, types, etc depending on the product or service chosen.
I attempted to accomplish this by creating a picklist field within each custom object which states the names of all the products or services, I then created dependant picklists in relation to what choice was made in the name picklist and then made this hidden.
I want to make this as simple as possible for the user and so I intend to make it so that when the lookup field is selected, it will autopopulate the name picklist so it is the same as the lookup field and then the Destiny product or services record will have stages and type which will be related to the product chosen.
I need to write an apex trigger which will set the picklist value in the products and services object, to be the same as the picklist option from the record chosen in the lookup field (product object).
Any help would be much appreciate, even advice on alternative and perhaps easier ways that this can be accomplished. I am sorry if this is difficult to understand.
Mikie
I forgot about the silliy limitations on the picklists for field updates... You would have to make one rule for each picklist value... This is how I do it for clients, because then they have the opportunity to update it themselves when they change values, without having to call me (as my rates are crazy! :p)
The most versatile way to do this in a trigger would be as follows:
1) Create a new formula field on the Destiny_Products_and_Services__c object called ProductName__c.
The formula should pull over "Product_or_Service_Name__r.Product_Name__c"
2) Create a trigger with the following code
And you're done
All Answers
I'm having trouble following your description. Can you use field names, and descriptions?
So you have DestinyProductsAndServices__c (Destiny object) which has a lookup to Product__c (and to Service__c ?)
You have created a ProductStage__c picklist, and a ServiceStage__c picklist on DestinyProductsAndServices__c. Each of these contains the same values as Product__c.Stage__c, or Service__c.Stage__c respectively.
The values of the Stage picklists on Destiny object are populated (presumably by workflow field update) to sync with their respective parent.
After this I get lost.
Certainly, I am sorry this is also my first post.
Destiny_Products_and_Services__c = custom object API name
Product_or_Service_hidden_picklist__c = Picklist field API name
Products__c = custom object API name
Product_Name__c = custom picklist field API name
These are the only ones that really matter. There is no service object as of yet. Destiny products and services has a lookup field for the products object which be chosen when creating the record. This serves the purpose of allowing multiple formula fields to auto-populate with information from the products object.
E.G. If soeone were to choose ádvantage program' in the lookup field, the record created will have description, price, etc all autopopulated from information stored in the products oject.
Description of objects: Destiny products and services is designed to keep track of the products in relation to the client, the products object is for information to do with the product and services (which is currently only around 6 products and services).
The two picklists fields lsited above have the exact same values, these values are the names of the products. I have set the picklist on each of the records in the products object so that they are the same as the name of the product. E.G. On the advantage program record, the picklist value will be set to advantage program.
When someone is creating a record the goal is that: After selecting what product the client wants to purchase from the lookup, the hidden product name picklist will be chosen to be the same as the product chosen from the lookup. Except as a picklist, it will have other visable picklists which are dependant upon it and therefore the stages and type, etc will change accordingly.
I hope this was explained better. :)
P.S. the lookup field is called: Product_or_Service_Name__c
P.S. the lookup field is called: Product_or_Service_Name__c
I see.. Then if I am understanding you correctly: you won't need a trigger at all.
You can create a workflow rule on Destiny object that runs on change of Product:
Then create a field update within the WF rule:
You can probably just call it Product_or_Service_Name__c as that is more accurate to what it is. It's name will confuse people when making reports, and developers when building functionality.
Hey,
I followed the instructions exactly, but when it came to the field update there is no place in which to put it in. As its a picklist, the only options are to chooose a pre-defined value or to move the picklist choice up or down.
Maybe I am missing something?
Thankyou so much for your time and help by the way
It also needs to be a picklist so I can set the other picklist fields to be dependant off it and therefore each product will have unique stages.
Mikie
I forgot about the silliy limitations on the picklists for field updates... You would have to make one rule for each picklist value... This is how I do it for clients, because then they have the opportunity to update it themselves when they change values, without having to call me (as my rates are crazy! :p)
The most versatile way to do this in a trigger would be as follows:
1) Create a new formula field on the Destiny_Products_and_Services__c object called ProductName__c.
The formula should pull over "Product_or_Service_Name__r.Product_Name__c"
2) Create a trigger with the following code
And you're done
I am now getting the error:
Error: Field Product_Name__c is a picklist field. Picklist fields are only supported in certain functions
Does this mean that it cannot be done?
I tried putting down the lookup field to the product, except when saved, the record just shows the URL ID number thing.
Ok, I found a way around this. I wrote another formula field which uses an if statement to read the name of the product
Just going to attempt the trigger name. I have checked it and the ProductName field and productName2 field both work. When a product is chosen from thelookup...the name is replicated in the ProductName2 field...I feel like I am close now...
You don't need any other formula fields other than the ProductName__c one I mentioned before.
Change the formula to 'TEXT(Product_or_service_name__r.Product_Name__c)'
Then remove the unecescary fields.
Will do.
I will delete the redundant field now. Once again thankyou soo much. I have entered the trigger into sandbox environment and then deployed it to my production version. One final question before i accept the inbound change set into my production version. Firstly I jsut want to say that I am very new to apex triggers and do not full understand them as of yet. Do i need to test the code in anyway before deploying it....If so how would I do this? Short of writing an apex test code?
Once again, I am very, very grateful for all your help.
You're welcome!
Yes, you will need to write a test class in order to deploy it. Triggers require at least 75% code coverage for the trigger itself, as well as at least 75% global coverage in the organisation to deploy to...
Thankfully, this is a very simple trigger to test for.
Apex testing is a whole other kettle of fish that many amatuer coders tend to underestimate the value of.
Poorly architected tests can cost huge amounts of man hours as your organization grows. As a consultant, I commonly have to augment client applications that are made up from other consultants, or the clients themselves. Sadly, most of the time, it is not done correctly, and the man hours I burn fixing improper code, and ensuring test coverage must be passed on to the client to pay for.
Added to that: the vast majority of free sample code out there has test classes that are poorly architected... Here is how I would cover this code:
1) Create a class that will store your test object records. From what I know of your system, you will need at least two records. The class would look as follows:
Note my naming convention. I keep all test and test related classes prefixed with the name 'TEST' so that they're easier to view and sort etc...
This class will grow as your org grows with tests. Anytime you need to create records to cover apex code, those records definition should be put in here in the same fashion as the examples i've placed.
NOTE: that if you have some required fields that I don't know about, you would need to add those to these two records as well. This is just a framework.
By creating all objects in once place, and havint your test classes reference all the same objects, you avoid having to recode every single test class when you make a change to a business rule.
Next, create your test class to cover the trigger:
That's easy. We know it's covered because all the trigger does is set a value from the record in one field to another field. So there is really nothing else to do. this should get you to 100% coverage.
Again, notice the naming convention: TEST then I put the name of the trigger I'me testing against. This way, there are no questions as to what this test is supposed to accomplish, because it is defined by the very trigger process it covers.
Ok, I feel like I have made progress. I have been using FORCE.com IDE as my sandbox inbound change sets are not working....Either way, I have two clases and one trigger in my project. Not one of them can be saved to the server because of these three reasons:
Save Error: Invalid type: product__c , I assumed this was because the actual API name for the object was products__c. So I changed it and the text became blue, I assume this is a good sign...But the error remains.
Save Error: variable does not exist: TESThelper.testDestiny00
Test coverage of selected apex trigger is 0%, atleast 1% test coverage.......
Randomly after clicking save on TESThelper for the 11th time, the error finally went away...but it was replaced by another two errors that say:
Save error: Unable to perform save on all files: com.salesforce.ide.api.metadata.types.Metadata$JaxbAccessorF_fullName cannot be cast to com.sun.xml.internal.bind.v2.runtime.reflect.Accessor TESThelper.cls-meta.xml /MikiesDellComputerProjects/src/classes line 1 Force.com save problem
I know I am being a pain npw, but it feels so close I can almost taste success.
Thankyou again
Randomly after clicking save on TESThelper for the 11th time, the error finally went away...but it was replaced by another two errors that say:
Save error: Unable to perform save on all files: com.salesforce.ide.api.metadata.types.Metadata$JaxbAccessorF_fullName cannot be cast to com.sun.xml.internal.bind.v2.runtime.reflect.Accessor TESThelper.cls-meta.xml /MikiesDellComputerProjects/src/classes line 1 Force.com save proble
I know I am being a pain npw, but it feels so close I can almost taste success.
Thankyou again
I am so sorry I do not understand this at all....now there is three errors again....
The third is still as a result of the trigger not being tested, but the other two are:
Description Resource Path Location Type
Save error: Field is not writeable: Destiny_Products_and_Services__c.Name TESThelper.cls /MikiesDellComputerProjects/src/classes line 15 Force.com save problem
Description Resource Path Location Type
Save error: Variable does not exist: TESThelper.testDestiny00 TESTdestiny_bIbU.cls /MikiesDellComputerProjects/src/classes line 25 Force.com save problem
My only idea is that.....it is saying that Destiny_products_and_services__.Name is an autonumber and therefore it cannot be "testDestiny00"
The second error is then because TESThelper cannot create the class?
One hurdle over....I Changed the autonumber to just text and now the Test class has saved.
I still have three errors:
Description Resource Path Location Type
Average test coverage across all Apex Classes and Triggers is 70%, at least 75% test coverage is required. MikiesDellComputerProjects line 1 Force.com code coverage warning
Description Resource Path Location Type
Save error: Variable does not exist: TESThelper.testDestiny00 TESTdestiny_bIbU.cls /MikiesDellComputerProjects/src/classes line 25 Force.com save problem
Description Resource Path Location Type
Test coverage of selected Apex Trigger is 0%, at least 1% test coverage is required destiny_bIbU.trigger /MikiesDellComputerProjects/src/triggers line 1 Force.com code coverage warning
Maybe...it is because Destiny products and services is a child to accounts object?
You can change the object name back to an auto nuber if you like. If there is no reason for users to enter a specific name, then leave it as an auto number, and remove the line in the TESThelper class that assigns a value to the name.
Using the IDE is pretty advanced. If you can use change sets, they're easier to handle because they do a lot of the order of execution stuff for you. The ide does not.
Try creating a change set, and deploying that. See what error pops up if any.
Before you do that, go in to your sandbox and do a "run all tests" from the apex classes list, and see if there are failures anywhere that are preventing you from getting the needed coverage
I have taken your advice and copied all my work over from IDE to my sandbox. You were right, it is easier to use.
TestHelper has saved with 87% code coverge, as for the Test, I am getting this error:
Error Message System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Account__c]: [Account__c] Stack Trace
Class.TESThelper.__sfdc_testDestiny00: line 18, column 1
Class.TESTdestiny_bIbU.myUnitTest: line 25, column 1
I created an account inside the sandbox environment called TestTrigger, I wrote into the TestHelper in place of the name: TestDestiny00, Account__c = TestTrigger. But I get this error:
Error: Compile Error: Variable does not exist: TestTrigger at line 15 column 34
Is there a different way in which to input if it is a masterdetail relationship or a lookup?
Mikie
It is weird though as the original trigger...now it randomly has 2/2 100% code coverage. Should I just deploy it or wait until I figure out this class and test problem?
Ok, I went into Testtrigger and wrote down the number in the URL and inserted that into the TestHelper. Now everything has passed with 100% code coverage!
I will just deploy it now and see how she goes.
Ok, I went into Testtrigger and wrote down the number in the URL and inserted that into the TestHelper. Now everything has passed with 100% code coverage!
I will just deploy it now and see how she goes.
Ok, I tested it out in sandbox before accepting inbound change sets in production. The product or service hidden picklist has filled itself with the Product ID:a06N0000000tLY0, rather than the actual name of the product..
I think I have two options now, whichd o you think would be best:
1. It is a hidden field anyway and therefore what it actually says matters little...If i were to just change the picklist to be the Id's and then make the other picklists dependant on it.
2. Add to the trigger which will convert the id into the name?
What are your thoughts?
I also understand there is some kudos system to the forum. How do I do it and I assume that I pick the original trigger post as the solution?
Mikie
Scratch that.
I realised that my sandbox was still set to the old formula field for ProductName. I have changed it and in the sandbox environment, the Trigger works absolutely perfectly. You my friend are a genius!!
Everything passes and all the tests and code coverage is 100% inside the sandbox environment. However when I try to deploy it via changesets, it fails to validate because of:
TESTdestiny_bIbU.myUnitTest() Class 18 Failure Message: "System.DmlException: Insert failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []", Failure Stack Trace: "Class.TESThelper.__sfdc_testDestiny00: line 18, column 1 Class.TESTdestiny_bIbU.myUnitTest: line 25, column 1"
Ok, I created another record in production entitled TestTrigger, I recorded the ID, put it into the account Id int he TestHelper, deployed the changesets and everything works perfectly. I have tested it all out in production and it works perfectly.
You are a genius, thank you so much for the time and effort you have put into helping me. I am very greatful.
Could you recommend places in which would assist me to better understand Apex?
Mikie
I never went to school to code, I learned everything by myself through these means:
Reading a great deal of posts, right here on the boards.
Bookmarking the documentation:
- Force.com Apex Code Developer's Guide
- Force.com SOQL and SOSL Reference
- Visualforce Developer's Guide
- Metadata API Developer's Guide
- SOAP API Developer's Guide
- AJAX Toolkit Developer's Guide
- Web Services API Developer's Guide
- Operators and Functions
And, my personal favourite method:
Installing unmanaged packages in dev orgs, and reverse engineering all the cool stuff they do.
My personal tips:
1) Make sure EVERYTHING is batchable. You will need it one day...
2) Comment the crap out of your code so that other people could read it, understand it, and augment it
3) Clean up stuff that's no longer needed
4) Learn to apply the precise amount of pressure to get the job done, but still get it done right. Any more and it's convoluded, or over engineered. Any less and it won't do what you want.
4) If you need to start over, start over. You can't shine a turd.
Hahaha thankyou I will definitely take what you have said into account.