Copy standard Odoo module to new custom module - odoo

Is there a straight forward process to copy a module to a new module name with its own dependencies?
In my example I need to create a module very similar to the EVENTS module, but I also need the EVENTS module in its original form.
I figure the easiest way is to copy the events module to a new module name and then make my changes to it.

yes, you can do that... but you have to refactor the MODULE name, MODELS name, VIEWS(form,tree,action) name DIFFERENT from EVENT modules. So ur EVENT modules didn't get pile up.

Don't do that, it's a very bad idea.
Inheritance is what you want
What you want to do is create a new module with the module event as a dependency of your module. Then you can create new views that inherit existing views using the this in the view definitions:
<field name="inherit_id" ref="xml_id_of_view" />
Then all the model class that you need to update have to inherit the existing models as explained in ORM Inheritance. You'll have choice between 3 ways on inheritance:
creating a new model from an existing one, adding new information to the copy but leaving the original module as-is
extending models defined in other modules in-place, replacing the previous version
delegating some of the model’s fields to records it contains
# 1.
class Event(models.Model):
_name = "new_event"
_inherit = "event.event"
# 2.
class Event(models.Model):
_inherit = "event.event"
# 3.
class Holiday(models.Model):
_name = "event.holiday"
_inherits = {
"event.event": "event_id"
}
event_id = fields.Many2one("event.event")
I won't go into details on the 3 possible ways on inheritance to keep it short but.
Will copy the model definition to a new model so you essentially have the same thing as if you copied the code including extensions from other dependencies loaded before inheriting the model.
Will just extend the model adding new functions, will essentially share data but can be avoided by adding a type and correctly filtering models. For example you'd want a type on events to keep them separated logically while keeping them in the same table. This has the advantage to keep things together. So if you want to display multiple types of events in a calendar it will be possible.
This will create a new table having some of the data kept in a different table and new data inside the new model table. In other words when you create this new model, you'll create this model and the one being delegated. One example is having an Event and having an Holiday. The holiday type would remain in its table and you could list all holidays, but each holiday would be link to an event with a date and so on. It's a bit like inheritance method 2 with a type except that data is being isolated in different tables. For example, the holidays will be visible inside the calendar event.event but won't display anything defined in event.holiday as event.event has no idea what's an event.holiday. (for example, res.users -> res.partner is using this method).
With that said, method 2 doesn't really have any cost to implement in speed, method 1 will also be fast as data is kept in its own table but if a module extend the model and isn't in your dependency tree, the changes made to the model won't be visible so it's not 100% copying the schema.
Method 3 is good when you want to keep data normalized where each table own the data it needs to exist and the whole data of the model can be spanned across multiple tables with an implicit one2one relationship.
Also inheritance of views
Also, you can inherit views to create a new views by setting primary=True.
Documentation on views
View matching
if a view is requested by (model, type), the view with the right model and type, mode=primary and the lowest priority is matched
when a view is requested by id, if its mode is not primary its closest parent with mode primary is matched
Setting a view as primary essentially tell odoo to consider it as a top view so it doesn't extend the view it inherits but create a new view with the extension. This can be used with new models being created to prevent custom changes to affect the views of models that don't have the extension.
You can change the model of the view to handle a different model. For example, the holiday model could be handled by inheriting the event.event view and setting the model as event.holiday and changing the type of the view to primary=True. Any other module extending this new view will not have any effect on the parent event.event views.
Why not copying a whole module:
Now as to why copying an existing module is a bad idea. When you copy a module, you're taking the maintenance of the code on yourself. So any changes from one version to an other or bug fixed in the event module will not be present in your module unless you manually maintain change of code in the event module into your one.
Then you may think it's fine and can get away with it but the moment you'll want to upgrade from let say odoo12 to odoo13. Your module will have to be ported and if you want to rollback your change to create a module that extends the event module like explained above. You'll have to remember exactly which commit you forked the module from. Otherwise you'll have a hard time making a diff and seeing what changes you did introduce and how to port it to odoo13. If you only create a module that extends events, you'll have to port your changes and if you're lucky, you won't have to change anything as since odoo8-10 things didn't change much in some modules so moving from one to an other version is usually straight forward but if you copy you're adding a lot of work in the future for nothing.
Also, this is all based on personal experience after I had to work on projects and modules developed from outsourced companies. Some of the people "developing" the modules did exactly what you're trying to achieve and it costed us so much time to extract the changes made by this company to the PointOfSale which resulted in a module with a few lines of code. The module prevented us from installing the actual point of sale, and the module I had to fix was based from a very old version of the PoS missing critical bug fixes.
It simply isn't worth it.

Related

Reusable complex read model

In my organisation we have a complex product card with lots of different properties. I could use Steam product card to visualize what I'm talking about: http://store.steampowered.com/app/219740/ (PS: Awesome game, check it).
Product card representation consists of properties such as title, description, price and associations like screenshots, reviews, ratings, tags etc.
Segments of product are used in different parts of application - for example you can find tag lists in user library (where you don't need screenshots).
How would you structure read model here?
a) Try to create small, generic view models (Screenshot, Tag) and composite them in concrete view (ProductCard, UserLibrary)?
b) Create one, god Product view model that'll contain every property that is related to product? (performance-wise - doesn't sound very good)
c) Create property tailored view models for each view? If so, how can I avoid code duplications (we use parts of product on EVERY page) if I have to re-use some specific parts (product title, price etc) all across application?
d) ?
I cannot use event listeners as projectors since product state is changed via legacy CRUD application which we cannot modify - we rely on shared database.
The answer is...
Create property tailored view models for each view
Why? Because it's the simplest and the most maintainable solution. In a read context, you're just dealing with read-only data. You don't need encapsulation or granular representation (a specific model for 'Screenshot' or 'Tag'). That doesn't mean you can't reuse any of the other view models if you already have them and they have the same data, but the main principle here is to create a view model to serve a particular view only.
Duplication doesn't exist in this context, because DRY refers to (same context) behaviour not data.
Why do you want to avoid code duplication ? Or more specifically why do you want to avoid code duplication in different bounded context ;)... If you create dependencies only based in avoiding code duplication you will create a wrong abstraction (not related to a valid use case).
I will quote Sandi Metz :
duplication is far cheaper than the wrong abstraction
prefer duplication over the wrong abstraction
Find more here about wrong abstraction

MVC : How to use database to drive validation attributes, or ALTERNATIVES?

In summary, I'm trying to create instance-specific data-annotation attributes at runtime, based on database fields. What I have now works fine for creating the initial model, but falls over when the model is posted-back and the server-validation happens.
(I have the same input model being used in a collection within a viewmodel, but different validation must be applied to each instance in the collection....for example the first occurrence of the input may be restricted to a range of 1-100 but the next occurrence of the same model, prompted for on the same input page, would be a range of 1000-2000. Another may be a date, or a string that has to be 6 characters long.......)
I'll explain what I've done and where my issues are:
I've inherited DataAnnotationsModelMetadataProvider and provided my own implementation of GetMetadataForProperty (This doesn't have any bearing on the validation problem....yet)
I've inherited DataAnnotationsModelValidatorProvider and provided a facade implementation of GetValidators. What I want to do here is create new attributes based on my database-records and then pass those attributes through to the base implementation so the Validators are created accordingly.
However...... GetValidators is called at a PROPERTY level....When it is called with a propertyname that I want to apply validators to, I need to find the applicable DB record for this propertyname so I can find out what attributes I need to create....BUT...I can't get the DB record's key from just a propertyname of the value field.....In fact, the DB key is in the parent model.....So how do I get hold of it?!
I've tried using a static variable (YUK) and storing the key during a call for one property, and retrieving it during another call for my value field property....But because the model is serialised one-way and deserialised the opposite way I end up with my key being out-of-sync with my required attributes.
To add a slight complication I'm also using a custom model binder. I've overridden CreateModel as advised elsewhere on here, but I can't find a way of attaching metadata or additionalvalues to a PROPERTY of my output model....Only to the model itself....but how do I get at MODEL metadata/additionalvalues inside the GetValidators call for a PROPERTY ?
So....My question is twofold.....
1) Can anyone help me get my database-key from my custom-Model-binder to my GetValidators method on my ValidationProvider? Or maybe using my custom Metadata provider?
2) Is there a different, simpler, way of creating validators at runtime based on database records?
I think you are making this far more complicated than it needs to be. You just need to make whatever your validation criteria selectors are part of your view model. They don't necessarily have to be displayed (they can be stored in hiddens if they need to be kept for postback purposes).
Then you can use something like FluentValidation to create rules that say
RuleFor(model => model.myprop)
.When(model => model.criteria == whatever)
.GreaterThan(100)
.LessThan(1000);
Where criteria is whatever value you use to select when your property has to be in a certain range.
So that would mean you build your view model to include the criteria that is used for validation rule selection.
I'd asked this on the FluentValidation forums also and the lack of answers here as well as the advice against using Fluent from there led me to find my own solution (I understand this almost certainly means I'm doing something really bad / unusual / unnecessary!)
What I've ended up doing is assigning my controller static variable in my Custom Model Binder's CreateModel method, where I have access to the entire client model, rather than trying to do it through a custom MetaDataProvider. This seems to work just fine and gets me towards v1 of my app.
I'm not really happy with this solution though so will look to refactor this whole area in the coming months so would still appreciate any other comments / ideas people have about how to implement dynamic validation in a generic way.
I know this is an old question, but I am answering this so that many others can be benefited from this.
Please see the below article where they are loading the attributes from an xml
Loading C# MVC .NET Data Annotation Attributes From XML, Form Validation
I think you can follow the same approach and instead of reading from xml you can read from database and add these rules dynamically based on the model data type
You can refer the below approach also
DataAnnotations dynamically attaching attributes

yii and non database models

I need some help as I seem not to be able to grasp the concept.
In a framework, namely Yii, we create models that correspond to database tables. We extend them from CActiveRecord.
However, if I want to create a class that will get some data from other models but then will do all the computations based on those results and do something with them... then how do I proceed?
I want to clearly divide the responsibility so I don't want put all the calculations in source db based models. Basically the idea is that it will be taking some stuff from some models and then updating another models with the results of the calculations.
What do I do?
Keep all the calculations in some controller and use required models? (Hesitant about this because there is a rule to keep controller slim)
Create a none db model and then work from there (how?)?
Do something else (what?)?
Thanks for any help!
For you to use the Yii interpretation of Model, you will have to create class, which depends on CModel. It is an abstract class, thus you will be required to implement attributeNames() method.
To use other "Models" with this new structure, you will need to inject them in constructor, or right after your custom model has been created.
In real MVC model is a layer, which mostly contains two sets of classes with specific responsibilities: domain business logic and data access operations. Objects which are responsible for Domain Business Logic have no clue where the information is stored and where it comes from. Or even if there is such a thing as "database".
This video might explain a bit: https://vimeo.com/21173483

How to bind an NSTableView to multiple core data entity types

I'm writing an application to help diabetics manage their condition. Information that is tracked includes blood sugar results, nutrition, exercise, and medication information.
In similar applications these entries are all presented in a single table view even though each type of entry has different fields. This data is manually tracked by many diabetics in a logbook, and I'm looking to keep that paradigm.
Each entry has some common information (timestamp, category, and notes) as well as information specific to each entry type. For instance, meal entries would have detailed nutrition information (carb counts, fiber, fat, etc), medication entries would indicate which medication and dosage, etc.
I've considered two different approaches but I'm getting stuck at both a conceptual level and a technical level when attempting to implement either. The first approach was to create an abstract entity to contain all the common fields and then create entities for each log entry type (meals, meds, bg, etc.) that are parented to the abstract entity. I had this all modeled out but couldn't quite figure out how to bind these items to an array controller to have them show up in a single table view.
The second approach is to have one entity that contains the common fields, and then model the specific entry types as separate entities that have a relationship back to the common record (sort of like a decorator pattern). This was somewhat easier to build the UI for (at least for the common field entity), but I come to the same problem when wanting to bind the specific data entities.
Of course the easiest approach is to just throw all the fields from each different entry type into one entity but that goes against all my sensibilities. And it seems I would still run into a similar problem when I go to bind things to the table view.
My end goal is to provide an interface to the user that shows each entry in chronological order in a unified interface instead of having to keep a separate list of each entry type. I'm fine with adding code where needed, but I'd like to use the bindings as much as possible.
Thanks in advance for any advice.
Don't get bogged down with entity inheritance. You shouldn't use it save duplicate attributes like you would with classes. It's major use is allow different entities to be in the same relationship. Also, entity inheritance and class inheritance don't have to overlap. You can have a class inheritance hierarchy without an entity inheritance hierarchy.
I'm not sure I understand exactly what you really need but here's some generic advice: You shouldn't create your data model based on the needs of the UI. The data model is really a simulation of the real-world objects, events or conditions that your app deals with. You should create your data model first and foremost to accurately simulate the data. Ideally, you should create a data model that could be used with any UI e.g. command-line, GUI, web page etc.
Once your model is accurately setup, then whipping up the UI is usually easy.

How to prevent multiple classes for the same business object?

A lot of the time I will have a Business object that has a property for a user index or a set of indexes for some data. When I display this object in a form or some other view I need the users full name or some of the other properties of the data. Usually I create another class myObjectView or something similar. What is the best way to handle this case?
To further clarify:
If I had a class an issue tracker and my class for an issue has IxCreatedByUser as a property and a collection of IxAttachment values (indexes for attachment records). When I display this on a web page I want to show John Doe instead of the IxCreatedByUser and I want to show a link to the Attachment and the file name on the page. So usually I create a new class with a Collection of Attachment objects and a CreatedByUserFullName property or something of that nature. It just feels wrong creating this second class to display data on a page. Perhaps I am wrong?
The façade pattern.
I think your approach, creating a façade pattern to abstract the complexities with multiple datasources is often appropriate, and will make your code easy to understand.
Care should be taken to create too many layers of abstractions, because the level of indirection will ruin the initial attempt at making the code easier to read. Especially, if you feel you just write classes to match what you've done in other places. For intance if you have a myLoanView, doesn't necessarily you need to create a myView for every single dialogue in the system. Take 10-steps back from the code, and maybe make a façade which is a reusable and intuitive abstraction, you can use in several places.
Feel free to elaborate on the exact nature of your challenge.
One key principle is that each of your classes should have a defined purpose. If the purpose of your "Business object" class is to expose relevant data related to the business object, it may be entirely reasonable to create a property on the class that delegates the request for the lookup description to the related class that is responsible for that information. Any formatting that is specific to your class would be done in the property.
Here's some guidelines to help you with deciding how to handle this (pretty common, IMO) pattern:
If you all you need is a quickie link to a lookup table that does not change often (e.g. a table of addresses that links to a table of states and/or countries), you can keep a lazy-loaded, static copy of the lookup table.
If you have a really big class that would take a lot of joins or subqueries to load just for display purposes, you probably want to make a "view" or "info" class for display purposes like you've described above. Just make sure the XInfo class (for displaying) loads significantly faster than the X class (for editing). This is a situation where using a view on the database side may be a very good idea.