You need to sign in to do that
Don't have an account?
Custom Clone Opportunity
As discussed in Ideas (http://ideas.salesforce.com/article/show/69729) here's a solution we have used for clients to enable customisation of the Clone button on Opportunities. This can be used to selectively choose which fields to copy and set default values:
For full details and the code to clone opportunity Line Items please contact me directly. We will be re-writing this in VisualForce over the coming months to make it futureproof.
Steps to Implement - Admins only
1. Setup -> Customize -> Opportunity -> Buttons and Links
2. Create new custom button called Clone, behaviour is Execute Javascript, Display Type Detail Page Button.
3. Paste in the code below and edit to match your requirements.
4. Remember to add the new button to the Opportunity page layout(s) and hide the original Clone button.
4. Test!
// Copyright 2008 BrightGen Ltd - All Rights Reserved try{ {!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")} // ** EDIT THIS QUERY TO LIST THE FIELDS YOU WANT TO COPY ** var result = sforce.connection.query("Select o.Type, o.StageName, o.Product_Type__c, o.Planned_Opportunity__c, o.MarketSector__c, o.CampaignId, o.Business_Unit__c, o.Amount, o.AccountId From Opportunity o WHERE o.Id = '{!Opportunity.Id}'"); var newOpp = result.getArray("records"); // Reset the Opp Id and reset fields to default values newOpp[0].Id = ''; newOpp[0].Name = "Clone {!Opportunity.Name}"; // ** EDIT THESE FIELDS TO SET DEFAULT ANY VALUES ** newOpp[0].StageName = "1. Prospecting"; newOpp[0].CloseDate = new Date(2099, 0, 1); var saveResult = sforce.connection.create(newOpp); if (saveResult[0].getBoolean("success")) { newOpp[0].id = saveResult[0].id; alert("Opportunity cloned without line items"); } else { alert("Failed to create clone: " + saveResult[0]); } // Refresh the page to display the new oppportunity window.location = newOpp[0].id; } catch (err) { alert (err.description ); }
The above code is without the clone opp line items, simply due to trying to keep the example small. If you get in touch with me directly I'm happy to send you the code for the Opp Line Items too.
When you say Mass Close, is this a typo for Mass Clone? In either case, you would need to write a simple Apex class method to do the clone and given a list of IDs VisualForce to create a page a control to do the record selection and display of the cloned results.
If you're interested in this it's something we could discuss development of.
Good stuff. I'm looking for the same solution in Apex/Visualforce. Unfortuneately, list.clone() and list.deepclone() will preserve the ID (which you can not reset as you do in the example below).
Any ideas?
I hate when I do this. I found the answer myself 2 minutes after posting this.
Apex Language Refererence: sObject clone with the opt_preserve_id parameter.
Thanks for the info. I have one question on these. We have fields that the are restricted to some users, but we want those fields to be cloned. Is there a way to clone a field that the user does not have access to? Kind of like a "Clone as admin" button? That would be ideal. Also, the attachments- did you say you had a way to carry those over as well?
Thanks a ton.
public class CaseClone { //courtesy of "Me, Myself and I, Inc." public String CaseNumberOld {get; set; } public String CaseNumberNew {get; set; } public Id CaseIdOld {get; set; } public Id CaseIdNew {get; set; } // this is the constructor public CaseClone (){ //get the passed parm CaseIdOld = System.currentPageReference().getParameters().get('caseid') ; } // this will be invoked from VForce page // in this kind of VForce page / controller, the constructor can not do the work public void doit(){ //SPECIFICALLY EXCLUDE: // , c.Close_Reason__c // , c.ClosedDate // , c.Case_Resolution_Description__c // , c.IsClosed // , c.IsDeleted // , c.CreatedDate // , c.LastModifiedDate // , c.New_Email_Has_Arrived__c // , c.System_Comment_Added__c // , c.System_New_Comment__c // , c.SystemModstamp //this gets the case... Case cOld = [ Select c.AccountId , c.AssetId , c.Best_Time_To_Call__c , c.Bill_For_DCT__c , c.Box_Count__c , c.Caller_Type__c , c.Case_Number_Subject__c , c.Case_Reason_2__c , c.Case_Watchers__c , c.CaseNumber , c.Category__c , c.CB_CC_SAT_Brand__c , c.CB_CC_SAT_Model__c , c.Cities_Affected__c , c.ContactId , c.Controller_Type__c , c.Date_Completed__c , c.Date_Due__c , c.Description , c.Effective_Date__c , c.Email_To_Case_Ref__c , c.Equipment__c , c.External_Case_Number__c , c.Firmware_Version__c , c.GBA__c , c.HasCommentsUnreadByOwner , c.HasSelfServiceComments , c.Head_End_ID__c , c.Host_Version__c , c.Households__c , c.Id , c.Inbound_Email_Address__c , c.IR_Connected__c , c.IR_Work__c , c.Last_Email_Comment__c , c.Legacy_Ticket_Number__c , c.Message_End_Date__c , c.Message_Start_Date__c , c.Message_Title__c , c.Model_Number__c , c.MSO_Account__c , c.MSO_s_Impacted__c , c.Origin , c.OwnerId , c.ParentId , c.Priority , c.Problem_Type__c , c.Product__c , c.Product_Version__c , c.Product_Version_Lvl_2__c , c.Reason , c.Recall_Date__c , c.RecordTypeId , c.Scheme_Version__c , c.SDV_Vendor__c , c.SDV_Vendor_Version__c , c.Second_Reference_Number__c , c.Secondary_Legacy__c , c.Setup_Type__c , c.Status , c.STB_Output_CH__c , c.Sub_Product__c , c.Subject , c.SuppliedCompany , c.SuppliedEmail , c.SuppliedName , c.SuppliedPhone , c.TechOps_Script_File__c , c.Type , c.VOD_Software_Version__c , c.VOD_Vendor__c , c.Zip_Code__c from Case c where id = :CaseIdOld ] ; //grab the old case number CaseNumberOld = cOld.CaseNumber ; // clones the original (resets id) Case cNew = cOld.clone(false, false); //over ride some fields cNew.Subject = '[CLONED CASE] ' + cOld.Subject; cNew.Status = 'New' ; cNew.ParentId = cOld.id ; //insert cloned case insert cNew; CaseIdNew = cNew.Id; //for some reason need to get the CaseNumber... Case cTemp = [select id, CaseNumber from Case where id = :cNew.Id ]; CaseNumberNew = cTemp.CaseNumber; // // COMMENTS // List<CaseComment> CommentsToAdd = new List<CaseComment>(); //loop existing records... for ( CaseComment EachComment : [SELECT CommentBody, CreatedById, CreatedDate, Id , IsPublished, ParentId FROM CaseComment c WHERE parentId = :cOld.id and isDeleted = False LIMIT 50]) { system.debug ('********** ' + EachComment.Id) ; CaseComment NewComment = EachComment.clone(false, false); NewComment.ParentId = cNew.Id ; NewComment.CommentBody = '[CLONED COMMENT] ' + NewComment.CommentBody ; CommentsToAdd.add(NewComment); } // this creates a brand new comment with information about this process CaseComment NewComment = new CaseComment(); NewComment.ParentId = cNew.Id ; NewComment.CommentBody = 'Note: this case was created via a CLONE of case ' + CaseNumberOld ; NewComment.IsPublished = False ; CommentsToAdd.add(NewComment); //ready to insert? insert CommentsToAdd ; // // ATTACHMENTS // // SPecifically excluded from attachment query... // , a.SystemModstamp // , a.CreatedById // , a.CreatedDate // , a.IsDeleted // , a.IsPrivate // , a.LastModifiedById // , a.LastModifiedDate //create a list of items to add... List<Attachment> AttachmentsToAdd = new List<Attachment>(); //loop existing records... for ( Attachment EachAttachment : [Select a.Body , a.BodyLength , a.ContentType , a.Id , a.Name , a.OwnerId , a.ParentId from Attachment a WHERE parentId = :cOld.id and isDeleted = False LIMIT 50]) { system.debug ('********** ' + EachAttachment.Name ) ; Attachment aNew = EachAttachment.clone(false, false); aNew.ParentId = cNew.Id ; AttachmentsToAdd.add(aNew); } insert AttachmentsToAdd ; } }
<apex:page controller="CaseClone" action="{!doit}"><apex:pageBlock title="Hello {!$User.FirstName}!"><br />Your support case has been cloned!<br /><br /><i><b>Warning! Do not hit "refresh" on your browser or your case will be cloned AGAIN</b></i><br /><br /><br /><table cellpadding="10"><tr> <td>Original Case Number:</td> <td>{!CaseNumberOld}</td> <td><a href="/{!CaseIdOld}">Go to this case...</a></td></tr><tr> <td>New Case Number:</td> <td>{!CaseNumberNew}</td> <td> <a href="/{!CaseIdNew}">Go to this case...</a>:</td></tr></table><br /><br /></apex:pageBlock></apex:page>
Wow, that does not look good. Let's try that again...
public class CaseClone { //courtesy of "Me, Myself and I, Inc." public String CaseNumberOld {get; set; } public String CaseNumberNew {get; set; } public Id CaseIdOld {get; set; } public Id CaseIdNew {get; set; } // this is the constructor public CaseClone (){ //get the passed parm CaseIdOld = System.currentPageReference().getParameters().get('caseid') ; } // this will be invoked from VForce page // in this kind of VForce page / controller, the constructor can not do the work public void doit(){ //SPECIFICALLY EXCLUDE: // , c.Close_Reason__c // , c.ClosedDate // , c.Case_Resolution_Description__c // , c.IsClosed // , c.IsDeleted // , c.CreatedDate // , c.LastModifiedDate // , c.New_Email_Has_Arrived__c // , c.System_Comment_Added__c // , c.System_New_Comment__c // , c.SystemModstamp //this gets the case... Case cOld = [ Select c.AccountId , c.AssetId , c.Best_Time_To_Call__c , c.Bill_For_DCT__c , c.Box_Count__c , c.Caller_Type__c , c.Case_Number_Subject__c , c.Case_Reason_2__c , c.Case_Watchers__c , c.CaseNumber , c.Category__c , c.CB_CC_SAT_Brand__c , c.CB_CC_SAT_Model__c , c.Cities_Affected__c , c.ContactId , c.Controller_Type__c , c.Date_Completed__c , c.Date_Due__c , c.Description , c.Effective_Date__c , c.Email_To_Case_Ref__c , c.Equipment__c , c.External_Case_Number__c , c.Firmware_Version__c , c.GBA__c , c.HasCommentsUnreadByOwner , c.HasSelfServiceComments , c.Head_End_ID__c , c.Host_Version__c , c.Households__c , c.Id , c.Inbound_Email_Address__c , c.IR_Connected__c , c.IR_Work__c , c.Last_Email_Comment__c , c.Legacy_Ticket_Number__c , c.Message_End_Date__c , c.Message_Start_Date__c , c.Message_Title__c , c.Model_Number__c , c.MSO_Account__c , c.MSO_s_Impacted__c , c.Origin , c.OwnerId , c.ParentId , c.Priority , c.Problem_Type__c , c.Product__c , c.Product_Version__c , c.Product_Version_Lvl_2__c , c.Reason , c.Recall_Date__c , c.RecordTypeId , c.Scheme_Version__c , c.SDV_Vendor__c , c.SDV_Vendor_Version__c , c.Second_Reference_Number__c , c.Secondary_Legacy__c , c.Setup_Type__c , c.Status , c.STB_Output_CH__c , c.Sub_Product__c , c.Subject , c.SuppliedCompany , c.SuppliedEmail , c.SuppliedName , c.SuppliedPhone , c.TechOps_Script_File__c , c.Type , c.VOD_Software_Version__c , c.VOD_Vendor__c , c.Zip_Code__c from Case c where id = :CaseIdOld ] ; //grab the old case number CaseNumberOld = cOld.CaseNumber ; // clones the original (resets id) Case cNew = cOld.clone(false, false); //over ride some fields cNew.Subject = '[CLONED CASE] ' + cOld.Subject; cNew.Status = 'New' ; cNew.ParentId = cOld.id ; //insert cloned case insert cNew; CaseIdNew = cNew.Id; //for some reason need to get the CaseNumber... Case cTemp = [select id, CaseNumber from Case where id = :cNew.Id ]; CaseNumberNew = cTemp.CaseNumber; // // COMMENTS // List<CaseComment> CommentsToAdd = new List<CaseComment>(); //loop existing records... for ( CaseComment EachComment : [SELECT CommentBody, CreatedById, CreatedDate, Id , IsPublished, ParentId FROM CaseComment c WHERE parentId = :cOld.id and isDeleted = False LIMIT 50]) { system.debug ('********** ' + EachComment.Id) ; CaseComment NewComment = EachComment.clone(false, false); NewComment.ParentId = cNew.Id ; NewComment.CommentBody = '[CLONED COMMENT] ' + NewComment.CommentBody ; CommentsToAdd.add(NewComment); } // this creates a brand new comment with information about this process CaseComment NewComment = new CaseComment(); NewComment.ParentId = cNew.Id ; NewComment.CommentBody = 'Note: this case was created via a CLONE of case ' + CaseNumberOld ; NewComment.IsPublished = False ; CommentsToAdd.add(NewComment); //ready to insert? insert CommentsToAdd ; // // ATTACHMENTS // // SPecifically excluded from attachment query... // , a.SystemModstamp // , a.CreatedById // , a.CreatedDate // , a.IsDeleted // , a.IsPrivate // , a.LastModifiedById // , a.LastModifiedDate //create a list of items to add... List<Attachment> AttachmentsToAdd = new List<Attachment>(); //loop existing records... for ( Attachment EachAttachment : [Select a.Body , a.BodyLength , a.ContentType , a.Id , a.Name , a.OwnerId , a.ParentId from Attachment a WHERE parentId = :cOld.id and isDeleted = False LIMIT 50]) { system.debug ('********** ' + EachAttachment.Name ) ; Attachment aNew = EachAttachment.clone(false, false); aNew.ParentId = cNew.Id ; AttachmentsToAdd.add(aNew); } insert AttachmentsToAdd ; } }
I can't see your original code, so can only extrapolate what is going on from the error message.
I believe that the opportunity object will always have id's starting with 006 (that's zero zero six). You seem to have an id of '06R' which I can only guess is a custom object. Therefore, I have to conclude that you are trying to stick the wrong Id into the opportunity ID foreign key. Just a guess...
Hi Fra08,
I had the same fail when I once mixed 2 ID. BTW, I'm trying the same thing here and my code is as follows, but I'm getting "undefined" so not getting to the insert, since you are getting a DB message can you tell me the way?
try{
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
// ** EDIT THIS QUERY TO LIST THE FIELDS YOU WANT TO COPY **
var result = sforce.connection.query("Select o.Tipo_de_Cota_o_2__c, o.AccountId, o.Name, o.Id, o.StageName, o.RecordTypeId, o.CloseDate From Opportunity o WHERE o.Id = '{!Opportunity.Id}'");
var newOpp = result.getArray("records");
// Reset the Opp Id and reset fields to default values
newOpp[0].Id = '';
newOpp[0].Name = "{!Opportunity.Name} - Pedido";
newOpp[0].RecordTypeId = '012400000009YRRAA2';
newOpp[0].Cotacao__c = '{!Opportunity.Id}';
var saveResult = sforce.connection.create(newOpp);
if (saveResult[0].getBoolean("success")) {
newOpp[0].id = saveResult[0].id;
alert("Corpo do Pedido Gerado com sucesso");
}
else {
alert("Falha para gerar o pedido: " + saveResult[0]);
}
var result1 = sforce.connection.query("Select t.Bloqueio_c__c, t.C_digo_do_produto__c, t.C_digo_do_Status_do_tem__c, t.codigocondicaodepagamento__c, t.COFINS__c, t.Com_Lote__c, t.desccondicaodepagamento__c, t.Desconto_extra__c, t.Descontoda_categoria__c, t.Descri_o_do_Status_do_tem__c, t.Encargos_financeiros_2__c, t.Estoque__c, t.Fator_de_equalizacao__c, t.Flag_Minimo_e_Multiplo__c, t.Frete_de_compra_2__c, t.Frete_de_venda_2__c, t.ICMS_DA_Cliente__c, t.ICMS_GY_DA__c, t.IPI__c, t.ListPrice, t.Lote__c, t.Lote_automatico__c, t.M_ltiplo__c, t.Markup__c, t.Minimo__c, t.Observa_es__c, t.OpportunityId, t.PIS__c, t.Preco_Venda_Total__c, t.PrecoPadrao__c, t.precovenda__c, t.PricebookEntryId, t.Quantity, t.Saldo__c, t.Status_de_Bloqueio_do_Item__c, t.Teste_Picklist__c, t.TipoRegistro__c, t.TotalPrice, t.Unidade__c, t.UnitPrice from OpportunityLineItem t WHERE t.OpportunityId = '{!Opportunity.Id}'");
var newOppline = result1.getArray("records");
// Reset the Opp Id and reset fields to default values
var i=0;
for (i=0;i<=20;i++) {
newOppline[i].Id = '';
newOppline[i].OpportunityId = newOpp[0].id
newOppline[i].Quantity = 0;
var saveResult1 = sforce.connection.create(newOppLine);
if (saveResult1[i].getBoolean("success")) {
newOppLine[i].id = saveResult1[i].id;
alert("Linha do Pedido Gerada com sucesso");
}
else {
alert("Falha para gerar a linha do pedido: " + saveResult1[i]);
}
}
// Refresh the page to display the new oppportunity
window.location = newOpp[0].id;
}
catch (err) {
alert (err.description );
}
{
//** <script type="text/javascript" src="/soap/ajax/14.0/connection.js"></script> **
{!requireScript("/soap/ajax/14.0/connection.js")}
// ** EDIT THIS QUERY TO LIST THE FIELDS YOU WANT TO COPY **
var result = sforce.connection.query("Select o.Type, o.StageName From Opportunity o WHERE o.Id = '{!Opportunity.Id}'");
var newOpp = result.getArray("records");
// Reset the Opp Id and reset fields to default values
newOpp[0].Id = '';
newOpp[0].Name = "Clone {!Opportunity.Name}";
// ** EDIT THESE FIELDS TO SET DEFAULT ANY VALUES **
newOpp[0].StageName = "Qualification";
newOpp[0].CloseDate = new Date(2099, 0, 1);
var saveResult = sforce.connection.create(newOpp);
if (saveResult[0].getBoolean("success"))
{
newOpp[0].id = saveResult[0].id;
//var sOportunity = newOpp[0].id.substring(0, newOpp[0].id.length - 3)
// duplicamos tambien los productos de la Opportunity original
var oppLineItemQuery = sforce.connection.query("select PricebookEntryId, Model__c, Operators__c, Months__c, Quantity, UnitPrice from OpportunityLineItem where OpportunityId = '{!Opportunity.Id}'");
oppLineItemList = oppLineItemQuery.getArray("records");
var examOrderItemArray = new Array();
for(var i = 0;i<oppLineItemList.length;i++)
{
oppLineItems = oppLineItemList[i];
var examOrderItem = new sforce.SObject("OpportunityLineItem");
examOrderItem.set("OpportunityId", newOpp[0].id);
//examOrderItem.set("PricebookEntryId", "01uR0000000sZ9IIAU");
examOrderItem.set("PricebookEntryId", oppLineItems.get("PricebookEntryId"));
examOrderItem.set("Model__c", oppLineItems.get("Model__c"));
examOrderItem.set("Operators__c", oppLineItems.get("Operators__c"));
examOrderItem.set("Months__c", oppLineItems.get("Months__c"));
examOrderItem.set("Quantity", oppLineItems.get("Quantity"));
examOrderItem.set("UnitPrice", oppLineItems.get("UnitPrice"));
examOrderItemArray.push(examOrderItem);
}
try {
var examOrderItemSaveResults = sforce.connection.create(examOrderItemArray);
for (var i=0; i<examOrderItemSaveResults.length; i++)
{
if (!examOrderItemSaveResults[i].getBoolean("success")) alert("failed to create ProductLine " + examOrderItemSaveResults[i]);
/*
{
alert("new ProductLine created with id " + examOrderItemSaveResults[i].id);
} else {
alert("failed to create ProductLine " + examOrderItemSaveResults[i]);
}
*/
}
}
catch(error)
{
sforce.debug.log(error.faultcode);
sforce.debug.log(error.faultstring);
}
} else {
alert("Failed to create clone: " + saveResult[0]);
}
// Refresh the page to display the new oppportunity
window.location = newOpp[0].id;
}
catch (err) {
sforce.debug.log(err.faultcode);
sforce.debug.log(err.faultstring);
}
Thank you very much for your code. It has helped us to move forward. But we are still getting one fail msg, that follows bellow. Have you had this problem as well? We have already tryied the Opp ID with 18 digits and 15 digits but we are still getting that fail msg, but we know that the opp is been inserted. Thanks again.
"failed to create ProductLine {errors:{fields:'OpportunityId', message:'Campos obrigatórios ausentes: [OpportunityId]', statusCode:'REQUIRED_FIELD_MISSING', }, id:null, success:'false', }"
try{
//** <script type="text/javascript" src="/soap/ajax/14.0/connection.js"></script> **
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
// ** EDIT THIS QUERY TO LIST THE FIELDS YOU WANT TO COPY **
var result = sforce.connection.query("Select o.Tipo_de_Cota_o_2__c, o.AccountId, o.Name, o.Id, o.StageName, o.RecordTypeId, o.CloseDate From Opportunity o WHERE o.Id = '{!Opportunity.Id}'");
var newOpp = result.getArray("records");
// Reset the Opp Id and reset fields to default values
newOpp[0].Id = '';
newOpp[0].Name = "{!Opportunity.Name} - Pedido";
newOpp[0].RecordTypeId = '012400000009YRRAA2';
newOpp[0].Cotacao__c = '{!Opportunity.Id}';
var saveResult = sforce.connection.create(newOpp);
if (saveResult[0].getBoolean("success")){
newOpp[0].id = saveResult[0].id;
var sOportunity = newOpp[0].id.substring(0, newOpp[0].id.length - 3);
alert ("ID Oportunidade " + newOpp[0].id + "ID - 3 >" + sOportunity);
var oppLineItemQuery = sforce.connection.query("Select t.Id, t.Bloqueio_c__c, t.C_digo_do_produto__c, t.C_digo_do_Status_do_tem__c, t.codigocondicaodepagamento__c, t.COFINS__c, t.Com_Lote__c, t.desccondicaodepagamento__c, t.Desconto_extra__c, t.Descontoda_categoria__c, t.Descri_o_do_Status_do_tem__c, t.Flag_Minimo_e_Multiplo__c, t.IPI__c, t.Lote__c, t.Lote_automatico__c, t.Observa_es__c, t.OpportunityId, t.PIS__c, t.PrecoPadrao__c, t.precovenda__c, t.PricebookEntryId, t.Quantity, t.Saldo__c, t.Status_de_Bloqueio_do_Item__c, t.Teste_Picklist__c, t.Unidade__c, t.UnitPrice from OpportunityLineItem t WHERE t.OpportunityId = '{!Opportunity.Id}'");
oppLineItemList = oppLineItemQuery.getArray("records");
var examOrderItemArray = new Array();
for(var i = 0;i<oppLineItemList.length;i++){
oppLineItems = oppLineItemList[i];
var examOrderItem = new sforce.SObject("OpportunityLineItem");
examOrderItem.set("OpportunityId", sOportunity);
examOrderItem.set("Bloqueio_c__c", oppLineItems.get("Bloqueio_c__c"));
examOrderItem.set("C_digo_do_produto__c",oppLineItems.get("C_digo_do_produto__c"));
examOrderItem.set("C_digo_do_Status_do_tem__c", oppLineItems.get("C_digo_do_Status_do_tem__c"));
examOrderItem.set("codigocondicaodepagamento__c",oppLineItems.get("codigocondicaodepagamento__c"));
examOrderItem.set("COFINS__c", oppLineItems.get("COFINS__c"));
examOrderItem.set("Com_Lote__c", oppLineItems.get("Com_Lote__c"));
examOrderItem.set("desccondicaodepagamento__c",oppLineItems.get("desccondicaodepagamento__c"));
examOrderItem.set("Desconto_extra__c",oppLineItems.get("Desconto_extra__c"));
examOrderItem.set("Descontoda_categoria__c", oppLineItems.get("Descontoda_categoria__c"));
examOrderItem.set("Descri_o_do_Status_do_tem__c", oppLineItems.get("Descri_o_do_Status_do_tem__c"));
// errado examOrderItem.set("Encargos_financeiros_2__c", oppLineItems.get("Encargos_financeiros_2__c"));
// errado examOrderItem.set("Estoque__c", oppLineItems.get("Estoque__c"));
// errado examOrderItem.set("Fator_de_equalizacao__c", oppLineItems.get("Fator_de_equalizacao__c"));
examOrderItem.set("Flag_Minimo_e_Multiplo__c", oppLineItems.get("Flag_Minimo_e_Multiplo__c"));
// errado examOrderItem.set("Frete_de_compra_2__c", oppLineItems.get("Frete_de_compra_2__c"));
// errado examOrderItem.set("Frete_de_venda_2__c", oppLineItems.get("Frete_de_venda_2__c"));
// errado examOrderItem.set("ICMS_DA_Cliente__c", oppLineItems.get("ICMS_DA_Cliente__c"));
// errado examOrderItem.set("ICMS_GY_DA__c", oppLineItems.get("ICMS_GY_DA__c"));
examOrderItem.set("IPI__c", oppLineItems.get("IPI__c"));
//examOrderItem.set("ListPrice", oppLineItems.get("ListPrice"));
examOrderItem.set("Lote__c", oppLineItems.get("Lote__c"));
examOrderItem.set("Lote_automatico__c", oppLineItems.get("Lote_automatico__c"));
// errado examOrderItem.set("M_ltiplo__c", oppLineItems.get("M_ltiplo__c"));
// errado examOrderItem.set("Markup__c", oppLineItems.get("Markup__c"));
// errado examOrderItem.set("Minimo__c",oppLineItems.get("Minimo__c"));
examOrderItem.set("Observa_es__c", oppLineItems.get("Observa_es__c"));
examOrderItem.set("OpportunityId", oppLineItems.get("Operators__c"));
examOrderItem.set("PIS__c", oppLineItems.get("PIS__c"));
// errado examOrderItem.set("Preco_Venda_Total__c", oppLineItems.get("Preco_Venda_Total__c"));
examOrderItem.set("PrecoPadrao__c", oppLineItems.get("PrecoPadrao__c"));
examOrderItem.set("precovenda__c", oppLineItems.get("precovenda__c"));
examOrderItem.set("PricebookEntryId", oppLineItems.get("PricebookEntryId"));
examOrderItem.set("Quantity",0);
examOrderItem.set("Saldo__c",oppLineItems.get("Saldo__c"));
examOrderItem.set("Status_de_Bloqueio_do_Item__c", oppLineItems.get("Status_de_Bloqueio_do_Item__c"));
examOrderItem.set("Teste_Picklist__c", oppLineItems.get("Teste_Picklist__c"));
//errado examOrderItem.set("TipoRegistro__c", oppLineItems.get("TipoRegistro__c"));
//errado examOrderItem.set("TotalPrice", oppLineItems.get("TotalPrice"));
examOrderItem.set("Unidade__c", oppLineItems.get("Unidade__c"));
examOrderItem.set("UnitPrice",oppLineItems.get("UnitPrice"));
examOrderItemArray.push(examOrderItem);
}
try {
var examOrderItemSaveResults = sforce.connection.create(examOrderItemArray);
}catch(error){
sforce.debug.log(error.faultcode);
sforce.debug.log(error.faultstring);
}
for (var i=0; i<examOrderItemSaveResults.length; i++){
if (!examOrderItemSaveResults[i].getBoolean("success")){
alert("failed to create ProductLine " + examOrderItemSaveResults[i]);
}
}
} else {
alert("Failed to create clone: " + saveResult[0]);
}
// Refresh the page to display the new oppportunity
window.location = newOpp[0].id;
} catch (err) {
sforce.debug.log(err.faultcode);
sforce.debug.log(err.faultstring);
}
http://sites.force.com/appexchange/listingDetail?listingId=a0N30000001SRXAEA4
Hi Thanks for the code works great.
one problem thought , how can i get it to add 365 days to the cloned opportuntie so we can use it as a renewal.
Thanks
Jake
Hello bg_richard... Would it be possible for me to get a copy of all the opp clone changes, including the line items as well?
Regards,
Having some problems, the error I am receiving is:
"invalid assignment left hand side"
I got past the undefined argument errors, here is my code:
try{
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
// use this select statement to pull the field data from old dp that you want in the new DP
var result = sforce.connection.query("Select dp.Product__c, dp.Related_ContactId__c, dp.Related_OpportunityId__c, dp.Corp_ID__c, dp.Client_received_a_live_demo__c, dp.Fusion_Demo_Complete_Date__c, dp.Fusion_Mode__c, dp.Is_using_a_dedicated_Fusion_seat__c, dp.Salesforce_Version__c, dp.SFDC_is_backed_up__c, dp.Which_objects_Fusion_to_Manage__c, dp.Sync_Status__c, dp.Sync_Start_Timestamp__c, dp.Sync_Complete_Timestamp__c, dp.Data_SpecialistId__c From Data_Project__c dp WHERE dp.Name = '{!Data_Project__c.Name}'");
var newDP = result.getArray("records");
// Reset the DP ID and reset fields to default values
newDP[0].{!Data_Project__c.Name} = '';
// ** EDIT THESE FIELDS TO SET DEFAULT ANY VALUES **
newDP[0].{!Data_Project__c.Pissed_Blissed_Score__c} = '';
newDP[0].{!Data_Project__c.Project_Summary__c} = "Test Value";
var saveResult = sforce.connection.create(newDP);
if (saveResult[0].getBoolean("success")) {
newDP[0].{!Data_Project__c.Name} = saveResult[0].{!Data_Project__c.Name};
alert("Data Project cloned without related line items");
}
else {
alert("Failed to create clone: " + saveResult[0]);
}
// Refresh the page to display the new data proj
window.location = newDP[0].{!Data_Project__c.Name};
}
catch (err) {
alert (err.description );
}
Should I be using the "ID" value for the lookup fields that are being selected above or should I select the actual values of those related fields?
Any help is very appreciated in advance!
I have an unmanaged package using VisualForce for those that can't (or no longer want to) use S-Controls. It includes a method for Clone Opportunity and Clone Opportunity with Product Line Items. It requires knowledge of Apex to edit the class to set your defaults, and hence is no good installing into a production Org. You'll need to install it to your Sandbox, make the changes below, test it then promote it to your live org using Metadata publish or Change Sets.
Here's the link to the package: Unmanaged Clone Opportunity Package
Instructions are as follows:
1. Install the package to your sandbox
2. Edit the Apex Class CloneOpportunity and look for all the TODO lines. The package will work for vanilla Orgs but if you want to set your own default values or ensure all your fields are copied you need to edit the code.
3. The package includes 2 custom buttons CloneOpportunity and Clone_With_Products, these both point to the same Visualforce page - if you want to have both you'll need to do some additional development or get some help (see below). For now, just make sure you add one to your opportunity page layout.
4. You need to make sure your user profiles can access the Visualforce page "CloneOpportunity". This page doesn't render, it's just the hidden glue to link the Buttons to the Apex code.
5. Test!
6. Install your changes to your production instance.
The package assumes you want to call the Clone With Products function out of the box. As mentioned above you can change this by editing the CloneOppButtonController apex class, there is a TODO comment telling you what to change
If you need help customising this then please contact me, otherwise good luck!
Checking it out in a sandbox right now. Looking good so far!
Thanks for your efforts on a tool like this.
Reccomend everyone vote up this idea:
https://sites.secure.force.com/ideaexchange//apex/ideaView?c=09a30000000D9xt&id=08730000000BpUXAA0
Thnx.
Thanks so much for posting this code. It works great and exactly what I needed. However, I'm having trouble customizing - any help would be greatly appreciated.
There are some fields in the new opportunity, that need to be populated with data from a different field in the old opportunity.
For example, I need for the new opportunity "Close Date" to be equal to the old opportunity "Contract End Date". I did this before with:
newOpp[0].CloseDate = new Date("{!Opportunity.ContractEndDate__c}");
And, I need the new opportunity "Name" to include fields from the old opportunty. I previously accomplished this with the following code:
newOpp[0].Name = "{!Opportunity.ContractEndDate__c} - {!Opportunity.Product_Type__c} ({!Opportunity.End_User_Company__c})";
Hi Marya,
Difficult to debug your issues without being able to see the changes you've made in context. It may be as simple as not changing from double to single quotes. However, here's how I'd change the code to do as you describe, compare the difference:
CloneOpportunity Class: cloneOpp method
In the SELECT SOQL statement (Lines 20-23) add your custom fields, changes in bold:
// TODO: Amend this method to set the fields you wish to bring across // if they're not in the SELECT they won't be copied Opportunity origOpp = [SELECT Name, CloseDate, StageName, Amount, AccountId, CampaignId, Type, Description
,ContractEndDate__c, Product_Type__c, End_User_Company__c
FROM Opportunity WHERE Id = :oppId][0];
At line 30 & 31, replace my Name and CloseDate fields with your own settings:
cloneOpp.Name = origOpp.Contract_End_Date__c + '-' + origOpp.Product_Type__c + ' (' + origOpp.End_User_Company__c + ')';
cloneOpp.CloseDate = origOpp.Contract_End_Date__c;
Of course, the old way using s-controls will still work with Spring 10, so if you prefer stick to that. It's only new SFDC customers that have to now use the Visualforce/Apex solution.
Thanks so much. Working like a charm. :smileyvery-happy:
One last question - for the opportunity name, where I'm displaying the close date, is there a way to format the date so it's MM/DD/YY? Currently, it displays as YYYY-MM-DD HH:MM:SS, which is overkill for an oppurtunity name.
cloneOpp.Name = origOpp.ContractEndDate__c + origOpp.Product_Type__c + ' (' + origOpp.End_User_Company__c + ')';
Nevermind on the date thing. It may not be the prettiest thing, but I got it to work:
cloneOpp.Name = origOpp.ContractEndDate__c.month() + '/' + origOpp.ContractEndDate__c.day() + '/' + origOpp.ContractEndDate__c.year() + ' ' + origOpp.Product_Type__c + ' (' + origOpp.End_User_Company__c + ')';
We've now released a free package on the AppExchange that takes away the need to understand either S-Controls or Apex. It's a simple to use tool for Admins that allows them to set up default values, or blank fields for a limited set of standard salesforce objects. The free package currently supports: Account, Case, Contact, Event, Opportunity, OpportunityLineItem, Product and Task objects.
Unfortunately custom objects are not supported but custom fields on the above are.
Here's the link to the AppExchange listing: http://sites.force.com/appexchange/listingDetail?listingId=a0N30000003IxcZEAS
I am getting an undefined error every time I try to modify this. Here is my code (I kept it simple fro testing, I will be adding more once I know what the problem is):
// Copyright 2008 BrightGen Ltd - All Rights Reserved
try{
{!REQUIRESCRIPT("/soap/ajax/14.0/connection.js")}
// ** EDIT THIS QUERY TO LIST THE FIELDS YOU WANT TO COPY **
var result = sforce.connection.query("Select o.Account, o.StageName, o.Name, o.CloseDate From Opportunity o WHERE o.Id = '{!Opportunity.Id}'");
var newOpp = result.getArray("records");
// Reset the Opp Id and reset fields to default values
newOpp[0].Id = '';
newOpp[0].Name = "Clone {!Opportunity.Name}";
// ** EDIT THESE FIELDS TO SET DEFAULT ANY VALUES **
newOpp[0].StageName = "In Applications Engineering";
newOpp[0].CloseDate = new Date(2099, 0, 1);
var saveResult = sforce.connection.create(newOpp);
if (saveResult[0].getBoolean("success")) {
newOpp[0].id = saveResult[0].id;
alert("Opportunity cloned without line items");
}
else {
alert("Failed to create clone: " + saveResult[0]);
}
// Refresh the page to display the new oppportunity
window.location = newOpp[0].id;
}
catch (err) {
alert (err.description );
}
If anyone can help I would really appreciate it.
Thanks!!
The javascript undefined error is basically it's way of saying you're trying to reference something that doesn't exist or is null. This would occur if you try and reference a non-existant attribute (try adding o.Id to your SELECT statement first), or because no data is returned by the SELECT statement.
To avoid wasting time you should also use debug statements to track between which points the error is occuring. Simply add something like:
is easiest.
Finally, frustration debugging this (I wrote the original post while at BrightGen) and SFDC dropping s-Controls for new Orgs, is why I redeveloped it as a free Managed Apex Package (see previous item in thread) which works on Professional Edition too. For all that you're trying to do it should meet your needs.
Good luck.
@bg_richard - Could you please email me the full code that supports opp line items? Cheers! Sorry - you probably need this cfederspiel@ic-2000.com
How would this be different if I wanted the custom clone to perform ALL the standard clone functions with the exception that the New Opp Owner will be the same as the original, rather than being the current user?
Thanks in advance!
Hi,
I've subsequently developed an Apex package to replace the Javascript solution. I no longer publish the Javascript versin but you can install EnthClone from the AppExchange for free, and this includes the cloning of line items. It's also much easier to use than the Javascript version!
Richard
Exactly what I was looking for. Thanks!
Thank you for this code. Can you please send me the code for cloning with the Opportunity Line Items?
We have a free managed package on the AppExchange that does this. We no longer provide the Apex source code now for legal reasons.