odoo8 Field year selection with today year as default - odoo

I want to make a year selection where the default year is now.
This is my .py
def get_years():
year_list = []
for i in range(2022, 2036):
year_list.append((i, str(i)))
return year_list
def get_year(self):
return str(datetime.now().year)
year = fields.Selection(get_years(), string='Year', default=get_year)
and this is my .xml
<field name="year">
But I get this error
ValueError: Wrong value for wizard.report.purchase.tracking.year: '2023'
What should I do? Thank you for your help

You have to set the string type key and pair value of touple for the selection field.
def get_years():
year_list = []
for i in range(2022, 2036):
year_list.append((str(i), str(i)))
return year_list
also You can set default value directly at selection.
year = fields.Selection(get_years(), string='Year', default=str(datetime.now().year))

Related

How to use get default method on a selection field based on condition odoo 12?

What im trying to do is fetching a element from the selection field based on the state of the record.
#api.model
def _get_next_step(self):
for rec in self:
if rec.state == 'draft':
return rec.write({'next_step': 'waiting_room'})
elif rec.state == 'waiting_room':
return rec.write({'next_step': 'start_consultation'})
elif rec.state == 'start_consultation':
return rec.write({'next_step': 'finish_consultation'})
next_step = fields.Selection([
('waiting_room', 'To Waiting Room'),
('start_consultation', 'Start Consultation'),
('finish_consultation', 'Finish Consultation'),
('follow_up', 'Follow-Up'),
], string='Next Step', copy=False, index=True, track_visibility='onchange', defult='_get_next_step')
what i tried to do here is that,applying default in the selection field and wrote a function for the default method,But the field next_step is not getting updated.
The default execution environment will never have records, self is always an empty recordset. The api.model decorator is telling you that already.
You could just change the field next_step to a computed field and trigger the recomputation on state. When you store the computed field, everything like searches/grouping will work like on normal fields.

How to creat records in odoo tree view onclick button?

please help
I need when I click Enregistrer Button to create those fields in the tree view on the bottom
for this example, I have quantity equal 12 so I need 12 lines to be created on the tree view with the values on the wizard view
the wizard code :
class LinesWizard(models.Model):
_name = 'bons.wizard'
w_contrat_name = fields.Many2one('contrat.contrat', string='Contrat')
w_contrat_line = fields.Many2one('contrat.lignes', string='Ligne contrat')
w_product_name = fields.Many2one('product.product', string='Produit')
w_po_number = fields.Char(string='Numero PO')
w_qtt = fields.Float('quantite', related='w_contrat_line.quantity')
w_prix = fields.Float(string='Prix unitaire', related='w_contrat_line.unit_price')
#api.onchange('w_contrat_name')
def on_change_contrat_name(self):
if self.w_contrat_name:
self.w_contrat_line = False
return {'domain': {'w_contrat_line' : [('ligne_ids', '=', self.w_contrat_name.id)]}}
else:
return {'domain': {'w_contrat_line': []}}
In your function for the Enregistrer button, you can use below code to get the active sale.order ID.
session_id = self.env['sale.order'].browse(self._context.get('active_id'))
Then in the same function, simply create and add your rows.
session_id.write({
'your_tree_ids': [(0, False,
{
'w_contrat_name': self.w_contrat_name,
'w_product_name': self.w_product_name,
'etc': 'etc...'}
)] * int(self.w_qtt) # assuming rows to be added are the same, create a list of w_qtt quantity of (0, _, values), since your qty is a float, need to convert to int first
})

Is it possible to change the value of a selection field dynamically in Odoo 10?

I would like to have my selections depend on the value of a Char field, for instance, a Char field defined as such:
my_char = fields.Char("Enter Something", readonly = False)
so I suppose the selection field should call a function, something like "_get_value"
my_selection = fields.Selection(selection = ' _get_value')
#api.model
def _get_value(self):
my_list = [('key1','value1')]
#no idea how to assign the value of my_char to value1
return my_list
Eventually, I would like to have the selections in the drop down list vary as the user input different strings in my_char.
Is this achievable in Odoo? Because if it's not, I should better start reorganizing my structure. Thanks a lot.
As far is i know, it isn't possible with field type Selection. But you can use a Many2one field for such a behaviour.
class MySelectionModel(model.Models):
_name = "my.selection.model"
name = fields.Char()
class MyModel(models.Model):
_name = "my.model"
my_char = fields.Char()
my_selection_id = fields.Many2one(
comodel_name="my.selection.model", string="My Selection")
#api.onchange("my_char")
def onchange_my_char(self):
return {'domain': {'my_selection_id': [('name', 'ilike', self.my_char)]}}
Or without a onchange method:
my_selection_id = fields.Many2one(
comodel_name="my.selection.model", string="My Selection",
domain="[('name', 'ilike', my_char)]")
To let the Many2one field look like a selection, add the widget="selection" on that field in the form view.
How the domain should look like, should be decided by you. Here it is just an example.
No need to write method here. Just declare the dictionary to a variable and call it in selection field.
VAR_LIST = [('a','ABC'),
('p','PQR'),
('x','XYZ')]
my_selection = fields.Selection(string="Field Name",VAR_LIST)

Concatenate fields on Odoo v9

I'm trying to concatenate 3 fields to form a internal code and display it in the views:
I have 3 models:
Category (size=2)
Product (size=4)
Serie (size=3)
And I want to display it in the form like this
Product Code: CAT-PROD-001
I don't know if i have to use a computed field or if exist anoter way to do this, because I was doing test with computed fields but can't reach the desired output.
Edit:
Now I'm trying to use a computed field with a onchange function to generate the value on the field
MODEL
# -*- coding:utf-8 -*-
from openerp import models,fields,api
class exec_modl(models.Model):
_name = "exec.modl"
_rec_name = "exec_desc"
exec_code = fields.Char('Identificador',required=True,size=3)
exec_desc = fields.Char('DescripciĆ³n',required=True)
cour_exec = fields.Many2one('cour.modl')
proc_exec = fields.Many2one('enro.modl')
inte_code = fields.Char(compute='_onchange_proc')
FUNCTION
#api.onchange('proc_exec')
def _onchange_proc(self):
cate = "XX"
cour = "XXXX"
exet = "XXX"
output = cate+"-"+cour+"-"+exet
return output
I'm just trying with plain values just to know how to send it to the field.
EDIT 2:
Using the answer from #Charif I can print the static strings on the form, but the next milestome I'm trying to reach is getting the codes (external models fields) to crate that inte_code
ex: From the model cour.modl I want to get the value from the field cour_code(internal_id for course) corresponding to the cour_exec field on the first model (the cour_exec field have the description of the course from cour.modl model)
#api.depends('proc_exec')
def _onchange_proc(self):
cate = "XX"
cour = self.env['cour.modl'].search([['cour_desc','=',self.cour_exec]])
exet = "XXX"
output = cate+"-"+cour+"-"+exet
self.inte_code = output
E #api.depends('inte_code')
def _onchange_proc(self):
cate = "XX"
# first domain use tuple not list
cour_result = self.env['cour.modl'].search([('id','=',exec_modl.cour_exec)]).cour_code
cour = "" # empty string because you cannot contcatenate None or False with a string value
#if cour_result :
# cour = ",".join(crse_code for crse_code in cour_result.ids)
#else :
# print "result of search is empty check you domain"
exet = "XXX"
output = cate+"-"+cour+"-"+exet+"-"+cour_result
self.inte_code = output
EDIT 3
I've been trying to usse the search mode calling other model values but I have the console output :
Can't adapt type 'Many2One' , seems im trying to compare 2 different type of fields, the types can be parsed on odoo ? or I'm using a wrong syntax for search method?
#api.depends('inte_code')
def _onchange_proc(self):
cate = "XX"
# first domain use tuple not list
cour_result = self.env['cour.modl'].search([('id','=',exec_modl.cour_exec)]).cour_code
exet = "XXX"
output = cate+"-"+cour+"-"+exet+"-"+cour_result
self.inte_code = output
EDIT 4 : ANSWER
Finally I've reach the desired output! using the following code:
#api.depends('inte_code')
def _onchange_proc(self):
cate_result = self.cate_exec
proc_result = self.env['enro.modl'].search([('id','=',str(self.proc_exec.id))]).enro_code
cour_result = self.env['cour.modl'].search([('id','=',str(self.cour_exec.id))]).cour_code
output = str(proc_result)+"-"+str(cate_result)+"-"+str(cour_result)+"-"+self.exec_code
self.inte_code = output
Additionaly I've added a related field for add the course category to the final output.
cate_exec = fields.Char(related='cour_exec.cour_cate.cate_code')
Now the output have this structure:
INTERNAL_PROC_ID-CAT_COURSE-COURSE-EXECUTION_CODE
EX: xxxxxxxx-xx-xxxx-xxx
First in compute field use api.depends not onchange :
Second the compute function don't return anything but it passes the record on the self variable so all you have to do is assign the value to the computed field.
#api.depends('proc_exec')
def _onchange_proc(self):
# compute the value
# ...
# Than assign it to the field
self.computed_field = computed_value
one of the thing that i recommand to do is to loop the self because it's recordSet so if the self contains more than one record this previous code will raise signlton error
so you can do this :
# compute the value here if it's the same for every record in self
for rec in self :
# compute the value here it depends on the value of the record
rec.compute_field = computeValue
or use api.one with api.depends
#api.one
#api.depends('field1', 'field2', ...)
EDITS:
#api.depends('proc_exec')
def _onchange_proc(self):
cate = "XX"
# first domain use tuple not list
cour_result = self.env['cour.modl'].search([('cour_desc','=',self.cour_exec)])
cour = "" # empty string because you cannot contcatenate None or False with a string value
if cour_result :
cour = ",".join(id for id in cour_result.ids)
else :
print "result of search is empty check you domain"
exet = "XXX"
output = cate+"-"+cour+"-"+exet
self.inte_code = output
try this code i think the result of search is a recordSet so you can get the list of ids by name_of_record_set.ids than create a string from the list of ids to concatenate it try and let me know if there is an error because i'm using work PC i don't have odoo on my hand ^^
You can create new wizard.
From wizard you can generate Internal Reference.
class create_internal_reference(models.TransientModel):
_name="create.internal.reference"
#api.multi
def create_internal_reference(self):
product_obj=self.env['product.product']
active_ids=self._context.get('active_ids')
if active_ids:
products=product_obj.browse(active_ids)
products.generate_new_internal_reference()
return True
Create View & act_window
<record model="ir.ui.view" id="create_internal_reference_1">
<field name="name">Create Internal Reference</field>
<field name="model">create.internal.reference</field>
<field name="arch" type="xml">
<form string="Create Internal Reference">
<footer>
<button name="create_internal_reference" string="Generate Internal Reference" type="object" class="oe_highlight"/>
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<act_window name="Generate Internal Reference" res_model="create.internal.reference"
src_model="product.product" view_mode="form" view_type="form"
target="new" multi="True" key2="client_action_multi"
id="action_create_internal_reference"
view_id="create_internal_reference_1"/>
class product_product(models.Model):
_inherit='product.product'
#api.multi
def generate_new_internal_reference(self):
for product in self:
if not product.internal_reference:
product.internal_reference='%s-%s-%s'%(str(product.categ_id.name)[:2],str(product.name)[:4],third_field[:3])
From product.product under more button you can access this wizard and generate internal reference.
This may help you.

How to assign a value of selection field to other selection field in a onchange method in odoo?

Just working on the following code to autofill a Selection field
calendar.event has a location field which is a selection field, trying to autofill it in my custom module based upon an onchange method.
I wanted to get the selected value in that selection field for a particular record into 'loc' field which is also a selection field in my custom module
def get_meet_dets(self, cr, uid, ids, meet_ref, context=None):
val = {}
res = []
if meet_ref:
for det in self.pool.get('calendar.event').browse(cr,uid,meet_ref,context=context):
for asst in det.attendee_ids:
emp_id = self.pool.get('hr.employee').search(cr, uid, [('user_id','in',user_id)])
val = {
'empname' : emp_id[0],
'wk_mail': asst.partner_id.email,
'loc' : det.location,
}
res.append(val)
val.update({'matp':res})
and 'loc' is a selection field in current class. Anyone having any idea on this?
You need to pass an existing id for your loc field, you can try 'loc' : det.location.id,. I hope this can be helpful for you.