-
-
Notifications
You must be signed in to change notification settings - Fork 729
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by pedrobaeza
- Loading branch information
Showing
35 changed files
with
2,729 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../stock_vlm_mgmt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
=============================== | ||
Vertical Lift Module management | ||
=============================== | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:16cc58033099be982092f3cf06236fc4a8ab693fcfa4ff09ff5555062362ce43 | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |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--warehouse-lightgray.png?logo=github | ||
:target: https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_vlm_mgmt | ||
:alt: OCA/stock-logistics-warehouse | ||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
:target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-16-0/stock-logistics-warehouse-16-0-stock_vlm_mgmt | ||
: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-warehouse&target_branch=16.0 | ||
:alt: Try me on Runboat | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
This module adds basic a management system for Vertical Lift Modules. It's thought as | ||
a simpler alternative attemp to stock_vertical_lift and all the dependencies that | ||
come with it. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Known issues / Roadmap | ||
====================== | ||
|
||
* Launch the tasks in batches so we don't have to send them to the VLM one by one. In | ||
the case of Kardex, we'll be dealing with the connection limitations. If we send a | ||
list of tasks, right now we're closing the connection once we receive a response (Kardex). | ||
We need to keep listening until all the ids are received, but that locks our thread... | ||
We also need to respond to operation issues on every task, like full trays, changes | ||
of quantity, etc... and we can't lock many threads as we could put down the instance. | ||
Something along the lines of queue_job maybe would need to push to the bus the tasks | ||
updates (hard?) Or maybe the kardex proxy from c2c where we use a controller to send | ||
the tasks? This should rely on js, if we want a proper UX. | ||
* Confirming the VLM tasks after the picking is confirmed makes not much sense, but | ||
we're dealing with the quants limitations. Anyway we shouldn't allow to leave | ||
operations on halt and after a real VLM task is done, the picking should be validated. | ||
What to do with the non existing quants (inputs)... maybe we could leave the vlm task | ||
pending assignation, so when we finally validate the picking we just have to perform | ||
the proper links. | ||
* Not a requiste right now, but we could need to support batch pickings. Let's deal | ||
with the basics for now anyway. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-warehouse/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-warehouse/issues/new?body=module:%20stock_vlm_mgmt%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 | ||
~~~~~~~ | ||
|
||
* Tecnativa | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* `Tecnativa <https://www.tecnativa.com>`_: | ||
|
||
* David Vidal | ||
* Pedro M. Baeza | ||
|
||
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. | ||
|
||
.. |maintainer-chienandalu| image:: https://github.com/chienandalu.png?size=40px | ||
:target: https://github.com/chienandalu | ||
:alt: chienandalu | ||
|
||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__: | ||
|
||
|maintainer-chienandalu| | ||
|
||
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/16.0/stock_vlm_mgmt>`_ project on GitHub. | ||
|
||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import models | ||
from . import wizards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright 2023 Tecnativa - David Vidal | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
{ | ||
"name": "Vertical Lift Module management", | ||
"summary": "Light self contained alternative for VLM integrations", | ||
"version": "16.0.1.0.0", | ||
"author": "Tecnativa, Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/stock-logistics-warehouse", | ||
"maintainers": ["chienandalu"], | ||
"license": "AGPL-3", | ||
"category": "Stock", | ||
"depends": ["stock", "base_sparse_field"], | ||
"data": [ | ||
"security/ir.model.access.csv", | ||
"views/stock_location_vlm_tray_views.xml", | ||
"views/stock_location_views.xml", | ||
"views/stock_picking_views.xml", | ||
"views/stock_quant_views.xml", | ||
"views/stock_vlm_task_views.xml", | ||
"views/stock_quant_vlm_views.xml", | ||
"views/stock_location_tray_type_views.xml", | ||
"wizards/stock_vlm_task_action_views.xml", | ||
], | ||
"assets": { | ||
"web.assets_backend": [ | ||
"stock_vlm_mgmt/static/src/scss/stock_vlm_mgmt.scss", | ||
"stock_vlm_mgmt/static/src/js/**/*", | ||
], | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from . import vlm_tray_cell_position_mixin | ||
from . import stock_location | ||
from . import stock_location_vlm_tray | ||
from . import stock_location_vlm_tray_type | ||
from . import stock_move_line | ||
from . import stock_picking | ||
from . import stock_quant | ||
from . import stock_vlm_task |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# Copyright 2023 Tecnativa - David Vidal | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
from odoo import _, fields, models | ||
from odoo.exceptions import UserError | ||
|
||
|
||
class StockLocation(models.Model): | ||
_inherit = "stock.location" | ||
|
||
is_vlm = fields.Boolean() | ||
vlm_vendor = fields.Selection( | ||
selection=[ | ||
("test", "Test"), | ||
], | ||
) | ||
vlm_address = fields.Char( | ||
help=( | ||
"An VLM normally will be behind some propietary proxy that handles several " | ||
"VLMs at once, so we need to set which one corresponds to this location" | ||
) | ||
) | ||
vlm_hostname = fields.Char() | ||
vlm_port = fields.Char() | ||
vlm_removal_strategy = fields.Selection( | ||
selection=[ | ||
("fifo", "FIFO"), | ||
("lifo", "LIFO"), | ||
("optimal", "Less carrier movements"), | ||
], | ||
default="fifo", | ||
) | ||
vlm_tray_ids = fields.One2many( | ||
comodel_name="stock.location.vlm.tray", inverse_name="location_id" | ||
) | ||
vlm_sequence_id = fields.Many2one(comodel_name="ir.sequence") | ||
vlm_user = fields.Char() | ||
vlm_password = fields.Char() | ||
|
||
def _prepare_vlm_request(self, **kw) -> dict: | ||
return { | ||
"task_type": kw.get("task_type", "release"), | ||
"task_id": self.vlm_sequence_id.next_by_id(), | ||
"address": self.vlm_address, | ||
"carrier": kw.get("carrier", "0"), | ||
"pos_x": kw.get("pos_x", "0"), | ||
"pos_y": kw.get("pos_y", "0"), | ||
"qty": str(kw.get("qty", "0")), | ||
"info1": kw.get("info1", "") or "", | ||
"info2": kw.get("info2", "") or "", | ||
"info3": kw.get("info3", "") or "", | ||
"info4": kw.get("info4", "") or "", | ||
} | ||
|
||
def send_vlm_request(self, data: dict, **options) -> dict: | ||
"""Send request to the vendor methods. The vendor connector should deal with | ||
the connection issues transforming the response into these standard codes: | ||
-1: Connection refused | ||
-2: The request is issued but the response is lost | ||
-3: Timeout in the request | ||
-4: VLM Hardware issues | ||
""" | ||
self.ensure_one() | ||
if not hasattr(self, "_%s_vlm_connector" % self.vlm_vendor): | ||
raise UserError(_("No implemented request connector for this vendor!")) | ||
timeout = ( | ||
self.env["ir.config_parameter"].sudo().get_param("stock_vlm_mgmt.timeout") | ||
) | ||
vlm_connector = getattr(self, "_%s_vlm_connector" % self.vlm_vendor)()( | ||
self.vlm_hostname, | ||
self.vlm_port, | ||
timeout=timeout, | ||
user=self.vlm_user, | ||
password=self.vlm_password, | ||
**options | ||
) | ||
response = vlm_connector.request_operation(data) | ||
response_code = response.get("code", "") | ||
# These negative codes are issued by the connector and they're common connection | ||
# problems. | ||
if response_code == "-1": | ||
raise UserError( | ||
_("The connection was refused by the VLM and couldn't be stablished.") | ||
) | ||
elif response_code == "-2": | ||
raise UserError( | ||
_( | ||
"The command response has been lost for unknown reasons. Did you " | ||
"perform the operation on the VLM? Make sure there aren't " | ||
"unconsistencies with the recorded data" | ||
) | ||
) | ||
elif response_code == "-3": | ||
raise UserError( | ||
_("The task couldn't be performed due to a timeout in the request"), | ||
) | ||
elif response_code == "-4": | ||
raise UserError( | ||
_( | ||
"The task couldn't be performed. Try again or check the vertical " | ||
"lift module for hardware issues" | ||
) | ||
) | ||
elif response_code == "-5": | ||
raise UserError(_("The task was cancelled by the VLM")) | ||
return response | ||
|
||
def action_release_vlm_trays(self): | ||
"""Send to the VLM a special command that releases all the trays""" | ||
data = self._prepare_vlm_request( | ||
task_type="release", | ||
info1=_( | ||
"%(user)s has requested a release of the trays from Odoo", | ||
user=self.env.user.name, | ||
), | ||
) | ||
self.send_vlm_request(data) | ||
|
||
def action_view_vlm_tray(self): | ||
action = self.env["ir.actions.act_window"]._for_xml_id( | ||
"stock_vlm_mgmt.location_vlm_tray_action" | ||
) | ||
action["domain"] = [("id", "in", self.vlm_tray_ids.ids)] | ||
action["context"] = dict(self.env.context, default_location_id=self.id) | ||
return action | ||
|
||
def action_view_vlm_quants(self): | ||
action = self.env["ir.actions.act_window"]._for_xml_id( | ||
"stock_vlm_mgmt.location_quant_vlm_action" | ||
) | ||
action["domain"] = [("location_id", "=", self.id)] | ||
action["context"] = dict( | ||
self.env.context, | ||
vlm_inventory_mode=True, | ||
) | ||
view_id = self.env.ref("stock_vlm_mgmt.view_stock_quant_inventory_tree").id | ||
action.update( | ||
{ | ||
"view_mode": "tree", | ||
"views": [ | ||
[view_id, "tree"] for view in action["views"] if view[1] == "tree" | ||
], | ||
} | ||
) | ||
return action |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Copyright 2023 Tecnativa - David Vidal | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
from odoo import _, api, fields, models | ||
from odoo.osv import expression | ||
|
||
|
||
class StockLocationVlmTray(models.Model): | ||
_name = "stock.location.vlm.tray" | ||
_description = "Individual trays in a Vertical Lift Module" | ||
|
||
name = fields.Char() | ||
location_id = fields.Many2one( | ||
comodel_name="stock.location", domain=[("is_vlm", "=", True)] | ||
) | ||
tray_type_id = fields.Many2one( | ||
comodel_name="stock.location.vlm.tray.type", required=True | ||
) | ||
tray_matrix = fields.Serialized(compute="_compute_tray_matrix") | ||
is_full = fields.Boolean() | ||
|
||
@api.depends("tray_type_id") | ||
def _compute_tray_matrix(self): | ||
"""Render empty and allocated cells""" | ||
# TODO: Unify computes and optimize query to do it in one shot | ||
for tray in self: | ||
cell_not_empty = self.env["stock.quant.vlm"].search_read( | ||
[("tray_id", "=", tray.id)], ["pos_x", "pos_y", "tray_id"] | ||
) | ||
tray_matrix = { | ||
"selected": [], | ||
"cells": tray.tray_type_id._generate_cells_matrix(), | ||
"first_empty_cell": [], | ||
} | ||
for position in cell_not_empty: | ||
# Let's be gentle with positioning errors. | ||
try: | ||
tray_matrix["cells"][position["pos_y"]][position["pos_x"]] = 1 | ||
# pylint: disable=except-pass | ||
except IndexError: | ||
pass | ||
for row, cells in enumerate(tray_matrix["cells"]): | ||
if 0 not in cells: | ||
continue | ||
tray_matrix["first_empty_cell"] = [cells.index(0), row] | ||
break | ||
tray.tray_matrix = tray_matrix | ||
|
||
def action_tray_content(self, pos_x=None, pos_y=None): | ||
"""See the vlm quants belonging to the tray""" | ||
self.ensure_one() | ||
domain = [("tray_id", "=", self.id)] | ||
if (pos_x is not None) and (pos_y is not None): | ||
domain = expression.AND( | ||
[domain, [("pos_x", "=", pos_x), ("pos_y", "=", pos_y)]] | ||
) | ||
vlm_quant = self.env["stock.quant.vlm"].search(domain) | ||
action = self.env["ir.actions.act_window"]._for_xml_id( | ||
"stock_vlm_mgmt.location_quant_vlm_action" | ||
) | ||
self.env.ref("stock_vlm_mgmt.view_location_form") | ||
action["domain"] = [("id", "in", vlm_quant.ids)] | ||
action["context"] = dict( | ||
self.env.context, | ||
default_tray_id=self.id, | ||
default_location_id=self.location_id.id, | ||
vlm_inventory_mode=True, | ||
) | ||
view_id = self.env.ref("stock_vlm_mgmt.view_stock_quant_inventory_tree").id | ||
action.update( | ||
{ | ||
"view_mode": "tree", | ||
"views": [ | ||
[view_id, "tree"] for view in action["views"] if view[1] == "tree" | ||
], | ||
} | ||
) | ||
return action | ||
|
||
def action_tray_call(self): | ||
"""Send to the VLM a special command that calls this tray""" | ||
data = self.location_id._prepare_vlm_request( | ||
task_type="count", | ||
carrier=self.name, | ||
info1=_( | ||
"%(user)s has requested a release of the trays from Odoo", | ||
user=self.env.user.name, | ||
), | ||
) | ||
self.location_id.with_context(vlm_tray_call=True).send_vlm_request(data) |
Oops, something went wrong.