I need to mark the CaseMilestone as complete and populate the completion date, when the owner of it's parent Case is changed.

For other objects I can use

List<Account> acctsToUp = new list<Account>();
for(Entitlement e:entitlements){

    Account a = new Account(Id = e.AccountId);

to create a list of Accounts and then update the Account fields (I'm new to Apex and although I know the outcome of using this code, I'm not sure exactly what's happening there).

When I try to do the same in the below code, it causes an error

Field is not writeable: CaseMilestone.CaseId

and I realise that this Id can't be updated whereas the Account's can but I'm not sure what the alternative is?

When selecting the CaseMilestone(s) to update, I need to check that their MilestoneTypeId matches the Id fetched by the SOQL query.

trigger completeMilestoneOnAssignment on Case (after update) {

    List<WEID__c> weids = WEID__c.getall().values();
    Set<Id> validRecordTypeIds = new Set<Id>();

        for (WEID__c weid: weids) {
        try {
            } catch (System.StringException e) {
                'Invalid Record Type Id ' + weid.WECaseId__c

    List<Id> caseIds = new List<Id>();
    for (Case c : Trigger.new){

            Case oldCase = Trigger.oldMap.get(c.Id);
            if(oldCase != null && oldCase.OwnerId != c.OwnerId &&

    if(caseIds.isEmpty() == false){

        List<MilestoneType> milestoneId = [SELECT Id
                                        From MilestoneType
                                        Where Name = 'Case Accepted'];
        if(milestoneId.isEmpty() == false){

            List<CaseMilestone> milestonesToUp = new List<CaseMilestone>();
            for (Case c:caseIds){

                CaseMilestone m = new CaseMilestone(CaseId = c.Id);
                m.IsCompleted = TRUE;
                m.CompletionDate = System.now();


            update milestonesToUp;

I think the issue is that you are trying to update caseId rather than Id on CaseMilestone. It may be because Case - CaseMilestone is a Master detail type relationship and you are not allowed to change it. As an alternative what you could do is

//Query for CaseMilestones using your CaseIds
List<CaseMilestone> cms = [select Id,Name from CaseMilestone where CaseId=:caseIds AND MilestoneTypeId = :caseAcceptedId];
//loop through them and set completed date etc
for(CaseMilestone cm : cms){
    cm.CompletionDate = System.now();

//then update the caseMilestones
update cms;
  • I've just found out that IsCompleted can't be edited by Apex see this post salesforce.stackexchange.com/questions/1729/…. I'll suggest an edit for your answer to include AND MilestoneTypeId = :caseAcceptedId] for other user's benefit. Thanks Ranga!
    – Alex S
    May 17 '15 at 19:44
  • Nice one. Thanks for sharing :) I've updated the snippet as you suggested
    – Ranga
    May 17 '15 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.