8

When a new portal user is created, can we check the number of used and total portal licenses?

  • I reckon [SELECT Count(Id) FROM User Where IsActive= true and isportalenabled = true] gives you the total portal licenses in use. You could subtract this from total num to give available – techtrekker Oct 31 '12 at 8:31
  • @techtrekker Can we also get total licenses assigned to an org? – doga Oct 31 '12 at 9:00
  • I couldn't find anything just yet, however this is unlikely to be a dynamically changing value, so is It perhaps a candidate for a Custom Setting ? – techtrekker Oct 31 '12 at 9:10
10

THe only way I've been able to achieve this kind of functionality in apex is via screen scraping. Create a pagereference to the company information page, execute the getcontent method to retrieve the raw HTML and then find the table row(s) containing the portal license information and extract the relevant elements. Its fragile, as there's no guarantee that the format of this page will remain the same (though it has for the last couple of years I've been using this technique) and you also can't execute the getContent from a trigger or scheduled apex, so I've tied it to a visualforce page embedded into a dashboard.

You can access the page via the organization id, so the code to get the content is:

Organization orgDetails =[select Id from Organization 
                      limit 1];
Id orgId = orgDetails.Id;
PageReference pr=new PageReference('/'+orgId);
String rawData=pr.getContent().toString();

and then you can locate a particular element using code similar to the following, which extracts the percentage of data space currently used::

Integer pos=rawData.indexOf('Used Data Space');
String result;
if (-1!=pos)
{
   pos=rawData.indexOf('<td', pos);
   if (-1!=pos)
   {
      pos=rawData.indexOf('>', pos+3);
      if (-1!=pos)
      { 
         Integer endPos=rawData.indexOf('%)', pos);
         result=rawData.substring(pos+1, endPos+2);
      }
   }
}
5

The technique above worked great for me. I used it in a Schedulable interface as triggers can't employ the getContent method. We just run this nightly. Below is the code I used to implement in our Org:

global class LicenseAvail implements Schedulable {

public String result;
public String orgName;
public String orgCountry;

global void execute(SchedulableContext ctx){

 //Get Organization to get content of company info details
         Organization orgDetails =[ select Id, Name, Country from Organization limit 1];
            Id orgId = orgDetails.Id;
            orgName = orgDetails.Name;
            orgCountry = orgDetails.Country;

        PageReference pr=new PageReference('/'+orgId);
        //called screenscraping: get the data from the page
        String rawData=pr.getContent().toString();

    //locate a particular element within the raw data
    //the info after this line contains the active license count
    String licRow = '>Salesforce</th><td class=" dataCell  ">Active</td><td class=" dataCell  numericalColumn">';
    Integer licLen = licRow.length();
    System.debug('******************** licLen: ' + licLen);
    Integer pos=rawData.indexOf(licRow);

if (-1!=pos)
{
         Integer licStart = pos + licLen;
         result=rawData.substring(licStart, licStart+3);
         System.debug('***************** SubString: ' + result);
  }

//get used licenses and determine if count of available is 5 or less

Decimal lic = decimal.valueOf(result);

integer u = [select count() from user where profile.UserLicense.Name = 'salesforce' and isactive = true];

 Decimal userCount = decimal.valueOf(u);

Integer totalUnused = (lic.intValue() - userCount.intValue());
System.debug('************ Licenses???? ***************** ' + String.valueOf(totalUnused));
    if(totalUnused <= 5) {

   System.debug('Sending Email...');
   Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
   String[] toAdd = new String[]{'email@address.com'};
   mail.setToAddresses(toAdd);
   mail.setReplyTo('email@address.com');
   mail.setSenderDisplayName('Salesforce License Notification');
   mail.setSubject(orgName + ' License Count: ' + String.valueOf(totalUnused));
   mail.setBccSender(false);
   mail.setUseSignature(false);
   mail.setPlainTextBody('License Count: ' + String.valueOf(totalUnused));
   mail.setHtmlBody('License Availability Alert:<br/>' + orgName + ', '+ orgCountry + '<br/>' + 'License Count: ' + String.valueOf(totalUnused));
   List<Messaging.SendEmailResult> results = Messaging.sendEmail(new Messaging.Email[] { mail });
   System.debug('****************** Email Sent: '+results.get(0).isSuccess() );
}

}   
}
0

There are UsedLicenses / TotalLicenses fields from UserLicense object available only through API call and only available for organization subscribed for related Pilot Program.

If your question relates to usage of UsedLicenses / TotalLicenses fields, you may vote up for this idea https://success.salesforce.com/ideaView?id=08730000000cJTEAA2 and also you may be interested in a managed beta package I created recently which may serve as workaround for this. It screenscrapes company profile page and gets number of total license.

This package includes a User_License_Extended__c custom object which contains Total License number and Used Licenses number ( and some more fields ), these numbers are updated whenever a user is activated or deactivated or user profile is changed assuming package is properly set up with necessary data

Install link for production-like org https://login.salesforce.com/packaging/installPackage.apexp?p0=04t580000001ENa

More details and release notes https://patlatus.wordpress.com/2016/03/07/salesforce-uletas-beta-1-0-release-notes/

Just noticed Bob was giving more advanced approach than I had implemented, using

> PageReference pr=new PageReference('/'+orgId); String
> rawData=pr.getContent().toString();

instead of doing callout - I should try that as well and rewrite my package - didn't know that pr.getContent() may be used for screen scraping

  • Guys, i have a requirement for finding out the Total licenses of SF for OTHER orgs which means i would have to screen scrape other orgs. Is this possible? How can I use the session details to access the /OrgId page of another org? Any ideas highly appreciated. – Shalini SF May 3 '16 at 6:16
  • @ShaliniMendu Actually my original version of the package already does that: you can screen scrape OTHER orgs Total Licenses, but the threshold email part will not be working as expected – Patlatus May 7 '16 at 10:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.