Client Company Organization

Hi Cuba team,

As I came from ERP background (Compiere, Adempiere, iDempiere, Navision, Dynamics etc)
I wish to ask whether below are easy to implement using CUBA studio

Note : Only 1 database for this project.

  1. A user with a client id will only see his client data after login. (i have read the saas example in github). Is is possible to have 1 user access multiple client data? So that we do not need to create 1 user per client for the same physical user.

  2. Each entity (table) should have 2 columns called company and organization. Organization belongs to Company belongs to Client. Said the login user has

client = 111
company = 222
organization = 333

all list and read or any operation must be upon unique rows of 111,222,333.

(optional) if company = 222,444 and organization = 333,555,666. Then all list and read or any operation will be upon rows of 111, 222 and 444, 333 and 555 and 666.

We are used to this pattern and our customers base also accept that. I understand that and read all your documentation that CUBA doesn’t seem to have this currently. What I need to know are ways to implement that.

There is a database issue.

The current project are using Postgres-XL. We will have 3 coordinators. 192.168.1.101:5432, 192.168.1.102:5432 and 192.168.1.103:5432. Said I will 3 middleware clusters host 3, host 4 and host 5 and wish to connect coordinator similar to normal postgresql connection

host 3 > 192.168.1.101:5432
host 4 > 192.168.1.102:5432
host 5 > 192.168.1.103:5432

host 3, 4 and 5 is from the same source code but the connection string will be different. i guess i can’t fix the connection string inside studio. do i need to modify property file for that inside each tomcat instance? where is the file location? My plan for development inside studio will be using either postgresql or postgres-xl (single coordinator) inside my laptop. When I finish war creation, after i deploy to each tomcat. Will it override my previous connection property file on each tomcat instance?

Thank you for helping.

1 Like

Hi Adam,

regarding your first question:
> 1. A user with a client id will only see his client data after login. (i have read the saas example in github). Is is possible to have 1 user access multiple client data? So that we do not need to create 1 user per client for the same physical user.
This is possible. Create an Entity called “Client” and create a association “user” as a many-to-one relationship. With this you can create multiple client that all have a relationship towards a user and therefore a user can see data from multiple clients.

For the other questions - others might step in here.

Bye,
Mario

1 Like

Hi Adam,
In addition to creating the many-to-one relationship between Client and User (as Mario suggested), you should dynamically set the Session Attribute for the logged in user based on what clients he should see. In the SaaS example, the session attributes are defined statically for each client access group - this is simple, but you cannot assign one user to several clients . So you should do the following:

  • in your App class, override the connectionStateChanged() method and after checking connection.isConnected() load the list of clients for the current user. Then set the session attribute:

connection.getSession().setAttribute("client_ids", <a list of integers>);
  • in the Access Group Constraints tab for the root Clients group change the constraints for all entities to the following:

{E}.client in :session$client_ids

As for your second question about client-company-organization structure, I don’t quite understand how it is different from the task of separating users by clients? Could you elaborate?

Regarding the connection URL problem, the solution is easy. We assume that when you work in Studio, you connect to a development database only, so the connection URL which is set in Studio is used only on development stage. When you deploy to a test or production environment, you should provide other connection parameters. A quote from the docs:
You can do it in the context.xml file of your web application (webapps/app-core/META-INF/context.xml), or copy this file to conf/Catalina/localhost/app-core.xml as described in the previous section to separate development and production settings.
So when you deploy a new version of the app in WAR or exploded WAR to webapps folder, your production connection settings will remain untouched in the conf folder and override settings in WAR.

2 Likes

Thanks Mario David.

Thanks Konstantin Krivopustov,

I have subscribed a license for me to starts with. Man, this is the first featureful product I feel so happy to work with after Microsoft Access many years ago :smiley: Of course, visual basic, netbeans, eclipse and etc. are nice. The price are worth to save times for google search and reading books XD.

The Client, Company and Organization concept is to share a database for all staff scattered over locations. Originally it’s Client + Organization, but my country here alot of my customer has group of companies. Said customer Boss A having 3 group of companies for selling raw materials, building house and logistics services. Each group has multiple companies that has different functions. Like there are building business buildings, building condominium, building government buildings, building housing estate, building factory and etc. Each different industry derive different trade licenses. I don’t know why but that is my customers’ behavior here. So, in order to calculate and showing some reports. Client + Company + Organization is the normal setup. eg.

Client = Sales and Marketing
Company = XXX Ice Cream Ltd.
Organization = State Region, City Branch, Branch Warehouse, HR Department etc.

or

Client = Sales and Marketing
Company = YYY IT Store Ltd.
Organization = State Region, City Branch, Branch Warehouse, HR Department etc.

or

Client = Logistics
Company = ZZZ Third Party Logistics for AAA Client
Organization = State Region, City Branch, Branch Warehouse, HR Department etc.

or

Client = Logistics
Company = TTT Third Party Logistics for BBB Client
Organization = State Region, City Branch, Branch Warehouse, HR Department etc.

Above examples might seems illogical, but it is what had requested. The main purpose is to produce reports for MD, CEO, Managers and Supervisors starting from Organization towards Multiple Client (I know analytics like mapreduce, hadoop and etc. can solve that but we don’t have that kind of experts here). Of course data validation and workflow control are needed as basics or else who want to computerised the works :smiley:

Client access has solved. Now left is

Elaine login, as PIC for Company A, she can read only rows with Company = Company A and Organization = ALL.

James login, as sales manager for Company A, he can read only rows with Company = Company A and Organization = Sales Department.

Mark login, as inventory staff for Company B and working under Branch C can read only rows with Company = Company B, Organization = Branch C, Warehouse D (Company = Company B and Organization = Branch C).

To be simple, every row will have 2 columns named “CompanyId” and “OrganizationId” and we need to make sure the user can read only what have been assigned.

Note : Like Client, 1 user can read multiple Company + multiple Organization.

eg. John login, as PIC for Company A, Company C and Company J. His access with be

Client = 1 (for A) and 3 (for C and J)
Company = A, C and J
Organization = *

Note : Client, Company and Organization is all about data filtering before serving to the form / page. It is different to Access Rights for Page, Form, Entity, Operation and Columns.

I guess need to override a framework class for filtering or else have to override every entity in the project to filter the rows.

Thanks for helping up.

Hi Adam,
Thank you for such positive feedback and for the explanation of your problem.

I think you can solve it by using the same approach as with Client alone.

  • Create a data structure that describes links between User and your Client, Company and Organization. It can be a separate entity, say, Employee, that has one-to-one reference to User and many-to-many references to Client, Company and Organization.
  • On login, in your App.connectionStateChanged() method (as I explained above), load the Employee entity for the current user together with related collections. You can do it through DataManager providing a relevant view.
  • Set session attributes:

connection.getSession().setAttribute("client_ids", <a list of integers>);
connection.getSession().setAttribute("company_ids", <a list of integers>);
connection.getSession().setAttribute("org_ids", <a list of integers>);
  • In the Access Group Constraints tab for the root Clients group change the constraints for all entities:

({E}.client in :session$client_ids) and ({E}.company in :session$company_ids) and ({E}.organization in :session$org_ids)

So all entities having such constraint will be available only to users with corresponding sets of Client, Company, Organization values. This filtering takes place when data is loaded to the client tier through datasources and DataManager. When you write business logic on the middleware, you can decide, whether you want to apply these constraints. By default, security is not applied on the middleware, but you can turn it on if you use DataManager.secure() wrapper.

2 Likes