public inherited sharing class CreateListView { public class Request { @InvocableVariable(required=true label='List View Label') public String listViewLabel; @InvocableVariable(required=true label='Object API Name') public String objectApiName; @InvocableVariable(required=true label='Queue Group Id') public Id groupId; @InvocableVariable(required=true label='Display Columns') public String displayColumns; } public class Result { @InvocableVariable(label='List View API Name') public String listViewApiName; @InvocableVariable(label='Metadata Full Name') public String metadataFullName; @InvocableVariable(label='Created') public Boolean created; } @InvocableMethod( label='Create List View' description='Creates or updates a queue-scoped list view that excludes resolved, cancelled, and closed records.' category='Queue Configuration' callout=true ) public static List createView(List requests) { MetadataXml.require( requests != null && requests.size() == 1, 'Create List View accepts exactly one request per invocation.' ); Request input = requests[0]; input.listViewLabel = input.listViewLabel == null ? null : input.listViewLabel.trim(); input.objectApiName = input.objectApiName == null ? null : input.objectApiName.trim(); MetadataXml.require( !String.isBlank(input.listViewLabel), 'List View Label is required.' ); MetadataXml.require( !String.isBlank(input.objectApiName), 'Object API Name is required.' ); MetadataXml.require(input.groupId != null, 'Queue Group Id is required.'); MetadataXml.require( !String.isBlank(input.displayColumns), 'Display Columns is required.' ); MetadataXml.require( Schema.getGlobalDescribe().containsKey(input.objectApiName), 'Object API Name does not identify an object in this org.' ); List queues = [ SELECT Id, DeveloperName FROM Group WHERE Id = :input.groupId AND Type = 'Queue' WITH USER_MODE LIMIT 1 ]; MetadataXml.require( !queues.isEmpty(), 'Queue Group Id must identify a queue.' ); List columns = new List(); for (String column : input.displayColumns.split(',')) { if (!String.isBlank(column)) { columns.add(column.trim()); } } MetadataXml.require( !columns.isEmpty(), 'Display Columns must contain at least one field.' ); String apiName = MetadataXml.developerName(input.listViewLabel); String fullName = input.objectApiName + '.' + apiName; Boolean existed = MetadataApiClient.readMetadata('ListView', fullName) != null; String metadataXml = '' + MetadataXml.escape(fullName) + ''; for (String column : columns) { metadataXml += '' + MetadataXml.escape(column) + ''; } metadataXml += 'Queue' + '' + MetadataXml.escape(statusField(input.objectApiName)) + 'notEqual' + 'Resolved,Cancelled,Closed' + '' + MetadataXml.escape(queues[0].DeveloperName) + ''; MetadataApiClient.upsertMetadata('ListView', metadataXml); Result result = new Result(); result.listViewApiName = apiName; result.metadataFullName = fullName; result.created = !existed; return new List{ result }; } private static String statusField(String objectApiName) { return objectApiName.equalsIgnoreCase('Case') ? 'CASE.STATUS' : 'Status'; } }