Please see code below and comments inside
trigger Account on Account (after insert, after update) {
List<Contact> contactsForUpsert = New List<Contact>();
// We want to avoid SOQL inside the for loop, because it might be a reason of troubles
// and in order to follow best practices, thus we queried all needed information about Contacts
// which are related with Accounts which are under insert/update
// You have to think in 200 record's context when working with triggers
// -->
Map<Id, Contact> contactsByAccountId = new Map<Id, Contact>();
List<Contact> contacts = [SELECT Id,
AccountId,
mailingstreet,
mailingcity,
mailingstate,
mailingpostalcode
FROM Contact WHERE AccountId IN: Trigger.newMap.keySet()];
for (Contact cont: contacts) {
contactsByAccountId.put(cont.accountId, cont);
}
// <-- finished collecting information about Contacts. All contacts were placed in Map<AccountId, Contact>
for (Account account: Trigger.new) {
// old records are available only in update call
Account old;
if (Trigger.isUpdate) {
old = Trigger.oldMap.get(account.Id);
}
// we want to perfoem the update of contact address fields in two cases:
// 1. we insert new account, but there is a question: is that right business case for inserting Contact record here?
// 2. we updated ShippingAddress in an exisitng account, I do believe that we do not want to update Contact record
// each time when other fields were changed
Boolean isShippingAddressChangedOrNew = Trigger.isInsert ? true :
( account.ShippingStreet != old.ShippingStreet
|| account.ShippingCity != old.ShippingCity
|| account.ShippingState != old.ShippingState
|| account.ShippingPostalCode != old.ShippingPostalCode
|| account.ShippingCountry != old.ShippingCountry) ? true : false;
// check that field was changed
if (isShippingAddressChangedOrNew) {
// get existing Contact if exist
Contact relatedContact = contactsByAccountId.get(account.Id);
if (relatedContact == null) { // for insert call we create new Contact record
relatedContact = new Contact();
relatedContact.AccountID = account.Id;
}
relatedContact.mailingstreet = account.Shippingstreet;
relatedContact.mailingcity = account.Shippingcity;
relatedContact.mailingstate = account.Shippingstate;
relatedContact.mailingpostalcode = account.shippingpostalcode;
contactsForUpsert.add(relatedContact);
}
}
try {
upsert contactsForUpsert;
} catch(Dmlexception e) {
System.debug(LoggingLevel.ERROR, 'Contact insert from createopp.trigger has failed with message:' + e.getMessage());
}
}