Hi I am new to OpenERP7/Odoo7 and not really getting how to do this.
I have a existing records in my custom product module and I want to retrieve that record by entering only to my prodcode fields and want to autofill some fields.
I have been reading a lot on the internet, Odoo forums, but cannot find the answer or I just don't understand it. I already have post with regards to my problem
So if is there someone could give me an answer on how to achieve this, or direct me to a easy to understand explanation.
That would be great.
Here is I have done already
PYTHON---
class test_product(osv.Model):
_name = "test.product"
def name_change(self, cr, uid, ids, test_prodcode_id, prodname, desc, price, context=None):
return {
'value': {
'prodname': 'Plastic Ware',
'desc': 'Affordable Plastic Ware',
'price': 100.00,
}
}
_columns = {
'test_prodcode_id': fields.many2one('test.prodcode', 'Code'),
'prodname': fields.char('Name', size=32),
'desc': fields.char('Description', size=32),
'price': fields.float('Price',),
}
class test_prodcode(osv.Model):
_name = "test.prodcode"
_columns = {
'name': fields.char('Product Code', size=32),
}
XML----
<record id="test_product_form_view" model="ir.ui.view">
<field name="name">test.product.form.vew</field>
<field name="model">test.product</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Product" version="7.0">
<sheet>
<field name="test_prodcode_id" on_change="name_change(test_prodcode_id,prodname,desc,price)"/>
<field name="prodname"/>
<field name="desc"/>
<field name="price"/>
</sheet>
</form>
</field>
</record>
Yeah, I've had this problem too.
I've got the solution. Auto fill can be achieved by doing
_defaults = {}
, or, as in your example, by doing
class test_product(osv.Model):
_columns = {
'test_prodcode_id': fields.many2one('test.prodcode', 'Code'),
'prodname': fields.char('Name', size=32),
'desc': fields.char('Description', size=32),
'price': fields.float('Price',),
}
_defaults: {
'test_prodcode_id' : 'defaults_prodcode',
}
You can also assign a function that return the value of the defaults.
I have solution but it is not as exactly as you want but you can do like
this also.
You can use related for auto fill your other fields. Suppose you set
product_id it will auto fill product_name, desc and price regarding to
your product_id.
You can also see Example here :
https://stackoverflow.com/a/42453539/5161074
Related
I'm trying to port Project issue module from Odoo 8 to Odoo 10 to add version field to projects.
project_version.py :
class project_version(models.Model):
_inherit = 'project.project'
_name = "project.version"
_order = "name desc"
_columns = {
'name': fields.char('Version Number', required=True),
'active': fields.boolean('Active', required=False),
}
_defaults = {
'active': 1,
}
When I try to install it, Odoo say
Model not found: project.project.version
Error context:
View `project_version list`
[view_id: 750, xml_id: n/a, model: project.project.version, parent_id: n/a]
None" while parsing file:///c:/Program%20Files%20(x86)/Odoo%2010.0/server/custom/project_task_version/views/views.xml:9, near
<record model="ir.ui.view" id="project_version.list">
<field name="name">project_version list</field>
<field name="model">project.version</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="active"/>
</tree>
</field>
</record>
This error means, that Odoo can't find you model. As I see, you set name "project.version" to you model, but Odoo searching for "project.project.version". So, just try to change name of model from "project.version" to "project.project.version".
Next:
This type of declaration of model now is not supported by Odoo 10:
_columns = {
'name': fields.char('Version Number', required=True),
'active': fields.boolean('Active', required=False), }
Try to look at this documentation - https://www.odoo.com/documentation/10.0/howtos/backend.html#model-fields
You must replace the declaration _columns and _default by the following: these being used by you is from old API syntax.
The syntax about your field attributes should be like this:
name = fields.Char('Version Number', required=True)
active = fields.Boolean('Active', required=True, default=True)
I usually create a new Database Structure Field by using the Debugging Mode, then Edit FormView and writing e.g. <field name="x_delivery_date"/>. Also I can show it later on the printed report like this:
<div name="x_delivery_date" t-if="doc.x_delivery_date">
<strong>Delivery Date:</strong>
<p t-field="doc.x_delivery_date"/>
</div>
But how do I display a field (commitment_date), which is available in the model (sale.order) in another models formview (account.invoice)? I guess that I have to use object relations or related field, but I don't know how. I hope somebody can help me. Many thanks in advance.
You can use related fields for that. You have to add two fields to account.invoice to do it.
class AccountInvoice(models.Model):
_inherit = "account.invoice"
order_id = fields.Many2one('sale.order', 'Related_order')
commitment_date = fields.Date(related='order_id.commitment_date')
Then you can use the commitment_date fields in account.invoice forms. The value of the field in sale.order will be reflected on the form right away. But be aware that changing the value of that field will change the value of that field on the sale.order as well.
EDIT
For reports just use the field like it is a regular field of account.invoice (so doc.commitment_date)
First you need to add a many2one field in account.invoice
class account_invoice(osv.osv):
_inherit = "account.invoice"
_columns = {
'source_id':fields.many2one('sale.order','Source')
}
Then inherit the _prepare_invoice function in sale_order. In this function you are going to pass the sale order id as source id to the account.invoice
class sale_order(osv.osv):
_inherit = "sale.order"
def _prepare_invoice(self, cr, uid, order, lines, context=None):
if context is None:
context = {}
journal_id = self.pool['account.invoice'].default_get(cr, uid, ['journal_id'], context=context)['journal_id']
if not journal_id:
raise osv.except_osv(_('Error!'),
_('Please define sales journal for this company: "%s" (id:%d).') % (order.company_id.name, order.company_id.id))
invoice_vals = {
'name': order.client_order_ref or '',
'origin': order.name,
'type': 'out_invoice',
#Sale order id as source_id
'source_id':order.id,
'reference': order.client_order_ref or order.name,
'account_id': order.partner_invoice_id.property_account_receivable.id,
'partner_id': order.partner_invoice_id.id,
'journal_id': journal_id,
'invoice_line': [(6, 0, lines)],
'currency_id': order.pricelist_id.currency_id.id,
'comment': order.note,
'payment_term': order.payment_term and order.payment_term.id or False,
'fiscal_position': order.fiscal_position.id or order.partner_invoice_id.property_account_position.id,
'date_invoice': context.get('date_invoice', False),
'company_id': order.company_id.id,
'user_id': order.user_id and order.user_id.id or False,
'section_id' : order.section_id.id
}
invoice_vals.update(self._inv_get(cr, uid, order, context=context))
return invoice_vals
Add this in View file
<record id="invoice_form" model="ir.ui.view">
<field name="name">account.invoice.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='date_invoice']" position="after">
<field name="source_id"/>
</xpath>
</field>
</record>
Now add this in your report file
<div name="x_delivery_date" t-if="doc.x_delivery_date">
<strong>Delivery Date:</strong>
<p t-field="doc.x_delivery_date"/>
<p t-field="doc.source_id.commitment_date"/>
</div>
i want to add onchange function in module manufacturing (mrp.production)
in view.xml
<record model="ir.ui.view" id="partner_instructur_form_view">
<field name="name">mrp.production.form.instructur</field>
<field name="model">mrp.production</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[#name='location_dest_id']" position="after">
<field name="product_qty" on_change="onchange_hitung_kuota(product_qty, prod_qtys)"/>
<field name="prod_qtys" on_change="onchange_hitung_kuota(product_qty, prod_qtys)"/>
<field name="progres_persen" widget="progressbar"/>
</xpath>
</field>
</record>
in python
class ala_mrp_prod(osv.osv):
_inherit = 'mrp.production'
def onchange_hitung_kuota(self, cr, uid, ids, prod_qtys, product_qty):
kurangi = product_qty - prod_qtys
res = {
'value':{ 'progres_persen': (kurangi * 100) / product_qty}
}
return res
_columns = {
'prod_qtys':fields.integer('Jumlah Total'),
'progres_persen': fields.float('Progres'),
}
_defaults = {
'prod_qtys': 1,
}
ala_mrp_prod()
why product quantity show 2?
so if i input product_quantity 3 , jumlah total 5 progres 40%?
please help
You passed parameters in the wrong order.
product_qty should be the first in onchange_hitung_kuota() method:
def onchange_hitung_kuota(self, cr, uid, ids, product_qty, prod_qtys)
In odoo new api you do not need to modify the xml file. what you have to do is
class mrp_order(models.Model)
_inherit = 'mrp.production'
#api.onchange('product_qty', 'prod_qtys')
def onchange_hitung_kuota(self):
kurangi = product_qty - prod_qtys
self.progres_persen = (kurangi * 100) / self.product_qty
hope this helps!
I think you inverted the two parameters inside the onchange_hitung_kuota function
Need to store default value on qty in M.sqr and square meter like quantity on hand showing default entered value.
when i click on update button of quantity on Hand from product inventory page
then it should show me a previous entered value.
class stock_change_product_qty(osv.osv):
_inherit = 'stock.change.product.qty'
_columns = {
'new_quantity' : fields.float('Qty in Boxes'),
'squ_meter': fields.related('product_id','squ_meter', type='float', relation='product.product', string='Square Meter'),
'qty_char': fields.float('Qty in M.sqr', compute='_compute_qty_char'),
}
#api.depends('new_quantity', 'squ_meter')
def _compute_qty_char(self):
for record in self:
record.qty_char = record.new_quantity * record.squ_meter
view.xml
<field name="name">update_product_quantity inherit</field>
<field name="model">stock.change.product.qty</field>
<field name="inherit_id" ref="stock.view_change_product_quantity"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='new_quantity']" position="attributes">
<attribute name="string">Qty in Boxes</attribute>
</xpath>
<xpath expr="//field[#name='new_quantity']" position="replace">
<field name="new_quantity"/>
<field name="squ_meter"/>
<field name="qty_char"/>
</xpath>
</field>
</record>
A solution is to use a function as default value for your field:
odoo V8
from openerp import api, fields, models
class stock_change_product_qty(models.Model):
_inherit = 'stock.change.product.qty'
new_quantity = fields.Float(string='Qty in Boxes', default=1.0),
squ_meter = fields.Float(related='product_id.squ_meter', string='Square Meter', default=1.0),
qty_char = fields.Float('Qty in M.sqr', compute='_compute_qty_char'),
}
#api.one
#api.depends('new_quantity', 'squ_meter')
def _compute_qty_char(self):
for record in self:
record.qty_char = record.new_quantity * record.squ_meter
odoo V7
def _your_function(self, cr, uid, context=None):
your code here
...
...
...
return field_value
_defaults = {
'your_field' : _your_function,
}
#api.onchange
This decorator will trigger the call to the decorated function if any of the fields specified in the decorator is changed in the form:
#api.onchange('fieldx')
def do_stuff(self):
if self.fieldx == x:
self.fieldy = 'toto'
In previous sample self corresponds to the record currently edited on the form. When in on_change context all work is done in the cache. So you can alter RecordSet inside your function without being worried about altering database. That’s the main difference with #api.depends
At function return, differences between the cache and the RecordSet will be returned to the form.
I'm working on OpenERP7, trying to access a related field located in a parent model of said related model. If someone at this point understand something, you're way smarter than I am, so i will just put the example of what i'm trying to achieve :
My model :
class trench(osv.osv):
_name = 'trench'
_inherit = 'common'
_columns = {
'trench_lines': fields.one2many('trench.line', 'trench_id', 'Trench Lines'),
'trench_depth': fields.one2many('trench.depth', 'trench_id', 'Trench Depth'),
}
trench()
class trench_common(osv.osv):
_name = 'trench.common'
def compute_vals(self, cr, uid, ids, field_name, arg, context):
...
def on_change_values(self, cr, uid, ids, context=None):
...
_columns = {
'trench_id': fields.many2one('trench', 'Trench', ondelete='cascade', required=True),
'length' : fields.function(compute_vals, type='float', string="Length", method=True, store=True),
}
trench_common()
class trench_line(trench_common):
_name = 'trench.line'
_inherit = 'trench.common'
trench_line()
class trench_dig_common(trench_common):
_name = 'trench.dig.common'
_inherit = 'trench.common'
_columns = {
'length' : fields.float('Length', digits=(6,3)),
'height' : fields.float('Height', digits=(6,3)),
'total_m3' : fields.float('Total m3', digits=(6,3)),
'observation' : fields.text('Observation'),
}
trench_dig_common()
class trench_depth(trench_dig_common):
_name = 'trench.depth'
_inherit = 'trench.common'
trench_depth()
My view :
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="trench_form" model="ir.ui.view">
<field name="name">trench.form</field>
<field name="model">trench</field>
<field name="inherit_id" ref="common_form" />
<field name="arch" type="xml">
<group string="Worksite" position="after">
<separator string="Progress" />
<field name="trench_lines">
<tree editable="bottom">
<field name="length"/>
</tree>
</field>
<separator string="Cumulate Length" />
<field name="total_length"/>
<separator string="Trench Particularity" />
<notebook>
<page string="Surdepth">
<field name="trench_depth">
<tree editable="bottom">
<field name="height"/>
</tree>
</field>
</page>
</notebook>
</group>
</field>
</record>
</data>
</openerp>
My error :
except_orm: ('View error', u"Can't find field 'height' in the following view parts composing the view of object model 'qhse.trench':\n * trench.form\n\nEither you wrongly customized this view, or some modules bringing those views are not compatible with your current data model")
2015-05-21 07:56:28,631 13918 ERROR ahak_production openerp.tools.convert: Parse error in trench_view.xml:4:
So, i'm figuring i can't access a field of a model with so many layers, but is there a way to achieve this, and if so, how? I'm trying to make something DRY, but always end up duplicating code with OpenERP.
Thanks for reading.
You need to define your last class as below.
class trench_depth(trench_dig_common):
_name = 'trench.depth'
_inherit = 'trench.dig.common'
trench_depth()
Then after you can access all fields which are available inside "trehch.dig.common" model.