2
votes

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

2
Is one of this field a compute field if not than use compute field put your code that you tried and didn't work as you wantedCharif DZ
I've added some code of my local testsNMenam

2 Answers

1
votes
  1. First in compute field use api.depends not onchange :
  2. 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 ^^

1
votes

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.