Get value from a Many2one related model in model create function - odoo

I have two models, TextMessage and Device, that are related many TextMessages to one Device.
from odoo import models, fields, api
class Device(models.Model):
_name = 'device'
_description = 'A model for storing all devices'
name = fields.Char()
iden = fields.Char()
model_name = fields.Char()
manufacturer = fields.Char()
push_token = fields.Char()
app_version = fields.Integer()
icon = fields.Char()
has_sms = fields.Char()
text_message_ids = fields.One2many("text_message", "device_id", string="Text Messages")
from odoo import models, fields, api
class TextMessage(models.Model):
_name = 'text_message'
_description = 'Text Messages'
name = fields.Char()
message_text = fields.Text()
pb_response = fields.Text()
target_number = fields.Char()
device_id = fields.Many2one('device', 'Device', required=True)
#api.model
#api.depends("device_id")
def create(self, values):
print("values['device_id']",values["device_id"])
print("self.device_id",self.device_id.iden)
for rec in self.device_id:
print("Device ID",rec.iden)
values['pb_response'] = rec.device_id.iden
return super().create(values)
In the create method of TextMessage, I want to retrieve the value of the iden attribute of the Device model.
The print statements in TextMessage.create print:
values['device_id'] 1
self.device_id False
The print statement in the loop prints nothing.

You can't access self before creating the record so it will be false.
You can write the create method in two ways:
Create the record first and then get the iden value:
#api.model
def create(self, values):
res = super().create(values)
res.pb_response = res.device_id.iden
return res
Or you can get the device_id record from values as below:
#api.model
def create(self, values):
if 'device_id' in values and values.get('device_id',False):
device = self.env['device'].browse(values.get('device_id'))
if device:
values['pb_response'] = device.iden
return super().create(values)
If the pb_response field is the same of the iden field then you can create it as related field to device_id.iden and you will get the iden value automatically once the device-id assigned as below:
pb_response = fields.Char(related="device_id.iden")

Related

Update value of field of another model from a create method of another model

I want to update value of field state from another model in odoo 14.Using the following code it is not working
_inherit = 'crm.lead'
lead_details_id = fields.Many2one('leads.details', string="Lead Id")
def create(self, vals):
if vals.get('lead_details_id'):
detail = self.env['leads.details'].search([('id', '=', vals.get('lead_details_id'))])
if detail:
detail.write({'state':'customer'})
return super(LeadDetailsInh, self).create(vals)

DRF- how to do many readonly and writeonly fields in serializers

I used two foreignkey in my model. I want to show those fields name when we give get request I have tried but its worked only one fields not rest one.
models.py
class Organization(models.Model):
code = models.CharField(max_length=25, null=False, unique=True)
name = models.CharField(max_length=100, null=False)
location = models.ForeignKey(Location, on_delete=models.RESTRICT)
mol_number = models.CharField(max_length=100)
corporate_id = models.CharField(max_length=100)
corporate_name = models.CharField(max_length=100)
routing_code = models.CharField(max_length=100)
iban = models.CharField(max_length=100)
description = models.TextField()
total_of_visas = models.IntegerField(null=False, default=0)
base_currency = models.ForeignKey(Currency, on_delete=models.RESTRICT)
def __str__(self):
return self.name
serializers.py
class OrganizationSerializer(serializers.ModelSerializer):
location = serializers.CharField(read_only=True, source="location.name")
base_currency = serializers.CharField(read_only=True, source="base_currency.currency")
location_id = serializers.IntegerField(write_only=True, source="country.id")
base_currency_id = serializers.IntegerField(write_only=True, source="base_currency.id")
class Meta:
model = Organization
fields = ["id", "name", "location", "mol_number", "corporate_id", "corporate_name",
"routing_code", "iban", "description", "total_of_visas", "base_currency",
"location_id", "base_currency_id"]
def create(self, validated_data):
...
def update(self, instance, validated_data):
...
How can I access those two fields???.. Anyhelp Appreciable..
you can override the to_representation method
def to_representation(self, instance):
....
so something like this:
class OrganizationSerializer(serializers.ModelSerializer):
...
class Meta:
...
def to_representation(self, instance):
rep = super(OrganizationSerializer, self).to_representation(instance)
rep['location'] = instance.location.name //the .name is the field in the //location model that you want to return it can be anything in the model
rep['base_currency'] = instance.base_currency.currency
rep['location_id'] = instance.location_id.country.id
rep['base_currency_id'] = instance.base_currency_id.base_currency_id
return rep
def create(self, validated_data):
...
def update(self, instance, validated_data):

odoo-How to save related fields for one2many relation

my problem is that when i saved the fields in model's from B , i did't saw the result in model's view A execept the name of empoyee and department becuse declared in the same model, some freinds suggeste me to use onchnage function but how !!
class FeuilleTemps(models.Model): # A
_name = 'tbrh.feuilletemps'
_rec_name = 'name_emp'
name_emp = fields.Many2one('hr.employee', string="Employé")
name_dep = fields.Many2one('hr.department', string="Département")
abscence_ids = fields.One2many('tbrh.abscences', 'feuille_id', string="ma liste ")
relation_id = fields.Many2one('tbrh.abscences')
date2 = fields.Date(related='relation_id.date', store=True, use_parent_address=False)
statut = fields.Selection(related='relation_id.statut', store=True)
class Abscences(models.Model): # B
_name = 'tbrh.abscences'
statut = fields.Selection([('abscent', 'Abscent'), ('present', 'Présent')], string="Statut")
date = fields.Date()
feuille_id = fields.Many2one('tbrh.feuilletemps',
ondelete='cascade', string="feuille ", required=True)

what should I add to display the value of fields correctly?

what should I add to display user_id and cat correctly
#api.model
def create(self, vals):
record=super(test, self).create(vals)
if vals['total'] > 0:
vals['date'] = fields.Datetime.now()
self.env['journal'].create({
'user_id': record.patient_id,
'cat': record.cat,})
....
.....
on the tree view (journal):
user_id is displayed as test.user(6,)
cat is displayed as cat1
EDITS:
class test(models.Model):
_name = 'test'
cat = fields.Selection(
required=True,
related='test_type_cat.name',
store=True,
)
user_id = fields.Many2one('res.users', string='user', readonly=True,)
.....
#api.model
def create(self, vals):
record=super(test, self).create(vals)
if vals['total'] > 0:
vals['date'] = fields.Datetime.now()
self.env['journal'].create({
'patient_id': record.patient_id.name,
'cat': record.cat,
'user_id': record.user_id.name,
})
record.total = 0
return record
why does it work with .name and not .id ?
for m2o field should I pass the integer value ? if it is the case why does it work here with .name ? and what about m2m and o2m?
this worked for you because you are creating a record in model: journal not in test model.
and if you go to journal model you will find that patient_id is Char field not a many2one field.
so if you pass: record.patient_id you are passing an object and it's converted to char this is why you get test(1,). because pateint_id is a many2one field in test model witch mean is an object.
Hope this clear thing little bit for you.

TypeError: generate_purchase_order() takes exactly 1 argument (5 given)

I am trying to convert openerp 7 code to odoo8. In V7 browse() method had several parameters like self,cr,uid,ids,context but in V8 I think none of these is needed.In my custom module I am trying to create a purchase order based on the information obtained from mrp.I have done a custom calculation for how many Kgs of paper needed for 10000 quantities of books to be manufactured.After calculation this info should go to purchase invoice.Products will be obtained from bill of materials,quantity from no of kgs of paper needed and unit price from product cost attribute.I am unable to solve this error "method takes exactly 1 argument (5 given)"
mrp.py,
from openerp import models
class mrp_production(models.Model):
_inherit = 'mrp.production'
def generate_purchase_order(self,supplier_id,warehouse_id):
purchase_obj = self.env['purchase.order']
purchase_line_obj = self.env['purchase.order.line']
warehouse_obj = self.env['stock.warehouse']
warehouse = warehouse_obj.browse(warehouse_id)
if not warehouse:
return False
if isinstance(warehouse, list):
warehouse = warehouse[0]
for order in self:
vals = {}
vals = purchase_obj.onchange_partner_id()
vals['origin'] = order.name
vals['partner_id'] = supplier_id
vals['warehouse_id'] = warehouse_id
vals['location_id'] = warehouse.lot_stock_id.id
vals['date_order'] = order.date_planned
purchase_id = purchase_obj.create(vals)
for line in self.bom_id.bom_line_ids:
if not line.product_id:
continue
line_vals = purchase_line_obj.onchange_product_id(line.product_id.id,
line.product_uom_qty, line.product_uom.id, supplier_id,
date_planned=line.date_planned)['value']
line_vals['name'] = line.name
line_vals['product_id'] = line.product_id.id
if not line_vals.get('price_unit', False):
line_vals['price_unit'] = line.product_id.list_price
line_vals['product_uom'] = line.product_uom.id
line_vals['product_uom_qty'] = 181.13
line_vals['order_id'] = purchase_id
purchase_line_obj.create(line_vals)
return True
generate_purchase_order.py,
from openerp import models,fields,api
class generate_purchase_order(models.Model):
_name = 'mrp_to_purchase_order.generate_purchase_order'
_description = 'Generate Purchase Order'
partner_id = fields.Many2one('res.partner', 'Supplier', required=True, domain="[('supplier','=',True)]")
warehouse_id = fields.Many2one('stock.warehouse', 'Warehouse', required=True)
#api.multi
def onchange_partner_id(self,partner_id):
return {}
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
mrp_obj.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}
If you are calling the generate_purchase_order method from some other method in your model, then use the decorator #api.multi for that method.
Also in your generate_purchase_order method, replace
for order in self.browse():
by
for order in self:
EDIT
#api.multi
def generate_purchase_order(self):
for wizard in self:
#mrp_order_ids = [context['active_id']]
mrp_obj = self.env['mrp.production']
# Get the mrp record
mrp_rec = code to get mrp record
mrp_rec.generate_purchase_order(wizard.partner_id.id, wizard.warehouse_id.id)
return { 'type': 'ir.actions.act_window_close'}