Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][ADD] stock_quant_package_fast_move #1428

Open
wants to merge 2 commits into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions setup/stock_quant_package_fast_move/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
156 changes: 156 additions & 0 deletions stock_quant_package_fast_move/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
===================================
Fast Package Move Between Locations
===================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:53129da11b93c9b036f2a132594fc1be4de37f42f675ed6e844c0ad3136f7565
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_quant_package_fast_move
:alt: OCA/stock-logistics-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/stock-logistics-workflow-16-0/stock-logistics-workflow-16-0-stock_quant_package_fast_move
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-workflow&target_branch=16.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module simplifies package movement between different warehouse
locations.

You can simply select several packages and use a wizard that will
perform all the underlying inventory operations.

NB: This module depends on the `Stock Picking Move Package to Another
Package <https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_picking_move_package_to_package>`__
module. You should configure it properly in case you want to use the
**destination package** option.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

Imagine that you need to transfer different packages between different
locations in your warehouse.

Regular Odoo flow looks like this:

- Go to **Inventory -> Overview** and select an operation type (e.g.,
**Internal Transfer**).
- Create a corresponding picking.
- Add packages if **Move Entire Packages** is enabled or add all the
package products.
- Set quantities done.
- Validate.

However, if you are working with packages, you will primarily operate
from the **Packages** menu.

And it would be much more convenient if you could move packages directly
from this menu.

This is what this module is designed for.

Configuration
=============

- Go to **Inventory -> Configuration -> Settings**.
- Activate the **Packages** checkbox.
- In the **Package Move Operation**, select the operation type that
will be used for easy package transfers. Make sure that the **Move
Entire Packages** checkbox is enabled. This setting is configured for
each company separately.

|Package Fast Move Configuration|

.. |Package Fast Move Configuration| image:: https://raw.githubusercontent.com/OCA/stock-logistics-workflow/16.0/stock_quant_package_fast_move/static/img/package_fast_move_configure.png

Usage
=====

- Go to **Inventory -> Products -> Packages**.

- Open a package or select several packages in the list view.
**Important**: All selected packages must be located in the same
location.

- Open the **Action** menu and select **Move packages**.

- In the opened wizard, select the destination location where you want
to move the packages.

- You can select an optional destination package in the **Destination
Package** field. If selected, the content of the selected packages
will be moved into the destination package located at the destination
location.

- If you check **Validate**, the created internal picking will be
validated. Otherwise, it will remain in the **Ready** state.

- Click the **Move** button.

|Package Fast Move Action|

.. |Package Fast Move Action| image:: https://raw.githubusercontent.com/OCA/stock-logistics-workflow/16.0/stock_quant_package_fast_move/static/img/package_fast_move_action.png

Known issues / Roadmap
======================

Only packages residing in the same source location can be moved.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-workflow/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/stock-logistics-workflow/issues/new?body=module:%20stock_quant_package_fast_move%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Cetmix

Contributors
------------

- `Cetmix <https://cetmix.com/>`__

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/stock-logistics-workflow <https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_quant_package_fast_move>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
5 changes: 5 additions & 0 deletions stock_quant_package_fast_move/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
from . import wizard
18 changes: 18 additions & 0 deletions stock_quant_package_fast_move/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Fast Package Move Between Locations",
"version": "16.0.1.0.0",
"category": "Inventory/Inventory",
"summary": "Move packages between locations directly from the 'Package' menu",
"depends": ["stock_picking_move_package_to_package"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @angelinaanaki why do we need to depend on this module?
Are we using any of its functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ivs-cetmix, the dependency is needed because of the extension on picking validation in stock_picking_move_package_to_package necessary for package movements by setting the package_dest_id field in _move_to_location.

"website": "https://github.com/OCA/stock-logistics-workflow",
"author": "Cetmix, Odoo Community Association (OCA)",
"installable": True,
"data": [
"security/ir.model.access.csv",
"wizard/stock_quant_package_fast_move_wizard.xml",
"views/res_config_settings_view.xml",
],
"license": "AGPL-3",
}
6 changes: 6 additions & 0 deletions stock_quant_package_fast_move/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import stock_quant_package
from . import res_company
from . import res_config_settings
15 changes: 15 additions & 0 deletions stock_quant_package_fast_move/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

package_move_picking_type_id = fields.Many2one(
"stock.picking.type",
string="Package Move Operation",
domain="[('show_entire_packs', '=', True)]",
)
use_batch_transfers = fields.Boolean()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any use for having this option?

15 changes: 15 additions & 0 deletions stock_quant_package_fast_move/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

package_move_picking_type_id = fields.Many2one(
related="company_id.package_move_picking_type_id", readonly=False
)
use_batch_transfers = fields.Boolean(
related="company_id.use_batch_transfers", readonly=False
)
165 changes: 165 additions & 0 deletions stock_quant_package_fast_move/models/stock_quant_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Copyright (C) 2023 Cetmix OÜ
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, exceptions, models


class StockQuantPackage(models.Model):
_inherit = "stock.quant.package"

def action_show_package_fast_move_wizard(self):
"""Open wizard for fast package movement."""
return {

Check warning on line 12 in stock_quant_package_fast_move/models/stock_quant_package.py

View check run for this annotation

Codecov / codecov/patch

stock_quant_package_fast_move/models/stock_quant_package.py#L12

Added line #L12 was not covered by tests
"type": "ir.actions.act_window",
"name": _("Move Packages"),
"res_model": "stock.quant.package.fast.move.wizard",
"target": "new",
"view_id": self.env.ref(
"stock_quant_package_fast_move.stock_quant_package_fast_move_wizard_view_form"
).id,
"view_mode": "form",
"context": self.env.context,
}

def create_batch_transfer(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def create_batch_transfer(
def _move_with_batch_transfer(

self, location, destination_package, validate, picking_type_id
):
"""
Creates a new Batch Transfer and a separate picking for each package,
adds them to the Batch Transfer, and confirms the transfer. If the "validate"
option is enabled, the batch is also validated.

Parameters:
- location (recordset of stock.location): The destination location.
- destination_package (recordset of stock.quant.package, optional):
Optional destination package. If provided, it must belong to the specified location.
- validate (boolean): If set to True, the created picking will be validated.
Otherwise it will remain in the "Ready" state. Defaults to False.
- picking_type_id (recordset of stock.picking.type):
The picking type to be used for the transfer, as configured in settings.
"""
# Create a batch transfer
batch_vals = {
"picking_type_id": picking_type_id.id,
}
batch_transfer = self.env["stock.picking.batch"].create(batch_vals)

for package in self:
# Create a picking
picking_vals = {
"location_id": package.location_id.id,
"location_dest_id": location.id,
"picking_type_id": picking_type_id.id,
}
picking = self.env["stock.picking"].create(picking_vals)

# Create a package_level record
package_level_vals = {
"package_id": package.id,
"package_dest_id": destination_package.id
if destination_package
else False,
"picking_id": picking.id,
"company_id": self.env.company.id,
"location_id": package.location_id.id,
"location_dest_id": location.id,
}
package_level = self.env["stock.package_level"].create(package_level_vals)
package_level.write({"is_done": True})
picking.write({"batch_id": batch_transfer.id})

# Confirm the Batch Transfer
batch_transfer.action_confirm()

if validate:
# Validate the Batch Transfer
batch_transfer.action_done()

def _move_to_location(self, location, destination_package=None, validate=False):
"""
Move packages to a specified location.

Parameters:
- location (recordset of stock.location): The destination location.
- destination_package (recordset of stock.quant.package, optional):
Optional destination package. If provided, it must belong to the specified location.
- validate (boolean, optional):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If set to True, the created picking will be validated. Otherwise it will remain in the "Ready" state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your review. Could you please check it again?

If set to True, the created picking will be validated.
Otherwise it will remain in the "Ready" state. Defaults to False.

Returns:
- bool: True if the move is successful.

Raises:
- exceptions.UserError: If the source location of the packages is different,
If the destination location is the same as the current location
or if the destination package does not belong to the specified location.
"""

# Check if the location is different from the current location
if location == self[0].location_id and not destination_package:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you only check the location_id in the first package?

What will happen if packages from different location_ids are selected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't spot where is that check? And why is this necessary that they are all in the same source location?

Suggested change
if location == self[0].location_id and not destination_package:
if location in self.location_id and not destination_package:

raise exceptions.UserError(
_("The destination location is the same as the current location.")
)

# Check if the destination package belongs to the same location
# If the location_id is False it means that the package is new or empty
if (
destination_package
and destination_package.location_id
and destination_package.location_id != location
):
raise exceptions.UserError(
_("The destination package does not belong to the specified location.")
)

active_company = self.env.company
picking_type_id = active_company.package_move_picking_type_id
use_batch_transfers = active_company.use_batch_transfers

if use_batch_transfers:
self.create_batch_transfer(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
self.create_batch_transfer(
self._move_with_batch_transfer(

location, destination_package, validate, picking_type_id
)
else:
# Create a picking
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you create a method for above option, create also a method for this option like
_move_with_picking(location, destination_package, validate, picking_type_id)
to be consistent

picking_vals = {
"location_id": self[0].location_id.id,
"location_dest_id": location.id,
"picking_type_id": picking_type_id.id,
}
picking = self.env["stock.picking"].create(picking_vals)

for package in self:
# Create a package_level record for each package
package_level_vals = {
"package_id": package.id,
"package_dest_id": destination_package.id
if destination_package
else False,
"picking_id": picking.id,
"company_id": active_company.id,
"location_id": package.location_id.id,
"location_dest_id": location.id,
}
self.env["stock.package_level"].create(package_level_vals)

picking.action_confirm()
# Set the is_done flag to True for all package levels
# associated with the created picking
picking.package_level_ids.write({"is_done": True})
if validate:
# Validate the picking
picking.button_validate()

return True

def create_new_package(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need this hook, then move it inside the wizard as this serves the wizard only

"""
Create a new stock package.

Returns:
- package (recordset of stock.quant.package): The newly created package object.
"""
package = self.env["stock.quant.package"].create({})
return package

Check warning on line 165 in stock_quant_package_fast_move/models/stock_quant_package.py

View check run for this annotation

Codecov / codecov/patch

stock_quant_package_fast_move/models/stock_quant_package.py#L164-L165

Added lines #L164 - L165 were not covered by tests
Comment on lines +157 to +165
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just create a package inline?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just create a package inline?

This is in case someone would need to implement some custom flow here

Loading
Loading