commit 1f20ad87e690f4c83cd3b4f5b7439375092bb343 Author: Ernad Husremovic Date: Fri Aug 29 15:49:21 2025 +0200 Initial commit: Ventor Odoo packages (4 packages) diff --git a/README.md b/README.md new file mode 100644 index 0000000..d187a47 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Ventor Odoo Packages + +This repository contains **4** Odoo packages from Ventor vendor. + +## About Ventor + +Ventor is a recognized vendor in the Odoo ecosystem, providing specialized addons and customizations. + +## Packages Included (4 packages) + +- **odoo-bringout-ventor-custom_import_wizard** - Custom Import Wizard +- **odoo-bringout-ventor-outgoing_routing** - Outgoing Routing +- **odoo-bringout-ventor-product_multiple_barcodes** - Product Multiple Barcodes +- **odoo-bringout-ventor-ventor_base** - Ventor Base + + +## Installation + +Install any package from this collection: + +```bash +# Install from local directory +pip install packages/ventor/PACKAGE_NAME/ + +# Install in development mode +pip install -e packages/ventor/PACKAGE_NAME/ + +# Using uv (recommended for speed) +uv add packages/ventor/PACKAGE_NAME/ +``` + +## Repository Structure + +Each package in this repository follows the standard Odoo addon structure: + +``` +ventor/ +├── odoo-bringout-ventor-ADDON/ +│ ├── ADDON_NAME/ # Complete addon code +│ │ ├── __init__.py +│ │ ├── __manifest__.py +│ │ └── ... (models, views, etc.) +│ ├── pyproject.toml # Python package configuration +│ └── README.md # Package documentation +└── ... +``` + +## License + +Each package maintains its original license as specified by Ventor. + +## Support + +For support with these packages, please refer to the original Ventor documentation or community resources. diff --git a/odoo-bringout-ventor-custom_import_wizard/README.md b/odoo-bringout-ventor-custom_import_wizard/README.md new file mode 100644 index 0000000..b41d39f --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/README.md @@ -0,0 +1,46 @@ +# Custom Import Wizard + +Custom Odoo addon: custom_import_wizard + +## Installation + +```bash +pip install odoo-bringout-ventor-custom_import_wizard +``` + +## Dependencies + +This addon depends on: + + +## Manifest Information + +- **Name**: Custom Import Wizard +- **Version**: 16.0.1.0.0 +- **Category**: Tools +- **License**: LGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-ventor vendor, addon `custom_import_wizard`. + +## License + +This package maintains the original LGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/README.rst b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/README.rst new file mode 100644 index 0000000..a908256 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/README.rst @@ -0,0 +1,2 @@ +Custom Import Wizard +==================== diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__init__.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__init__.py new file mode 100644 index 0000000..ed4e30e --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +# Localfolder: +from . import models +from . import wizard diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__manifest__.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__manifest__.py new file mode 100644 index 0000000..081fd1b --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/__manifest__.py @@ -0,0 +1,22 @@ +# pylint: disable=missing-docstring +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +{ + "name": "Custom Import Wizard", + "category": "Tools", + "version": "16.0.1.0.0", + "website": "https://ventor.tech", + "author": "VentorTech OU", + "license": "LGPL-3", + "depends": [], + "data": [ + "security/security.xml", + "security/ir.model.access.csv", + "views/custom_import_history.xml", + "wizard/custom_import_wizard.xml", + "wizard/info_result_import_wizard.xml", + ], + "external_dependencies": {"python": ["xlrd"]}, + "installable": True, +} diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/doc/index.rst b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/doc/index.rst new file mode 100644 index 0000000..a908256 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/doc/index.rst @@ -0,0 +1,2 @@ +Custom Import Wizard +==================== diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/bs.po b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/bs.po new file mode 100644 index 0000000..604f9b3 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/bs.po @@ -0,0 +1,230 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * custom_import_wizard +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:42+0000\n" +"PO-Revision-Date: 2022-08-18 13:42+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Are you sure?" +msgstr "Are you sure?" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Cancel" +msgstr "Otkaži" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__create_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__create_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__create_uid +msgid "Created by" +msgstr "Kreirao" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__create_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__create_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__create_date +msgid "Created on" +msgstr "Kreirano" + +#. module: custom_import_wizard +#: model:res.groups,name:custom_import_wizard.custom_import_group_user +msgid "Custom Import" +msgstr "Prilagođeni uvoz" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_custom_import_history +msgid "Custom Import History" +msgstr "Prilagođeni uvoz History" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_custom_import_wizard +msgid "Custom Import Wizard" +msgstr "Prilagođeni uvoz Čarobnjak" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__display_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__display_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__display_name +msgid "Display Name" +msgstr "Prikazani naziv" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__error_details +msgid "Error Details" +msgstr "Greška Detalji" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__extra_info +msgid "Extra Info" +msgstr "Dodatne informacije" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Final Import" +msgstr "Final Uvoz" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__formatted_file +msgid "Formatted File" +msgstr "Formaatted File" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__formatted_file_name +msgid "Formatted File Name" +msgstr "Formaatted File Naziv" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__id +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__id +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__id +msgid "ID" +msgstr "ID" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Import" +msgstr "Uvoz" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__name +msgid "Import Date" +msgstr "Uvoz Datum" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_history_view_form +msgid "Import History" +msgstr "Uvoz History" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_history_view_form +msgid "Imported by" +msgstr "Uvozed by" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.view_info_result_import_wizard +msgid "Info" +msgstr "Informacija" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_info_result_import_wizard +msgid "Info Result Import Wizard" +msgstr "Info Result Uvoz Čarobnjak" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__message +msgid "Info: " +msgstr "Info: " + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history____last_update +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard____last_update +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard____last_update +msgid "Last Modified on" +msgstr "Zadnje mijenjano" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__write_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__write_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__write_uid +msgid "Last Updated by" +msgstr "Zadnji ažurirao" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__write_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__write_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__write_date +msgid "Last Updated on" +msgstr "Zadnje ažurirano" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__model +msgid "Model" +msgstr "Model" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.view_info_result_import_wizard +msgid "OK" +msgstr "U redu" + +#. module: custom_import_wizard +#: model:res.groups,comment:custom_import_wizard.custom_import_group_user +msgid "Only responsible can access import functionallity" +msgstr "Samo odgovorna osoba može pristupiti funkciji uvoza" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__original_file +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__original_file +msgid "Original File" +msgstr "Original File" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__original_file_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__original_file_name +msgid "Original File Name" +msgstr "Original File Naziv" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__result_file +msgid "Result File" +msgstr "Result File" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__result_file_name +msgid "Result File Name" +msgstr "Result File Naziv" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__sample_file +msgid "Sample File" +msgstr "Sample File" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Sample Format" +msgstr "Sample Formaat" + +#. module: custom_import_wizard +#: code:addons/custom_import_wizard/wizard/custom_import_wizard.py:0 +#, python-format +msgid "" +"Successfully imported: {} | Duplicates not imported: {} | Error importing " +"(bad info): {}" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Test Import" +msgstr "Test Uvoz" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_duplicated +msgid "Total Duplicated" +msgstr "Ukupno Duplicated" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_errors +msgid "Total Errors" +msgstr "Ukupno Greškas" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_imported +msgid "Total Imported" +msgstr "Ukupno Uvozed" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__user_id +msgid "User" +msgstr "Korisnik" diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/custom_import_wizard.pot b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/custom_import_wizard.pot new file mode 100644 index 0000000..eb7d08c --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/i18n/custom_import_wizard.pot @@ -0,0 +1,230 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * custom_import_wizard +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:42+0000\n" +"PO-Revision-Date: 2022-08-18 13:42+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Are you sure?" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Cancel" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__create_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__create_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__create_uid +msgid "Created by" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__create_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__create_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__create_date +msgid "Created on" +msgstr "" + +#. module: custom_import_wizard +#: model:res.groups,name:custom_import_wizard.custom_import_group_user +msgid "Custom Import" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_custom_import_history +msgid "Custom Import History" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_custom_import_wizard +msgid "Custom Import Wizard" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__display_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__display_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__display_name +msgid "Display Name" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__error_details +msgid "Error Details" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__extra_info +msgid "Extra Info" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Final Import" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__formatted_file +msgid "Formatted File" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__formatted_file_name +msgid "Formatted File Name" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__id +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__id +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__id +msgid "ID" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Import" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__name +msgid "Import Date" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_history_view_form +msgid "Import History" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_history_view_form +msgid "Imported by" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.view_info_result_import_wizard +msgid "Info" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model,name:custom_import_wizard.model_info_result_import_wizard +msgid "Info Result Import Wizard" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__message +msgid "Info: " +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history____last_update +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard____last_update +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard____last_update +msgid "Last Modified on" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__write_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__write_uid +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__write_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__write_date +#: model:ir.model.fields,field_description:custom_import_wizard.field_info_result_import_wizard__write_date +msgid "Last Updated on" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__model +msgid "Model" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.view_info_result_import_wizard +msgid "OK" +msgstr "" + +#. module: custom_import_wizard +#: model:res.groups,comment:custom_import_wizard.custom_import_group_user +msgid "Only responsible can access import functionallity" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__original_file +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__original_file +msgid "Original File" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__original_file_name +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__original_file_name +msgid "Original File Name" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__result_file +msgid "Result File" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__result_file_name +msgid "Result File Name" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_wizard__sample_file +msgid "Sample File" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Sample Format" +msgstr "" + +#. module: custom_import_wizard +#: code:addons/custom_import_wizard/wizard/custom_import_wizard.py:0 +#, python-format +msgid "" +"Successfully imported: {} | Duplicates not imported: {} | Error importing " +"(bad info): {}" +msgstr "" + +#. module: custom_import_wizard +#: model_terms:ir.ui.view,arch_db:custom_import_wizard.custom_import_wizard_view_form +msgid "Test Import" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_duplicated +msgid "Total Duplicated" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_errors +msgid "Total Errors" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__total_imported +msgid "Total Imported" +msgstr "" + +#. module: custom_import_wizard +#: model:ir.model.fields,field_description:custom_import_wizard.field_custom_import_history__user_id +msgid "User" +msgstr "" diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/__init__.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/__init__.py new file mode 100644 index 0000000..a3e8853 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +# Localfolder: +from . import custom_import_history diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/custom_import_history.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/custom_import_history.py new file mode 100644 index 0000000..714074a --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/models/custom_import_history.py @@ -0,0 +1,31 @@ +""" + Copyright 2020 VentorTech OU + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). +""" + +# Stdlib: +from datetime import datetime + +# Odoo: +from odoo import fields, models + + +# pylint: disable=too-few-public-methods +class CustomImportHistory(models.Model): + """ History for import """ + + _name = "custom.import.history" + _description = "Custom Import History" + + name = fields.Datetime(default=lambda self: datetime.now(), string="Import Date") + original_file = fields.Binary() + formatted_file = fields.Binary() + original_file_name = fields.Char() + formatted_file_name = fields.Char() + total_imported = fields.Integer() + total_duplicated = fields.Integer() + total_errors = fields.Integer() + user_id = fields.Many2one("res.users", default=lambda self: self.env.user) + model = fields.Char() + extra_info = fields.Char() + error_details = fields.Char() diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/ir.model.access.csv b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/ir.model.access.csv new file mode 100644 index 0000000..259f1a3 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +import_history,import_history,model_custom_import_history,custom_import_wizard.custom_import_group_user,1,0,1,0 +import_custom_wizard,import_custom_wizard,model_custom_import_wizard,custom_import_wizard.custom_import_group_user,1,0,1,0 +info_result_import_wizard,info_result_import_wizard,model_info_result_import_wizard,custom_import_wizard.custom_import_group_user,1,0,1,0 +import_history_admin,import_history,model_custom_import_history,base.group_system,1,1,1,1 diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/security.xml b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/security.xml new file mode 100644 index 0000000..7a401b6 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/security/security.xml @@ -0,0 +1,6 @@ + + + Custom Import + Only responsible can access import functionallity + + diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/icon.png b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/icon.png new file mode 100644 index 0000000..c915932 Binary files /dev/null and b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/icon.png differ diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/index.html b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/index.html new file mode 100644 index 0000000..5c025de --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/static/description/index.html @@ -0,0 +1,29 @@ +
+
+
+

Custom Import Wizard

+
+
+

+ TO AVOID ANY ISSUES, PLEASE, USE ALWAYS LATEST VERSION FROM OUR GITHUB REPOSITORY - + + https://github.com/ventor-tech/merp/tree/16.0 + +

+
+
+
+ +
+
+
+

Notes

+

+ VentorTech (https://ventor.tech/) is company specialized on building Personalized Inventory and Product Management System. +

+

+For all questions contact hello@ventor.tech. +

+
+
+
diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/views/custom_import_history.xml b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/views/custom_import_history.xml new file mode 100644 index 0000000..207a394 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/views/custom_import_history.xml @@ -0,0 +1,41 @@ + + + + + + + custom.import.history.view.form + custom.import.history + +
+ + + + + + + + + + + + + + +
+
+
+ + + + custom.import.history.view.tree + custom.import.history + + + + + + + + +
diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/__init__.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/__init__.py new file mode 100644 index 0000000..05e6ea0 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +# Localfolder: +from . import custom_import_wizard +from . import info_result_import_wizard diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.py new file mode 100644 index 0000000..671d06e --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.py @@ -0,0 +1,257 @@ +""" + Copyright 2020 VentorTech OU + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). +""" + +# Stdlib: +import binascii +import io +import logging +from collections import defaultdict + +# Odoo: +from odoo import _, fields, models +from odoo.exceptions import ValidationError + +# Thirdparty: +import xlrd + +try: + from odoo.tools.misc import xlsxwriter +except ImportError: + import xlsxwriter + +_logger = logging.getLogger(__name__) + +IMPORT_STATUSES = ["success", "error", "duplicate"] + + +class CustomImportWizard(models.TransientModel): + """ Allows you to import records without duplicates and errors """ + + _name = "custom.import.wizard" + _description = "Custom Import Wizard" + + original_file = fields.Binary() + original_file_name = fields.Char() + result_file = fields.Binary() + result_file_name = fields.Char() + sample_file = fields.Binary() + + def read_original_file(self, no_convert_indexes=None): + """ Get data from imported file """ + + if no_convert_indexes is None: + no_convert_indexes = [] + if not self.original_file: + raise ValidationError('No file!') + book = xlrd.open_workbook( + file_contents=binascii.a2b_base64(self.original_file) or b"" + ) + sheet = book.sheet_by_index(0) + lines = [] + for row_no in range(1, sheet.nrows): + row = sheet.row(row_no) + if all([not str(cell.value).strip() for cell in row]): + continue + lines.append(self.read_original_line(row)) + return lines + + # pylint: disable=no-self-use + def read_original_line(self, row): + """ This method is for formatting raw data from a cell """ + + line = {"values": [], "errors": [], "status": "success"} + for cell in row: + line["values"].append(str(cell.value)) + return line + + # pylint: disable=no-self-use + def _get_formats(self): + return { + "header": {"align": "center", "bold": True, "font_size": "10px"}, + "success": {"font_size": "8px"}, + "error": {"font_size": "8px", "bg_color": "#fccfac"}, + "duplicate": {"font_size": "8px", "bg_color": "#f29d9d"}, + } + + def write_result_file(self, headers, lines): + """ + Writes result XLSX file + Arguments: + headers {list} -- List of column headers ['Company Name', 'Email'] + ] + lines {list} -- List of dictionaries [ + { + 'values': ['My Company', 'test@example.com'], + 'errors': [], + 'status': 'success' + }, + { + 'values': ['Mega LLC', 'mega@example.com'], + 'errors': ['Error 1', 'Error 2'], + 'status': 'error' + }, + ] + """ + with io.BytesIO() as output: + with xlsxwriter.Workbook(output, {"in_memory": True}) as workbook: + sheet = workbook.add_worksheet() + sheet.set_column(0, 12, 30) + + col = row = 0 + # Write headers + for header in headers: + sheet.write(row, col, header) + col += 1 + + def _write_lines_by_status(lines_by_status, row): + for line in lines_by_status: + row += 1 + col = 0 + # Write line values + for val in line["values"]: + sheet.write(row, col, val) + col += 1 + # Write Status + sheet.write(row, col, line["status"]) + # Write Errors + col += 1 + sheet.write(row, col, "; ".join(line["errors"])) + + return row + + for status in IMPORT_STATUSES: + row = _write_lines_by_status( + filter(lambda l, st=status: l["status"] == st, lines), row + ) + + output.seek(0) + self.result_file = binascii.b2a_base64(output.read()) + self.result_file_name = self.original_file_name.replace( + ".xlsx", "_formatted.xlsx" + ) + + def download_result_file(self): + """ Downloading file from odoo field""" + + return { + "name": "Result File", + "type": "ir.actions.act_url", + "url": ( + "/web/content/?model={model}&id={id}&field=result_file&" + "download=true&filename={fname}" + ).format(model=self._name, id=self.id, fname=self.result_file_name), + "target": "new", + } + + # pylint: disable=no-self-use + def _get_model_name(self): + return "" + + # pylint: disable=no-self-use + def _get_extra_info(self): + return "" + + def create_import_history(self, totals): + """ + Creating history for created lines + + Arguments: + totals {dict} + + Returns: + record("custom.import.history") -- history of created records + """ + + return self.env["custom.import.history"].create( + { + "original_file": self.original_file, + "formatted_file": self.result_file, + "original_file_name": self.original_file_name, + "formatted_file_name": self.result_file_name, + "extra_info": self._get_extra_info(), + "total_imported": totals.get("success", 0), + "total_duplicated": totals.get("duplicate", 0), + "total_errors": totals.get("error", 0), + "model": self._get_model_name(), + } + ) + + # pylint: disable=no-self-use,unused-argument + def handle_import(self, test=True): + """ + Inherit and override this method in child model + + Arguments: + totals {boolean} -- indicates test import + + Returns: + {list} -- list of lines + """ + return [] + + def test_import(self): + """ Download formatted file without importing correct records to db """ + + self.handle_import() + return self.download_result_file() + + # pylint: disable=no-self-use + def get_totals(self, lines): + """ + Count totals of imported lines splited by import statuses + """ + res = defaultdict(int) + for line in lines: + res[line["status"]] += 1 + return res + + def final_import(self): + """ Importing correct record """ + + lines = self.handle_import(test=False) + import_history_record = self.create_import_history(self.get_totals(lines)) + context = { + "default_message": _( + "Successfully imported: {} | " + "Duplicates not imported: {} | Error importing (bad info): {}" + ).format( + import_history_record.total_imported, + import_history_record.total_duplicated, + import_history_record.total_errors, + ) + } + return { + "name": "Import Leads Info", + "type": "ir.actions.act_window", + "res_model": "info.result.import.wizard", + "view_mode": "form", + "view_type": "form", + "target": "new", + "context": context, + } + + # pylint: disable=no-self-use + def _get_sample_file_path(self): + """ + Inherit and override this method in child models + Return a path the sample xlsx file that will be returned to the user + """ + return "" + + def print_sample_xlsx(self): + """ Print sample file how to should be created leads """ + + xlsx_file_path = self._get_sample_file_path() + file_content = open(xlsx_file_path, "rb").read() + self.sample_file = binascii.b2a_base64(file_content) + return { + "name": "Sample File", + "type": "ir.actions.act_url", + "url": ( + "/web/content/?model={model}&id={id}&field=sample_file&" + "download=true&filename={fname}" + ).format(model=self._name, id=self.id, fname="Sample Import.xlsx"), + "target": "new", + } diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.xml b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.xml new file mode 100644 index 0000000..8cd4f64 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/custom_import_wizard.xml @@ -0,0 +1,40 @@ + + + + + custom.import.wizard.form + custom.import.wizard + +
+ + + + +
+
+
+
+
+ +
diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.py b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.py new file mode 100644 index 0000000..ae3434c --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.py @@ -0,0 +1,11 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +# Odoo: +from odoo import fields, models + + +class InfoResultImportWizard(models.TransientModel): + _name = "info.result.import.wizard" + _description = "Info Result Import Wizard" + message = fields.Char(string="Info: ", readonly=True, store=True) diff --git a/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.xml b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.xml new file mode 100644 index 0000000..bda6e55 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/custom_import_wizard/wizard/info_result_import_wizard.xml @@ -0,0 +1,18 @@ + + + + + info.result.import.wizard.form + info.result.import.wizard + +
+ + + +
+
+
+
+
+
diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/ARCHITECTURE.md b/odoo-bringout-ventor-custom_import_wizard/doc/ARCHITECTURE.md new file mode 100644 index 0000000..c0dd47b --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Custom_import_wizard Module - custom_import_wizard + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/CONFIGURATION.md b/odoo-bringout-ventor-custom_import_wizard/doc/CONFIGURATION.md new file mode 100644 index 0000000..902a09c --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for custom_import_wizard. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/CONTROLLERS.md b/odoo-bringout-ventor-custom_import_wizard/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/DEPENDENCIES.md b/odoo-bringout-ventor-custom_import_wizard/doc/DEPENDENCIES.md new file mode 100644 index 0000000..3b4b1b6 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/DEPENDENCIES.md @@ -0,0 +1,3 @@ +# Dependencies + +No explicit module dependencies declared. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/FAQ.md b/odoo-bringout-ventor-custom_import_wizard/doc/FAQ.md new file mode 100644 index 0000000..08d5f4d --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon custom_import_wizard or install in UI. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/INSTALL.md b/odoo-bringout-ventor-custom_import_wizard/doc/INSTALL.md new file mode 100644 index 0000000..8192f1a --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-ventor-custom_import_wizard" +# or +uv pip install odoo-bringout-ventor-custom_import_wizard" +``` diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/MODELS.md b/odoo-bringout-ventor-custom_import_wizard/doc/MODELS.md new file mode 100644 index 0000000..ddf26a6 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/MODELS.md @@ -0,0 +1,12 @@ +# Models + +Detected core models and extensions in custom_import_wizard. + +```mermaid +classDiagram + class custom_import_history +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/OVERVIEW.md b/odoo-bringout-ventor-custom_import_wizard/doc/OVERVIEW.md new file mode 100644 index 0000000..920fe51 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: custom_import_wizard. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon custom_import_wizard +- License: LGPL-3 diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/REPORTS.md b/odoo-bringout-ventor-custom_import_wizard/doc/REPORTS.md new file mode 100644 index 0000000..e0ea35f --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/REPORTS.md @@ -0,0 +1,3 @@ +# Reports + +This module does not define custom reports. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/SECURITY.md b/odoo-bringout-ventor-custom_import_wizard/doc/SECURITY.md new file mode 100644 index 0000000..99fdf8e --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/SECURITY.md @@ -0,0 +1,42 @@ +# Security + +Access control and security definitions in custom_import_wizard. + +## Access Control Lists (ACLs) + +Model access permissions defined in: +- **[ir.model.access.csv](../custom_import_wizard/security/ir.model.access.csv)** + - 4 model access rules + +## Record Rules + +Row-level security rules defined in: + +## Security Groups & Configuration + +Security groups and permissions defined in: +- **[security.xml](../custom_import_wizard/security/security.xml)** + - 1 security groups defined + +```mermaid +graph TB + subgraph "Security Layers" + A[Users] --> B[Groups] + B --> C[Access Control Lists] + C --> D[Models] + B --> E[Record Rules] + E --> F[Individual Records] + end +``` + +Security files overview: +- **[ir.model.access.csv](../custom_import_wizard/security/ir.model.access.csv)** + - Model access permissions (CRUD rights) +- **[security.xml](../custom_import_wizard/security/security.xml)** + - Security groups, categories, and XML-based rules + +Notes +- Access Control Lists define which groups can access which models +- Record Rules provide row-level security (filter records by user/group) +- Security groups organize users and define permission sets +- All security is enforced at the ORM level by Odoo diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/TROUBLESHOOTING.md b/odoo-bringout-ventor-custom_import_wizard/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/USAGE.md b/odoo-bringout-ventor-custom_import_wizard/doc/USAGE.md new file mode 100644 index 0000000..e81ab22 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon custom_import_wizard +``` diff --git a/odoo-bringout-ventor-custom_import_wizard/doc/WIZARDS.md b/odoo-bringout-ventor-custom_import_wizard/doc/WIZARDS.md new file mode 100644 index 0000000..c69e029 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/doc/WIZARDS.md @@ -0,0 +1,9 @@ +# Wizards + +Transient models exposed as UI wizards in custom_import_wizard. + +```mermaid +classDiagram + class CustomImportWizard + class InfoResultImportWizard +``` diff --git a/odoo-bringout-ventor-custom_import_wizard/pyproject.toml b/odoo-bringout-ventor-custom_import_wizard/pyproject.toml new file mode 100644 index 0000000..17150c3 --- /dev/null +++ b/odoo-bringout-ventor-custom_import_wizard/pyproject.toml @@ -0,0 +1,41 @@ +[project] +name = "odoo-bringout-ventor-custom_import_wizard" +version = "16.0.0" +description = "Custom Import Wizard - Custom Odoo addon" +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["custom_import_wizard"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +] diff --git a/odoo-bringout-ventor-outgoing_routing/README.md b/odoo-bringout-ventor-outgoing_routing/README.md new file mode 100644 index 0000000..5a1a703 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/README.md @@ -0,0 +1,48 @@ +# Picking and Reservation Strategy + +Custom Odoo addon: outgoing_routing + +## Installation + +```bash +pip install odoo-bringout-ventor-outgoing_routing +``` + +## Dependencies + +This addon depends on: +- sale_management +- stock_picking_batch +- ventor_base + +## Manifest Information + +- **Name**: Picking and Reservation Strategy +- **Version**: 16.0.1.1.0 +- **Category**: N/A +- **License**: LGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-ventor vendor, addon `outgoing_routing`. + +## License + +This package maintains the original LGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-ventor-outgoing_routing/doc/ARCHITECTURE.md b/odoo-bringout-ventor-outgoing_routing/doc/ARCHITECTURE.md new file mode 100644 index 0000000..61f4c57 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Outgoing_routing Module - outgoing_routing + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/CONFIGURATION.md b/odoo-bringout-ventor-outgoing_routing/doc/CONFIGURATION.md new file mode 100644 index 0000000..0e25ec7 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for outgoing_routing. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/CONTROLLERS.md b/odoo-bringout-ventor-outgoing_routing/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/DEPENDENCIES.md b/odoo-bringout-ventor-outgoing_routing/doc/DEPENDENCIES.md new file mode 100644 index 0000000..5040000 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/DEPENDENCIES.md @@ -0,0 +1,7 @@ +# Dependencies + +This addon depends on: + +- [sale_management](../../odoo-bringout-oca-ocb-sale_management) +- [stock_picking_batch](../../odoo-bringout-oca-ocb-stock_picking_batch) +- [ventor_base](../../odoo-bringout-ventor-ventor_base) diff --git a/odoo-bringout-ventor-outgoing_routing/doc/FAQ.md b/odoo-bringout-ventor-outgoing_routing/doc/FAQ.md new file mode 100644 index 0000000..a7e8f70 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon outgoing_routing or install in UI. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/INSTALL.md b/odoo-bringout-ventor-outgoing_routing/doc/INSTALL.md new file mode 100644 index 0000000..cb07cc6 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-ventor-outgoing_routing" +# or +uv pip install odoo-bringout-ventor-outgoing_routing" +``` diff --git a/odoo-bringout-ventor-outgoing_routing/doc/MODELS.md b/odoo-bringout-ventor-outgoing_routing/doc/MODELS.md new file mode 100644 index 0000000..6633873 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/MODELS.md @@ -0,0 +1,19 @@ +# Models + +Detected core models and extensions in outgoing_routing. + +```mermaid +classDiagram + class stock_picking + class stock_picking_batch + class stock_picking_mixin + class res_company + class res_config_settings + class stock_location + class stock_move_line + class stock_quant +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/OVERVIEW.md b/odoo-bringout-ventor-outgoing_routing/doc/OVERVIEW.md new file mode 100644 index 0000000..b6ecf48 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: outgoing_routing. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon outgoing_routing +- License: LGPL-3 diff --git a/odoo-bringout-ventor-outgoing_routing/doc/REPORTS.md b/odoo-bringout-ventor-outgoing_routing/doc/REPORTS.md new file mode 100644 index 0000000..e0ea35f --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/REPORTS.md @@ -0,0 +1,3 @@ +# Reports + +This module does not define custom reports. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/SECURITY.md b/odoo-bringout-ventor-outgoing_routing/doc/SECURITY.md new file mode 100644 index 0000000..e07da9d --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/SECURITY.md @@ -0,0 +1,8 @@ +# Security + +This module does not define custom security rules or access controls beyond Odoo defaults. + +Default Odoo security applies: +- Base user access through standard groups +- Model access inherited from dependencies +- No custom row-level security rules diff --git a/odoo-bringout-ventor-outgoing_routing/doc/TROUBLESHOOTING.md b/odoo-bringout-ventor-outgoing_routing/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-ventor-outgoing_routing/doc/USAGE.md b/odoo-bringout-ventor-outgoing_routing/doc/USAGE.md new file mode 100644 index 0000000..65aaccc --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon outgoing_routing +``` diff --git a/odoo-bringout-ventor-outgoing_routing/doc/WIZARDS.md b/odoo-bringout-ventor-outgoing_routing/doc/WIZARDS.md new file mode 100644 index 0000000..48e790d --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/doc/WIZARDS.md @@ -0,0 +1,3 @@ +# Wizards + +This module does not include UI wizards. diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/README.rst b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/README.rst new file mode 100644 index 0000000..46b5da9 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/README.rst @@ -0,0 +1,10 @@ +================================ +Picking and Reservation Strategy +================================ + +* Allows to automatically build optimal picking routes and apply custom reservation options. + +16.0.1.1.0 (2023-11-04) +*********************** + +* Fixed tests \ No newline at end of file diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__init__.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__init__.py new file mode 100644 index 0000000..3e370cb --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import models +from . import tests diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__manifest__.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__manifest__.py new file mode 100644 index 0000000..a92c81f --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/__manifest__.py @@ -0,0 +1,26 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +{ + 'name': 'Picking and Reservation Strategy', + "version": "16.0.1.1.0", + 'author': 'VentorTech', + 'website': 'https://ventor.tech/', + 'license': 'LGPL-3', + 'installable': True, + 'images': ['static/description/images/image1.JPG'], + 'summary': 'Allows to automatically build optimal picking routes and apply custom reservation options', + 'depends': [ + 'sale_management', + 'stock_picking_batch', + 'ventor_base', + ], + 'data': [ + 'data/product_removal.xml', + 'views/res_config.xml', + 'views/stock.xml', + 'views/picking.xml', + 'views/report_stockpicking.xml', + 'views/stock_picking_wave.xml', + ], +} diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/data/product_removal.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/data/product_removal.xml new file mode 100644 index 0000000..9618c7a --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/data/product_removal.xml @@ -0,0 +1,9 @@ + + + + + By Location Priority + location_priority + + + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/doc/index.rst b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/doc/index.rst new file mode 100644 index 0000000..c592e31 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/doc/index.rst @@ -0,0 +1,42 @@ +Please read our detailed guide about optimal picking routes in your warehouse here - https://ventor.tech/warehouse-management/how-to-build-picking-routes-in-your-warehouse-for-walking-minimization/ + +| + +Read also Picking and Packing optimization guide - https://ventor.tech/mobile/pick-more-walk-less-full-picking-and-packing-optimization-in-odoo/ + +| + +========================== + Quick configuration guide +========================== + +| + +1. Install the Ventor Outgoing routing module on your Odoo server (and all dependencies) +2. Assign removal priority (sequence) for each location. You can do it manually or `import `_ a .csv file + +| + +.. image:: images/image7.png + :width: 800px + +| + +3. Go to Settings > Ventor/mERP. Set up needed Picking strategy and Reservation strategy + +| + +.. image:: images/image8.png + :width: 800px + +| + +\*Reservation strategy available for Odoo 12 and higher + +Change Log +########## + +| + +* 16.0.1.1.0 (2023-11-04) + - Fixed tests diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/bs.po b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/bs.po new file mode 100644 index 0000000..d6571bd --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/bs.po @@ -0,0 +1,272 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * outgoing_routing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:42+0000\n" +"PO-Revision-Date: 2022-08-18 13:42+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "- quants are reserved according to Picking startegy (see above)" +msgstr "- quants are reserved according to Picking startegy (see above)" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location name 'A' and beyond)" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location name 'Z' to 'A')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location with removal priority " +"'0' to '∞')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location with removal priority " +"'∞' to '0')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "- quants are reserved in Odoo standard way (FIFO/LIFO)" +msgstr "- quants are reserved in Odoo standard way (FIFO/LIFO)" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location 'A' to 'Z'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location 'Z' to 'A'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location contains product 'A' " +"to 'Z'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location contains product 'Z' " +"to 'A'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location with removal priority " +"'0' to ''" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location with removal priority " +"'' to '0'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "
Your current settings:" +msgstr "
Your current Postavke:" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_order__0 +msgid "Ascending (A-Z)" +msgstr "Ascending (A-Z)" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking_batch +msgid "Batch Transfer" +msgstr "Skupni prijenos" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__base +msgid "By Picking Strategy" +msgstr "By Picking Strategy" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__quantity +msgid "By Quantity" +msgstr "Po količini" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_res_company +msgid "Companies" +msgstr "Kompanije" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__company_id +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__company_id +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_mixin__company_id +msgid "Company" +msgstr "Preduzeće" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_res_config_settings +msgid "Config Settings" +msgstr "Postavke" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__none +msgid "Default" +msgstr "Zadano" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_order__1 +msgid "Descending (Z-A)" +msgstr "Descending (Z-A)" + +#. module: outgoing_routing +#: code:addons/outgoing_routing/models/stock_picking.py:0 +#, python-format +msgid "Hint: operations are sorted by {} in {} order." +msgstr "Hint: Operacije are sorted by {} in {} Narudžba." + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_location +msgid "Inventory Locations" +msgstr "Lokacije inventure" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__location_id_name +msgid "Location name" +msgstr "Lokacija name" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__location_id_removal_prio +msgid "Location removal priority" +msgstr "Location removal priority" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__related_pack_operations +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_wave_form +msgid "Operations" +msgstr "Operacije" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__operations_to_pick +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__operations_to_pick +msgid "Operations to Pick" +msgstr "Operacije to Pick" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__outgoing_routing_order +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__outgoing_routing_order +msgid "Picking Order" +msgstr "Picking Narudžba" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__outgoing_routing_strategy +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__outgoing_routing_strategy +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Picking Strategy" +msgstr "Picking Strategy" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Please, select parameters to calculate route through warehouse(s):" +msgstr "Please, select parameters to calculate route through Skladište(s):" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Please, select parameters to reorder quants during reservation:" +msgstr "Please, select parameters to reorder quants during reservation:" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_move_line +msgid "Product Moves (Stock Move Line)" +msgstr "Skladišna kretanja proizvoda(stavke)" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__product_id_name +msgid "Product name" +msgstr "Proizvod Naziv" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_quant +msgid "Quants" +msgstr "Količine" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_location__removal_prio +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_quant__removal_prio +msgid "Removal Priority" +msgstr "Prioritet uklanjanja" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__stock_reservation_strategy +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__stock_reservation_strategy +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Reservation Strategy" +msgstr "Reservation Strategy" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_mixin__routing_module_version +msgid "Routing Module Version" +msgstr "Routing Module Version" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_location__strategy_sequence +msgid "Sequence" +msgstr "Sekvenca" + +#. module: outgoing_routing +#: model:ir.model.fields,help:outgoing_routing.field_stock_location__strategy_sequence +msgid "Sequence based on warehouse location outgoing strategy/order" +msgstr "Sequence based on Skladište location outgoing strategy/Narudžba" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking_mixin +msgid "Stock Picking Mixin" +msgstr "Zalihe Picking Mješavina" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__strategy_order_r +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__strategy_order_r +msgid "Strategy Order" +msgstr "Strategy Narudžba" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_form +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_wave_form +msgid "To Process" +msgstr "Za obradu" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking +msgid "Transfer" +msgstr "Prijenos" diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/outgoing_routing.pot b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/outgoing_routing.pot new file mode 100644 index 0000000..cf8437f --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/i18n/outgoing_routing.pot @@ -0,0 +1,272 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * outgoing_routing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:42+0000\n" +"PO-Revision-Date: 2022-08-18 13:42+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "- quants are reserved according to Picking startegy (see above)" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location name 'A' and beyond)" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location name 'Z' to 'A')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location with removal priority " +"'0' to '∞')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- quants are reserved first in locations that contain a sufficient amount of" +" product and have higher priority (i.e. from location with removal priority " +"'∞' to '0')" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "- quants are reserved in Odoo standard way (FIFO/LIFO)" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location 'A' to 'Z'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location 'Z' to 'A'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location contains product 'A' " +"to 'Z'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location contains product 'Z' " +"to 'A'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location with removal priority " +"'0' to ''" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "" +"- the route is calculated from location with removal priority " +"'' to '0'" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "
Your current settings:" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_order__0 +msgid "Ascending (A-Z)" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking_batch +msgid "Batch Transfer" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__base +msgid "By Picking Strategy" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__quantity +msgid "By Quantity" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_res_company +msgid "Companies" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__company_id +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__company_id +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_mixin__company_id +msgid "Company" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__stock_reservation_strategy__none +msgid "Default" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_order__1 +msgid "Descending (Z-A)" +msgstr "" + +#. module: outgoing_routing +#: code:addons/outgoing_routing/models/stock_picking.py:0 +#, python-format +msgid "Hint: operations are sorted by {} in {} order." +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__location_id_name +msgid "Location name" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__location_id_removal_prio +msgid "Location removal priority" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__related_pack_operations +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_wave_form +msgid "Operations" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__operations_to_pick +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__operations_to_pick +msgid "Operations to Pick" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__outgoing_routing_order +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__outgoing_routing_order +msgid "Picking Order" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__outgoing_routing_strategy +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__outgoing_routing_strategy +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Picking Strategy" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Please, select parameters to calculate route through warehouse(s):" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Please, select parameters to reorder quants during reservation:" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_move_line +msgid "Product Moves (Stock Move Line)" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields.selection,name:outgoing_routing.selection__res_company__outgoing_routing_strategy__product_id_name +msgid "Product name" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_location__removal_prio +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_quant__removal_prio +msgid "Removal Priority" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__stock_reservation_strategy +#: model:ir.model.fields,field_description:outgoing_routing.field_res_config_settings__stock_reservation_strategy +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_stock_config_settings +msgid "Reservation Strategy" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_res_company__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__routing_module_version +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_mixin__routing_module_version +msgid "Routing Module Version" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_location__strategy_sequence +msgid "Sequence" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,help:outgoing_routing.field_stock_location__strategy_sequence +msgid "Sequence based on warehouse location outgoing strategy/order" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking_mixin +msgid "Stock Picking Mixin" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking__strategy_order_r +#: model:ir.model.fields,field_description:outgoing_routing.field_stock_picking_batch__strategy_order_r +msgid "Strategy Order" +msgstr "" + +#. module: outgoing_routing +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_form +#: model_terms:ir.ui.view,arch_db:outgoing_routing.view_picking_wave_form +msgid "To Process" +msgstr "" + +#. module: outgoing_routing +#: model:ir.model,name:outgoing_routing.model_stock_picking +msgid "Transfer" +msgstr "" diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/init_hook.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/init_hook.py new file mode 100644 index 0000000..1480a1f --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/init_hook.py @@ -0,0 +1,53 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +import logging + +logger = logging.getLogger(__name__) + + +def pre_init_hook(cr): + """ + The objective of this hook is to speed up the installation + of the module on an existing Odoo instance. + Without this script, big databases can take a long time to install this + module. + """ + set_stock_location_priority_default(cr) + set_stock_quant_location_priority_default(cr) + + +def set_stock_location_priority_default(cr): + cr.execute( + """SELECT column_name + FROM information_schema.columns + WHERE table_name='stock_location' AND + column_name='removal_prio'""" + ) + if not cr.fetchone(): + logger.info("Creating field removal_prio on stock_location") + cr.execute( + """ + ALTER TABLE stock_location + ADD COLUMN removal_prio integer + DEFAULT 0; + """ + ) + + +def set_stock_quant_location_priority_default(cr): + cr.execute( + """SELECT column_name + FROM information_schema.columns + WHERE table_name='stock_quant' AND + column_name='removal_prio'""" + ) + if not cr.fetchone(): + logger.info("Creating field removal_prio on stock_quant") + cr.execute( + """ + ALTER TABLE stock_quant + ADD COLUMN removal_prio integer + DEFAULT 0; + """ + ) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/__init__.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/__init__.py new file mode 100644 index 0000000..6964bc3 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/__init__.py @@ -0,0 +1,12 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import res_company +from . import res_config +from . import stock_location +from . import stock_picking_mixin +from . import stock_picking +from . import stock_pack_operation +from . import stock_picking_wave +from . import stock_quant + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_company.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_company.py new file mode 100644 index 0000000..ef18076 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_company.py @@ -0,0 +1,50 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields + + +class Company(models.Model): + _inherit = 'res.company' + + outgoing_routing_strategy = fields.Selection( + [ + # path should be valid for both stock pickings and quants + ('location_id.removal_prio', 'Location removal priority'), + ('location_id.name', 'Location name'), + ('product_id.name', 'Product name'), + ], + string='Picking Strategy', default='location_id.name') + + outgoing_routing_order = fields.Selection( + [ + ('0', 'Ascending (A-Z)'), + ('1', 'Descending (Z-A)'), + ], + string='Picking Order', default='0') + + stock_reservation_strategy = fields.Selection( + [ + ('base', 'By Picking Strategy'), + ('quantity', 'By Quantity'), + ('none', 'Default'), + ], + string='Reservation Strategy', default='base') + + routing_module_version = fields.Char( + string='Routing Module Version', + compute='_compute_routing_module_version', + compute_sudo=True, + ) + + def _compute_routing_module_version(self): + self.env.cr.execute( + "SELECT latest_version FROM ir_module_module WHERE name='outgoing_routing'" + ) + result = self.env.cr.fetchone() + full_version = result and result[0] + split_value = full_version and full_version.split('.') + module_version = split_value and '.'.join(split_value[-3:]) + + for rec in self: + rec.routing_module_version = module_version diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_config.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_config.py new file mode 100644 index 0000000..a3068f1 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/res_config.py @@ -0,0 +1,23 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields + + +class StockConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + outgoing_routing_strategy = fields.Selection( + string='Picking Strategy', + related='company_id.outgoing_routing_strategy', + readonly=False) + + outgoing_routing_order = fields.Selection( + string='Picking Order', + related='company_id.outgoing_routing_order', + readonly=False) + + stock_reservation_strategy = fields.Selection( + string='Reservation Strategy', + related='company_id.stock_reservation_strategy', + readonly=False) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_location.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_location.py new file mode 100644 index 0000000..2043435 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_location.py @@ -0,0 +1,53 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields, api + + +class StockLocation(models.Model): + _inherit = "stock.location" + + removal_prio = fields.Integer( + string='Removal Priority', + default=0, + ) + + strategy_sequence = fields.Integer( + string='Sequence', + help='Sequence based on warehouse location outgoing strategy/order', + compute='_compute_outgoing_strategy_sequence', + store=False, + ) + + def _compute_outgoing_strategy_sequence(self): + """ + """ + strategy = self.env.user.company_id.outgoing_routing_strategy + strategy_order = self.env.user.company_id.outgoing_routing_order + + if strategy and len(strategy.split('.')) > 1: + base, field = strategy.split('.', 1) + if base not in ('location_id') and field not in self: + return + else: + return + + res = self.sudo().search([], order='{} {}'.format( + field, ['asc', 'desc'][int(strategy_order)])) + processed = self.env['stock.location'] + for sequence, location in enumerate(res): + if location not in self: + continue + location.strategy_sequence = sequence + processed |= location + remaining_locations = self - processed + max_seq = len(res) + for remaining in remaining_locations: + remaining.strategy_sequence = max_seq + + @api.onchange('location_id') + def _onchange_parent_location(self): + """ Set location's parent removal priority by default + """ + if self.location_id: + self.removal_prio = self.location_id.removal_prio diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_pack_operation.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_pack_operation.py new file mode 100644 index 0000000..7c9d8bd --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_pack_operation.py @@ -0,0 +1,29 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, api + + +class StockPackOperation(models.Model): + _inherit = 'stock.move.line' + + @api.model + def _compute_operation_valid(self): + res = True + if hasattr(super(StockPackOperation, self), '_compute_operation_valid'): + res &= super(StockPackOperation, self)._compute_operation_valid() + res &= self.qty_done != self.reserved_qty + return res + + def _get_operation_attr(self, attr, flag): + if not flag: + return getattr(self, attr) + return getattr((self.package_level_id or self), attr) + + def _get_operation_tuple(self): + self.ensure_one() + show_pack = self.picking_id.picking_type_id.show_entire_packs + return ( + ('id', self._get_operation_attr('id', show_pack)), + ('_type', self._get_operation_attr('_name', show_pack)), + ) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking.py new file mode 100644 index 0000000..d13d039 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking.py @@ -0,0 +1,81 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import http +from odoo import models, fields, api, _ + +import functools + + +class StockPicking(models.Model): + _name = 'stock.picking' + _inherit = ['stock.picking', 'stock.picking.mixin'] + + operations_to_pick = fields.Many2many( + 'stock.move.line', relation='picking_operations_to_pick', + string='Operations to Pick', + compute='_compute_operations_to_pick', store=False) + + strategy_order_r = fields.Char( + string='Strategy Order', + compute='_compute_operations_to_pick', + store=False, + ) + + @api.depends( + 'move_line_ids', + 'move_line_ids.location_id', + 'move_line_ids.qty_done', + ) + def _compute_operations_to_pick(self): + """ + """ + strategy = self.env.user.company_id.outgoing_routing_strategy + strategy_order = self.env.user.company_id.outgoing_routing_order + + for rec in self: + all_operations = self.env['stock.move.line'].search([ + ('picking_id', '=', rec.id), + ]) + rec.strategy_order_r = rec.get_strategy_string(strategy, strategy_order) + rec.operations_to_pick = rec.sort_operations(all_operations, strategy, strategy_order) + + def sort_printer_picking_list(self, move_line_ids): + """ sort list of pack operations by configured field + """ + strategy = self.env.user.company_id.outgoing_routing_strategy + strategy_order = self.env.user.company_id.outgoing_routing_order + + return self.sort_operations(move_line_ids, strategy, strategy_order) + + def get_strategy_string(self, strategy, strategy_order): + """ + """ + settings = self.env['res.company'].fields_get([ + 'outgoing_routing_strategy', + 'outgoing_routing_order', + ]) + + strategies = settings['outgoing_routing_strategy']['selection'] + orders = settings['outgoing_routing_order']['selection'] + + result = _('Hint: operations are sorted by {} in {} order.').format( + dict(strategies)[strategy].lower(), + dict(orders)[strategy_order].lower() + ) + + return result + + def sort_operations(self, all_operations, strategy, strategy_order): + """ + """ + def _r_getattr(obj, attr, *args): + return functools.reduce(getattr, [obj] + attr.split('.')) + + validated_operations = all_operations.filtered(lambda op: op._compute_operation_valid()) + + result = validated_operations.sorted( + key=lambda op: _r_getattr(op, strategy, 'None'), + reverse=int(strategy_order) + ) + return result diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_mixin.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_mixin.py new file mode 100644 index 0000000..5e39a91 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_mixin.py @@ -0,0 +1,60 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields + +import logging + +_logger = logging.getLogger(__file__) + + +class StockPickingMixin(models.AbstractModel): + _name = 'stock.picking.mixin' + _description = 'Stock Picking Mixin' + + company_id = fields.Many2one( + comodel_name='res.company', + ) + routing_module_version = fields.Char( + related='company_id.routing_module_version', + ) + + @staticmethod + def _recheck_record_list(record_list): + rechecked_list = [] + for rec in record_list: + if rec.get('_type') == 'stock.package_level' and rec.get('is_done'): + continue + rechecked_list.append(rec) + return rechecked_list + + def _read_record(self, record_tuple): + """ + record_tuple = ( + ('id', 100), + ('_type', 'stock.move.line'), + ) + + id:: number (int) + _type:: 'stock.move.line' or 'stock.package_level' (str) + """ + record_dict = dict(record_tuple) + record = self.env[record_dict['_type']].browse(record_dict['id']) + record_dict.update(record.read()[0]) + return record_dict + + def serialize_record_ventor(self, rec_id): + """Record serialization for the Ventor app.""" + filtered_list = [] + try: + stock_object = self.search([ + ('id', '=', int(rec_id)), + ]) + except Exception as ex: + _logger.error(ex) + return filtered_list + + full_list = [rec._get_operation_tuple() for rec in stock_object.operations_to_pick] + [filtered_list.append(rec) for rec in full_list if rec not in filtered_list] + record_list = [self._read_record(rec) for rec in filtered_list] + return self._recheck_record_list(record_list) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_wave.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_wave.py new file mode 100644 index 0000000..359045c --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_picking_wave.py @@ -0,0 +1,58 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields, api + + +class PickingWave(models.Model): + _name = 'stock.picking.batch' + _inherit = ['stock.picking.batch', 'stock.picking.mixin'] + + related_pack_operations = fields.Many2many( + 'stock.move.line', relation='wave_pack_operations', + string='Operations', + compute='_compute_related_pack_operations', store=True) + + operations_to_pick = fields.Many2many( + 'stock.move.line', relation='wave_operations_to_pick', + string='Operations to Pick', + compute='_compute_operations_to_pick', store=False) + + strategy_order_r = fields.Char( + string='Strategy Order', + compute='_compute_operations_to_pick', + store=False, + ) + + @api.depends( + 'picking_ids', + 'picking_ids.move_line_ids', + ) + def _compute_related_pack_operations(self): + for rec in self: + res = self.env['stock.move.line'] + for picking in rec.picking_ids: + for operation in picking.move_line_ids: + res += operation + rec.related_pack_operations = res + + @api.depends( + 'picking_ids', + 'picking_ids.move_line_ids', + 'picking_ids.move_line_ids.location_id', + 'picking_ids.move_line_ids.qty_done', + ) + def _compute_operations_to_pick(self): + strategy = self.env.user.company_id.outgoing_routing_strategy + strategy_order = self.env.user.company_id.outgoing_routing_order + + for rec in self: + picking_ids = rec.picking_ids.ids + all_operations = self.env['stock.move.line'].search([ + ('picking_id', 'in', picking_ids), + ]) + rec.strategy_order_r = self.env['stock.picking'].get_strategy_string(strategy, + strategy_order) + rec.operations_to_pick = self.env['stock.picking'].sort_operations(all_operations, + strategy, + strategy_order) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_quant.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_quant.py new file mode 100644 index 0000000..b60d4a6 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/models/stock_quant.py @@ -0,0 +1,108 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import api, models, fields +from odoo.tools.float_utils import float_compare + +import functools + + +class StockQuant(models.Model): + _inherit = 'stock.quant' + + removal_prio = fields.Integer( + related="location_id.removal_prio", + store=True, + ) + + @api.model + def _get_removal_strategy_order(self, removal_strategy): + # THIS IS A OVERRIDE STANDARD METHOD + strategy_order = self.env.user.company_id.outgoing_routing_order + + if removal_strategy == 'location_priority': + return 'removal_prio %s, id' % (['ASC', 'DESC'][int(strategy_order)]) + return super(StockQuant, self)._get_removal_strategy_order(removal_strategy) + + @api.model + def _update_reserved_quantity(self, product_id, location_id, quantity, lot_id=None, package_id=None, owner_id=None, strict=False): + """ Updates reserved quantity in quants + """ + self = self.with_context(reservation_strategy=self.env.user.company_id.stock_reservation_strategy, reservation_quantity=quantity) + return super(StockQuant, self)._update_reserved_quantity(product_id, location_id, quantity, lot_id, package_id, owner_id, strict) + + def _gather(self, product_id, location_id, lot_id=None, package_id=None, owner_id=None, strict=False): + """ Gather (and reorder, if required) quants + """ + context = dict(self.env.context) + quants = super(StockQuant, self)._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=strict) + + if self._context.get('skip_ventor_reordering') or (product_id.categ_id and product_id.categ_id.removal_strategy_id)\ + or location_id.removal_strategy_id: + return quants + + strategy = self.env.user.company_id.stock_reservation_strategy + + func_reorder = getattr(self, '_reorder_{}'.format(strategy)) + if func_reorder: + quants = func_reorder(quants, product_id) + + # mom taught us to clean after ourselves + if context.get('reservation_strategy'): + del context['reservation_strategy'] + if context.get('reservation_quantity'): + del context['reservation_quantity'] + self = self.with_context(context) + + return quants + + def _reorder_none(self, quants, product_id): + """ No reorder, i.e. use out of the box strategy + """ + return quants + + def _reorder_base(self, quants, product_id): + """ Reorders quants by location removal priority + """ + def _r_getattr(obj, attr, *args): + return functools.reduce(getattr, [obj] + attr.split('.')) + + route = self.env.user.company_id.outgoing_routing_strategy + order = self.env.user.company_id.outgoing_routing_order + + return quants.sorted( + key=lambda op: _r_getattr(op, route, 'None'), + reverse=int(order) + ) + + def _reorder_quantity(self, quants, product_id): + """ Reorders quants by product quantity in locations and location priority + """ + default_route = 'name' # i.e. location_id.name + + route = self.env.user.company_id.outgoing_routing_strategy + order = self.env.user.company_id.outgoing_routing_order + + base, field = route.split('.', 1) + startegy = field if base in ('location_id') else default_route + + required = self.env.context.get('reservation_quantity', 0) + rounding = product_id.uom_id.rounding + + locations = {} + queues = [self.env['stock.quant'], self.env['stock.quant']] # (lprio, hprio) + + for quant in quants: + locations.setdefault(quant.location_id, []).append(quant) + + for location in sorted(locations, + key=lambda location: getattr(location, startegy, 'None'), + reverse=int(order) + ): + location_quants = locations.get(location) + quantity = sum([qt.quantity - qt.reserved_quantity for qt in location_quants]) + priority = float_compare(quantity, required, precision_rounding=rounding) >= 0 + for location_quant in location_quants: + queues[priority] |= location_quant + + return queues[True] + queues[False] diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/icon.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/icon.png new file mode 100644 index 0000000..c69c3e5 Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/icon.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image1.JPG b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image1.JPG new file mode 100644 index 0000000..6d18a8e Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image1.JPG differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image2.gif b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image2.gif new file mode 100644 index 0000000..bec215f Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image2.gif differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image3.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image3.png new file mode 100644 index 0000000..4197805 Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image3.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image4.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image4.png new file mode 100644 index 0000000..841084f Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image4.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image5.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image5.png new file mode 100644 index 0000000..860ef7a Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image5.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image6.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image6.png new file mode 100644 index 0000000..86ca4fe Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image6.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image7.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image7.png new file mode 100644 index 0000000..5088f9f Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image7.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image8.png b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image8.png new file mode 100644 index 0000000..e4e1799 Binary files /dev/null and b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/images/image8.png differ diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/index.html b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/index.html new file mode 100644 index 0000000..f0e1e29 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/static/description/index.html @@ -0,0 +1,182 @@ +
+
+
+

Picking and Reservation Strategy

+
+
+

+ TO AVOID ANY ISSUES, PLEASE, USE ALWAYS LATEST VERSION FROM OUR GITHUB REPOSITORY - + + https://github.com/ventor-tech/merp/tree/16.0 + +

+
+
+
+ +
+
+
+

+ + Description + +

+
+

The app allows creating optimal picking routes in your warehouse and process picking orders and batches in an optimal way. Additionally, you can change reservation priority and make reservations in the way you want, without following FIFO/LIFO methods. Pickers get the shortest pathway, save picking time, and reduce extra walking around the warehouse.

+
+
+
+
+ +
+
+
+
+ +
+
+
+

+ + Key points + +

+
+
    +
  • All products inside outgoing shipments are reserved from locations according to the removal priority field. That means you define locations from where Odoo will reserve products for delivery orders (*for Odoo 12 and higher)
  • +
  • All products inside outgoing shipments are sorted according to the removal priority field. That means all product lines inside delivery orders are sorted by the optimal route to pick products from the start location to the destination
  • +
  • Works with both Odoo Community and Enterprise (self-hosted or odoo.sh)
  • +
  • Fully supportable by the Ventor app to guide pickers through an optimal route
  • +
+
+
+
+
+ +
+
+
+

+ + Manage + +

+
+
+
+
+
+ + + +
+
+
+

+ Sort pack operations in picking depending on selected strategy (see list below) and order (ascending or descending): +

+
    +
  • sort by source locations name
  • +
  • sort by location removal strategy priority
  • +
  • sort by product name
  • +
+

+ where removal strategy priority is an integer value that should be used to define order (priority) of warehouse locations. +

+

+ Sorted list of pack operations could now be found on a new tab 'To Process' on picking form. +

+
+
+
+
+
+ + + +
+
+
+

+ Sort quants to be reserved depending on selected rule (see list below) in addition to standard FIFO/LIFO/FEFO rules: +

+
    +
  • outgoing routing (see above): by location name and removal strategy priority
  • +
  • by quantity: first reverse quants in location that contain a sufficient amount of product (and higher priority according to outgoing routing settings)
  • +
  • or default (out-of-the-box) strategy
  • +
+

+ Thus, the module allows users to calculate the most effective route (based on your settings) to collect all ordered products from the entire warehouse to save your time. +

+
+
+
+
+
+ + + +
+
+
+

+ Sorts list of pack operations in picking report in accordance with available strategies. +

+
+
+
+
+

+ DOWNLOAD VENTOR APP - https://ventor.app +

+ + VISIT OUR YOUTUBE CHANNEL + +
+
+
+ +
+
+
+

Notes

+
+

The routing feature was designed to work only with the "Ventor" application that can be downloaded from:

+
    +
  1. + https://ventor.app/ website - version obtained from here is suitable for all types of organizations +
  2. +
  3. + Google Play - has limitations, not possible to customize app by request - https://play.google.com/store/apps/details?id=com.xpansa.merp.warehouse +
  4. +
+

Custom reservation works independently from the "Ventor" mobile app. (*the feature available for Odoo 12 and higher)

+

"Ventor" works both on regular mobile phones with Android 4.1+ and with professional barcode scanners. +

+

+ VentorTech (https://ventor.tech/) is company specialized on building Personalized Inventory and Product Management System. +

+

+ For all questions contact hello@ventor.tech. +

+
+
+ + + +
+
+
+
\ No newline at end of file diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/__init__.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/__init__.py new file mode 100644 index 0000000..0372bcb --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/__init__.py @@ -0,0 +1,9 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import test_merp_outgoing_routing +from . import test_merp_picking_wave_base +from . import test_merp_quants_location_routing +from . import test_stock_reservation_by_name +from . import test_stock_reservation_by_priority +from . import test_stock_reservation_by_quantity diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_outgoing_routing.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_outgoing_routing.py new file mode 100644 index 0000000..3aebfae --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_outgoing_routing.py @@ -0,0 +1,150 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo.tests.common import TransactionCase +from datetime import datetime + + +class TestMerpOutgoingRouting(TransactionCase): + + def setUp(self): + super(TestMerpOutgoingRouting, self).setUp() + + self.location_1 = self.env['stock.location'].create({ + 'name': 'test_location_1', + 'removal_prio': 2 + }) + self.location_2 = self.env['stock.location'].create({ + 'name': 'test_location_2', + 'removal_prio': 3 + }) + self.location_3 = self.env['stock.location'].create({ + 'name': 'test_location_3', + 'removal_prio': 1 + }) + self.location_4 = self.env['stock.location'].create({ + 'name': 'test_location_4', + 'removal_prio': 4 + }) + + company = self.env.user.company_id + picking_type = self.env['stock.picking.type'].search([], limit=1) + self.stock_picking = self.env['stock.picking'].create({ + 'name': 'test_stock_picking', + 'location_id': self.location_1.id, + 'location_dest_id': self.location_2.id, + 'move_type': 'one', + 'company_id': company.id, + 'picking_type_id': picking_type.id + }) + + products = self.env['product.product'] + for suf in range(1, 5): + products += self.create_product(suf) + + self.move_line_1 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 1.0, + 'location_id': self.location_1.id, + 'date': datetime.now(), + 'location_dest_id': self.location_2.id, + 'reserved_uom_qty': 20.0, + 'product_uom_id': products[1].uom_id.id, + 'product_id': products[1].id + }) + self.move_line_2 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 2.0, + 'location_id': self.location_2.id, + 'date': datetime.now(), + 'location_dest_id': self.location_3.id, + 'reserved_uom_qty': 25.0, + 'product_uom_id': products[0].uom_id.id, + 'product_id': products[0].id + }) + self.move_line_3 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 3.0, + 'location_id': self.location_3.id, + 'date': datetime.now(), + 'location_dest_id': self.location_2.id, + 'reserved_uom_qty': 15.0, + 'product_uom_id': products[2].uom_id.id, + 'product_id': products[2].id + }) + self.move_line_4 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 10.0, + 'location_id': self.location_4.id, + 'date': datetime.now(), + 'location_dest_id': self.location_2.id, + 'reserved_uom_qty': 10.0, + 'product_uom_id': products[3].uom_id.id, + 'product_id': products[3].id + }) + + def create_product(self, suf): + name = 'test_product_{}'.format(suf) + product_data = { + 'name': name, + } + return self.env['product.product'].create(product_data) + + def test_sort_alphabet_a_z(self): + self.set_way_outgoing_routing('location_id.name', '0') + + locations_name = self.stock_picking.mapped('operations_to_pick.location_id.name') + self.assertEqual(locations_name[0], 'test_location_1') + self.assertEqual(locations_name[1], 'test_location_2') + self.assertEqual(locations_name[2], 'test_location_3') + + def test_sort_alphabet_z_a(self): + self.set_way_outgoing_routing('location_id.name', '1') + + locations_name = self.stock_picking.mapped('operations_to_pick.location_id.name') + self.assertEqual(locations_name[0], 'test_location_3') + self.assertEqual(locations_name[1], 'test_location_2') + self.assertEqual(locations_name[2], 'test_location_1') + + def test_sort_removal_priority_a_z(self): + self.set_way_outgoing_routing('location_id.removal_prio', '0') + + locations_removal_prio = self.stock_picking\ + .mapped('operations_to_pick.location_id.removal_prio') + self.assertEqual(locations_removal_prio[0], 1) + self.assertEqual(locations_removal_prio[1], 2) + self.assertEqual(locations_removal_prio[2], 3) + + def test_sort_removal_priority_z_a(self): + self.set_way_outgoing_routing('location_id.removal_prio', '1') + + locations_removal_prio = self.stock_picking\ + .mapped('operations_to_pick.location_id.removal_prio') + self.assertEqual(locations_removal_prio[0], 3) + self.assertEqual(locations_removal_prio[1], 2) + self.assertEqual(locations_removal_prio[2], 1) + + def test_sort_by_products_name_a_z(self): + self.set_way_outgoing_routing('product_id.name', '0') + + products_name = self.stock_picking \ + .mapped('operations_to_pick.product_id.name') + self.assertEqual(products_name[0], 'test_product_1') + self.assertEqual(products_name[1], 'test_product_2') + self.assertEqual(products_name[2], 'test_product_3') + + def test_sort_by_products_name_z_a(self): + self.set_way_outgoing_routing('product_id.name', '1') + + products_name = self.stock_picking \ + .mapped('operations_to_pick.product_id.name') + self.assertEqual(products_name[0], 'test_product_3') + self.assertEqual(products_name[1], 'test_product_2') + self.assertEqual(products_name[2], 'test_product_1') + + def set_way_outgoing_routing(self, outgoing_routing_strategy, outgoing_routing_order): + config = self.env['res.config.settings'].create({ + 'outgoing_routing_strategy': outgoing_routing_strategy, + 'outgoing_routing_order': outgoing_routing_order + }) + config.execute() diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_picking_wave_base.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_picking_wave_base.py new file mode 100644 index 0000000..1e91e71 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_picking_wave_base.py @@ -0,0 +1,170 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo.tests.common import TransactionCase +from datetime import datetime + + +class TestMerpPickingWaveBase(TransactionCase): + + def setUp(self): + super(TestMerpPickingWaveBase, self).setUp() + self.location_1 = self.env['stock.location'].create({ + 'name': 'test_location_1', + 'removal_prio': 2 + }) + self.location_2 = self.env['stock.location'].create({ + 'name': 'test_location_2', + 'removal_prio': 3 + }) + self.location_3 = self.env['stock.location'].create({ + 'name': 'test_location_3', + 'removal_prio': 1 + }) + self.location_4 = self.env['stock.location'].create({ + 'name': 'test_location_4', + 'removal_prio': 4 + }) + company = self.env.user.company_id + picking_type = self.env['stock.picking.type'].search([], limit=1) + self.stock_picking = self.env['stock.picking'].create({ + 'name': 'test_stock_picking', + 'location_id': self.location_1.id, + 'location_dest_id': self.location_2.id, + 'move_type': 'one', + 'company_id': company.id, + 'picking_type_id': picking_type.id + }) + self.picking_batch = self.env['stock.picking.batch'].create({ + 'name': 'test_stock_picking_batch', + 'picking_ids': [(4, self.stock_picking.id, 0)] + }) + + products = self.env['product.product'] + for suf in range(1, 5): + products += self.create_product(suf) + + self.move_line_1 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 1.0, + 'location_id': self.location_1.id, + 'date': datetime.now(), + 'location_dest_id': self.location_2.id, + 'reserved_uom_qty': 20.0, + 'product_uom_id': products[1].uom_id.id, + 'product_id': products[1].id + }) + self.move_line_2 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 2.0, + 'location_id': self.location_2.id, + 'date': datetime.now(), + 'location_dest_id': self.location_3.id, + 'reserved_uom_qty': 25.0, + 'product_uom_id': products[1].uom_id.id, + 'product_id': products[0].id + }) + self.move_line_3 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 3.0, + 'location_id': self.location_3.id, + 'date': datetime.now(), + 'location_dest_id': self.location_1.id, + 'reserved_uom_qty': 15.0, + 'product_uom_id': products[2].uom_id.id, + 'product_id': products[2].id + }) + self.move_line_4 = self.env['stock.move.line'].create({ + 'picking_id': self.stock_picking.id, + 'qty_done': 10.0, + 'location_id': self.location_4.id, + 'date': datetime.now(), + 'location_dest_id': self.location_2.id, + 'reserved_uom_qty': 10.0, + 'product_uom_id': products[3].uom_id.id, + 'product_id': products[3].id + }) + + def create_product(self, suf): + name = 'test_product_{}'.format(suf) + product_data = { + 'name': name, + } + return self.env['product.product'].create(product_data) + + def test_related_pack_operations(self): + self.assertEqual(len(self.picking_batch.related_pack_operations), 4) + + def test_operations_to_pick(self): + self.assertEqual(len(self.picking_batch.operations_to_pick), 3) + + def test_sort_alphabet_a_z(self): + outgoing_routing_strategy = 'location_id.name' + outgoing_routing_order = '0' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + locations_name = self.picking_batch.mapped('operations_to_pick.location_id.name') + self.assertEqual(locations_name[0], 'test_location_1') + self.assertEqual(locations_name[1], 'test_location_2') + self.assertEqual(locations_name[2], 'test_location_3') + + def test_sort_alphabet_z_a(self): + outgoing_routing_strategy = 'location_id.name' + outgoing_routing_order = '1' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + locations_name = self.picking_batch.mapped('operations_to_pick.location_id.name') + self.assertEqual(locations_name[0], 'test_location_3') + self.assertEqual(locations_name[1], 'test_location_2') + self.assertEqual(locations_name[2], 'test_location_1') + + def test_sort_removal_priority_a_z(self): + outgoing_routing_strategy = 'location_id.removal_prio' + outgoing_routing_order = '0' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + locations_removal_prio = self.picking_batch \ + .mapped('operations_to_pick.location_id.removal_prio') + self.assertEqual(locations_removal_prio[0], 1) + self.assertEqual(locations_removal_prio[1], 2) + self.assertEqual(locations_removal_prio[2], 3) + + def test_sort_removal_priority_z_a(self): + outgoing_routing_strategy = 'location_id.removal_prio' + outgoing_routing_order = '1' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + locations_removal_prio = self.picking_batch \ + .mapped('operations_to_pick.location_id.removal_prio') + self.assertEqual(locations_removal_prio[0], 3) + self.assertEqual(locations_removal_prio[1], 2) + self.assertEqual(locations_removal_prio[2], 1) + + def test_sort_by_products_name_a_z(self): + outgoing_routing_strategy = 'product_id.name' + outgoing_routing_order = '0' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + products_name = self.picking_batch \ + .mapped('operations_to_pick.product_id.name') + self.assertEqual(products_name[0], 'test_product_1') + self.assertEqual(products_name[1], 'test_product_2') + self.assertEqual(products_name[2], 'test_product_3') + + def test_sort_by_products_name_z_a(self): + outgoing_routing_strategy = 'product_id.name' + outgoing_routing_order = '1' + self.set_way_outgoing_routing(outgoing_routing_strategy, outgoing_routing_order) + + products_name = self.picking_batch \ + .mapped('operations_to_pick.product_id.name') + self.assertEqual(products_name[0], 'test_product_3') + self.assertEqual(products_name[1], 'test_product_2') + self.assertEqual(products_name[2], 'test_product_1') + + def set_way_outgoing_routing(self, outgoing_routing_strategy, outgoing_routing_order): + config = self.env['res.config.settings'].create({ + 'outgoing_routing_strategy': outgoing_routing_strategy, + 'outgoing_routing_order': outgoing_routing_order + }) + config.execute() diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_quants_location_routing.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_quants_location_routing.py new file mode 100644 index 0000000..ed12e77 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_merp_quants_location_routing.py @@ -0,0 +1,162 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from datetime import date +from odoo.tests.common import TransactionCase + + +class TestMerpQuantsLocationRouting(TransactionCase): + + def setUp(self): + super(TestMerpQuantsLocationRouting, self).setUp() + self.res_users_model = self.env['res.users'] + self.stock_location_model = self.env['stock.location'] + self.stock_warehouse_model = self.env['stock.warehouse'] + self.stock_picking_model = self.env['stock.picking'] + self.stock_change_model = self.env['stock.change.product.qty'] + self.product_model = self.env['product.product'] + self.quant_model = self.env['stock.quant'] + + self.picking_internal = self.env.ref('stock.picking_type_internal') + self.picking_out = self.env.ref('stock.picking_type_out') + self.location_supplier = self.env.ref('stock.stock_location_suppliers') + + self.company = self.env.ref('base.main_company') + + self.wh1 = self.stock_warehouse_model.create({ + 'name': 'WH2', + 'code': 'WH2', + }) + + # Removal strategies: + self.fifo = self.env.ref('stock.removal_fifo') + self.lifo = self.env.ref('stock.removal_lifo') + self.removal_location_priority = self.env.ref( + 'outgoing_routing.removal_location_priority' + ) + + # Create locations: + self.stock = self.stock_location_model.create({ + 'name': 'Default Base', + 'usage': 'internal', + }) + + self.location_A = self.stock_location_model.create({ + 'name': 'location_A', + 'usage': 'internal', + 'location_id': self.stock.id, + 'removal_prio': 1, + }) + + self.location_B = self.stock_location_model.create({ + 'name': 'Location_B', + 'usage': 'internal', + 'location_id': self.stock.id, + 'removal_prio': 0, + }) + + self.stock_2 = self.stock_location_model.create({ + 'name': 'Another Location', + 'usage': 'internal', + }) + + # Create a product + self.product_1 = self.product_model.create({ + 'name': 'Product 1', + 'type': 'product', + }) + + # Create quants + today = date.today() + quant_1 = self.quant_model.create({ + 'product_id': self.product_1.id, + 'location_id': self.location_A.id, + 'quantity': 10.0, + 'in_date': today, + }) + + quant_2 = self.quant_model.create({ + 'product_id': self.product_1.id, + 'location_id': self.location_B.id, + 'quantity': 5.0, + 'in_date': today, + }) + + self.quants = quant_1 + quant_2 + + def _create_picking(self, picking_type, location, location_dest, qty): + move_line_values = { + 'name': 'Default Test Move', + 'product_id': self.product_1.id, + 'product_uom': self.product_1.uom_id.id, + 'product_uom_qty': qty, + 'location_id': location.id, + 'location_dest_id': location_dest.id, + 'price_unit': 2, + } + + picking = self.stock_picking_model.create({ + 'picking_type_id': picking_type.id, + 'location_id': location.id, + 'location_dest_id': location_dest.id, + 'move_ids': [(0, 0, move_line_values)], + }) + + return picking + + def test_stock_removal_location_by_removal_location_priority(self): + """Tests removal priority with Location Priority strategy.""" + self.stock.removal_strategy_id = self.removal_location_priority + + # Quants must start unreserved + for quant in self.quants: + self.assertEqual( + quant.reserved_quantity, + 0.0, + 'Quant must not have reserved qty right now.' + ) + + if quant.location_id == self.location_A: + self.assertEqual( + quant.removal_prio, + 1, + 'Removal Priority Location must be 1' + ) + if quant.location_id == self.location_B: + self.assertEqual( + quant.removal_prio, + 0, + 'Removal Priority Location must be 0' + ) + + self.assertEqual( + self.quants[0].in_date, + self.quants[1].in_date, + 'Dates must be Equal' + ) + + picking_1 = self._create_picking( + self.picking_internal, + self.stock, + self.stock_2, + 5, + ) + + # picking_1.flush() + picking_1.action_confirm() + picking_1.action_assign() + + # Quants must be reserved in Location B (lower removal_priority value). + for quant in self.quants: + if quant.location_id == self.location_A: + self.assertEqual( + quant.reserved_quantity, + 0.0, + 'This quant must not have reserved qty.' + ) + if quant.location_id == self.location_B: + self.assertEqual( + quant.reserved_quantity, + 5.0, + 'This quant must have 5 reserved qty.' + ) diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_name.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_name.py new file mode 100644 index 0000000..36a7e7a --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_name.py @@ -0,0 +1,110 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from datetime import date +from odoo.tests.common import TransactionCase + + +class TestStockRouting(TransactionCase): + + def setUp(self): + super(TestStockRouting, self).setUp() + + self.base_company = self.env.ref('base.main_company') + + self.product_product_model = self.env['product.product'] + self.res_users_model = self.env['res.users'] + self.stock_location_model = self.env['stock.location'] + self.stock_move_model = self.env['stock.move'] + self.stock_picking_model = self.env['stock.picking'] + self.stock_quant_model = self.env['stock.quant'] + + self.picking_internal = self.env.ref('stock.picking_type_internal') + + today = date.today() + + self.env['res.config.settings'].create({ + 'outgoing_routing_strategy': 'location_id.name', + 'outgoing_routing_order': '0', + 'stock_reservation_strategy': 'none', + }).execute() + + self.stock_A = self.stock_location_model.create({ + 'name': 'A', + 'usage': 'internal', + }) + + self.stock_A1 = self.stock_location_model.create({ + 'name': 'A-1', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 2, + }) + + self.stock_A2 = self.stock_location_model.create({ + 'name': 'A-2', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 3, + }) + + self.stock_A3 = self.stock_location_model.create({ + 'name': 'A-3', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 1, + }) + + self.stock_B = self.stock_location_model.create({ + 'name': 'B', + 'usage': 'internal', + }) + + self.product_Z = self.product_product_model.create({ + 'name': 'Product', + 'type': 'product', + }) + + quant_1 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A1.id, # prio:2 + 'quantity': 15.0, + 'in_date': today, + }) + + quant_2 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A2.id, # prio:3 + 'quantity': 5.0, + 'in_date': today, + }) + + quant_3 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A3.id, # prio:1 + 'quantity': 10.0, + 'in_date': today, + }) + + self.quants = quant_1 + quant_2 + quant_3 + + def test_stock_reservation_by_name_case1(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 10) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-1') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-3') + + def test_stock_reservation_by_name_case2(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 12) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 12.0, '12 products should be reserved in A-1') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-3') + + def test_stock_reservation_by_name_case3(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 22) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 15.0, '15 products should be reserved in A-1') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 5.0, '5 products should be reserved in A-2') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 2.0, '2 products should be reserved in A-3') diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_priority.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_priority.py new file mode 100644 index 0000000..0ac4bbe --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_priority.py @@ -0,0 +1,110 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from datetime import date +from odoo.tests.common import TransactionCase + + +class TestStockRouting(TransactionCase): + + def setUp(self): + super(TestStockRouting, self).setUp() + + self.base_company = self.env.ref('base.main_company') + + self.product_product_model = self.env['product.product'] + self.res_users_model = self.env['res.users'] + self.stock_location_model = self.env['stock.location'] + self.stock_move_model = self.env['stock.move'] + self.stock_picking_model = self.env['stock.picking'] + self.stock_quant_model = self.env['stock.quant'] + + self.picking_internal = self.env.ref('stock.picking_type_internal') + + today = date.today() + + self.env['res.config.settings'].create({ + 'outgoing_routing_strategy': 'location_id.removal_prio', + 'outgoing_routing_order': '0', + 'stock_reservation_strategy': 'base', + }).execute() + + self.stock_A = self.stock_location_model.create({ + 'name': 'A', + 'usage': 'internal', + }) + + self.stock_A1 = self.stock_location_model.create({ + 'name': 'A-1', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 2, + }) + + self.stock_A2 = self.stock_location_model.create({ + 'name': 'A-2', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 3, + }) + + self.stock_A3 = self.stock_location_model.create({ + 'name': 'A-3', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 1, + }) + + self.stock_B = self.stock_location_model.create({ + 'name': 'B', + 'usage': 'internal', + }) + + self.product_Z = self.product_product_model.create({ + 'name': 'Product', + 'type': 'product', + }) + + quant_1 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A1.id, # prio:2 + 'quantity': 15.0, + 'in_date': today, + }) + + quant_2 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A2.id, # prio:3 + 'quantity': 5.0, + 'in_date': today, + }) + + quant_3 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A3.id, # prio:1 + 'quantity': 10.0, + 'in_date': today, + }) + + self.quants = quant_1 + quant_2 + quant_3 + + def test_stock_reservation_by_priority_case1(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 10) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-3 (prio:1)') + + def test_stock_reservation_by_priority_case2(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 12) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 2.0, '2 products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-3 (prio:1)') + + def test_stock_reservation_by_priority_case3(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 22) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 12.0, '12 products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-3 (prio:1)') diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_quantity.py b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_quantity.py new file mode 100644 index 0000000..8c1eac5 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/tests/test_stock_reservation_by_quantity.py @@ -0,0 +1,110 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from datetime import date +from odoo.tests.common import TransactionCase + + +class TestStockRouting(TransactionCase): + + def setUp(self): + super(TestStockRouting, self).setUp() + + self.base_company = self.env.ref('base.main_company') + + self.product_product_model = self.env['product.product'] + self.res_users_model = self.env['res.users'] + self.stock_location_model = self.env['stock.location'] + self.stock_move_model = self.env['stock.move'] + self.stock_picking_model = self.env['stock.picking'] + self.stock_quant_model = self.env['stock.quant'] + + self.picking_internal = self.env.ref('stock.picking_type_internal') + + today = date.today() + + self.env['res.config.settings'].create({ + 'outgoing_routing_strategy': 'location_id.removal_prio', + 'outgoing_routing_order': '0', + 'stock_reservation_strategy': 'quantity', + }).execute() + + self.stock_A = self.stock_location_model.create({ + 'name': 'A', + 'usage': 'internal', + }) + + self.stock_A1 = self.stock_location_model.create({ + 'name': 'A-1', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 2, + }) + + self.stock_A2 = self.stock_location_model.create({ + 'name': 'A-2', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 3, + }) + + self.stock_A3 = self.stock_location_model.create({ + 'name': 'A-3', + 'usage': 'internal', + 'location_id': self.stock_A.id, + 'removal_prio': 1, + }) + + self.stock_B = self.stock_location_model.create({ + 'name': 'B', + 'usage': 'internal', + }) + + self.product_Z = self.product_product_model.create({ + 'name': 'Product', + 'type': 'product', + }) + + quant_1 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A1.id, # prio:2 + 'quantity': 15.0, + 'in_date': today, + }) + + quant_2 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A2.id, # prio:3 + 'quantity': 5.0, + 'in_date': today, + }) + + quant_3 = self.stock_quant_model.create({ + 'product_id': self.product_Z.id, + 'location_id': self.stock_A3.id, # prio:1 + 'quantity': 10.0, + 'in_date': today, + }) + + self.quants = quant_1 + quant_2 + quant_3 + + def test_stock_reservation_by_quantity_case1(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 10) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-3 (prio:1)') + + def test_stock_reservation_by_quantity_case2(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 12) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 12.0, 'No products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, '12 products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-3 (prio:1)') + + def test_stock_reservation_by_quantity_case3(self): + quants = self.stock_quant_model._update_reserved_quantity(self.product_Z, self.stock_A, 22) + for quant, quantity in quants: + if quant.location_id == self.stock_A1: self.assertEqual(quant.reserved_quantity, 12.0, '12 products should be reserved in A-1 (prio:2)') + if quant.location_id == self.stock_A2: self.assertEqual(quant.reserved_quantity, 0.0, 'No products should be reserved in A-2 (prio:3)') + if quant.location_id == self.stock_A3: self.assertEqual(quant.reserved_quantity, 10.0, '10 products should be reserved in A-3 (prio:1)') diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/picking.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/picking.xml new file mode 100644 index 0000000..f788c54 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/picking.xml @@ -0,0 +1,32 @@ + + + + + stock.picking.form.inherit + stock.picking + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/report_stockpicking.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/report_stockpicking.xml new file mode 100644 index 0000000..9871cd7 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/report_stockpicking.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/res_config.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/res_config.xml new file mode 100644 index 0000000..9bc2d90 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/res_config.xml @@ -0,0 +1,121 @@ + + + + + Ventor/mERP Picking Wave - Stock Settings + res.config.settings + + + +

Picking Strategy

+
+
+
+ Please, select parameters to calculate route through warehouse(s): +
+
+
Your current settings: +
+
+ - the route is calculated from location 'A' to 'Z' +
+
+ - the route is calculated from location 'Z' to 'A' +
+
+ - the route is calculated from location with removal priority '0' to '' +
+
+ - the route is calculated from location with removal priority '' to '0' +
+
+ - the route is calculated from location contains product 'A' to 'Z' +
+
+ - the route is calculated from location contains product 'Z' to 'A' +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Reservation Strategy

+
+
+
+ Please, select parameters to reorder quants during reservation: +
+
+
Your current settings: +
+
+ - quants are reserved in Odoo standard way (FIFO/LIFO) +
+
+ - quants are reserved according to Picking strategy (see above) +
+
+ - quants are reserved first in locations that contain a sufficient amount of product and have higher priority (i.e. from location name 'A' and beyond) +
+
+ - quants are reserved first in locations that contain a sufficient amount of product and have higher priority (i.e. from location name 'Z' to 'A') +
+
+ - quants are reserved first in locations that contain a sufficient amount of product and have higher priority (i.e. from location with removal priority '0' to '∞') +
+
+ - quants are reserved first in locations that contain a sufficient amount of product and have higher priority (i.e. from location with removal priority '∞' to '0') +
+
+
+
+
+
+
+
+
+
+ + + + + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock.xml new file mode 100644 index 0000000..9383317 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock.xml @@ -0,0 +1,28 @@ + + + + + stock.location.tree.removal.strategy + stock.location + + + + + + + + + + stock.location.form.removal.strategy + stock.location + + + + + + + + + + + diff --git a/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock_picking_wave.xml b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock_picking_wave.xml new file mode 100644 index 0000000..9109435 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/outgoing_routing/views/stock_picking_wave.xml @@ -0,0 +1,43 @@ + + + + + stock.picking.wave.form.inherit + stock.picking.batch + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/odoo-bringout-ventor-outgoing_routing/pyproject.toml b/odoo-bringout-ventor-outgoing_routing/pyproject.toml new file mode 100644 index 0000000..b955fe3 --- /dev/null +++ b/odoo-bringout-ventor-outgoing_routing/pyproject.toml @@ -0,0 +1,44 @@ +[project] +name = "odoo-bringout-ventor-outgoing_routing" +version = "16.0.0" +description = "Picking and Reservation Strategy - Allows to automatically build optimal picking routes and apply custom reservation options" +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "odoo-bringout-ventor-sale_management>=16.0.0", + "odoo-bringout-ventor-stock_picking_batch>=16.0.0", + "odoo-bringout-ventor-ventor_base>=16.0.0", + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["outgoing_routing"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +] diff --git a/odoo-bringout-ventor-product_multiple_barcodes/README.md b/odoo-bringout-ventor-product_multiple_barcodes/README.md new file mode 100644 index 0000000..5d78372 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/README.md @@ -0,0 +1,49 @@ +# Product Multiple Barcodes + +Custom Odoo addon: product_multiple_barcodes + +## Installation + +```bash +pip install odoo-bringout-ventor-product_multiple_barcodes +``` + +## Dependencies + +This addon depends on: +- product +- sale +- purchase +- stock + +## Manifest Information + +- **Name**: Product Multiple Barcodes +- **Version**: 16.0.1.0.0 +- **Category**: N/A +- **License**: LGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-ventor vendor, addon `product_multiple_barcodes`. + +## License + +This package maintains the original LGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/ARCHITECTURE.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/ARCHITECTURE.md new file mode 100644 index 0000000..f31a55b --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Product_multiple_barcodes Module - product_multiple_barcodes + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/CONFIGURATION.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/CONFIGURATION.md new file mode 100644 index 0000000..58bfd9d --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for product_multiple_barcodes. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/CONTROLLERS.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/DEPENDENCIES.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/DEPENDENCIES.md new file mode 100644 index 0000000..0a890b0 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/DEPENDENCIES.md @@ -0,0 +1,8 @@ +# Dependencies + +This addon depends on: + +- [product](../../odoo-bringout-oca-ocb-product) +- [sale](../../odoo-bringout-oca-ocb-sale) +- [purchase](../../odoo-bringout-oca-ocb-purchase) +- [stock](../../odoo-bringout-oca-ocb-stock) diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/FAQ.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/FAQ.md new file mode 100644 index 0000000..8f0e125 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon product_multiple_barcodes or install in UI. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/INSTALL.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/INSTALL.md new file mode 100644 index 0000000..844c9a5 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-ventor-product_multiple_barcodes" +# or +uv pip install odoo-bringout-ventor-product_multiple_barcodes" +``` diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/MODELS.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/MODELS.md new file mode 100644 index 0000000..5725b26 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/MODELS.md @@ -0,0 +1,14 @@ +# Models + +Detected core models and extensions in product_multiple_barcodes. + +```mermaid +classDiagram + class product_barcode_multi + class product_product + class product_template +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/OVERVIEW.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/OVERVIEW.md new file mode 100644 index 0000000..6ce80ce --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: product_multiple_barcodes. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon product_multiple_barcodes +- License: LGPL-3 diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/REPORTS.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/REPORTS.md new file mode 100644 index 0000000..e0ea35f --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/REPORTS.md @@ -0,0 +1,3 @@ +# Reports + +This module does not define custom reports. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/SECURITY.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/SECURITY.md new file mode 100644 index 0000000..00283c7 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/SECURITY.md @@ -0,0 +1,34 @@ +# Security + +Access control and security definitions in product_multiple_barcodes. + +## Access Control Lists (ACLs) + +Model access permissions defined in: +- **[ir.model.access.csv](../product_multiple_barcodes/security/ir.model.access.csv)** + - 5 model access rules + +## Record Rules + +Row-level security rules defined in: + +```mermaid +graph TB + subgraph "Security Layers" + A[Users] --> B[Groups] + B --> C[Access Control Lists] + C --> D[Models] + B --> E[Record Rules] + E --> F[Individual Records] + end +``` + +Security files overview: +- **[ir.model.access.csv](../product_multiple_barcodes/security/ir.model.access.csv)** + - Model access permissions (CRUD rights) + +Notes +- Access Control Lists define which groups can access which models +- Record Rules provide row-level security (filter records by user/group) +- Security groups organize users and define permission sets +- All security is enforced at the ORM level by Odoo diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/TROUBLESHOOTING.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/USAGE.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/USAGE.md new file mode 100644 index 0000000..64f5298 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon product_multiple_barcodes +``` diff --git a/odoo-bringout-ventor-product_multiple_barcodes/doc/WIZARDS.md b/odoo-bringout-ventor-product_multiple_barcodes/doc/WIZARDS.md new file mode 100644 index 0000000..fcda18e --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/doc/WIZARDS.md @@ -0,0 +1,8 @@ +# Wizards + +Transient models exposed as UI wizards in product_multiple_barcodes. + +```mermaid +classDiagram + class MultiplyBarcodeWizard +``` diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/README.rst b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/README.rst new file mode 100644 index 0000000..6ce9ea4 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/README.rst @@ -0,0 +1,4 @@ +Product Multiple Barcodes +========================= + +This module allows to define multiple additional barcodes for products and to search products by additional barcodes and internal reference. diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__init__.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__init__.py new file mode 100644 index 0000000..13ec90f --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from . import models +from . import wizard diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__manifest__.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__manifest__.py new file mode 100644 index 0000000..b327136 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/__manifest__.py @@ -0,0 +1,25 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Product Multiple Barcodes', + "version": "16.0.1.0.0", + 'author': 'VentorTech', + 'website': 'https://ventor.tech/', + 'license': 'LGPL-3', + 'installable': True, + 'images': ['static/description/main_banner.png'], + 'summary': 'Allows to define multiple additional barcodes for products and to search products by additional barcodes and internal reference.', + 'depends': [ + 'product', + 'sale', + 'purchase', + 'stock', + ], + 'data': [ + 'security/ir.model.access.csv', + 'wizard/multiply_barcode_wizard.xml', + 'views/product_template_views.xml', + 'views/stock_picking_views.xml', + ], +} diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/doc/index.rst b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/doc/index.rst new file mode 100644 index 0000000..faa3212 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/doc/index.rst @@ -0,0 +1,6 @@ +Product Multiple Barcodes +========================= + +| + +**This module allows to define multiple additional barcodes for products and to search products by additional barcodes and internal reference.** diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/bs.po b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/bs.po new file mode 100644 index 0000000..946b2a0 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/bs.po @@ -0,0 +1,145 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_multiple_barcodes +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-16 14:30+0000\n" +"PO-Revision-Date: 2022-08-16 14:30+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_product__barcode_ids +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_template__barcode_ids +msgid "Additional Barcodes" +msgstr "Dodatno Barcodes" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__name +msgid "Barcode" +msgstr "Barkod" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Cancel" +msgstr "Otkaži" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__create_uid +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__create_uid +msgid "Created by" +msgstr "Kreirao" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__create_date +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__create_date +msgid "Created on" +msgstr "Kreirano" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__display_name +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__display_name +msgid "Display Name" +msgstr "Prikazani naziv" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__id +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__id +msgid "ID" +msgstr "ID" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard____last_update +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi____last_update +msgid "Last Modified on" +msgstr "Zadnje mijenjano" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__write_uid +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__write_uid +msgid "Last Updated by" +msgstr "Zadnji ažurirao" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__write_date +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__write_date +msgid "Last Updated on" +msgstr "Zadnje ažurirano" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__name +msgid "New Barcode" +msgstr "New Barcode" + +#. module: product_multiple_barcodes +#: model:ir.model.constraint,message:product_multiple_barcodes.constraint_product_product_barcode_uniq +msgid "No error" +msgstr "No error" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_product +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__product_id +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_barcode_multi_view_search +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_variant_barcode_multi_view_search +msgid "Product" +msgstr "Artikal" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_barcode_multi +msgid "Product Barcode Multi" +msgstr "Proizvod Barcode Multi" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_template +msgid "Product Template" +msgstr "Predložak artikla" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__remember_previous_barcode +msgid "Remember previous barcode in \"Additional Barcodes\" field" +msgstr "Remember previous barcode in \"Dodatno Barcodes\" field" + +#. module: product_multiple_barcodes +#: code:addons/product_multiple_barcodes/models/product_product.py:0 +#, python-format +msgid "" +"The following barcode(s): {0} was found in other active products.\n" +"Note that product barcodes should not repeat themselves both in \"Barcode\" field and \"Additional Barcodes\" field." +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_product_view_form_multiply_barcode +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_template_view_form_multiply_barcode +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Update Barcode" +msgstr "Update Barcode" + +#. module: product_multiple_barcodes +#: model:ir.actions.act_window,name:product_multiple_barcodes.action_multiply_barcode_wizard +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Update Product Barcode" +msgstr "Update Proizvod Barcode" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_multiply_barcode_wizard +msgid "Update Product Multiply Barcode Wizard" +msgstr "Update Proizvod Multiply Barcode Wizard" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "" +"Use this popup in case you would like to update barcode of current product. It also allows you to record automatically previous barcode into \"Additional Barcodes\" field,\n" +" so it will still be searchable and also in this case you will be 100% sure that this barcode will not be used by other products also" +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "or" +msgstr "ili" diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/product_multiple_barcodes.pot b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/product_multiple_barcodes.pot new file mode 100644 index 0000000..9dfa1b0 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/i18n/product_multiple_barcodes.pot @@ -0,0 +1,145 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_multiple_barcodes +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-16 14:30+0000\n" +"PO-Revision-Date: 2022-08-16 14:30+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_product__barcode_ids +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_template__barcode_ids +msgid "Additional Barcodes" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__name +msgid "Barcode" +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Cancel" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__create_uid +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__create_uid +msgid "Created by" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__create_date +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__create_date +msgid "Created on" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__display_name +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__display_name +msgid "Display Name" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__id +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__id +msgid "ID" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard____last_update +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__write_uid +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__write_date +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__name +msgid "New Barcode" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.constraint,message:product_multiple_barcodes.constraint_product_product_barcode_uniq +msgid "No error" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_product +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_product_barcode_multi__product_id +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_barcode_multi_view_search +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_variant_barcode_multi_view_search +msgid "Product" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_barcode_multi +msgid "Product Barcode Multi" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_product_template +msgid "Product Template" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model.fields,field_description:product_multiple_barcodes.field_multiply_barcode_wizard__remember_previous_barcode +msgid "Remember previous barcode in \"Additional Barcodes\" field" +msgstr "" + +#. module: product_multiple_barcodes +#: code:addons/product_multiple_barcodes/models/product_product.py:0 +#, python-format +msgid "" +"The following barcode(s): {0} was found in other active products.\n" +"Note that product barcodes should not repeat themselves both in \"Barcode\" field and \"Additional Barcodes\" field." +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_product_view_form_multiply_barcode +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.product_template_view_form_multiply_barcode +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Update Barcode" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.actions.act_window,name:product_multiple_barcodes.action_multiply_barcode_wizard +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "Update Product Barcode" +msgstr "" + +#. module: product_multiple_barcodes +#: model:ir.model,name:product_multiple_barcodes.model_multiply_barcode_wizard +msgid "Update Product Multiply Barcode Wizard" +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "" +"Use this popup in case you would like to update barcode of current product. It also allows you to record automatically previous barcode into \"Additional Barcodes\" field,\n" +" so it will still be searchable and also in this case you will be 100% sure that this barcode will not be used by other products also" +msgstr "" + +#. module: product_multiple_barcodes +#: model_terms:ir.ui.view,arch_db:product_multiple_barcodes.view_multiply_barcode_wizard_form +msgid "or" +msgstr "" diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/__init__.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/__init__.py new file mode 100644 index 0000000..3b7b891 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from . import product_barcode_multi +from . import product_template +from . import product_product diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_barcode_multi.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_barcode_multi.py new file mode 100644 index 0000000..d2f520d --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_barcode_multi.py @@ -0,0 +1,21 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields + + +class ProductBarcodeMulti(models.Model): + _name = 'product.barcode.multi' + _description = 'Product Barcode Multi' + + name = fields.Char( + 'Barcode', + required=True, + ) + + product_id = fields.Many2one( + 'product.product', + string='Product', + required=True, + ondelete="cascade", + ) diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_product.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_product.py new file mode 100644 index 0000000..17c39d4 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_product.py @@ -0,0 +1,73 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields, api, _ +from odoo.osv import expression +from odoo.exceptions import UserError + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + barcode_ids = fields.One2many( + 'product.barcode.multi', + 'product_id', + string='Additional Barcodes', + ) + + # THIS IS OVERRIDE SQL CONSTRAINTS. + _sql_constraints = [ + ('barcode_uniq', 'check(1=1)', 'No error') + ] + + @api.model + def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): + args = args or [] + domain = [] + if name: + domain = ['|', '|', ('name', operator, name), ('default_code', operator, name), + '|', ('barcode', operator, name), ('barcode_ids', operator, name)] + return self._search(expression.AND([domain, args]), + limit=limit, access_rights_uid=name_get_uid) + + @api.constrains('barcode', 'barcode_ids', 'active') + def _check_unique_barcode(self): + barcodes_duplicate = [] + for product in self: + barcode_names = [] + if product.barcode_ids: + barcode_names = product.mapped('barcode_ids.name') + if product.barcode: + barcode_names.append(product.barcode) + if not barcode_names: + continue + products = self.env['product.product'].search([ + ('barcode', 'in', barcode_names), + ('id', '!=', product.id), + ('active', '=', True), + ]) + barcode_ids = self.env['product.barcode.multi'].search([ + ('name', 'in', barcode_names), + ('product_id', '!=', product.id), + ('product_id.active', '=', True), + ]) + if len(barcode_names) != len(set(barcode_names)): + barcodes_multi = set([barcode for barcode in barcode_names if barcode_names.count(barcode) > 1]) + for barcode in barcodes_multi: + barcodes_duplicate.append(barcode) + if barcode_ids: + barcodes = [barcode.name for barcode in barcode_ids] + for barcode in barcodes: + barcodes_duplicate.append(barcode) + if products: + barcodes_product = [product.barcode for product in products] + for barcode in barcodes_product: + barcodes_duplicate.append(barcode) + if barcodes_duplicate: + raise UserError( + _( + "The following barcode(s): {0} was found in other active products." + "\nNote that product barcodes should not repeat themselves both in " + '"Barcode" field and "Additional Barcodes" field.' + ).format(", ".join(set(barcodes_duplicate))) + ) diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_template.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_template.py new file mode 100644 index 0000000..49a77d8 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/models/product_template.py @@ -0,0 +1,10 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + barcode_ids = fields.One2many(related='product_variant_ids.barcode_ids', readonly=False) diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/security/ir.model.access.csv b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/security/ir.model.access.csv new file mode 100644 index 0000000..32d9dba --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/security/ir.model.access.csv @@ -0,0 +1,7 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_product_barcode_multi_user,product.barcode.multi.user,model_product_barcode_multi,base.group_user,1,0,0,0 +access_product_barcode_multi_root,product.barcode.multi.root,model_product_barcode_multi,base.group_system,1,1,1,1 +access_multiply_barcode_wizard,access_multiply_barcode_wizard,model_multiply_barcode_wizard,base.group_user,1,1,1,1 +access_product_multiply_barcode_purchase_manager,product.multiply.barcode.purchase.manager,model_product_barcode_multi,purchase.group_purchase_manager,1,1,1,1 +access_product_multiply_barcode_sale_manager,product.multiply.barcode.sale.manager,model_product_barcode_multi,sales_team.group_sale_manager,1,1,1,1 +access_product_multiply_barcode_stock_manager,product.product.stock.manager,model_product_barcode_multi,stock.group_stock_manager,1,1,1,1 \ No newline at end of file diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/bottom_icon.png b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/bottom_icon.png new file mode 100644 index 0000000..86ca4fe Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/bottom_icon.png differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/icon.png b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/icon.png new file mode 100644 index 0000000..bac9ef9 Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/icon.png differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_1.png b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_1.png new file mode 100644 index 0000000..bb54d20 Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_1.png differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_2.png b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_2.png new file mode 100644 index 0000000..271ace3 Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/image_2.png differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/index.html b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/index.html new file mode 100644 index 0000000..07af461 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/index.html @@ -0,0 +1,36 @@ +
+
+
+

Product Multiple Barcodes

+
+
+

+ TO AVOID ANY ISSUES, PLEASE, USE ALWAYS LATEST VERSION FROM OUR GITHUB REPOSITORY - + + https://github.com/ventor-tech/merp/tree/16.0 + +

+
+
+
+

+ If your products have multiple barcodes on the package you can add them into Odoo using this module. +

+ +

+ Then you will be able to find such products by these barcodes as in web Odoo... +

+ +

+ ... as via the Ventor mobile app installed on your handheld terminal +

+ +

+ Learn more about warehouse optimization in our blog. +

+ +

ventor.tech

+
+
+
+
diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_banner.png b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_banner.png new file mode 100644 index 0000000..c5fec25 Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_banner.png differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_description.gif b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_description.gif new file mode 100644 index 0000000..5022e0c Binary files /dev/null and b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/static/description/main_description.gif differ diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/__init__.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/__init__.py new file mode 100644 index 0000000..13762d4 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from . import test_merp_product_barcode_multi diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/test_merp_product_barcode_multi.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/test_merp_product_barcode_multi.py new file mode 100644 index 0000000..fab2dad --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/tests/test_merp_product_barcode_multi.py @@ -0,0 +1,67 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import TransactionCase +import logging +_logger = logging.getLogger(__name__) + + +class TestMerpProductBarcodeMulti(TransactionCase): + + def setUp(self): + super(TestMerpProductBarcodeMulti, self).setUp() + self.product_1 = self.env['product.template'].create({ + 'name': 'product_1', + 'barcode': 'test003', + }) + self.product_1.product_variant_ids[0].write({ + 'barcode_ids': [(0, 0, {'name': 'test001'})] + }) + + self.product_2 = self.env['product.template'].create({ + 'name': 'product_2', + }) + self.product_2.product_variant_ids[0].write({ + 'barcode_ids': [(0, 0, {'name': 'test002'})] + }) + + self.product_3 = self.env['product.product'].create({ + 'name': 'product_2', + 'barcode_ids': [(0, 0, {'name': 'test004'})] + }) + + ctx = self.env.context.copy() + ctx.update({ + 'active_model': 'product.product', + 'active_id': self.product_3.id, + }) + self.env.context = ctx + + def test_search_by_barcode_multi_product_1(self): + results = self.env['product.product']._name_search('test001') + p = self.env['product.product'].browse(results) + self.assertEqual(p.name, 'product_1') + + def test_search_by_barcode_product_1(self): + results = self.env['product.product']._name_search('test003') + p = self.env['product.product'].browse(results) + self.assertEqual(p.name, 'product_1') + + def test_search_by_barcode_multi_product_2(self): + results = self.env['product.product']._name_search('test002') + p = self.env['product.product'].browse(results) + self.assertEqual(p.name, 'product_2') + + def test_update_barcode_wizard(self): + product = self.product_3 + + old_barcode = product.barcode + new_barcode = 'test007' + + self.env['multiply.barcode.wizard'].create({ + 'name': new_barcode, + 'remember_previous_barcode': True, + }).update_barcode() + + self.assertNotEqual(old_barcode, product.barcode) + self.assertEqual(new_barcode, product.barcode) diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/product_template_views.xml b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/product_template_views.xml new file mode 100644 index 0000000..7b1a0a9 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/product_template_views.xml @@ -0,0 +1,100 @@ + + + + + product.variant.barcode.multi.view.form + product.product + + + + + + + + + + + + + + product.variant.barcode.multi.easy.view.form + product.product + + + + + + + + + + + + + + product.barcode.multi.view.search + product.template + + + + + + + + + + product.variant.barcode.multi.view.search + product.product + + + + + + + + + + product.product.view.form.multiply.barcode + product.product + + + + + + + + + product.template.view.form.multiply.barcode + product.template + + + + + + + + diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/stock_picking_views.xml b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/stock_picking_views.xml new file mode 100644 index 0000000..6c4c0ba --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/views/stock_picking_views.xml @@ -0,0 +1,13 @@ + + + + stock.picking.internal.search + stock.picking + + + + + + + + diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/__init__.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/__init__.py new file mode 100644 index 0000000..ef642ad --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from . import multiply_barcode_wizard diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.py b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.py new file mode 100644 index 0000000..54015d7 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.py @@ -0,0 +1,50 @@ +# Copyright 2021 VentorTech OU +# Part of Ventor modules. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields + + +class MultiplyBarcodeWizard(models.TransientModel): + _name = 'multiply.barcode.wizard' + _description = 'Update Product Multiply Barcode Wizard' + + name = fields.Char( + string='New Barcode', + required=True, + ) + + remember_previous_barcode = fields.Boolean( + string='Remember previous barcode in "Additional Barcodes" field', + default=True, + ) + + def update_barcode(self): + model_name = self.env.context['active_model'] + if model_name == 'product.product': + product = self.env['product.product'].browse(self.env.context['active_id']) + if model_name == 'product.template': + product = self.env['product.template'].browse( + self.env.context['active_id'] + ).product_variant_id + + if self.remember_previous_barcode: + barcode = product.barcode + + if barcode: + product_barcode_multi = self.env['product.barcode.multi'].create({ + 'name': barcode, + 'product_id': product.id, + }) + + product.write({ + 'barcode': self.name, + 'barcode_ids': [(4, product_barcode_multi.id)], + }) + + else: + product.write({ + 'barcode': self.name + }) + + else: + product.barcode = self.name diff --git a/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.xml b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.xml new file mode 100644 index 0000000..60d6e79 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/product_multiple_barcodes/wizard/multiply_barcode_wizard.xml @@ -0,0 +1,33 @@ + + + + multiply.barcode.wizard.form + multiply.barcode.wizard + +
+ +

Use this popup in case you would like to update barcode of current product. It also allows you to record automatically previous barcode into "Additional Barcodes" field, + so it will still be searchable and also in this case you will be 100% sure that this barcode will not be used by other products also

+
+ + + + +
+
+
+
+
+ + + Update Product Barcode + multiply.barcode.wizard + form + + new + + +
diff --git a/odoo-bringout-ventor-product_multiple_barcodes/pyproject.toml b/odoo-bringout-ventor-product_multiple_barcodes/pyproject.toml new file mode 100644 index 0000000..d36bea8 --- /dev/null +++ b/odoo-bringout-ventor-product_multiple_barcodes/pyproject.toml @@ -0,0 +1,45 @@ +[project] +name = "odoo-bringout-ventor-product_multiple_barcodes" +version = "16.0.0" +description = "Product Multiple Barcodes - Allows to define multiple additional barcodes for products and to search products by additional barcodes and internal reference." +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "odoo-bringout-oca-ocb-product>=16.0.0", + "odoo-bringout-oca-ocb-sale>=16.0.0", + "odoo-bringout-oca-ocb-purchase>=16.0.0", + "odoo-bringout-oca-ocb-stock>=16.0.0", + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["product_multiple_barcodes"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +] diff --git a/odoo-bringout-ventor-ventor_base/README.md b/odoo-bringout-ventor-ventor_base/README.md new file mode 100644 index 0000000..8fef5cf --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/README.md @@ -0,0 +1,48 @@ +# Ventor Base + +Custom Odoo addon: ventor_base + +## Installation + +```bash +pip install odoo-bringout-ventor-ventor_base +``` + +## Dependencies + +This addon depends on: +- base +- stock +- stock_picking_batch + +## Manifest Information + +- **Name**: Ventor Base +- **Version**: 16.0.1.4.0 +- **Category**: N/A +- **License**: LGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-ventor vendor, addon `ventor_base`. + +## License + +This package maintains the original LGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-ventor-ventor_base/doc/ARCHITECTURE.md b/odoo-bringout-ventor-ventor_base/doc/ARCHITECTURE.md new file mode 100644 index 0000000..af8dc7a --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Ventor_base Module - ventor_base + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-ventor-ventor_base/doc/CONFIGURATION.md b/odoo-bringout-ventor-ventor_base/doc/CONFIGURATION.md new file mode 100644 index 0000000..7b33c42 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for ventor_base. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-ventor-ventor_base/doc/CONTROLLERS.md b/odoo-bringout-ventor-ventor_base/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-ventor-ventor_base/doc/DEPENDENCIES.md b/odoo-bringout-ventor-ventor_base/doc/DEPENDENCIES.md new file mode 100644 index 0000000..8305810 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/DEPENDENCIES.md @@ -0,0 +1,7 @@ +# Dependencies + +This addon depends on: + +- base +- [stock](../../odoo-bringout-oca-ocb-stock) +- [stock_picking_batch](../../odoo-bringout-oca-ocb-stock_picking_batch) diff --git a/odoo-bringout-ventor-ventor_base/doc/FAQ.md b/odoo-bringout-ventor-ventor_base/doc/FAQ.md new file mode 100644 index 0000000..2fbcdad --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon ventor_base or install in UI. diff --git a/odoo-bringout-ventor-ventor_base/doc/INSTALL.md b/odoo-bringout-ventor-ventor_base/doc/INSTALL.md new file mode 100644 index 0000000..8fa38e4 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-ventor-ventor_base" +# or +uv pip install odoo-bringout-ventor-ventor_base" +``` diff --git a/odoo-bringout-ventor-ventor_base/doc/MODELS.md b/odoo-bringout-ventor-ventor_base/doc/MODELS.md new file mode 100644 index 0000000..6dbf29a --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/MODELS.md @@ -0,0 +1,21 @@ +# Models + +Detected core models and extensions in ventor_base. + +```mermaid +classDiagram + class pallet_transfer + class ventor_option_setting + class ventor_setting_value + class res_company + class res_config_settings + class res_users + class stock_location + class stock_picking_type + class stock_quant + class stock_warehouse +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-ventor-ventor_base/doc/OVERVIEW.md b/odoo-bringout-ventor-ventor_base/doc/OVERVIEW.md new file mode 100644 index 0000000..daef2c5 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: ventor_base. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon ventor_base +- License: LGPL-3 diff --git a/odoo-bringout-ventor-ventor_base/doc/REPORTS.md b/odoo-bringout-ventor-ventor_base/doc/REPORTS.md new file mode 100644 index 0000000..df9b4f2 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/REPORTS.md @@ -0,0 +1,22 @@ +# Reports + +Report definitions and templates in ventor_base. + +```mermaid +classDiagram +``` + +## Available Reports + +No named reports found in XML files. + + +## Report Files + +- **report_stockpicking_operations.xml** (XML template/definition) + +## Notes +- Named reports above are accessible through Odoo's reporting menu +- Python files define report logic and data processing +- XML files contain report templates, definitions, and formatting +- Reports are integrated with Odoo's printing and email systems diff --git a/odoo-bringout-ventor-ventor_base/doc/SECURITY.md b/odoo-bringout-ventor-ventor_base/doc/SECURITY.md new file mode 100644 index 0000000..fb79351 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/SECURITY.md @@ -0,0 +1,42 @@ +# Security + +Access control and security definitions in ventor_base. + +## Access Control Lists (ACLs) + +Model access permissions defined in: +- **[ir.model.access.csv](../ventor_base/security/ir.model.access.csv)** + - 5 model access rules + +## Record Rules + +Row-level security rules defined in: + +## Security Groups & Configuration + +Security groups and permissions defined in: +- **[groups.xml](../ventor_base/security/groups.xml)** + - 32 security groups defined + +```mermaid +graph TB + subgraph "Security Layers" + A[Users] --> B[Groups] + B --> C[Access Control Lists] + C --> D[Models] + B --> E[Record Rules] + E --> F[Individual Records] + end +``` + +Security files overview: +- **[groups.xml](../ventor_base/security/groups.xml)** + - Security groups, categories, and XML-based rules +- **[ir.model.access.csv](../ventor_base/security/ir.model.access.csv)** + - Model access permissions (CRUD rights) + +Notes +- Access Control Lists define which groups can access which models +- Record Rules provide row-level security (filter records by user/group) +- Security groups organize users and define permission sets +- All security is enforced at the ORM level by Odoo diff --git a/odoo-bringout-ventor-ventor_base/doc/TROUBLESHOOTING.md b/odoo-bringout-ventor-ventor_base/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-ventor-ventor_base/doc/USAGE.md b/odoo-bringout-ventor-ventor_base/doc/USAGE.md new file mode 100644 index 0000000..c106c81 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon ventor_base +``` diff --git a/odoo-bringout-ventor-ventor_base/doc/WIZARDS.md b/odoo-bringout-ventor-ventor_base/doc/WIZARDS.md new file mode 100644 index 0000000..48e790d --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/doc/WIZARDS.md @@ -0,0 +1,3 @@ +# Wizards + +This module does not include UI wizards. diff --git a/odoo-bringout-ventor-ventor_base/pyproject.toml b/odoo-bringout-ventor-ventor_base/pyproject.toml new file mode 100644 index 0000000..5f44113 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/pyproject.toml @@ -0,0 +1,44 @@ +[project] +name = "odoo-bringout-ventor-ventor_base" +version = "16.0.0" +description = "Ventor Base - Base module that allow relation between Ventor modules" +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "odoo-bringout-oca-ocb-base>=16.0.0", + "odoo-bringout-oca-ocb-stock>=16.0.0", + "odoo-bringout-ventor-stock_picking_batch>=16.0.0", + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["ventor_base"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +] diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/README.rst b/odoo-bringout-ventor-ventor_base/ventor_base/README.rst new file mode 100644 index 0000000..7a9bcdd --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/README.rst @@ -0,0 +1,39 @@ +Ventor Base +========================= + +Base module that allow relation between Ventor modules + +Changelog +--------- + +16.0.1.4.0 (2023-11-04) +*********************** + +* Added the setting "Check shipping information" to the Package Management menu +* Added the setting "Scan destination location once" to the Warehouse Operations menu +* Added the setting "Prohibition on updating inventory" to the Instant Inventory menu +* Added "Hide product's quantity" and "Hide Apply button" settings in the Inventory Adjustments menu +* Fixed tests + +16.0.1.3.0 (2023-06-26) +*********************** + +* Added the setting "Force pack" to the Package Management menu +* Added the setting "Show quantity dialog first" to the Create SO and Create PO menus +* Added Wave Picking Menu +* Renamed the "Force destination package scan“ setting to “Confirm destination package“ +* Added setting “Use reusable packages“ to Cluster picking menu + +16.0.1.2.0 (2023-03-06) +*********************** + +* Added RFID menu +* Added the barcode of the Sale order name to the Picking Operations report for outgoing transfers +* Added "Order Recheck" menu + +16.0.1.1.0 (2022-12-23) +*********************** + +* Added the setting "Save transfer after exit" to the Internal Transfers menu +* Added the setting "Allow creating new packages" to menus Instant Inventory, Batch Picking, Cluster Picking, Internal Transfers, and all Operation Types +* Added the ability to move pallets diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/__init__.py b/odoo-bringout-ventor-ventor_base/ventor_base/__init__.py new file mode 100644 index 0000000..01dcf60 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/__init__.py @@ -0,0 +1,59 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import models +from . import report +from odoo import api, SUPERUSER_ID + +def _post_init_hook(cr, registry): + """ + This hook updates Ventor Settings in Operation Types + And adds to all users to Ventor - Administrator Role + """ + env = api.Environment(cr, SUPERUSER_ID, {}) + + users_model = env['res.users'] + + values = [(4, user.id) for user in users_model.search([])] + env.ref('ventor_base.ventor_role_admin').users = values + + cr.execute( + """ + UPDATE stock_picking_type + SET + change_destination_location = True, + show_next_product = CASE code when 'incoming' THEN False ELSE True END + """ + ) + + users = users_model.with_context(active_test=False).search( + [ + ('allowed_warehouse_ids', '=', False), + ('share', '=', False) + ] + ) + warehouses = env['stock.warehouse'].with_context(active_test=False).search([]) + for user in users: + user.allowed_warehouse_ids = [(6, 0, warehouses.ids)] + + group_settings = env['res.config.settings'].default_get( + [ + 'group_stock_tracking_lot', + ] + ) + + if group_settings.get('group_stock_tracking_lot'): + ventor_packages_settings = env['ventor.option.setting'].search( + [ + ('technical_name', '=', 'manage_packages'), + ] + ) + ventor_packages_settings.value = env.ref('ventor_base.bool_true') + + if group_settings.get('group_stock_tracking_owner'): + ventor_owner_settings = env['ventor.option.setting'].search( + [ + ('technical_name', '=', 'manage_product_owner'), + ] + ) + ventor_owner_settings.value = env.ref('ventor_base.bool_true') diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/__manifest__.py b/odoo-bringout-ventor-ventor_base/ventor_base/__manifest__.py new file mode 100644 index 0000000..aa864cb --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/__manifest__.py @@ -0,0 +1,40 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +{ + 'name': 'Ventor Base', + 'version': '16.0.1.4.0', + 'author': 'VentorTech', + 'website': 'https://ventor.tech/', + 'license': 'LGPL-3', + 'installable': True, + 'images': ['static/description/main_banner.png'], + 'summary': 'Base module that allow relation between Ventor modules', + 'depends': [ + 'base', + 'stock', + 'stock_picking_batch', + ], + 'data': [ + 'security/groups.xml', + 'security/ir.model.access.csv', + 'data/ventor_setting.xml', + 'data/ventor_option_setting.xml', + 'data/ventor_sequence_data.xml', + 'report/report_stockpicking_operations.xml', + 'views/res_config.xml', + 'views/res_users.xml', + 'views/stock_location.xml', + 'views/stock_picking.xml', + 'views/stock_quant.xml', + 'views/stock_warehouse.xml', + 'views/ventor_option_setting.xml', + 'views/pallet_transfer.xml', + ], + 'post_init_hook': '_post_init_hook', + 'assets': { + 'web.assets_backend': [ + 'ventor_base/static/src/**/*', + ], + } +} diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_option_setting.xml b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_option_setting.xml new file mode 100644 index 0000000..e5d763e --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_option_setting.xml @@ -0,0 +1,1028 @@ + + + + + + Pack extra items + enable_over_flow + + + bool + package_management + Move more items than it initially planned + + + + Validate uncompleted orders + allow_validate_less + + + bool + package_management + User will be able to validate the order even if not all items were found + + + + Manual correction + allow_manual_editing + + + bool + package_management + Packer can mannually change QTY of products + + + + Use default package name + use_default_package_name + + + bool + package_management + Create a package with default Odoo name (e.g 0000001) to put items there + + + + Force pack + pack_all_items + + + bool + package_management + Force all products to be packed + + + + Check shipping information + check_shipping_information + + + bool + package_management + If the setting is active the user can edit shipping information before validate OUT transfer + + + + + Confirm source location + confirm_source_location + + + bool + batch_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of source location + + + + Change source location + change_source_location + + + bool + batch_picking + User can change default source location to pick item from another location. Works only if "Confirm source location" setting is active + + + + Confirm product + confirm_product + + + bool + batch_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of product + + + + Show next product + show_next_product + + + bool + batch_picking + + + + + Confirm destination location + confirm_destination_location + + + bool + batch_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of destination location + + + + Change destination location + change_destination_location + + + bool + batch_picking + If this setting is active a user can change destination location while receiving to be placed at any available location + + + + Apply quantity automatically + apply_quantity_automatically + + + bool + batch_picking + Automatically validate the line after scanning a destination location. Warning: yoy have to insert QTY first before destination location + + + + Show packages fields + manage_packages + + + bool + batch_picking + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + Allow creating new packages + allow_creating_new_packages + + + bool + batch_picking + User can create new packages by scanning a new barcode or create it manually + + + + Confirm source package + confirm_source_package + + + bool + batch_picking + User has to scan a barcode of source package. The dot next to the field gets yellow color means user has to confirm it + + + + Confirm destination package + scan_destination_package + + + bool + batch_picking + User has to scan a barcode of destination package + + + + Show Product Owner field + manage_product_owner + + + bool + batch_picking + Allow scan product owner. You can specify product owner while moving items. Working only with "Consignment" setting on Odoo side + + + + Validate Picking + validate_picking_batch + + + bool + batch_picking + Validate Stock Picking automatically if it completely processed + + + + Apply default lots and serials + apply_default_lots + + + bool + batch_picking + If it's on. you don't need to scan lot number to confirm it. On receipts the app will create default Odoo lots and apply them to the product. On delivery zone you don't need to confirm lots and they will be taken Odoo by default + + + + Move more than planned + transfer_more_items + + + bool + batch_picking + Allow moving more items than expected (for example kg of meat, etc) + + + + Autocomplete the item quantity + autocomplete_the_item_quantity_field + + + bool + batch_picking + Automatically insert expected quantity. No need to enter the quantity of goods using the keyboard or using scanning + + + + Behavior on backorder creation + behavior_on_backorder_creation + + + select + batch_picking + Choose how to process backorders. You can always create backorders. always ignore backorders or choose it all the time (default) + + + + Behavior on split operation + behavior_on_split_operation + + + select + batch_picking + Choose how to to process less product qty than initial. You can always split the line, always move less items or choose it all the time (default) + + + + Show Print attachments button + show_print_attachment_button + + + bool + batch_picking + Showing the Print attachments button in the toolbar instead of keeping it in the hidden menu + + + + Show "Put in pack" button + show_put_in_pack_button + + + bool + batch_picking + Showing the Put in pack button in the toolbar instead of keeping it in the hidden menu + + + + + Confirm source location + confirm_source_location + + + bool + wave_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of source location + + + + Change source location + change_source_location + + + bool + wave_picking + User can change default source location to pick item from another location. Works only if "Confirm source location" setting is active + + + + Confirm product + confirm_product + + + bool + wave_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of product + + + + Show next product + show_next_product + + + bool + wave_picking + + + + + Confirm destination location + confirm_destination_location + + + bool + wave_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of destination location + + + + Change destination location + change_destination_location + + + bool + wave_picking + If this setting is active a user can change destination location while receiving to be placed at any available location + + + + Apply quantity automatically + apply_quantity_automatically + + + bool + wave_picking + Automatically validate the line after scanning a destination location. Warning: yoy have to insert QTY first before destination location + + + + Show packages fields + manage_packages + + + bool + wave_picking + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + Allow creating new packages + allow_creating_new_packages + + + bool + wave_picking + User can create new packages by scanning a new barcode or create it manually + + + + Confirm source package + confirm_source_package + + + bool + wave_picking + User has to scan a barcode of source package. The dot next to the field gets yellow color means user has to confirm it + + + + Confirm destination package + scan_destination_package + + + bool + wave_picking + User has to scan a barcode of destination package. The dot next to the field gets yellow color means user has to confirm it + + + + Show Product Owner field + manage_product_owner + + + bool + wave_picking + Allow scan product owner. You can specify product owner while moving items. Working only with "Consignment" setting on Odoo side + + + + Validate Picking + validate_picking_batch + + + bool + wave_picking + Validate Stock Picking automatically if it completely processed + + + + Apply default lots and serials + apply_default_lots + + + bool + wave_picking + If it's on. you don't need to scan lot number to confirm it. On receipts the app will create default Odoo lots and apply them to the product. On delivery zone you don't need to confirm lots and they will be taken Odoo by default + + + + Move more than planned + transfer_more_items + + + bool + wave_picking + Allow moving more items than expected (for example kg of meat, etc) + + + + Autocomplete the item quantity + autocomplete_the_item_quantity_field + + + bool + wave_picking + Automatically insert expected quantity. No need to enter the quantity of goods using the keyboard or using scanning + + + + Behavior on backorder creation + behavior_on_backorder_creation + + + select + wave_picking + Choose how to process backorders. You can always create backorders. always ignore backorders or choose it all the time (default) + + + + Behavior on split operation + behavior_on_split_operation + + + select + wave_picking + Choose how to to process less product qty than initial. You can always split the line, always move less items or choose it all the time (default) + + + + Show Print attachments button + show_print_attachment_button + + + bool + wave_picking + Showing the Print attachments button in the toolbar instead of keeping it in the hidden menu + + + + Show "Put in pack" button + show_put_in_pack_button + + + bool + wave_picking + Showing the Put in pack button in the toolbar instead of keeping it in the hidden menu + + + + + Confirm source location + confirm_source_location + + + bool + cluster_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of source location + + + + Change source location + change_source_location + + + bool + cluster_picking + User can change default source location to pick item from another location. Works only if "Confirm source location" setting is active + + + + Confirm product + confirm_product + + + bool + cluster_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of product + + + + Show next product + show_next_product + + + bool + cluster_picking + + + + + Confirm destination location + confirm_destination_location + + + bool + cluster_picking + The dot next to the field gets yellow color means user have to confirm it. User has to scan a barcode of destination location + + + + Change destination location + change_destination_location + + + bool + cluster_picking + If this setting is active a user can change destination location while receiving to be placed at any available location + + + + Apply quantity automatically + apply_quantity_automatically + + + bool + cluster_picking + Automatically validate the line after scanning a destination location. Warning: yoy have to insert QTY first before destination location + + + + Show packages fields + manage_packages + + + bool + cluster_picking + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + Allow creating new packages + allow_creating_new_packages + + + bool + cluster_picking + User can create new packages by scanning a new barcode or create it manually + + + + Confirm source package + confirm_source_package + + + bool + cluster_picking + User has to scan a barcode of source package. The dot next to the field gets yellow color means user has to confirm it + + + + Confirm destination package + scan_destination_package + + + bool + cluster_picking + User has to scan a barcode of destination package + + + + Show Product Owner field + manage_product_owner + + + bool + cluster_picking + Allow scan product owner. You can specify product owner while moving items. Working only with "Consignment" setting on Odoo side + + + + Validate Picking + validate_picking_batch + + + bool + cluster_picking + Validate Stock Picking automatically if it completely processed + + + + Apply default lots and serials + apply_default_lots + + + bool + cluster_picking + If it's on. you don't need to scan lot number to confirm it. On receipts the app will create default Odoo lots and apply them to the product. On delivery zone you don't need to confirm lots and they will be taken Odoo by default + + + + Move more than planned + transfer_more_items + + + bool + cluster_picking + Allow moving more items than expected (for example kg of meat, etc) + + + + Autocomplete the item quantity + autocomplete_the_item_quantity_field + + + bool + cluster_picking + Automatically insert expected quantity. No need to enter the quantity of goods using the keyboard or using scanning + + + + Behavior on backorder creation + behavior_on_backorder_creation + + + select + cluster_picking + Choose how to process backorders. You can always create backorders. always ignore backorders or choose it all the time (default) + + + + Behavior on split operation + behavior_on_split_operation + + + select + cluster_picking + Choose how to to process less product qty than initial. You can always split the line, always move less items or choose it all the time (default) + + + + Show Print attachments button + show_print_attachment_button + + + bool + cluster_picking + Showing the Print attachments button in the toolbar instead of keeping it in the hidden menu + + + + Show "Put in pack" button + show_put_in_pack_button + + + bool + cluster_picking + Showing the Put in pack button in the toolbar instead of keeping it in the hidden menu + + + + Blind cluster picking + suggest_next_product_cluster_picking + + + bool + cluster_picking + If it's active you will not see products to pick. This way you can scan items in any order to sort them out to boxes + + + + Add boxes before cluster + add_boxes_before_cluster + + + bool + cluster_picking + User has to scan all boxes before the cluster picking + + + + Multiple boxes for one transfer + multiple_boxes_for_one_transfer + + + bool + cluster_picking + One transfer can be picked in multiple boxes + + + + Use reusable packages + use_reusable_packages + + + bool + cluster_picking + Apply reusable packages as cluster boxes (same as Odoo does) instead of locations (default in Ventor) + + + + + Show packages fields + manage_packages + + + bool + internal_transfers + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + Allow creating new packages + allow_creating_new_packages + + + bool + internal_transfers + User can create new packages by scanning a new barcode or create it manually + + + + Move multiple items + move_multiple_products + + + bool + internal_transfers + Add a new button Next item to move more than one item per transaction + + + + Hold source location + hold_source_location + + + bool + internal_transfers + Hold latest scanned source location while transfers. Use it if you move the items from the same location. Reset after exit + + + + Hold destination location + hold_destination_location + + + bool + internal_transfers + Hold latest scanned destination location while transfers. Use it if you move items to the same location. Reset after exit + + + + Autofill for source location + apply_source_location + + + bool + internal_transfers + If it active, you can scan a product first to see the list of all locations where such product is placed. The source location field will be auto-filled if a product is placed only in one location + + + + Allow moving missed items + allow_move_more + + + bool + internal_transfers + Turn on if you want to move any item from any location even if you don't have enough in stock. Note this may cause a negative stock balance + + + + Show only lots from source location + lot_for_location + + + bool + internal_transfers + If it is active, you can select only lots from source location + + + + Show Product Owner field + manage_product_owner + + + bool + internal_transfers + Allow scan product owner. You can specify product owner while moving items. Working only with "Consignment" setting on Odoo side + + + + Save transfer after exit + save_transfer_after_exit + + + select + internal_transfers + Choose the action on the transfer after exit the menu. You can save it or cancel without dialog screen + + + + + Move all items automatically + set_auto_validate + + + bool + putaway + If this setting is active all scanned items will be validated automatically after scanning a destination location + + + + Show packages fields + manage_packages + + + bool + putaway + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + + Hide product's quantity + hide_products_quantity + + + bool + inventory_adjustments + Prevent users from seeing on-hand quantity + + + + Hide Apply button + hide_apply_button + + + bool + inventory_adjustments + Products quantity will be saved but not applied + + + + + Hold inventory location + hold_inventory_location + + + bool + instant_inventory + Hold latest scanned location while inventory. Use it if you make inventory of different items from the same location (e.g stock). Reset after exit + + + + Autofill for inventory location + auto_fill_inventory_location + + + bool + instant_inventory + If it active, you can scan a product first to see the list of all locations where such product is placed. The inventory location field will be auto-filled if a product is placed only in one location + + + + Show only lots/serials from inventory location + lot_for_location + + + bool + instant_inventory + If it is active, you can select only products, lots and serial numbers from inventory location + + + + Start inventory with 1 + start_inventory_with_one + + + bool + instant_inventory + User starts inventory with 1 and scan all the items to apply quantity + + + + Show packages fields + manage_packages + + + bool + instant_inventory + Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side + + + + Allow creating new packages + allow_creating_new_packages + + + bool + instant_inventory + User can create new packages by scanning a new barcode or create it manually + + + + Show Product Owner field + manage_product_owner + + + bool + instant_inventory + Allow scan product owner. You can specify product owner while moving items. Working only with "Consignment" setting on Odoo side + + + + Prohibition on updating inventory + prohibition_on_updating_inventory + + + bool + instant_inventory + The user will not be able to overwrite the inventory qty, but only count it and save + + + + + Group quants + grouping_quants + + + bool + quick_info + If active you can see aggregated QTY of all quants of the same product (including negative). Disable it to see all lines separately + + + + + Show packages fields + manage_packages + + + bool + scrap_management + It shows additional field "Package" that you can scan to make an inventory in a package. Works only if package management settings is active on Odoo side + + + + Show Product Owner field + manage_product_owner + + + bool + scrap_management + Allow scanning a product owner. You can specify owner while making inventory. Working only with active setting "Consignment" on Odoo side + + + + + Show quantity dialog first + show_quantity_dialog_first_so + + + bool + create_so + You can edit qty and taxes every time you scan the product + + + + + Show quantity dialog first + show_quantity_dialog_first_po + + + bool + create_po + You can edit qty and taxes every time you scan the product + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_sequence_data.xml b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_sequence_data.xml new file mode 100644 index 0000000..6e61a13 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_sequence_data.xml @@ -0,0 +1,15 @@ + + + + + + Pallet Transfers + pallet.transfer + PT/ + 5 + 1 + 1 + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_setting.xml b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_setting.xml new file mode 100644 index 0000000..97148bf --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/data/ventor_setting.xml @@ -0,0 +1,52 @@ + + + + bool + True + + + + bool + False + + + + behavior_on_backorder_creation + Always Create Backorder + + + + behavior_on_backorder_creation + Never Create Backorder + + + + behavior_on_backorder_creation + Ask Me Every Time + + + + behavior_on_split_operation + Always Split the Line + + + + behavior_on_split_operation + Always Move Less Items + + + + behavior_on_split_operation + Ask Me Every Time + + + + save_transfer_after_exit + Save transfer + + + + save_transfer_after_exit + Cancel transfer + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/doc/index.rst b/odoo-bringout-ventor-ventor_base/ventor_base/doc/index.rst new file mode 100644 index 0000000..db3e389 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/doc/index.rst @@ -0,0 +1,35 @@ +Ventor Base +=========== + +| + +**Base module that allow relation between Ventor modules** + +Change Log +########## + +| + +* 16.0.1.4.0 (2023-11-04) + - Added the setting "Check shipping information" to the Package Management menu + - Added the setting "Scan destination location once" to the Warehouse Operations menu + - Added the setting "Prohibition on updating inventory" to the Instant Inventory menu + - Added "Hide product's quantity" and "Hide Apply button" settings in the Inventory Adjustments menu + - Fixed tests + +* 16.0.1.3.0 (2023-06-26) + - Added the setting "Force pack" to the Package Management menu + - Added the setting "Show quantity dialog first" to the Create SO and Create PO menus + - Added Wave Picking Menu + - Renamed the "Force destination package scan“ setting to “Confirm destination package“ + - Added setting “Use reusable packages“ to Cluster picking menu + +* 16.0.1.2.0 (2023-03-06) + - Added RFID menu + - Added the barcode of the Sale order name to the Picking Operations report for outgoing transfers + - Added "Order Recheck" menu + +* 16.0.1.1.0 (2022-12-23) + - Added the setting "Save transfer after exit" to the Internal Transfers menu + - Added the setting "Allow creating new packages" to menus Instant Inventory, Batch Picking, Cluster Picking, Internal Transfers, and all Operation Types + - Added the ability to move pallets diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/i18n/bs.po b/odoo-bringout-ventor-ventor_base/ventor_base/i18n/bs.po new file mode 100644 index 0000000..d77dea8 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/i18n/bs.po @@ -0,0 +1,741 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ventor_base +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:43+0000\n" +"PO-Revision-Date: 2022-08-18 13:43+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "" +"'Autocomplete item quantity' is available only if 'Change destination " +"location' is enabled" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "" +"'Change source location' is available only if 'Confirm source location' is " +"enabled" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Custom Build Name" +msgstr "Custom Build Name" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Custom Mobile Logo" +msgstr "Custom Mobile Logo" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Add Outgoing Routing strategy options (sort locations)" +msgstr "Add Outgoing Routing strategy options (sort locations)" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Additional Customisation" +msgstr "Additional Customisation" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_admin +msgid "Administrator" +msgstr "Administrator" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__manage_product_owner +msgid "" +"Allow scan product owner. You can specify product owner while moving items. " +"Working only with 'Consignment' setting on Odoo side" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__allowed_warehouse_ids +msgid "Allowed Warehouses" +msgstr "Allowed Warehouses" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__transfer_more_items +msgid "Allows moving more items than expected (for example kg of meat, etc)" +msgstr "Allows moving more items than expected (for example kg of meat, etc)" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__always_create_backorder +msgid "Always Create Backorder" +msgstr "Always Create Backorder" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__always_move_less_items +msgid "Always Move Less Items" +msgstr "Always Move Less Items" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__always_split_line +msgid "Always Split the Line" +msgstr "Always Split the Line" + +#. module: ventor_base +#: code:addons/ventor_base/models/res_company.py:0 +#, python-format +msgid "" +"Apparently, the logotype is not a .png file or the file was incorrectly " +"converted to .png format" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__apply_default_lots +msgid "Apply default lots and serials" +msgstr "Apply default lots and serials" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__apply_quantity_automatically +msgid "Apply quantity automatically" +msgstr "Apply quantity automatically" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__ask_me_every_time +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__ask_me_every_time +msgid "Ask Me Every Time" +msgstr "Ask Me Every Time" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__autocomplete_the_item_quantity_field +msgid "Autocomplete item quantity" +msgstr "Autocomplete item quantity" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__autocomplete_the_item_quantity_field +msgid "" +"Automatically insert expected quantity. No need to enter the quantity of " +"goods using the keyboard or using scanning" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__apply_quantity_automatically +msgid "" +"Automatically validate the line after scanning a destination location. " +"Warning: you have to insert QTY first before destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__base_version +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Base Module Version" +msgstr "Base Module Version" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_batch_picking_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__batch_picking +#: model:ir.ui.menu,name:ventor_base.ventor_batch_picking_app_menu +msgid "Batch Picking" +msgstr "Batch Izbor" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_picking_wave +msgid "Batch Picking Menu" +msgstr "Batch Izbor Menu" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_picking_wave_allow_done +msgid "Batch Picking: Close batch picking" +msgstr "Batch Izbor: Close batch picking" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__behavior_on_backorder_creation +msgid "Behavior On Backorder Creation" +msgstr "Behavior On Backorder Creation" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__behavior_on_split_operation +msgid "Behavior On Split Operation" +msgstr "Behavior On Split Operation" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__value_type__bool +msgid "Boolean" +msgstr "Logički" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__change_destination_location +msgid "Change destination location" +msgstr "Change destination location" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__change_source_location +msgid "Change source location" +msgstr "Change source location" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__check_shipping_information +msgid "Check shipping information" +msgstr "Check shipping information" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__behavior_on_backorder_creation +msgid "" +"Choose how to process backorders. You can always create backorders, always " +"ignore backorders or choose it all the time (default)" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__behavior_on_split_operation +msgid "" +"Choose how to process less product qty than initial. You can always split " +"the line, always move less items or choose it all the time(default)" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_cluster_picking_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__cluster_picking +#: model:ir.ui.menu,name:ventor_base.ventor_cluster_picking_app_menu +msgid "Cluster Picking" +msgstr "Cluster Izbor" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_company +msgid "Companies" +msgstr "Kompanije" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_config_settings +msgid "Config Settings" +msgstr "Postavke" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_configs_action +msgid "Configuration" +msgstr "Konfiguracija" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_destination_location +msgid "Confirm destination location" +msgstr "Confirm destination location" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_product +msgid "Confirm product" +msgstr "Confirm product" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_source_location +msgid "Confirm source location" +msgstr "Confirm source location" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_source_package +msgid "Confirm source package" +msgstr "Confirm source package" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_create_purchase_order +msgid "Create Purchase Order Menu" +msgstr "Create Purchase Order Menu" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_create_sales_order +msgid "Create Sales Order Menu" +msgstr "Create Sales Order Menu" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__custom_package_name +msgid "Custom package name" +msgstr "Custom package name" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_debug +msgid "Debug: Technical Features" +msgstr "Debug: Technical Features" + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_manage_ventor_configuration_app +msgid "" +"Enable to see new root menu \"Ventor Configuration\" \n" +" that will allow to define global Ventor settings \n" +" from the Odoo interface." +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_external_management +msgid "External Transfers Menu" +msgstr "External Transfers Menu" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_company__force_lot_validation_on_inventory_adjustment +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__force_lot_validation_on_inventory_adjustment +msgid "Force Lot Validation on Inventory Adjustment" +msgstr "Force Lot Važećiation on Inventory Adjustment" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__scan_destination_package +msgid "Force destination package scan" +msgstr "Force destination package scan" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_global_settings +msgid "Global Settings" +msgstr "Global Settings" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_settings_app_menu +msgid "Global Ventor Settings" +msgstr "Global Ventor Settings" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_location_search +msgid "Group by..." +msgstr "Grupiši po..." + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_menu_allow_changing_settings +msgid "" +"If it's checked, the manual settings (defined on device by this user) \n" +" will be used instead Global Ventor Settings in Odoo. \n" +" If it's unchecked the user will not be able to modify settings on the \n" +" device manually. Global Ventor Settings will be used instead." +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__apply_default_lots +msgid "" +"If it's on, you don't need to scan lot number to confirm it. On receipts the" +" app will create default Odoo lots and apply them to the product. On " +"delivery zone you don't need to confirm lots and they will be taken Odoo by " +"default" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__check_shipping_information +msgid "" +"If the setting is active the user can edit shipping information before " +"validate OUT transfer" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__scan_destination_package +msgid "" +"If this active user has to scan a destination package (pallet) all the time" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__change_destination_location +msgid "" +"If this setting is active a user can change destination location while " +"receiving to be placed at any available location" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_instant_inventory_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__instant_inventory +#: model:ir.ui.menu,name:ventor_base.ventor_instant_inventory_app_menu +msgid "Instant Inventory" +msgstr "Instant Inventory" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_instant_inventory +msgid "Instant Inventory Menu" +msgstr "Instant Inventory Menu" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_internal_transfers_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__internal_transfers +#: model:ir.ui.menu,name:ventor_base.ventor_internal_transfers_app_menu +msgid "Internal Transfers" +msgstr "Interni prenosi" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_instant_move +msgid "Internal Transfers Menu" +msgstr "Internal Transfers Menu" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__inventory_adjustments +msgid "Inventory Adjustments" +msgstr "Inventure" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_inventory_adjustments +msgid "Inventory Adjustments Menu" +msgstr "Inventory Adjustments Menu" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_inventory_allow_ready_state +msgid "Inventory Adjustments: Waiting for Validation" +msgstr "Inventory Adjustments: Waiting for Važećiation" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_location +msgid "Inventory Locations" +msgstr "Lokacije inventure" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Inventory settings" +msgstr "Inventory settings" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_consignment_enabled +msgid "Is Consignment Enabled" +msgstr "Is Consignment Enabled" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_warehouse__is_internal +msgid "Is Internal Warehouse" +msgstr "Is Internal Warehouse" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_package_tracking_enabled +msgid "Is Package Tracking Enabled" +msgstr "Is Paket Tracking Enabled" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_stock_production_lot_enabled +msgid "Is Stock Production Lot Enabled" +msgstr "Is Zalihe Production Lot Enabled" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_res_users__allowed_warehouse_ids +msgid "List of all warehouses user has access to" +msgstr "List of all warehouses user has access to" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_manufacturing +msgid "MO and WO management" +msgstr "MO and WO management" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_manage_ventor_configuration_app +msgid "Manage Ventor Configuration app" +msgstr "Manage Ventor Configuration app" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__transfer_more_items +msgid "Move more than planned" +msgstr "Move more than planned" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "Multi Warehouses" +msgstr "Multi Warehouses" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__never_create_backorder +msgid "Never Create Backorder" +msgstr "Never Create Backorder" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__module_outgoing_routing +msgid "Outgoing Routing" +msgstr "Outgoing Routing" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_package_management_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__package_management +#: model:ir.ui.menu,name:ventor_base.ventor_package_management_app_menu +msgid "Package Management" +msgstr "Paket Management" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_package_management +msgid "Package Management Menu" +msgstr "Paket Management Menu" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_picking_type +msgid "Picking Type" +msgstr "Vrsta dokumenta" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_next_product +msgid "" +"Product field will show the next product to be picked. Use the setting " +"during picking and delivery. It is recommended to disable the setting for " +"the reception area" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_putaway_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__putaway +#: model:ir.ui.menu,name:ventor_base.ventor_putaway_app_menu +msgid "Putaway" +msgstr "Putaway" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_putaway +msgid "Putaway Menu" +msgstr "Putaway Menu" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_quant +msgid "Quants" +msgstr "Količine" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__quick_info +msgid "Quick Info" +msgstr "Quick Info" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_info +msgid "Quick Info Menu" +msgstr "Quick Info Menu" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_allow_update_product_on_hand +msgid "Quick Info: Update product on hand" +msgstr "Quick Info: Update product on hand" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_quick_info_action +#: model:ir.ui.menu,name:ventor_base.ventor_quick_info_app_menu +msgid "Quick info" +msgstr "Quick info" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__manage_packages +msgid "" +"Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side.\n" +"\n" +" If you want to use Show packages fields, you must turn on setting 'Packages' in inventory settings" +msgstr "" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_app_settings +msgid "Settings" +msgstr "Postavke" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_print_attachment_button +msgid "Show Print attachments button" +msgstr "Show Štampaj attachments button" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__manage_product_owner +msgid "Show Product Owner field" +msgstr "Show Product Owner field" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_put_in_pack_button +msgid "Show Put in pack button" +msgstr "Show Put in pack button" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_next_product +msgid "Show next product" +msgstr "Show next product" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__manage_packages +msgid "Show packages fields" +msgstr "Show packages fields" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__add_barcode_on_view +msgid "Show the Location barcode field on the form" +msgstr "Show the Location barcode field on the form" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_print_attachment_button +msgid "" +"Showing the Print attachments button in the toolbar instead of keeping it in" +" the hidden menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_put_in_pack_button +msgid "" +"Showing the Put in pack button in the toolbar instead of keeping it in the " +"hidden menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_destination_location +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_product +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of product." +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_source_location +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of source location" +msgstr "" + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_user_validate_inventory_adjustment +msgid "The group allows Inventory/User to validate inventory" +msgstr "The group allows Inventory/User to validate inventory" + +#. module: ventor_base +#: code:addons/ventor_base/models/res_company.py:0 +#, python-format +msgid "The logotype can't be less than {}x{} px." +msgstr "The logotype can't be less than {}x{} px." + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Use it to activate barcodes for the Community version" +msgstr "Use it to activate barcodes for the Community version" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_allow_changing_settings +msgid "Use local user device settings" +msgstr "Use local user device settings" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_user_settings +#: model:ir.ui.menu,name:ventor_base.ventor_app_user_settings_menu +msgid "User Settings" +msgstr "Korisničke postavke" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__change_source_location +msgid "" +"User can change default source location to pick item from another location. " +"Works only if 'Confirm source location' setting is active" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_source_package +msgid "" +"User has to scan a barcode of source package. The dot next to the field gets" +" yellow color means user has to confirm it" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_users +msgid "Users" +msgstr "Korisnici" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_user_validate_inventory_adjustment +msgid "Validate Inventory" +msgstr "Vrednovanje zaliha" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_merp_access_application +msgid "Ventor Access Rights" +msgstr "Ventor Access Rights" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_company__logotype_file +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__logotype_file +msgid "Ventor Application Logo File" +msgstr "Ventor Application Logo File" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Ventor Application modules" +msgstr "Ventor Application modules" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_base_version +msgid "Ventor Base Version" +msgstr "Ventor Base Version" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_app_base_menu +#: model_terms:ir.ui.view,arch_db:ventor_base.ventor_stock_picking_form +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Ventor Configuration" +msgstr "Ventor Configuration" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_merp_menu_application +msgid "Ventor Menu Management" +msgstr "Ventor Menu Management" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_ventor_option_setting +msgid "Ventor Option Setting" +msgstr "Ventor Option Setting" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "Ventor Preferences" +msgstr "Ventor Preferences" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_ventor_roles +msgid "Ventor Roles" +msgstr "Ventor Roles" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_ventor_setting_value +msgid "Ventor Setting Value" +msgstr "Ventor Setting Value" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_warehouse +#: model:ir.model.fields,field_description:ventor_base.field_stock_location__warehouse_id +#: model_terms:ir.ui.view,arch_db:ventor_base.view_location_search +msgid "Warehouse" +msgstr "Skladište" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_stock_picking_action +#: model:ir.ui.menu,name:ventor_base.ventor_wh_operations_app_menu +msgid "Warehouse Operations" +msgstr "Warehouse Operations" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_warehouse_operations +msgid "Warehouse Operations Menu" +msgstr "Warehouse Operations Menu" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_allow_applying_all_qty_of_product +msgid "Warehouse Operations: Allow applying all qty of product" +msgstr "Warehouse Operations: Allow applying all qty of product" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_wh_manager +msgid "Warehouse manager" +msgstr "Warehouse manager" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_wh_worker +msgid "Warehouse worker" +msgstr "Warehouse worker" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "Warning" +msgstr "Upozorenje" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "" +"Warning! If the user is Inventory / Administrator, \n" +" the Allowed Warehouses configuration is ignored and \n" +" the user will still be able to see all warehouses" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_quant.py:0 +#, python-format +msgid "You need to supply a Lot/Serial number for product: %s" +msgstr "You need to supply a Lot/Serial number for product: %s" diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/i18n/ventor_base.pot b/odoo-bringout-ventor-ventor_base/ventor_base/i18n/ventor_base.pot new file mode 100644 index 0000000..aef8b23 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/i18n/ventor_base.pot @@ -0,0 +1,741 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * ventor_base +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-08-18 13:43+0000\n" +"PO-Revision-Date: 2022-08-18 13:43+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "" +"'Autocomplete item quantity' is available only if 'Change destination " +"location' is enabled" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "" +"'Change source location' is available only if 'Confirm source location' is " +"enabled" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Custom Build Name" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Custom Mobile Logo" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Add Outgoing Routing strategy options (sort locations)" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Additional Customisation" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_admin +msgid "Administrator" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__manage_product_owner +msgid "" +"Allow scan product owner. You can specify product owner while moving items. " +"Working only with 'Consignment' setting on Odoo side" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__allowed_warehouse_ids +msgid "Allowed Warehouses" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__transfer_more_items +msgid "Allows moving more items than expected (for example kg of meat, etc)" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__always_create_backorder +msgid "Always Create Backorder" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__always_move_less_items +msgid "Always Move Less Items" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__always_split_line +msgid "Always Split the Line" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/res_company.py:0 +#, python-format +msgid "" +"Apparently, the logotype is not a .png file or the file was incorrectly " +"converted to .png format" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__apply_default_lots +msgid "Apply default lots and serials" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__apply_quantity_automatically +msgid "Apply quantity automatically" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__ask_me_every_time +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_split_operation__ask_me_every_time +msgid "Ask Me Every Time" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__autocomplete_the_item_quantity_field +msgid "Autocomplete item quantity" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__autocomplete_the_item_quantity_field +msgid "" +"Automatically insert expected quantity. No need to enter the quantity of " +"goods using the keyboard or using scanning" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__apply_quantity_automatically +msgid "" +"Automatically validate the line after scanning a destination location. " +"Warning: you have to insert QTY first before destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__base_version +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Base Module Version" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_batch_picking_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__batch_picking +#: model:ir.ui.menu,name:ventor_base.ventor_batch_picking_app_menu +msgid "Batch Picking" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_picking_wave +msgid "Batch Picking Menu" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_picking_wave_allow_done +msgid "Batch Picking: Close batch picking" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__behavior_on_backorder_creation +msgid "Behavior On Backorder Creation" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__behavior_on_split_operation +msgid "Behavior On Split Operation" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__value_type__bool +msgid "Boolean" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__change_destination_location +msgid "Change destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__change_source_location +msgid "Change source location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__check_shipping_information +msgid "Check shipping information" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__behavior_on_backorder_creation +msgid "" +"Choose how to process backorders. You can always create backorders, always " +"ignore backorders or choose it all the time (default)" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__behavior_on_split_operation +msgid "" +"Choose how to process less product qty than initial. You can always split " +"the line, always move less items or choose it all the time(default)" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_cluster_picking_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__cluster_picking +#: model:ir.ui.menu,name:ventor_base.ventor_cluster_picking_app_menu +msgid "Cluster Picking" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_company +msgid "Companies" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_configs_action +msgid "Configuration" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_destination_location +msgid "Confirm destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_product +msgid "Confirm product" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_source_location +msgid "Confirm source location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__confirm_source_package +msgid "Confirm source package" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_create_purchase_order +msgid "Create Purchase Order Menu" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_create_sales_order +msgid "Create Sales Order Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__custom_package_name +msgid "Custom package name" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_debug +msgid "Debug: Technical Features" +msgstr "" + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_manage_ventor_configuration_app +msgid "" +"Enable to see new root menu \"Ventor Configuration\" \n" +" that will allow to define global Ventor settings \n" +" from the Odoo interface." +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_external_management +msgid "External Transfers Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_company__force_lot_validation_on_inventory_adjustment +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__force_lot_validation_on_inventory_adjustment +msgid "Force Lot Validation on Inventory Adjustment" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__scan_destination_package +msgid "Force destination package scan" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_global_settings +msgid "Global Settings" +msgstr "" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_settings_app_menu +msgid "Global Ventor Settings" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_location_search +msgid "Group by..." +msgstr "" + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_menu_allow_changing_settings +msgid "" +"If it's checked, the manual settings (defined on device by this user) \n" +" will be used instead Global Ventor Settings in Odoo. \n" +" If it's unchecked the user will not be able to modify settings on the \n" +" device manually. Global Ventor Settings will be used instead." +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__apply_default_lots +msgid "" +"If it's on, you don't need to scan lot number to confirm it. On receipts the" +" app will create default Odoo lots and apply them to the product. On " +"delivery zone you don't need to confirm lots and they will be taken Odoo by " +"default" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__check_shipping_information +msgid "" +"If the setting is active the user can edit shipping information before " +"validate OUT transfer" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__scan_destination_package +msgid "" +"If this active user has to scan a destination package (pallet) all the time" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__change_destination_location +msgid "" +"If this setting is active a user can change destination location while " +"receiving to be placed at any available location" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_instant_inventory_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__instant_inventory +#: model:ir.ui.menu,name:ventor_base.ventor_instant_inventory_app_menu +msgid "Instant Inventory" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_instant_inventory +msgid "Instant Inventory Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_internal_transfers_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__internal_transfers +#: model:ir.ui.menu,name:ventor_base.ventor_internal_transfers_app_menu +msgid "Internal Transfers" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_instant_move +msgid "Internal Transfers Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__inventory_adjustments +msgid "Inventory Adjustments" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_inventory_adjustments +msgid "Inventory Adjustments Menu" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_inventory_allow_ready_state +msgid "Inventory Adjustments: Waiting for Validation" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_location +msgid "Inventory Locations" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Inventory settings" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_consignment_enabled +msgid "Is Consignment Enabled" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_warehouse__is_internal +msgid "Is Internal Warehouse" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_package_tracking_enabled +msgid "Is Package Tracking Enabled" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__is_stock_production_lot_enabled +msgid "Is Stock Production Lot Enabled" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_res_users__allowed_warehouse_ids +msgid "List of all warehouses user has access to" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_manufacturing +msgid "MO and WO management" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_manage_ventor_configuration_app +msgid "Manage Ventor Configuration app" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__transfer_more_items +msgid "Move more than planned" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "Multi Warehouses" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__stock_picking_type__behavior_on_backorder_creation__never_create_backorder +msgid "Never Create Backorder" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__module_outgoing_routing +msgid "Outgoing Routing" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_package_management_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__package_management +#: model:ir.ui.menu,name:ventor_base.ventor_package_management_app_menu +msgid "Package Management" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_package_management +msgid "Package Management Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_picking_type +msgid "Picking Type" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_next_product +msgid "" +"Product field will show the next product to be picked. Use the setting " +"during picking and delivery. It is recommended to disable the setting for " +"the reception area" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_putaway_action +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__putaway +#: model:ir.ui.menu,name:ventor_base.ventor_putaway_app_menu +msgid "Putaway" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_putaway +msgid "Putaway Menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_quant +msgid "Quants" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields.selection,name:ventor_base.selection__ventor_option_setting__action_type__quick_info +msgid "Quick Info" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_info +msgid "Quick Info Menu" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_allow_update_product_on_hand +msgid "Quick Info: Update product on hand" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_quick_info_action +#: model:ir.ui.menu,name:ventor_base.ventor_quick_info_app_menu +msgid "Quick info" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__manage_packages +msgid "" +"Scan source (destination) packages right after scanning source (destination) location. Use it if you move from one package to another or pick items from packages or pallets. Works only if package management settings is active on Odoo side.\n" +"\n" +" If you want to use Show packages fields, you must turn on setting 'Packages' in inventory settings" +msgstr "" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_app_settings +msgid "Settings" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_print_attachment_button +msgid "Show Print attachments button" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__manage_product_owner +msgid "Show Product Owner field" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_put_in_pack_button +msgid "Show Put in pack button" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__show_next_product +msgid "Show next product" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_stock_picking_type__manage_packages +msgid "Show packages fields" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__add_barcode_on_view +msgid "Show the Location barcode field on the form" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_print_attachment_button +msgid "" +"Showing the Print attachments button in the toolbar instead of keeping it in" +" the hidden menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__show_put_in_pack_button +msgid "" +"Showing the Put in pack button in the toolbar instead of keeping it in the " +"hidden menu" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_destination_location +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of destination location" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_product +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of product." +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_source_location +msgid "" +"The dot next to the field gets yellow color means user has to confirm it. " +"User has to scan a barcode of source location" +msgstr "" + +#. module: ventor_base +#: model:res.groups,comment:ventor_base.merp_user_validate_inventory_adjustment +msgid "The group allows Inventory/User to validate inventory" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/res_company.py:0 +#, python-format +msgid "The logotype can't be less than {}x{} px." +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Use it to activate barcodes for the Community version" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_allow_changing_settings +msgid "Use local user device settings" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_user_settings +#: model:ir.ui.menu,name:ventor_base.ventor_app_user_settings_menu +msgid "User Settings" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__change_source_location +msgid "" +"User can change default source location to pick item from another location. " +"Works only if 'Confirm source location' setting is active" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,help:ventor_base.field_stock_picking_type__confirm_source_package +msgid "" +"User has to scan a barcode of source package. The dot next to the field gets" +" yellow color means user has to confirm it" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_res_users +msgid "Users" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_user_validate_inventory_adjustment +msgid "Validate Inventory" +msgstr "" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_merp_access_application +msgid "Ventor Access Rights" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_company__logotype_file +#: model:ir.model.fields,field_description:ventor_base.field_res_config_settings__logotype_file +msgid "Ventor Application Logo File" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Ventor Application modules" +msgstr "" + +#. module: ventor_base +#: model:ir.model.fields,field_description:ventor_base.field_res_users__ventor_base_version +msgid "Ventor Base Version" +msgstr "" + +#. module: ventor_base +#: model:ir.ui.menu,name:ventor_base.ventor_app_base_menu +#: model_terms:ir.ui.view,arch_db:ventor_base.ventor_stock_picking_form +#: model_terms:ir.ui.view,arch_db:ventor_base.view_stock_config_settings +msgid "Ventor Configuration" +msgstr "" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_merp_menu_application +msgid "Ventor Menu Management" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_ventor_option_setting +msgid "Ventor Option Setting" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "Ventor Preferences" +msgstr "" + +#. module: ventor_base +#: model:ir.module.category,name:ventor_base.module_category_ventor_roles +msgid "Ventor Roles" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_ventor_setting_value +msgid "Ventor Setting Value" +msgstr "" + +#. module: ventor_base +#: model:ir.model,name:ventor_base.model_stock_warehouse +#: model:ir.model.fields,field_description:ventor_base.field_stock_location__warehouse_id +#: model_terms:ir.ui.view,arch_db:ventor_base.view_location_search +msgid "Warehouse" +msgstr "" + +#. module: ventor_base +#: model:ir.actions.act_window,name:ventor_base.ventor_stock_picking_action +#: model:ir.ui.menu,name:ventor_base.ventor_wh_operations_app_menu +msgid "Warehouse Operations" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_menu_warehouse_operations +msgid "Warehouse Operations Menu" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.merp_allow_applying_all_qty_of_product +msgid "Warehouse Operations: Allow applying all qty of product" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_wh_manager +msgid "Warehouse manager" +msgstr "" + +#. module: ventor_base +#: model:res.groups,name:ventor_base.ventor_role_wh_worker +msgid "Warehouse worker" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_picking.py:0 +#: code:addons/ventor_base/models/stock_picking.py:0 +#, python-format +msgid "Warning" +msgstr "" + +#. module: ventor_base +#: model_terms:ir.ui.view,arch_db:ventor_base.res_user_form +msgid "" +"Warning! If the user is Inventory / Administrator, \n" +" the Allowed Warehouses configuration is ignored and \n" +" the user will still be able to see all warehouses" +msgstr "" + +#. module: ventor_base +#: code:addons/ventor_base/models/stock_quant.py:0 +#, python-format +msgid "You need to supply a Lot/Serial number for product: %s" +msgstr "" diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.1.0/post-update_ventor_settings.py b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.1.0/post-update_ventor_settings.py new file mode 100644 index 0000000..05e1910 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.1.0/post-update_ventor_settings.py @@ -0,0 +1,13 @@ +from odoo import SUPERUSER_ID, _, api + + +def migrate(cr, version): + + env = api.Environment(cr, SUPERUSER_ID, {}) + + lot_for_location_setting = env.ref("ventor_base.lot_for_location_int_transfers") + lot_for_location_setting.write( + { + "description": "If it is active, you can select only lots from source location" + } + ) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.2.0/post-update_user_groups.py b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.2.0/post-update_user_groups.py new file mode 100644 index 0000000..afc5659 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.2.0/post-update_user_groups.py @@ -0,0 +1,16 @@ +from odoo import SUPERUSER_ID, _, api + + +def migrate(cr, version): + + env = api.Environment(cr, SUPERUSER_ID, {}) + + ventor_roles_warehouse_worker = env.ref('ventor_base.ventor_role_wh_worker') + ventor_roles_warehouse_worker.write( + { + 'implied_ids': [ + (4, env.ref('ventor_base.merp_order_recheck_menu').id), + (4, env.ref('ventor_base.merp_rfid_menu').id), + ] + } + ) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_user_groups.py b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_user_groups.py new file mode 100644 index 0000000..98bd8bb --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_user_groups.py @@ -0,0 +1,15 @@ +from odoo import SUPERUSER_ID, _, api + + +def migrate(cr, version): + + env = api.Environment(cr, SUPERUSER_ID, {}) + + ventor_roles_warehouse_worker = env.ref('ventor_base.ventor_role_wh_worker') + ventor_roles_warehouse_worker.write( + { + 'implied_ids': [ + (4, env.ref('ventor_base.merp_wave_picking_menu').id), + ] + } + ) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_ventor_settings.py b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_ventor_settings.py new file mode 100644 index 0000000..b5ccd84 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/migrations/16.0.1.3.0/post-update_ventor_settings.py @@ -0,0 +1,34 @@ +from odoo import SUPERUSER_ID, _, api + + +def migrate(cr, version): + + env = api.Environment(cr, SUPERUSER_ID, {}) + + allow_validate_less = env.ref("ventor_base.allow_validate_less") + allow_validate_less.write( + { + "name": "Validate uncompleted orders", + "description": "User will be able to validate the order even if not all items were found" + } + ) + + value = { + "name": "Confirm destination package", + "description": "User has to scan a barcode of destination package. " + "The dot next to the field gets yellow color means user has to confirm it" + } + + scan_destination_package_batch_picking = env.ref( + "ventor_base.scan_destination_package_batch_picking", + False, + ) + scan_destination_package_cluster_picking = env.ref( + "ventor_base.scan_destination_package_cluster_picking", + False, + ) + + if scan_destination_package_batch_picking: + scan_destination_package_batch_picking.write(value) + if scan_destination_package_cluster_picking: + scan_destination_package_cluster_picking.write(value) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/__init__.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/__init__.py new file mode 100644 index 0000000..83ea6cb --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/__init__.py @@ -0,0 +1,12 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import stock_location +from . import stock_picking +from . import stock_quant +from . import res_company +from . import res_config +from . import res_users +from . import stock_warehouse +from . import ventor_option_setting +from . import pallet_transfer diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/pallet_transfer.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/pallet_transfer.py new file mode 100644 index 0000000..f28cd91 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/pallet_transfer.py @@ -0,0 +1,37 @@ +# Copyright 2022 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +# Odoo: +from odoo import _, api, fields, models + + +class PalletTransfer(models.Model): + _name = "pallet.transfer" + _description = "All Pallet Transfers" + + name = fields.Char( + string="Transfer Name", + required=True, + default="New", + ) + pallet_name = fields.Char(string="Pallet Name") + pallet_id = fields.Many2one("stock.location", string="Pallets") + source_location_id = fields.Many2one("stock.location", string="Source Location") + destination_location_id = fields.Many2one("stock.location", string="Destination Location") + + def update_value(self): + self.write( + { + "name": self.env["ir.sequence"].next_by_code("pallet.transfer"), + "pallet_name": self.pallet_id.name, + "source_location_id": self.pallet_id.location_id, + } + ) + self.pallet_id.location_id = self.destination_location_id + + @api.model_create_multi + def create(self, vals_list): + res = super().create(vals_list) + if res: + res.update_value() + return res diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/res_company.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_company.py new file mode 100644 index 0000000..fba5b02 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_company.py @@ -0,0 +1,58 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import _, models, fields +from odoo.exceptions import UserError + +import io +import base64 +from PIL import Image + + +LOGOTYPE_W = 500 +LOGOTYPE_H = 500 + + +class Company(models.Model): + _inherit = 'res.company' + + barcode_on_picking_document = fields.Boolean( + string='Show Sales Order Barcode on Picking document', + help='Showing a barcode of the related sales order on all printed picking documents', + ) + + force_lot_validation_on_inventory_adjustment = fields.Boolean( + string='Force Lot Validation on Inventory Adjustment', + ) + + logotype_file = fields.Binary('Ventor Application Logo File', default=False) + + def _validate_logotype(self, vals): + if not vals.get('logotype_file'): + return False + + dat = base64.decodebytes(vals.get('logotype_file')) + + image = Image.open(io.BytesIO(dat)) + if image.format.lower() != 'png': + raise UserError( + _( + 'Apparently, the logotype is not a .png file' + ' or the file was incorrectly converted to .png format' + ) + ) + + if int(image.width) < LOGOTYPE_W or int(image.height) < LOGOTYPE_H: + raise UserError( + _( + 'The logotype can\'t be less than {}x{} px.'.format(LOGOTYPE_W, LOGOTYPE_H) + ) + ) + + return True + + def write(self, vals): + if 'logotype_file' in vals: + self._validate_logotype(vals) + res = super(Company, self).write(vals) + return res diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/res_config.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_config.py new file mode 100644 index 0000000..7a35a83 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_config.py @@ -0,0 +1,182 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields, api +import logging + +_logger = logging.getLogger(__name__) + + +class VentorConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + logotype_file = fields.Binary( + string='Ventor Application Logo File', + related='company_id.logotype_file', + readonly=False + ) + + module_outgoing_routing = fields.Boolean( + string='Outgoing Routing' + ) + + add_barcode_on_view = fields.Boolean( + string='Show the Location barcode field on the form', + ) + + base_version = fields.Char( + string='Base Module Version', + compute='_compute_base_version', + store=False, + ) + + barcode_on_picking_document = fields.Boolean( + string='Show Sales Order Barcode on Picking document', + readonly=False, + related='company_id.barcode_on_picking_document', + ) + + force_lot_validation_on_inventory_adjustment = fields.Boolean( + string='Force Lot Validation on Inventory Adjustment', + readonly=False, + related='company_id.force_lot_validation_on_inventory_adjustment', + ) + + custom_package_name = fields.Char( + string='Custom package name', + config_parameter='ventor_base.custom_package_name', + ) + + @api.depends('company_id') + def _compute_base_version(self): + self.env.cr.execute( + "SELECT latest_version FROM ir_module_module WHERE name='ventor_base'" + ) + result = self.env.cr.fetchone() + full_version = result and result[0] + split_value = full_version and full_version.split('.') + self.base_version = split_value and '.'.join(split_value[-3:]) + + @api.model + def get_values(self): + res = super(VentorConfigSettings, self).get_values() + + view_with_barcode = self.env.ref( + 'ventor_base.view_location_form_inherit_additional_barcode', + raise_if_not_found=False + ) + if view_with_barcode: + res['add_barcode_on_view'] = view_with_barcode.active + + return res + + def _set_apply_default_lots(self, previous_group): + operation_type_ids = self.env['stock.picking.type'].search([]) + group_stock_production_lot = previous_group.get('group_stock_production_lot') + + if ( + group_stock_production_lot != self.group_stock_production_lot + and not self.group_stock_production_lot + ): + operation_type_ids.apply_default_lots = False + ventor_apply_default_lots = self.env['ventor.option.setting'].search( + [ + ('technical_name', '=', 'apply_default_lots'), + ] + ) + ventor_apply_default_lots.with_context( + disable_apply_default_lots=True + ).set_apply_default_lots_fields(self.group_stock_production_lot) + + def _set_packages_fields(self, previous_group): + operation_type_ids = self.env['stock.picking.type'].search([]) + group_stock_tracking_lot = previous_group.get('group_stock_tracking_lot') + + if group_stock_tracking_lot != self.group_stock_tracking_lot: + operation_type_ids.manage_packages = self.group_stock_tracking_lot + operation_type_ids.show_put_in_pack_button = self.group_stock_tracking_lot + if not self.group_stock_tracking_lot: + operation_type_ids.show_put_in_pack_button = self.group_stock_tracking_lot + operation_type_ids.scan_destination_package = self.group_stock_tracking_lot + operation_type_ids.confirm_source_package = self.group_stock_tracking_lot + operation_type_ids.allow_creating_new_packages = self.group_stock_tracking_lot + + ventor_packages_settings = self.env['ventor.option.setting'].search( + [ + ( + 'technical_name', + 'in', + ( + 'confirm_source_package', + 'scan_destination_package', + 'manage_packages', + 'allow_creating_new_packages', + 'pack_all_items', + 'use_reusable_packages', + ), + ), + ] + ) + ventor_packages_settings.with_context( + disable_package_fields=True + ).set_related_package_fields(self.group_stock_tracking_lot) + if self.group_stock_tracking_lot: + ventor_packages_settings = self.env['ventor.option.setting'].search( + [ + ('technical_name', '=', 'manage_packages'), + ] + ) + ventor_packages_settings.value = self.env.ref('ventor_base.bool_true') + + def _set_manage_product_owner(self, previous_group): + operation_type_ids = self.env['stock.picking.type'].search([]) + group_stock_tracking_owner = previous_group.get('group_stock_tracking_owner') + + if group_stock_tracking_owner != self.group_stock_tracking_owner: + operation_type_ids.manage_product_owner = self.group_stock_tracking_owner + + ventor_owner_settings = self.env['ventor.option.setting'].search( + [ + ('technical_name', '=', 'manage_product_owner'), + ] + ) + ventor_owner_settings.value = self.env.ref('ventor_base.bool_true') if self.group_stock_tracking_owner else self.env.ref('ventor_base.bool_false') + + def _update_display_wave_picking_menu(self, previous_group): + group_stock_picking_wave = previous_group.get('group_stock_picking_wave') + + if group_stock_picking_wave != self.group_stock_picking_wave: + merp_wave_picking_menu = self.env.ref('ventor_base.merp_wave_picking_menu') + users = self.env['res.users'].with_context(active_test=False).search([ + ('share', '=', False) + ]) + merp_wave_picking_menu.write( + { + 'users': [(6, 0, users.ids)] + if self.group_stock_picking_wave + else [(5, 0, 0)], + } + ) + + def set_values(self): + previous_group = self.default_get( + [ + 'group_stock_tracking_lot', + 'group_stock_tracking_owner', + 'group_stock_production_lot', + 'group_stock_picking_wave', + ] + ) + res = super(VentorConfigSettings, self).set_values() + + view_with_barcode = self.env.ref('ventor_base.view_location_form_inherit_additional_barcode') + view_with_barcode.active = self.add_barcode_on_view + + # Updating the values of dependent fields + self.sudo()._set_apply_default_lots(previous_group) + self.sudo()._set_packages_fields(previous_group) + self.sudo()._set_manage_product_owner(previous_group) + + # Updating the menu display in Ventor for users + self.sudo()._update_display_wave_picking_menu(previous_group) + return res diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/res_users.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_users.py new file mode 100644 index 0000000..302dd45 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/res_users.py @@ -0,0 +1,131 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +import json + +from odoo import api, models, fields + + +class ResUsers(models.Model): + _inherit = 'res.users' + + allowed_warehouse_ids = fields.Many2many( + comodel_name='stock.warehouse', + string='Allowed Warehouses', + help='List of all warehouses user has access to', + ) + + custom_package_name = fields.Char( + string='Custom Build Name', + compute="_compute_custom_package_name", + compute_sudo=True, + ) + + ventor_base_version = fields.Char( + compute="_compute_ventor_base_version", + compute_sudo=True, + readonly=True, + ) + + ventor_global_settings = fields.Text( + string='Global Settings', + readonly=True, + compute='_compute_global_settings' + ) + + ventor_user_settings = fields.Text( + string='User Settings' + ) + + @property + def SELF_READABLE_FIELDS(self): + readable_fields = [ + 'ventor_global_settings', + 'ventor_user_settings', + 'custom_package_name', + 'ventor_base_version', + ] + return super().SELF_READABLE_FIELDS + readable_fields + + @property + def SELF_WRITEABLE_FIELDS(self): + writable_fields = ['ventor_user_settings'] + return super().SELF_WRITEABLE_FIELDS + writable_fields + + def _compute_custom_package_name(self): + custom_package_name = ( + self.env["ir.config_parameter"] + .get_param("ventor_base.custom_package_name", "") + ) + self.custom_package_name = custom_package_name + + def _compute_ventor_base_version(self): + ventor_base_version = ( + self.env["ir.module.module"] + .search([("name", "=", "ventor_base"), ("state", "=", "installed")]) + .latest_version + ) + for user in self: + if ventor_base_version: + user.ventor_base_version = ventor_base_version + else: + user.ventor_base_version = "" + + def _compute_global_settings(self): + settings = [] + + for stock_picking_type in self.env['stock.picking.type'].search([]): + stock_picking_type_settings = stock_picking_type.get_warehouse_operation_settings() + if stock_picking_type.code != 'outgoing': + stock_picking_type_settings['settings'].pop('check_shipping_information') + if stock_picking_type.code != 'incoming': + stock_picking_type_settings['settings'].pop('hide_qty_to_receive') + settings.append(stock_picking_type_settings) + + ventor_option_settings = self._get_ventor_option_settings() + + obj = {'operation_types': settings} + obj.update(ventor_option_settings) + + self.ventor_global_settings = json.dumps( + obj=obj, + indent=' ', + sort_keys=True + ) + + def _get_ventor_option_settings(self): + ventor_option_settings = self.env['ventor.option.setting'].sudo().get_general_settings() + if self.env.ref('ventor_base.merp_wave_picking_menu') not in self.groups_id: + ventor_option_settings.pop('wave_picking') + return ventor_option_settings + + def _update_group_picking_wave_menu(self, vals): + vals = self._remove_reified_groups(vals) + if 'groups_id' in vals: + group_stock_picking_wave = self.env.ref('stock.group_stock_picking_wave') + merp_wave_picking_menu = self.env.ref('ventor_base.merp_wave_picking_menu') + for user in self: + if group_stock_picking_wave not in user.groups_id and merp_wave_picking_menu in user.groups_id: + merp_wave_picking_menu.write({'users': [(3, user.id)]}) + + @api.model_create_multi + def create(self, vals_list): + result = super().create(vals_list) + if not result.allowed_warehouse_ids: + result.write( + { + 'allowed_warehouse_ids': [ + ( + 6, 0, self.env["stock.warehouse"].sudo().with_context(active_test=False).search([]).ids + ) + ] + } + ) + return result + + def write(self, vals): + result = super().write(vals) + if result and 'allowed_warehouse_ids' in vals: + self.env['ir.rule'].clear_caches() + self._update_group_picking_wave_menu(vals) + return result diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_location.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_location.py new file mode 100644 index 0000000..d8bbac6 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_location.py @@ -0,0 +1,14 @@ +# Copyright 2021 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + + +# Odoo: +from odoo import api, fields, models + + +class StockLocation(models.Model): + _inherit = "stock.location" + + # store attribute for Group By 'Warehouse', locations tree view + warehouse_id = fields.Many2one(store=True) + is_pallet = fields.Boolean(string="Is Pallet") diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_picking.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_picking.py new file mode 100644 index 0000000..e3aa12f --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_picking.py @@ -0,0 +1,299 @@ +from odoo import fields, models, api, _ + + +class StockPickingType(models.Model): + _inherit = "stock.picking.type" + + allow_creating_new_packages = fields.Boolean( + string="Allow creating new packages", + help="User can create new packages by scanning a new barcode or create it manually" + ) + + apply_default_lots = fields.Boolean( + string="Apply default lots and serials", + help="If it's on, you don't need to scan lot number to confirm it. " + "On receipts the app will create default Odoo lots and apply them to the product. " + "On delivery zone you don't need to confirm lots and " + "they will be taken Odoo by default" + ) + + apply_quantity_automatically = fields.Boolean( + string="Apply quantity automatically", + help="Automatically validate the line after scanning a destination location. " + "Warning: you have to insert QTY first before destination location" + ) + + autocomplete_the_item_quantity_field = fields.Boolean( + string="Autocomplete item quantity", + help="Automatically insert expected quantity. No need to enter the quantity " + "of goods using the keyboard or using scanning" + ) + + behavior_on_backorder_creation = fields.Selection( + [ + ("always_create_backorder", "Always Create Backorder"), + ("never_create_backorder", "Never Create Backorder"), + ("ask_me_every_time", "Ask Me Every Time"), + ], + string="Behavior On Backorder Creation", + default="ask_me_every_time", + required=True, + help="Choose how to process backorders. You can always create backorders, " + "always ignore backorders or choose it all the time (default)" + ) + + behavior_on_split_operation = fields.Selection( + [ + ("always_split_line", "Always Split the Line"), + ("always_move_less_items", "Always Move Less Items"), + ("ask_me_every_time", "Ask Me Every Time"), + ], + string="Behavior On Split Operation", + compute="_compute_behavior_on_split_operation", + readonly=False, + store=True, + help="Choose how to process less product qty than initial. You can always split " + "the line, always move less items or choose it all the time(default)" + ) + + change_destination_location = fields.Boolean( + string="Change destination location", + help="If this setting is active a user can change destination location " + "while receiving to be placed at any available location", + ) + + change_source_location = fields.Boolean( + string="Change source location", + help="User can change default source location to pick item from another location. " + "Works only if 'Confirm source location' setting is active", + ) + + check_shipping_information = fields.Boolean( + string="Check shipping information", + help="If the setting is active the user can edit shipping information " + "before validate OUT transfer", + ) + + confirm_destination_location = fields.Boolean( + string="Confirm destination location", + help="The dot next to the field gets yellow color means user has to confirm it. " + "User has to scan a barcode of destination location" + ) + + confirm_product = fields.Boolean( + string="Confirm product", + help="The dot next to the field gets yellow color means user has to confirm it. " + "User has to scan a barcode of product." + ) + + confirm_source_location = fields.Boolean( + string="Confirm source location", + help="The dot next to the field gets yellow color means user has to confirm it. " + "User has to scan a barcode of source location" + ) + + confirm_source_package = fields.Boolean( + string="Confirm source package", + help="User has to scan a barcode of source package. " + "The dot next to the field gets yellow color means user has to confirm it" + ) + + hide_qty_to_receive = fields.Boolean( + string="Hide QTYs to receive", + help="Setting’s description: User will not see how many QTYs they need to receive." + ) + + is_consignment_enabled = fields.Boolean( + compute="_compute_is_consignment_enabled" + ) + + is_package_tracking_enabled = fields.Boolean( + compute="_compute_is_package_tracking_enabled" + ) + + is_stock_production_lot_enabled = fields.Boolean( + compute="_compute_is_stock_production_lot_enabled" + ) + + manage_packages = fields.Boolean( + string="Show packages fields", + default=lambda self: self.env.ref("stock.group_tracking_lot") + in self.env.ref("base.group_user").implied_ids, + help="Scan source (destination) packages right after scanning source (destination) " + "location. Use it if you move from one package to another or pick items from " + "packages or pallets. Works only if package management settings is active on Odoo " + "side.\n\n If you want to use Show packages fields, you must turn on setting " + "'Packages' in inventory settings", + ) + + manage_product_owner = fields.Boolean( + string="Show Product Owner field", + default=lambda self: self.env.ref("stock.group_tracking_owner") + in self.env.ref("base.group_user").implied_ids, + help="Allow scan product owner. You can specify product owner while moving items. " + "Working only with 'Consignment' setting on Odoo side" + ) + + scan_destination_location_once = fields.Boolean( + string="Scan destination location once", + help="Scan the destination location only once with the last item. " + "The destination location will be applied to all lines." + ) + + scan_destination_package = fields.Boolean( + string="Confirm destination package", + help="User has to scan a barcode of destination package. The dot next to the field " + "gets yellow color means user has to confirm it" + ) + + show_next_product = fields.Boolean( + string="Show next product", + help="Product field will show the next product to be picked. " + "Use the setting during picking and delivery. " + "It is recommended to disable the setting for the reception area", + ) + + show_print_attachment_button = fields.Boolean( + string="Show Print attachments button", + default=True, + help="Showing the Print attachments button in the toolbar instead of " + "keeping it in the hidden menu" + ) + + show_put_in_pack_button = fields.Boolean( + string="Show Put in pack button", + default=lambda self: self.env.ref("stock.group_tracking_lot") + in self.env.ref("base.group_user").implied_ids, + help="Showing the Put in pack button in the toolbar instead of " + "keeping it in the hidden menu" + ) + + transfer_more_items = fields.Boolean( + string="Move more than planned", + help="Allows moving more items than expected (for example kg of meat, etc)" + ) + + @api.depends('code') + def _compute_behavior_on_split_operation(self): + for operation_type in self: + if operation_type.code == 'incoming': + operation_type.behavior_on_split_operation = 'always_split_line' + else: + operation_type.behavior_on_split_operation = 'ask_me_every_time' + + def _compute_is_consignment_enabled(self): + internal_user_groups = self.env.ref('base.group_user').implied_ids + group_tracking_owner = self.env.ref("stock.group_tracking_owner") + for item in self: + item.is_consignment_enabled = group_tracking_owner in internal_user_groups + + def _compute_is_package_tracking_enabled(self): + internal_user_groups = self.env.ref('base.group_user').implied_ids + group_tracking_lot = self.env.ref("stock.group_tracking_lot") + for item in self: + item.is_package_tracking_enabled = group_tracking_lot in internal_user_groups + + def _compute_is_stock_production_lot_enabled(self): + internal_user_groups = self.env.ref('base.group_user').implied_ids + group_production_lot = self.env.ref("stock.group_production_lot") + for item in self: + item.is_stock_production_lot_enabled = group_production_lot in internal_user_groups + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if 'code' in vals: + vals['show_next_product'] = vals['code'] != "incoming" + vals['change_destination_location'] = True + + return super(StockPickingType, self).create(vals_list) + + @api.onchange('confirm_source_location') + def _onchange_confirm_source_location(self): + if not self.confirm_source_location: + self.change_source_location = False + + @api.onchange('confirm_destination_location') + def _onchange_confirm_destination_location(self): + if not self.confirm_destination_location: + self.apply_quantity_automatically = False + + @api.onchange('change_source_location') + def _onchange_change_source_location(self): + if self.change_source_location and not self.confirm_source_location: + return { + 'warning': { + 'title': _("Warning"), + 'message': _("'Change source location' is available only " + "if 'Confirm source location' is enabled") + } + } + + @api.onchange('apply_quantity_automatically') + def _onchange_apply_quantity_automatically(self): + if self.apply_quantity_automatically and not self.confirm_destination_location: + return { + 'warning': { + 'title': _("Warning"), + 'message': _("'Apply quantity automatically' is available only " + "if 'Confirm destination location' is enabled") + } + } + + def write(self, vals): + res = super(StockPickingType, self).write(vals) + + if 'change_source_location' in vals or 'confirm_source_location' in vals: + for stock_picking_type in self: + if stock_picking_type.change_source_location: + if not stock_picking_type.confirm_source_location: + stock_picking_type.change_source_location = False + + if 'apply_quantity_automatically' in vals or 'confirm_destination_location' in vals: + for stock_picking_type in self: + if stock_picking_type.apply_quantity_automatically: + if not stock_picking_type.confirm_destination_location: + stock_picking_type.apply_quantity_automatically = False + + if 'manage_packages' in vals: + for stock_picking_type in self: + if not stock_picking_type.manage_packages: + if stock_picking_type.scan_destination_package: + stock_picking_type.scan_destination_package = False + if stock_picking_type.confirm_source_package: + stock_picking_type.confirm_source_package = False + if stock_picking_type.allow_creating_new_packages: + stock_picking_type.allow_creating_new_packages = False + return res + + def get_warehouse_operation_settings(self): + return { + "id": self.id, + "name": self.name, + "wh_code": self.warehouse_id.code, + "wh_name": self.warehouse_id.name, + "settings": { + "allow_creating_new_packages": self.allow_creating_new_packages, + "confirm_source_location": self.confirm_source_location, + "change_source_location": self.change_source_location, + "show_next_product": self.show_next_product, + "confirm_product": self.confirm_product, + "apply_default_lots": self.apply_default_lots, + "transfer_more_items": self.transfer_more_items, + "confirm_destination_location": self.confirm_destination_location, + "apply_quantity_automatically": self.apply_quantity_automatically, + "change_destination_location": self.change_destination_location, + "scan_destination_location_once": self.scan_destination_location_once, + "autocomplete_the_item_quantity_field": self.autocomplete_the_item_quantity_field, + "show_print_attachment_button": self.show_print_attachment_button, + "show_put_in_pack_button": self.show_put_in_pack_button, + "manage_packages": self.manage_packages, + "manage_product_owner": self.manage_product_owner, + "behavior_on_backorder_creation": self.behavior_on_backorder_creation, + "behavior_on_split_operation": self.behavior_on_split_operation, + "scan_destination_package": self.scan_destination_package, + "confirm_source_package": self.confirm_source_package, + "check_shipping_information": self.check_shipping_information, + "hide_qty_to_receive": self.hide_qty_to_receive, + } + } diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_quant.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_quant.py new file mode 100644 index 0000000..f46183d --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_quant.py @@ -0,0 +1,45 @@ +# Copyright 2021 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import models, fields, api, _ +from odoo.exceptions import ValidationError + + +class StockQuant(models.Model): + _inherit = 'stock.quant' + + @api.constrains("lot_id", "inventory_quantity") + def _check_product_lot(self): + """ check product lot/serial except for stock_fix_lot """ + + for quant in self: + if ( + not quant.inventory_quantity + or not quant.company_id.force_lot_validation_on_inventory_adjustment + or ( + quant.env.context.get("skip_product_lot_check") and not quant.inventory_quantity) + ): + return + if quant.tracking in ("lot", "serial") and not quant.lot_id: + raise ValidationError( + _( + "You need to supply a Lot/Serial number for product: %s", + quant.product_id.display_name, + ) + ) + + @api.model + def user_has_groups(self, groups): + # we need to override method as we need different access group + # to be allowed to validate inventory + if ( + self.env.context.get("validate_inventory") + and groups == "stock.group_stock_manager" + ): + groups = "ventor_base.merp_user_validate_inventory_adjustment" + res = super(StockQuant, self).user_has_groups(groups) + return res + + def _apply_inventory(self): + res = super(StockQuant, self.with_context(validate_inventory=True))._apply_inventory() + return res diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_warehouse.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_warehouse.py new file mode 100644 index 0000000..dedf421 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/stock_warehouse.py @@ -0,0 +1,45 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import api, models, fields + + +class StockWarehouse(models.Model): + _inherit = 'stock.warehouse' + + is_internal = fields.Boolean( + string='Is Internal Warehouse', + ) + + @api.model_create_multi + def create(self, vals_list): + res = super(StockWarehouse, self).create(vals_list) + if res: + res.update_users_calculated_warehouse() + return res + + def update_users_calculated_warehouse(self): + for warehouse in self: + users = self.env['res.users'].with_context(active_test=False).search([ + ('share', '=', False)]) + wh_ids = self.env['stock.warehouse'].with_context(active_test=False).search([ + ('id', '!=', warehouse.id)]).ids + wh_ids.sort() + modified_user_ids = [] + for user in users.with_context(active_test=False): + # Because of specifics on how Odoo working with companies on first start, we have to filter by company + user_wh_ids = user.allowed_warehouse_ids.filtered( + lambda wh: wh.company_id.id == warehouse.env.company.id + ).ids + user_wh_ids.sort() + if wh_ids == user_wh_ids: + user.allowed_warehouse_ids = [(4, warehouse.id, 0)] + modified_user_ids.append(user.id) + + # Because access rights are using this field, we need to invalidate cache + if modified_user_ids: + self.env['res.users'].browse(modified_user_ids).invalidate_recordset( + [ + 'allowed_warehouse_ids', + ] + ) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/models/ventor_option_setting.py b/odoo-bringout-ventor-ventor_base/ventor_base/models/ventor_option_setting.py new file mode 100644 index 0000000..bd5f45b --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/models/ventor_option_setting.py @@ -0,0 +1,268 @@ +# Copyright 2022 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo import _, api, models, fields + + +class VentorOptionSetting(models.Model): + _name = 'ventor.option.setting' + _description = 'Ventor Option Setting' + + name = fields.Char(required=True, index=True) + action_type = fields.Selection( + [ + ('warehouse_opration', 'Warehouse Opration'), + ('package_management', 'Package Management'), + ('batch_picking', 'Batch Picking'), + ('wave_picking', 'Wave Picking'), + ('cluster_picking', 'Cluster Picking'), + ('internal_transfers', 'Internal Transfers'), + ('putaway', 'Putaway'), + ('instant_inventory', 'Instant Inventory'), + ('inventory_adjustments', 'Inventory Adjustments'), + ('quick_info', 'Quick Info'), + ('scrap_management', 'Scrap Management'), + ('create_so', 'Create SO'), + ('create_po', 'Create PO'), + ], required=True + ) + description = fields.Text() + technical_name = fields.Char(required=True) + value = fields.Many2one( + 'ventor.setting.value', + string='Value', + required=True, + domain="[('id', 'in', settings_dependency)]", + ) + value_type = fields.Selection( + [ + ('bool', 'Boolean'), + ('select', 'Selection'), + ] + ) + settings_dependency = fields.Many2many( + comodel_name='ventor.setting.value' + ) + + @api.onchange('value') + def _onchange_value(self): + if self.technical_name in ('confirm_source_location', 'change_source_location'): + return self._set_change_source_location() + elif self.technical_name in ('add_boxes_before_cluster', 'multiple_boxes_for_one_transfer'): + return self._set_add_boxes_before_cluster() + elif self.technical_name in ( + 'manage_packages', + 'confirm_source_package', + 'scan_destination_package', + 'allow_creating_new_packages', + 'pack_all_items', + 'allow_validate_less', + ): + return self.set_related_package_fields(self._get_group_settings_value('stock.group_tracking_lot')) + elif self.technical_name in ('manage_product_owner'): + self.set_manage_product_owner_fields(self._get_group_settings_value('stock.group_tracking_owner')) + elif self.technical_name in ('apply_default_lots'): + self.set_apply_default_lots_fields(self._get_group_settings_value('stock.group_production_lot')) + elif self.technical_name in ('move_multiple_products', 'hold_destination_location'): + return self.set_hold_destination_location_fields() + elif self.technical_name in ('use_reusable_packages'): + return self.set_reusable_packages_related_fields(self._get_group_settings_value('stock.group_tracking_lot')) + elif self.technical_name in ('confirm_destination_location'): + self._set_confirm_destination_location_cluster_picking_fields() + + def _get_group_settings_value(self, key): + internal_user_groups = self.env.ref('base.group_user').implied_ids + group = self.env.ref(key) + return group in internal_user_groups + + def _get_warning(self, message): + return {'warning': { + 'title': _('Another Settings were changed automatically!'), + 'message': message, + }} + + def get_setting_field(self, technical_name): + if not isinstance(technical_name, list): + technical_name = [technical_name] + return self.env['ventor.option.setting'].search( + [ + ('action_type', '=', self.action_type), + ('technical_name', 'in', technical_name), + ] + ) + + def get_general_settings(self): + action_types = [ + 'package_management', + 'batch_picking', + 'wave_picking', + 'cluster_picking', + 'internal_transfers', + 'putaway', + 'instant_inventory', + 'inventory_adjustments', + 'quick_info', + 'scrap_management', + 'create_so', + 'create_po', + ] + ventor_option_settings = self.env['ventor.option.setting'].search([]) + + settings = {} + for action_type in action_types: + settings[action_type] = { + set.technical_name: self.get_normalized_value(set.value.setting_value) + for set in ventor_option_settings.filtered(lambda r: r.action_type == action_type) + } + return settings + + def set_allow_validate_less(self): + if self.technical_name == 'allow_validate_less': + pack_all_items = self.get_setting_field('pack_all_items') + if pack_all_items.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + elif self.technical_name == 'pack_all_items': + allow_validate_less = self.get_setting_field('allow_validate_less') + if allow_validate_less.value == self.env.ref('ventor_base.bool_true'): + allow_validate_less.value = self.env.ref('ventor_base.bool_false') + return self._get_warning(_( + 'Because you changed "Force Pack" to True, ' + 'automatically the following settings were also changed: ' + '\n- "Validate uncompleted orders" was changed to False' + )) + + def set_apply_default_lots_fields(self, group_stock_production_lot): + if self.env.context.get('disable_apply_default_lots'): + self.value = self.env.ref('ventor_base.bool_false') + elif not group_stock_production_lot and self.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + + def _set_add_boxes_before_cluster(self): + if self.technical_name == 'add_boxes_before_cluster' and self.value == self.env.ref('ventor_base.bool_true'): + multiple_boxes_for_one_transfer = self.get_setting_field('multiple_boxes_for_one_transfer') + use_reusable_packages = self.get_setting_field('use_reusable_packages') + if multiple_boxes_for_one_transfer.value == self.env.ref('ventor_base.bool_true'): + multiple_boxes_for_one_transfer.value = self.env.ref('ventor_base.bool_false') + return self._get_warning(_( + 'Because you changed "Add boxes before cluster" to True, ' + 'automatically the following settings were also changed: ' + '\n- "Multiple boxes for one transfer" was changed to False' + )) + if use_reusable_packages.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + elif self.technical_name == 'multiple_boxes_for_one_transfer' and self.value == self.env.ref('ventor_base.bool_true'): + add_boxes_before_cluster = self.get_setting_field('add_boxes_before_cluster') + if add_boxes_before_cluster.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + + def _set_change_source_location(self): + if self.technical_name == 'confirm_source_location' and self.value == self.env.ref('ventor_base.bool_false'): + change_source_location = self.get_setting_field('change_source_location') + change_source_location.value = self.env.ref('ventor_base.bool_false') + return self._get_warning(_( + 'Because you changed "​Confirm source location" to False, ' + 'automatically the following settings were also changed: ' + '\n- "Change source location" was changed to False' + )) + elif self.technical_name == 'change_source_location' and self.value == self.env.ref('ventor_base.bool_true'): + confirm_source_location = self.get_setting_field('confirm_source_location') + if confirm_source_location.value == self.env.ref('ventor_base.bool_false'): + self.value = self.env.ref('ventor_base.bool_false') + + def _set_confirm_destination_location_cluster_picking_fields(self): + if self.value == self.env.ref('ventor_base.bool_true') and self.action_type == 'cluster_picking': + use_reusable_packages = self.get_setting_field('use_reusable_packages') + if use_reusable_packages.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + + def set_hold_destination_location_fields(self): + if self.technical_name == 'move_multiple_products' and self.value == self.env.ref('ventor_base.bool_true'): + hold_destination_location = self.get_setting_field('hold_destination_location') + if hold_destination_location.value == self.env.ref('ventor_base.bool_true'): + hold_destination_location.value = self.env.ref('ventor_base.bool_false') + return self._get_warning(_( + 'Because you changed "Move multiple items" to True, ' + 'automatically the following settings were also changed: ' + '\n- "Hold destination location" was changed to False' + )) + elif self.technical_name == 'hold_destination_location' and self.value == self.env.ref('ventor_base.bool_true'): + move_multiple_products = self.get_setting_field('move_multiple_products') + if move_multiple_products.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + + def set_manage_product_owner_fields(self, group_stock_tracking_owner): + if not group_stock_tracking_owner and self.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_false') + + def set_related_package_fields(self, group_stock_tracking_lot): + if not group_stock_tracking_lot: + self.value = self.env.ref('ventor_base.bool_false') + elif group_stock_tracking_lot: + manage_packages = self.get_setting_field('manage_packages') + if self.value.setting_value == 'False' and self.technical_name == 'manage_packages': + relate_manage_packages_fields = self.get_setting_field( + [ + 'confirm_source_package', + 'scan_destination_package', + ] + ) + relate_manage_packages_fields.value = self.env.ref('ventor_base.bool_false') + if self.action_type in ('batch_picking', 'cluster_picking'): + return self._get_warning(_( + 'Because you changed "Show packages fields" to False, ' + 'automatically the following settings were also changed: ' + '\n- "Confirm source package" was changed to False' + '\n- "Confirm destination package" was changed to False' + )) + if self.technical_name != 'manage_packages' and manage_packages.value == self.env.ref('ventor_base.bool_false'): + self.value = self.env.ref('ventor_base.bool_false') + if self.value.setting_value == 'True' and self.technical_name in ('pack_all_items', 'allow_validate_less'): + return self.set_allow_validate_less() + if self.technical_name == 'scan_destination_package' and self.value == self.env.ref('ventor_base.bool_false'): + use_reusable_packages = self.get_setting_field('use_reusable_packages') + if use_reusable_packages.value == self.env.ref('ventor_base.bool_true'): + self.value = self.env.ref('ventor_base.bool_true') + + def set_reusable_packages_related_fields(self, group_stock_tracking_lot): + if not group_stock_tracking_lot: + self.value = self.env.ref('ventor_base.bool_false') + elif self.value == self.env.ref('ventor_base.bool_true'): + related_settings_for_disabling = self.get_setting_field( + [ + 'confirm_destination_location', + 'add_boxes_before_cluster', + ] + ) + related_settings_for_enabling = self.get_setting_field('scan_destination_package') + if related_settings_for_disabling: + related_settings_for_disabling.value = self.env.ref('ventor_base.bool_false') + if related_settings_for_enabling: + related_settings_for_enabling.value = self.env.ref('ventor_base.bool_true') + return self._get_warning(_( + 'Because you changed "Use reusable packages" to True, ' + 'automatically the following settings were also changed: ' + '\n- "Confirm destination location" was changed to False' + '\n- "Add boxes before cluster" was changed to False' + '\n- "Confirm destination package" was changed to True' + )) + + def get_normalized_value(self, setting_value): + normalized_settings = { + 'True': 'true', + 'False': 'false', + 'Always Create Backorder': 'always_create_backorder', + 'Never Create Backorder': 'never_create_backorder', + 'Always Split the Line': 'always_split_line', + 'Always Move Less Items': 'always_move_less_items', + 'Ask Me Every Time': 'ask_me_every_time', + } + return normalized_settings.get(setting_value) + + +class VentorSettingValue(models.Model): + _name = 'ventor.setting.value' + _description = 'Ventor Setting Value' + _rec_name = 'setting_value' + + setting_type = fields.Char() + setting_value = fields.Char() diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/report/report_stockpicking_operations.xml b/odoo-bringout-ventor-ventor_base/ventor_base/report/report_stockpicking_operations.xml new file mode 100644 index 0000000..95e89a0 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/report/report_stockpicking_operations.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/security/groups.xml b/odoo-bringout-ventor-ventor_base/ventor_base/security/groups.xml new file mode 100644 index 0000000..3e3f141 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/security/groups.xml @@ -0,0 +1,462 @@ + + + + + + + Ventor Menu Management + 0 + + + + + Warehouse Operations Menu + + + + + + Inventory Adjustments Menu + + + + + + Batch Picking Menu + + + + + + Instant Inventory Menu + + + + + + Internal Transfers Menu + + + + + + MO and WO management Menu + + + + + + Create Purchase Order Menu + + + + + + Create Sales Order Menu + + + + + + Quick Info Menu + + + + + + Package Management Menu + + + + + + External Transfers Menu + + + + + + Putaway Menu + + + + + + Scrap Management Menu + + + + + + Cluster Picking Menu + + + + + + RFID Menu + + + + + + Order Recheck Menu + + + + + + Wave Picking Menu + + + Enables the display of the "Wave Picking Menu" in Ventor. + To enable this setting, the "Use wave pickings" group must be enabled + + + + + Ventor Access Rights + 1 + + + + + Quick Info: Update product on hand + + + + + + + Manage Local User Device Settings + Enable to allow to define local Ventor settings + from Ventor application interface. + + + + + + Use Local User Device Settings + If it's checked, the manual settings (defined on device by this user) + will be used instead Global Ventor Settings in Odoo. + If it's unchecked the user will not be able to modify settings on the + device manually. Global Ventor Settings will be used instead. + + + + + + Debug: Technical Features + + + + + + Batch Picking: Close batch picking + + + + + + Inventory Adjustments: Waiting for Validation + + + + + + + Warehouse Operations: Allow applying all qty of product + + + + + + Validate Inventory + + + The group allows Inventory/User to validate inventory + + + + Manage Ventor Configuration app + Enable to see new root menu "Ventor Configuration" + that will allow to define global Ventor settings + from the Odoo interface. + + + + + + Allow Pallet Transfers + + + Allow Pallet Transfer from one location to another one + + + + + + + + + + + + + Ventor Roles + 1 + + + + + + Warehouse worker + + + + + + Warehouse manager + + + + + + Administrator + + + + + + + + + + See locations from allowed warehouses + + + ['|', ('warehouse_id','=',False), ('warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See All Location + + + [(1,'=',1)] + + + + + See Operation Types from allowed warehouses + + + ['|', ('warehouse_id','=',False), ('warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See all Operation Types + + + [(1,'=',1)] + + + + + See Scrap Orders from allowed warehouses + + + ['|', ('location_id.warehouse_id','=',False), ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See All Scrap Orders + + + [(1,'=',1)] + + + + + See Reordering Rules from allowed warehouses + + + ['|', ('location_id.warehouse_id','=',False), ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See All Reordering Rules + + + [(1,'=',1)] + + + + + See Quants from allowed warehouses + + + ['|', ('location_id.warehouse_id','=',False), ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See all Stock Quants + + + [(1,'=',1)] + + + + + See Warehouses from allowed warehouses + + + ['|', ('id','=',False), ('id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See all Warehouses + + + [(1,'=',1)] + + + + + See Stock Pickings from allowed warehouses + + + [ + '&', + '|','|', + ('location_id', '=', False), + ('location_id.warehouse_id', '=', False), + ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + '|','|', + ('location_dest_id', '=', False), + ('location_dest_id.warehouse_id', '=', False), + ('location_dest_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + ] + + + + See all Stock Pickings + + + [(1,'=',1)] + + + + + See Picking Batches from allowed warehouses + + + ['|', ('picking_type_id','=',False), ('picking_type_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids])] + + + + See all Picking Batches + + + [(1,'=',1)] + + + + + stock_picking_batch multi-company + + [('company_id', 'in', company_ids)] + + + + + + See Stock Moves from allowed warehouses + + + [ + '&', + '|', + ('location_id.warehouse_id', '=', False), + ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + '|', + ('location_dest_id.warehouse_id', '=', False), + ('location_dest_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + ] + + + + See all Stock Moves + + + [(1,'=',1)] + + + + + See Stock Move Lines from allowed warehouses + + + [ + '&', + '|', + ('location_id.warehouse_id', '=', False), + ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + '|', + ('location_dest_id.warehouse_id', '=', False), + ('location_dest_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]), + ] + + + + See all Stock Move Lines + + + [(1,'=',1)] + + + + + See Stock Quant Package from allowed warehouses + + + [ + '|', '|', + ('location_id', '=', False), + ('location_id.warehouse_id','=',False), + ('location_id.warehouse_id','in',[wh.id for wh in user.allowed_warehouse_ids]) + ] + + + + See Stock Quant Package + + + [(1,'=',1)] + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/security/ir.model.access.csv b/odoo-bringout-ventor-ventor_base/ventor_base/security/ir.model.access.csv new file mode 100644 index 0000000..49a71f8 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +validate_inventory_user,validate_inventory_user,model_stock_location,ventor_base.merp_user_validate_inventory_adjustment,1,1,0,0 +ventor_settings_admin,ventor_settings_admin,ventor_base.model_ventor_option_setting,ventor_base.merp_manage_ventor_configuration_app,1,1,0,0 +ventor_setting_value,ventor_setting_value,ventor_base.model_ventor_setting_value,ventor_base.merp_manage_ventor_configuration_app,1,0,0,0 +pallet_transfer_stock_user,pallet_transfer_stock_user,model_pallet_transfer,stock.group_stock_user,1,1,1,0 +pallet_transfer_stock_manager,pallet_transfer_stock_manager,model_pallet_transfer,stock.group_stock_manager,1,1,1,1 diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/icon.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/icon.png new file mode 100644 index 0000000..c874e9f Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/icon.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/index.html b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/index.html new file mode 100644 index 0000000..f674c7c --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/index.html @@ -0,0 +1,113 @@ +
+
+
+

Ventor/mERP Base module

+
+
+

+ TO AVOID ANY ISSUES, PLEASE, USE ALWAYS LATEST VERSION FROM OUR GITHUB REPOSITORY - + + https://github.com/ventor-tech/merp/tree/16.0 + +

+
+
+
+ +
+
+
+

+The base module required for all Ventor/mERP-related modules, i.e.: +

+
    +
  • Ventor/mERP Outgoing Routing
  • +
  • Ventor/mERP Picking Product Skip
  • +
  • Ventor/mERP Picking Wave
  • +
  • Ventor/mERP Internal Warehouse
  • +
  • and more ...
  • +
+

+It allows user to install/uninstall modules via Inventory/Warehouse Settings screen. +

+
+
+
+ +
+
+ +
+
+
+

+ In case there are multiple warehouses, this modules allows to select default warehouse that will be pre-selected for user when using menu "Internal Transfer" +

+

+ Allows to define default location that will be used for Inventory Adjustments instead of default 'WH/Stock'. +

+

+ Allows to show location barcodes disabled in the Community version. +

+
+ +
+
+ +
+
+ +
+
+ +
+

+ Adds special access rights required by the "Ventor" app: +

+
    +
  • Warehouse Operations Menu
  • +
  • Inventory Adjustments Menu
  • +
  • Instant Inventory Menu
  • +
  • Internal Transfers Menu
  • +
  • Manufacturing Menu
  • +
  • Create Sales Order Menu
  • +
  • Quick Info Menu
  • +
  • Batch Picking Menu
  • +
  • Ventor Access Rights
  • +
  • and more ...
  • +
+

+ Module also allows to define user's default stock location for instant moves. +

+
+
+ +
+ +
+
+
+

Notes

+

+This module is designed to work only with "Ventor" application that can be downloaded from: +

+
    +
  1. + https://ventor.app website - version obtained from here is suitable for all types of organizations +
  2. +
  3. + Google Play - has limitations, not possible to customize app by request - https://play.google.com/store/apps/details?id=com.xpansa.merp.warehouse +
  4. +
+

+"Ventor" app work both on regular mobile phones with Android 4.1+ and with professional barcode scanners. For full list of supported devices check F.A.Q. +

+

+ VentorTech (https://ventor.tech/) is company specialized on building Personalized Inventory and Product Management System. +

+

+For all questions contact hello@ventor.tech. +

+
+
+
diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/main_banner.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/main_banner.png new file mode 100644 index 0000000..df2bce2 Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/main_banner.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base.png new file mode 100644 index 0000000..682862a Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_1.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_1.png new file mode 100644 index 0000000..f93e61c Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_1.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_2.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_2.png new file mode 100644 index 0000000..109a3ed Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/description/merp_base_2.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/src/scss/stock_picking_type.scss b/odoo-bringout-ventor-ventor_base/ventor_base/static/src/scss/stock_picking_type.scss new file mode 100644 index 0000000..c56f5ac --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/static/src/scss/stock_picking_type.scss @@ -0,0 +1,17 @@ +.custom-control.custom-checkbox.o_field_boolean.o_field_widget.o_readonly_modifier{ + pointer-events: none; +} + +.ventor_base_tree { + & > .table-responsive { + & > .table { + & > thead { + & > tr { + & > :not(:empty) { + white-space: pre-wrap; + } + } + } + } + } +} diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/400_400.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/400_400.png new file mode 100644 index 0000000..6a75ebd Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/400_400.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/600_600.png b/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/600_600.png new file mode 100644 index 0000000..96606f1 Binary files /dev/null and b/odoo-bringout-ventor-ventor_base/ventor_base/static/test_logo/600_600.png differ diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/tests/__init__.py b/odoo-bringout-ventor-ventor_base/ventor_base/tests/__init__.py new file mode 100644 index 0000000..335a846 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/tests/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from . import test_check_default_location +from . import test_checking_logotype +from . import test_set_active_view diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_check_default_location.py b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_check_default_location.py new file mode 100644 index 0000000..57268b6 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_check_default_location.py @@ -0,0 +1,30 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo.tests.common import TransactionCase + + +class TestCheckDefaultLocation(TransactionCase): + + def setUp(self): + super(TestCheckDefaultLocation, self).setUp() + self.location = self.env['stock.location'].create({ + 'name': 'test_location' + }) + self.user = self.env['res.users'].create({ + 'name': 'test_user', + 'login': 'test_user', + 'email': 'test.user@email.com' + }) + self.ventor_worker = self.env.ref('ventor_base.ventor_role_wh_worker') + self.ventor_worker.write({'users': [(4, self.user.id)]}) + self.inventory_manager = self.env.ref('stock.group_stock_manager') + self.inventory_manager.write({'users': [(4, self.user.id)]}) + self.administration_settings = self.env.ref('base.group_system') + self.administration_settings.write({'users': [(4, self.user.id)]}) + self.company = self.env['res.company'].create({ + 'name': 'test_company', + }) + self.product = self.env['product.template'].create({ + 'name': 'new_product' + }) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_checking_logotype.py b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_checking_logotype.py new file mode 100644 index 0000000..e6e6500 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_checking_logotype.py @@ -0,0 +1,35 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo.tests.common import TransactionCase +from odoo.exceptions import UserError +from odoo.modules.module import get_resource_path +import base64 + + +class TestCheckingLogotype(TransactionCase): + + def setUp(self): + super(TestCheckingLogotype, self).setUp() + self.user = self.env['res.users'].create({ + 'name': 'admin', + 'login': 'login@email.com' + }) + self.ventor_admin = self.env.ref('ventor_base.ventor_role_admin') + self.ventor_admin.write({'users': [(4, self.user.id, 0)]}) + self.inventory_manager = self.env.ref('stock.group_stock_manager') + self.inventory_manager.write({'users': [(4, self.user.id, 0)]}) + self.administration_settings = self.env.ref('base.group_system') + self.administration_settings.write({'users': [(4, self.user.id, 0)]}) + self.company = self.env['res.company'].search([], limit=1) + + def test_upload_invalid_logo(self): + img_path = get_resource_path('ventor_base', 'static', 'test_logo', '400_400.png') + img_content = base64.b64encode(open(img_path, "rb").read()) + with self.assertRaises(UserError): + self.company._validate_logotype({'logotype_file': img_content}) + + def test_upload_valid_logo(self): + img_path = get_resource_path('ventor_base', 'static', 'test_logo', '600_600.png') + img_content = base64.b64encode(open(img_path, "rb").read()) + self.assertEqual(self.company._validate_logotype({'logotype_file': img_content}), True) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_set_active_view.py b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_set_active_view.py new file mode 100644 index 0000000..287285d --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/tests/test_set_active_view.py @@ -0,0 +1,39 @@ +# Copyright 2020 VentorTech OU +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0). + +from odoo.tests.common import TransactionCase +from odoo.exceptions import Warning +import base64 + + +class TestSetActiveView(TransactionCase): + def setUp(self): + super(TestSetActiveView, self).setUp() + self.view_with_barcode = self.env.ref('ventor_base.view_location_form_inherit_additional_barcode') + self.ConfigObj = self.env['res.config.settings'] + + def test_get_values(self): + # A default value, adjusted in a view.xml + config = self.ConfigObj.get_values() + self.assertEqual( + config['add_barcode_on_view'], + False + ) + # We set True directly to the ir.ui.view + self.view_with_barcode.active = True + config = self.ConfigObj.get_values() + self.assertEqual( + config['add_barcode_on_view'], + True + ) + + def test_set_values(self): + for value in (True, False): + config = self.ConfigObj.create( + {'add_barcode_on_view': value} + ) + config.execute() + self.assertEqual( + self.view_with_barcode.active, + value + ) diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/pallet_transfer.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/pallet_transfer.xml new file mode 100644 index 0000000..08ea82b --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/pallet_transfer.xml @@ -0,0 +1,121 @@ + + + + + ventor.base.pallet.transfer.tree + pallet.transfer + + + + + + + + + + + + ventor.base.pallet.transfer.form + pallet.transfer + +
+ +
+

+ +

+
+ + + + + + + + +
+
+
+
+ + + ventor.base.quick.pallet.transfer.form + pallet.transfer + +
+
+

+ +

+
+ + + + + + + + +
+
+
+
+
+ + + Quick Pallet Transfers + pallet.transfer + form + + new + + + + All Pallet Transfers + pallet.transfer + menu + tree,form + + current + + + + + + Quick Pallet Transfers + + + + + + + All Pallet Transfers + + + + +
diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/res_config.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/res_config.xml new file mode 100644 index 0000000..55783bb --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/res_config.xml @@ -0,0 +1,104 @@ + + + + + Ventor Application Demo - Stock Settings + res.config.settings + + + +
+ +

Ventor Application modules

+
+
+
+ +
+
+
+
+
+
+ +
+ Base Module Version +
+
+
+
+

Inventory settings

+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+

Additional Customisation

+
+
+
+
+ Custom Mobile Logo +
+ +
+
+
+
+
+
+ Custom Build Name +
+ +
+
+
+
+
+ + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/res_users.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/res_users.xml new file mode 100644 index 0000000..4b6db7f --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/res_users.xml @@ -0,0 +1,40 @@ + + + + + + + Users Preferences + res.users + + + + + + + + + + + + + + + +
+

+ Warning! If the user is Inventory / Administrator, + the Allowed Warehouses configuration is ignored and + the user will still be able to see all warehouses +

+
+
+
+
+
+ +
diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_location.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_location.xml new file mode 100644 index 0000000..9e31a0a --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_location.xml @@ -0,0 +1,41 @@ + + + + + stock.location.form.inherit.additional.barcode + stock.location + + + + + + + + + + + stock.location.form.inherited + stock.location + + + + + + + + + + + stock.location.inherit.view.search + stock.location + + + + + + + + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_picking.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_picking.xml new file mode 100644 index 0000000..98cc9a8 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_picking.xml @@ -0,0 +1,140 @@ + + + + + + + Operation Types + stock.picking.type + 1000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Operation Types + stock.picking.type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Warehouse Operations + stock.picking.type + tree,form + menu + + + + + Configuration + ir.actions.act_window + res.config.settings + form + inline + {'module' : 'ventor_base'} + + + + + + + + + + + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_quant.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_quant.xml new file mode 100644 index 0000000..60686ea --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_quant.xml @@ -0,0 +1,13 @@ + + + + view.stock.quant.tree.inherit.inventory.editable + stock.quant + + + + ventor_base.merp_user_validate_inventory_adjustment + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_warehouse.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_warehouse.xml new file mode 100644 index 0000000..a0705d6 --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/stock_warehouse.xml @@ -0,0 +1,15 @@ + + + + + stock.warehouse + stock.warehouse + + + + + + + + + diff --git a/odoo-bringout-ventor-ventor_base/ventor_base/views/ventor_option_setting.xml b/odoo-bringout-ventor-ventor_base/ventor_base/views/ventor_option_setting.xml new file mode 100644 index 0000000..fd3fb2f --- /dev/null +++ b/odoo-bringout-ventor-ventor_base/ventor_base/views/ventor_option_setting.xml @@ -0,0 +1,206 @@ + + + + + + + Ventor Settings + ventor.option.setting + 1000 + + + + + + + + + + + + + + + + Package Management + ventor.option.setting + tree + menu + + [('action_type', '=', 'package_management')] + + + + Batch Picking + ventor.option.setting + tree + menu + + [('action_type', '=', 'batch_picking'), ('technical_name', '!=', 'show_next_product')] + + + + Wave Picking + ventor.option.setting + tree + menu + + [('action_type', '=', 'wave_picking'), ('technical_name', '!=', 'show_next_product')] + + + + Cluster Picking + ventor.option.setting + tree + menu + + [('action_type', '=', 'cluster_picking'), ('technical_name', '!=', 'show_next_product')] + + + + Internal Transfers + ventor.option.setting + tree + menu + + [('action_type', '=', 'internal_transfers')] + + + + Putaway + ventor.option.setting + tree + menu + + [('action_type', '=', 'putaway')] + + + + Inventory Adjustments + ventor.option.setting + tree + menu + + [('action_type', '=', 'inventory_adjustments')] + + + + Instant Inventory + ventor.option.setting + tree + menu + + [('action_type', '=', 'instant_inventory')] + + + + Quick info + ventor.option.setting + tree + menu + + [('action_type', '=', 'quick_info')] + + + + Scrap Management + ventor.option.setting + tree + menu + + [('action_type', '=', 'scrap_management')] + + + + Create SO + ventor.option.setting + tree + menu + + [('action_type', '=', 'create_so')] + + + + Create PO + ventor.option.setting + tree + menu + + [('action_type', '=', 'create_po')] + + + + + + + + + + + + + + + + + + + + + + + + + + + +