On the commit 69dcdd4, the order='create_date desc'
was removed and the way of getting the MO for the notification changed. Now, the context is used, it should be written_after instead of written_date.
In addition, the now declaration should be at the beginning of the method action_replenish.
(The MO created is correct, only the notification is wrong)
Should be forwarded
OPW-2877457
closesodoo/odoo#96986
X-original-commit: 029da238a2baaf59bdf9ae828a4739ee4a9f3ede
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
On the commit 69dcdd4, the order='create_date desc'
was removed and the way of getting the MO for the notification changed. Now, the context is used, it should be written_after instead of written_date.
(The MO created is correct, only the notification is wrong)
OPW-2877457
closesodoo/odoo#96856
X-original-commit: b80287b265a4c01babedcbb58459c35d36a48066
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
When a user exports a picking with the option 'import-compatible', he
won't be able to import the record later.
To reproduce the issue:
(Need stock. Use demo data)
1. Inventory > Operations > Transfers
2. Select a transfer (without opening it)
3. Action > Export:
- Enable the option "import-compatible"
- Add the field "Operation Type"
- Export the transfer
4. Back to the transfers list view, click on Import
5. Load the exported file and click on Test
Error: An error message is displayed ("No matching record [...] in field
'Operation Type'"). However, the option "import-compatible" was enabled
and the operation does exist, so the record should be found.
When exporting a record, if one of the selected fields is a relational
one, we use its `display_name` as value:
https://github.com/odoo/odoo/blob/5797fd80a63309269f15bcbe4948d4429a53eec2/odoo/models.py#L883-L886
Then, when importing, we use `name_search` to retreive the record:
https://github.com/odoo/odoo/blob/662ecf4e20ceab92b62804cb2a06e51f6b897623/odoo/addons/base/models/ir_fields.py#L406
Back in the use case: if an operation type has a warehouse, its display
name will be the combination of the warehouse name and its name:
https://github.com/odoo/odoo/blob/b6833702044b0d3057d543dae71fbea7ef091d98/addons/stock/models/stock_picking.py#L146-L151
However, the `_name_search` does not handle this type of search key:
https://github.com/odoo/odoo/blob/b6833702044b0d3057d543dae71fbea7ef091d98/addons/stock/models/stock_picking.py#L157-L164
Therefore, using that value ("Warehouse: Operation name") in this
`name_search` will not work.
According to the review from odoo/odoo#95526, such a model is considered
as broken: "if the display name (`name_get`) is overridden, then the
`name_search` should be overridden to match". Moreover, the generic
solution proposed in the previous PR would not work in case of
multi-warehouses.
OPW-2739786
closesodoo/odoo#96768
X-original-commit: 456784ca98b3e3bc30c40b1cffe46574930ae492
Signed-off-by: Adrien Widart <awt@odoo.com>
Signed-off-by: Tiffany Chang <tic@odoo.com>
When canceling a transfer, all its moves and move lines having qty done
(if any) are canceled as well. But this doesn't happen on package levels
having such move lines with qty done filled, the state was set to
'confirmed' while all its move lines are 'cancel', which was not
consistent.
closesodoo/odoo#96764
X-original-commit: d9b16c3732c7e935c21a0396bb01ed4f19456827
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
When receiving more than expected, we try to redirect the SM thanks to
the putaway rules. This can lead to undesirable behaviors.
To reproduce the issue:
1. In Settings, enable 'Storage Locations'
2. Create a storable product P
3. Edit the operation type "Receipt":
- Show Detailed Operations: True
4. Create and confirm a planned receipt for 1 x P
5. In the Detailed Operations:
- Set the done quantity to 3
- Set the destination location to Shelf 1
6. Validate the receipt
Error: The destination location of the SML has changed: Stock. It should
still be Shelf 1
When validating the SM, because the done quantity is more than the
demand, an exra-move is created. During such a process, the extra move
is confirmed and assigned, so it leads to the destination redirection
thanks to the putaway rules (that's the reason why the destination Stock
will be selected and defined on the SML).
In such situation, we should not try to apply the putaway rules.
OPW-2900283
closesodoo/odoo#96124
X-original-commit: 0183298293192538a801f52262c047ea34a1b76a
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
Adding a @depend decorator on product_id in the stock_move_line model can trigger a search on stock.move.line.product_id
When the number of StockMoveLine reach a million, a simple `SELECT id FROM stock_move_line WHERE product_id = XXX` can take 200ms.
When a transfer contains a few hundred StockMoveLine (ex: when dealing with serial numbers), the process of validating it will take a few minutes.
Indexing product_id will change the process time back to a few seconds.
OPW-2893131
closesodoo/odoo#95511closesodoo/odoo#95915
X-original-commit: b8156cf9a2d01448244c306c24c3c55687fd0d23
Signed-off-by: DavidFesquet <dafr@odoo.com>
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Christophe Monniez (moc) <moc@odoo.com>
Signed-off-by: Rémy Voet <ryv@odoo.com>
In a multistep configuration, decreasing the quantity on a line of a
confirmed sale order may create some inconsistencies.
To reproduce the issue:
1. In Settings, enable "Multi-Step Routes"
2. Edit the existing warehouse:
- Outgoing Shipments: 3 steps
3. Create a storable product P
4. Set the on-hand qty to 5
5. Create and confirm a sale order SO with 5 x P
6. Process the PICK/PACK pickings
7. Edit the SO:
- Decrease the qty: 3 x P
8. In the SO's deliveries, open the return of the pack step (Output ->
Packing)
- Error: Nothing changes, there isn't any reserved quantity.
However, there are currently 5 x P at the Output location, so the
reservation should work
9. Inventory > Report > Stock Moves, list all SM related to P
- Error: The origin/destination moves of the pack's return (Output
-> Packing) are incorrect too: the origins contain the pick's return
(Packing -> Stock) while it should not contain anything and the
destination moves contain the ship move (Output -> Customer) while it
should contain the pick's return (Packing -> Stock)
`SM_ship`: SM used to deliver from Output to Customers
`SM_ret_ship`: SM used to return P from Customers to Output
`SM_ret_pack`: SM used to return P from Output to Packing
`SM_ret_pick`: SM used to return P from Packing to Stock
When confirming a move, we transform the move if its demand is negative:
https://github.com/odoo/odoo/blob/53b424d9e43b07fe7aa84ff00035fb7772ef6291/addons/stock/models/stock_move.py#L1239-L1247
We reverse the source/destination locations but we don't do the same
with the origin/destination moves. That is an issue: before reversing,
we have:
| SM | Qty | From | To | Origin | Destination |
|-------------|-----|---------|-----------|-------------|-------------|
| SM_ret_pick | -2 | Stock | Packing | / | SM_ret_pack |
| SM_ret_pack | -2 | Packing | Output | SM_ret_pick | SM_ret_ship |
| SM_ret_ship | -2 | Output | Customers | SM_ret_pack | / |
Therefore, reversing the source/destination locations without updating
the origin/destination moves does not make sense: we should reverse them
too depending on their direction (positive/negative) and their
source/destination location.
Also, before trying to transform the moves, we try to merge them:
https://github.com/odoo/odoo/blob/53b424d9e43b07fe7aa84ff00035fb7772ef6291/addons/stock/models/stock_move.py#L1236-L1237
This is relevant for `SM_ret_ship`: we find an existing SM (`SM_ship`,
qty=5) that can absorb the negative demand of `SM_ret_ship` (qty=-2). In
such case, we add the origin/destination moves of the negative SM to the
positive one. However, in the above case, it will create an
inconsistency: after the fix, at that point, `SM_ret_pick` and
`SM_ret_pack` have been correctly reversed, so we have:
| SM | Qty | From | To | Origin | Destination |
|-------------|-----|---------|-----------|-------------|-------------|
| SM_ret_pick | 2 | Packing | Stock | SM_ret_pack | / |
| SM_ret_pack | 2 | Output | Packing | SM_ret_pack | SM_ret_pick |
| SM_ret_ship | -2 | Output | Customers | / | SM_ret_pack |
| SM_ship | 5 | Output | Customers | (SM_pack) | / |
Therefore, adding `SM_ret_pack` to the destination moves of `SM_ship` is
incorrect. (Note that, without the fix, `SM_ret_pack` would be added to
the origins of `SM_ship`, which would be incorrect too)
Finally, the reservation (step 8) does't work because of two reasons:
- If there are some `move_orig_ids`, we use the done value of these SM
to assign the current SM. However, as explained above, there is an issue
with this field
- If there isn't any `move_orig_ids`, there is an issue with the procure
method. Its value is `make_to_order`: we skip the reservation for such a
value:
https://github.com/odoo/odoo/blob/53b424d9e43b07fe7aa84ff00035fb7772ef6291/addons/stock/models/stock_move.py#L1499-L1501
OPW-2889679
closesodoo/odoo#95263closesodoo/odoo#95926
X-original-commit: fb94c140a91aca26a56c5162d61b00b4a4b0d85b
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This follows revision
odoo/odoo@9925c8fbaf
On creation of an orderpoint,
if warehouse and location are not specified,
set default warehouse and location
if warehouse is specified but not location,
set default location according to the warehouse chosen
(and not the location of the default warehouse, as formerly)
if location is specified, but not location,
set default warehouse according to the location chosen
(and not the default warehouse, as formerly)
if warehouse and location are specified,
let them, do not overwrite them.
closesodoo/odoo#95851
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Convert the onchange on `picking_type_id` to a compute field
This allows to create a `stock.picking` record without
the need to specify the locations during the creation nor calling the onchange
method. The locations defaults from the picking type locations.
This way, if the database is not configured to use multi locations,
the users do not have the specify the UOM to use.
For instance during an XMLRPC call to create a picking.
closesodoo/odoo#95423
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This allows to create a stock.package_level record without
the need to set the `location_dest_id` during the `create` call.
For instance, this makes easier to create a package level
using XMLRPC when you do not use multiple locations.
closesodoo/odoo#95361
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This allows to create a stock.warehouse.orderpoint record without
the need to call the onchanges to set the warehouse and location
or to set it manually during the `create` call.
For instance, this makes easier to create orderpoints
using XMLRPC when you do not use multiple locations.
closesodoo/odoo#95352
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This allows to create a stock.move record without
the need to call the onchanges to set the uom
or to set it manually during the `create` call.
This allows to create a stock.move.line record
without the need to call the onchanges to set the uom and locations
or to set it manually during the `create` call.
For instance, this makes easier to create stock moves
using XMLRPC when you do not use multiple UOMs or multiple locations.
closesodoo/odoo#95332
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Fixes 38bfbed
We cannot create a `set` from `None`
```
File "/home/odoo/src/odoo/15.0/addons/stock/models/stock_production_lot.py", line 225, in <listcomp>
delivery_ids.update(*[set(delivery_by_lot.get(lot_id)) for lot_id in (producing_move_lines.produce_line_ids.lot_id - next_lots).ids])
TypeError: 'NoneType' object is not iterable
```
Small optimization: no need to create a list that's immediately unpacked.
This error was detected during upgrades.
upg-360084
closesodoo/odoo#95398
X-original-commit: 1870ef4cf4c177846fce72325ff3f2fa97224417
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: Tiffany Chang <tic@odoo.com>
Signed-off-by: Alvaro Fuentes Suarez (afu) <afu@odoo.com>
Rewrite _find_delivery_ids_by_lot to reduce the number
of recursive calls by grouping the producing move lines
together before each recursive calls. This reduces
the number of search calls, speeding up the whole method.
Add a unittest to check if the delivery_ids field
of a lot recordset is properly computed.
opw-2824464
X-original-commit: e7b9f14d4a9ce4ed61451b24b567f751fb4bcbe2
Part-of: odoo/odoo#95398
Updating the scheduled date of a delivery doesn't update the quantity to
order of an orderpoint
To reproduce the issue:
(Need purchase)
1. Create a storable product P with a seller
2. Create and confirm a planned delivery D with 1 x P
3. Open the replenishment page
- There should be a line for P (Forecast: -1, To Order: 1)
4. Edit D and postpone the scheduled date
5. Go back to replenishment page
Error: The line is still present, its forecast qty is correct (0) but
the quantity to order is still 1 (instead of 0)
`qty_to_order` is a stored field, so when loading the replenishment
page, its compute method is not called. Moreover, even though
`qty_to_order` depends on `qty_forecast` and the compute method of
`qty_forecast` is called, it still won't trigger the compute:
when setting the value of `qty_forecast` from its compute method, it
will lead to:
https://github.com/odoo/odoo/blob/b54f78de307543efcea934206806f361eaac811a/odoo/fields.py#L1106-L1109
So, as shown and explained, we bypass the `write` of `BaseModel` and
skip the business logic and the recomputations
The compute of `qty_to_order` should actually be triggered earlier: when
we edit the scheduled date (step 4). That's the reason why this commit
adds a dependency to the compute of `qty_forecast`: it makes more sense
and becomes an implicit dependency of `qty_to_order` -> update the
scheduled date will trigger the compute of `qty_to_order`
OPW-2868167
closesodoo/odoo#94400
X-original-commit: 791b68fc02cbc4dc5b376e5fc5d37e725f88d0dc
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
In picking type, we introduce a new setting ask-always-never setting for
creating backorder. When a backorder is needed, the behaviour will be
different according to this setting:
- ask: popup a wizard to ask if a backorder is needed
- always: generate backorder automatically
- never: no backorder
The main reasoning behind this change is that there are some scenarios
in which operators always create backorders (e.g. by validating the
transfer after scanning a pallet and setting quantities). Hence, always
asking if the user (operator) wants to create a backorder can be confusing.
task-2648993
Part-of: odoo/odoo#83462
Sorting the `stock.quant` by lot_id didn't work correctly
Steps to reproduce:
1. Install Inventory
2. Edit a product tracking to 'By Unique Serial Number' (e.g. Acoustic
Bloc Screens)
3. Go to Inventory > Overview > Receipts, create a receipt for 3
Acoustic Bloc Screens with serial number '05', '01' and '03' and
validate
4. Go to Inventory > Reporting > Inventory Report, remove the
'Group By' filters and sort the entries by Lot/Serial Number
5. The serial numbers are not properly ordered ('01' is between '03'
and '05')
Solution:
Order the `stock.production.lot` by name
Problem:
Sorting the `stock.quant` by lot_id used the id of
`stock.production.lot`
opw-2879464
closesodoo/odoo#94358
X-original-commit: 4c855bd3eeb7ffcebd76eb4eaa1e41edf2935021
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
Avoid leaks in case of exception.
closesodoo/odoo#93993
X-original-commit: 1a1a10b7ce53f24eabed3e3a38f34b354d2d1911
Signed-off-by: Christophe Simonis <chs@odoo.com>
Currently, certain fields take the decimal accuracy of the product_uom
whilst other's don't follow this logic.
This causes a discrepancy between the decimal accuracy of all fields
where there should be none.
The purpose of this commit, is to stay consistent across all fields in
the view.
closesodoo/odoo#93935
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Steps to reproduce the product:
- Create a new product:
- Select “Service” type
- Go to the Sales tab:
- Select "Create a task in an existing project" in the `service
tracking` field
- the `project` field becomes visible
- Change the Type of the product to “Consumable”
- Try to save
Problem:
The field `project` remains visible and as it is a required field,
we have to fill it in before being able to save the product.
While it is a feature only for service-type products
Solution:
- The `project` field is based on the `service_tracking` field
to become invisible or not. So when the product is not of service type,
we must remove the tracking service so that the project field
becomes invisible.
- Prevent the user from changing the type of products already used in
a sale order
opw-2858064
closesodoo/odoo#93804
X-original-commit: 102951140e3f35ced8653d4bedb82b63bb2c963f
Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com>
Signed-off-by: Djamel Touati (otd) <otd@odoo.com>
- Install stock
- Go to Inventory > Configuration > Settings and enable "Lots" and "Storage Locations"
- Create a Product tracked By Lots (i.e. Product X)
- Go to Inventory > Operations > Inventory Adjustments
- Create an Inventory Adjustment for Product X:
Product | Location | Lot/SN | Real Quantity
-------------------------------------------------------------
Product X | WH/Stock | LOT 01 | 20
Product X | WH/Stock | | 10
- Validate Inventory
- Go to Inventory > Operations > Transfers and create one:
* Source Location: WH/Stock
* Destination Location: WH/Stock/Shelf1
* Operation Type: Internal Transfers
* Operations:
[Product: Product X, Initial Demand: 25]
- Save Transfer, Mark As Todo and Check availability
- Click on list icon of Operation line for Product X to display Detailed Operations
- 20 units of LOT 01 and 5 units without lot have been reserved
- Set LOT 01 for the 5 reserved units without lot and confirm
- Open Detailed Operations again
- There are now 20 units of LOT 01 and 5 units of LOT 01
- Remove the row with 5 units and confirm
- Check availability and open Detailed Operation
- There is now only a row with 25 reserved units of LOT 01
- Unreserve
The following errror is raised:
"It is not possible to unreserve more products of P than you have in stock."
It happens because the system is not able to manage quants with lots and
wihtout lots at the same time. When modifying the move line to 25
reserved units. It's composed of 20 quants with lot and 5 quants without
lot. And when unreserving it will check if there is a quants with 25
units with the lot and if it's not found 25 units without lot. But never
25 units of quants with lots and without lots.
opw-2419444
Close#64497closesodoo/odoo#66029closesodoo/odoo#93141
X-original-commit: 83d55d8ed8b8b5a5232e3cdfc09abf5285f18ed7
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Since https://github.com/odoo/odoo/pull/86682, when a user opens
the replenishment view, the Days to Purchase are not taken into
consideration when calculating the forecast of a product.
This was due to the fact that the Days to Purchase are now taken from the
orderpoint and not from the company settings. This is fixed by taking
the company setting if no value from the orderpoint is sent to the
method.
closesodoo/odoo#93252
Task-id: 2871408
X-original-commit: ac1df1949e4523aff65543f1381300fc7de3b4e4
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Signed-off-by: npi-odoo <npi@odoo.com>
account.account: code was already in unique constraint
account.journal: inverting compound unique constraint to benefit from indexing company_id
hr.employee: user_id already in unique index
phone.blacklist: number already in unique index
stock.orderpoint: product_id already in unique constraint/index
closesodoo/odoo#92932
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
- Add the concept of 'Days to Prepare MO' in mrp, similar to 'Days to
Purchase' but defined at the product level. Both concepts are merged into
Days to Order at the orderpoint level, taking the value of Days to Purchase
for orderpoints with a buy route and Days to Prepare MO for orderpoint with a
manufacturing route.
- Add the concept of 'Visibility Days' on orderpoints. The idea is to
avoid to create through reordering rules multiple small orders for the
same product on a small time frame but rather to order directly a bigger
quantity. When Visibility Days are defined, the quantity of the orders
created by a RR is not the quantity forecasted at Today + Lead times
(quantity that triggered the order according to the RR), but the
quantity forecasted at Today + Lead Times + Visibility days.
The Visibility Days are different for purchase and manufacturing.
Changing the route of the orderpoint will change its value. They
can be defined at the company level and further fine-tuned on the
orderpoint. In case of change of the parameters at the company level,
only orderpoints without a specific value of Visibility Days will
be changed.
- Alignement between Manufacturing and Purchase Security Lead Time
(previously the Manufacturing Security Lead time didn't impact the
procurement date, instead the manufacturing time was made longer).
closesodoo/odoo#86682
Task-id: 2738838
Pr: https://github.com/odoo/odoo/pull/86682
Related: odoo/upgrade#3415
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
following commit 55398263f9297ab2709e4c4c2a9c6c3ee7f59c8a
Introduce a new param to fix a notification issue. However
we could use the context instead of a new parameter in order
to avoid breaking the customisation.
Linked to PR #88303 discussion
closesodoo/odoo#92353
X-original-commit: 69dcdd410adcefe29bfa4fecd2e7c50fe3465b19
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
When moving some products between two warehouses thanks to an internal
transfer, the forecasted inventory becomes incorrect
To reproduce the issue:
1. In Settings, enable "Multi-Warehouses"
2. Let WH01 be the existing warehouse. Create a second one WH02
3. Create a storable product P
4. Update the quantity of P:
- 3 in WH01/Stock
5. Create a planned and internal transfer T:
- Source: WH01/Stock
- Destination: WH02/Stock
- Ignore the warning
- Operations:
- 1 x P
6. Mark T as todo
7. Open the Forecasted Inventory:
- Filters:
- Forecasted Stock
- Product: P
- Group By: Warehouse
Error: The report is incorrect, it says there are 3 P in WH01 and 0 in
WH02 (should be 2 and 1). It becomes worst if T is done (the quantities
in the past become incorrect)
We should be able to move a product between two warehouses thanks to an
internal transfer (so the warning of the step 5 should be removed).
Moreover, the `report.stock.quantity` should consider that use case.
When processing a stock move, the SQL view translates it as an in-move
or out-move for a specific warehouse. For instance, if the SM comes from
a warehouse and goes to a location without any warehouse (e.g., customer
location), the SM is considered as an out-move. But here is the issue:
in case of an inter-warehouse SM, both source and destination have a
defined warehouse.
Therefore, we need to:
- Duplicate the inter-warehouses SM (so we have one in and one out)
- Fake the values (no destination warehouse for the out move, no source
warehouse for the in move)
Also, before duplicating all SM, we filter out some useless SM:
- Draft and cancelled ones
- SM done more than 3 months ago (because the report only works for [-3
months; +3 months])
Considering some tests:
(SM are confirmed. Each test has been repeated 5 times to get an
average)
| | |
|:-------------------------------------:|:--------:|
| 5000 SM, 0% inter-wh, without the fix | ~715 ms |
| 5000 SM, 0% inter-wh, with the fix | ~710 ms |
| Impact | 0.99x |
| | |
| 6666 SM, 0% inter-wh, without the fix | ~911 ms |
| 5000 SM, 33% inter-wh, with the fix | ~999 ms |
| Impact | 1.10x |
| | |
| 7500 SM, 0% inter-wh, without the fix | ~1004 ms |
| 5000 SM, 50% inter-wh, with the fix | ~1097 ms |
| Impact | 1.09x |
The impact is not that significant
OPW-2752017
task-2822157
closesodoo/odoo#91772
X-original-commit: b1efc0243bbf886bbef42a32587f4a818fa34e64
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit will correct the precision_rounding parameter in the float_compare call to use the current move's product. Previously, this was using the product_id variable from a previous for loop.
An issue is caused when a transfer is created from `mts_else_mto` procure methods in stock.rule records. When the '_adjust_procure_method' hits a rule with this procure method, it reaches the 'mtso_moves' for loop. The needed quantity and forecasted quantity will be compared to decide whether a stock.move record is needed to fulfill the needed amount.
The problem is that the 'float_compare' method is using 'product_id' to set its precision_rounding method. The 'product_id' variable is only accessed in the prior for-loop and will always reference the final product iterated. As a result, any case where there are product quantities smaller than the final product's UoM, it is skipped.
opw-2820401
closesodoo/odoo#91361
X-original-commit: 892232b5aef42dd2706cb9d1d027b1c463ca50dd
Signed-off-by: Arnold Moyaux <arm@odoo.com>
When clicking order now on a replenishment line (orderpoint) for a manufacture or WH resupply route, it will sometimes show a notification for a purchase order that was created earlier instead of the correct one.
closesodoo/odoo#91404
X-original-commit: 9ca9bcc51fa289ddb0548f81a795755d196e31ca
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Tiffany Chang <tic@odoo.com>
The auto-reserve feature does not work if the products are received in
several steps
To reproduce the issue:
1. In Settings, enable "Multi-Step Routes"
2. Edit the existing warehouse:
- Incoming Shipments: 2 steps
3. Create a storable product P
4. Create and confirm a SO with 1 x P
- The delivery D is created and is waiting for one available P
5. Create and validate a receipt for 1 x P
- An internal transfer T is generated (Input -> Stock)
6. Validate T
7. Open D
Error: The delivery is still waiting for the product while this product
should be reserved. This is correctly working in 1-step receipt
In 1-step receipt, when the user marks the receipt as done, the
destination of the associated SM is WH/Stock and its operation type code
is "incoming". Therefore, the module checks if some other moves (from
WH/Stock) can reserve the newly-available quantity.
However, in [2/3]-steps receipt, the operation type code of the
in-WH/Stock move is "internal". So, the conditions are not respected and
the module doesn't check the needs of reservation.
OPW-2806423
closesodoo/odoo#90715
Signed-off-by: Tiffany Chang <tic@odoo.com>
A user should be able to scrap some products thanks to an internal
transfer.
To reproduce the issue:
1. In Settings, enable "Multi-Step Routes"
2. Create a storable product P and update its quantity (> 1)
3. Create a planned and internal transfer T:
- From: WH/Stock
- To: Virtual Locations/YourCompany: Scrap
- With: 1 x P
4. Mark T as done
Error: T is still in draft
The `_compute_state` of a picking should not ignore the scrapped moves.
However, if we include them, we need to think about this use case: a
picking with a cancelled normal move and a done scrapped move -> its
state should be cancelled (see use case and test from [1])
[1] 429b589618e8dc2b0c0ccdec3f6eed88f1c73fc8
OPW-2841190
closesodoo/odoo#90870
X-original-commit: 1c956d49b45e9d3fec2bfa2c2020ea278ea80507
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
When triggering an inter-warehouses reordering rule, the partner of the
receipt is incorrect. When triggering several inter-warehouses
reordering rules, it will remove the partner of both receipt and
delivery
To reproduce the issue:
(Let C be the current company)
1. In Settings, enable "Multi-Step Routes"
2. Let WH01 be the existing warehouse. Edit WH01:
- Set a new address ADD01:
- Type: Individual
- Company: C
- Address Type: Delivery Address
3. Create a new warehouse WH02:
- Set a new address ADD02:
- Type: Individual
- Company: C
- Address Type: Delivery Address
4. Edit WH02:
- Resupply From: WH01
5. Create 2 products PA, PB:
- Type: Storable
- Routes:
- WH02: Supply product from WH01
6. For product PA:
- Update the quantity:
- 10 in WH01/Stock
- Add a reordering rule:
- Location: WH02/Stock
- Trigger: Manual
- Min = Max = 1
7. Run the scheduler
- It generates a delivery D and a receipt R
8. Open R
- Error 01: the field "Receive From" is incorrect (ADD02 instead of
ADD01)
9. Repeat step 6 for PB and run the scheduler again
- Error 02: R and D have no more partner
Error 01: see diff
Error 02: we have two SM (one for PA, one for PB) that have a different
origin (one per reordering rule). Therefore, we remove the origin of the
pickings. However, we also remove the partners while we shouldn't
OPW-2733989
closesodoo/odoo#90706
X-original-commit: 20e0ad13afa2a0ff85d555ab57a6800d3db30341
Signed-off-by: Tiffany Chang <tic@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
Steps to reproduce:
- Create two extra warehouses (B and C):
* Warehouse B: Resupply from San Francisco
* Warehouse C: Resupply from San Francisco
- Create a new Product:
* Storable
* Inventory > Routes: select only Warehouse B and Warehouse C
- Create a new Move:
* From WHC to a Customer
* Confirm the order
Issue:
In replenishment, the defined prefered route will be Warehouse B
Cause:
When the replenishment view is loaded, in
https://github.com/odoo/odoo/blob/5757502a79c920e1aa4c7ca1c581c533907ce674/addons/stock/models/stock_orderpoint.py#L427
The preferred route (route_id) is defined as the first element of the routes defined for the produc which is wrong.
Solution:
Filter the route_ids by selecting the route for which the supplied warehouse is equal to the warehouse selected for the orderpoint.
Note:
1) The test in "test_bom" has been modified because it was using the wrong flow (a route should have been set by default)
2) In Master we only use the _set_default_route method
opw-2815462
closesodoo/odoo#90560
X-original-commit: 15b04d616a5196192a96e6bf2114698b34654348
Signed-off-by: Adrien Widart <awt@odoo.com>
Signed-off-by: yosa-odoo <yosa@odoo.com>
Current behavior:
When 2 steps delivery and product packing is activated, and have 2 kit products that have common components.
If you create a sale order with those 2 kits and pack them in the first step of the delivery. And in the second delivery step mark the pack as done the done quantity in the package
are not correct.
Before this fix, all the products quantities from different kits were on the same stock move line and the other lines were ignored,
this result in lines with too much products and lines with no product. When validating this
incorrect transfer an unnecessary backorder was created and the sale order lines were not correctly marked as delivered.
Steps to reproduce:
- Activate 2 steps delivery and product packing.
- Create Kit A with Component A and Component B
- Create Kit B with Component A and Component B
- Create a SO with 1 Kit A and 1 Kit B
- Confirm the SO
- Go in the first step of the delivery and put everything in a pack
- Go in the second step of the delivery and set the pack as done
- Go in the package details : The first component A has 1 reserved and 2 done, same for component B
opw-2754106
closesodoo/odoo#90033
X-original-commit: b81f70babc774eff2e04d2f7854d75ec7273a757
Signed-off-by: Engels Robin (roen) <roen@odoo.com>
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Refactor the `load_views` API so it no longer sends multiple times the same
fields description.
e.g.
When `load_views` is called to get the kanban, tree and form views,
the list of fields of the model was sent 4 times:
- Once for each view, with only the fields used in the view,
in `['fields_views']['kanban']['fields']` for instance
- Once globally, with all the fields of the model, in `['fields']`
The goal of this revision is to change that so it sends the list of all fields
only once.
In addition, if a view contains x2many fields,
the fields description of the comodel is also sent.
It was sent in the `views` key of the view fields dict.
e.g.
When calling `load_views` of `res.partner` to get the kanban,
tree and form views,
the `res.partner` fields description was actually sent 6 times:
- Once for each view
- Once globally
- Once for each view of the many2many field `child_ids` of the form view, in
- `['fields_views']['form']['fields']['child_ids']['views']['kanban']['fields']`
- `['fields_views']['form']['fields']['child_ids']['views']['form']['fields']`
The change suggested in this revision is to:
- Remove the fields description for each view in `['fields_views']`.
As it no longer contains the fields,
the key becomes `['views']` instead of `['fields_views']`.
- Replace the dict key `['fields']` by `['models']`,
which is a dict with as key the model name and as values
the model fields description. It contains the fields description
for all models implied in the view:
the model of the main view and the model of all one2many and many2many fields.
With this change, the fields description will only be sent once by model
implied in the view.
In addition, the web client was getting the information about the fields
sometimes in the global fields description list (e.g. `['fields']`),
sometimes in the fields description list of the view type
(e.g. `['fields_views']['form']['fields']`),
making it a pain to try to make changes / performance gain
in these field description dictionaries, because you never knew in which dict
the web client was getting its info.
Now, as there is only one place to get the fields description from,
it's clearer and cleaner.
- one2many and many2many fields views are passed directly in the main view
architecture rather than being put in the `views` key
of the field description.
This is actually easier to treat by the web client,
and this will allow in a future work to cache an entire view in one block
of text rather than having to combine multiple cached blocks of text
to return one view.
- one2many and many2many fields which do not have directly embedded views
have their views directly injected in the architecture,
so the web client doesn't have to do RPC calls to `load_views`
for each one2many and many2many fields not having embedded views.
For instance, this allow to reduce the number of RPC calls to `load_views`
from 8 to 1 when loading the form of `product.product`.
Currently, this behavior is limited to 1 level deep but we consider making it
go all the way down in future works. We did not do it for the moment because
in certain cases it rises the processing time and the size (bytes) too much.
e.g. the sale.order view can be 5 levels deep,
meaning you can reach 4 dialogs on top the main view.
```
sale.order form > order_line > sale.order.line form > invoice_lines >
account.move.line form > asset_ids > account.asset form >
depreciation_move_ids > account.move form.
```
This will also benefit in future works to cache an entire view in one block
of text rather to having to combine multiple cached block of text
to get one view.
- `fields_view_get` becomes `get_view`.
As it no longer returns the fields description,
keeping the `fields` in the name `fields_view_get` no longer makes sense.
Hence removing `fields` from the method name, it becomes `view_get`.
As it gets renamed anyway, we take the opportunity to rename it `get_view`,
which is more in line with the general getter/setter guidelines
in the model object world.
- `_fields_view_get` becomes `_get_view`. For the same reasons than above.
- `load_views` becomes `get_views`.
This is not mandatory, there is no technical reason to rename `load_views` as
it practically sends the same info as before,
the view architectures and their fields description. Just in another way.
We just take the opportunity of this pull request to suggest a cleaner API:
`_get_view`, `get_view` and `get_views`.
- Arguments `toolbar=False, submenu=False` fo the methods
`_fields_view_get` and `fields_view_get` are converted to a kwargs `**options`
in `_get_view` and `get_view`.
The rationale is that submenu was already no longer used (deprecated)
and the mobile options is introduced.
The mobile options is necessary to tell the server to send the mobile views
for x2many fields (kanban instead of tree).
Instead of adding a new argument each time we add a new option to
`fields_view_get`, it seems wiser to have a kwargs `**options` to avoid
to re-write all overrides each time a new option is introduced.
- `_fields_view_get` returned a dict containing the arch in text and some of the
view information. Now, `get_view` returns a tuple with the view architecture
as an `etree` node, and the view as a browse record. The rationale is that all
overrides of `_fields_view_get` were about modifying the arch only
(e.g. changing the address format/re-organizing the address related field
nodes of the partner according to the company country).
To do so, all these overrides were doing `etree.fromstring` to parse the arch
which was sent in text to convert it to an `etree`,
then operations were done on the `etree`,
and then `etree.tostring` was called to convert back the arch to string.
With this change of signature to send the arch as an `etree`,
all these back and forth `etree.fromstring` -> `etree.tostring` are avoided,
allowing some performance gain and less code in the end.
- A cleanup of the keys returned in the dict of `fields_view_get`
has been performed in `get_view`:
- `fields` is removed, as explained above,
- `view_id` is renamed `id`,
- `name` is removed, it was unused by the web client,
- `type` is removed, it was unused by the web client,
- `field_parent` is removed, it was unused by the web client,
- `base_model` is removed, it was unused by the web client.
- `filters` is moved from the global dict returned by `load_views`
(now `get_views`) to the dict returned by `fields_view_get` (now `get_view`)
as it applies only to the `search` view type.
- Retro-compatible methods for the 3 methods
`fields_view_get`, `_fields_view_get` and `load_views` are provided,
with deprecation warnings in them.
- The web client could cache the model fields description
(as it already caches the views),
so it doesn't need to fetch them again if it asks for another view of a model
for which he already has the fields description.
If we do so, `get_views` could return only the list of models used by
the views, without the fields description as of now,
and the web client would then call `fields_get` independently only for
the models for which it doesn't have yet the fields description.
This would avoid the server to return the fields description
and to call `fields_get`, which is costly, for each `get_views`,
therefore gaining performances.
- Inject the views of the one2many and many2many fields all the way down,
unlimited depth level, as explained above.
- Cache with `ormcache` the architecture of back-end views.
This is already done for qweb views, it's not done for back-end views.
Therefore the postprocessing of the views is performed for each `get_views`,
which is costly, while the view architecture doesn't change for users
belonging to the same groups, according to the groups implied by the view.
This pull request is co-authored by
Aaron Bohy (aab) for the web client part and
Denis Ledoux (dle) for the server part.
Part-of: odoo/odoo#87522
Cancelling a picking with scrapped and done SM will cancel this SM too.
To reproduce the issue:
1. In Settings, enable "Storage Locations"
2. Create a storable product P
3. Update the quantity of P: 10 in WH/Stock
4. Create a planned delivery order DO with 2 x P
5. Mark DO as todo, Check availability
6. Scrap 2 x P
7. Cancel DO
8. Open the SM of the scrapping
Error: The SM is cancelled. This is incorrect: the move was done, so
there is a quant with 2 x P in scrap location. There is now an
incoherence between quants and SMs report.
OPW-2805604
closesodoo/odoo#89987
X-original-commit: bd3324acc3ec227438d2cb25a1df1e0fca2a2789
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
When trying to absorb quantity from a negative move, the product_uom_qty
of the negative move is updated several times (n-1 times if n positives
moves are required to fully absorb the quantity).
All these updates trigger the write() method, which would then log a
message in the picking because the move quantity is updated. This is
valid for positive moves as their quantity is truly updated, but for the
negatives during merge it is a temporary state, before either being
fully absorbed or create a backorder.
Also, in the case of multiple negative moves processed in a single
_merge_moves() call, merged moves would get all move_dest_ids &
move_orig_ids instead of only the ones of the merged move.
closesodoo/odoo#88047
X-original-commit: cc03ec1dea2cf5d3aab9ccfe92fd3e09a4c16044
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Quentin Wolfs (quwo) <quwo@odoo.com>
The putaway strategies are not correctly working with packages
To reproduce the issue:
1. In Settings, enable:
- Multi-Step Routes
- Storage Categories
- Packages
2. Create a Storage Category SC:
- Allow New Product: mixed
- Max Weight: 100 kg
- Capacity by Package:
- 1 x Pallet
3. Create two locations L1, L2:
- Parent: WH/Stock
- Type: Internal
- Storage Category: SC
4. Create a putaway rule:
- When in: WH/Stock
- Package type: Pallet
- Store to: WH/Stock
- Having Category: SC
5. Edit the warehouse:
- Incoming Shipments: 2 steps
6. Create a product P:
- Type: Storable
- Weight: 1 kg
7. Create a planned receipt R:
- To: WH/Input
- Operations:
- 100 x P
8. Mark R as Todo
9. Create two packages:
- 50 x P in PK01 (! PK01 must be a Pallet)
- 50 x P in PK02 (! PK02 must be a Pallet)
10. Validate R
11. Open the related internal transfer T
- Error [1]: Both packages are redirected to L01, but the capacity
by package is 1 x Pallet. PK01 should be redirected to L01 and PK02 to
L02
12. Set the done quantity of PK01
- Note: PK01 is now redirected to L02
13. Set the done quantity of PK02
- Error [2]: PK02 is also redirected to L02. Again, it violates the
package capacity constraint
**Context**
When validating the receipt (step 10), it creates a picking
Input->Stock. The module then tries to assign some quantities, which
leads to `_prepare_move_line_vals` for each package. In this method,
`_get_putaway_strategy` is called to define the best destination of each
stock move line:
https://github.com/odoo/odoo/blob/d55a99ff2d2f7b8d44cde1db3b6d48cdaac1cd3a/addons/stock/models/stock_move.py#L1313
The computation of the best location is in 3 phases:
- Phase 01: `_get_putaway_strategy` finds the relevant putaway rules and
computes the current and forecasted stock related to the current
package/product
- Phase 02: `_get_putaway_location` checks if, considering the putaway
rule and the current package/product, a location can be used
- Phase 03: `_check_can_be_used` checks if a location can receive a
package/product (considering the weight and the capacity constraints)
**Error 01**
During the first phase, in case of a package, the forecasted quantities
are computed by searching all SML that have the same package type:
https://github.com/odoo/odoo/blob/4bae10e0d960e5b80055e0e44056493238e552d3/addons/stock/models/stock_location.py#L258-L263
This can not work. The SML used to move the product in PK01 (from Input
to Stock) is created but its field `result_package_id` is not yet
defined. This operation will be done at the of the assign process,
thanks to:
https://github.com/odoo/odoo/blob/d55a99ff2d2f7b8d44cde1db3b6d48cdaac1cd3a/addons/stock/models/stock_move.py#L1547
So, during the first phase, when searching a location for PK02, the
computations are not aware that PK01 is already sent to L01. This
explains the error [1].
**Error 01 (Other examples)**
Considering how it is currently working, we could imagine another
problematic use case: 2 different products on the same package. Since
there is one SML per product, `_prepare_move_line_vals` will be called
twice (as well as the putaway strategy process). It may lead to two
different locations while the product are on the same package.
**Error 02**
When setting the done quantity, an onchange method is triggered:
https://github.com/odoo/odoo/blob/4202e46a8313fa9f1487d372ef0cb771f769be8d/addons/stock/models/stock_move_line.py#L200-L208
and tries to find the best location, considering the done quantity. As
said before, during the first phase, it looks for the current and
forecasted stock of a location. Since it will find the SML we are
writing on, the parameter `additional_qty` is used to subtract the
quantity of this SML (we need to ignore the current SML's quantity). But
here is a new issue:
https://github.com/odoo/odoo/blob/4202e46a8313fa9f1487d372ef0cb771f769be8d/addons/stock/models/stock_move_line.py#L217-L222
`_get_putaway_additional_qty` returns the quantity of products while the
first phase is looking for the quantity of packages. As a result, we do
some operations between products and packages:
https://github.com/odoo/odoo/blob/4bae10e0d960e5b80055e0e44056493238e552d3/addons/stock/models/stock_location.py#L290-L292
`qty_by_location[location_id]` is 2 (i.e. PK01 and PK02) for L01 while
`qty` is `-50` (i.e. the 50 products of the current SML), so the value
becomes `-48`. This can not work properly because the value doesn't have
sense anymore. Later on, during the third phase:
https://github.com/odoo/odoo/blob/4bae10e0d960e5b80055e0e44056493238e552d3/addons/stock/models/stock_location.py#L340-L346
The forecasted weight is not subtracted by the quantity of the current
SML. So the weight is exceeded, this is the reason why the destination
of PK01 becomes L02 on step 12 (it will be the same on step 13)
**Additional error**
Suppose the user is receiving a tracked product (suppose qty > 1). When
confirming the picking, several SMLs are generated to "reserve" the
quantity from the customer:
https://github.com/odoo/odoo/blob/d55a99ff2d2f7b8d44cde1db3b6d48cdaac1cd3a/addons/stock/models/stock_move.py#L1469-L1471
Later on, thanks to the wizard `stock.assign.serial`, the user generates
all USN. However, because the option `show_reserved` is disabled, the
wizard creates some new SMLs. But here is the issue, the SMLs created
during the assign process are already existing. Therefore, when looking
for the best location (for the new SMLs), the existing SMLs will disturb
the result (`_get_putaway_strategy` will find these SMLs and think that
some products are already incoming in some locations)
**Solutions**
- We should compute the best locations once all SMLs are created (and
linked with their package)
- In case of a package with a type, we should try to find the best
location for the package itself, not for each product of the package
- When calling the putaway strategy process, we should provide the
SML(s) to exclude instead of providing some quantities. This will
prevent subtracting products with packages and allow the correct
calculation of the forecasted weight for each location
- When creating a putaway rule, we ensure that the option
`show_reserved` of the destination location is enabled
OPW-2746169
closesodoo/odoo#89350
X-original-commit: 98169b391f4610545b7f4745b729ad95eac3696a
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
By updating all the fields/keys retrieved by _compute_quantities_dict,
rather than just a group of hardcoded ones, it makes it possible to
efficiently extend the model to add extra fields to compute by it.
closesodoo/odoo#88049
Signed-off-by: Arnold Moyaux <arm@odoo.com>