ODOO 10 custom report pdf name - odoo

I am developing a custom report in ODOO10 CE and I have a problem naming the generated PDF. It always names the "string" field in the report definition. It ignores the print_report_name field.
Here is the report definition:
<report
id="action_report_as"
model="report_as"
string="Report AS_EE"
report_type="qweb-pdf"
name="report_as_ee.report_as"
paperformat="report.vertical_1"
/>
<record
id="action_report_as"
model="ir.actions.report.xml">
<field name="print_report_name">mycorrectreportname.pdf</field>
</record>
And here is the .py:
class ReportAs(models.AbstractModel):
_name = 'report.report_as_ee.report_as'
#api.model
def render_html(self, docids, data=None):
self.model = self.env.context.get('active_model')
docs = self.env[self.model].browse(self.env.context.get('active_id'))
as_records = []
#
# code that puts records in as_records array
#
docargs = {
'doc_ids': self.ids,
'doc_model': self.model,
'docs': docs,
'time': time,
'as': as_records
}
return self.env['report'].render('report_as_ee.report_as', docargs)
Maybe I need to put the name from the .py? How?
Thanks.

you can do it like this, go to Settings -> Technical ->reports ->reports, select the report of the sales,
Example, Report Quotation / Order. Then open the report and add
"((object.name or '').replace('/','')+'.pdf')" this to field Printed Report Name.
Check with Quotation/Sale Order Print.
Thanks

Related

Getting id from URL to filling wizard form, Odoo

I want to get id from url when i click the button.
This is URL, id is 69:
http://localhost:8069/web#id=69&cids=1&menu_id=385&action=507&model=inventory.menu&view_type=form
I need to get this id in many2one field.
This is my wizard py file:
from odoo import api,fields,models
class ReduceInventoryWizard(models.TransientModel):
_name = "reduce.inventory.wizard"
_description = "Reduce Inventory Wizard"
inventory_ids = fields.Many2one('inventory.menu', string="Ürün Referans No: ", default=lambda self: self.env['inventory.menu'].search([('id', '=', 69)], limit=1))
As you can see, ('id', '=', 69) this is running but just one product. I want the information of that product to come automatically when I click the button in which product.
I tried this one: ('id', '=', self.id). But is not working.
In this situation there should be active_id or better active_ids in Odoo's context.
So you just can set the default parameter to use a default method, which will either return a value or an empty recordset:
def default_my_many2one_field_id(self):
active_ids = self.env.context.get("active_ids")
if active_ids:
return self.env["another.model"].browse(active_ids[0])
return self.env["another.model"]
my_many2one_field_id = fields.Many2one(
comodel_name="another.model", string="My M2o Field",
default=default_my_many2one_field_id)

Not getting records which created in One2many field on onchange in transient model

I am trying to create records in one2many field in one of my transient model on onchange of boolean field.
Eg.
Models
class test_model(models.TransientModel):
_name ="test.model"
is_okay = fields.Boolean("Okay?")
lines = fields.One2many("opposite.model","test_id",string="Lines")
#api.onchange('is_okay')
def onchnage_is_okay(self):
ids = []
for l in range(5):
record = self.env['opposite.model'].create({'name':str(l),'test_id':self.id})
ids.append(record.id)
self.lines = [(6,0,ids)]
class opposite_model(models.TransientModel):
_name ="opposite.model"
name = fields.Char("Name")
test_id = fields.Many2one("test.model",string="Test Model")
View
<record id="view_form" model="ir.ui.view">
<field name="name">view.form</field>
<field name="model">test.model</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Test Model">
<field name="is_okay" />
<field name="lines" />
<footer>
<button name ="click_okay" string="Okay" type="object"/>
</footer>
</form>
</field>
</record>
Now, problem is that when in check or uncheck the is_okay field it fills the records in the One2many field.
That is working fine.
But in my above view i have button which calls the method click_okay().
Eg.
#api.one
def click_okay(self):
print self.lines
So, print statement gives me blank recordset. But, i can see the 5 records in the view when i am changing is_okay field.
I am not getting any idea how to get those lines in method?
Any response would be appreciated?
It should work. That's wired behavior.
You may try with following alternative way using self.update()
#api.onchange('is_okay')
def onchnage_is_okay(self):
ids = []
for l in range(5):
record = self.env['opposite.model'].create({'name':str(l),'test_id':self.id})
ids.append(record.id)
self.update({
'lines' : [(6,0,ids)]
)}
No matter what odoo keep doing the same thing:
the problem is that odoo always passes this records to create method with command 1 but in odoo we cannot use this command in create method and this
why you lose this records in the call of method.
(1, id, values)
updates an existing record of id id with the values in values. Can not be used in create().
i don't know why you are creating this record in onchange event because this not recomanded if the user hit close instead of ok the record all ready created in database and every time he check the button will recreate this record again and again.
if you don't need to create this records in the onchange event what you should do is:
#api.onchange('is_okay')
def onchnage_is_okay(self):
ids = []
for l in range(5):
record = self.env['opposite.model'].new({'name': str(l)})
ids.append(record.id)
self.lines = ids
one thing here onchange will return the dictionnary to the form, the tree of the one2field must have all field that are passed in that dictionary in this case the tree must have field name if oppisite.model have for example another field like test_field if we pass {'name': value, 'test_field': value_2} if the tree have only name field value of test_field will be lost in create method.
but if you need like you are doing, you should work arround odoo and change the command to 4 in create a method:
#api.model
def create(self, vals):
"""
"""
lines = vals.get('lines', False)
if lines:
for line in lines:
line[0] = 4
line[2] = False
vals.update({'lines': lines})
return super(test_model, self).create(vals)

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.

Change Selection Field odoo 8

I am trying to generate different selection choices depending on other field in the Model. I am working in Odoo 8.
Below is the code :
My Model: (test.py)
type = fields.Selection(selection='_get_selection', string='Type')
#api.onchange('role_name')
def _get_selection(self):
choise = []
if self.role_name == 'primary':
choise.append(('unit','Unit Case'))
if self.role_name == 'reserve':
choise.append(('res','Reserve Case'))
return choise
The View: (template.xml)
<field name="type" widget="selection"/>
But i don't see any values in Selection Field.
Please Help.
Thanks,
This is an example from 'account.invoice' in Odoo 8:
#api.model
def _get_reference_type(self):
return [('none', _('Free Reference'))]
reference_type = fields.Selection('_get_reference_type', string='Payment Reference',
required=True, readonly=True, states={'draft': [('readonly', False)]},
default='none')
This should help you in resolving the issue.
#api.model
def _get_selection(self):
#DO SOMETHING
return choise
type = fields.Selection(selection=_get_selection, string='Type')

How to make domain dynamic in OpenERP

I want to give a dynamic domain equation in view or in field definition in .py.
like
<field name="product_id" domain="[('name','in',get_names)]"/>
product_id is a many2one field.
get_names is function that creates a list at run time.
Its showing an error - "name 'get_names' is not defined"
Any Ideas.
I have also tried the following.
'product_id': fields.many2one('mymodule.relation.model','Title',selection=get_names)
This displays all entries in mymodule.relation.model. The only thing it does is to validate if value selected/submittted by user belongs to the 'get_names'.
inherit the fields_view_get() function and manage the domain condition. Please check these posts
How to create a dynamic view on OpenERP
How can I change the choices in an OpenERP selection field based on other field values?
1- You can use function field like this:
def _get_domain(self, cr, uid, ids, field_name, arg, context=None):
record_id = ids[0]
# do some computations....
return {record_id: YOUR DOMAIN}
and function field:
'domain_field': fields.function(_get_domain, type='char', size=255, method=True, string="Domain"),
And use the name of the field in xml (domain attr):
<field name="product_id" domain="domain_field" />
2- you can use 'fields_view_get':
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(taskmng_task, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
doc = etree.XML(res['arch'])
for node in doc.xpath("//field[#name='project_id']"):
# do some computations....
node.set('domain', YOUR DOMAIN)
res['arch'] = etree.tostring(doc)
return res
You can't use a function or method in the domain expression, only object fields.
It's not equivalent, but closest thing is to create a function field to use in the domain expression.
As Don't know your exact requirement .but may be any one from these 2 can help you
http://ruchir-shukla.blogspot.in/2010/11/domains-value-depending-on-condition.html
or check the Account Invoice product onchange . You can return domain from the onchange.