Apex Trigger in Salesforce using 2 objects - salesforce

I am new to Salesforce, project requests I keep track of last_id used.
I created 2 SF objects, one holds the last_id other holds total number of ids to assign. I would like user to enter a number and the number will be added to the last_id. Result will be stored in the tracking object.
Code:
tracking_next_id__c[] btnext = [SELECT last_end_id__c FROM tracking_next_id__c];
for (tracking__c updatedAccount : Trigger.new) 
{
updatedAccount.next_id__c = btnext[0].last_end_id__c + updatedAccount.total_account__c;
}
When I run the trigger; I get error Error:
Invalid Data.
Review all error messages below to correct your data.
Apex trigger getNextId caused an unexpected exception, contact your administrator: getNextId: execution of AfterUpdate caused by: System.FinalException: Record is read-only: Trigger.getNextId: line 11, column 1

After much research, found if I changed my trigger to before update instead of after update, it worked.

Right, you cannot edit a record in after insert trigger.

Related

Error in Salesforce flow: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY

Error detected during debug:
Create one OpportunityLineItem record where
OpportunityId = {!$Record.ConvertedOpportunityId} (null)
Product2Id = {!get_related_Product.Id} (01t5j000000I80nAAC)
Quantity = {!DefaulQuantityOfProduct} (1)
TotalPrice = {!TotalPriceDefaultForNewOpp} ($637.54)
Result
Info
Failed to create record.
Info
Error Occurred:
This error occurred when the flow tried to create records: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY: insufficient access rights on cross-reference id. You can look up ExceptionCode values in the SOAP API Developer Guide.
Manually or using Apex, I can add a record. The fields that I add (opportunityid,Quantity,TotalPrice,Product2id) are not read-only. I need a detailed answer. Am I missing some permission?
1 flow schema
2 trigger condition
3 get related record
4 create new record
OpportunityId = {!$Record.ConvertedOpportunityId} (null)
This looks like the opportunity doesn't exist yet (got any errors? Do you create them always or only when certain condition is met? Did it fail?). Or it exists but it just has been inserted, SF didn't manage to update the Lead with the Id yet? Maybe add entry criteria that check if the field is populated.
Lead conversion is bit nasty topic, see https://salesforce.stackexchange.com/questions/3956/lead-conversion-trigger-order-of-execution
Actually you might be better of on SF stackexchange, more admins over there and flows are no-code solution so not a good fit for stackoverflow?

Trigger to restrict duplicate record for a particular type

I have a custom object consent and preferences which is child to account.
Requirement is to restrict duplicate record based on channel field.
foe example if i have created a consent of channel email it should throw error when i try to create second record with same email as channel.
The below is the code i have written,but it is letting me create only one record .for the second record irrespective of the channel its throwing me the error:
Trigger code:
set<string> newChannelSet = new set<string>();
set<string> dbChannelSet = new set<string>();
for(PE_ConsentPreferences__c newCon : trigger.new){
newChannelSet.add(newCon.PE_Channel__c);
}
for(PE_ConsentPreferences__c dbcon : [select id, PE_Channel__c from PE_ConsentPreferences__c where PE_Channel__c IN: newChannelSet]){
dbChannelSet.add(dbcon.PE_Channel__c);
}
for(PE_ConsentPreferences__c newConsent : trigger.new){
if(dbChannelSet.contains(newConsent.PE_Channel__c))
newConsent.addError('You are inserting Duplicate record');
}
Your trigger blocks you because you didn't filter by Account in the query. So it'll let you add 1 record of each channel type and that's all.
I recommend not doing it with code. It is going to get crazier than you think really fast.
You need to stop inserts. To do that you need to compare against values already in the database (fine) but also you should protect against mass loading with Data Loader for example. So you need to compare against other records in trigger.new. You can kind of simplify it if you move logic from before insert to after insert, you can then query everything from DB... But it's weak, it's a validation that should prevent save, it logically belongs in before. It'll waste account id, maybe some autonumbers... Not elegant.
On update you should handle update of Channel but also of Account Id (reparenting to another record!). Otherwise I'll create consent with acc1 and move it to acc2.
What about undelete scenario? I create 1 consent, delete it, create identical one and restore 1st one from Recycle Bin. If you didn't cover after undelete - boom, headshot.
Instead go with pure config route (or simple trigger), let the database handle that for you.
Make a helper text field, mark it unique.
Write a workflow / process builder / simple trigger (before insert, before update) that writes to this field combination of Account__c + ' ' + PE_Channel__c. Condition could be ISNEW() || ISCHANGED(Account__c) || ISCHANGED(PE_Channel__c)
Optionally prepare data fix to update existing records.
Job done, you can't break it now. And if you ever need to allow more combinations (3rd field) it's easy for admin to extend it. As long as you keep under 255 chars total.
Or (even better) there are duplicate matching rules ;) give them a go before you do anything custom? Maybe check https://trailhead.salesforce.com/en/content/learn/modules/sales_admin_duplicate_management out.

NO_SQL_DATA error when deleting a record, firedac, delphi 10.3.1

using sql server and delphi 10.3.1, and firedac.
I am using cached updates, with autocommit on.
I keep managing to get my data into a state where the record has been deleted from the database, and I have also deleted that record in the dataset.
then, when it attempts to commit the change to the database(where the data no longer exists), I get an error:
[my application] raised exception class emssqlNativeException with message [firedac][Phys][odbc][sqlncli11.dll] SQL_NO_DATA
and then I can't clear the cached updates flag on the dataset, because there is stuff 'sitting' there.
my question - how can I get it to NOT return that error? because it's really not an error, it's trying to delete a record that no longer exists. I am not finding ANY documentation on the update options on a query, so is there a flag there I need to set?
You can handle update errors in OnUpdateError and perform any additional checks before deciding how to proceed. Blindly pretending all deletes worked would be something like:
procedure TForm1.FDQuery1UpdateError(ASender: TDataSet; AException:
EFDException; ARow: TFDDatSRow; ARequest: TFDUpdateRequest; var AAction:
TFDErrorAction);
begin
if ARequest = ARDelete then AAction := eaApplied;
end;
Read the online help for OnUpdateError for more information.

how to update the count of the "retry column" when the spring retries invoke web services

Am trying to use spring-retry and i want to update my DB every time the spring-retry works for 5 retries.
In database a column need to be updated in order to track if the retry was made 5 times or not.
You can add a RetryListener to the RetryTemplate; the count is in the RetryContext argument passed in.
You can add more information to the context if needed, by getting a reference to it using the RetrySynchronizationManager.

TClientDataset ApplyUpdates error because of database table constraint

I have an old Delphi 7 application that loads data from one database table, make many operations and calculation and finally writes records to a destination table.
This old application calls ApplyUpdates every 500 records, for performances reasons.
The problem is that, sometimes, in this bunch of records lies one that will trigger database constraint; Delphi fires an exception on ApplyUpdates.
My problem is I don't know which record is responsible for this exception. There are 500 candidates!
Is it possible to ask TClientDataset which is the offending record?
I do not want to ApplyUpdates foreach appended record for speed issues.
I think you may try to implement the OnReconcileError event which is being fired once for each record that could not be applied to the dataset. So I would try the following code, raSkip means here to skip the current record:
procedure TForm1.ClientDataSet1ReconcileError(DataSet: TCustomClientDataSet;
E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
Action := raSkip;
ShowMessage('The record with ID = ' + DataSet.FieldByName('ID').AsString +
' couldn''t be updated!' + sLineBreak + E.Context);
end;
But please note, I've never tried this before and I'm not sure if it's not too late to ignore the errors raised by the ApplyUpdates function. Forgot to mention, try to use the passed parameter DataSet which should contain the record that couldn't be updated; it might be the way to determine what record caused the problem.
And here is described the updates applying workflow.
Implementing OnReconcileError will give you access to the record and data that is responsible for the exception. An easy to accomplish this is to add a “Reconcile Error Dialog”. It is located on the “New Items” dialog which is displayed by File | New | Other. Once you have added it to your project and used it in the form with the clientdataset. The following code shows how it is invoked.
procedure TForm1.ClientDataSetReconcileError(DataSet: TCustomClientDataSet;
E: EReconcileError; UpdateKind: TUpdateKind;
var Action: TReconcileAction);
begin
Action := HandleReconcileError(DataSet, UpdateKind, E);
end;
It will display instead of the exception dialog. It will allow you to view the offending data and select how you want to proceed. It has been over 5 years since I last used it, hopefully I have not forgotten some details.

Resources