I have a module which will not inherit from another one it will be for sports club
players and trainers will have access rights to use the system and my question as follows:
1- which is better, create new model from scratch or inherit from partners, employee, contact or users
2- if I create new model or inherit from another model which is not users how to make any player a user by default
You will probably have to create a partner for your user anyways. My thought is that you may want to make your players partners. You can override the view and remove the elements that are not player oriented or hide them if the is_player flag is true. (You may want to add a new is_player boolean). You can use the is_player boolean to define when to display the player view or a generic contact view.
Personally I would use partner and users as so much of Odoo's security and structures are already built around these models.
If your player inherits partner you can override the create() method and within it simply create a user after you have created your contact.
#api.model
#api.returns('self', lambda rec: rec.id)
def create(self, vals):
vals['notify_email'] = 'always'
rec = super(Partner, self).create(vals)
v = {
'active': True,
'login': rec.email,
'company_id': 1,
'partner_id': rec.id,
'create_uid': 1,
'write_uid': 1,
'display_groups_suggestions': False,
'share': False
}
user_id = self.env['res.users'].sudo().create(v)
return rec
The above example creates a user with a bunch of values you will probably want to change to be more appropriate for your needs. After you create the user you will want to send a password reset.
Related
I am trying to model a company and its relevant employee strucutre. I have 3 tables (company, position, employee) as below, and company haveMany position, and employee haveMany position. Position belongs to company, and position belongs to employee.
However, different position have some common field like onboard date, but have some fields are different. Forexmaple, CEO has a gurantee employment period, while other position dont. Quite a number of field is different too for different position.
In that case, should I using polymorphic to model? but as the company has quite a number of different position, this will create quite a lot new table in the database.
Do you have any advice on how to model different positions?
Companies
id
Position
Positions
id
type [CEO, manager, director, clerk, etc]
company_id
employee_id
Onboard Date
Ceased Date
Employees
id
position id
In that case, should I using polymorphic to model? but as the company has quite a number of different position, this will create quite a lot new table in the database.
No, why would be?
First of all, it should be manyToMany relation and not oneToMany because if you have two companies both of those can have CEO (for example) position and if you set $position->belongsTo(Company::class); it couldn't work.
It is polymorph relation there with positions as polymorphic angle of that triangle.
You would need
// companies
id
name
// employees
id
name
// positions
id
name
// positionables
position_id
positionable_id
positionable_type
With this, your models would be
class Company extends Model
{
public function positions()
{
return $this->morphToMany(Position::class, 'positionable');
}
}
class Employee extends Model
{
public function positions()
{
return $this->morphToMany(Position::class, 'positionable');
}
}
class Position extends Model
{
public function companies()
{
return $this->morphedByMany(Company::class, 'positionable');
}
public function employees()
{
return $this->morphedByMany(Company::class, 'positionable');
}
}
It allows you to set positions, companies and employees separately. Meaning, From dashboard you can make some new positions that will be available on frontend from select options let's say. Of course you should allow company and to employee to create new position (I suggest) and not just to use existing one but it could be out of scope of this question now: in example, when (and if) company creates new position (instead of selecting existing ones from options list), you would first create that position and store it into positions table and then associate company with it. Also, when using this kind of chained inputs to DB don't forget to use DB transactions. Into positionables table you would set other fields important for each relation (onboard_date, ceased_date, etc).
Documentation is very good and consult it if something is not clear (I hope it is already).
Disclaimer: I don't know rest of your project business plan and rest of project's requirements but for these three entities this is the best structure you can go with. I have set just mandatory members to models and tables for this example. Also in offered answer, I presumed use of Laravel's naming convention that's blindly followd from docs and this repo.
If the fields have no relationship with other tables, one possible way is to have a key-value table to store those fields and values:
position_fields
- id
- position_id
- key
- value
You can hence store the fields in key and the respective value in value. Then you may overwrite the __get magic method in Position model e.g.
public function __get($key){
$position_field = $this->hasMany(PositionField::class)->where('key', $field)->first();
return !!$position_field ? $position_field->value : $this->getAttribute($key);
}
I have an appointments table and an appointment_members table and my users need to be able to get a collection of appointments by searching with a "member_id", which could be a Person, Incident or CustomerID. The appointment_members table has member_id and appointment_id columns, so the member_type (also a column) is irrelevant. This all set up by a previous dev and what is missing are the relationships on the Eloquent models. I'm just creating a simple GET route that needs to return any/all appointments by that member_id. Each row has one appointment, so if I were to pass in a member_id that returned 10 results, some could have appts and others not, but at the end of the day I just need a collection of appts that are related to that member_id. Here's a screenshot of the appointment_members table:
If I create a simple hasOne relationship to appointments on appointment_members:
public function appointments()
{
return $this->HasOne(Appointment::class, 'id', 'appointment_id');
}
I can get a collection of appointment_members with it's respective appointment, but not sure how I boil it down to just getting the appointments. One workaround I have is to use that HasOne and then pluck/filter the appointments:
$appointmentMembers = AppointmentMembers::where('member_id', $request->input('memberId'))->get();
$appointments = $appointmentMembers->pluck('appointments')->filter();
Curious if anyone might see a better way to go about this. Thanks!
I'm possibly not understanding, but I would probably take the simplest approach here if the member type is not important.
The table is already set up to handle either a belongsToMany or a morphMany, so create the relationship on the Member class (or if you don't have a parent member class, stick it on each of the types Person, Incident, etc. You can also do this via poly, of course, but this is a simple example to get what you need):
public function appointments()
{
return $this->belongsToMany(Appointment::class)->withPivot('member_type');
}
And then just query on the member object you need appointments for (having poly would make this one step):
$allAppointmentsForID = $member->appointments();
$appointments = $allAppointmentsForID->wherePivot('member_type', $whateverClassThisIS);
The above takes member_type into account. If this doesn't matter, you can just use the top line.
Your original db is setup to handle polymorphic relations, so if you wanted more than the appointment you can set it up this way as well. For now, you'll need to add the TYPE to the query to cover the different classes.
If the member type is important, polymorphic might be something like this on the Member class:
public function appointments()
{
return $this->morphMany(Appointment::class, 'memberableOrmember_typeOrWhatever');
}
Then you can query on the member object with just one line
$appointments = $member->appointments();
In my module i have two models, book and room. In room i will keep room details. In book i will keep the booking details of room. I have a many2one field in book model relating to room model. When i save the record of book, near to the many2one field a redirecting button will come. On clicking that, it will open the form view of room model. I want to make the second form view to be read only. How can i do that?. I tried to keep only read access for room model, then i can't able to save book model record. So how can i complete
class room(models.Model):
_name = 'room'
name = fields.Char('room name')
class book(models.Model):
_name = 'book'
name = fields.Char('booking person')
time = fields.Datetime('time')
room_name = fields.Many2one('room','room name')
Hello First take one boolean(like temp_bool) in room object,
now in book object, when you select room then write temp_bool field as True in selected room,
now based on this boolean you can give attrs in room object like attrs="{'readonly': [('temp_bool','=','True')]}"
This question is related to Parse.com
I want to build a push query to push a notification from cloud code to all users belonging to 'Moderator' role.
I tried below code, it failed to push as "users" is a relation, not an object.
var moderatorQuery = new Parse.Query(Parse.Role);
moderatorQuery.equalTo("name", "Moderators");
// Push to devices belonging to these moderators
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesKeyInQuery("installationOwner", "users", moderatorQuery);
Another way of doing this is by fetching the Moderator role object and using the relation.query() or by calling getUsers() on moderator object.
But my requirement is to push to a query directly without fetching(get/find) any object.
How to build such a query ?
I think you need first to get the role, then use it's user relation query as the query to match in the pushQuery, like this:
var moderatorQuery = new Parse.Query(Parse.Role);
moderatorQuery.equalTo("name", "Moderators");
moderatorQuery.first().then(function(moderatorRole) {
var pushQuery = new Parse.Query(Parse.Installation);
var usersQuery = moderatorRole.relation("users").query();
pushQuery.matchesQuery("installationOwner", usersQuery);
// setup push, then send()
});
EDIT - Missed the last sentence of the question. The short answer is that there's no way to query the "many" side of the relationship in a single query.
The longer answer is that it can be done with additional data. You can make the query singular at the cost of keeping additional data up-to-date.
For example, you could keep an (a) isModerator bool on the User, or (b) more generally, a "roles" array of pointers (not a relation, because that's your root problem) on User, or (c) a separate table altogether that joins Role and User with singular pointers.
All of these ideas make the single-query easy (a) query User where isModerator == true, (b) query User where roles isEqual to moderator, (c) query TheJoinTable where role == moderator, include user and select user.
Doing this shifts the burden from the query to keeping the extra data up to date. You could accomplish this pretty simply using beforeSave on either end of the Role-User relation (probably Role).
All that said, you should examine the added constraint of a single query very carefully and make sure its worth the extra trouble.
I have to implemene Single Table Inheritance for a class Person who can be of type Teacher, Student,Outsider.
class Person < ActiveRecord::Base
end
class Teacher < Person
end
class Student < Person
end
class Outsider < Person
end
What changes do I need to make in the routes and the forms while register a new user. I have a column(string) "type" in the people table which can be implemented as a dropdown in the form to register a new user. Is there anything else that I need to do in the form so the user is registered as a particular type of Person? Do I need to make any changes in the routes too?
Since you use one form to create all types of Persons, then you should stick with one Controller as well so you don't need to add any additional routes.
The type attribute is not really something you should assign manually to an instance, it should be set automatically by choosing which type of model to create.
I don't know how it looks in your controller and views, but you can extract the type of model to create like this:
class_type = params[:type].constantize
#person = class_type.new
On the other hand, if the type attribute is nested in a form_for in your view, then the type attribute is probably send to the controller like params[:person][:type] in which case it should be removed from the :person hash before it is used to create the new instance. Perhaps something like this:
class_type = params[:person].delete(:type).constantize
#person = class_type.new(params[:person])
Except adding a dropdown list of type selection in the form, there's nothing more to do. You can create a user in the normal way, like:
#user = Person.new params[:user]
But the type attribute could not be mass assigned, so you have to assign it separately.
#user.type = sanitize_user_type params[:user][:type]
The method sanitize_user_type is used to validate user input value.
The route for creating new user doesn't need to change. Whether other routes need to change or not depend on your requirement. Actually you can add the routes for Teacher, Student, Outsider and relative controllers, so that you can build restful urls.