How to carry data from one form to another in odoo 11? - action

I have three models.
class student(models.Model):
_name = 'student.info'
_description = 'Students\' Information'
name = fields.Char('Name', required=True)
age = fields.Integer('Age', compute='_compute_age', store=True)
date_of_birth = fields.Date('Date of Birth', required=True)
teacher_id = fields.Many2one('teacher.info', 'Teacher')
class teacher(models.Model):
_name = 'teacher.info'
_description = 'Teachers\' Information'
name = fields.Char('Name', required=True)
position = fields.Char('Position')
section_id = fields.Many2one('stu.section', 'Section')
student_ids = fields.Many2many('student.info', 'student_teacher_rel', 'teacher_id', 'student_id', 'Students')
class section(models.Model):
_name = 'stu.section'
_description = 'Students\' Sections'
name = fields.Char('Name', required=True)
student_ids = fields.Many2many('student.info', 'student_section_rel', 'section_id', 'student_id')
two actions,
<record id="action_student_to_class" model="ir.actions.act_window">
<field name="name">Class</field>
<field name="res_model">stu.section</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="context">{'default_student_ids' : [(4, active_id)]}</field>
</record>
<record id="action_class_to_teacher" model="ir.actions.act_window">
<field name="name">Class</field>
<field name="res_model">teacher.info</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="context">{
'default_student_ids' : active_id.student_ids,
'default_section_id' : active_id,
}</field>
</record>
and two buttons. One in student form view and the other in section form view.
<button name="%(action_student_to_class)d"
type="action"
string="To Class"
class="oe_highlight"/>
<button name="%(action_student_to_class)d"
type="action"
string="To Class"
class="oe_highlight"/>
When 'To Class' button is clicked from student form, the action updates the current student in the section student_ids. But when 'To Teacher' button is clicked from section form, I want to update both the current section and student_ids in section in the teacher form. I have done this by returning action from python, but I want to do this from xml? How can I achieve this? Thanks.

I have found the solution.
It's okay if we don't add context in action for the button. We can add context in button like
<button name="%(action_student_to_class)d"
type="action"
string="To Class"
class="oe_highlight"
context="{'default_student_ids' : student_ids, 'default_section_id' : active_id}"/>

Related

How to get the value of product description from purchase.order

I want to add a "designation" field in the "stock.quant.tree" view that displays the description of each product in stock. I have already added the field in the tree but I am stuck how I get the value of the description product of the model "purchase.order" to "stock.quant" Any idea for help please?
stock_quant_tree_designation.xml
<data>
<record id="stock_quant_tree_designation" model="ir.ui.view">
<field name="name">stock.quant.tree.designation</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.view_stock_quant_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='qty']" position="after">
<field name="designation2"/>
</xpath>
</field>
</record>
</data>
stock.py
from openerp.osv import fields, osv
from openerp import tools , api
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
class StockQuantTreeDesignation(osv.osv):
_inherit = 'stock.quant'
_columns = {
'designation2': fields.char(string="Désignation", required=True, select=True),
}
You already have product_id field in stock.quant, you can make designation2 related to product_id.
designation2 = fields.Char(related='product_id.name')
To add a relation between purchase.order and stock.quant you can use a compute field that search for move_id from quant_ids field to access the picking_id which store the purchase.order name (unique) inorigin field.
# coding: utf8
from openerp import models, fields, api
class StockQuant(models.Model):
_inherit = "stock.quant"
purchase_id = fields.Many2one("purchase.order", string="Purchase Order", compute="_get_purchase_order")
#api.multi
def _get_purchase_order(self):
for record in self:
# Search for one move_id to get stock_picking reference
self.env.cr.execute("SELECT move_id FROM stock_quant_move_rel WHERE quant_id=%s LIMIT 1", (record.id,))
(move_id, ) = self.env.cr.fetchone()
move = self.env["stock.move"].browse(move_id)
# Use stock_picking to get purchase_order reference using `origin` which is unique
po = self.env["purchase.order"].search([("name", '=', move.picking_id.origin)])
record.purchase_id = po.id

How to set computed one2many field calculation odoo

I just want to know how to set the values in one2many by using computed field calculation. Here my code is
python file
from openerp import models ,fields,api
from openerp import SUPERUSER_ID
from dateutil.relativedelta import relativedelta
import openerp.addons.decimal_precision as dp
import math
import logging
import datetime
class extend_product_product(models.Model):
_inherit = 'product.product'
monthly_lines = fields.One2many('minmax.monthly.data','month_id', 'Monthy Sales',compute="_get_monthly_sales")
#api.one
def _get_monthly_sales(self):
vals = {}
vals.update({'monthly_lines':[(0,0,{'month_name_id':1,'so_qty':35})]})
self.write(vals) # Also I have tried self.monthly_lines = [(0,0,{'month_name_id':1,'so_qty':35})]
class minmax_monthly_data(models.Model):
_name = 'minmax.monthly.data'
month_id = fields.Many2one('product.product', 'Product Reference', select=True, required=True)
month_name_id = fields.Many2one('minmax.months','Minmax Month',required=True)
so_qty = fields.Float('Sales Qty', digits_compute=dp.get_precision('Product Unit of Measure'), required=True)
XML File
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record model="ir.ui.view" id="product_monthly_minmax_tree">
<field name="name">product.product.tree</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_product_tree_view"/>
<field name="type">form</field>
<field name="arch" type="xml">
<field name="ean13" position="after">
<field name="monthly_lines" widget="one2many_tags" />
</field>
</field>
</record>
</data>
</openerp>
Here I have tried to insert the data manually. The function is called properly whenever we load the product.product tree view. But there is no results. Thanks in advance.
In your code you have not specified to which product that record
belongs, this is why this record is not getting mapped to any one2many
records because there is no many2one reference defined. Means you need
to set month_id in minmax.monthly.data model and then you can
see the data in one2many field in product.product.
Your code should be like that...
class extend_product_product(models.Model):
_inherit = 'product.product'
monthly_lines = fields.One2many('minmax.monthly.data','month_id', 'Monthy Sales',compute="_get_monthly_sales")
#api.multi
def _get_monthly_sales(self):
for rec in self:
rec.monthly_lines = [(0,0,{'month_name_id':1,'so_qty':35, 'month_id' : rec.id})]
In new api functional field directly be assigned with the object, we don't need to return dictionary as we did in old version.
These functional fields can be stored into the database, for that you need to set the store=True attribute only in field definition.
And if you store the field in database then in such situation we need to update it's value as well, for that you need to decorate the function with #api.depends('field name1','field name2')
#api.multi
#api.depends('fieldname')
def _get_monthly_sales(self):
for rec in self:
rec.monthly_lines = [(0,0,{'month_name_id':1,'so_qty':35,'month_id' : rec.id})]
One2many fields can be auto managed by odoo framework, when you set
many2one reference in record then the inverse model have the one2many
relation and that will be managed auto (One2many field needed to be defined). However you can manage
One2many as well, this is bi-directional, so you need to manage either
many2one or one2many.

How to create Odoo scheduler

I want to make a modification on hr_holidays module to create a schedule every month to allocate 3 extra days for each employee.
By following this tutorial I managed to create a single record for each employee which updates itself to add extra 3 days for each employee. Here's my code
class hr_holidays(models.Model):
_inherit = 'hr.holidays',
#This function is called when the scheduler goes off
def process_demo_scheduler_queue(self, cr, uid, context=None):
scheduler_line_obj = self.pool.get('hr.holidays')
#Contains all ids for the model hr.holidays
scheduler_line_ids = self.pool.get('hr.holidays').search(cr, uid, [])
#Loops over every record in the model hr.holidays
for scheduler_line_id in scheduler_line_ids :
#Contains all details from the record in the variable scheduler_line
scheduler_line =scheduler_line_obj.browse(cr, uid,scheduler_line_id ,context=context)
number_of_days_temp = scheduler_line.number_of_days_temp
state = scheduler_line.state
#Prints out the name of every record.
#Update the record
scheduler_line_obj.write(cr, uid, scheduler_line_id, {'number_of_days_temp': (number_of_days_temp +3), 'state': 'confirm'}, context=context)
cron view:
<record id="ir_cron_scheduler_hr_holidays" model="ir.cron">
<field name="name">Leaves scheduler</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">months</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="'hr.holidays'" name="model"/>
<field eval="'process_demo_scheduler_queue'" name="function"/>
</record>
But what I need is that I want to schedule every month with a new created record ea. each employee will have 12 allocation records in a single year, not only one record which update itself every month.
How to do that?

How to make a field computed only if some condition is fulfilled in Odoo 8?

Is there any way in Odoo 8 to create a field which is computed only if some condition is fulfilled, otherwise the user will be able to set its value?
Example
I have a model named box, which has a float field named value.
Imagine a box can have several boxes inside, each one which its own value.
So we have a one2many field named child_ids pointing to box and a many2one named parent_id pointig to box too.
Now I want the following behaviour: an user can set the value field of a box which has not any box inside (it means, childs_ids is False), but, if the box has at least one box inside (it means, childs_ids is NOT False), the value field must be computed and it will be the sum of its childs value.
Does anyone have an idea of how to achieve this behaviour?
I put my code, which is not working (the value of value is always being reset to 0):
class box(models.Model):
_name='box'
#api.one
#api.depends('child_ids', 'child_ids.value')
def _compute_value(self):
if self.child_ids:
self.value = sum(
[child.value for child in self.child_ids])
def _set_value(self):
pass
parent_id = fields.Many2one(comodel_name='box',
string='Parent Box')
child_ids = fields.One2many(comodel_name='box',
inverse_name='parent_id',
string='Boxes inside')
value = fields.Float(
string='Value',
compute='_compute_value',
inverse='_set_value',
store=False,
required=True,
readonly=True,
states={'draft':[('readonly',False)]},
)
in the model
computed_field = fields.Char(compute='comp', inverse='inv', store=True)
boolean_field = fields.Boolean()
#api.one
def comp(self):
...
#api.one
def inv(self):
...
in the view
<field name="boolean_field" />
<field name="computed_field" attrs="{'readonly': [('boolean_field','=',True)]}" />
edit:
now that your example is more clear, i'd say you should change the following:
set value's store parameter to True instead of False and just remove the inverse which, in your case, you don't need.
then you need another 2 fields
value_manual = fields.Float()
manual = fields.Boolean(compute='_is_manual', default=True)
#api.one
#api.depends('child_ids')
def _is_manual(self):
self.manual = len(self.child_ids) == 0
plus
#api.one
#api.depends('child_ids', 'child_ids.value')
def _compute_value(self):
if self.child_ids:
self.value = sum(
[child.value for child in self.child_ids])
else:
self.value = self.value_manual
in the view:
<field name="manual" invisible="1" />
<field name="value" attrs="{'invisible': [('manual','=',True)]}" />
<field name="value_manual" attrs="{'invisible': [('manual','=',False)]}" />
There could be another solution that avoid this double field, maybe using the inverse, but I am not sure.

retrieve all values of fleet_service_type.name into sale.order

The FLEET module has a list of service types
class fleet_service_type(osv.Model):
_name = 'fleet.service.type'
_description = 'Type of services available on a vehicle'
_columns = {
'name': fields.char('Name', required=True, translate=True),
'cost':fields.float('Cost Of Service',required=True),
'category': fields.selection([('contract', 'Contract'), ('service', 'Service'), ('both', 'Both')], 'Category', required=True, help='Choose wheter the service refer to contracts, vehicle services or both'),
}
fleet_service_type()
i want to have a field in my sale.order module that will be the dropdownlist of all 'name' values in the fleet module.
Can anyone suggest how to i do that
For get all value of relationship object (Fleet Service Type), you need to add many2one relationship on Sale Order with target object.
Put this code in your .py file
class sale_order(osv.Model):
_inherit = 'sale.order'
_columns = {
'fleet_id': fields.many2one('fleet.service.type', 'Fleet Service Type'),
}
And do some customization on view xml file.
<record id="view_sale_order_extended_form1" model="ir.ui.view">
<field name="name">sale.order.form1.extend</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<field name="partner_id" position="before">
<field name="fleet_id"/>
</field>
</field>
</record>
After this you can see field Fleet Service Type after Customer field in Sale Order Form. And you can select your desire value of Fleet Service Type.
Hope this will help you.