You need to sign in to do that
Don't have an account?
Problem with Update StandardPrice on product with trigger
I am new with triggers and I am trying to achieve the following. Every time a BundlePrice field is inserted or updated it should automatically update the standard price with that info according the exchange rate.
This is the trigger that I made.
trigger UpdateStandardPrices on Product2 (after insert, after update) { //Update the Standard price in all currencies from the Cost price on the Product. Cost Price is always in SEK //Create a PriceBookEntry if it's a new Product System.Debug('USP TRIGGER'); //This trigger will cause recursion if it's not stopped. //The TriggerMonitor class is static, and remains for the lifetime of the insert/update //This prevents recursion. //string TriggerName = 'UpdateStandardPrices'; if (TriggerMonitor.runOnce()) { //TriggerMonitor.ExecutedTriggers.add(TriggerName); // GET ALL DATA // Id PriceBookId = [SELECT Id From Pricebook2 WHERE IsStandard=TRUE].Id; //Get the ID of the Standard Price Book list<CurrencyType> ActiveCurrencies = [SELECT ISOCode, ConversionRate FROM CurrencyType WHERE IsActive=TRUE]; //Get a list of all active currencies list<Product2> Products = new List<Product2>([SELECT Id, Bundle_Price__c, CurrencyIsoCode FROM Product2 WHERE Id in :Trigger.new]); //Get a list of all new entries list<PricebookEntry> resultList = new list<PricebookEntry>(); //List to populate and update for( Product2 product : Products) { list<PricebookEntry> loopList = new list<PricebookEntry>([Select Id, CurrencyISOCode FROM PricebookEntry WHERE PricebookEntry.Product2Id =: product.Id]); //Get a list of all entries in the Standard Price Book for the product id for(CurrencyType c : ActiveCurrencies) { integer currencyExists = 0; //Reset the currency exists flag PricebookEntry price = new PricebookEntry(); for(PricebookEntry l : loopList) { //Is there already an entry in the currency if(l.CurrencyIsoCode == c.IsoCode) currencyExists = 1; } if(currencyExists == 0) { //Does not exist in this currency: Insert new StandardPrice price.UnitPrice = product.Bundle_Price__c * c.ConversionRate; price.Product2Id = product.Id; price.CurrencyISOCode = c.IsoCode; price.Pricebook2Id = PriceBookId; price.IsActive = TRUE; insert price; } else { //Exist in this currency: Update with new StandardPrice for(PricebookEntry l : loopList) { //Loop through to find the unique Id for the PricebookEntry if(l.CurrencyIsoCode == c.IsoCode) price.Id = l.Id; } price.UnitPrice = product.Bundle_Price__c* c.ConversionRate; price.IsActive = TRUE; resultList.add(price); } } } update resultList; }
What the trigger does is checks currencies check rate and add them to the standard price. But when i test it, it change the price to all currencies the same and ignores the rate. I need to edit the product so the rates will get changed. What I am doing wrong?
Additionally how can I update the trigger to check the PricebookId(sweden) that I have and add the corresponding Standardprice(SEK) to the Swedish price-book.
Any help to reach this mission will be highly appreciated.
Thanks, Darko
BUT, at a high level, my recommendations are:
- Avoid DML and SOQL inside your record loop. Try preparing collections like you see below, then using those inside the for loop to avoid problems with bulk processing
- Put in more debug statements to test the assumptions in your logic. Something happening here is not happening the way you think it is. Without an active org to test in, it's hard to say exactly, but debug statements will help
- You shouldn't need to query the records in your product2 trigger set - you have them already, by virtue of being in the trigger context.
Good luck! Hope that helps.Thanks monsterloomis for the reply. I didn't replied earlier but i managed to fix the issue. I also tested your code it works fine except when you try to create a product with a bundle_price__c to be empty. then I get this error:
Do you know by any chance how can i dodge that? So if the Bundle_Price__c is empty just create the product. I kinda need this so i wont need to create a default value of 0 for this field and have it inside the code to check if its empty create the product if it has a value of 0 predefine the price.
Thanks,
Darko
No problem, and glad you got it working. Just so I'm sure I understand: when you say to create the product, isn't all this happening in a trigger context on the product itself? If you just want to see if the bundle_price__c is empty and then create a product, you can certainly do it: ...but why would you create the product if the bundle price is null, but update the price if the value is 0? The bundle price may be empty/null, but the product itself is the scope of the trigger itself, so it seems odd to create a new product. Maybe I'm not fully understanding the requirement, though. If you can help me figure out what you're after and why, I'd be happy to offer some suggestions.
Well my products in salesforce are organised like this: I have a software, hardware accessories and bundle. All of them are products. I have made a custom CPQ for salesforce that combines them in a different matter and fields that are used accordingly for bundle hardware software accessories and so on. Now i have a custom object that sorts them and its called bundle line item and in that bundle line item i have lines that can be combined.
When i am creating a bundle i am making api calls and i need that bundle price to be 0. So when I add bundle line items that price needs to be updated and from that field bundle price i want to standard price to be updated for all currencies and with possibility on adding predefined pricebook.
Anyway thank you so much for your code. Let me test it good and i will give you a feedback :)
Cheers,
D.
I kinda feel I need to explain my logic better, because the more I test it the more problems i am facing :(
My Product has the following product Family values:
Then I have a custom object called Bundle_Line_Item__c where I am adding only when I am picking Bundle from the product family. This way I need to update the price of the bundle all the time and for that I am having a trigger to do that which works fine.
I have couple of scenarios that I need to take care of:
Here is what I did with the code so far with monsterloomis update.
Silly me, I've disabled the currencies, now that they are enabled I have tested everything and most of the things work fine.Except i am facing additional 2 problems:
1 When I add bundle line item to the product the bundle price updates but it doesn't change the value of the standard price in the pricebookentries.
2 is error when I clone the product.
I've googled the solution and i found this https://help.salesforce.com/articleView?id=000199313&language=en_US&type=1
But doesn't help me much... :(
After debuging when I create a new bundle_line_item__c record the value of the bundle_price__c is updated but that value doesn't affect the prices in the pricebook entry. Somehow it returns the old value even so the value is updated. This only occurs when I create a new bundle line item record.
Check error:
Ok so I found the solution partially the reason for the trigger not to work right and get me the old value was this code:
The trigger runs once and because of that it doesn't update as it should. Now I need to find a way to handle the loops differently and still to figure out the code with the cloning of the product.
error of the cloning:
Your trigger is trying to insert a pricebook entry that has already been inserted. Instead of creating a new PriceBookEntry in this trigger, can you try querying for the newly inserted pricebook entry and updating that instead? So for line 27, you'd want to refer to a collection you query outside the loop and then update that PBE instead of attempting to insert a new one. I'll admit that I haven't spent a lot of time with products and PBEs, so there may be factors and black box behaviors I'm not considering, but: it seems to me that if you're violating a unique constraint on insert, then you're attempting to create a record that already exists, and the best course of action would be to attempt to retrieve it first using the product2.id and pricebook id, and then update it rather than attempting to insert a new one.