Alternative partial picking procedure

Registered by Numérigraphe on 2011-10-13

== Description of the issues ==
The current partial picking wizard has several flaws.
The refactoring effort has made the code unclean and difficult to change. This needs to be cleaned up.
More importantly, the user interface is unintuitive and inconsistent. Some operations can only be made from the stock move views (scrap, divide into prodlots, tracking) and other only on the partial move wizards (partial move, purchase price update).
Additionally, there are 2 partial move wizards: one for single moves, and one for whole pickings. This is worsened by the fact that the wizard does not show the same data on incoming and outgoing pickings.
The wizard that lets users split moves in lots also looks a lot like the partial move wizard.
This makes the interface very inefficient (and in some cases unworkable!) for users who need to both split moves into lots and make partial moves.
In some circumstances, this makes workers handle the goods twice: once for keying in lots and packing data, and once to key in partial quantities.
I also won't let users force availability for partial quantities : users can only force availability on whole Stock Moves.
One good point of the wizard UI is that it lets users key in several prodlots, prices etc in one shot.

== Proposed solution ==
We propose to move the features of the "process" wizard to the main views, to make them available at all times. The "process" button should only be in charge of changing the states and advancing the workflows.
The features of the wizard that we want to keep are :
- Backorder generation
[1a] let users enter the quantities actually processed
[1b] allow users to revert to the original state (like they would cancel the wizard)
[1c] automatically create backorders when the picking is done, keeping the initial moves unfinished so that the other workflows don't advance
- average price computation
[2a] let users key in prices on receptions
[2b] update the average prices when the picking advances to "done"
- ergonomics
[3a] make the move tree views editable inside the picking views
[3b] make sure the original picking remains visible when creating a backorder, so users can invoice from it.
- code cleanup
[4a] update the automatic tests to use the new partial move procedure
[4b] remove the partial picking wizards introduced in v6.0, drop *.do_partial() and action_split()

== Implementation ==
The partial move wizard and the partial picking wizards will be discarded.
The "process" button on move views will directly call move.do_partial() and mark the move "done".
The "process" button on picking views will directly call move.do_partial() on all lines (code deduplication) and mark the picking done.

For [1a], users must not change the quantity on the stock move (that would change stock reservations), so we intend to generalize line splitting.
We will refactor the wizards that split in lots, in packs and to scrap:
- a single button "Split line" will call a wizard asking the quantity to leave on the original line and the type of splitting (new/existing lot, new pack, scrap, backorder). "new/existing lot" will make more fields visible to key in lot details.
- when users press "ok", a new line is created with the required properties and the original qty is changed.

For [1b] we neither want to add a bolean field (that's clumsy), nor to add a new "state" value (that would break reservations and virtual stock), so we propose to add a new field "pick_state" with 3 possible values:
- Pending (default value)
- Picked: this is informational and indicates the move was processed normally. This value is set in the action for the "Process" button of the move.
- Not picked: this marks the move for becoming a backorder. This value is set using a button.
As a bonus, we could present a button to set "pick_state" to "Picked" manually without validating the line, to let users track progress of the operation (check incoming goods or pick outgoing move)

Given the changes above, [1c] only needs stock.move.do_patial() to base the backorder creation on "pick_state" instead of values from a wizard:
- "Pending": no backorder and change to "Picked"
- "Picked": no backorder, no change.
- "Not picked": move to backorder and reset to "Pending"

[2a] is straightforward: we propose to display the existing fields price_unit and price_currency_id on all move views in a reception context. The fields are required and read-only for moves in state "done".

Given that, [2b] only requires to use price_unit and price_currency_id from the stock moves instead of the wizards.

[3a] only requires to add editable="top" in the tree views, to add onchange events that could be missing, and maybe to set some fields read-only for consistency.

[3b] needs the procedure to return an action to the client to display the original picking.

== Modularity ==
As a proof of concept, these changes will be implemented as a branch from the addons v6.1. Depending on feedback, they could either be proposed for merging into the trunk, or be maintained as a patch, or be refactored into a dedicated module.
A backport patch will be provided for 6.0.

== Refactoring opportunity ==
If practical, the code duplication in move.do_partial and picking.do_partial will be resolved.
The average price computation should also be moved out of do_partial, and possibly pushed out of the "stock" module into "product".

Whiteboard

== Demonstration at the OpenERP Open Days ==
The current implementation of this blueprint was demoed by Lionel at the OpenERP Open Days in Brussels on the 12th of April 2012, 17h10.
A screencast of the presentation is at http://fr.slideshare.net/openobject/openerp-new-procedure-for-partial-deliveries .

The proposal received positive feedback, so we'll try to progressively merge the changes to the trunk.

== Work to do ==
The implementation is still a single large patch against the official addons. For further adoption it should be split in clean modules.
They must also be ported to v7.0 and properly tested.

== Implementation status==
This blueprint is almost completely for v6.0 and deployed in production in 1 installation.

The port of this patch to v6.1 is at lp:~numerigraphe/openobject-addons/6.1-stock-backorder-rewrite
[1a] is implemented only at the lowest level, no refactoring was made for the moment.
[4*] won't be implemented unless the core team agrees to the other changes.
[2a] and [2b] will need to be re-implemented later if the average price calculation is rewritten in the trunk, as was announced by the Core Team.

The following branches are also merged into this main branch:
- lp:~numerigraphe/openobject-addons/6.1-stock-split-move-refactoring partially implement [1a] : we've added a new wizard to split moves in a clean way. We'd like to refactor the other wizards too later on.
- lp:~numerigraphe/openobject-addons/trunk-stock-qty-help provides additional GUI helps useful for [3a]
- lp:~numerigraphe/openobject-addons/trunk-stock-editable-compatible-picking-line fixes issues that prevent the picking lines from being editable as suggested by Don Kirkby.

A backport to v6.0 is available at lp:~numerigraphe/openobject-addons/6.0-stock-backorder-rewrite .
The server needs a small patch found at lp:~numerigraphe/openobject-server/6.0-workflow-return-action , otherwise the original picking is not displayed.

== Chained moves ==
René Gausser asked Numérigraphe if this would let users split chained moves too. This is not implemented but now that the splitting method is clearly isolated it could be made recursive more easily.

== Notes ==
Additions and corrections are most welcome here.
...

Side notes and additional thoughts:
----
Note : are partial moves a stock concern in the first place?
It would be tempting to declare that the partial shipping management should not be handeled by the stock module at all. After all, isn't it more intuitive to let users change the quantity on the stock move? Then the ERP could compare that shipped quantity with that of the origin order (sale, purchase, production, procurement) and create the needed backorder.
Unfortunately that would require very deep changes to several workflows that expect events to come from the stock to progress.
There is also a problem with procurements, which only have a link to a single stock move. Finishing that move means the procurement is complete, which may mean the sale order line is honored: no backorder can be made then.

---
A simpler but still elaborate approach would be to integrate the features of the wizard directly into the picking. This would have the advantage to let users process part of the picking, save it, and recall it later on.
This boils down to adding a new object "Stock Move Order" representing the ordered stock move vs the actual stock.move. Back orders would be created by comparing the two.
Or it could just as well be considered the other way round: we could add a distinct "Picking Line" object between stock.picking and stock.move: it would contain the required products and quantities, with a o2m relation to stock.move representing the actual stock moves.

---
Another possible approach : make the main views read-only and move all the features to the "process" wizard
Moving everything to the wizard has several problems. First it's not consistent with the rest of OpenERP. Moreover, it makes data volatile, which can be a real problem for complex cases and data that take long to key in.

---
If the user will be making several changes to the move lines in a picking, then you might consider letting him edit the lines in the tree view like some of the accounting screens do. Even without that, this still sounds like an improvement over the wizards, but the wizards did let the user edit all the prices at once, for example.
~ Don Kirkby
=> Thanks for the suggestion, we've proposed a few changes to the trunk to help this: lp:~numerigraphe/openobject-addons/trunk-stock-editable-compatible-picking-line

(?)

Work Items