Community PR: https://github.com/odoo/odoo/pull/91187
## Proposed feature and relevance
Add a new retrieval strategy for gathering products: "Least packages".
The goal of this strategy is to select specific product quantities from stock by using as few packages as possible, to allow for efficient logistics operations and avoid unnecessary opening/unpacking of packages.
This strategy will behave as follows:
- In case a negative qty is requested this strategy will behave as a FIFO strategy.
- Otherwise, the strategy will determine a combination using the least amount of packages that sum to the requested quantity, and adapt the provided domain to select only the quantities in these packages. This way no packages need to be opened to select the requested quantity.
- In case an exact matching of current packages to get the requested quantity is not possible, a selection of packages is made where the largest packages are selected one by one until the requested quantity is reached, or until no more quantities are available. For this approach, one package needs to be unpacked as it will not be used completely. The final selected package that will be unpacked will be the smallest one possible, to try to unpack smaller packages over bigger packages.
- In case the search for a minimal matching of packages results in an out-of-memory situation, the strategy will fall back to a FIFO strategy.
- Loose items (not tied to a package) are considered as single-item packages for the purposes of package selection.
- **NOTE:** To force the selection strategy to "clean up" certain packages that have previously been opened, it is recommended to unpack these packages into single items, as they will then be consumed to "fill up" requested quantities in later retrievals.
## Changes to allow more complex strategies
To allow for the integration of this new strategy the structure of `_gather()` needed to be adapted to allow a removal strategy to provide not only the SQL `ORDER BY` string but also adapt the domain used to retrieve the requested quantities.
This change is reflected in the method signature of `_get_removal_strategy_domain_order()`.
## How the strategy works
The strategy does one extra query of the database, to determine the different packages and their respective quantities (using the provided domain).
Loose items (that do not belong to a package) are added as single-item packages to also consider them.
For minimal exact package selection, an A* algorithm is used with 2 performance modifications:
- Using the information that the packages are sorted by size (large -> small).
- Using the information that the generated subtree for a specific package of size x is the same as all other packages of size x at a specific node.
By using the A* algorithm, as soon as a matching packaging selection is found, it is ensured to be optimal and other combinations do not need to be considered.
In case the A* algorithm runs out of memory the provided domain is just returned, which equates to a FIFO strategy.
In case the A* algorithm does not find an exact matching of packages for the requested quantity, a selection is made using the least amount of packages, unpacking the smallest possible package (or until no more quantities are available, in which case effectively all quantities in the domain are returned).
## Used heuristic
The heuristic used for the A* algorithm exploits the knowledge that our packages to select from are ordered by the highest to the lowest quantity (on the database side, SQL `ORDER BY`).
It assumes the "best case scenario" as an estimate for the amount of packages remaining, which is if we were to "match" the required quantity using fractional multiples of the next biggest package size.
***Example**:
Remaining quantity to select: 27
Remaining package sizes to select from: [10, 10, 5, 5, 5, 1, 1, 1]
Heuristic for choosing package with qty 10 as next package: 27/10 = 2.7
Heuristic for choosing package with qty 5 as next package: 27/5 = 5.4
Heuristic for choosing package with qty 1 as next package: 27/1 = 27*
This way the heuristic is always a "best case" (fractional) for the amount of packages that still need to be selected.
As required by the A* algorithm this also results in an underestimation as the fractional result is not possible, and it is not certain that there are still enough packages of this size that can actually be selected, but favours larger packages to make the search converge more quickly.
## Performance
### CPU
Two test cases were run to evaluate the performance.
***Total nr of pkg**: The total amount of different packages generated during data generation
**Qty to select**: The total quantity that needs to be selected
**Selected nr of pkg**: The amount of packages that was ultimately selected by the algorithm
**Data generation time**: The time required to generate all packages
**Assignment time**: The total time to run `_action_assign()` for the move
**A\* time**: The time to run the `_run_least_packages_removal_strategy_astar()` method*
#### First test case
This scenario simulates a case with a large quantity to select from a large amount of packages, but of relatively homogenous size.
Generate 30 different package sizes between 2 and 1000. For each package size, generate 100 to 250 packages each. Also add 100 to 250 "loose items".
The quantity to select is chosen between 1 and 50000.
| RESULTS | RUN 1 | RUN 2 | RUN 3 | RUN 4 | RUN 5 | AVG |
|--------------------------|----------|-----------|------------|-----------|----------|------------|
| Total nr of pkg | 5298 | 5772 | 5855 | 5533 | 5179 | 5527.4 |
| Qty to select | 10319 | 20762 | 44422 | 39306 | 1783 | 23318.4 |
| Selected nr of pkg | 11 | 22 | 48 | 41 | 3 | 25 |
| Data generation time (s) | 64.59124 | 92.916682 | 133.673384 | 82.711438 | 85.54542 | 91.8876328 |
| Assignment time (s) | 4.060216 | 11.212937 | 4.763776 | 8.60248 | 3.461941 | 6.42027 |
| A* time (s) | 0.28 | 6.88 | 0.21 | 3.96 | 0.03 | 2.272 |
#### Second test case
This scenario generates a large amount of small packages of different sizes.
Generate 250 different package sizes between 2 and 10. For each package size, generate 5 to 15 packages each. Also add 5 to 15 "loose items".
The quantity to select is chosen between 1 and 10000.
| RESULTS | RUN 1 | RUN 2 | RUN 3 | RUN 4 | RUN 5 | AVG |
|--------------------------|-----------|-----------|-----------|-----------|----------|------------|
| Total nr of pkg | 2485 | 2406 | 2491 | 2555 | 2542 | 2495.8 |
| Amount to assign | 27 | 4029 | 3966 | 3049 | 1833 | 2580.8 |
| Selected nr of pkg | 3 | 411 | 411 | 306 | 184 | 263 |
| Data generation time (s) | 18.502933 | 18.692048 | 19.969955 | 19.169106 | 19.16439 | 19.0996864 |
| Assignment time (s) | 1.35635 | 7.958852 | 8.470518 | 6.300406 | 3.895457 | 5.5963166 |
| A* time (s) | 0.01 | 0.07 | 0.77 | 0.56 | 0.31 | 0.344 |
### Memory
In cases with large amounts of different-sized packages (200+ different sizes and 200+ packages required to get an exact match) the memory performance of the A* strategy might become problematic.
When lots of packages have the same size (which would be considered typical in cases where there are large amounts of packages) the specific modifications to the A* algorithm ensure that the strategy still delivers good memory performance for this use case as the tree size can be significantly reduced, even with large quantities.
### IO
This strategy only requires one extra SQL query to fetch the different quantities and their respective packages.
## Limitations
No tests for this strategy were done for non-integer quantities. In these cases the performance of the A* algorithm might not be satisfactory and another approach might be preferred.
More research could be done for specific use cases where packaged quantities are non-integer values.
closesodoo/odoo#91187
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
- The `Returns` word should be translated but it has not been
initialized via xml
data so i added.
closesodoo/odoo#98966
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
San Francisco is in data since commit 33950bfdc3
However the task aims to clear demo data but warehouse0 is the default
warehouse in data and should not have a demo name
closesodoo/odoo#101305
X-original-commit: 0fd86c9ab1bbd237b3c7cb3c22b3362612142993
Signed-off-by: Steve Van Essche <svs@odoo.com>
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
Minor UX updates in purchase and stock:
Reworded (in stock):
- Default name location "Partner Locations" => "Partners"
- Default result for "Apply All" wizard "Inventory Adjustment" =>
"Quantity Updated"
- Individual "Apply" move reference/name updated for individual quants
(i.e. "Quantity Updated / Confirmed") so that the scheduled date is
no longer included
Removed (from purchase):
- Duplicated menuitems, i.e. "Purchase > Reporting > Purchase" showed
the same thing as Enterprise menuitem and both were being displayed in
Enterprise version. Also updated the no records found help message
since old message appeared to be slightly out of date.
ENT PR: odoo/enterprise#29974
"other" part of b2b task: 2882539
Part-of: odoo/odoo#97109
Assuming that the only thing cared about when removing items from stock
is the accessibility of the product. Then it would be better to take
products stored on the floor instead of on higher levels of my racks.
In this case current solutions in Odoo are not the most efficient.
Closest location picks items in the 'smallest' location (in alphabetical
order), so it assumes the locations are ordrered alphabetically
according to how close they are to the ground.
Assume we have the following stock :
- WH/Stock/Shelf 2
- WH/Stock
- WH/Stock/Shelf 1
Quants would be looked at in the following order :
1. WH/Stock (due to shortest name for the same stock)
2. WH/Stock/Shelf 1 (due to alphabetical order)
3. WH/Stock/Shelf 2
Task-2568735
closesodoo/odoo#75303
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
- Remove unused `sequence_tracking`
- Group data by models when it is possible, which implies
to remove `procurement_data.xml` file (data into `stock_sequence_data`).
- Clean messing comments
- Reorder the manifest (when it is possible)
task-2373638
Improve onboarding by removing the replenish on order route.
Companies that do MTO process could unarchive the route in
order to have a basic configuration.
closesodoo/odoo#55147
Task: 2245882
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
Rename warehouse of compagnies as following:
- YourCompany -> San Francisco
(WH) (WH)
- My Company (Chicago) -> Chicago 1
(MyCo) (CHIC1)
- Chicago Warehouse -> Chicago 2
(Chic) (CHIC2)
Also, can pass a default code through the context when create a new
company to set the `code` value when creating the default warehouse for
the newly created company.
Task #1970460
All transit locations were set as active by default, confusing some users.
There are now set as active only when when a ressuply route is created
between some warehouses
TaskID: 1873106
This commit adds fields 'company_id' on stock.scrap model.
The company will filter locations and stock moves linked to the scrap
document.
We add also a specific sequence by company.
Task-1930055
closesodoo/odoo#30498
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
Stock.locations should be in no-update:
Limit the impact of recompute fields during the upgrade of stock module. (especially method _compute_product_availability)
Limit the impact on migration
Method _compute_product_availability is triggered during an upgrade of module and during migrations.
This may take a lot of time of big databases
closesodoo/odoo#34074
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
The stock location usage 'procurement' is not used anymore in stock, and
we remove it as it is not used either for the stock and valuation of
stock.
TASK-ID: 38469
Purpose : When we create order point in another company, it is not setting name ( sequence ).
After this commit it will use ( sequence ) in all company, as we not set company_id on the sequence of order point.
Task #1908526Closes#28597
We move the code from the 'post_init_hook' into a function tag, to be
consistent with the way we populate missing data when stock module is
installed.
TASK-ID: 1882269
Create new methods on `BaseModel` to create records with given xml ids in
batch. Those methods replace the methods `_update` and `_update_dummy` of
model 'ir.model.data', which are now deprecated.
Adapt XML and CSV import code to create records in batch.
Usability improvement:
- Common view for push and pull rules
- Add an help text in order to describe the rule
- Rules menu
- Warehouse checked by default on route created by a warehouse
- Lower the MTO route sequence in order to take it first.
- Tooltip cleaning
Technical improvement:
The purpose of this task was also to merge stock.location.path(push rule) and
procrement.rule. Those two model were design to execute the same task
but in a different direction. Thus it contains duplicate code.
Task ID 1852969.
At stock installation, the warehouse0 has the name of the first company found
(order "sequence, name"), while the comapny_id field is
`_company_default_get('stock.inventory')` (the company of the user installing
the stock module).
In a multi-company environment, it is possible than both results are different
and having name = 'Company A' and company_id = 'Company B'.
Use the name of the default company as default value for the field name.
Note that 'stock.inventory' is not needed in _company_default_get call but
kept to match the default of company_id (in case of override).
Using a default on the field will impact all the future records but should,
hopefully, not be problematic as it is a valid default value.
Closes#19563
Purpose
=======
As the 'function' tag is re-evaluated on the module update (even when noupdate="1"), the ir.model.data will be created a second time with the function 'create'.
This leads to the record deletion after the update when calling '_process_end'.
Specification
=============
Use '_update' instead of 'create' and '_update_dummy'.
- _update won't create another ir.model.data if it already exists.
- _update already calls _update_dummy to avoid the record deletion.
Use case to reproduce the bug:
- Enable multi company and create a second one.
- Add both company to another user and give him stock manager rights
- Login on the second user and select as active the created company
- Go to product and create one
-> access right error on stock.location.route message.
It happens because the routes 'buy' is selected by default.
However the route buy when created use the default company
although it's generic for all companies.
This commit change the data in order to remove the company on
routes buy, mto, manufacture and drop_shipping. Since this commit
was released after v11 release, it could happens that already created
database still have the problem thus the solution is to remove
manually the company on the routes quoted above.
opw-777718
Not used since a while, remaining of old res.request. Requests have been
removed at 881a76dbcf . Links have been kept because still
used in some reference fields. It seems the last use was in OpenERP v9.0
in crm_claim module. As links are not used since a while let us get rid of
it.
This removes the procurement.order model. To fufill their needs SO, PO, MO and
stock moves now call the _run method of the relevant procurement.group.
This mecanism is now only used for stockable product, tasks now uses their own
independent mecanism.
The _run method will check all the applicable rules and create directly the
needed model to fufill the need.
The modules stock, purchase, mrp, extends the _run method to implement their
specific strategy relevant for the rule type they define.
If an exception happens the message will be logged as a mail messsage on the
source model, for example, if a sales order cannot be fufilled the salesperson
will now see directly the reason.
OLD commit messages:
[WIP] procurement: removing procurement.order in stock, sale, purchase, sale_stock. WIP
fixup! [WIP] procurement: removing procurement.order in stock, sale, purchase, sale_stock. WIP
[IMP] Basic tests
[FIX] test not necessary anymore
[FIX] remove unnecessary print statement
[FIX] unnecessary test + why passing warehouse worked before?
[IMP] purchase: one move by purchase order line
[FIX] purchase: correct inventory tests and pass move_dest_ids among procurements
[FIX] because of bad cherry-pick merge
[IMP] make mrp pass by adding move_dest_ids there too
[IMP] tests of sale_mrp, no need for cancelpropagation then
[IMP] better to consistently use recordsets also for one2many
[FIX] purchase_requisition
[FIX] Exceptions should trigger errors, which should be caught in the tests
[FIX] sale_mrp: remove usage of procurement.order and use sale order name instead of sol
[FIX] stock_dropshipping: add sale_line_id on purchase_line_id
[FIX] Remove pdb
[IMP] add stock_dropshipping files
[IMP] stock: search carrier through sale line instead of procurement group
[IMP] add procrule test and preision needed when updating sol
[FIX] sale_order_dates + [IMP] procurement exceptions by scheduler
[FIX] No need to return task
[IMP] move file as name changes and add corrections
[FIX] Continue Run Schedulers wizard fix
[FIX] name issues of takss
[FIX] updating sale order line, but there is still a problem with the recompute
This commit contains the core of the new MRP. It contains a whole refactoring
of the MRP application, with improved and new features, written in new API.
Among other here are the main manufacturing workflow improvements :
- Picking type not only for pickings but also for manufacturing orders
- Properties replaced by picking type
- BoM can only be produced with its routing (no other)
- Either produce without routing with only production orders, or produce with
routing
- By default, there is an order in the work orders (serially), but you can
override it to be able to work in parallel
- Time clocking on work orders and block time on work centers with reporting
on OEE, performance, losses, ...
- Real-time adaptation of timings on operations
- Lots/serial numbers can be inputted like in the pickings on manufacturing
orders. It is also possible to input them in the work orders.
- Material availability independent of production order state (possibility to
start production when only part of it is there)
- Work sheets on work orders
- Put messages on work orders to make your workers pay attention to something
- Full traceability link to see for each produced piece of stock, the
consumed pieces, ...
- Separate scrap object (a scrap is not done based on an original move
anymore)
- Separate unbuild system (if you want to unbuild into its original
components)
Thanks to all people that helped during this development, notably but not
limited to Chirag A Dodiya (cod@odoo.com), Gaurav Panchal (gan@odoo.com),
Jignesh Rathod (jir@odoo.com), Mansi Trivedi (mtr@odoo.com), Pariket Trivedi
(ptr@odoo.com).
In master , some places the string "Lot" is used and at some places
"Serial Numbers" is used , which is very confusing for the user.
Make a common string "Lots / Serial Numbers" everywhere for the uniformity.
Moves performed
- data and demo files are now located inside the data directory
- data and demo files name updated
- report views moved inside report directory instead of views
- main stock menus declarations moved from stock.xml to stock_menu_views.xml
in order to have all main menus in a single file, extracted from model
specific views
- data section of __openerp__.py file reorganized accordingly
No change done in this commit.