+ Start a Discussion
Terry411Terry411 

Insufficient privileges error

I'm getting an insufficient privileges error that I cannot understand why.  I have the following pieces of code:
- SalesReportExtension.cls v31
- SalesReport.page v31
- SalesReport.component v31
- Sales_Report.email v31

The user profiles have access to the above code.

Nothing in this code updates or creates Account record however, in-order to run the Sales Report the Profile needs to have Create and Edit rights.  Without both, they will get an insufficient privileges error.  The Account is the Controller but otherwise there are not updates of any object taking place in the code.  It simply is reading sales data associated to the account and summarizing it for the user and allowing them to create a PDF attached to a SF email.  The code works fine as an Admin and it works fine if I give the user Create/Edit rights to the Account.  Help
Best Answer chosen by Terry411
SarfarajSarfaraj
In this kind of situation I comment all my codes and gradually uncomment them section by section to see which part of my code is causinig the problem. See if this helps to find out the problem.

All Answers

SarfarajSarfaraj
Can you please post the associated code?
Terry411Terry411
Thanks for the reply akram.  The code produces the attached screen shot and then if selected, an email, with an attached PDF of the page.  This was my first attempt to use a component on both the vf page and within an email.  What I have is working but I'm not entirely sure it's the best approach.  Any feedback would be greatly appreciated in addition to whatever may be causing the need to create/edit access on the Account object.

SalesReportExtension.cls
public with sharing class SalesReportExtension {
    private ApexPages.StandardController controller {get; set;}
    public list<tableRow> dollarTable {get; set;}
    public list<tableRow> unitTable {get; set;} 
    // set First of Year and Prior Month End dates and table header labels
    public date foy {get; set;}
    public date pme {get; set;}
    public string foyLabel {get; set;}
    public string oneAgoLabel {get; set;}
    public string oneAgoPLabel {get; set;}
    public string twoAgoLabel {get; set;}
    public string twoAgoPLabel {get; set;}
    // set up account and ship to/sold to variables
    public Account a {get;set;}
    public string accountId {get;set;}
    public string accountName {get;set;}        // display at top of page
    public set<string> accountIds = new set<string>();      // used to query records
    public list<Account> accountNames {get;set;}
    public string selectedFilter {get;set;}
    public list<selectOption> filterOptions {get; set;}
    public string selectedTimeframe {get;set;}
    public list<selectOption> timeframeOptions {get; set;}
    public string value {get;set;}

    public SalesReportExtension(ApexPages.StandardController controller) {
        accountId = System.currentPageReference().getParameters().get('id');
        system.debug('------------------------- on screen version');
        system.debug('------------------------- accountId: ' + accountId);
        
        accountIds.add(accountId);
        a = getAccount();
        //a = [SELECT Id, Name, Ship_To_SAP_ID__c, Sold_To_SAP_ID__c, ShippingCity, ShippingState FROM Account WHERE Id IN :accountIds];
        accountNames = new list<Account>{a};
        accountName = a.Name;
        
        // setup picklist values
        filterOptions = selectOptions();
        selectedFilter = 'ShipTo';
        timeframeOptions = timeframeOptions();
        selectedTimeframe = 'YTD';
        //dollarTable = getDollarTable();
    }

    public SalesReportExtension() {
    	accountId = value;
    	
        if (a==null) a = getAccount();
        system.debug('------------------------- a: ' + a);
        accountNames = new list<Account>{a};
        accountName = a.Name;
        selectedFilter = 'ShipTo';
        selectedTimeframe = 'YTD';
        dollarTable = getDollarTable();
    } 

    public Account getAccount() {
        //accountId = '001i000000AbyAI';
        //accountId = value;
        if (accountId == null)
        	accountId = ApexPages.CurrentPage().getParameters().get('p3_lkid');
        if (accountId == null)
        	accountId = ApexPages.CurrentPage().getParameters().get('id');
        accountIds.add(accountId);

        a = [SELECT Id, Name, Ship_To_SAP_ID__c, Sold_To_SAP_ID__c, ShippingCity, ShippingState FROM Account WHERE Id IN :accountIds];
        system.debug('------------------------- accountId(get): ' + accountId);
        
        return a;
    }

    public list<tableRow> getDollarTable() { 
        // setup dollarTable for the current year, this will be our base table
        system.debug('------------------------- accountIds: ' + accountIds);
        
        list<AggregateResult> thisYear = thisYearData();
        dollarTable = new list<tableRow>();
        unitTable = new list<tableRow>();
        string label = '';
        decimal sales = 0;
        decimal units = 0;
        
        for (AggregateResult ty : thisYear){
            label = (string)ty.get('Material_Group__c');
            if (label == null) label = '';
            sales = (decimal)ty.get('Sales');
            if (sales == null) sales = 0;
            units = (decimal)ty.get('Units');
            if (units == null) units = 0;
            system.debug('------------------------- label: ' + label + '-' + sales + '-' + units);

            dollarTable.add (new tableRow(label, sales, 0, 0, 0, 0));
            unitTable.add (new tableRow(label, units, 0, 0, 0, 0));
        }
        
        // add oneYearAgo data to the dollarTable
        list<AggregateResult> oneYearAgo = oneAgoYearData();
        for (AggregateResult oya : oneYearAgo){
            label = (string)oya.get('Material_Group__c');
            if (label == null) label = '';
            sales = (decimal)oya.get('Sales');
            if (sales == null) sales = 0;
            units = (decimal)oya.get('Units');
            if (units == null) units = 0;
            //dollarTable.add (new tableRow(label, sales, 0, 0, 0, 0));
            
            upsertDollarData('oneAgo', label, sales);
            upsertUnitData('oneAgo', label, units);
        }

        // add twoYearAgo data to the dollarTable
        list<AggregateResult> twoYearAgo = twoAgoYearData();
        for (AggregateResult tya : twoYearAgo){
            label = (string)tya.get('Material_Group__c');
            if (label == null) label = '';
            sales = (decimal)tya.get('Sales');
            if (sales == null) sales = 0;
            units = (decimal)tya.get('Units');
            if (units == null) units = 0;
            //dollarTable.add (new tableRow(label, sales, 0, 0, 0, 0));
            
            upsertDollarData('twoAgo', label, sales);
            upsertUnitData('twoAgo', label, units);
        }
        
        // add Total line for each column
        decimal total1 = 0;
        decimal total2 = 0;
        decimal total4 = 0;
        for (tableRow t : dollarTable){
            total1 = total1 + t.col1;
            total2 = total2 + t.col2;
            total4 = total4 + t.col4;
        }
        integer percent1 = 0;
        if (total2 <> 0) percent1 = integer.valueOf((total1 / total2) * 100);
        integer percent2 = 0;
        if (total4 <> 0) percent2 = integer.valueOf((total1 / total4) * 100);
        dollarTable.add (new tableRow('Total', total1, total2, percent1, total4, percent2));
        
        total1 = 0;
        total2 = 0;
        total4 = 0;
        for (tableRow t : unitTable){
            total1 = total1 + t.col1;
            total2 = total2 + t.col2;
            total4 = total4 + t.col4;
        }
        percent1 = 0;
        if (total2 <> 0) percent1 = integer.valueOf((total1 / total2) * 100);
        percent2 = 0;
        if (total4 <> 0) percent2 = integer.valueOf((total1 / total4) * 100);
        unitTable.add (new tableRow('Total', total1, total2, percent1, total4, percent2));
        
        // set the table header label variables
        foyLabel = foy.year() + ' thru ' + pme.format();
        oneAgoLabel = foy.addYears(-1).year() + ' thru ' + pme.addYears(-1).format();
        oneAgoPLabel = foy.year() + ' % of ' + pme.addYears(-1).year();
        twoAgoLabel = foy.addYears(-2).year() + ' thru ' + pme.addYears(-2).format();
        twoAgoPLabel = foy.year() + ' % of ' + pme.addYears(-2).year();
        
        return dollarTable;
    }
    
    
    public list<AggregateResult> thisYearData(){
        foy = firstOfYear(system.today());
        pme = system.today();
        if (selectedTimeframe == 'PME') pme = priorMonthEnd(system.today());
        system.debug('--------------------------- foy: ' + foy);
        system.debug('--------------------------- pme: ' + pme);
        
        list<AggregateResult> ar = [SELECT Material_Group__c, SUM(Sales__c) Sales, SUM(Units__c) Units, MAX(Material_Description__c) Description 
                FROM Sales_Order_Information__c
                WHERE Billing_Date__c >= :foy AND Billing_Date__c <= :pme 
                    AND Ship_To_Account_Name__c IN :accountIds 
                    AND (NOT Material_Group__c LIKE 'Non-BFDI%')
                    AND (NOT Material_Group__c LIKE 'Tube%')
                    AND Material_Group__c <> ''
                GROUP BY Material_Group__c
                ORDER BY Material_Group__c];
        return ar;
    }
    
    
    public list<AggregateResult> oneAgoYearData(){
        date oneAgoFoy = foy.addYears(-1);
        date oneAgoPme = pme.addYears(-1);
        system.debug('--------------------------- oneAgoFoy: ' + oneAgoFoy);
        system.debug('--------------------------- oneAgoPme: ' + oneAgoPme);
        
        list<AggregateResult> ar = [SELECT Material_Group__c, SUM(Sales__c) Sales, SUM(Units__c) Units, MAX(Material_Description__c) Description 
                FROM Sales_Order_Information__c
                WHERE Billing_Date__c >= :oneAgoFoy AND Billing_Date__c <= :oneAgoPme 
                    AND Ship_To_Account_Name__c IN :accountIds 
                    AND (NOT Material_Group__c LIKE 'Non-BFDI%')
                    AND (NOT Material_Group__c LIKE 'Tube%')
                    AND Material_Group__c <> ''
                GROUP BY Material_Group__c
                ORDER BY Material_Group__c];
        return ar;
    }
    
    
    public list<AggregateResult> twoAgoYearData(){
        date twoAgoFoy = foy.addYears(-2);
        date twoAgoPme = pme.addYears(-2);
        system.debug('--------------------------- twoAgoFoy: ' + twoAgoFoy);
        system.debug('--------------------------- twoAgoPme: ' + twoAgoPme);
        
        list<AggregateResult> ar = [SELECT Material_Group__c, SUM(Sales__c) Sales, SUM(Units__c) Units, MAX(Material_Description__c) Description 
                FROM Sales_Order_Information__c
                WHERE Billing_Date__c >= :twoAgoFoy AND Billing_Date__c <= :twoAgoPme 
                    AND Ship_To_Account_Name__c IN :accountIds 
                    AND (NOT Material_Group__c LIKE 'Non-BFDI%')
                    AND (NOT Material_Group__c LIKE 'Tube%')
                    AND Material_Group__c <> ''
                GROUP BY Material_Group__c
                ORDER BY Material_Group__c];
        return ar;
    }
    
    
    public list<Sales_Order_Information__c> getData(date startDate, date endDate){
        list<Sales_Order_Information__c> soi = new list<Sales_Order_Information__c>();
        return soi;
    }


    public void upsertDollarData(string columnName, string label, decimal sales){
        // spin through dollarTable and either update the existing row or insert a new row
        boolean wasFound = false;
        for (integer i=0; i<dollarTable.size(); i++){
            // get current row
            tableRow tr = dollarTable.get(i);
            
            // find matching row
            if (tr.label == label){
                // matching row
                wasFound=true;
                
                if (columnName == 'oneAgo') {
                    tr.col2 = sales;
                    tr.col3 = 0;
                    if (sales <> 0) tr.col3 = integer.valueOf( (tr.col1 / sales) * 100 );
                }
                if (columnName == 'twoAgo') {
                    tr.col4 = sales;
                    tr.col5 = 0;
                    if (sales <> 0) tr.col5 = integer.valueOf( (tr.col1 / sales) * 100 );
                }
                dollarTable.set(i, tr);
                break;      // no need to continue
            }
        }
        
        if (wasFound == false){
            // a match wasn't found so add a new row
            if (columnName == 'oneAgo') dollarTable.add (new tableRow(label, 0, sales, 0, 0, 0));
            if (columnName == 'twoAgo') dollarTable.add (new tableRow(label, 0, 0, 0, sales, 0));
        }
    }
    
    
    public void upsertUnitData(string columnName, string label, decimal units){
        // spin through unitTable and either update the existing row or insert a new row
        boolean wasFound = false;
        for (integer i=0; i<unitTable.size(); i++){
            // get current row
            tableRow tr = unitTable.get(i);
            
            // find matching row
            if (tr.label == label){
                // matching row
                wasFound=true;
                
                if (columnName == 'oneAgo') {
                    tr.col2 = units;
                    tr.col3 = 0;
                    if (units <> 0) tr.col3 = integer.valueOf( (tr.col1 / units) * 100 );
                }
                if (columnName == 'twoAgo') {
                    tr.col4 = units;
                    tr.col5 = 0;
                    if (units <> 0) tr.col5 = integer.valueOf( (tr.col1 / units) * 100 );
                }
                unitTable.set(i, tr);
                break;      // no need to continue
            }
        }
        
        if (wasFound == false){
            // a match wasn't found so add a new row
            if (columnName == 'oneAgo') unitTable.add (new tableRow(label, 0, units, 0, 0, 0));
            if (columnName == 'twoAgo') unitTable.add (new tableRow(label, 0, 0, 0, units, 0));
        }
    }
    
    
    public date firstOfYear(date d){
        // returns Jan 1 of the date passed in
        if (d.month() == 1 && selectedTimeframe == 'PME') d = d.addMonths(-3);      // just need to get to a prior year date
        return date.newInstance( d.year(), 1, 1);
    }
    
    public date priorMonthEnd(date d){
        // returns the prior month end of the date passed in
        return d.toStartOfMonth()-1;
    }
    
    
    public list<SelectOption> selectOptions() {
        list<SelectOption> options = new list<SelectOption>();
        options.add(new selectOption('ShipTo', 'Ship To')); 
        options.add(new selectOption('SoldTo', 'Sold To')); 
        return options;
    }


    public list<SelectOption> timeframeOptions() {
        list<SelectOption> options = new list<SelectOption>();
        options.add(new selectOption('YTD', 'Year To Date')); 
        options.add(new selectOption('PME', 'Prior Month End')); 
        return options;
    }


    public PageReference filterChanged(){
        system.debug('-------------------------- in changeFilter --------------------------');
        selectedFilter = this.selectedFilter;
        selectedTimeframe = this.selectedTimeframe;
        
        accountIds.clear();     // removes all records
        accountNames.clear();   // removes all records
        if (selectedFilter == 'SoldTo'){
            // gather all the AccountIds for the current account's SoldTo
            for (Account aList : [SELECT Id, Name, Ship_To_SAP_ID__c, Sold_To_SAP_ID__c, ShippingCity, ShippingState 
                                        FROM Account 
                                        WHERE Sold_To_SAP_ID__c = :a.Sold_To_SAP_ID__c]){
                accountIds.add(aList.Id);
                accountNames.add(aList);
            }
        } else {
            accountIds.add(a.Id);
            accountNames.add(a);
        }
        
        getDollarTable();
        return null;
    }
    
    public PageReference sendEmail(){
        system.debug('---------------------- a.Id: ' + a.Id);
        
        PageReference emailPage = new PageReference('/email/author/emailauthor.jsp');
        map<string, string> params = emailPage.getParameters();
        params.put('id', a.Id);                         // email will be attached to the activity history of the account where the button was clicked using the acct.ID
        params.put('p3_lkid', a.Id);                    // email will be attached to the activity history of the account where the button was clicked using the acct.ID
        string emailTemplate = '00Xi0000001FHdt';
        if (globalHelper.isSandBox()) emailTemplate = '00Xe0000000Irr3';
        params.put('template_id', emailTemplate);    // template ID of the email template to be shown goes here
        params.put('rtype','003');
        params.put('new_template','1'); 
        params.put('retURL', ApexPages.currentPage().getUrl());     //after send button is clicked, go back to the account where the button was clicked
             
        return emailPage;
    }

    
    //constructor
    public class tableRow{
        public string label {get;set;}
        public decimal col1 {get;set;}
        public decimal col2 {get;set;}
        public integer col3 {get;set;}
        public decimal col4 {get;set;}
        public integer col5 {get;set;}

        public tableRow(string l, decimal c1, decimal c2, integer c3, decimal c4, integer c5){
            this.label = l;
            this.col1 = c1;
            this.col2 = c2;
            this.col3 = c3;
            this.col4 = c4;
            this.col5 = c5;
        }
    }

}

SalesReport.page
<apex:page standardController="Account" Extensions="SalesReportExtension" sidebar="false" showHeader="false">
    <apex:form >
	    <apex:pageBlock title="{!accountName}" id="Dollars" mode="maindetail">
			
			<apex:pageBlockSection Title="Filter by:" id="filter" columns="4" >
				<apex:selectList value="{!selectedFilter}" multiselect="false" size="1">
					<apex:selectOptions value="{!filterOptions}"/>
			   	 	<apex:actionSupport event="onchange"
			    					action="{!filterChanged}"
			    					rerender="dataDollarTable,dataUnitTable,accountTable"
			    					status="queryStatus"/>
			    </apex:selectList>
				<apex:selectList value="{!selectedTimeframe}" multiselect="false" size="1">
					<apex:selectOptions value="{!timeframeOptions}"/>
			   	 	<apex:actionSupport event="onchange"
			    					action="{!filterChanged}"
			    					rerender="dataDollarTable,dataUnitTable,accountTable"
			    					status="queryStatus"/>
			    </apex:selectList>
			    
			    <apex:commandButton value="Email Report" action="{!sendEmail}" id="emailButton"/>

		    </apex:pageBlockSection>
			<apex:actionStatus id="queryStatus" startText="...gathering data..." stopText=""/>
		
			<c:SalesReport />
 			<p/>

	    	<apex:pageBlockSection id="accountTable" Title="" collapsible="true">
			    <apex:pageBlockTable value="{!accountNames}" var="an" cellpadding="10" border="1" style="width:700px; align:center">
			        <apex:column headerValue="Included Accounts" style="width:350px; text-align:left">
			        	{!an.Name}
			        </apex:column>
			        <apex:column headerValue="City" style="width:200px; text-align:left">
			        	{!an.ShippingCity}
			        </apex:column>
			        <apex:column headerValue="State" style="width:75px; text-align:left">
			        	{!an.ShippingState}
			        </apex:column>
			        <apex:column headerValue="Ship To Id" style="width:75px; text-align:left">
			        	{!an.Ship_To_SAP_ID__c}
			        </apex:column>
				</apex:pageBlockTable>
			</apex:pageBlockSection>
		</apex:pageBlock>

	</apex:form>    
</apex:page>

SalesReport.component:
<apex:component controller="SalesReportExtension" access="global">
    <apex:attribute name="value" description="the Account Id"
                  type="Id" assignTo="{!Account.Id}"/>
                  
	<style type="text/css">
    @page{
		size: landscape;
	}
	p {
		font-family: verdana,arial,sans-serif;
		font-size:12px;
		color:#333333;
		margin: 0px 0px 0px 10px;
	}
	table.gridtable {
		font-family: verdana,arial,sans-serif;
		font-size:11px;
		color:#333333;
		border-width: 1px;
		border-color: #666666;
		border-collapse: collapse;
		margin: 0px 0px 0px 10px;
	}
	table.gridtable th {
		border-width: 1px;
		padding: 8px;
		border-style: solid;
		border-color: #666666;
		background-color: #dedede;
	}
	table.gridtable td {
		border-width: 1px;
		padding: 8px;
		border-style: solid;
		border-color: #666666;
		background-color: #ffffff;
	}
	</style>
	
	<p>
		<b><apex:outputText styleClass="t1" value="by Dollars..."/></b>
	</p>
	<apex:dataTable value="{!dollarTable}" var="dt" cellpadding="20" border="1" style="width:800px" styleClass="gridtable">
	    <apex:column headerValue="Material" style="width:200px; text-align:left;">
	        {!dt.label}
	    </apex:column>
	    <apex:column headerValue="{!foyLabel}" style="text-align:right">
	            <apex:outputText value="${0, number, #,##0.00}">
	        <apex:param value="{!dt.Col1}"/>
	        </apex:outputText>
	    </apex:column>
	    <apex:column headerValue="{!oneAgoLabel}" style="text-align:right">
	            <apex:outputText value="${0, number, #,##0.00}">
	        <apex:param value="{!dt.Col2}"/>
	        </apex:outputText>
	    </apex:column>
	    <apex:column headerValue="{!oneAgoPLabel}" style="text-align:right">
	            <apex:outputText value="{0, number, #,##0}%">
	        <apex:param value="{!dt.Col3}"/>
	        </apex:outputText>
	    </apex:column>
	    <apex:column headerValue="{!twoAgoLabel}" style="text-align:right">
	            <apex:outputText value="${0, number, #,##0.00}">
	        <apex:param value="{!dt.Col4}"/>
	        </apex:outputText>
	    </apex:column>
	    <apex:column headerValue="{!twoAgoPLabel}" style="text-align:right">
	            <apex:outputText value="{0, number, #,##0}%">
	        <apex:param value="{!dt.Col5}"/>
	        </apex:outputText>
	    </apex:column>
	</apex:dataTable>
	    
	<br/>
	<p>
		<b><apex:outputText styleClass="t1" value="by Units..."/></b>
	</p>
	<apex:dataTable value="{!unitTable}" var="dt" cellpadding="10" border="1" style="width:800px" styleClass="gridtable">
        <apex:column headerValue="Material" style="width:200px; text-align:left;">
        	{!dt.label}
        </apex:column>
        <apex:column headerValue="{!foyLabel}" style="text-align:right">
              	<apex:outputText value="{0, number, #,##0}">
			<apex:param value="{!dt.Col1}"/>
			</apex:outputText>
        </apex:column>
        <apex:column headerValue="{!oneAgoLabel}" style="text-align:right">
                     <apex:outputText value="{0, number, #,##0}">
			<apex:param value="{!dt.Col2}"/>
			</apex:outputText>
        </apex:column>
        <apex:column headerValue="{!oneAgoPLabel}" style="text-align:right">
              	<apex:outputText value="{0, number, #,##0}%">
			<apex:param value="{!dt.Col3}"/>
			</apex:outputText>
        </apex:column>
        <apex:column headerValue="{!twoAgoLabel}" style="text-align:right">
              	<apex:outputText value="{0, number, #,##0}">
			<apex:param value="{!dt.Col4}"/>
			</apex:outputText>
        </apex:column>
        <apex:column headerValue="{!twoAgoPLabel}" style="text-align:right">
              	<apex:outputText value="{0, number, #,##0}%">
			<apex:param value="{!dt.Col5}"/>
			</apex:outputText>
        </apex:column>
    </apex:dataTable>
    
</apex:component>

Sales_Report.email:
<messaging:emailTemplate subject="Sales Report" recipientType="Contact" relatedToType="Account">
<messaging:plainTextEmailBody >
Please see the attached sales report outlining your historical purchases.  We appreciate your continued business and if you have any questions, please let us know.

Sincerely,
{!$User.FirstName} {!$User.LastName}
</messaging:plainTextEmailBody>

<messaging:attachment renderAs="pdf" filename="{!relatedTo.Name}">    
    <c:SalesReport value="{!relatedTo.Id}"/>
</messaging:attachment>
</messaging:emailTemplate>

 
Terry411Terry411
Here's a screen short of the resulting page
Screen shot of the report
SarfarajSarfaraj
I am not seeing any issue with your code. Can you please verify,
  • The profile has access to the VF page SalesReport.
  • The associated account record is accessible by the user. As your controller has access modifier with sharing. Any attempt to access inaccessible Accounts may lead to insufficient priviledge error.
  • Also please verify if the User has read permission to all of the objects and their fields accessed in your code.
--Akram
Terry411Terry411
Yup. The Profiles have access to the class and VF page and email template folder. All the code is the same API version. All profiles have View All access. The error shows when the VF page displays. When I trace the debug logs it all appears to be running as normal. I don't get it.
SarfarajSarfaraj
Seems strange to me. Can you please post a screenshot of the error page?
Terry411Terry411
error message

The URL is:   https://c.cs15.visual.force.com/apex/SalesReport?id=001i000000AbyAI

I saw other post talking about the API version and initially I did have differences there.  I have everything set to version 31 now.
SarfarajSarfaraj
What happens when you try to access this url?
https://cs15.visual.force.com/001i000000AbyAI
Terry411Terry411
"This webpage is not available"
SarfarajSarfaraj
Sorry my bad. what happens for this url,
https://cs15.salesforce.com/001i000000AbyAI
 
Terry411Terry411
The VF page is called from a button on the Account page.  
/apex/SalesReport?id={!Account.Id}
Terry411Terry411
The Account page displays fine...  Interestingly this profile does get an Insuffient Priveleges error if the try to Edit the page.  It has Read, Edit, View All rights in the Profile.  Sharing settings are Public
SarfarajSarfaraj
In this kind of situation I comment all my codes and gradually uncomment them section by section to see which part of my code is causinig the problem. See if this helps to find out the problem.
This was selected as the best answer
Terry411Terry411
Sounds good... now I'm curious why this Profile can't edit even the standard page.  Maybe if I find that answer, I'll solve the Sales Report as well.  Thanks
SarfarajSarfaraj
Does the profile have edit permission on account? If not this error is normal for the standard edit page.
Terry411Terry411
It did.. but i mis-read the Sharing Rules... The were Public Read-Only.  That explains the standard edit page but didn't fix the VF page.  I'll start commenting out sections of code and let you know what I find.  I'll work on that later today.
Terry411Terry411
The problem was caused by the <apex:attribute> in the controller.  I was able to remove it given I was getting the account.id in the controller from the URL line.  Thanks for the advice and help akram!