Software Engineering: Organize different kind of users - oop

Alright people,
In the last couple of days I've been thinking how to implement this properly, and I'd like to know what your approach would be to implement the following scenario:
I'm doing an eCommerce platform, and we have many kinds of "entities". Entities are not necessarily users that have credentials and can login in our platform, and everything should be fairly decoupled from everything else.
Real life scenario: We have customers, employees and suppliers, all of these can or not be a User, as in, they may or may not have login credentials. I can attach a contact (address info) to any of these models, or an invoice... The idea is that we may have customers that don't actually have credentials that we issue invoices to, or create an order to a user that doesn't actually login... Same for invoicing, I want to be able to invoice a customer, as well as a supplier.
The problem that I'm having is that these 3 types of user are more or less the same, they can have orders/invoices/contacts/whatever attached to them, but they aren't necessarily a user. In fact, credentials must be something that we should be able to attach to any of those models, if we want, so a supplier can have a login to access whatever they need.
How would you design this?

I would logically separate users from organizations, then create abstractions for both users and organizations, then create concrete classes for them that are composed in whatever combination is appropriate for each. You don't really have three types of users, you have two types, employees and representatives of outside organizations. Those outside organizations could have multiple authorized users (or not), and they may also have relationships with your employees. You don't mention whether a customer represents a single person or an organization, that makes a difference in how you model your domain. Here's how I would model it, assuming that a customer is logically an organization, not an individual person. If Customer is a person, authorizedUsers would move down into the Supplier, and Customer would have a single User property.
abstract class TransactionalEntity
{
String name;
Set<Address> billingAddresses;
Set<Address> shippingAddresses;
Set<Invoice> invoices;
Set<Order> Orders;
Set<User> authorizedUsers;
}
abstract class User
{
String firstName;
String lastName;
String email;
String username;
String password;
}
class Supplier extends TransactionalEntity
{
Set<Product> suppliedProducts;
}
class Customer extends TransactionalEntity
{
Employee salesRepresentative;
}
class Employee extends User
{
String title;
Double salary;
Date startDate;
Address homeAddress;
Employee supervisor;
}

Related

Referencing UserClaims in an Entity Framework Core class

I'm developing a data project with ASP.NET Core and Entity Framework Core. We're starting to use user claims (Identity) to manage authorization for things like managers etc. Previously, we had a separate table for managers, so that each permission could be set on each object and we looked it up as required.
Simple example prior to UserClaims:
Store { StoreId, Name etc... plus ICollection<ManagerPermissions> }
User { StoreId, Name, Email etc}
ManagerPermissions { StoreId, UserId }
Using the separate ManagerPermissions table meant it was easy to list the relevant manager(s) for that store by using a navigation property like ICollection<ManagerPermissions>. If writing a query, I could do _context.Store.Include(s => s.ManagerPermissions) to include a list of managers to display.
Now that we're using user claims, I haven't found an easy way to do this. I've extended IdentityDbContext so the claims data is held within the same database as the other data.
I have seen
UserManager.GetUsersWithClaimAsync({ ClaimType="ismanager", ClaimValue = StoreId})
but this requires an instance of userManager and also a separate roundtrip to the database. The only other way I could think of is by doing a join on UserClaims table, but I'm not sure the most efficient way of doing this.

How to add data to res.partner fields for mlutiple companies via API

I'm trying to add account payable and receivable fields for a partner in Odoo via API. However, they are only being applied to the default company. I hope the following images clarify.
How it appears for our default company :
How it appears for the other company :
I'm creating a partner as follows :
user_id = models.execute_kw(db, uid, password, 'res.partner', 'create', [{'name': name,'email':email,'company_id': odoo_company_id,'property_account_payable_id':account_payable_id,'property_account_receivable_id':account_receivables_id,'property_product_pricelist':pricelist_id}])
Any idea how this can be done ? Thanks in advance.
Those are properties and values are stored in ir.property objects. You probably have to write those entries for each company.
Remember that accounts are company-depending objects as well, so you cannot use same account.account object to every company. They are different objects with different ids in database even if accounts may have same code and name and you cannot see any difference on user interface.
You can also define default property for each company, if that is what you want. It can be done through GUI.

Use non standard types in Azure Easy Tables

I'm trying to use Azures Easy Tables in my Xamarin Application.
I have data in 2 tables in azure which i added through csv. These tables include only standard types like string, date and numbers and are correctly synced to the device.
Additionally i have several other tables which are present in the local sync store. These tables / classes also use non standard types i defined myself. For example i habe a class Contact which has a property Company, which again is another class with several standard properties. These tables are currently only saved locally in the sync store, and it's working as expected. I'm now trying to sync these tables to to Azure Easy Tables.
So what i did was creating the table as an Azure Easy Table in Azure named Contact, with dynamic schema activated. When i try to Client.SyncContext.PushAsync() i get the following Exception:
MobileServiceLocalStoreException:
"Push operation has failed. See the PushResult for details."
Inner Exception / JsonReaderException:
"Failed to read errors from the local store."
Inner Exception / JsonException
"Unexpected character encountered while parsing value: C. Path '', line 0, position 0."
Push Result seems to provide no information (Error Count 0)
I have no idea what this Exception tells me. Maybe the problem has something to do with the properties being non standard? How are these properties even mapped to an easy table. Is a non-standard property like company simply split into several columns like Name, Street, City?
Or does the Exception point to some other problem with the local sync Store? As i said, the local syncstore is currently working fine and the pull from azure easy tables for some tables is also working fine.
I'm grateful for every answer that might point me in the right direction.
Per my understanding, you are handling 1:1 relationships between Contact and Company tables. For offline sync, you need to define the Contact and Company classes in your mobile client as follows:
For mobile client models
public class Contact : TableData
{
public string ContactName {get;set;}
public string Phone {get;set;}
public string Address {get;set;}
public string CompanyId {get;set;}
}
public class Company : TableData
{
public string CompanyName {get;set;}
public string Address {get;set;}
}
Note: As adrian hall's book Chapter3 :Relationships states about relationships on mobile client as follows:
There are a couple of rules you must follow within your client code:
You need to ensure that you create a Company before associating that Company with a Contact.
You need to store the CompanyId with the Contact, not the Company object (as you would normally do within Entity Framework).
If you InsertAsync a Company in offline mode, it will be placed into the operations queue prior to anything that uses it. Since the operations queue is processed in order, the Company will be sent to the backend prior to any record updates that would use it.
For Azure Easy Tables, you need to create both Contact and Company tables, and it would automatically create the Node.js backend for your created tables.
I would prefer handling tables individually and handling relationship management on the mobile client manually which could make the server much simpler by avoiding most of the complexity of relationships. Additionally, you could refer to Chapter 3 - Data Access and Offline Sync.

Accessing role ID through module

Im quite stuck here. In my cwebuser I've already defined my roles. My logins to my modules are restricted by roles, which is great! But my problem is restricting the modules to specific users within the roles. In webuser isShop is defined as a certain user id (user_role_id) in database to see if the user is user or shop. The issue is shop module can be seen by all roles who are isShop. My question is is there a way to authorize so that shop module gets user's id and shop id?
Something that mimics yii::app()->user->user_id;
like yii::app()->getmodule(shop)->shop_id;
Or must this be defined in model through criteria by shop_id? Doesn't sound right though, doing it this way.
I think if you are using the following function in model, you can apply the SHOP relations in here
public function defaultScope() {
if(isset(yii::app()->user->user_id)) return array('condition'=>'');
// here you can apply your conditions with the relation feilds
}

Phone books and databases : what's the best option?

I am currently working on a development project for which I need to make a database (I will be using Postgre).
Part of that database must store a phonebook for every company, and also for every user. Those two "types" of phonebook are stored in two tables, although they contain the same type of information :
PersonalPhoneBook(IdOwner, IdUser)
//Ids of the owner and a user he's in contact with.
CompanyPhoneBook(IdCompany, IdUser)
//Ids of the company and a user it's in contact with
The personal phonebook will be retrieved with a request like:
SELECT * F
ROM User
WHERE IdUser IN
(SELECT IdUser FROM PersonalPhoneBook WHERE IdOwner = x);
(this request isn't optimized, but you get the gist).
I should also mention that every user and company has as many details (phone numbers, addresses, ...) as they want, thanks to these three tables :
ContactDetail(IdContactDetail, LbContactDetail, ValueContactDetail)
Company_ContactDetail(IdCompany, IdContactDetail)
User_ContactDetail(IdUser, IdContactDetail)
Now there is something that I didn't take in count in that model : the users and companies will want to include in their phone books some people that aren't users in the database.
So I've been exploring several solutions, and I'd need advice to determine which is best:
Making two other tables to store a fixed number of details (2 phone numbers, 1 address) on those "outsiders".
Making all "outsiders" users (but I find that pretty ugly to store them together)
Store an independent phonebook (LDAP-type) for every company and every user (but then data is replicated)
Keep the contact detail system for companies and users and use a LDAP system for the others
Other...?