0
votes

How can I set delivery order to state "done" with xmlrpc?

I'm using

$client->write('stock.move', array(58), ['state' => "done"]);

It does work but it does not update on hand quantity, only forecast quantity is getting updated.

Is there any way to call exec_workflow from PHP?

2

2 Answers

4
votes

I recently encountered the same issue when working on a PHP XMLRPC endpoint for Odoo 11 and I stumbled across this post and a few other even older posts, but none of them answered the question with enough detail that could provide me with a working solution. That said, here is what I ended up doing to solve the problem you were having (set the delivery order state or "done" and update the quantity-on-hand).

My solution requires two API calls instead of just one, and you will need the stock.picking id and any related stock.move id(s). I also created a simple class called OdooXmlrpc to handle the XMLRPC calls to Odoo. I am assuming you have done the same thing since your code snippet appears to be calling methods on your $client object. I’ll include my class methods below for reference.

Now for the code snippets. Using PHP, the first thing I did was set the ‘quantity_done’ field of the stock.move for each product/item in the picking because that is the field used for the quantity-on-hand update. You do not have to set the state field for the stock.picking or the stock.move records, Odoo will set those when we call the second execute_kw function.

// first we update the stock.move qty done
$update_move_data = array(array($move['id']), array('quantity_done' => $move['product_qty']));
$update_move = $xmlrpc_client->write('stock.move', $update_move_data);

Or using your syntax with some dummy data

$xmlrpc_client->write('stock.move', array(58), ['quantity_done' => 50]);

Next, I call a generic method that I created in my class called 'call_function' to process the delivery order transfer. This class method will accept an Odoo model and method. In theory, I could use this class method for any CRUD operations, but I reserve the usage for all non-CRUD based operations since params will vary – still a work in progress but seems useful and works for now.

// next we process the picking so its gets marked as done and qty on hand gets adjusted
$picking_do_transfer = $xmlrpc_client->call_function('stock.picking', 'do_transfer', array($picking['id']));

That’s it! the delivery order state is now "done," and the quantity-on-hand should have updated correctly in the system.

Note that using this "do_transfer" method, Odoo will create a backorder automatically for any item/move that did not have a quantity_done value set, which I found to be very useful. Hope this response helps you and any other users that stumble across it.

My OdooXmlrpc class methods for reference:

/**
* Write the records respective to the IDs and field value pairs provided
*
* @param        (string) $model, the Odoo model to be used in the call
* @param        (array) $domain, a multi-dim array of record ids and a mapping of updated fields to values
*
* @return       (int) $ret, 1 when operation was successful
*/
function write($model, $domain) {
    if (!isset($model) || !isset($domain)) {
        print "Missing params...";
        return;
    }
    // our odoo method
    $method = 'write';
    $ret = $this->client->execute_kw($this->database, $this->id, $this->password, $model, $method, $domain);
    return $ret;
}

/** !NOTE! EXPERIMENTAL: NOT SURE WORKS WITH ALL ODOO MODELS
* Call the model function with IDs and/or field values to run/update with
*
* @param        (string) $model, the odoo model to be used in the call
* @param        (array) $method, the name of the model method to call
* @param        (array) $args, an array of id(s) or records to modify
*
* @return       (int) $ret, 1 when operation was successful
*/
function call_function($model, $method, $args) {
    if (!isset($model) || !isset($method) || !isset($args)) {
        print "Missing params...";
        return;
    }
    $ret = $this->client->execute_kw($this->database, $this->id, $this->password, $model, $method, $args);
    return $ret;
}
0
votes

You have to pass model name, record id and the signal name.

client->exec_workflow('stock.move', array(58), signal_name);

from odoo9 on github

@http.route('/web/dataset/exec_workflow', type='json', auth="user")
def exec_workflow(self, model, id, signal):
    return request.session.exec_workflow(model, id, signal)