I'm currently building a module like a project module which shows Kanban view for model 'test.project' and when I click Kanban view, It shows tree views for model 'test.task' related to 'test.project'.
So I made a code below
class Test_project(osv.osv):
_name = "test.project"
_columns = {
'name': fields.char('Name'),
'task_ids': fields.one2many('test.task', 'project_id', string='TASK')
}
class Test_Task(osv.osv):
_name = 'test.task'
_columns = {
'project_id': fields.many2one('test.project', string='Project ID', required=1),
}
When I saved a data for 'test.project', It is saved correctly, But When I saved a data for 'test.task', It shows an error which is
IntegrityError: null value in column "project_id" violates not-null constraint
Cannot get the id.
You have set required=1 on the definition of the project_id field. That means that every time you create and save a record you will have to give a value to that fields otherwise you will not be able to save it.
Related
Hope you guys doin well,
I'm curious about how can a certain string like # and # can trigger a popup of a user and channels in Odoo Chatter & Discuss. This chatter has mail.thread Models related to it but i can't seem to understand how is it possible to create my own custom trigger in chatter?
Is it belong to certain views and not in models?
Any help will be appreciated!
Those are suggestion delimiters for the models used to update the suggestion list.
const suggestionDelimiters = ['#', ':', '#', '/'];
For example # is used to fetch partners (mail.partner model) matching a given search term. The _updateSuggestionList function will search the suggestions, sort them then will show (update) the popup list
To add a new custom trigger, you need add the delimiter to the suggestionDelimiters list and alter the _computeSuggestionModelName function to return the related model, the model must be defined like the mail.partner model.
If you want to patch an existing model, check the following example (taken from the hr module):
/** #odoo-module **/
import {
registerInstancePatchModel,
registerFieldPatchModel,
} from '#mail/model/model_core';
import { attr, one2one } from '#mail/model/model_field';
// Patch model
registerInstancePatchModel('mail.partner', 'hr/static/src/models/partner/partner.js', {
async checkIsEmployee() {
await this.async(() => this.messaging.models['hr.employee'].performRpcSearchRead({
context: { active_test: false },
domain: [['user_partner_id', '=', this.id]],
fields: ['user_id', 'user_partner_id'],
}));
this.update({ hasCheckedEmployee: true });
},
});
// Patch fields
registerFieldPatchModel('mail.partner', 'hr/static/src/models/partner/partner.js', {
hasCheckedEmployee: attr({
default: false,
}),
});
There is another way, and that is using the / or "command" popup. You can add your own item in the popup list and trigger any actions when a user selects your item from the popup.
Inherit from mail.channel
class MailChannel(models.Model):
_inherit = 'mail.channel'
Add a new method that starts with _define_command_XXXXX. This registers the item in the popup.
def _define_command_sample(self):
return {'help': _('Here is some sample help')}
Add a new method that starts with _execute_command_XXXXX. This method is executed when the user uses your command.
def _execute_command_sample(self, **kwargs):
# Send a "temporary" message to the user
self._send_transient_message(self.env.user.partner_id, f"Hello! You just successfully used the /sample command. You typed {kwargs['body']}.")
Reference: Github where Odoo defines the /lead command
PS: The above is for Odoo V12.0 - V14.0. Odoo V15.0 works a bit different, but you can check this and this for how to do it.
I am using KeystoneJS. I have a relationship field in my Post model that references another model called Device. I am using many: true to allow users to select multiple items from the Device model.
Is there a way to have them all initially selected when creating a Post?
Right now my relationship field looks like this:
availableDevices: {
type: Types.Relationship,
ref: 'Device',
many: true
}
In your model definition, you can add pre-processing steps to populate fields that you'd like to have a default value in the relationship. I haven't done this with a many relationship, but I have done it with a relationship like this:
Report.schema.pre('save', function (next) {
this.wasNew = this.isNew;
if (!this.employee) {
this.employee = this.createdBy;
}
if (!this.timeEnteredTheHomeStr) {
if(!this.timeEnteredTheHome) {
this.timeEnteredTheHome = Date.now
}
this.timeEnteredTheHomeStr = String(this.timeEnteredTheHome);
}
next();
});
When someone creates a new report object, the employee field is automatically set to the user object referenced in the createdBy field.
I'm developing on Odoo 10.
I created a dynamic form view which search and display a product from its barcode, but I've got a problem.
Since the view has no initial record to display it is opened in edit mode, and that's ok, because I want to type the 'barcode' field.
But, after the product is displayed, when I exit from that view the 'can_be_discarded' function is fired, opening the confirm dialog.
Have I to create a new view type inheriting from FormView or is there a way to workaround this problem?
The view is a classic form view, with nothing special.
Here's the server code instead.
class ProductFromBarcode(models.TransientModel):
_name = 'levelprime_product_general_status.product_from_barcode'
_inherits = { 'product.product': 'product_id' }
product_id = fields.Many2one(
comodel_name='product.product',
store=False)
product_barcode = fields.Integer(help='Insert the barcode to search '
'the correspondent product',
store=False)
#api.onchange('product_barcode')
def on_barcode_changed(self):
if self.product_barcode != 0:
self.product_id = self.get_product_from_barcode(self.product_barcode)
#api.model
def get_product_from_barcode(self, barcode):
r = self.env['product.product'].search([('barcode', '=', barcode)])
if r:
return r
Ok, I think I'm in the right way, there are some rendering problem to solve, but the main behavior is what I was searching for.
I created a new type of view which inherit from the 'FormView' one and override the 'can_be_discarded' method to not execute controls about the data changes.
JS
odoo.define('levelprime_product_general_status.readonly_formview', function(require) {
'use strict'
var core = require('web.core')
var FormView = require('web.FormView')
var ReadOnly_FormView = FormView.extend({
init: function() {
this._super.apply(this, arguments)
},
start: function() {
this._super.apply(this, arguments)
},
can_be_discarded: function() {
return $.Deferred().resolve()
}
})
core.view_registry.add('readonly_form', ReadOnly_FormView)
return ReadOnly_FormView
})
PY
class ViewExtension(models.Model):
_inherit = 'ir.ui.view'
type = fields.Selection(selection_add=[
('readonly_form', 'ReadOnly Form Version')])
Then you can simply use the tag in the xml.
You have used _inherits = { 'product.product': 'product_id' } in your wizard.
When using _inherits you will do a kind of polymorphic model in the database way.
For example product.product inherits product.template or res.users inherits res.partner.
This mean we create a model that gets the know how of a Model but adds aditional data/columns in a new database table. So when you create a user, all partner data is stored in res_partner table (and a partner is created) and all user related info is stored in res_users table.
In your code when wizard (levelprime_product_general_status.product_from_barcode) record will create then all product.product/product.template fields are required,due to that reason you are getting this type of error.
You can check difference between _inherit & _inherits from following link.
https://www.odoo.com/forum/how-to/developers-13/the-different-openerp-model-inheritance-mechanisms-what-s-the-difference-between-them-and-when-should-they-be-used-46
You need to follow following code.
class ProductFromBarcode(models.TransientModel):
_name = 'levelprime_product_general_status.product_from_barcode'
product_id= fields.Many2one(comodel_name='product.product',string="Product")
product_barcode = fields.Char(help='Insert the barcode to search '
'the correspondent product',
"Barcode")
#api.onchange('product_barcode')
def on_barcode_changed(self):
if self.product_barcode:
self.product_id = self.get_product_from_barcode(self.product_barcode)
#api.model
def get_product_from_barcode(self,barcode):
r = self.env['product.product'].search([('barcode', '=', barcode)])
if r:
return r
else:
return False
In above code just create wizard & add two fields.
This may help you.
from what you are saying you are using inherits to show the information of the product selected by the barcode remove it and use related field:
add the fields that you are showing on the form view to you model
name = fields.Char(related='product_id.name', readonly=True)
Now you can use name on your view it's like compute field or proxy.
you can make them readonly if you want to display them.
In the timesheets in odoo, is there any solution to predefine an text in the textfield like here in the picture?
Example: If I want all time the text: "Hi I'm a test text" in this field every time I create a new timesheet.
Where I can define this as a standard of this field?
If you use the new API, you can put a 'default' attribute on your field definition like this :
your_field = fields.Char(default='Your default text')
If you use the old API, you have to define a '_defaults' dictionnary in your class like this :
_defaults = {
'your_field': lambda *a: 'Your default text',
}
Currently the additional field is calculted in the grid columnCfgs using an xtype of templatecolumn. I need to add this field to the grid data store so that it can be used to filter the grid data.
Model classes fields property is processed in a special fashion. Instead of replacing the parent class' ones as a normal property would, child fields are appended to them.
See this example:
Ext.define('Base', {
extend: 'Ext.data.Model'
,fields: ['foo','bar']
});
Ext.define('Extended', {
extend: 'Base'
,fields: ['baz']
});
var record = Ext.create('Extended');
record.fields.each(function(field) {
console.log(field.name);
});
That gives the following output:
foo
bar
id
baz