3

I'm using the Inventory addon of Odoo 12 (but my problem could happen with any module).

In this addon, a StockMove model has a move_line_ids field.
In the Detailed Operations dialog, we can see a tree view of all the move lines of the selected move.

If we click the Add a line button, and set the fields, the values are stored in memory, but not in database unless we click the Confirm button.

I would like to copy this behaviour in a @api.onchange() method of my custom StockMove model, but I don't find how to proceed.
If I use the self.move_line_ids.create() method to create my new record, the move line will be stored in the database even if I don't click the Confirm button.

Is there someone who managed to do that?

Thank you in advance!
And sorry if it is a duplicate question, but I did not found the answer to my question yet ><


The jzeta answer is working but breaks other Move fields like reserved_availability (always 0) or quantity_done (always 1).


I am keeping jzeta as validated as the comments show the solution I was looking for.

Thank you a lot guys for your help!

mistiru
  • 2,996
  • 3
  • 11
  • 27

2 Answers2

2

I believe you can achieve it by directly assigning the value to move_line_ids. Of course, given the field is a One2many, you need to use the special list of triplets to achieve this. In your case, you need a [(0, _, values)] for you want to create a new record (where values is the dictionary that holds each new record's field values). In the example below I only create one record attached to a given stock.move instance and I merely pass the move_id value in the dictionary. You should complete the code with the appropriate values for the new move line, but note that you should always tell the new record which stock move it is been linked to.

@api.onchange('your_field_name')
def _onchange_field(self):
    self.move_line_ids = [(0, False, {'move_id': self.id})]
jzeta
  • 377
  • 1
  • 14
  • If I `print(type(self.move_line_ids))`, I get ``. Is it ok to do the assignment? What if I want to add to, and not to set the move_line_ids value? (sorry but I have difficulties with that ORM...) – mistiru May 13 '19 at 14:55
  • Ok, I tested, and it works. I still don't understand why the type don't change although we do an assignment, but... OK ! Thank you very much! – mistiru May 13 '19 at 15:07
  • Actually, it works, but break the move quantities, and the reserved ones. The wizards starts showing 0 / 3 Units (for instance), and after I add one, 1 / 0 Units, then I add again, and still 1 / 0 Units. – mistiru May 15 '19 at 15:21
  • 2
    As i remember is that you can use a `new` method it works like `create` except that it don't save the record in database – Charif DZ May 16 '19 at 20:02
  • 2
    I think you usually use `new()` when you want to call some `onchange` method to get those missing values you'd get when doing the job on GUI. You go as follows: `cache_record = self.env[''].new(values)`; then call whatever `onchange` method you want to call; then finally get the values dictionary from the cached object: `updated_values = cache_record._convert_to_write(cache_record._cache)`; finally use the updated values on `write` or `create` method. It might also do the trick for OP's question. Have not tried it though. – jzeta May 17 '19 at 08:52
  • I didn't see the two last answers, sorry, I just found the `new` method today by scrolling around the code (very long file... 6000 lines >< ). New was actually the exact thing I was looking for. I did `self.move_line_ids.new({...})`. – mistiru May 29 '19 at 16:51
-3

.create method creates a record into the database, so it's expected to do so, if I understood you, I think you should use something like TransientModel or AbstractModel ?!

An Abstract model is created by a class based on models.AbstractModel instead of
the usual models.Model. It has all the attributes and capabilities of regular models; the
difference is that the ORM will not create an actual representation for it in the database. So,
it can have no data stored in it. It serves only as a template for a reusable feature that is to be
added to regular models.
Black Kinght
  • 55
  • 1
  • 10
  • Not really, I want to add it in the database, but when clicking the `Confirm` button, as for every tree view with normal models. I just want to copy the `Add a line` behaviour in a `@api.onchange()` method. I mean, I want to add a new line to my tree view when a event that triggers this onchange occurs. – mistiru May 12 '19 at 10:29
  • Not what the OP is asking for. Usually, `AbstractModel` is used for mixins and `TransientModel` is used for wizards. OP is asking how to update a O2m field using and onchange method without calling `create`. – jzeta May 14 '19 at 09:14