function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Lara WasowskiLara Wasowski 

Problems with Quote Approval process / Android Wear

Hi all,

I have setup the Salesforce Wearable Pack for Android Wear and have configured the Quote Approval app, as found and described here:
https://github.com/developerforce/WearablePack-AndroidWear/blob/master/README.md
The app works fine, until I start trying to make some small changes to it - at which point I start getting some strange behavior and/or errors.

1) When an approval has been approved or rejected I would like to update the Quote Status field accordingly.  So, I tried adding a Field Update action to the Approval Process (as Final Approval and/or Final Rejection action).  When I do this, the approval process (which has been working fine; my colleague Tor creates a quote with a >20% discount, it comes to me for approval and my action gets registered) all of a sudden starts looping - and sends the approval to my manager after I have approved it.  I have made no other changes to the process other than adding the action...

2) Additionally, I seem to be getting this error a lot:
Validation Errors
While Saving Record(s) There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger CGDemo2015.QuoteApproval caused an unexpected exception, contact your administrator: CGDemo2015.QuoteApproval: execution of BeforeUpdate caused by: System.DmlException: Process failed. First exception on row 0; first error: ALREADY_IN_PROCESS, Cannot submit object already in process.: []: Trigger.CGDemo2015.QuoteApproval: line 20, column 1".
This is related to e.g. trying to submit a revised Quote for approval - which should work...

Attached are some screenshots of the "looping" behavior that starts when I add an action.
Lara WasowskiLara Wasowski
The Apex trigger that is part of the package I d/l from github
// Trigger an approval workflow and push notification when a Quote has a discount >= 20%
trigger QuoteApproval on Quote (before insert, before update) {
    for (Integer i = 0; i < Trigger.new.size(); i++) {
        Quote newQuote = Trigger.new[i];
        Quote oldQuote = new Quote();
        if (Trigger.old != null) {
            oldQuote = Trigger.old[i];
        }
        if (newQuote.Discount >= 20) {
            
            newQuote.Status = 'Needs Review';
            
            // submit the quote for approval
            
            Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
            
            req.setComments('The discount is >= 20% so it requires approval.');
            req.setObjectId(newQuote.Id);
            
            Approval.ProcessResult result = Approval.process(req);
            
            
            // Fetch related objects: Opportunity and Opportunity Owner
            
            Opportunity opp = [ select Name, OwnerId from Opportunity where Id = :newQuote.OpportunityId ];
            
            User owner = [ select Name, FullPhotoUrl from User where Id = :opp.OwnerId ];
            
            
            // send the notification
    
            Messaging.PushNotification msg = new Messaging.PushNotification();
            
            Map<String, Object> payload = new Map<String, Object>();
            payload.put('ownerName', owner.Name);
            payload.put('ownerFullPhotoUrl', owner.FullPhotoUrl);
            payload.put('processId', result.InstanceId);
            payload.put('workItemId', result.getNewWorkitemIds()[0]);
            payload.put('oppName', opp.Name);
            payload.put('quoteId', newQuote.Id);
            payload.put('quoteName', newQuote.Name);
            payload.put('amount', newQuote.TotalPrice);
            payload.put('discount', newQuote.Discount);

            msg.setPayload(payload);
    
            // The approver's Id
            String userId = result.actorIds[0];
    
            Set<String> users = new Set<String>();
            users.add(userId);
    
            msg.send('QuoteDiscountApproval', users);

        }
    }
}