Pages

Thursday 2 February 2012

system.security.NoAccessException : Update access denied on Pricebookentry

In my current assignment, I got a very strange issue which made me frustrated .

My task was to customize the "Add Product" functionality on Opportunity. Every thing was working fine until it was tested with the profile wherein no CREATE or EDIT permission was granted for PRICEBOOK sObject.
My own code rewarded me the exception

system.security.NoAccessException : Update access denied on Pricebookentry

at the final stage of adding products (on hitting the SAVE button).

I was puzzled because I used only one DML statement in my controller extension that was insert statement against OpportunityLineItem. I commented the insert statement and was still getting the same exception. If I provide CREATE or EDIT permission for PRICEBOOK then I was not getting the exception.

Bad luck, that I could not grant permision to some profiles as security was also a concern. I needed to play with my code and finally I resolved it after a hard work.

I used a Relationship query to get data from product2,pricebookentry,Pricebook2 objects. This gives me a list of pricebookentry.I used this  list of PriceBookEntry and bind it to PageBlockTable on my visualforce page. But when I hit save, I suspect the getter method of that list was generating the exception.

I never thought that Wrapper class  can save me in this situation.

Now I think I should share the resolution. Instead of binding the PageBlockTable with the list of pricebookentry, I created a wrapper class in following format :


 public class WrapPirceBook
    {
       Public Product2 prod {get;set;}
       public Decimal UnitPrice {get;set;}
       public ID Product2Id;
       public ID Pricebook2Id {get;set;}   
       public ID mainID {get;set;}   
        
       public WrapPirceBook(Product2 pro,Decimal u,ID p,ID c,ID ids) 
       {
            prod=pro;
            UnitPrice=u;
            Product2Id=p;
            Pricebook2Id=c;
            mainID =ids;
        }
    }
Now I am not using pricebookentry directly, instead I am doing all the stuff but without direct access of pricebookentry. After this implementation, when I hit save, I was on Cloud9. I was very happy to see that when I click on save, it saved all the selected products with the Opportunity.

I used wrapper class to resolve the issue but still I was using pricebookentry instead of Product2. I wanna say special thanks to my MANAGER who directed me to use Product2 instead of pricebookentry in the wrapper class.

Hope this helps if someone gets the same or similar problem. However, I am open if any body wants my help to get more knowledge about this functionality.

Sunday 15 January 2012

Close Popup and refresh parent window


It is very common requirement to open a pop up by clicking a button . Once you are done with pop up, close the pop up and refresh the parent window so that user will be able to see the update on parent window at the same time.

Here is the sample code for it:

<apex:commandbutton action="{!save}" id="button" oncomplete="javascript:CloseAndRefresh()" value="Update"/>

and here is the java script function

<script language="JavaScript" type="text/javascript">
function CloseAndRefresh(){
window.opener.location.href="/{!$CurrentPage.parameters.id}";
      window.top.close();
   
  }
</script>

Note : I would suggest to check this setting Setup-> Personal Setup  ->  My Personal Information -> Personal Information
Here check for "Development Mode". I have seen at various places and at community as well that if this check box is checked then popup would not close. Here, I would suggest to turn this checkbox off while you are testing this.

Tuesday 15 November 2011

How to create a visual force page to submit the Opportunity for mass approval or rejection

Hello friends,

Some time it may happen that you need a custom functionality for mass submission of Opportunity for approval and rejection. Here is the apex and visual force code for this functionality.

I have used wrapper class in this functionality.

Apex Controller :


    public class wrapperClassController {
    
        //Our collection of the class/wrapper objects cContact 
        public List<cContact> contactList {get; set;}
    
        //This method uses a simple SOQL query to return a List of Contacts
        public List<cContact> getContacts() {
            if(contactList == null) {
                contactList = new List<cContact>();
                for(Opportunity c: [select Id, Name from Opportunity ]) {
                    // As each contact is processed we create a new cContact object and add it to the contactList
                    contactList.add(new cContact(c));
                }
            }
            return contactList;
        }
    
    
        public PageReference processSelected() 
        {
            try
            {
    
                    //We create a new list of Contacts that we be populated only with Contacts if they are selected
            List<Opportunity > selectedContacts = new List<Opportunity >();
    
            //We will cycle through our list of cContacts and will check to see if the selected property is set to true, if it is we add the Contact to the selectedContacts list
            for(cContact cCon: getContacts()) {
                if(cCon.selected == true) {
                    selectedContacts.add(cCon.con);
                }
            }
    
            // Now we have our list of selected contacts and can perform any type of logic we want, sending emails, updating a field on the Contact, etc
            
     
            for(Opportunity con: selectedContacts) 
            {
                Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
                req.setComments('Submitted for approval. Please approve.');
                req.setObjectId(con.Id);
                // submit the approval request for processing
                Approval.ProcessResult result = Approval.process(req);
                // display if the reqeust was successful
                System.debug('Submitted for approval successfully: '+result.isSuccess());
            }
    
    
            }
            catch(Exception ex)
            {}
                    PageReference pageRef = new PageReference('/');
            pageRef.setRedirect(true);
                    return pageRef;
        }
    
    
        // This is our wrapper/container class. A container class is a class, a data structure, or an abstract data type whose instances are collections of other objects. In this example a wrapper class contains both the standard salesforce object Contact and a Boolean value
        public class cContact {
            public Opportunity con {get; set;}
            public Boolean selected {get; set;}
    
            //This is the contructor method. When we create a new cContact object we pass a Contact that is set to the con property. We also set the selected value to false
            public cContact(Opportunity c) {
                con = c;
                selected = false;
            }
        }
    }
     
     
     
Visual Force code :
    
    
    <apex:page controller="wrapperClassController">
    <apex:form >
        <apex:pageBlock >
            <apex:pageBlockButtons >
                <apex:commandButton value="Process Selected" action="{!processSelected}" reRender="table"/>
            </apex:pageBlockButtons>    
            <apex:pageBlockTable value="{!contacts}" var="c" id="table">
                <apex:column >
                    <apex:inputCheckbox value="{!c.selected}"/>
                </apex:column>
                <apex:column value="{!c.con.name}"/>
                
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
    </apex:page> 

Sunday 30 October 2011

How to Integrate Salesforce with .Net using C# ?

Hello friends ,


The most interesting and promising feature of Salesforce is the ease of Integration with any platform. You can find many integration Docs over the web. However , many times in discussion boards and in various blogs I have gone through the requirement where in users want to start up with Integration using c# code. In Salesforce official docs you can find sample code for Integration with .Net using VB.Net.

I am providing c# code, in case anyone needs it .

Code for .cs file :

   using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using sforce;
using getLeadInfo;

public partial class _Default : System.Web.UI.Page
{
    private string _userid = "niketsoral1@gmail.com";
    private string _password = "Google@1235et6wJW9TzsyCa3JqnVUoW7AU";
    private string _sessionId;
    private string _serverUrl;
    private string _leadEmail;
    private DateTime _nextLoginTime;


    protected void Page_Load(object sender, EventArgs e)
    {


    }

    protected void btn_Click(object sender, EventArgs e)
    {
        //       ' Confirm Lead Email Exists
        _leadEmail = txtEmail.Text;
        if(Application["_sessionId"] == null)
            Application["_sessionId"] = "";
        if (Application["_serverUrl"] == null)
            Application["_serverUrl"] = "";
        if (Application["_nextLoginTime"] == null)
            Application["_nextLoginTime"] = " #1/1/2000#";
        if (!isConnected())
            getSessionInfo();
        //       ' Call getLeadInfo Web Service

        getLeadInfoService getLeadInfo = new getLeadInfoService();
        getLeadInfo.SessionHeaderValue = new getLeadInfo.SessionHeader();
        getLeadInfo.SessionHeaderValue.sessionId=_sessionId;

        getLeadInfo.Lead getLeadInfoResponse;
        getLeadInfoResponse = getLeadInfo.getLeadAddressByEmail(_leadEmail);
        txtAddress.Text = getLeadInfoResponse.City.ToString();
        txtState.Text = getLeadInfoResponse.State.ToString();
        txtZip.Text = getLeadInfoResponse.PostalCode.ToString();

    }

    public Boolean isConnected()
    {
        if (_sessionId != "" & _sessionId != null)
        {
            if (DateTime.Now > _nextLoginTime)
                return false;
            else
                return true;
        }
        else
            return false;
    }

    public void getSessionInfo()
    {
        sforce.LoginResult lr;

        sforce.SforceService ss = new sforce.SforceService();
        lr = ss.login(_userid,_password);
        _sessionId = lr.sessionId;
        Application["_sessionId"] = lr.sessionId;
        _serverUrl = lr.serverUrl;
        Application["_serverUrl"] = lr.serverUrl;
        Application["_nextLoginTime"] = DateTime.Now;


    }
}



Code for .aspx Page :

<body>
    <form id="form1" runat="server">
        <div>
            <table>
                <tr>
                    <td>
                        Email:
                    </td>
                    <td>
                        <asp:TextBox ID="txtEmail" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        Address:
                    </td>
                    <td>
                        <asp:TextBox ID="txtAddress" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        City:
                    </td>
                    <td>
                        <asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        State:
                    </td>
                    <td>
                        <asp:TextBox ID="txtState" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        ZIP:
                    </td>
                    <td>
                        <asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td colspan="2" align="center">
                        <asp:Button ID="btn" runat="server" Text="Click" OnClick="btn_Click" />
                    </td>
                </tr>
            </table>
        </div>
    </form>
</body>


Note :- In order to use this code, you need to do some homework :
  1. Create web service method in your salesforce Org as mentioned in Salesforce official docs.
  2. Generate WSDL for you Salesforce Org an import it in your .Net application.
  3. Use the reference in the .cs file.
Hope this helps the new comers who are starting Integration using c#.

Cheers,
Niket
Certified Developer | Certified Administrator

Saturday 29 October 2011

How to deploy any trigger from sandbox to Production ??

Hi All ,

This is my first blog. So I am starting my journey with a simple topic.

I have seen multiple times that new developers face some problem  in deployment of their code from sandbox to Production. I believe, this solution will work for those guys.

In order to deploy a trigger from sandbox to production, you need to take care of some points :

  1. At first I would like to request you all that before going for any deployment, make sure that there is no test failure or less than 75% code coverage in Production Instance. Because when we deploy any thing from sandbox to Production, "Run All Test" is performed automatically in Production. If there is any issue in Production then it will not let you deploy your new code.
  2. If you are deploying any trigger in Production, then you must write a test class for that trigger with no Test failure and more than 75% code coverage.
  3. Create deployment connection in sandbox.
  4. Create Outbound change set in Sandbox and add your trigger and its associated test class in the change set.
  5. Create Inbound change set in Production.
  6. Add Change set components in Sandbox.
  7. Upload the change set.
  8. You can validate the change set in Production.
  9. Finally deploy the change set in Production.
I hope this will help new comers to deploy their development work.

Please let me know if you have any questions or need more clarification. Even I am open for criticism .

Cheers,
Niket