Insert list register with onchange (Odoo) - odoo

class base(models.Model):
_name = 'base'
name = fields.Char("Name")
c_id = fields.Many2one('base.ch')
class base_ch(models.Model):
_name = 'base.ch'
name = fields.Char("Name")
q_ids = fields.One2many("base.q","c_id")
class base_q(models.Model):
_name = "base.q"
name = fields.Char("Name")
c_id = fields.Many2one('base.ch',"Basec")
class base_h(models.Model):
_name = "base.h"
name = fields.Char("Name")
select = fields.Selection([('a', 'A'), ('b', 'B')], "select")
desc = fields.Char("Desc")
I have these classes and I want to add in the base class a field of the base_h class in tree view format.
I need to do an onchange function in the base class that when choosing c_id modify the name field of the added field of the base_h class with the records of c_id.q_ids
I tried:
#api.onchange('ch_id')
def onchange_ch(self):
if self.ch_id.q_ids:
self.one2manyfield.name = [(6, 0, self.ch_id.q_ids)]
#also with-> self.one2manyfield = [(6, 0, self.ch_id.q_ids)]
But it does not work

(6, 0, [IDs]) will take list of ids.
Try with following code.
#api.onchange('ch_id')
def onchange_ch(self):
if self.ch_id and self.ch_id.q_ids:
one2manyfield = [(6, 0, self.cht_id.q_ids.ids)]

This is the function that works
#api.onchange('ch_id')
def onch_ch(self):
valors = []
for r in self.ch_id.q_ids:
register = {'name': r.name}
valors.append(register)
self.one2manyfield = valors

Related

Get value from a Many2one related model in model create function

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")

Convert PostgreSQL COUNT … FILTER query to SQL Alchemy

I'm new to SQLAlchemy, and I would like to convert this PostgreSQL query:
SELECT product.*
, COUNT(feedback.like) FILTER (WHERE feedback.like = '1') AS like
, COUNT(feedback.like) FILTER (WHERE feedback.like = '-1') AS unlike
FROM feedback, product
WHERE product.id = feedback.product_id
GROUP BY product.id
ORDER BY product.id;
I have already tried this:
products = db.session.query(
Product,
func.count(Feedback.like > 0).label('like'),
func.count(Feedback.like < 0).label('unlike')
).filter(Product.guide_name_id==id)
.filter(Product.id == Feedback.product_id)
.group_by(Product.id)
.order_by(Product.id)
.all()
Thank you in advance for your help
Thanks to #IljaEverilä's comment, here is a more direct answer:
class Product(Base):
__tablename__ = "product"
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
def __repr__(self):
return f"<Product(name='{self.name}')>"
class Feedback(Base):
__tablename__ = "feedback"
id = Column(Integer, primary_key=True)
product_id = Column(Integer, ForeignKey(Product.id))
like = Column(Integer)
product = relationship(Product)
Base.metadata.create_all(engine)
with Session(engine) as session:
# set up test data
widget = Product(name="widget")
session.add_all(
[
widget,
Feedback(product=widget, like=1),
Feedback(product=widget, like=1),
Feedback(product=widget, like=-1),
Product(name="gadget"),
]
)
# run the query
query = (
select(
Product,
func.count(Feedback.like)
.filter(Feedback.like == 1)
.label("likes"),
func.count(Feedback.like)
.filter(Feedback.like == -1)
.label("dislikes"),
)
.select_from(Product)
.outerjoin(Feedback)
.group_by(Product)
)
results = session.execute(query).fetchall()
print(results)
# [(<Product(name='gadget')>, 0, 0), (<Product(name='widget')>, 2, 1)]
(Original answer)
I'm not sure if SQLAlchemy's postgresql dialect specifically handles COUNT … FILTER, but you can accomplish the same thing using SUM and CASE:
from sqlalchemy import __version__ as sa_version, case, Column, ForeignKey, func, Integer, String
from sqlalchemy.orm import Session
print(sa_version) # 1.4.0b2
class Product(Base):
__tablename__ = "product"
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
class Feedback(Base):
__tablename__ = "feedback"
id = Column(Integer, primary_key=True)
product_id = Column(Integer, ForeignKey(Product.id))
like = Column(Integer)
product = relationship(Product)
Base.metadata.create_all(engine)
with Session(engine, future=True) as session:
widget = Product(name="widget")
session.add_all(
[
widget,
Feedback(product=widget, like=1),
Feedback(product=widget, like=1),
Feedback(product=widget, like=-1),
Product(name="gadget"),
]
)
results = (
session.query(
Product.name,
func.sum(case((Feedback.like > 0, 1), else_=0)).label(
"likes"
),
func.sum(case((Feedback.like < 0, 1), else_=0)).label(
"dislikes"
),
)
.select_from(Product)
.outerjoin(Feedback)
.group_by(Product)
.all()
)
print(results) # [('widget', 2, 1), ('gadget', 0, 0)]

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)

Adding fields to item in scrapy from list

I have a long list of fields to add to a scrapy item but can't figure out how to do it. Basically I am trying to get the output of
class myItem(scrapy.Item):
a = scrapy.field()
b = scrapy.field()
But I want to create it from a list like
['a','b']
I tried
fields = ['a','b']
def generateFields(fields):
item = myItem()
for field in fields:
field = scrapy.Field()
return item
But that didn't work. Thanks!
You can manage it by using python magic method __dict__ pretty much as:
fields = ['a', 'b', 'c']
class MyItem(scrapy.Item):
def __init__(self):
for f in fields:
self.__dict__[f] = scrapy.field()
my_item = MyItem()
And so on...
Seems that my previous comment is valid for usual python classes, not for scrapy.Item class. Following code is working:
from scrapy import Item, Field
fields = ['a', 'b', 'c']
def generate_item(fields):
item = Item()
for f in fields:
item.fields[f] = Field()
return item
item_instance = generate_item(fields)
item_instance['a'] = 'some_value'
item_instance['b'] = 12
print(item_instance)

How to create sample sale order and sale order line in odoo?

I am trying to create a sample order in sales order.In the sample order form, products are sold to customers as complimentary copy(books in my case) without charging any money so I have created a separate sub-menu in sales menu.Here I take only product and quantity as input. Sample order number will be the next number from the sales order(like SO360).So I am fetching sales order number as parent_id in my inherited module.I am not able to create sale order line(data in order lines tab)
class SaleOrder(models.Model):
_inherit = 'sale.order'
# Fields
is_sample = fields.Boolean(string="Sample Order", default=False)
parent_id = fields.Many2one('sale.order', string="Parent Sales Order")
sample_ids = fields.One2many('sale.order', 'parent_id',
string="Sample Orders")
# Methods
#api.model
#api.returns('sale.order')
def create(self, vals):
if vals.get('is_sample', False) and vals.get('name', '/') == '/':
IrSeq = self.env['ir.sequence']
ref = IrSeq.next_by_code('sale.order.sample.ref') or '/'
parent = self.search([('id', '=', vals.get('parent_id'))])
vals['name'] = parent.name + ref
vals['user_id'] = parent.user_id.id
return super(SaleOrder, self).create(vals)
class SampleOrderWizard(models.TransientModel):
_name = 'sale.order.sample.wizard'
_description = 'Sample Sale Order Wizard'
# Field default values
#
def _get_parent(self):
res = False
if self.env.context \
and 'active_id' in list(self.env.context.iterkeys()):
res = self.env.context['active_id']
return res
def _get_new_sale_line(self, orig_sale, orig_sale_line, wizard_line):
"""Internal function to get the fields of the sale order line. Modules
enhancing this one should add their own fields to the return value."""
res = {
'order_id': orig_sale.id,
'product_id': orig_sale_line.product_id.id,
'name': orig_sale_line.name,
'sequence': orig_sale_line.sequence,
'price_unit': orig_sale_line.price_unit,
'product_uom': orig_sale_line.product_uom.id,
'product_uom_qty': wizard_line and wizard_line.qty or 0,
'product_uos_qty': wizard_line and wizard_line.qty or 0,
}
# Simple check for installation of sale_line_code module
if hasattr(orig_sale_line, 'order_line_ref'):
res.update({'order_line_ref': orig_sale_line.order_line_ref})
return res
def _get_order_lines(self, sale):
res = []
for line in sale.order_line:
wizard_line = False
for wzline in self.wizard_lines:
if wzline.product == line.product_id:
wizard_line = wzline
break
if wizard_line:
res.append(
(0, 0, self._get_new_sale_line(sale, line, wizard_line))
)
return res
def _get_wizard_lines(self):
res = []
if self._get_parent():
SaleOrder = self.env['sale.order']
parent = SaleOrder.search([('id', '=', self._get_parent())])
for line in parent.order_line:
res.append((0, 0,
{
'product': line.product_id,
'qty': 1,
}))
return res
# Fields
#
order = fields.Many2one('sale.order', default=_get_parent, readonly=True)
wizard_lines = fields.One2many('sale.order.sample.wizard.line', 'wizard',
default=_get_wizard_lines)
order_date = fields.Datetime(default=fields.Datetime.now())
# Methods
#
#api.one
def create_order(self):
sale_vals = {
'user_id': self.order.user_id.id,
'partner_id': self.order.partner_id.id,
'parent_id': self.order.id,
'date_order': self.order_date,
'client_order_ref': self.order.client_order_ref,
'company_id': self.order.company_id.id,
'is_sample': True,
'order_line': self._get_order_lines(self.order)
}
self.env['sale.order'].create(sale_vals)
return {'type': 'ir.actions.act_window_close'}
class SampleOrderWizardLine(models.TransientModel):
_name = 'sale.order.sample.wizard.line'
_description = 'Sample Order Wizard Line'
wizard = fields.Many2one('sale.order.sample.wizard')
product = fields.Many2one('product.product',
domain=[('sale_ok', '=', True)])
qty = fields.Float(string="Quantity", default=1.0,
digits_compute=dp.get_precision('Product UoS'))