- Create a BOM for Product A, using Component B
1 Unit of a is built with 1 Unit of B
- Update on hand quantity for B to 3.0
- Create a MO for 5 Units of A
- Update the quantity to produce to 3.0
The button 'Check Availability' never disappears.
The core of the problem is that the move remains "Partially Available".
Indeed, if there is no product available (`available_quantity <= 0`),
the stock move is skipped and its availability status is not updated.
We slightly change the logic by first checking if we need any quantity.
If not, the move can be considered as assigned.
opw-1850499
Since saas-11.2 stock_tracability refactoring do not use
level on moves orig/dest and filter on return is
not usefull anymore. It should display all return order
by date.
This commit remove the codition on the return inside the search
on move lines.
In a warehouse, mostly most of the products have no lot. It stays
important however to avoid having old products in stock, certainly if
we can distinguish them by pack or location.
As now in stable, in_date is not put on the quant for non-tracked products,
databases might mix quants with and without in_date of the same product.
We should see those without in_date as the oldest.
That is why we need to be able to apply a ASC NULLS FIRST (ASC is NULLS LAST by default) for FIFO
or DESC NULLS LAST for LIFO.
In order to do that, we copied the code from the _search method of the ORM to
be able to do this special order as the orm itself is restrictive as it
supposes the order itself has no spaces.
We adapted and added some tests to check it handles the combination of NULL/NOT NULL well.
Depending on the situation, it is possible to have move with origines
and destinations that have a loop.
A simple example is a return of a return, the origin and destination of
the return of a return is the return itself.
opw-1845444
closes#24787
When creating a new company, the fields customer/vendor location
were empty.
Now, these fields are set with the internal transit location for the company
of the partner and set with Partners Locations/Customers and Partners Locations/Vendors
for the other companies.
opw:1845753
Suppose we have a delta between two datetimes:
delta = dt1 - dt0
If delta is negative but less than a day, ``delta.days`` returns -1 (which is
compensated by positive seconds). In order to avoid this surprising effect,
use ``delta.total_seconds()`` to compute the number of days.
- Create 2 companies A & B
- Create a sequence for PO in each company
- Set User A in Company A and Admin in Company B
- Create a MTO product with a 'Buy' route
- Create a SO with User A using the product, validate
The PO created uses the sequence for Company B instead of Company A.
The creation is done as `sudo`, and ultimately `next_by_code` will use
the company of the Admin.
opw-1839656
When the reception route of a warehouse company is deleted by the user
e.g. My company, Chicago Receipt in 1 step is deleted,
and then changing the given warehouse `Incoming Shipments`
multiple times
e.g. from `one_step` to `two_steps` multiple time,
the reception route is created again and again and again.
This is because the reception route which is created for the
warehouse is not being assigned to the warehouse
as the `reception_route_id` once newly created.
opw-1836544
The goal of this change is not to be able to search a location_id/warehouse_id
but to properly make these fields "dummy": only used to put some keys in context
from the search view in order to influence computed field.
Use case:
In function _compute_quantities_dict, the quantity available for a product is computed
according to the warehouse or the location. But to compute this quantity, the specific
warehouse or location must be in the context.
Steps to reproduce:
- In the tree view of product.product, write the name of a warehouse W
- Click on dropdown menu "Search warehouse"
- Click on W
Expected behavior: the quantities available for W are displayed.
NB: search=lambda operator, operand, vals: [] must be written to
ensure these fields to be searchable. Otherwise "Non-stored field
product.template.warehouse_id cannot be searched." was logged.
opw:1839961
When we change the the uom of a product, a user error is triggered if
there are already moves created for this product. But if the product is
archived, the call to mapped('product_variant_ids') doesn't return any
product ids, so no moves are found and you can change the uom.
To fix this behaviour that can lead to bad configurations, because
quants and moves won't be in the same unit than the product's one.
When the reception route of a warehouse company is deleted by the user
e.g. My company, Chicago Receipt in 1 step is deleted,
and then changing the given warehouse `Incoming Shipments`
multiple times
e.g. from `one_step` to `two_steps` multiple time,
the reception route is created again and again and again.
This is because the reception route which is created for the
warehouse is not being assigned to the warehouse
as the `reception_route_id` once newly created.
_update_routes should work the same way than _create_routes,
it should return new value to write on the warehouse.
based on preliminary by Denis Ledoux
opw-1836544
In a situation where there's a negative quant next to a positive one,
they should be merged when the scheduler runs or when the user open its
inventory view. However, if in the meantime the user reserves and
unreserves, there may be some issues.
The system will only reserve on positive quant ;
the system will unreserve on the first encountered quant (even negative)
The issue is the second part of the early break condition:
float_is_zero(available_quantity, precision_rounding=rounding):
The issue here is `available_quantity`. In a reservation scenario, it
represents the maximum quantity we can reserve across quant. It is
useful so we do not lose time loopin over quants where nothing will be
available. In an unreserve scenario however, it represented the same
thing, which is wrong. In the case you reserved all the quantities,
`available_quantity` will be 0 we'll loop only on the first quant where
we won't do anything.
As the code doesn't check the success or failure of the unreserve, move
lines were unlinked while the reserved quantity on the quants were not
updated, resulting in the desynchronization of the move lines/ reserved
quantities.
This continues the work done at [1] to track down the "cannot unreserve
more than" errors.
[1] cce6030c0d
When an internal locations has its `scrapped` field set to True,
reserving will increment the quant's `reserved_quantity` while
unreserving will bypass the reservation mechanism (as in a supplier
location). This leads to a desynchronisation between the
partially_available/available move lines and the quant's
`reserved_quantity`, leading later on to "cannot unreserve more than
available" errors.
To prevent this kind of issues, there's a `should_bypass_reservation`
method set on the location that we *should* use everywhere, it was
implemented by [0]. Sadly, this line was not adapted since its
implementaton in [1].
Co-authored by len-odoo <len@odoo.com>
opw 1837900
[0] e1cea2640f
[1] 0469d2e712
Do not try to keep the reservation when creating a backorder for two
reasons:
1) it doesn't make sense since the backordered move will only be
confirmed while it got some reserved move lines
2) with badly configured uom's rounding, it is possible that the
initial demand of the backorder is inferior to the now reserved
quantity
We also fix another "cannot unreserve more than available" cause that
could happen in the second case ; let's imagine in the second case that
the backordered quantity is 0.999, `_update_reserved_qty` will reserve
0.999 on the quants but do not create a move line as range (0, 0.999)
will not return anything.
We remove `test_split_1` as it tested a behavior we removed and add a
new test showing a new flow with what we fixed.
Please note that setting the rounding of unit to 1.0 would have
prevented all the issues here.
Followup of rev 383947646f
Let's say you have 6 units and you try to reserve a dozen while the
rounding of the dozen is 1.0. The previous commit correctly only allows
to reserve 12 units, and handle correctly forced quantities in other
compatible UOM, all that with extra moves/backoders.
But we missed an important issue: if now you have 12 units, you will
reserve them. If these 12 units are split across quants, i.e. some are
in another sublocations or are assigned a special lot_id, then we'll
again have rounding issue because the reservation was always expressed
in the move's uom while sometimes it is not possible to go back and
forth between the move uom and and the product's uom. In other word,
we'll reserve 12 times 0 dozen and get stuck at the next step.
This patch now only reserve a quantity if the quantity is expressible in
the rounding's UOM. If this quantity is split across multiple move
lines, we'll make the move line reserved in the UOM of the quants if
necessary. We also do not apply the rounding down -> halfup dance if
`_update_reserved_quantity` is called with the force argument set as
True (meaning, in an mto scenario). The change in
`_prepare_move_line_vals` will make the move lines in the uom of the
qants and everything should be good. With the last change, we need to
adapt the test added by the previous patch, else we won't be able to
make a chain of 2 move moving producst tracked by serial number if the
rounding of the dozen is set at 1.0.
opw-1835186
opw-1835946
When validating a delivery order, some stock moves might be merged by an
internal function, which thus might delete some stock moves.
Since an inventory user has no right to unlink stock moves,
the validation might fail.
We simply had a sudo when doing the unlink, since this is an external method.
opw 1836761
Usecase to reproduce:
- Create a product A with a qty on hand 5.5
- Create a delivery order with an initial demand of 5.5
- Validate it with a qty equals to 5.95
The initial demand is updated to 5.951 then reduced to 5.95
and a backorder is created with an initial demand of 0.001.
That should not happen since I process extra quantities.
It python 5.95 - 5.5 = 0.4500000000000002 and the float_compare
use a round UP method thus it returns 0.451 and the following
flow is based on a wrong value.
In this case a float compare is used before the float round, so an
HALF-UP rounding should be okay since a very small quantity diff should
be filter by the compare.
Fixes#24401
When a scrapped move is part of an open picking, it was not possible to
unreserve the picking. A scrapped move is done and scrapped ; this
combination should be allowed.
opw-1835186
Scenario : Create a transfer on a product tracking by lot. Update the
operation type "Receipt" by unchecking the "show reserved" option.
Open the Register lots, pack, location wizard and set some lots with a
quantity done. The quantity done field is not updated in real time.
Issue :
The depends function on quantity_done is triggered only on move_line_ids
but "show reserverd" option replace move_line_ids by
move_line_nosuggest_ids in the wizard.
There's a certain configuration of UOM that is not correctly handled in
the v11 stock:
- create a move with an UOM having an higher factor than the product's
UOM
- this higher UOM has a rounding of 1.0, meaning it doesn't allow
partial reservation
- use the product's uom in this move and enter quantities that aren't
expressible in the move's uom
A practical example is to set the rounding of dozen at 1.0, set the uom
of a product to units, create a move for a dozen and create a new move
line with 8 units.
The first issue is the `quantity_done` field, that uses an half-up
rounding on the `qty_done` field of each move line and sum them. When
applying this logic to the previous example, `quantity_done` field would
be 1.0, meaning we won't make a backorder for the missing 4 units. We
fix these issue by summing a non rounded qty_done and afterwards
rounding this value to the general products'UOM. This mean
`quantity_done` is technically not be expressible in the move's uom, but
keeping this value close to the reality will allow to handle the
backorders and extra moves correctly.
The second issue is that the backorder is always expressed in the move's
uom. In the previous example, this would mean creating a backorder of 0
dozen. In v10, an error was throwed, saying this operation is
impossible.
The `_prepare_move_split_vals` previously always received the quantity
of the backordered move in the uom of the original move. This is a
remnant of the v10 implementation where, if the quantity to backorder is
not expressible in the original move's UOM, an error was throwed. We now
pass the used uom via a context key to not update the method signature,
as it is probably legitimately overidden by custom modules. This way, in
the previous example, a backorder of 4 units is created.
The last issue is in `_action_assign`. Let's say you have 8 units in
stock and you want to reserve a dozen, the system will reserve 8 units
and then convert back 8 units in dozen, meaning a dozen was reserved.
This resulted in awkward situation where more items than available were
reserved, and the famous "cannot unreserve more than what's available in
stock" was throwed at almost each operation. To solve this, we convert
the not-yet reserved quantities back and forth in both uom. This
prevents partial reservation when not allowed, which is good. We had to
adapt some lines of `_action_assgn` that expected
`_update_reserved_quantity` always at least partially reserved the move.
It is now possible that it doesn't reserve anything.
We also normalize the quantity with a greater decimal precision when
deciding if we open the immediate transfer wizard or not (in the
original exemple, if you enter a single unit the immediate transfer
wizard would be openned because 0 was done in the UOM of the dozen). We
also prevent to enter `qty_done` on the move line if the value doesn't
honour the rounding of the UOM.
We introduce two tests, a simple `_action_assign` in MTS and a more
complete MTO scenario with backorders, extra moves and invalid qty_done.
opw-1835186
opw-1835946
- Create a stockable Product A
- Get create an incoming picking at date D for A
- Go to Inventory > Report > Inventory, and search for the the inventory
at date D-1.
- A should appear with a quantity on hand of 0.
- Filter on 'Available Products'
The product still appear in the list with a quantity on hand of zero.
The optimized method `_search_qty_available_new` is used, although it
doesn't take into account dates.
The original use case for this optimized method was to quickly get
products with stock on hand, i.e. products with quants without needed
information of stock moves.
opw-1833510
Do not allow to change the product on a serial/lot number for a product
which has existing stock moves. Doing so would screw up the traceability
report.
opw-1832452
Using `break` when looping over a recordset in a compute method could
have side effects. Computed field are computed in batch, according to
the order of the recordset, the value may only be computed correctly for
some records
related to rev c493569866
opw-1833347
The code in res config that enabled or disabled internal operation type
did not take into account that active_test is set to False inside this
type of code since c2e259d8.
Thus a picking type of an archived warehouse would possibly unexpectedly
be enabled after saving the settings.
opw-1826196
closes#23956