function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
cassiecassie 

"last Modified by" is always administrator's name

we have customized object "Quote configuration" on Opportunity Page. There is SFDC quote ID (exp SF-11111) generated after one Quote is created, which only get general information about the quote, similar like billing address, customer information, etc.  there is  one custom link on  this quote page  to link our external application for real product detail  quote configuration.  After this real product detail quote is generated, there is corresponding quote ID called EZ-12345 created.  there is also "Save" button on our external application which can update the SFDC database.   SFDC quote ID  SF-11111 and EZ-12345 were insert to quote table in SFDC and opportunity table in SFDC, the issue is the "last modified by" field in Quote table and opportunity table is always using system administrator's name not individual sfdc user name.
 
anyone knows what caused this issue?
 
 
 
 
mojeebahmedmojeebahmed
Hi Cassie,

    I am guessing that you are using your administrator's login when you update the SF database from your external Application. this is why you get your administrator's name in the Last Modified by field. If you can explain the process in some more detail, then I might be able to help you.


Message Edited by mojeebahmed on 06-13-2007 02:59 PM

cassiecassie
Mojeeb,
 
thank you for quick response, I did thought about this, we have 2 files, one is Newquote.aspx.cs and another is savequote.aspx.cs, in these 2 files the administrator login was hardcoded, I have tried to change it with dynamic username and password, but still got the same result.
 
Your help is really appreciated.
 
 
1. on newquote.aspx.cs file, see the login function below.
private string login()
  {
   binding = new sforce.SforceService(); 
   try 
   {
//    binding.SessionHeaderValue = new sforce.SessionHeader();
//    binding.SessionHeaderValue.sessionId = Request.QueryString["SessionID"];
//    binding.Url = Request.QueryString["SessionURL"] ;
    sforce.LoginResult lr = binding.login("qqq@abc.com", "P12345");
    
    //sforce.LoginResult lr = binding.login(username, password);
    binding.Url = lr.serverUrl;
    binding.SessionHeaderValue = new sforce.SessionHeader();
    binding.SessionHeaderValue.sessionId = lr.sessionId;
    return "OK";
   }
   catch (Exception ex)
   {
    return ex.ToString();
   }
  }
 
I tried to use  sforce.LoginResult lr = binding.login(username, password); to replace sforce.LoginResult lr = binding.login("qqq@abc.com", "P12345");
 
 
2. on savequote.aspx.cs file, this file is used for loading quote information to SFDC database.
 
 
public class WebForm2 : System.Web.UI.Page
 {
  private sforce.SforceService binding;
  protected System.Web.UI.WebControls.Label Label1;
  string qr_str = new string(' ',1);
  private void Page_Load(object sender, System.EventArgs e)
  {
   binding = new sforce.SforceService(); 
   try 
   {
//    binding.SessionHeaderValue = new sforce.SessionHeader();
//    binding.SessionHeaderValue.sessionId = Request.QueryString["SFSessionID"]; 
//    binding.Url= Request.QueryString["SFSessionURL"];
   sforce.LoginResult lr = binding.login("qqq@abc.com", "P12345");
 
//I tried to use  sforce.LoginResult lr = binding.login(username, password); to replace sforce.LoginResult lr = binding.login("qqq@abc.com", "P12345"); but still got same issue.

    //sforce.LoginResult lr = binding.login(username, password);
    
    binding.Url = lr.serverUrl;
    binding.SessionHeaderValue = new sforce.SessionHeader();
    binding.SessionHeaderValue.sessionId = lr.sessionId;
    if (Request.QueryString["Redir"] != "QuoteOutput")  //if not loading, only update quote
    {
     sforce.Quote__c q = new sforce.Quote__c();
     q.Id = Request.QueryString["SFQuoteID"].ToString();    
     q.Quote_Date__c = DateTime.Now;
     q.Quote_Date__cSpecified=true;
     q.Quote_Total__c = Convert.ToDouble(Request.QueryString["QuoteTotal"]);
     q.Quote_Total__cSpecified=true;    
     q.EZ_Quote_Quote_Id__c = Request.QueryString["QuoteID"];
     sforce.SaveResult[] sr = binding.update(new sforce.sObject[]{q});
    }
    else  //loading quote into opportunity
    {
     //initializing variables     
     sforce.QueryResult qr = null;
     sforce.sObject[] updateArr = new sforce.sObject[50];
     sforce.sObject[] createArr = new sforce.sObject[50];
     string[] deleteArr = new String[50];
     sforce.Quote__c q = new sforce.Quote__c();
     string EzQuoteProductID = new string('c',1);
     try
     { 
      //starting building update array
      //1. all other quotes in the opportunity needs to have their forecast flags turned off
      qr_str = ("Select Id from Quote__c where Opportunity__c = '" + Request.QueryString["OppID"] + "'" + " and Id <> '" + Request.QueryString["SFQuoteID"]) + "'";        
      qr= binding.query(qr_str);
      for (int j=0; j<qr.size; j++)
      {        
       sforce.Quote__c q2 = (sforce.Quote__c)qr.records[j];
       q2.Forecast_Flag__c = false;
       q2.Forecast_Flag__cSpecified=true;
       updateArr[j+2] = q2;
      }
     
          
     /* for (int i=0;i<sr3.Length;i++)
      {
       if (sr3[i].success)
       {
        Label1.Text = "success";
       }
       else
       {
        // Iterate through the errors
        sforce.Error[] errors = sr3[i].errors;
        for (int j=0;j<errors.Length;j++)
        {
         Label1.Text = (errors[j].message);
        }
       }
      }*/
      //4. Products
      //      
      qr_str = ("Select Id from OpportunityLineItem where OpportunityId = '" + Request.QueryString["OppID"] + "'");        
      qr= binding.query(qr_str);
      for (int j=0; j<qr.size; j++)
      {        
       sforce.OpportunityLineItem q3 = (sforce.OpportunityLineItem)qr.records[j];
       deleteArr[j] = q3.Id; //retrieve all exisiting products on Opportunity      
      }
      sforce.DeleteResult[] deleteResults = binding.delete(deleteArr);  //delete all existing product from Opportunity
      //get product info from ezquote
      sforce.OpportunityLineItem OI= new SFDC.sforce.OpportunityLineItem();
      SqlDataAdapter DataAdapter = (new SqlDataAdapter("select i.SortOrder, q.strPartNo as ProductID, i.strDescription as Descr, q.intQuantity as Quantity, i.Price as ListPrice,case when i.ezcategory=7 then convert(varchar(11),convert(decimal(9,2), round(q.fltListPrice * (1-fltDiscount),2))) else convert(varchar(11),convert(decimal(9,2), round((q.fltListPrice * (1-fltDiscount)*(100-" + Request.QueryString["Disc"] + ")/100),2))) end as UnitPrice,convert(decimal(9,2),round((q.fltListPrice * (1-fltDiscount) * intQuantity),2))  as TotalPrice, i.SFDC_PartID, i.SFDC_PriceBookEntryID from quoteline q, items i where q.strPartNo = i.strPartNo and q.intQuoteid = " + Request.QueryString["QuoteID"] + " order by SortOrder", "server='test'; uid=sa;pwd=12345;database=testquote"));         
      DataSet Prices = new DataSet();
      DataAdapter.Fill (Prices, "QuoteLine");
      DataTable pricesTable = Prices.Tables[0];
      int k=0;
      double QuoteSum = 0;
      foreach (DataRow dataRow in pricesTable.Rows)  //loop through each quote line in EzQuote
      {                   
       OI= new SFDC.sforce.OpportunityLineItem();
       OI.Description= dataRow["Descr"].ToString(); //sfdc product descr, limited to 255
       OI.OpportunityId = Request.QueryString["OppID"]; //sfdc Opportunity ID, obtained and saved from NewQuote.aspx
       OI.PricebookEntryId = dataRow["SFDC_PriceBookEntryID"].ToString();       
       OI.Quantity = Convert.ToDouble(dataRow["Quantity"]); //ezquote quantity
       OI.QuantitySpecified=true;
       OI.UnitPrice = Convert.ToDouble(dataRow["UnitPrice"]);  //EzQuote actual line price (might be discount)
       OI.UnitPriceSpecified = true;
       createArr[k++] = OI; //build an array
       //QuoteSum += Convert.ToDouble(dataRow["Quantity"]) *  Convert.ToDouble(dataRow["UnitPrice"]);
      }
      //custom discount
      DataAdapter = (new SqlDataAdapter("select fltAmount as UnitPrice, strDescription as Descr from Discounts where intQuoteID=" + Request.QueryString["QuoteID"] + " union select (select sum(fltlistprice*(1-fltdiscount)*intquantity)* subtotals.fltdiscount from quoteline where intquoteid = subtotals.intquoteid and intquoteline between subtotals.intlinestart and subtotals.intlineend), strDescription from subtotals where intquoteid = " + Request.QueryString["QuoteID"], "server='test'; uid=sa;pwd=12345;database=testquote"));   
      Prices = new DataSet();
      DataAdapter.Fill (Prices);
      pricesTable = Prices.Tables[0];
      
      foreach (DataRow dataRow in pricesTable.Rows)  //loop through each quote line in EzQuote
      {                         
       OI= new SFDC.sforce.OpportunityLineItem();
       OI.Description= dataRow["Descr"].ToString(); //sfdc product descr, limited to 255
       OI.OpportunityId = Request.QueryString["OppID"]; //sfdc Opportunity ID, obtained and saved from NewQuote.aspx
       OI.PricebookEntryId = "01u30000000KKHb".ToString();       
       OI.Quantity = 1; //ezquote quantity
       OI.QuantitySpecified=true;
       OI.UnitPrice = Convert.ToDouble(dataRow["UnitPrice"])*-1;  //EzQuote actual line price (might be discount)
       OI.UnitPriceSpecified = true;
       createArr[k++] = OI; //build an array
       //QuoteSum += Convert.ToDouble(Convert.ToDouble(dataRow["UnitPrice"])*-1);
      }     
      //Label1.Text= Request.QueryString["OppID"];
      //create
      sforce.SaveResult[] sr4 = binding.create(createArr);  //create products on Opportunity
      //end of loop    
      //2. this quote needs to have Quote Date, Quote Total updated and Forecast Flag set to yes
      q.Id = Request.QueryString["SFQuoteID"].ToString();    
      q.Quote_Date__c = DateTime.Now;
      q.Quote_Date__cSpecified=true;
      q.Quote_Total__c = Convert.ToDouble(Request.QueryString["QuoteTotal"]);
      //q.Quote_Total__c = QuoteSum;
      q.Quote_Total__cSpecified=true;   
      q.Forecast_Flag__c=true;
      q.Forecast_Flag__cSpecified=true;
      q.EZ_Quote_Quote_Id__c =Request.QueryString["QuoteID"];      
      updateArr[0] = q;  //append unto array
      sforce.SaveResult[] sr = binding.update(updateArr);
      /*for (int i=0;i<sr4.Length;i++)
      {
       if (sr4[i].success)
       {
        Label1.Text = (sr4[i].id);
       }
       else
       {
        // Iterate through the errors
        sforce.Error[] errors = sr4[i].errors;
        for (int j=0;j<errors.Length;j++)
        {
         Label1.Text = (errors[j].message);
        }
       }
      }*/
     }
     catch (Exception ex)
     {Label1.Text=ex.ToString();}     
    }
mojeebahmedmojeebahmed
Hi Cassie,
    I have a few more questions. What is the custom link doing on the quote page? Does it open up some S-Control or it is just a direct link to your external application? And how are you getting the dynamic username and password for the salesforce user?

cassiecassie
the custom link is the direct link to external application, i am not sure how to get the dynamic username and password, i am assuming
 
"sforce.LoginResult lr = binding.login(username, password)"  can load the username and password whenever user login, i am not familar that part.
 
Thanks,
 
Cassie
mojeebahmedmojeebahmed
Cassie,

    Have you tried to pass the salesforce user session id from salesforce to your external application? you can get the salesforce user's session id easily and pass it to your external application as an argument and replace the following line:

binding.SessionHeaderValue.sessionId = lr.sessionId;


with this:

binding.SessionHeaderValue.sessionId = Request.QueryString["SFUserSessionID"].ToString();


You can still login with the admin user, just replace the above line and after that every request from your external application will be received by salesforce as if the request is coming from the actual salesforce user and not the admin.

I hope that this will work for you and the last modified by field wil contain the name of the salesforce user and not the admin user.

Let me know what happen after this change.
cassiecassie
Mojeeb,
 
after tried with following change, i still got the same result, last modified is still administrator.
 
 
Thanks,
 
Cassie
cassiecassie
the code was written in C#, i am not familiar with c#, does need it to compile or not?
mojeebahmedmojeebahmed
Hi Cassie,

    It depends how you have created the project as there are a few ways to make the changes, if al the project files i.e. aspx and cs files are on your server then you don't need to recompile the files. The server will do it automatically on run time. in other case you have to recompile the files and your project.

    So you better recompile the project and rebuild it. I hope this will work. Any ways please let me know what happen.
cassiecassie
I try to debug and change the code on .aspx.cs file,  I have hardcode my self's login instead of old administrator's login, but still gave me old administrator's after i modified the code. since i am not familiar with C#, the code was done by previous administrator, he left. i am trying to take over his work, how do you do printout  or alert message like "hello world" in C#, so I can debug it.