The rational is:
Currently we have 2 columns. One for reservation, the other
for quantity picked.
However in real time, either you follow the reservation and everything
goes well. Otherwise you pick something else. In the case where you
pick somewhere else than reserved, you would like to modify the
reservation to have something similar and free the quantity you
didn't pick and expect the system to not suggest the ones you took.
In other hand, we always want to have the reserve quantity similar to
the done.
On top, having two columns could be confusing for the end user.
The cons:
-The qty_done column could be use during the picking, to
remember if something has been pick or still to pick.
- For some flow (put in pack), it's easier to write a part of the quantity to pack
and still want to reserve the full amount of product.
We goes back and choose a ligther interface over complex feature.
Changes:
Qty done and reserved qty are merged into a single column.
A new checkbox on the move exists to mark it as picked or not
Since the reservation always follow the quantity, it's now possible
to have more reserved quantity than stock. However the system will
never propose it and the inventory showing reserved > quantity should
be a warning.
The system should never modify a move that has been picked. We don't
want to overide the user action.
Regression:
Not able to pick a single stock.move.line
closesodoo/odoo#137864
Related: odoo/enterprise#48709
Related: odoo/upgrade#5310
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit fix 3 issues with the reservation with use_expiration_date set on the product:
1) -- Discrepancy of available_quantity --
StockMove._update_reserved_quantity() works along StockMove._get_available_quantity()
If the with_expiration context is added to one and not the other, the available_quantity sent to the 'update' method will not be correct.
2) -- Can't reserve on imperishable quants --
On the Quant, if expiration_date is False, the reservation will not be possible.
Changed the domain from `expiration_date >= date` to `expiration is False or expiration_date >= date`
---
# How to Reproduce
- Create a product P, tracked by lot, with use_expiration_date = True
- Set quantity on hand to 10 (without lot)
- Create a Sale Order for 1 unit of P: Confirm
- On the Delivery, 'Check Availability' (if not done automatically)
=> The Transfer is marked as Ready (aka: at least 1 unit reserved), but nothing is reserved.
=> If you Unreserve, the product availability is shown as Available, and if your Reserve again, it is shown as 'Not Available'
OPW-3434996
closesodoo/odoo#137097
X-original-commit: b5463465fa877b9913eb9747869aae00c6b394ca
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: David Fesquet (dafr) <dafr@odoo.com>
The field `move_line_nosuggest_ids` was missing on the stock move form
view. Depending on the `show_reserved` setting on the picking type, we
should show either `move_line_ids` or `move_line_nosuggest_ids`.
Displaying the wrong field will trigger the wrong computes
Part-of: odoo/odoo#136067
Steps to reproduce:
1. Have 2 companies, and select the one w/ the highest ID
2. Create a new product tracked by lot + expiration date
3. Receive product
4. Set the received lot's expiration and alert dates in the past
5. Inventory > Operations > Run scheduler
Before this commit:
An activity is created on the lot for OdooBot,
despite the product's responsible set to the current user.
It happens because the default value for `responsible_id` is the current
user, but the value is only set for the current company. When the
scheduler runs, it doesn't set the company; therefore, it takes the
product's responsible user for the company with the lowest ID, which is
not set.
After this commit:
The activity is created for the product's responsible user using
the lot's company.
opw-3489340
closesodoo/odoo#136172
X-original-commit: dacfa84486c3251f503ef2a36b56006471961123
Signed-off-by: Tiffany Chang (tic) <tic@odoo.com>
Signed-off-by: Walravens Mathieu (wama) <wama@odoo.com>
In order to reduce the amount of RPCs in the detailed operation view.
The two wizards to populate the stock move line one2many with lot/serial
number to create are replaced with twos Owl dialogs.
only one RPCs is done to generate the stock move lines values from
either a serial number + a count or a list of lots name
Task : 3256447
Part-of: odoo/odoo#124409
This commit replaces the opening of the stock moves detailed operation
wizard by the one2Many record preview. This means creating a move in a
picking is still done via a new line but the edition is done via the
`fa-list` button that open the record in the web client. The goal is to
reduce the RPCs call as much as possible. The stock move lines data are
stored in the stock move record until the picking save.
Additionally, this commit change a bit the immediate transfers flows.
The stock move show only initial demand (`product_uom_qty`) but the
column wording is still "Done". In the detailed operation view, the
stock move line `qty_done` is displayed as "Reserved".
At picking validation, the user is expected to enter the same quantity
in `product_uom_qty` and `quantity_done`. If `product_uom_qty` is equals
to 0, the done quantity is used as actual transfer quantity. If
`product_uom_qty` is different than 0 but small than the done quantity,
an error is raised.
Task: 3256447
Part-of: odoo/odoo#124409
Steps to reproduce:
- Install product_expiry
- Create Product P:
- Product type: Storable
- Inventory tab > Tracking: By Lots
- Check Expiration Date
- Expiration Date: 100 days after receipt
- Best Before Date, Removal Date, Alert Date: 10 days before
expiration date
- Save
- Products > Lots/Serial Numbers > New
- Product: P
- open Dates tab
There are two different usecases and issues starting from this point.
Usecase 1:
- Dates tab, delete all dates, save
- set the Expiration Date, all other dates are set
- without saving, update the Expiration Date again
Issue 1: The other dates don't update according to the new Expiration Date. This happens because neither if conditions in `_compute_dates` match the case where the product has an expiration date set, but it has not been saved to the lot.
Solution 1: Add an additional condition in the `_compute_dates` method where `lot.expiration_date` is set, but `lot._origin.expiration_date` is not set. This will ensure the other dates are updated correctly when setting the Expiration Date without saving.
Usecase 2:
- Dates tab, set an Expiration Date, save
- Without saving the record, update the Expiration Date several times, with dates in the future
Issue 2: The other dates (Best Before Date, Removal Date, Alert Date) will drift off further in the future, while they should always be 10 days apart from the expiration date. This happens because the new dates are being set relative to the actual value of the date, which changes with each successive update.
Solution 2: set the new dates relative to the value of the `lot._origin` dates, which remain constant between successive (saveless) updates. This will ensure that the other dates maintain a 10-day difference from the Expiration Date consistently.
opw-3374135
closesodoo/odoo#130599
X-original-commit: a275cbcd2d8a87bbd8cadf85c094625ebd8358c4
Signed-off-by: Tiffany Chang <tic@odoo.com>
This commit improves the performance of reservation by removing
the `get_available_quantity` and `update_reserved_quantity` inside
`_action_assign` which each does a search on quants with the same domain,
both of which are done per move to assign.
Instead the quants needed by the moves to reserve are fetched first and
are then filtered in memory for each move to reserve from.
A new function is provided `get_quants_by_product` which should be used
when reserving moves to fetch the relevant quants once and then call
`_update_reserved_quantity` on them which will filter them in memory.
This avoids searching for quants for every move.
The changes in `point_of_sale` and `product_expiry` are all
due to the the method signature change and change nothing in the flow.
Performance stats:
These stats are from the Odoo profiler on the `_action_assign` called
on a specific number of moves. For each number of moves the duration was
taken multiple times and the average was taken. The 10 moves durations
were quite random since the numbers were very small and could be considered
an outlier.
Before this commit:
| No. of Moves | SQL Queries | Duration (s) |
| ------------- | ------------- | ------------|
| 10 | 70 | 0.044440283 |
| 100 | 633 | 0.398992664 |
| 1,000 | 4,518 | 6.264924025 |
| 10,000 | 46,954 | 79.76809310 |
After this commit:
| No. of Moves | SQL Queries | Duration (s) |
| ------------- | ------------- | ------------|
| 10 | 62 | 0.062840558 |
| 100 | 540 | 0.323033646 |
| 1,000 | 3,893 | 4.062329989 |
| 10,000 | 39,259 | 49.92596793 |
Besides 10 moves duration, there's a general performance
improvement of 20% - 35%
closesodoo/odoo#116803
Related: odoo/enterprise#40633
Signed-off-by: Tiffany Chang <tic@odoo.com>
This commit makes hotkey uses more coherent throughout the entire
codebase by setting alt+q as main shortcurt for confirm and default
actions and alt+x for cancel actions.
task-3370463
closesodoo/odoo#127469
Related: odoo/enterprise#43694
Signed-off-by: Mathieu Duckerts-Antoine (dam) <dam@odoo.com>
Lots and serials are currently only differentiated by their number and potentially expiry dates. In many industries, they choose their lot/serial based on many data.
For instance on Iron lots in the metal industry there are multiple properties helping to define the quality. This also happen in the second-hand industry and many others.
added:
- properties field on stock.lot
- properties field on stock.quant, related to stock.lot
- kanban view on stock.lot
- search on properties in stock.lot and stock.quant list views
task 3061173
Part-of: odoo/odoo#117316
PR odoo/odoo#109511 added in a related expiration_date field linked to
its lot_id's expiration_date. This field was added as readonly=False,
which was a mistake due to the following issues it causes:
bug - the related dates (use_date, removal_date, alert_date) won't
correctly update, this is easily fixable
bug - [mostly a nuisance, but will be confusing for users], if there are
2 lines for the same lot (e.g. different locations) then updating
the expiration_date for one line won't show in the other lines
without a view refresh (could be fixed with custom JS, but not
ideal)
bad UX - cluttered view of editable values
redundancy - the ability to edit the expiration_date is easily done by
clicking on the lot name within the view or by opening the
list view of the lots and batch editing dates
For stable we will make this field readonly. This field and
`removal_date` would ideally be removed since they would never be
different from the lot value, but both need to remain stored since they
are used for the removal_strategy_order and gathering non-expired
lots/SNs.
opw-3328901
closesodoo/odoo#123746
X-original-commit: d21d9259aef855c900169263db90873b736f3df6
Signed-off-by: Steve Van Essche <svs@odoo.com>
Signed-off-by: Tiffany Chang <tic@odoo.com>
Currently, only stable releases see their translations updated. This has
resulted in master accumulating outdated stuff for years, which can be
confusing for users testing master on runbot.
This one-shot commit resynchronizes master translations based on the
content from 16.0 and removes empty PO files (i.e. no longer containing
translations).
closesodoo/odoo#121629
Related: odoo/enterprise#41171
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
This replace the generate serial numbers mechanism on stock move by two
new buttons in the detailed operation wizard. One for generate serial
numbers from a sequence and one to import serial/lot names.
Created lots will create the stock move lines automatically as well.
Task: 3256447
Part-of: odoo/odoo#117513
In a flow where the reservation is used (internal transfers, deliveries,
...) adding a new stock move line is now made from the quantities
available in stock. The 'add a line' button in the show detail wizard
trigger the quant list view to directly pick the wanted lot or location
where the stock is available. Only the quantity done is needed to be
updated before the validation.
This commit remove the 'quant reserve wizard' as the behaviour is an
extension of it.
Task: 3256447
Part-of: odoo/odoo#117513
This commit changes the process flow of stock pickings. A new picking will
always be created in immediate transfer mode and 'ready' state. From
their, it can be validated directly or 'reset to draft'. This second action
switch the immediate mode to planned mode and reset the state as draft.
From their the classical workflow is processed
confirm -> (assigned ->) validated
Task: 3256447
Part-of: odoo/odoo#117513
Before, when the user pastes a list of tracking numbers into the move
line's `lot_name` field (through the move's detailed view), a lot is
created for each line, creating a move line for each new lot, or
assigning each lot to an existing line with no lot.
With this commit, it will also take `qty_done` and `expiration_date` (if
`product_expiry` is installed) from the pasted list if it's relevant.
Each data should be separate either by a semicolon, either by a tab, and
the first data should always be the lot name.
Valid examples for lots and quantities:
lot-01;22
lot-02 12
Valid examples for lots, expiration date and quantities:
lot-03;8;01-02-2005
lot-04 2005/02/01 12-20
The only valid separation characters for the date are the space (" "),
the dash ("-") and the slash ("/"). Examples of valid dates:
20-02-24 20-Feb-2024
20 02 24 20 Feb 2024
20/02/24 20/Feb/2024
If any of the extra values can't be converted into either a quantity or
a date, the whole line will be used as the tracking number.
Also, if dates are pasted but the product doesn't use any expiration
date, the date's part will be ignored.
task-3171866
closesodoo/odoo#115401
Signed-off-by: Tiffany Chang <tic@odoo.com>
Currently, when a product with an expiration date is reserved, the
expiration date isn't checked when seeking which lot/serial to use. This
can lead to the shipping and delivery of already expired products, since
their expiration date came before their scheduled delivery.
Task-3203121
closesodoo/odoo#117138
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
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>
When printing the label of a lot, the datamatrix may overlap the
product/lot name and will overlap the 'best before' date.
To reproduce the issue:
1. In Settings:
- Barcode Nomenclature: GS1
- Enable "Print GS1 barcodes for lots [...]"
2. Create a product P:
- Name: a long name
- Type: Storable
- Barcode: 1111111111113
- Tracking: USN
- Expiration Date: True
- Dates > Expiration Date: 1 days
3. Process a receipt with 1 x P
- The serial number should be long
4. Print Labels
- To Print: Lot/SN Labels
- (Confirm)
- Format: 4 x 12
Error: the datamatrix overlaps the product name, the serial number,
and the 'best before' date
For the product/lot names, we can only improve the situation. If the
user define a too long name, the issue will still happen and nothing
can be done
For the dates, we can shorten the labels. That way, the dates will
always be correctly displayed
OPW-3193836
closesodoo/odoo#116541
X-original-commit: f175897cefd1db149e94a50882d9e7babfc6293d
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
In large databases with > 2M stock_move_lines, installing
the product_expiry module can raise a MemoryError because the
field_cache is overfilled by the computation of the expiration_date
computed stored field.
Adding an _auto_init for this field prevent such errors from being
raised by creating the column manually.
closesodoo/odoo#116456
X-original-commit: 8b82d3154858582f6d321bd6473557fc192af25f
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
They dates from < 2027 and are quite outdated. Favour the nl
translation instead.
n_BE is not on Transifex so it was not possible to correct bad
translations.
closesodoo/odoo#115845
X-original-commit: d04c8b7e484db8306d858c891a7a2b11885fdcd9
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
According to Wiktionary, French spacing is "the archaic practice (though
still current in French) of inserting a space around colons, semicolons,
question marks, and exclamation marks". This is not standard practice in
English and most languages of the world.
The purpose of this commit is to start purging the code from this typo,
as it may reflect poorly on the software for some people.
closesodoo/odoo#114533
Related: odoo/enterprise#37853
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
The `date` widget, when used with a datetime value, doesn't offset the
value relative to the session timezone. This can lead to strange issue
like this following one
date1 = 12/03/2023 05:34:12
date2 = 12/03/2023 18:34:12
in the deliveryslip report, the datetime are casted as date, they become
date1 = 12/03/2023
date2 = 13/03/2023
closesodoo/odoo#114983
Opw: 3199862
X-original-commit: b6757daac6272092c37024ac2bdd49747177d2bc
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit allows the user to choose which quants to reserve from stock
and the quantity to reserve from each quant, making reservation much more
flexible from the picking form.
In addition, the `reserved_uom_qty` of stock.move.line
is now editable in views to allow for users to change the qty reserved
by existing move lines. When editing the reserved qty, if quantity is not available,
it will reserve only what is available..
closesodoo/odoo#106006
Taskid: 3090913
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
In the Inventory's Configuration, the option to enable expiration dates
depends of the activation of lot and serial numbers.
But if the user disables the tracking and the expirations dates were
enabled, they still are.
Also, if the module `product_expiry` is installed directly, the tracking
numbers aren't enabled alongside.
To fix that, this commit modifies the `res.config.settings` onchange
`_onchange_group_stock_production_lot` to disable automatically
expiration dates when tracking is disabled, and this commit also adds a
hook in the `product_expiry` init to enable tracking numbers at the
installation.
Part-of: odoo/odoo#109511
- The `picking_type_id` field in the pickings form view is not openable;
- Display the `description` field (optional) in the SVL list view;
- Add the `expiration_date` field (optional) in the quant list views;
- Add a description text for the landed cost;
- Renames field `requisition_id`: "Purchase Agreement" > "Blanket Order"
- In Inventory Adjustment, hides the "Apply All" button is at least one
record is selected;
- In `product_expiry`, renames two views to stick to the XML's coding
guidelines: https://www.odoo.com/documentation/16.0/contributing/development/coding_guidelines.html#xml-ids-and-naming
- For the replenishment:
- Places the field `product_id` as the first option when the user
writes something in the searchbar;
- Renames `route_id`: "Preferred Route" > "Route";
- Renames the button "Automate Orders" into "Automate";
- Set the `route_id` field as "optional=hide" until `mrp_purchase` is
installed (in this case, it will be set as "optional=show") because
in this case, there is at least two routes (Buy and Manufacturing).
task-3076044
Part-of: odoo/odoo#109511
When creating a new lot in an inventory adjustment, the removal date,
the best before date and the alert date are not always defined.
To reproduce the issue:
1. Create a product P
- Type: Storable
- Tracking: By Lots
- Expiration Date: True
- Expiration Time: 2
- Best Before Time: 0
- Removal Time: 0
- Alert Time: 0
2. Update the on hand quantity of P:
- 1 x P with lot L01
3. Open L01
Error: Only the expiration date is defined. The other dates
(removal, best before and alert) should be defined too.
Considering the definition of the fields set on step 1:
https://github.com/odoo/odoo/blob/221ee0cdc362e1958f9a5326c1966de9dfb47c48/addons/product_expiry/models/product_product.py#L23-L35
The times defined on Best Before, Removal and Alert are the number of
days before the Expiration Date. So, if for instance the user
defines the best before time to 0, it means that the best before
date must be the same as the expiration date.
OPW-3072000
closesodoo/odoo#109353
X-original-commit: 8b06046379e6cfa62bd5b2df261a7ab22d5e2c3b
Signed-off-by: Adrien Widart <awt@odoo.com>
The aim of this commit is to simplify and standardize the settings archs.
To do this, a small DSL exclusively for the settings was created. This
new DSL introduces 3 tags: `app`, `block` and `setting`.
The `app` tag is used to declare the application on the settings view.
It creates an entry with its logo on the sidebar of the view. It also
acts as delimiter when searching.
```xml
<app string="CRM" name="crm">
...
</app>
```
- `string` : The "display" name of the application.
- `name` : The technical name of the application (the name of the module).
- `logo` *optional* : The relative path to the logo. If not set, the
logo is created using the `name` parameter :
`/{name}/static/description/icon.png`.
The `block` tag is used to declare a group of settings. This group can
have a title and a description/help.
```xml
<block title="Title of group Bar">
...
</block>
```
- `title` *optional* : The title of the block of settings (the old h2),
you can perform research on its text.
- `help` *optional* : The description/help of the block of settings
(the old h3), you can perform research on its text.
The `setting` tag is used to declare the setting itself. The first field
in the setting is used as the main field (optional). This field is
placed on the left panel (if it's a boolean field) or on the top of the
right panel (otherwise). The field is also used to create the setting
label if a `string` is not defined. The `setting` tag can also contain
more elements (e.g. html), all of these elements are rendered in the
right panel.
```xml
<setting string="this is bar">
<field name="bar"/>
...More elements
</setting>
```
- `type` *optional* : By default, a setting is visually separated on two
panels (left and right), and is used to edit a given field. By
defining `type='header'`, a special kind of setting is rendered
instead. This setting is used to modify the scope of the other
settings. For example, on the website application, this setting
is used to indicate to which website the other settings apply.
The header setting is visually represented as a yellow banner on
the top of the screen.
- `string` *optional* : The text used as label of the setting. If it's
not defined, the first field is used as label.
- `title` *optional* : The text used as tooltip.
- `help` *optional* : The help/description of the setting. This text is
displayed just below the setting label (with classname
`text-muted`).
- `company_dependent` *optional* : If this attribute is set to "1" an
icon is displayed next to the setting label to explicit that
this setting is company-specific.
- `documentation` *optional* : If this attribute is set, an icon is
added next to the setting label, this icon is a link to the
documentation. Note that you can use relative or absolute path.
The relative path is relative to
`https://www.odoo.com/documentation/server_version`, so it's not
necessary to hard-code the server version on the arch anymore.
closesodoo/odoo#106425
Task-id: 3081367
Related: odoo/enterprise#34337
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Co-authored-by: "Michael Mattiello (mcm)" <mcm@odoo.com>
Inventory report has been updated to have:
- better applicability: report renamed to "Locations" and is only
visible w/Locations, Consignment, or debug mode active
- improved UX: list view rearranged, buttons added, grouping removed,
sums added to bottom of list
- improved quant "Value": instead of the accounting value, this is now
the average unit cost (i.e. sum(valuation layer values)/sum(valuation
layer quantities) per product x on hand qty (of quant).
- single click load for products
- search based on Warehouse option (including storing
location.warehouse_id to avoid overly complex search function)
- always show "Location" column in this view even if multi-locations is
not active
"inventory report" part of b2b task: 2882539
Upgrade PR: odoo/upgrade#3819
Part-of: odoo/odoo#97109
Just doing the summer file cleaning. Move mail data into files named based on
their model, easing maintenance and searching for those data.
Spotted during Task-2207626 (Rating: Delay rating notification to ease feedback)
Part-of: odoo/odoo#98661
expiration
Previously, we do
{expiration,use,removal,alert}_date = receipt_date + {expiration,use,removal,alert}_time
After this commit, expiration date remains unchange, for the other 3
dates, we calculate them by
{use,removal,alert}_date = expiration_date - {use,removal,alert}_time
Task-2657043
closesodoo/odoo#86760
Related: odoo/enterprise#25419
Signed-off-by: Steve Van Essche <svs@odoo.com>
Steps to reproduce the bug:
- Enable “Expiration date” in inventory settings
- Create a Storable product “P1”
- Tracking: by serial number
- Enable the expiration date option
- Update the quantity:
- Create a new Lot “SN1”:
- select today's date as the alert date
- Go to inventory > reporting > Inventory Report
- Try to filter by “Expiration Alerts”
Problem:
The product P1 is not selected, because the filter checks the removal
date instead of the alert date
Solution:
The filter should check if the alert date is less than or equal
to today's date to display products or not, as it is for lots:
https://github.com/odoo/odoo/blob/14.0/addons/product_expiry/views/production_lot_views.xml#L30-L39
opw-2889737
closesodoo/odoo#95289
X-original-commit: 1c04bc5407f02c7299b86a7f4fef207f4aa01c77
Signed-off-by: Christophe Simonis <chs@odoo.com>
Remove most values uselessly specified because giving the same value as
the default one (see _DEFAULT_MANIFEST in odoo/modules/module.py)
* auto_install is Falsy by default
* author is Odoo SA by default
* summary & description are empty strings by default
* application is False by default
* test, demo, depends and data are empty lists by default
This will reduce noise/inconsistencies between manifests specifications,
simplify analysis of manifests content, ...
closesodoo/odoo#90209
Related: odoo/enterprise#26807
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
On a receipt, when defining the expiration date of a lot, the SML keeps
<today> as expiration date
To reproduce the issue:
1. Edit the operation type "Receipts":
- Show Detailed Operations: True
- Use Existing Lots/Serial Numbers: True
2. Create a product P:
- Type: Storable
- Tracking: By Lots
- Expiration Date: Enabled
3. Create a planned receipt R with 1 x P
4. Mark R as Todo
5. Add a detailed operations:
- 1 x P with new lot L
6. Edit the lot:
- Expiration Date: <today + 7days>
Error: When saving the picking (with the lot updated), the expiration
date is incorrect (set to <today>).
OPW-2785256
closesodoo/odoo#88283
X-original-commit: dd78e43a6286f798c54cf6b3222d3861b9dad34f
Signed-off-by: Steve Van Essche <svs@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
When printing Lot/SNs barcodes, it's sometimes desired that we print a
GS1 compliant datamatrix with the following info (when applicable):
Product barcode,
Lot/SN barcode,
Best By Date,
Expiration Date
For flexibility, a setting has been added for when the GS1 datamatrix
should print instead of 1D barcode.
Note that datamatrix will automatically exclude invalid product barcodes
(i.e. non-EAN compliant) and datamatrix size can vary based on amount
of data in datamatrix (so size has been set to accomodate expected
largest gs1 compliant datamatrix possible).
If it appears that datamatrix cannot be created, then default to
standard 1D barcode. Note that zpl printer has built in datamatrix
creation command, so we can always assume they will print correctly.
Part of Task: 2494740
Part-of: odoo/odoo#82389
When a product's barcode is EAN compliant (i.e. EAN-8, EAN-13, GTIN-14})
and feature to create DataMatrix is fully installed then we would like
to print its GS1 datamatrix on the package content report.
Additionally, if the product is tracked, we would like to include its
SN/Lot if assigned one + any "use by"/"expiration date" to make the
overall usefulness of the report go up.
Part of Task: 2494740
Part-of: odoo/odoo#82389
Two updates:
1. Match the ZPL layout, i.e. remove text centering / horizonal lines.
2. Make layout match 4x12 format (same used by Product Labels). Note
that unlike the Product Labels, we expect the lot labels to ALWAYS be
printed in a 4x12 format (i.e. we keep it simple and contained within
1 template).
Task: 2494740
Part-of: odoo/odoo#82389
Several UX improvements:
1 - Add "Unbuild" filter to MOs (1 or more 'Done' unbuilds) + added
Unbuilds smart button to MO form view
2 - When copying an operation across BoMs, it is annoying that it adds
"Copy" to the end of the name, so we remove that.
3 - Display a warning when using an expired Lot/SN in detailed operations
view (burger window + tab).
4 - Allow adding/removing WO Real Duration + add/remove/edit specific time
time tracking (time_ids) for Done, Unlocked MOs.
5 - Allow search WOs by product to manufacture
7 - Fix validation error message typo
Parts 1-5 and 7 of Task: 2667151
Part-of: odoo/odoo#80319
This commit adresses to two issues:
Since 0c83542a93dde8dcaead04fadb7db95cf627a8b4, the move line's `expiration_date`
set by the user is always overrided at the creation of the move which
means the user has to modify it after the move was created.
To fix that, the compute doesn't override the `expiration_date` if there
is already one set.
Therefore, the onchange on the product who was removed is re-added to
force to recompute the `expiration_date` if the move line's product is
changed and it has already an `expiration_date` set.
closesodoo/odoo#78189
X-original-commit: db2881c4b6dc02b68ad61c1be8464d874f9115db
Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
Signed-off-by: Steve Van Essche <svs-odoo@users.noreply.github.com>