Odoo Help

Welcome!

This community is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.

1

How to filter field on a one2many?

By
Anirudh Lou
on 2/5/15, 2:18 AM 1,580 views

Hello everyone, kindda lost for my odoo adventure and i need a help. I have a class named "planned.bom", some of it's columns are product_id (many2one on product), project_id (many2one on project). This is where i stuck, in my purchase requisition, when i add purchase requisition lines, i want to show only those products which are under planned.bom and base on project.

Here is the image i want to tell:

Any help is much appreciated.

 

 

-------------------------------------------------------------------------

 

In purchase.requisition i add fields.function;

'product_ids_to_chose_from' : fields.function(_get_assigned_bom, type='many2many', method=True,store=False, multi='compute_assigned_bomproduct', string='Assigned BOM product')

and the functions looks lik this:

 

    def _get_assigned_bom(self,cr,uid,ids,context=None):
        vals = {}
        pr_id = None
        for rec in self.browse(cr, uid, ids, context=context):
            pr_id = self.pool.get('project.project').search(cr,uid,[('id','=',rec.project_id.id)])
            for project in self.pool.get('project.project').browse(cr,uid,pr_id,context=context):
                p_bom_ids = self.pool.get('planned.bom').search(cr,uid,[('project_id','=',project.id)])
                for bom in self.pool.get('planned.bom').browse(cr,uid,p_bom_ids,context=context):
                    pr_id = bom.product_id.id
            vals[rec.id] = {'product_ids_to_chose_from':pr_id}
        return vals

 

on purchase.requisition.line i add this one:

'product_ids_to_chose_from': fields.related('requisition_id', 'product_ids_to_chose_from', type='many2many', string='Assigned BOM product'),

and on my form here how create the domain:

<page string="Products" attrs="{'invisible':[('state','=','new')]}">
      <field name="line_ids" context="{'requisition_id': active_id}" attrs="{'readonly':[('state','not in','add_product')]}">
                 <tree string="Products" editable="bottom">
                       <field name="product_id" required="True"                                               

                                               on_change="onchange_product_id_limit(product_id,product_uom_id,product_qty,context)"

                                              domain="[('is_bom','=',True),('ids','in',product_ids_to_chose_from[0][2])]" />

upon clicking on a product i recieve this client error:

Uncaught Error: NameError: name 'product_ids_to_chose_from' is not defined

 

i don't know what it cause.

 

****************** EDIT

 

    def _get_assigned_bom(self, cr, uid, ids, name, arg, context=None):
        vals = {}
        pr_id = []
        for rec in self.browse(cr, uid, ids, context=context):
            id = rec.id
            vals[id] = []
            if rec.project_id:
                p_bom_ids = self.pool.get('planned.bom').search(cr,uid,[('project_id','=',rec.project_id.id)])
                for bom in self.pool.get('planned.bom').browse(cr,uid,p_bom_ids,context=context):
                    pr_id = bom.product_id
            vals[id] = [(6, 0, [x.id for x in pr_id])]
        return vals

1

Ivan

--Ivan--
3210
| 5 3 6
Jakarta, Indonesia
--Ivan--
Ivan
On 2/5/15, 3:20 AM

I presume that the purchase.requisition (PR) is somehow linked to the planned.bom.  So, here is a trick that I usually used:

  • Create a function many2many field in the PR (or you can alternatively populate this column during create / write).
  • The many2many field need to be populated with all the product.product that is linked to the planned.bom.
  • In your purchase.requisiton.line model, extend (using related field in v7 or compute argument in v8) to reflect the new many2many field of the related PR.  Say, it is named product_ids_to_chose_from
  • Use that field to domain your product_id: domain="[('ids', 'in', product_ids_to_chose_from[0][2])]"

Thank you sir for your response, actually purchase.requisition has no direct link with planned.bom other than that it has many2one on project.project and with all due respect sir, do you mean in 'create a function' i need to create fields.function on my PR?

Anirudh Lou
on 2/5/15, 3:38 AM

It's OK if the link is not direct as long as it has link. Because it is needed for the step in the 2nd point. And yes, you need to create fields.function (I presume that you are developing in v7 then, cause in v8 it is implemented differently).

Ivan
on 2/5/15, 3:40 AM

Sir i updated my question above, i am not sure if i correctly followed your suggestion and that's why i got an error.

Anirudh Lou
on 2/5/15, 5:36 AM

The domain need to be implemented in the view XML not from the field definition. Reason: product_ids_to_chose_from can only have value when a record is selected. The domain in field definition can only use something that is not depending on the record value.

Ivan
on 2/5/15, 6:20 AM

One more note: the first 3 lines in the first for loop in _get_assigned_bom can be collapsed. There are 3 lines that I'm referring to: pr_id = self.pool.get('project.project').search(cr,uid,[('id','=',rec.project_id.id)]); for project in self.pool.get('project.project').browse(cr,uid,pr_id,context=context):; p_bom_ids = self.pool.get('planned.bom').search(cr,uid,[('project_id','=',project.id)]). Can be collapsed to p_bom_ids = self.pool.get('planned.bom').search(cr,uid,[('project_id','=',res.project_id.id)]). You might want to put a check before to see if res.project_id is empty or not.

Ivan
on 2/5/15, 6:24 AM

Sir, i guess i recieved a client error because my fields product_ids_to_chose_from is not srored in my database, I am not sure though. Yeah the domain: "domain="[('is_bom','=',True),('ids','in',product_ids_to_chose_from[0][2])]" is in my view form. I tried to make product_ids_to_chose_from as store=True but it also produce an error.

Anirudh Lou
on 2/5/15, 8:26 PM

Sorry forgot to mention that you need to put the field product_ids_to_chose_from in the view. Don't store, unless if you are sure that the list of products will only change if the purchase.requisition is saved (i.e. there is no way that the list of products may change because there is new planned.bom added to the project.)

Ivan
on 2/5/15, 10:08 PM

Sir, after adding the field on the view, my using vals[rec.id] = {'product_ids_to_chose_from':pr_id} produce no output, when i click the tree view of my purchase requisition it says: "Uncaught TypeError: undefined is not a function" and using vals[rec.id] = pr_id it says: "AttributeError: 'int' object has no attribute 'iteritems'"

Anirudh Lou
on 2/6/15, 12:15 AM

Return of _get_assigned_bom should be in the form or [(6, 0, [XXXX])]. Where [XXXX] is the list of product ids that you have collected. I see that you assign just one id to pr_id. Why so? Also, pr_id variable is reused, you may end up in the situation where self.pool.get('planned.bom').browse(cr,uid,p_bom_ids,context=context) and your pr_id is the one returned from self.pool.get('project.project').search(cr,uid,[('id','=',rec.project_id.id)]).

Ivan
on 2/6/15, 1:14 AM

Do you mean sir, pr_id = bom.product_id.id must be changed to pr_id = bom.product_id and then loop for this items? Or my head is already spinning and that's why i can't spot it.

Anirudh Lou
on 2/6/15, 2:01 AM

Sir I have updated my function replacing vals[rec.id] into vals[id] = [(6, 0, [x.id for x in pr_id])] and terminal says, NotImplementedError: Iteration is not allowed on browse_record(product.product, 4)

Anirudh Lou
on 2/6/15, 2:26 AM

Because you are still using pr_id which is assigned in this line: pr_id = bom.product_id. And thus pr_id is a single browser_record and cannot be interated. You should collect all bom.product_id in a list, like so: pr_id = [bom.product.id if bom.product else False for bom in self.pool.get('planned.bom').browse(cr,uid,p_bom_ids,context=context)]

Ivan
on 2/6/15, 5:12 AM

Oh oh, kindda nose bleed for the code structure. Can you explain it to me sir, if it's okay with you.

Anirudh Lou
on 2/8/15, 7:27 PM

Sir, using vals[id] = [(6, 0, [x.id for x in pr_id])] produce an error, it says AttributeError: 'int' object has no attribute 'id'. When i tried, vals[id] = {'product_ids_to_chose_from':pr_id} it works but on my purchase.requisition.line field "product_ids_to_chose_from" is empty while field "product_ids_to_chose_from" on purchase.requisition has item on it. When i check product_ids_to_chose_from on purchase.requisition.line it is related to product_ids_to_chose_from on purchase.requisition.

Anirudh Lou
on 2/8/15, 10:26 PM

Sorry, I did make the pr_id to be a list of Database IDs instead of list of browse_objects. You can change the vals[id] line to be: vals[id] = [(6, 0, pr_id)] OR change the pr_id line to be: pr_id = [bom.product for bom in self.pool.get('planned.bom').browse(cr,uid,p_bom_ids,context=context)]

Ivan
on 2/9/15, 4:05 AM

And if you have difficulty in reading the code, I suggest that you familiarise yourself with list comprehension: https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions, http://www.python-course.eu/list_comprehension.php, http://www.secnetix.de/olli/Python/list_comprehensions.hawk

Ivan
on 2/9/15, 4:08 AM

I have tried it sir, using vals[id] = [(6, 0, pr_id)] and it says AttributeError: 'list' object has no attribute 'iteritems'.

Anirudh Lou
on 2/9/15, 4:56 AM

Not sure what causes the AttributeError. But from code I think vals has been defined as list instead of dictionary as it should. The code that you have posted in the question defined it as dictionary.

Ivan
on 2/9/15, 5:45 AM

but everytime i tried vals[id] = {'product_ids_to_chose_from':pr_id} it works but on the purchase.requisition only, on purchase.requisition.line the field product_ids_to_chose_from is empty.

Anirudh Lou
on 2/9/15, 6:03 AM

but everytime i tried vals[id] = {'product_ids_to_chose_from':pr_id} it works but on the purchase.requisition only, on purchase.requisition.line the field product_ids_to_chose_from is empty.

Anirudh Lou
on 2/9/15, 6:03 AM

It is from a different method. Your definition of vals does not carry over different methods.

Ivan
on 2/9/15, 7:07 AM

even if it is fields.related sir?

Anirudh Lou
on 2/9/15, 7:55 PM

After changing vals = {} into vals = [] and assigning vals[id] = [(6, 0, pr_id)], now the compiler says: "IndexError: list assignment index out of range" for my vals assignment.

Anirudh Lou
on 2/9/15, 10:28 PM

Sir,can i ask one more question. Now in my purchase requisition form it does not completely shows my BOM (i.g if project A, have 4 BOM only three is bieng displayed on my form. I tried to show it on my terminal but it all print planned.bom under that project). What's the possible cause of this one?

Anirudh Lou
on 2/12/15, 9:11 PM

Sorry I did not caught your earlier messages. I'm not sure what you mean by your question about fields.related. The vals need to be a dictionary {} not list []. The error "IndexError: list assignment index out of range" is due to you using a list. On the subject of 4 BOMs showing only 3, I would suggest that you check: 1. Are there really 4 planned.bom that are connected to that project (whose project_id is the project's database ID)? 2. Do you have any Record Rules or any domain applied to the view/column/model?

Ivan
on 2/13/15, 12:41 AM

In my purchase.requisition.line i have product_ids_to_chose_from w/c is of fields.related on product_ids_to_chose_from from purchase.requisition. For number one, yes there exist a four planned bom under same project. For number 2, yes there is a domain on product_ids_to_chose_from in my view.

Anirudh Lou
on 2/13/15, 2:02 AM

Actually sir, it works properly on my purchase.requisition.line, it shows all products whose planned bom is under project selected by the user from purchase.requisition. I am just wondering, why all planned bom are not shown on purchase.requisition view.

Anirudh Lou
on 2/13/15, 2:06 AM

If it shows in the purchase.requisition.line but not in the purhcase.requisition, my suspect will be a domain that prevents the record to be shown in the view definition.

Ivan
on 2/13/15, 2:16 AM

Copy, perhaps i just have to make it invisible. What is the important is it filter the product. By the way thanks a lot sir for your patient especially for the help. :)

Anirudh Lou
on 2/13/15, 2:52 AM
0
Anirudh Lou
On 2/9/15, 5:45 AM

Thanks for the links sir.

Your Answer

Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!

About This Community

This community is for professionals and enthusiasts of our products and services. Read Guidelines

Question tools

1 follower(s)

Stats

Asked: 2/5/15, 2:18 AM
Seen: 1580 times
Last updated: 3/16/15, 8:10 AM