1. CreatedDate/LastModifiedDate of the enhanced note must be same that of the old Note. Create a permission set for that. Follow the steps to create the same-
- From Setup, enter Permission Sets in the Quick Find box, then select Permission Sets.
- Create a new permission set.
- Select System Permissions.
- Click Edit and enable the following permissions:
- In the Systems section:
- a. Modify All Data
- b. Set Audit Fields upon Record Creation
- In the Users section:
- c. View All Users
- In the Systems section:
- Click Save.
- Click Manage Assignments.
- Assign the permission set to anyone who will be converting old Notes into enhanced Note. this typically includes admins.
Sample Code:-
* This class converts all notes related to a record
*
* Uses ‘without sharing’ to ensure can perform SOQL queries on
* existing ContentVersions and ContentDocumentLinks to know if
* a Note has already been converted or not.
*/
public without sharing class ConvertNotesToContentNotesService {
private String parentId { get; set; }
// if context user is a community user then we
// need to pass on the network id to assign to ContentVersion
private ID networkId { get; set; }
public ConvertNotesToContentNotesService( String parentId ) {
this.parentId = parentId;
}
public ConvertNotesToContentNotesService( String parentId, ID networkId ) {
this.parentId = parentId;
this.networkId = networkId;
}
/**
* Each note record should have these fields populated:
* – Id
* – ParentId
* – OwnerId
* – Title
* – Body
* – IsPrivate
* – CreatedById
* – CreatedDate
* – LastModifiedById
* – LastModifiedDate
*/
public void convert() {
List oldNotes = [SELECT id, ownerId, owner.isActive, parentId, title, body, isPrivate,
createdById, createdDate, lastModifiedById, lastModifiedDate
FROM Note
WHERE
parentId = :parentId];
// determine if communities are enabled and if so then we will need
// to assign the network id field when inserting the content versions
// otherwise error “INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY” occurs
// if community user creates a note and it tries to get converted
Boolean communitiesEnabled = ContentVersion.sObjectType.getDescribe().fields.getMap().containsKey( ‘NetworkId’ );
Map oldNotesMap = new Map( oldNotes );
// the new notes to try and save
List newNoteVersions = new List();
for ( Note oldNote : oldNotes ) {
// per Salesforce we must escape certain special characters
// logic inspired by David Reed (http://www.ktema.org//2016/08/24/importing-notes-into-salesforce/)
// https://help.salesforce.com/apex/HTViewSolution?id=000230867&language=en_US
String noteBody = ( String.isBlank( oldNote.body ) ? ” : oldNote.body )
// the escape entity for ‘&’ is ‘&’
// so it includes ‘&’ in its own escape sequence, which is a problem
// because escapeXml() changes ‘&’ to ‘&’ as well
// so a single ‘&’ would become ‘&’
// therefore we first find any normal ‘&’
// and replace them with a token value that will
// be later replaced with ‘&’
.replace(‘&’, ‘sfdcAMPERSANDsfdc’)
.escapeXml()
.replace(‘sfdcAMPERSANDsfdc’, ‘&’)
// handle nitpick on apostrophe html entity
.replace(”’, ‘'’)
// handle known unsupported non-ascii characters
// oddly, other symbols like ® ™ are ok unescaped
.replace(‘©’, ‘©’)
// handle new lines
.replace(‘\r\n’, ‘
‘)
.replace(‘\r’, ‘
‘)
.replace(‘\n’, ‘
‘)
;
// content version cannot have a null or empty string body
// so set to empty paragraph which will appear as blank note.
// we do this after escaping the original note body otherwise
// the
tag would get escaped, doh!
if ( String.isBlank( noteBody ) ) {
noteBody = ‘
‘;
}
// We set the owner of the new content note to be the
// same as the note’s owner because both fields
// must have same value to insert the content note.
// If they do not match then we get error:
// “Documents in a user’s private library must always be owned by that user.”
// The other reason to reference the old record’s owner
// is if the original creator is inactive and the admin
// needs the new converted file to be owned by an active user.
// The owner of records can be changed, the created by cannot.
ContentVersion newNoteVersion = new ContentVersion(
// data fields
title = oldNote.title,
versionData = Blob.valueOf( noteBody ),
pathOnClient = oldNote.title + ‘.snote’,
firstPublishLocationId = oldNote.parentId,
sharingPrivacy = ( oldNote.isPrivate ? ‘P’ : ‘N’ ),
// custom fields for history tracking and conversion purposes
//original_record_id__c = oldNote.id,
//original_record_parent_id__c = oldNote.parentId,
//original_record_owner_id__c = oldNote.ownerId,
// audit fields
ownerId = oldNote.ownerId, // system requirement, owner and creator must be the same
createdById = oldNote.ownerId,
createdDate = oldNote.createdDate,
lastModifiedById = oldNote.lastModifiedById,
lastModifiedDate = oldNote.lastModifiedDate
);
// if communities are enabled then assign network id
if ( communitiesEnabled ) {
newNoteVersion.put( ‘NetworkId’, this.networkId );
}
newNoteVersions.add( newNoteVersion );
}
Database.insert( newNoteVersions);
}
}