What to do in case of too many DML Statements?
I am attempting to write a Quick Action that is a LWC that will validate if a quote can be submitted for approval. If there is a validation it will return a string and display it on the screen, with no validation it should submit a record into approval flow and return a string and display. When kicking off the approval flow I get the error of To Many DML Statements 1. I have read that it is because I am either using @wire or (cacheable=true). If I take (cacheable=true) away the string will not be returned and nothing will display. How should the below be handled?
HTML
{somethingReturned.data}
Javascript
import { LightningElement, api, wire } from 'lwc'; import ValidateQuoteForApproval from '@salesforce/apex/clsSubmitToOrderLWC.ValidateQuoteForApproval'; export default class TestQuickAction extends LightningElement { @api recordId; //@wire must be used to call the method. @wire(ValidateQuoteForApproval, {idQuote:'$recordId' }) somethingReturned; //API Invoke is used to display the Quick action @api invoke() { somethingReturned } }
Apex
public with sharing class clsSubmitToOrderLWC { @AuraEnabled(cacheable=true) public static String ValidateQuoteForApproval(Id idQuote) { boolean blnError = False; String strErrorMessage = ''; system.debug(logginglevel.debug, 'Start ValidateQuoteForApproval ' + idQuote); SBQQ__Quote__c soQuote = [Select Id, SBQQ__LineItemCount__c, Special_Lines_Roll_UP__c From SBQQ__Quote__c Where Id = : idQuote]; system.debug(logginglevel.debug, 'ValidateQuoteForApproval' + soQuote); If(soQuote.SBQQ__LineItemCount__c == 0){ strErrorMessage = strErrorMessage + 'Wait a Second! This Particular Quote has no Quote Line items n'; blnError = True; } If(soQuote.Special_Lines_Roll_UP__c >= 0){ blnError = True; strErrorMessage = strErrorMessage + 'Wait a Second! This Particular Quote has some Special line items which are rejected.'; } If(blnError == True){ Return strErrorMessage; }Else{ Approval.ProcessSubmitRequest req1 = new Approval.ProcessSubmitRequest(); req1.setComments(''); req1.setObjectId(soQuote.id); Approval.ProcessResult result = Approval.process(req1); Return 'Quote has been submitted for Approval'; } } }
In case of too many dml statements - you cannot perform a DML statement within cacheable=true as you noted. If you added a debug log, you'd notice the following under LIMIT_USAGE
Number of DML statements: 1 out of 0 * CLOSE TO LIMIT
This is by design.
In your case, and when working with LWC, you should always take a look to see if there's any provided wire adapters that can handle the action before jumping into apex.
It seems you're doing two things:
Querying the record you're on to do some validation checks
The approval process.
getRecord is the perfect adapter for the first step so you can quickly validate data. I'll also throw out that the createRecord is also very helpful, although won't work with your use case of processing an approval so you'll have to set @cacheable=false and call the apex method imperatively.
const FIELDS = ['SBQQ__Quote__c.SBQQ__LineItemCount__c','SBQQ__Quote__c.Special_Lines_Roll_UP__c']; export default class TestQuickAction extends LightningElement { quote; @wire(getRecord, { recordId: '$recordId', fields: FIELDS }) wiredRecord({ error, data }) { if(data) { this.quote = data; if(this.quote.fields.SBQQ__LineItemCount__c == 0){ //handle displaying error toast message } // after all validations pass, I'd suggest renaming method to do //what it now does without validations CreateQuoteApproval, ({idQuote:'$recordId' }) .then(result => { //process success toast }) } } }