Thursday, April 23, 2015

Unifier Permissions

Unifier Permission Structure 


As you can see, Permissions consist of a (Company or Shell) + (User or Group) + (Module).

The problem with this model comes if you have a system with a lot of shells.  I worked in a system that had 100,000 shells, 30 bps, and to support 700 users, required over 2 million entries in the permission table.

The nice thing about the model, is it does allow you to control what BP's can be used per shell or company.  







Unifier Permission Table


The permissions for companies are stored in the SYS_COMPANY_PERMISSIONS table.  This table contains a reference for Company, Group or User, and Module ref id  (PermissionId).  The permissions for Shells are located in the SYS_PROJECT_PERMISSIONS table.  In the table structure Project = Shell.

Now Permission ID = REF ID from the menu object in the database.  The menu objects can be found in SYS_USER_DEFINED_MENU table. In the CONTENT field, you will find JSON like the following: Notice the refid.  Now refid that are 7 digits long are BP's.  In fact the id matches the SYS_BP_CONFIG table, the BP_ID column.


{
  "name":"Company Workspace",
  "image":"../icons/u_company.png",
  "children":
  [
    {
      "name":"Summary",
      "image":"../icons/u_summary.png",
      "label":"Summary",
      "nodeType":"0",
      "refid":"project_summary"
    },
    {
      "name":"Collaboration",
      "children":
      [
        {
          "name":"Tasks",
          "image":"../icons/u_tasks.png",
          "label":"Tasks",
          "nodeType":"0",
          "refid":"project_tasks"
        },
        {
          "name":"Messages",
          "image":"../icons/u_messages.png",
          "label":"Messages",
          "nodeType":"0",
          "refid":"project_messages"
        },
        {
          "name":"Drafts",
          "image":"../icons/u_drafts.png",
          "label":"Drafts",
          "nodeType":"0",
          "refid":"project_drafts"
        }
      ],
      "image":"../icons/u_collaborate.png",
      "label":"Collaboration",
      "nodeType":"1"
    },
    {
      "name":"General",
      "image":"../icons/u_general.png",
      "label":"General",
      "nodeType":"0",
      "refid":"project_general"
    },
    {
      "name":"Document Manager",
      "children":
      [
        {
          "name":"Company Documents",
          "image":"../icons/u_project_documents.png",
          "label":"Company Documents",
          "nodeType":"0",
          "refid":"75"
        },
        {
          "name":"Unpublished Documents",
          "image":"../icons/u_unpublish_docs.png",
          "label":"Unpublished Documents",
          "nodeType":"0",
          "refid":"76"
        }
      ],
      "image":"../icons/u_reports.png",
      "label":"Reports",
      "nodeType":"1"
    },
    {
      "name":"Custom",
      "children":
      [
        {
          "name":"Operations",
          "children":
          [
            {
              "name":"Work Order",
              "image":"../icons/u_business_process.gif",
              "label":"Operational Work Order",
              "nodeType":"0",
              "refid":"1000003"
            },
            {
              "name":"Facility Improvement",
              "image":"../icons/u_business_process.gif",
              "label":"Facility Improvement",
              "nodeType":"0",
              "refid":"1000005"
            }
          ],
          "image":"../icons/u_default_folder.gif",
          "label":"Operations",
          "nodeType":"1"
        }
  ],
  "label":"Company Workspace",
  "nodeType":"1",
  "refid":"projectname"
}

How the permission byte array works

In the permission table, you will notice that the PermissionValue is a byte array varying in length.  The length of the byte array depends on what permissions are being represented.  

The checkbox represents the value of the first character in the byte array.  So if the first character is a 1, then Modify Record Ownership is checked.  If 0, then Modify Record Ownership is unchecked.  

Monday, January 19, 2015

Creating dynamic hyperlinks

How to create dynamic hyper links in Oracle Primavera Unifier

Step 1: Create Hyperlink Element

  1. Go to Data Structure Setup > Data Elements
  2. Click New
  3. Set Data Definition Source to Hyperlink Picker
  4. Click OK


Step 2: Create String Element for Hyperlink Label

  1. Go to Data Structure Setup > Data Elements
  2. Click New
  3. Set Data Definition Source to Sys Short Description Text 250
  4. Set Name Hyperlink Label
  5. Click OK

Step 3: Create String Element for Hyperlink address

  1. Go to Data Structure Setup > Data Elements
  2. Click New
  3. Set Data Definition Source to Sys Short Description Text 250
  4. Set Name Hyperlink address
  5. Click OK

Step 4: Create String Element for Hyperlink address base

  1. Go to Data Structure Setup > Data Elements
  2. Click New
  3. Set Data Definition Source to Sys Short Description Text 250
  4. Set Name Hyperlink address base
  5. Click OK

Step 5: Add link to Form 

  1. Go to a Form in uDesigner.  
  2. Select an empty field
  3. Click Custom
  4. Selected created element in step 1, step 2, step 3, step 4
  5. Click save

How hyperlinks work

Hyperlinks are two parts, the first part represents the address, the second part represents the display name of the link.  The two are separated by a space.  So in the database it looks like "http://link.com Link Name"(<hyperlink> <label>). So when you use a formula, you need to create two elements, one to hold the hyperlink address, and another to hold Hyperlink label.  When you add the two in a formula, you just separate them with a space, and you have a hyperlink.  

Step 6: Configure hyperlink address base

  1. Click Properties
  2. Select hyperlink address base
  3. Click Auto-Populate
  4. Set source name to Constant Value

Step 7: Configure hyperlink address 

  1. Click Properties
  2. Select hyperlink address 
  3. Click Formula
  4. Select hyperlink address base
  5. Click Add Parameter
  6. click ()
  7. Add field that has parameter (option)
  8. Click OK

Step 8: Configure hyperlink label

  1. Click Properties
  2. Select hyperlink label
  3. Click Auto-Populate
  4. Set source name to Constant Value
  5. Set value to whatever  you want the link to say.  

Step 9: Configure hyperlink 

  1. Click Properties
  2. Select hyperlink
  3. Click Formula
  4. Change delimiter to Space( ) the one with a space in it
  5. Select Hyperlink Address 
  6. Click Add Parameter
  7. click ( )
  8. Select Hyperlink Label 
  9. Click Add Parameter
  10. Click OK


Sunday, January 18, 2015

Reverse Engineering Oracle Primavera Unifier

Why reverse engineer Primavera Unifier?

I have been working with Primavera Unifier, for a year now.  After working with it for a month, it wasn't very difficult to see that Unifier had some limitations, that would hinder our ability to scale, and integrate with our many solutions.   After studying Primavera Unifier for the next, month I found that most of the configurations, permissions, and data was all stored in the Database.  Once I learned this, I spent the next 10 months, studying each screen and page in Unifier, and finding the equivalent data source in the database.  This has enabled me to be able to build tools to help enhance the Unifier experience.   

Limitations with Primavera Unifier

  • Can't add buttons
    • Wouldn't it be cool if we could add a button, that could execute a javascript command that we program?  Would it be cool, if we could program a button to perform certain functions.   Currently this is a limitation in Unifier, we are limited in our ability to interact with the Bp's.  
  • No external calls to a web service
    • One of the largest limitations, is not being able to make an external service call.  There's a lot of times we would love to integrate with peoplesoft, or update information in an external system.  Or pull in information from an external system, but not have to store the information.  
  • Managing permissions at a shell level
    • If you are a large organization with a  lot of properties, then managing the permissions on this can be quite cumbersome.  Unifier only has shell level permissions, meaning, each shell, has ownership of its own set of permissions.  When you are trying to scale what you really need is one set of permissions for all of your properties. The Unifier model makes it difficult to support the permissions for such large amount of shells, and it also it makes it slow when you have a large amount of changes to make.   In the database, to support about 700 employees, creates about 12,000,000 permission records in unifier.
  • Unable to push permissions down a shell hierarchy
    • Again when scaling to support thousands of properties, most organizations of a hierarchy to help support all the properties.  A regional manager may have access to 300 properties, but the only way to give him access to those 300 properties, is to go to each property and add the permission.  If you have multiple levels of shells, this becomes increasingly cumbersome. 
  • Unable to update data directly in the database
    • Unfortunately tampering with the database invalidates the warranty. Which means the only way to update the database is through the web service, which is obviously slower.   
  • Unable to export pieces of translations
    • If you have a large Unifier project, and you want to be able to translate certain BP's above others, you can't.  You can only translate all the strings at once.  
    • Another issue, if you add more strings, and you just want to translate the new strings, Unifier does not allow you.  It always exports all the strings, and leaves you  no ability to figure out which strings have been already translated.  
  • Unable to deploy permission, and configuration changes
    • When your supporting an enterprise level solution, you typically need a few lanes of promotion.  Currently the only piece you can transfer between environments are uDesigner modules.  You can't do configurations and permissions.  Which means these pieces have to be deployed manually.  For a BP you are looking at about 350 unique configurations, any mistake, or missed click can drastically alter your end result.  
  • Unable to delete, or hide records, bps, workflows, setups, and configurations.
    • If a mistake is made in a module, or workflow, there is no way to delete, or hide the module from uDesigner, or configurations properties.  This makes for a messy environments, as the only way to distinguish them is through a naming schema.  
  • No Encrypted sensitive data
    • If storing sensitive data, like ssn's, credit card numbers, etc. There is no way to encrypt this information at the database layer.