Skip to content

Commit

Permalink
Merge PR #2102 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by pedrobaeza
  • Loading branch information
OCA-git-bot committed Jul 12, 2024
2 parents 464d66f + 018496a commit 1fb4df4
Show file tree
Hide file tree
Showing 35 changed files with 2,729 additions and 0 deletions.
1 change: 1 addition & 0 deletions setup/stock_vlm_mgmt/odoo/addons/stock_vlm_mgmt
6 changes: 6 additions & 0 deletions setup/stock_vlm_mgmt/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,
)
110 changes: 110 additions & 0 deletions stock_vlm_mgmt/README.rst
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.
2 changes: 2 additions & 0 deletions stock_vlm_mgmt/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
30 changes: 30 additions & 0 deletions stock_vlm_mgmt/__manifest__.py
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/**/*",
],
},
}
8 changes: 8 additions & 0 deletions stock_vlm_mgmt/models/__init__.py
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
144 changes: 144 additions & 0 deletions stock_vlm_mgmt/models/stock_location.py
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
89 changes: 89 additions & 0 deletions stock_vlm_mgmt/models/stock_location_vlm_tray.py
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)
Loading

0 comments on commit 1fb4df4

Please sign in to comment.