Organisation/User Configuration

Problem statement: As of now organisation upload sample file is  static file , so changes for any attributes required changes in portal as well. We need to make sample file generation as dynamic. The reason behind making file generation dynamic is , different adopters need different fields to be passed during org bulk upload.

Proposed Solution 1:

     Sunbird will define all attribute for org creation as org master attribute and consumer can use some of this value to define upload file structure. Attribute will be define per installation.

   Based on adopters defined value sunbird will do request validation as well. There will be a default settings for organisation create attribute , adopters can override it. 

 Organisation Attribute :

  

Organisation attribute
{
"org":{
     "attributes":[
        {
         "name":"orgName",
         "optional":false
        } , 
         {
         "name":"locationCode",
         "optional":false
         
        } ,
        {
         "name":"orgId",
         "optional":true
        } ,
        {
         "name":"externalId",
         "optional":true
         }, 
        {
         "name":"status",
         "optional":false
         
         }, 
         {
         "name":"description",
         "optional":false
         } 
        ]
   }   
}


ProsCons

user can select any attribute from supported attribute list 

Extra configuration required for org attribute settings .

 Org creation sample csv can be generated at runtimeExtra configuration/api required for all supported organisation attribute.
As data is store inside database , so value can be updated any time

Usages : 

            This setting will be stored inside system settings table  with column name "orgAttributeSettings" and column value as above setting in Json format.

            There is a getSystemsetting api that need be called by consumer to get settings for particular key.

Define All supported attribute for an organisation:

       There are two approach to define all supported attribute of an organisation:

     Approach 1: 

                     Define all the supported attribute in sunbird doc as follow.

namedataType description
orgNamestringname of the organisation



ProsCons
less development effortmaintenance cost is more , any changes in attributes required doc updates.

 Approach 2: 

              Define a new api that will provide all attributes of organisations at runtime. it will reduce maintenance cost.

Proposed Solution 2:

            Sunbird will take only list of mandatory attributes from adopters  and it will have master list for org creation. Master list will define which field is option/mandatory , field data type and other details.

    Adopters can see all supported fields from master list and then they can create  mandatory list for org creation.

{
"orgMandatoryAttributes":"orgName","orgCodes","status"
}

ProsCons
Setting is simplified for adopters, they need to select mandatory attributes onlyExtra configuration required , increase development time 

Need more logic from consumer to create dynamic csv sample. Because for optional they don't know field should be in csv.

Proposed Solution 3:

   Sunbird will take two list from adopters. 

  •     Mandatory list : This will contains all mandatory parameter required for org creation.
  •     Optional list : This will contains optional parameter for org creation . Both mandatory and optional parameter will be part of master list (all the attribute supported for org creation 
{
"orgMandatoryAttributes":["orgName","orgCodes","status"],
"orgOptionalAttributes": ["orgId","externalId","description"] 

}
ProsCons
Mandatory and optional  are define separately , so it will have clear picture of all fields adopters need to set both mandatory and optional lsit
Easy for consumer to generate sample csv based on both attribute

Proposed Solution 4: 

     We can used config service to put org creation configuration. In that case same configuration will moved from sunbird to config service.

ProsCons
All configuration will be moved to config serviceSince config service is optional ,so we need to have fallback as well. Or some time config service is down.

Adding one more dependency , will increase development time

Still we have to support config service and local config both

How setting can be done by adopters:

  Adopter need to make system settings api call to update/insert settings

 

URI : /data/v1/system/setting/set
Method: POST
request body:
{
  "request": {
            "id": "orgAttributeSettings", //fix value
            "field": "orgAttributeSettings", // fix value
            "value": "it can be json"
    }
}

After Discussion we arrive to a point that no need to do dynamic generation of org and user sample file.

How Consumer will used it:

Consumer will make below api call to get org attribute settings.

Consumer will read settings data and they can provide option to org admin to generates files only with mandatory field or mandatory plus optional both.This can be ask during download time or can be a env variable that will decide business logic for file generation.

URI: /data/v1/system/setting/read/orgAttributeSettings
Method: GET

or they can make api call to get all settings.

 /data/v1/system/settings/list

Method: GET



Proposed fields for user and org :

Organisation Fields:

FieldTypeRequired
orgNamestringtrue
locationCodesarray of stringtrue
statusinttrue
organisationIdstringfalse
descriptionstringfalse
externalIdstringfalse


Doubts:

 1.  In Bulk upload are we always going to create suborg only, because for rootOrg creation "channel" is mandatory.

 2.  Will only externalId be unique across system or externalId and channel combination should be unique

  Resp: The external ID field will be used by states to assign the state ID for the school (if available) - this could be different formats for different states. This will not be a mandatory field in Diksha.

3.  WorkFlow for status changes : if org status is inactive (0) then will all user of this org should be inactive, similarly if it's rootOrg and status is inactive then all suborg and there user need to be inactive.

Resp : The active/ inactive flag cannot be accessed via the api as confirmed by +vinayab@ilimi.in . We'll take up these workflows in V2.

4.  Old org will have several other fields as well , so that field need to be retain as it is or need to be dropped. if need to be dropped then is it only applicable for DIKSHA or all adopters.


User Fields:


FieldTypeRequired
namestringtrue
phonestringconditional (phone or email)
emailstringconditional (phone or email)
organisationIdstringconditional (if userType=teacher then it's required)
userTypestringrequired (possible values : teacher and others)
roleslist

conditional (required if userType is teacher)


userFrameworkMap<string,List<string>>false


or Framework related data we can directly save as well:

 * Board , class, subject, medium



Doubts: 

      1.  Email and phone are unique for a user , so during bulk upload what should be the flow. Means if phone/email exist then do we need to override it or throw an error.

      2.  Old user is having lot's more different fields as well , so how are we going to handle old field.

      3.  As some of the mandatory field we are going to change (firstName and userName) , so now how old app will behave?

  


User search based on locations:

 Background: 

As of now user search is not possible based on geo location, but now we need to provide capabilities to do user search based on Geo loaction (state,district, block etc).


Proposed Solution 1: 

  Sunbird will store locationIds inside user object . When ever a user is added to an organisation , it will store all hierarchical locations ids.  If any user is removed from an organisation then it's locationIds need to be recalculated based on all other associated organisations.

ProsCons 
User can be search based on any location hierarchy. In each user org association and disassociation locationIds need to be calculated, System load will increase

During org update , aging system need to do user location ids recalculations for all associated userIds.



Proposed Solution 2:

In every user search api call, sunbird will check filters value, if filters having Geo location then it will first search all those organisation ids that belongs to provided geo location codes then it update user search filter with collected organisation ids.

 "request": {
        "filters":{
           "state":"stateId",
           "district":"districtId",
           "block":"blockId" 
         }
    }


ProsCons
There is no changes in user org association and disassociationUser search will be little slower, because of making one extra search call
During org update we don't need to do any user location updates
No need to directly store one more key locationIds inside user


After discussion Solution 2 is accepted.



Changes in user profile read api:

 Background: 

                 As of now user profile read api is providing user basic details , and some extra details based on passed fields  (completeness,missingFields,topic,organisations) , User is having organisation association and geolocation data as well. So Profile consumer need to make two extra call to get those values . one call for collecting organisation details and another for collecting geolocation.


Proposed Solution :

       In get user api call system will take  one  extra field as  organisations, if  field will be available then system will make internal call and provide all values in same api.

      

getUserProfile
"organisations":[
{
"organisationId":"0123653943740170242",
"updatedBy":null,
"addedByName":null,
"addedBy":null,
"roles":[
"PUBLIC",
"CONTENT_REVIEWER",
"BOOK_REVIEWER",
"COURSE_MENTOR",
"ORG_ADMIN"
],
"approvedBy":null,
"updatedDate":null,
"userId":"97255811-5486-4f01-bad1-36138d0f5b8a",
"approvaldate":null,
"isDeleted":false,
"hashTagId":null,
"isRejected":null,
"id":"01236539303387955231",
"position":"ASD",
"isApproved":null,
"orgjoindate":"2017-10-31 10:47:05:805+0000",
"orgLeftDate":
// Adding new field in organisation
"orgName: "name of organisation",
"description": "description of org",
"channel":"org channel",
"hashTagId":"org hashTag",
"locationIds":[],
"locations":[
   {
   "code": "Mug-99",
    "name": "Munger-99",
    "id": "9587fd13-e742-4899-97e0-819b6771ac38",
    "type": "state",
    "parentId": null
   }
 ]
}

]


User Search:

 Problem statement : 

                             As of now in user search response only public fields are visible. But now email and phone also need to be visible in user search, and it should always be mask. And this should come is caller is org admin or course mentor role. As per current implementation all user private fields are stored in a separate index as "profileVisiblity" , so during search search private fields won't come because search is happen on user index.


Proposed Solution 1: 

     User email and phone will be always stored in user index inside ES  as mask data. During search system will check caller role if caller role is either org admin or course mentor then it will include email and phone as well in search. if caller is not having above role then email and phone won't come.


Proposed Solution 2: 

  User Private data will still be inside "profileVisiblity" index , so when ever search will happen based on caller role , system will fetch mask phone and email from another index and merge with existing response.


Accepted design is Solution 2: 




Note: What ever solution will be accepted for org creation , same can be applied for user creation as well.