It's a bit of a hack, but you could create a Visualforce page and controller action that will redirect the user to the most recently created Task for a record.
Set the &retURL going into the task creation to send the user to this new VF page and include the parent opporutnity record ID in the query string.
/00T/e?what_id={!Opportunity.Id}&retURL=%2Fapex%2FredirectLastTask?rId=
{!Opportunity.Id}
public with sharing class redirectTaskController {
string recordId = '';
public redirectTaskController() {
recordId = ApexPages.currentPage().getParameters().get('rId');
}
public PageReference redirectToTask() {
PageReference activityPage = new PageReference('/' + recordId);
Task[] recentTasks = [SELECT Id, CreatedDate
FROM Task WHERE WhatId = :recordId
ORDER BY CreatedDate DESC LIMIT 1];
// Check that the new Task if fairly recent.
if (recentTasks.Size() == 1 &&
recentTasks[0].CreatedDate.addHours(1) > Datetime.now()) {
activityPage = new PageReference('/' + recentTasks[0].Id);
}
activityPage.setRedirect(true);
return activityPage;
}
}
Visualforce Page
<apex:page controller="redirectTaskController" action="{!redirectToTask}" >
<p>Redirecting to task</p>
</apex:page>
Another idea would be to create a Visualforce page that uses the Task standardController and provides a custom save action.
Found the solution! Apparently, salesforce automatically adds a parameter called newId to the saveURL.
Just as an example here is my use case - I have an object called Compliance that lives on Opportunity (has a lookup to Opportunity, and is created from Opportunity) and has a many-to-many relationship with Quote and Sales Order (custom objects). The many-to-many relationship is fulfilled via a junction object called Compliance Link, and which has lookup fields to Compliance, Quote, and Sales Order. Users wanted a way to create Compliance records not only from the Opportunity, but also from Quote or Sales Order.
Solution:
Create a button on Quote and on Sales Order, that calls a standard URL for creating a new Compliance record, but then runs some code to create a Junction object record. First it takes user to the standard record type selection page, then it takes the user to the new record EDIT page. Finally, on Save, it redirects the user to a visualforce page (which is never displayed but does some processing). The page's controller gets various parameters from the page's URL, creates a new junction object, and takes the user to the newly-created Compliance record's page.
URL behind the button:
{!$Site.Domain}/setup/ui/recordtypeselect.jsp?ent=01IZ00000000zbt&retURL=%2F{!Quote__c.Id}&save_new_url=%2Fa6Z%2Fe%3FCF00NZ0000000nuQS%3D{!Quote__c.Opportunity__c}%26CF00NZ0000000nuQS_lkid%3D{!Quote__c.OpportunityId__c}%26retURL%3D%252F{!Quote__c.Id}%26saveURL%3D%2Fapex%2FComplianceCreateAndLink%253FquoteId%253D{!Quote__c.Id}
Explanation:
{!$Site.Domain} - have to use this because the record's view is overridden with a visualforce page.
/setup/ui/recordtypeselect.jsp?ent=01IZ00000000zbt - takes you to the recordtype selection page for the object identified by the ent parameter
&retURL=%2F{!Quote__c.Id} - standard return URL, takes you back to the record where you clicked the button.
&save_new_url=%2Fa6Z%2Fe%3FCF00NZ0000000nuQS%3D{!Quote_c.Opportunity_c}%26CF00NZ0000000nuQS_lkid%3D{!Quote_c.OpportunityId_c}%26retURL%3D%252F{!Quote_c.Id}%26saveURL%3D%2Fapex%2FComplianceCreateAndLink%253FquoteId%253D{!Quote_c.Id} - takes you to a standard new object edit page, while prepopulating a lookup field for you. In the save_new_url is another parameter - saveURL, value of which is doublly-url-encoded.
The magic saveURL (double encode it): calls an apex page, while passing it a the original source object ID (Quote ID). Salesforce automatically adds one more parameter to it on invocation - newId: "/apex/ComplianceCreateAndLink?quoteId={!Quote__c.Id}
When Salesforce takes you to this URL, it will look something like this (note the newId parameter that got added automatically):
https://cs11.salesforce.com//apex/ComplianceCreateAndLink?quoteId=1QWE3000000000133&newId=18HG00000000012345
Page:
<apex:page controller="ComplianceCreateAndLinkController" action="{!link}">
Controller:
public class ComplianceCreateAndLinkController {
public Map<String, String> params = null;
public ComplianceCreateAndLinkController() {
params = ApexPages.CurrentPage().getParameters();
}
public PageReference link() {
String complianceId = params.get('newId');
String quoteId = params.get('quoteId');
String sOrderId = params.get('sOrderId');
Compliance_Quote_Link__c newLink = new Compliance_Quote_Link__c();
newLink.Compliance__c = params.get('newId');
newLink.Quote__c = params.get('quoteId');
newLink.Sales_Order__c = params.get('sOrderId');
newLink.Sales_Order_Number__c = params.get('sOrderNumber');
insert newLink;
return new PageReference('/' + newLink.Compliance_Audit__c);
}
}
Note - I guess all this could have been done with Javascript also.
Best Answer
I focused on getting the Cancel action from new Sobject page to return to a page other than from whence I started. Apologies for not using Cases
Foo__c
has record typesa09/e
is the key prefix forFoo__c
ID
is the ID of the record of the VF page where the outputLink exists - I used a standardController to test this; you could use something different heresomeNonFooId
represents your intent - go to a page other than where you came if user clicks Cancel on the new Foo__c page after selecting a recordtype. Your VF page should know what to put here.Code
The trick was to tell the record type selection page to use a provided parameter
save_new_url
as otherwise, the recordtype selection page will generate asave_new_url
for itself with aretURL
that goes back to whence it came (the page with the outputlink). Note thesave_new_url
parameter value contains a parameterretURL
- this is what gets passed to the NewFoo__c
page and is used by the newFoo__c
page's OOB cancel button. I probably could have made the value ofsave_new_url
a URLFOR itself but ran out of time.Of course, URL hacking the record type selection process is subject to SFDC change