Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
165
sale_block_no_stock/README.rst
Executable file
165
sale_block_no_stock/README.rst
Executable file
@@ -0,0 +1,165 @@
|
||||
===================
|
||||
Sale Block no Stock
|
||||
===================
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:c16ad9d6d37bb710e3897f013a183f2653b71255c3092b60129cd8f9245149bb
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Alpha
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
|
||||
:alt: License: LGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/sale-workflow/tree/18.0/sale_block_no_stock
|
||||
:alt: OCA/sale-workflow
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_block_no_stock
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
|
||||
:target: https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&target_branch=18.0
|
||||
:alt: Try me on Runboat
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
This module extends the functionality of Sales to support blocking sales
|
||||
and to allow you to ensure you are capable to send product you have in
|
||||
stock.
|
||||
|
||||
When a Sale Order is going to be confirmed, it will be checked if the
|
||||
quantity demanded exceeds that of the field selected in the
|
||||
configuration, and in this case a wizard will appear to allow you to fix
|
||||
quantities indicating what is the maximum quantity that can be ordered.
|
||||
|
||||
Then, you can adjust UoM quantities, Packaging quantities or move
|
||||
remaining unfixed lines to a new order.
|
||||
|
||||
If the user who is confirming an order has a group that is allowed, an
|
||||
extra option to confirm the Order with errors will appear on the Wizard.
|
||||
|
||||
This module only can block lines with product type 'product' (storable
|
||||
products).
|
||||
|
||||
Internal notes will be posted on sales when adjusting quantities or
|
||||
moving to another orders.
|
||||
|
||||
.. IMPORTANT::
|
||||
This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
`More details on development status <https://odoo-community.org/page/development-status>`_
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Use Cases / Context
|
||||
===================
|
||||
|
||||
This module was developed because sometimes you don't want to allow a
|
||||
sale to be confirmed when there is no enough product to sold.
|
||||
|
||||
It will be useful for you if selling more than you have in stock or
|
||||
planned is not a desired behaviour.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
To configure this module, you need to:
|
||||
|
||||
1. Go to Settings > Sales > Quotations & Orders > Blocking sales due to
|
||||
lack of stock
|
||||
2. Fill *Field to compare against the quantity demanded*. Possible
|
||||
values:
|
||||
|
||||
- *virtual_available_at_date*: Planned quantity to be in stock on the
|
||||
day of delivery
|
||||
- *qty_available_today*: Quantity available in stock today
|
||||
- *free_qty_today*: Quantity available without reserve in stock
|
||||
|
||||
3. Fill *Groups allowed to bypass the block*
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use this module, you need to:
|
||||
|
||||
1. Go to Settings > Sales > Quotations & Orders > Blocking sales due to
|
||||
lack of stock
|
||||
2. Fill *Field to compare against the quantity demanded*: This field
|
||||
will be used to check if the quantity demanded is less than or equal
|
||||
to the value marked in this field. Set it to
|
||||
*virtual_available_at_date* for this test.
|
||||
3. Fill *Groups allowed to bypass the block*: These groups will allow
|
||||
the blocking to be bypassed if the quantity demanded exceeds the
|
||||
quantity we want to check. Leave it blank to not allow any group to
|
||||
bypass that restriction.
|
||||
4. Create a Product and set it to be storable.
|
||||
5. Create a Purchase Order for the product and confirm it. Set the
|
||||
Picking Schedule Date on 3 days.
|
||||
6. Create a Sale Order with the product and set the Commitment Date on 2
|
||||
days. Confirm it and check the wizard.
|
||||
7. Click on *Ajust UoM Quantity* and see the order has been modified to
|
||||
match forecasted quantity.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_block_no_stock%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
* Moduon
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
- Eduardo de Miguel (`Moduon <https://www.moduon.team/>`__)
|
||||
- Rafael Blasco (`Moduon <https://www.moduon.team/>`__)
|
||||
|
||||
Other credits
|
||||
-------------
|
||||
|
||||
The development of this module has been financially supported by:
|
||||
|
||||
- Ulzama
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
.. |maintainer-Shide| image:: https://github.com/Shide.png?size=40px
|
||||
:target: https://github.com/Shide
|
||||
:alt: Shide
|
||||
|
||||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|
||||
|
||||
|maintainer-Shide|
|
||||
|
||||
This module is part of the `OCA/sale-workflow <https://github.com/OCA/sale-workflow/tree/18.0/sale_block_no_stock>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
2
sale_block_no_stock/__init__.py
Executable file
2
sale_block_no_stock/__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
23
sale_block_no_stock/__manifest__.py
Executable file
23
sale_block_no_stock/__manifest__.py
Executable file
@@ -0,0 +1,23 @@
|
||||
# Copyright 2024 Moduon Team S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
{
|
||||
"name": "Sale Block no Stock",
|
||||
"summary": """Block Sales if products has not enough Quantity
|
||||
based on a chosen field""",
|
||||
"version": "18.0.1.0.0",
|
||||
"development_status": "Alpha",
|
||||
"category": "Sales/Sales",
|
||||
"website": "https://github.com/OCA/sale-workflow",
|
||||
"author": "Moduon, Odoo Community Association (OCA)",
|
||||
"maintainers": ["Shide"],
|
||||
"license": "LGPL-3",
|
||||
"application": False,
|
||||
"installable": True,
|
||||
"depends": ["sale_stock", "mail_message_destiny_link_template"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"views/res_config_settings_views.xml",
|
||||
"wizard/sale_order_block_wizard_views.xml",
|
||||
],
|
||||
}
|
||||
314
sale_block_no_stock/i18n/es.po
Executable file
314
sale_block_no_stock/i18n/es.po
Executable file
@@ -0,0 +1,314 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_block_no_stock
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-28 09:31+0000\n"
|
||||
"PO-Revision-Date: 2024-06-28 11:32+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.4.4\n"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid ""
|
||||
"<span class=\"fa fa-lg fa-building-o\" title=\"Values set here are company-"
|
||||
"specific.\" groups=\"base.group_multi_company\"/>"
|
||||
msgstr ""
|
||||
"<span class=\"fa fa-lg fa-building-o\" title=\"Los valores configurados aquí "
|
||||
"son específicos de la empresa.\" groups=\"base.group_multi_company\"/>"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust Packaging Quantity"
|
||||
msgstr "Ajustar cantidad Envasada"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust UoM Quantity"
|
||||
msgstr "Ajustar cantidad en UdM"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid "Allowed Groups to bypass the block"
|
||||
msgstr "Grupos permitidos para evitar el bloqueo"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__confirmation_allowed
|
||||
msgid "Allowed to confirm"
|
||||
msgstr "Permitido para confirmar"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Avoid selling more product than you have in stock or planned"
|
||||
msgstr "Evite vender más producto del que tiene en stock o planificado"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Blocking sales due to lack of stock"
|
||||
msgstr "Bloqueo de ventas por falta de stock"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "Cannot launch wizard from sale orders from different companies."
|
||||
msgstr ""
|
||||
"No se puede abrir el asistente para Pedidos de Venta de diferentes compañías."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr "Compañías"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__company_id
|
||||
msgid "Company"
|
||||
msgstr "Compañía"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr "Opciones de configuración"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Confirm anyway"
|
||||
msgstr "Confirmar igualmente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creado por"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creado el"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nombre mostrado"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Field to compare against the quantity demanded"
|
||||
msgstr "Campo a comparar con la cantidad demandada"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid "Field to compare quantities on Sale Order Lines"
|
||||
msgstr "Campo para comparar cantidades en líneas de orden de venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Groups allowed to bypass the block"
|
||||
msgstr "Grupos autorizados a saltarse el bloqueo"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__id
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_packaging_adjustable
|
||||
msgid "Is Packaging Adjustable"
|
||||
msgstr "Es ajustable por Paquetes"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_uom_adjustable
|
||||
msgid "Is Uom Adjustable"
|
||||
msgstr "Es ajustable por UdM"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard____last_update
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Última modificación el"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Última actualización por"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Última actualización el"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_allowed_max_qty
|
||||
msgid "Max. Qty. (Pkg.)"
|
||||
msgstr "Cant. Máx. (Env.)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_allowed_max_qty
|
||||
msgid "Max. Qty. (UoM)"
|
||||
msgstr "Cant. Máx. (UdM)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Move to New Order"
|
||||
msgstr "Mover a un nuevo Pedido"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "Order confirmed with errors by %s."
|
||||
msgstr "Pedido confirmado con errores por %s."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_id
|
||||
msgid "Packaging"
|
||||
msgstr "Envase"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_id
|
||||
msgid "Product"
|
||||
msgstr "Producto"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Product <b>%(product)s</b> adjusted from <b>%(init_qty)s</b> %(uom)s to <b>"
|
||||
"%(final_qty)s</b> %(uom)s."
|
||||
msgstr ""
|
||||
"Producto <b>%(product)s</b> ajustado de <b>%(init_qty)s</b> %(uom)s a <b>"
|
||||
"%(final_qty)s</b> %(uom)s."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_qty
|
||||
msgid "Qty. (Pkg.)"
|
||||
msgstr "Cant. (Env.)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_qty
|
||||
msgid "Qty. (UoM)"
|
||||
msgstr "Cant. (UdM)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__sale_line_block_ids
|
||||
msgid "Sale Block Lines"
|
||||
msgstr "Líneas de Venta Bloqueadas"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__sale_line_id
|
||||
msgid "Sale Line"
|
||||
msgstr "Línea de venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__order_id
|
||||
msgid "Sale Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Sale Order Block"
|
||||
msgstr "Bloqueo de Pedidos de Venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard
|
||||
msgid "Sale Order Block Wizard"
|
||||
msgstr "Asistente de Bloqueo de Pedidos de Venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard_line
|
||||
msgid "Sale Order Block Wizard Line"
|
||||
msgstr "Línea del Asistente de Bloqueo de Pedidos de Venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.actions.act_window,name:sale_block_no_stock.sale_order_block_wizard_action
|
||||
msgid "Sale Order Blocked to Confirm"
|
||||
msgstr "Pedido de Venta bloqueado en la Confirmación"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid ""
|
||||
"These groups will be able to bypass the block on the Sale Order Lines if the "
|
||||
"quantity is not enough"
|
||||
msgstr ""
|
||||
"Estos grupos podrán evitar el bloqueo en las Líneas de Orden de Venta si la "
|
||||
"cantidad no es suficiente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid ""
|
||||
"This field will be checked to block the Sale Order Lines if the quantity is "
|
||||
"not enough"
|
||||
msgstr ""
|
||||
"Este campo se comprobará para bloquear las líneas de orden de venta si la "
|
||||
"cantidad no es suficiente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid ""
|
||||
"This order cannot be confirmed because it contains products that are not in "
|
||||
"stock. Please manage the following products before confirming the order."
|
||||
msgstr ""
|
||||
"Este pedido no puede ser confirmado porque contiene productos que no están "
|
||||
"en stock. Por favor, gestiona los siguientes productos antes de confirmar el "
|
||||
"pedido."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom
|
||||
msgid "UoM"
|
||||
msgstr "UdM"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__wizard_id
|
||||
msgid "Wizard"
|
||||
msgstr "Asistente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to confirm the Sale Order with not solved lines"
|
||||
msgstr "Vas a confirmar Pedidos de Venta con líneas sin solventar"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to move pending lines to a new order"
|
||||
msgstr "Vas a mover líneas a un nuevo pedido"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "You are not allowed to confirm these orders."
|
||||
msgstr "No tienes permitido confirmar estos pedidos."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "or"
|
||||
msgstr "o"
|
||||
313
sale_block_no_stock/i18n/it.po
Executable file
313
sale_block_no_stock/i18n/it.po
Executable file
@@ -0,0 +1,313 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_block_no_stock
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-07-08 08:59+0000\n"
|
||||
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.6.2\n"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid ""
|
||||
"<span class=\"fa fa-lg fa-building-o\" title=\"Values set here are company-"
|
||||
"specific.\" groups=\"base.group_multi_company\"/>"
|
||||
msgstr ""
|
||||
"<span class=\"fa fa-lg fa-building-o\" title=\"I valori impostati qui sono "
|
||||
"specifici per azienda.\" groups=\"base.group_multi_company\"/>"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust Packaging Quantity"
|
||||
msgstr "Correzione quantità confezione"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust UoM Quantity"
|
||||
msgstr "Correzione UdM quantità"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid "Allowed Groups to bypass the block"
|
||||
msgstr "Gruppi autorizzati a superare il blocco"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__confirmation_allowed
|
||||
msgid "Allowed to confirm"
|
||||
msgstr "Autorizzato alla conferma"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Avoid selling more product than you have in stock or planned"
|
||||
msgstr "Evita di vendere più prodotti di quelli in giacenza o pianificati"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Blocking sales due to lack of stock"
|
||||
msgstr "Blocco delle vendite per mancanza di giacenza"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "Cannot launch wizard from sale orders from different companies."
|
||||
msgstr ""
|
||||
"Non si può avviare la procedura guidata da ordini di vendita da aziende "
|
||||
"diverse."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Close"
|
||||
msgstr "Chiudi"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr "Aziende"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__company_id
|
||||
msgid "Company"
|
||||
msgstr "Azienda"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr "Impostazioni configurazione"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Confirm anyway"
|
||||
msgstr "Conferma comunque"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creato da"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creato il"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nome visualizzato"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Field to compare against the quantity demanded"
|
||||
msgstr "Campo ca confrontare con la quantità richiesta"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid "Field to compare quantities on Sale Order Lines"
|
||||
msgstr "Campo per confrontare le quantità nelle righe dell'ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Groups allowed to bypass the block"
|
||||
msgstr "Gruppi autorizzati a superare il blocco"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__id
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_packaging_adjustable
|
||||
msgid "Is Packaging Adjustable"
|
||||
msgstr "È possibile correggere l'imballaggio"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_uom_adjustable
|
||||
msgid "Is Uom Adjustable"
|
||||
msgstr "È possibile correggere l'UdM"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard____last_update
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Ultima modifica il"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Ultimo aggiornamento di"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Ultimo aggiornamento il"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_allowed_max_qty
|
||||
msgid "Max. Qty. (Pkg.)"
|
||||
msgstr "Qt.à max (Imb.)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_allowed_max_qty
|
||||
msgid "Max. Qty. (UoM)"
|
||||
msgstr "Qt.à max (UdM)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Move to New Order"
|
||||
msgstr "Sposta a nuovo ordine"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "Order confirmed with errors by %s."
|
||||
msgstr "Ordine confermato con errori da %s."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_id
|
||||
msgid "Packaging"
|
||||
msgstr "Imballaggio"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_id
|
||||
msgid "Product"
|
||||
msgstr "Prodotto"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Product <b>%(product)s</b> adjusted from <b>%(init_qty)s</b> %(uom)s to <b>"
|
||||
"%(final_qty)s</b> %(uom)s."
|
||||
msgstr ""
|
||||
"Prodotto <b>%(product)s</b> rettificato da <b>%(init_qty)s</b> %(uom)s a "
|
||||
"<b>%(final_qty)s</b> %(uom)s."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_qty
|
||||
msgid "Qty. (Pkg.)"
|
||||
msgstr "Qt.à (Imb.)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_qty
|
||||
msgid "Qty. (UoM)"
|
||||
msgstr "Qt.à (UdM)"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__sale_line_block_ids
|
||||
msgid "Sale Block Lines"
|
||||
msgstr "Righe vendite bloccate"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__sale_line_id
|
||||
msgid "Sale Line"
|
||||
msgstr "Riga di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__order_id
|
||||
msgid "Sale Order"
|
||||
msgstr "Ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Sale Order Block"
|
||||
msgstr "Blocco ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard
|
||||
msgid "Sale Order Block Wizard"
|
||||
msgstr "Procedura guidata blocco ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard_line
|
||||
msgid "Sale Order Block Wizard Line"
|
||||
msgstr "Riga procedura guidata blocco ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.actions.act_window,name:sale_block_no_stock.sale_order_block_wizard_action
|
||||
msgid "Sale Order Blocked to Confirm"
|
||||
msgstr "Ordine di vendita bloccato da confermare"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Ordine di vendita"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid ""
|
||||
"These groups will be able to bypass the block on the Sale Order Lines if the "
|
||||
"quantity is not enough"
|
||||
msgstr ""
|
||||
"Questi gruppi potranno superare il blocco nelle righe ordine di vendita se "
|
||||
"la quantità non è sufficiente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid ""
|
||||
"This field will be checked to block the Sale Order Lines if the quantity is "
|
||||
"not enough"
|
||||
msgstr ""
|
||||
"Questo campo sarà selezionato per bloccare le righe ordine di vendita se la "
|
||||
"quantità non è sufficiente"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid ""
|
||||
"This order cannot be confirmed because it contains products that are not in "
|
||||
"stock. Please manage the following products before confirming the order."
|
||||
msgstr ""
|
||||
"Questo ordine non può essere confermato perché contiene prodotti che non "
|
||||
"hanno giacenza. Gestire i seguenti prodotti prima di confermare l'ordine."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom
|
||||
msgid "UoM"
|
||||
msgstr "UdM"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__wizard_id
|
||||
msgid "Wizard"
|
||||
msgstr "Procedura guidata"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to confirm the Sale Order with not solved lines"
|
||||
msgstr "Si sta confermando l'ordinei di vendita senza righe risolte"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to move pending lines to a new order"
|
||||
msgstr "Si stanno spostando le righe in attesa in un nuovo ordine"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
#, python-format
|
||||
msgid "You are not allowed to confirm these orders."
|
||||
msgstr "Non si è autorizzati a confermare questo ordine."
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "or"
|
||||
msgstr "o"
|
||||
276
sale_block_no_stock/i18n/pt.po
Executable file
276
sale_block_no_stock/i18n/pt.po
Executable file
@@ -0,0 +1,276 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_block_no_stock
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 18.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust Packaging Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust UoM Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid "Allowed Groups to bypass the block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__confirmation_allowed
|
||||
msgid "Allowed to confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Avoid selling more product than you have in stock or planned"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Blocking sales due to lack of stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid ""
|
||||
"Cannot launch wizard from sale orders\n"
|
||||
" from different companies."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Confirm anyway"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Field to compare against the quantity demanded"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid "Field to compare quantities on Sale Order Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Groups allowed to bypass the block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__id
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_packaging_adjustable
|
||||
msgid "Is Packaging Adjustable"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_uom_adjustable
|
||||
msgid "Is Uom Adjustable"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_allowed_max_qty
|
||||
msgid "Max. Qty. (Pkg.)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_allowed_max_qty
|
||||
msgid "Max. Qty. (UoM)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Move to New Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid "Order confirmed with errors by %s."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_id
|
||||
msgid "Packaging"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_id
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_qty
|
||||
msgid "Qty. (Pkg.)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_qty
|
||||
msgid "Qty. (UoM)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__sale_line_block_ids
|
||||
msgid "Sale Block Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__sale_line_id
|
||||
msgid "Sale Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__order_id
|
||||
msgid "Sale Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Sale Order Block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard
|
||||
msgid "Sale Order Block Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard_line
|
||||
msgid "Sale Order Block Wizard Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.actions.act_window,name:sale_block_no_stock.sale_order_block_wizard_action
|
||||
msgid "Sale Order Blocked to Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid ""
|
||||
"These groups will be able to bypass the block on the Sale Order Lines if the"
|
||||
" quantity is not enough"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid ""
|
||||
"This field will be checked to block the Sale Order Lines if the quantity is "
|
||||
"not enough"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid ""
|
||||
"This order cannot be confirmed because it contains products that are not in "
|
||||
"stock. Please manage the following products before confirming the order."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom
|
||||
msgid "UoM"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__wizard_id
|
||||
msgid "Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to confirm the Sale Order with not solved lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to move pending lines to a new order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid "You are not allowed to confirm these orders."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
275
sale_block_no_stock/i18n/sale_block_no_stock.pot
Executable file
275
sale_block_no_stock/i18n/sale_block_no_stock.pot
Executable file
@@ -0,0 +1,275 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_block_no_stock
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 18.0\n"
|
||||
"Report-Msgid-Bugs-To: \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: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust Packaging Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Adjust UoM Quantity"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid "Allowed Groups to bypass the block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__confirmation_allowed
|
||||
msgid "Allowed to confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Avoid selling more product than you have in stock or planned"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Blocking sales due to lack of stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid ""
|
||||
"Cannot launch wizard from sale orders\n"
|
||||
" from different companies."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__company_id
|
||||
msgid "Company"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Confirm anyway"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__create_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Field to compare against the quantity demanded"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid "Field to compare quantities on Sale Order Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.res_config_settings_view_form
|
||||
msgid "Groups allowed to bypass the block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__id
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_packaging_adjustable
|
||||
msgid "Is Packaging Adjustable"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__is_uom_adjustable
|
||||
msgid "Is Uom Adjustable"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_uid
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__write_date
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_allowed_max_qty
|
||||
msgid "Max. Qty. (Pkg.)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_allowed_max_qty
|
||||
msgid "Max. Qty. (UoM)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Move to New Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid "Order confirmed with errors by %s."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_id
|
||||
msgid "Packaging"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_id
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_packaging_qty
|
||||
msgid "Qty. (Pkg.)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom_qty
|
||||
msgid "Qty. (UoM)"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard__sale_line_block_ids
|
||||
msgid "Sale Block Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__sale_line_id
|
||||
msgid "Sale Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__order_id
|
||||
msgid "Sale Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "Sale Order Block"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard
|
||||
msgid "Sale Order Block Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order_block_wizard_line
|
||||
msgid "Sale Order Block Wizard Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.actions.act_window,name:sale_block_no_stock.sale_order_block_wizard_action
|
||||
msgid "Sale Order Blocked to Confirm"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model,name:sale_block_no_stock.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_block_allowed_groups
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_block_allowed_groups
|
||||
msgid ""
|
||||
"These groups will be able to bypass the block on the Sale Order Lines if the"
|
||||
" quantity is not enough"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_company__sale_line_field_block
|
||||
#: model:ir.model.fields,help:sale_block_no_stock.field_res_config_settings__sale_line_field_block
|
||||
msgid ""
|
||||
"This field will be checked to block the Sale Order Lines if the quantity is "
|
||||
"not enough"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid ""
|
||||
"This order cannot be confirmed because it contains products that are not in "
|
||||
"stock. Please manage the following products before confirming the order."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__product_uom
|
||||
msgid "UoM"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model:ir.model.fields,field_description:sale_block_no_stock.field_sale_order_block_wizard_line__wizard_id
|
||||
msgid "Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to confirm the Sale Order with not solved lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "You are going to move pending lines to a new order"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#. odoo-python
|
||||
#: code:addons/sale_block_no_stock/wizard/sale_order_block_wizard.py:0
|
||||
msgid "You are not allowed to confirm these orders."
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_block_no_stock
|
||||
#: model_terms:ir.ui.view,arch_db:sale_block_no_stock.sale_order_block_wizard_view
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
3
sale_block_no_stock/models/__init__.py
Executable file
3
sale_block_no_stock/models/__init__.py
Executable file
@@ -0,0 +1,3 @@
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
from . import sale_order
|
||||
33
sale_block_no_stock/models/res_company.py
Executable file
33
sale_block_no_stock/models/res_company.py
Executable file
@@ -0,0 +1,33 @@
|
||||
# Copyright 2024 Moduon Team S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
sale_line_field_block = fields.Many2one(
|
||||
comodel_name="ir.model.fields",
|
||||
string="Field to compare quantities on Sale Order Lines",
|
||||
help="This field will be checked to block the Sale Order Lines "
|
||||
"if the quantity is not enough",
|
||||
domain=[
|
||||
("model_id.model", "=", "sale.order.line"),
|
||||
(
|
||||
"name",
|
||||
"in",
|
||||
(
|
||||
"free_qty_today",
|
||||
"qty_available_today",
|
||||
"virtual_available_at_date",
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
sale_line_block_allowed_groups = fields.Many2many(
|
||||
comodel_name="res.groups",
|
||||
string="Allowed Groups to bypass the block",
|
||||
help="These groups will be able to bypass the block on the Sale Order Lines "
|
||||
"if the quantity is not enough",
|
||||
)
|
||||
22
sale_block_no_stock/models/res_config_settings.py
Executable file
22
sale_block_no_stock/models/res_config_settings.py
Executable file
@@ -0,0 +1,22 @@
|
||||
# Copyright 2024 Moduon Team S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
sale_line_field_block = fields.Many2one(
|
||||
related="company_id.sale_line_field_block",
|
||||
help="This field will be checked to block the Sale Order Lines "
|
||||
"if the quantity is not enough",
|
||||
readonly=False,
|
||||
)
|
||||
sale_line_block_allowed_groups = fields.Many2many(
|
||||
related="company_id.sale_line_block_allowed_groups",
|
||||
help="These groups will be able to bypass the block on the Sale Order Lines "
|
||||
"if the quantity is not enough",
|
||||
readonly=False,
|
||||
)
|
||||
41
sale_block_no_stock/models/sale_order.py
Executable file
41
sale_block_no_stock/models/sale_order.py
Executable file
@@ -0,0 +1,41 @@
|
||||
# Copyright 2024 Moduon Team S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
def action_confirm(self):
|
||||
"""Check the stock of the products before confirming the sale order."""
|
||||
if self.env.context.get("skip_block_no_stock_check") and all(
|
||||
self.env.user in company.sale_line_block_allowed_groups.users
|
||||
for company in self.mapped("company_id")
|
||||
):
|
||||
return super().action_confirm()
|
||||
|
||||
for record in self:
|
||||
field_to_check = record.sudo().company_id.sale_line_field_block
|
||||
if not field_to_check:
|
||||
continue
|
||||
|
||||
blocked_lines = self.env["sale.order.line"].browse()
|
||||
lines = record.order_line.filtered_domain(
|
||||
[("product_type", "=", "consu"), ("is_storable", "=", True)]
|
||||
)
|
||||
for line in lines:
|
||||
if line.product_uom_qty > line[field_to_check.name]:
|
||||
blocked_lines |= line
|
||||
if blocked_lines:
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
"sale_block_no_stock.sale_order_block_wizard_action"
|
||||
)
|
||||
action["context"] = {
|
||||
"default_sale_line_block_ids": [
|
||||
(0, 0, {"sale_line_id": line.id}) for line in blocked_lines
|
||||
]
|
||||
}
|
||||
return action
|
||||
|
||||
return super().action_confirm()
|
||||
3
sale_block_no_stock/pyproject.toml
Executable file
3
sale_block_no_stock/pyproject.toml
Executable file
@@ -0,0 +1,3 @@
|
||||
[build-system]
|
||||
requires = ["whool"]
|
||||
build-backend = "whool.buildapi"
|
||||
10
sale_block_no_stock/readme/CONFIGURE.md
Executable file
10
sale_block_no_stock/readme/CONFIGURE.md
Executable file
@@ -0,0 +1,10 @@
|
||||
To configure this module, you need to:
|
||||
|
||||
1. Go to Settings > Sales > Quotations & Orders > Blocking sales due to lack of stock
|
||||
2. Fill *Field to compare against the quantity demanded*. Possible values:
|
||||
|
||||
- *virtual_available_at_date*: Planned quantity to be in stock on the day of delivery
|
||||
- *qty_available_today*: Quantity available in stock today
|
||||
- *free_qty_today*: Quantity available without reserve in stock
|
||||
|
||||
3. Fill *Groups allowed to bypass the block*
|
||||
3
sale_block_no_stock/readme/CONTEXT.md
Executable file
3
sale_block_no_stock/readme/CONTEXT.md
Executable file
@@ -0,0 +1,3 @@
|
||||
This module was developed because sometimes you don't want to allow a sale to be confirmed when there is no enough product to sold.
|
||||
|
||||
It will be useful for you if selling more than you have in stock or planned is not a desired behaviour.
|
||||
2
sale_block_no_stock/readme/CONTRIBUTORS.md
Executable file
2
sale_block_no_stock/readme/CONTRIBUTORS.md
Executable file
@@ -0,0 +1,2 @@
|
||||
- Eduardo de Miguel ([Moduon](https://www.moduon.team/))
|
||||
- Rafael Blasco ([Moduon](https://www.moduon.team/))
|
||||
3
sale_block_no_stock/readme/CREDITS.md
Executable file
3
sale_block_no_stock/readme/CREDITS.md
Executable file
@@ -0,0 +1,3 @@
|
||||
The development of this module has been financially supported by:
|
||||
|
||||
- Ulzama
|
||||
11
sale_block_no_stock/readme/DESCRIPTION.md
Executable file
11
sale_block_no_stock/readme/DESCRIPTION.md
Executable file
@@ -0,0 +1,11 @@
|
||||
This module extends the functionality of Sales to support blocking sales and to allow you to ensure you are capable to send product you have in stock.
|
||||
|
||||
When a Sale Order is going to be confirmed, it will be checked if the quantity demanded exceeds that of the field selected in the configuration, and in this case a wizard will appear to allow you to fix quantities indicating what is the maximum quantity that can be ordered.
|
||||
|
||||
Then, you can adjust UoM quantities, Packaging quantities or move remaining unfixed lines to a new order.
|
||||
|
||||
If the user who is confirming an order has a group that is allowed, an extra option to confirm the Order with errors will appear on the Wizard.
|
||||
|
||||
This module only can block lines with product type 'product' (storable products).
|
||||
|
||||
Internal notes will be posted on sales when adjusting quantities or moving to another orders.
|
||||
9
sale_block_no_stock/readme/USAGE.md
Executable file
9
sale_block_no_stock/readme/USAGE.md
Executable file
@@ -0,0 +1,9 @@
|
||||
To use this module, you need to:
|
||||
|
||||
1. Go to Settings > Sales > Quotations & Orders > Blocking sales due to lack of stock
|
||||
2. Fill *Field to compare against the quantity demanded*: This field will be used to check if the quantity demanded is less than or equal to the value marked in this field. Set it to *virtual_available_at_date* for this test.
|
||||
3. Fill *Groups allowed to bypass the block*: These groups will allow the blocking to be bypassed if the quantity demanded exceeds the quantity we want to check. Leave it blank to not allow any group to bypass that restriction.
|
||||
4. Create a Product and set it to be storable.
|
||||
5. Create a Purchase Order for the product and confirm it. Set the Picking Schedule Date on 3 days.
|
||||
6. Create a Sale Order with the product and set the Commitment Date on 2 days. Confirm it and check the wizard.
|
||||
7. Click on *Ajust UoM Quantity* and see the order has been modified to match forecasted quantity.
|
||||
3
sale_block_no_stock/security/ir.model.access.csv
Executable file
3
sale_block_no_stock/security/ir.model.access.csv
Executable file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_order_block_wizard,access.sale.order.block.wizard,model_sale_order_block_wizard,base.group_user,1,1,1,1
|
||||
access_sale_order_block_wizard_line,access.sale.order.block.wizard.line,model_sale_order_block_wizard_line,base.group_user,1,1,1,1
|
||||
|
BIN
sale_block_no_stock/static/description/icon.png
Executable file
BIN
sale_block_no_stock/static/description/icon.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
506
sale_block_no_stock/static/description/index.html
Executable file
506
sale_block_no_stock/static/description/index.html
Executable file
@@ -0,0 +1,506 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
|
||||
<title>Sale Block no Stock</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
Despite the name, some widely supported CSS2 features are used.
|
||||
|
||||
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: gray; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic, pre.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="sale-block-no-stock">
|
||||
<h1 class="title">Sale Block no Stock</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:c16ad9d6d37bb710e3897f013a183f2653b71255c3092b60129cd8f9245149bb
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_block_no_stock"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_block_no_stock"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||
<p>This module extends the functionality of Sales to support blocking sales
|
||||
and to allow you to ensure you are capable to send product you have in
|
||||
stock.</p>
|
||||
<p>When a Sale Order is going to be confirmed, it will be checked if the
|
||||
quantity demanded exceeds that of the field selected in the
|
||||
configuration, and in this case a wizard will appear to allow you to fix
|
||||
quantities indicating what is the maximum quantity that can be ordered.</p>
|
||||
<p>Then, you can adjust UoM quantities, Packaging quantities or move
|
||||
remaining unfixed lines to a new order.</p>
|
||||
<p>If the user who is confirming an order has a group that is allowed, an
|
||||
extra option to confirm the Order with errors will appear on the Wizard.</p>
|
||||
<p>This module only can block lines with product type ‘product’ (storable
|
||||
products).</p>
|
||||
<p>Internal notes will be posted on sales when adjusting quantities or
|
||||
moving to another orders.</p>
|
||||
<div class="admonition important">
|
||||
<p class="first admonition-title">Important</p>
|
||||
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
|
||||
Only for development or testing purpose, do not use in production.
|
||||
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
|
||||
</div>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#use-cases-context" id="toc-entry-1">Use Cases / Context</a></li>
|
||||
<li><a class="reference internal" href="#configuration" id="toc-entry-2">Configuration</a></li>
|
||||
<li><a class="reference internal" href="#usage" id="toc-entry-3">Usage</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#other-credits" id="toc-entry-8">Other credits</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="use-cases-context">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Use Cases / Context</a></h1>
|
||||
<p>This module was developed because sometimes you don’t want to allow a
|
||||
sale to be confirmed when there is no enough product to sold.</p>
|
||||
<p>It will be useful for you if selling more than you have in stock or
|
||||
planned is not a desired behaviour.</p>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Configuration</a></h1>
|
||||
<p>To configure this module, you need to:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Go to Settings > Sales > Quotations & Orders > Blocking sales due to
|
||||
lack of stock</li>
|
||||
<li>Fill <em>Field to compare against the quantity demanded</em>. Possible
|
||||
values:</li>
|
||||
</ol>
|
||||
<ul class="simple">
|
||||
<li><em>virtual_available_at_date</em>: Planned quantity to be in stock on the
|
||||
day of delivery</li>
|
||||
<li><em>qty_available_today</em>: Quantity available in stock today</li>
|
||||
<li><em>free_qty_today</em>: Quantity available without reserve in stock</li>
|
||||
</ul>
|
||||
<ol class="arabic simple" start="3">
|
||||
<li>Fill <em>Groups allowed to bypass the block</em></li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#toc-entry-3">Usage</a></h1>
|
||||
<p>To use this module, you need to:</p>
|
||||
<ol class="arabic simple">
|
||||
<li>Go to Settings > Sales > Quotations & Orders > Blocking sales due to
|
||||
lack of stock</li>
|
||||
<li>Fill <em>Field to compare against the quantity demanded</em>: This field
|
||||
will be used to check if the quantity demanded is less than or equal
|
||||
to the value marked in this field. Set it to
|
||||
<em>virtual_available_at_date</em> for this test.</li>
|
||||
<li>Fill <em>Groups allowed to bypass the block</em>: These groups will allow
|
||||
the blocking to be bypassed if the quantity demanded exceeds the
|
||||
quantity we want to check. Leave it blank to not allow any group to
|
||||
bypass that restriction.</li>
|
||||
<li>Create a Product and set it to be storable.</li>
|
||||
<li>Create a Purchase Order for the product and confirm it. Set the
|
||||
Picking Schedule Date on 3 days.</li>
|
||||
<li>Create a Sale Order with the product and set the Commitment Date on 2
|
||||
days. Confirm it and check the wizard.</li>
|
||||
<li>Click on <em>Ajust UoM Quantity</em> and see the order has been modified to
|
||||
match forecasted quantity.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sale-workflow/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_block_no_stock%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#toc-entry-5">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-6">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Moduon</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Eduardo de Miguel (<a class="reference external" href="https://www.moduon.team/">Moduon</a>)</li>
|
||||
<li>Rafael Blasco (<a class="reference external" href="https://www.moduon.team/">Moduon</a>)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="other-credits">
|
||||
<h2><a class="toc-backref" href="#toc-entry-8">Other credits</a></h2>
|
||||
<p>The development of this module has been financially supported by:</p>
|
||||
<ul class="simple">
|
||||
<li>Ulzama</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org">
|
||||
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
|
||||
</a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
|
||||
<p><a class="reference external image-reference" href="https://github.com/Shide"><img alt="Shide" src="https://github.com/Shide.png?size=40px" /></a></p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_block_no_stock">OCA/sale-workflow</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1
sale_block_no_stock/tests/__init__.py
Executable file
1
sale_block_no_stock/tests/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
from . import test_sale_block_no_stock
|
||||
317
sale_block_no_stock/tests/test_sale_block_no_stock.py
Executable file
317
sale_block_no_stock/tests/test_sale_block_no_stock.py
Executable file
@@ -0,0 +1,317 @@
|
||||
# Copyright 2024 Moduon Team S.L.
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0)
|
||||
|
||||
from freezegun import freeze_time
|
||||
|
||||
from odoo.fields import Command
|
||||
from odoo.tests.common import TransactionCase, new_test_user, tagged
|
||||
|
||||
|
||||
@freeze_time("2024-01-01")
|
||||
@tagged("post_install", "-at_install")
|
||||
class TestSaleBlockNoStock(TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.company = cls.env.user.company_id
|
||||
cls.saleblock_user = new_test_user(
|
||||
cls.env,
|
||||
"saleblock",
|
||||
"sales_team.group_sale_manager,stock.group_stock_manager,base.group_system",
|
||||
company_ids=[Command.set(cls.company.ids)],
|
||||
)
|
||||
|
||||
cls.f_qty_today = cls.env.ref(
|
||||
"sale_stock.field_sale_order_line__qty_available_today"
|
||||
)
|
||||
cls.f_free = cls.env.ref("sale_stock.field_sale_order_line__free_qty_today")
|
||||
cls.f_virtual = cls.env.ref(
|
||||
"sale_stock.field_sale_order_line__virtual_available_at_date"
|
||||
)
|
||||
|
||||
cls.partner = cls.env["res.partner"].create({"name": "Test Partner"})
|
||||
cls.product = cls.env["product.product"].create(
|
||||
{
|
||||
"name": "Test Product",
|
||||
"type": "consu",
|
||||
"is_storable": True,
|
||||
"uom_id": cls.env.ref("uom.product_uom_unit").id,
|
||||
}
|
||||
)
|
||||
cls.product_packaging = cls.env["product.packaging"].create(
|
||||
{
|
||||
"name": "Half Unit",
|
||||
"product_id": cls.product.id,
|
||||
"qty": 0.5,
|
||||
}
|
||||
)
|
||||
cls.quant = cls.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": cls.product.id,
|
||||
"location_id": cls.env.ref("stock.stock_location_stock").id,
|
||||
"quantity": 1,
|
||||
"company_id": cls.company.id,
|
||||
}
|
||||
)
|
||||
cls.sale = cls.env["sale.order"].create(
|
||||
{
|
||||
"state": "draft",
|
||||
"company_id": cls.company.id,
|
||||
"partner_id": cls.partner.id,
|
||||
"commitment_date": "2024-01-01",
|
||||
"user_id": cls.saleblock_user.id,
|
||||
"order_line": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": cls.product.id,
|
||||
"product_uom_qty": 1,
|
||||
"product_uom": cls.env.ref("uom.product_uom_dozen").id,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
cls.in_picking = cls.env["stock.picking"].create(
|
||||
{
|
||||
"picking_type_id": cls.env.ref("stock.picking_type_in").id,
|
||||
"company_id": cls.company.id,
|
||||
"location_id": cls.env.ref("stock.stock_location_suppliers").id,
|
||||
"location_dest_id": cls.env.ref("stock.stock_location_stock").id,
|
||||
"scheduled_date": "2024-01-05",
|
||||
"state": "assigned",
|
||||
"move_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"name": "Test Move",
|
||||
"product_id": cls.product.id,
|
||||
"product_uom_qty": 11.0,
|
||||
"product_uom": cls.product.uom_id.id,
|
||||
"location_id": cls.env.ref(
|
||||
"stock.stock_location_suppliers"
|
||||
).id,
|
||||
"location_dest_id": cls.env.ref(
|
||||
"stock.stock_location_stock"
|
||||
).id,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
cls.in_picking.move_ids[0].quantity = 11.0
|
||||
|
||||
def _get_wizard(self, wizard_user, wizard_action):
|
||||
"""Returns a new wizard instance from the given action."""
|
||||
self.assertEqual(isinstance(wizard_action, dict), True)
|
||||
self.assertEqual(wizard_action["res_model"], "sale.order.block.wizard")
|
||||
wiz_vals = (
|
||||
self.env[wizard_action["res_model"]]
|
||||
.with_context(**wizard_action["context"])
|
||||
.default_get(["sale_line_block_ids"])
|
||||
)
|
||||
return (
|
||||
self.env[wizard_action["res_model"]]
|
||||
.with_user(wizard_user.id)
|
||||
.with_context(uid=wizard_user.id)
|
||||
.create(wiz_vals)
|
||||
)
|
||||
|
||||
def test_sale_blocking_qty_available_today(self):
|
||||
"""Test Sale Order Blocking with Quantity Available Today."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# Block: No 1 Dozen in stock
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
# Block: No 2 Units in stock
|
||||
self.sale.order_line[0].product_uom_qty = 2
|
||||
self.sale.order_line[0].product_uom = self.env.ref("uom.product_uom_unit").id
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
self.assertFalse(wizard.confirmation_allowed)
|
||||
|
||||
def test_sale_blocking_free_qty_today(self):
|
||||
"""Test Sale Order Blocking with Free Quantity Available Today."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_free
|
||||
# Change quantities to 1 Unit
|
||||
self.sale.order_line[0].product_uom_qty = 1
|
||||
self.sale.order_line[0].product_uom = self.env.ref("uom.product_uom_unit").id
|
||||
# Confirm sale and create a new Sale to check reserved quantity
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm()
|
||||
self.assertNotEqual(self.sale.state, "draft")
|
||||
self.sale.picking_ids.action_confirm()
|
||||
new_sale = self.env["sale.order"].create(
|
||||
{
|
||||
"state": "draft",
|
||||
"company_id": self.company.id,
|
||||
"partner_id": self.partner.id,
|
||||
"commitment_date": "2024-01-01",
|
||||
"user_id": self.saleblock_user.id,
|
||||
"order_line": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product.id,
|
||||
"product_uom_qty": 1,
|
||||
"product_uom": self.env.ref("uom.product_uom_dozen").id,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
# Block: No unreserved 1 Unit on 2024-01-01
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
new_sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
self.assertFalse(wizard.confirmation_allowed)
|
||||
|
||||
def test_sale_blocking_virtual_available_at_date(self):
|
||||
"""Test Sale Order Blocking with Virtual Available at Date (Forecast)."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_virtual
|
||||
# Block: No 1 Dozen on 2024-01-01
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
self.assertFalse(wizard.confirmation_allowed)
|
||||
self.sale.commitment_date = "2024-01-05"
|
||||
self.in_picking.action_assign()
|
||||
# No Block: 1 Dozen on 2024-01-05
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm()
|
||||
self.assertNotEqual(self.sale.state, "draft")
|
||||
|
||||
def test_sale_blocking_allowed_groups(self):
|
||||
"""Test Sale Order Blocking with Allowed Groups."""
|
||||
self.company.sale_line_block_allowed_groups = [
|
||||
(6, 0, self.env.ref("sales_team.group_sale_manager").ids)
|
||||
]
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# No Block: No 1 Dozen on 2024-01-01 + allowed groups
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
self.assertTrue(wizard.confirmation_allowed)
|
||||
wizard.with_user(self.saleblock_user.id).confirm()
|
||||
self.assertNotEqual(self.sale.state, "draft")
|
||||
|
||||
def test_sale_blocking_not_allowed_groups(self):
|
||||
"""Test Sale Order Blocking with Not Allowed Groups."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# No Block: No 1 Dozen on 2024-01-01 + not allowed groups
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
self.assertFalse(wizard.confirmation_allowed)
|
||||
|
||||
def test_sale_adjust_uom_quantity(self):
|
||||
"""Test Wizard Adjusting Quantity."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# Block: No 2 Units in stock
|
||||
self.sale.order_line[0].product_uom_qty = 2
|
||||
self.sale.order_line[0].product_uom = self.env.ref("uom.product_uom_unit").id
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
# Wizard: Adjust Quantities to 1 Unit
|
||||
wizard.action_adjust_uom_quantity()
|
||||
self.assertEqual(self.sale.order_line[0].product_uom_qty, 1)
|
||||
# No Block: 1 Unit in stock
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm()
|
||||
self.assertNotEqual(self.sale.state, "draft")
|
||||
# Check messages
|
||||
self.assertTrue(
|
||||
any(
|
||||
[
|
||||
"adjusted from" in body
|
||||
for body in self.sale.message_ids.mapped("body")
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def test_sale_adjust_packaging_quantity(self):
|
||||
"""Test Wizard Adjusting Packaging Quantity."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# Block: No 2 Units in stock (4 Packagings)
|
||||
self.sale.order_line[0].product_uom = self.env.ref("uom.product_uom_unit").id
|
||||
self.sale.order_line[0].product_uom_qty = 4 * self.product_packaging.qty
|
||||
self.sale.order_line[0].product_packaging_id = self.product_packaging.id
|
||||
self.sale.order_line[0].product_packaging_qty = 4
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
# Wizard: Adjust Packaging Quantities
|
||||
wizard.action_adjust_packaging_quantity()
|
||||
self.assertEqual(self.sale.order_line[0].product_uom_qty, 1)
|
||||
self.assertEqual(self.sale.order_line[0].product_packaging_qty, 2)
|
||||
# No Block: 1 Unit (2 Packagings) in stock
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm()
|
||||
self.assertNotEqual(self.sale.state, "draft")
|
||||
# Check messages
|
||||
self.assertTrue(
|
||||
any(
|
||||
[
|
||||
"adjusted from" in body
|
||||
for body in self.sale.message_ids.mapped("body")
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def test_sale_move_to_new_order(self):
|
||||
"""Test Wizard Moving to New Order."""
|
||||
self.company.sale_line_block_allowed_groups = False
|
||||
self.company.sale_line_field_block = self.f_qty_today
|
||||
# Block: No 4 Units in stock
|
||||
self.sale.order_line[0].product_uom = self.env.ref("uom.product_uom_unit").id
|
||||
self.sale.order_line[0].product_uom_qty = 4
|
||||
wizard = self._get_wizard(
|
||||
self.saleblock_user,
|
||||
self.sale.with_user(self.saleblock_user.id).action_confirm(),
|
||||
)
|
||||
self.assertEqual(len(wizard.sale_line_block_ids), 1)
|
||||
# Wizard: Move to new order
|
||||
new_orders = wizard.action_move_to_new_order()
|
||||
self.assertEqual(len(self.sale.order_line), 0)
|
||||
self.assertEqual(len(new_orders.order_line), 1)
|
||||
# Check messages
|
||||
self.assertTrue(
|
||||
any(
|
||||
[
|
||||
"This sales order has created" in body
|
||||
for body in self.sale.message_ids.mapped("body")
|
||||
]
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
any(
|
||||
[
|
||||
"This sales order has been modified from" in body
|
||||
for body in new_orders.message_ids.mapped("body")
|
||||
]
|
||||
)
|
||||
)
|
||||
46
sale_block_no_stock/views/res_config_settings_views.xml
Executable file
46
sale_block_no_stock/views/res_config_settings_views.xml
Executable file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.sale.block</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="sale.res_config_settings_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//setting[@id='no_edit_order']" position="after">
|
||||
<setting
|
||||
id="sale_line_field_block"
|
||||
string="Blocking sales due to lack of stock"
|
||||
help="Avoid selling more product than you have in stock or planned"
|
||||
company_dependent="1"
|
||||
>
|
||||
<div class="content-group">
|
||||
<div class="mt-2">
|
||||
<label
|
||||
for="sale_line_field_block"
|
||||
string="Field to compare against the quantity demanded"
|
||||
class="w-100"
|
||||
/>
|
||||
<field
|
||||
name="sale_line_field_block"
|
||||
options="{'no_create': True, 'no_open': True}"
|
||||
class="w-75"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<label
|
||||
for="sale_line_block_allowed_groups"
|
||||
string="Groups allowed to bypass the block"
|
||||
class="w-100"
|
||||
/>
|
||||
<field
|
||||
name="sale_line_block_allowed_groups"
|
||||
widget="many2many_tags"
|
||||
options="{'no_create': True, 'no_open': True}"
|
||||
class="w-100"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
1
sale_block_no_stock/wizard/__init__.py
Executable file
1
sale_block_no_stock/wizard/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
from . import sale_order_block_wizard
|
||||
312
sale_block_no_stock/wizard/sale_order_block_wizard.py
Executable file
312
sale_block_no_stock/wizard/sale_order_block_wizard.py
Executable file
@@ -0,0 +1,312 @@
|
||||
from markupsafe import Markup
|
||||
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
from odoo.tools import groupby
|
||||
|
||||
|
||||
class SaleOrderBlockWizard(models.TransientModel):
|
||||
_name = "sale.order.block.wizard"
|
||||
_description = "Sale Order Block Wizard"
|
||||
_transient_max_hours = 0.25 # 15 minutes until destroyed
|
||||
|
||||
sale_line_block_ids = fields.One2many(
|
||||
comodel_name="sale.order.block.wizard.line",
|
||||
inverse_name="wizard_id",
|
||||
string="Sale Block Lines",
|
||||
)
|
||||
confirmation_allowed = fields.Boolean(
|
||||
string="Allowed to confirm",
|
||||
compute="_compute_confirmation_allowed",
|
||||
)
|
||||
is_uom_adjustable = fields.Boolean(
|
||||
compute="_compute_is_adjustable",
|
||||
store=True,
|
||||
readonly=True,
|
||||
compute_sudo=True,
|
||||
)
|
||||
is_packaging_adjustable = fields.Boolean(
|
||||
compute="_compute_is_adjustable",
|
||||
store=True,
|
||||
readonly=True,
|
||||
compute_sudo=True,
|
||||
)
|
||||
|
||||
@api.depends_context("uid")
|
||||
@api.depends("sale_line_block_ids.company_id")
|
||||
def _compute_confirmation_allowed(self):
|
||||
"""Compute if the user is allowed to confirm the sale orders."""
|
||||
self.confirmation_allowed = (
|
||||
self.env.user
|
||||
in self.sale_line_block_ids.company_id.sale_line_block_allowed_groups.users
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
"sale_line_block_ids.product_packaging_allowed_max_qty",
|
||||
"sale_line_block_ids.product_uom_allowed_max_qty",
|
||||
)
|
||||
def _compute_is_adjustable(self):
|
||||
"""Compute if the sale lines are adjustable."""
|
||||
for record in self:
|
||||
lines = record.mapped("sale_line_block_ids")
|
||||
record.is_packaging_adjustable = bool(
|
||||
lines.filtered(
|
||||
lambda line: line.product_packaging_allowed_max_qty > 0.0
|
||||
)
|
||||
)
|
||||
record.is_uom_adjustable = bool(
|
||||
lines.filtered(lambda line: line.product_uom_allowed_max_qty > 0.0)
|
||||
)
|
||||
|
||||
def confirm(self):
|
||||
"""Confirm the sale orders ignoring next possible wizards."""
|
||||
if not all(self.mapped("confirmation_allowed")):
|
||||
raise exceptions.UserError(
|
||||
_("You are not allowed to confirm these orders.")
|
||||
)
|
||||
orders = self.mapped("sale_line_block_ids.order_id")
|
||||
orders.message_post(
|
||||
body=_("Order confirmed with errors by %s.", self.env.user.name),
|
||||
subtype_id=self.env.ref("mail.mt_note").id,
|
||||
)
|
||||
return orders.with_context(skip_block_no_stock_check=True).action_confirm()
|
||||
|
||||
def action_adjust_uom_quantity(self):
|
||||
"""Adjust the quantity of the sale lines to the maximum allowed by the
|
||||
UoM."""
|
||||
return self.sale_line_block_ids._action_adjust_uom_quantity()
|
||||
|
||||
def action_adjust_packaging_quantity(self):
|
||||
"""Adjust the quantity of the sale lines to the maximum allowed by the
|
||||
packaging."""
|
||||
return self.sale_line_block_ids._action_adjust_packaging_quantity()
|
||||
|
||||
def action_move_to_new_order(self):
|
||||
"""Move the sale lines to a new sale order."""
|
||||
return self.sale_line_block_ids._action_move_to_new_order()
|
||||
|
||||
@api.constrains("sale_line_block_ids")
|
||||
def _check_sale_line_block_ids(self):
|
||||
"""Check that all sale lines are from the same company."""
|
||||
for record in self:
|
||||
companies = record.mapped(
|
||||
"sale_line_block_ids.sale_line_id.order_id.company_id"
|
||||
)
|
||||
if len(companies) > 1:
|
||||
raise exceptions.UserError(
|
||||
_(
|
||||
"""Cannot launch wizard from sale orders
|
||||
from different companies."""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SaleOrderBlockWizardLine(models.TransientModel):
|
||||
_name = "sale.order.block.wizard.line"
|
||||
_description = "Sale Order Block Wizard Line"
|
||||
_transient_max_hours = 0.25 # 15 minutes until destroyed
|
||||
|
||||
wizard_id = fields.Many2one(
|
||||
comodel_name="sale.order.block.wizard",
|
||||
string="Wizard",
|
||||
required=True,
|
||||
)
|
||||
sale_line_id = fields.Many2one(
|
||||
comodel_name="sale.order.line",
|
||||
string="Sale Line",
|
||||
required=True,
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
related="sale_line_id.order_id.company_id",
|
||||
string="Company",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
order_id = fields.Many2one(
|
||||
related="sale_line_id.order_id",
|
||||
string="Sale Order",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
related="sale_line_id.product_id",
|
||||
string="Product",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
product_uom_qty = fields.Float(
|
||||
related="sale_line_id.product_uom_qty",
|
||||
string="Qty. (UoM)",
|
||||
readonly=True,
|
||||
)
|
||||
product_uom = fields.Many2one(
|
||||
related="sale_line_id.product_uom",
|
||||
string="UoM",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
product_uom_allowed_max_qty = fields.Float(
|
||||
string="Max. Qty. (UoM)",
|
||||
compute="_compute_allowed_max_qty",
|
||||
readonly=True,
|
||||
store=True,
|
||||
compute_sudo=True,
|
||||
)
|
||||
product_packaging_qty = fields.Float(
|
||||
related="sale_line_id.product_packaging_qty",
|
||||
string="Qty. (Pkg.)",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
product_packaging_id = fields.Many2one(
|
||||
related="sale_line_id.product_packaging_id",
|
||||
string="Packaging",
|
||||
readonly=True,
|
||||
store=True,
|
||||
)
|
||||
product_packaging_allowed_max_qty = fields.Float(
|
||||
string="Max. Qty. (Pkg.)",
|
||||
compute="_compute_allowed_max_qty",
|
||||
readonly=True,
|
||||
store=True,
|
||||
compute_sudo=True,
|
||||
)
|
||||
|
||||
@api.depends("sale_line_id", "product_uom_qty", "company_id.sale_line_field_block")
|
||||
def _compute_allowed_max_qty(self):
|
||||
"""Compute the maximum allowed quantity by UoM and Packaging of
|
||||
storable products."""
|
||||
self.product_uom_allowed_max_qty = 0.0
|
||||
self.product_packaging_allowed_max_qty = 0.0
|
||||
for record in self:
|
||||
field_to_check = record.company_id.sale_line_field_block
|
||||
if not field_to_check:
|
||||
self.env.cr.postcommit.add(record.unlink)
|
||||
continue
|
||||
if (
|
||||
record.sale_line_id.product_type != "consu"
|
||||
and record.sale_line_id.product_id.is_storable
|
||||
):
|
||||
self.env.cr.postcommit.add(record.unlink)
|
||||
continue
|
||||
allowed_max_qty = record.sale_line_id[field_to_check.name]
|
||||
if (
|
||||
allowed_max_qty > 0
|
||||
and record.sale_line_id.product_uom_qty <= allowed_max_qty
|
||||
):
|
||||
self.env.cr.postcommit.add(record.unlink)
|
||||
continue
|
||||
record.product_uom_allowed_max_qty = allowed_max_qty
|
||||
if record.product_packaging_id:
|
||||
record.product_packaging_allowed_max_qty = (
|
||||
allowed_max_qty // record.product_packaging_id.qty
|
||||
)
|
||||
|
||||
def _get_adjustable_records(self, packaging=False):
|
||||
"""Return the records that can be adjusted by UoM or Packaging."""
|
||||
if packaging:
|
||||
return self.filtered(
|
||||
lambda r: r.product_packaging_allowed_max_qty > 0.0
|
||||
and r.product_packaging_qty > r.product_packaging_allowed_max_qty
|
||||
)
|
||||
return self.filtered(
|
||||
lambda r: r.product_uom_allowed_max_qty > 0.0
|
||||
and r.product_uom_qty > r.product_uom_allowed_max_qty
|
||||
)
|
||||
|
||||
def _get_reopen_action(self):
|
||||
"""Return the action to reopen the wizard."""
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
"sale_block_no_stock.sale_order_block_wizard_action"
|
||||
)
|
||||
action["context"] = {
|
||||
"default_sale_line_block_ids": [
|
||||
(0, 0, {"sale_line_id": line.id})
|
||||
for line in self.mapped("sale_line_id")
|
||||
]
|
||||
}
|
||||
return action
|
||||
|
||||
def _action_move_to_new_order(self):
|
||||
"""Move the sale lines to a new sale order."""
|
||||
mt_note_id = self.env.ref("mail.mt_note").id
|
||||
partner_id = self.env.user.partner_id.id
|
||||
new_orders = self.env["sale.order"].browse()
|
||||
for order, records in groupby(self, lambda r: r.order_id):
|
||||
new_order = order.copy(default={"order_line": None})
|
||||
new_order.message_post_with_source(
|
||||
"mail.message_origin_link",
|
||||
render_values={"self": new_order, "origin": order, "edit": True},
|
||||
subtype_id=mt_note_id,
|
||||
author_id=partner_id,
|
||||
)
|
||||
order.message_post_with_source(
|
||||
"mail_message_destiny_link_template.message_destiny_link",
|
||||
render_values={"self": order, "destiny": new_order, "edit": False},
|
||||
subtype_id=mt_note_id,
|
||||
author_id=partner_id,
|
||||
)
|
||||
for record in records:
|
||||
record.sale_line_id.write({"order_id": new_order.id})
|
||||
new_orders |= new_order
|
||||
return new_orders
|
||||
|
||||
@api.model
|
||||
def _get_adjusted_message(self, product, init_qty, final_qty, uom):
|
||||
message = Markup(
|
||||
"""
|
||||
Product <b>%(product)s</b> adjusted from
|
||||
<b>%(init_qty)s</b> %(uom)s to <b>%(final_qty)s</b> %(uom)s.
|
||||
"""
|
||||
) % {
|
||||
"product": product,
|
||||
"init_qty": init_qty,
|
||||
"final_qty": final_qty,
|
||||
"uom": uom,
|
||||
}
|
||||
return message
|
||||
|
||||
def _action_adjust_uom_quantity(self):
|
||||
"""Adjust the quantity of the sale lines to the maximum allowed by the
|
||||
UoM."""
|
||||
mt_note_id = self.env.ref("mail.mt_note").id
|
||||
adjustable_records = self._get_adjustable_records()
|
||||
for record in adjustable_records:
|
||||
record.sale_line_id.order_id.message_post(
|
||||
body=self._get_adjusted_message(
|
||||
product=record.product_id.display_name,
|
||||
init_qty=record.product_uom_qty,
|
||||
final_qty=record.product_uom_allowed_max_qty,
|
||||
uom=record.product_uom.name,
|
||||
),
|
||||
subtype_id=mt_note_id,
|
||||
)
|
||||
record.sale_line_id.product_uom_qty = record.product_uom_allowed_max_qty
|
||||
if not self - adjustable_records:
|
||||
return
|
||||
return (self - adjustable_records)._get_reopen_action()
|
||||
|
||||
def _action_adjust_packaging_quantity(self):
|
||||
"""Adjust the quantity of the sale lines to the maximum allowed by the
|
||||
packaging."""
|
||||
mt_note_id = self.env.ref("mail.mt_note").id
|
||||
adjustable_records = self._get_adjustable_records(packaging=True)
|
||||
for record in adjustable_records:
|
||||
record.sale_line_id.order_id.message_post(
|
||||
body=self._get_adjusted_message(
|
||||
product=record.product_id.display_name,
|
||||
init_qty=record.product_packaging_qty,
|
||||
final_qty=record.product_packaging_allowed_max_qty,
|
||||
uom=record.product_packaging_id.display_name,
|
||||
),
|
||||
subtype_id=mt_note_id,
|
||||
)
|
||||
record.sale_line_id.product_packaging_qty = (
|
||||
record.product_packaging_allowed_max_qty
|
||||
)
|
||||
record.sale_line_id.product_uom_qty = (
|
||||
record.product_packaging_id.qty
|
||||
* record.product_packaging_allowed_max_qty
|
||||
)
|
||||
if not self - adjustable_records:
|
||||
return
|
||||
return (self - adjustable_records)._get_reopen_action()
|
||||
108
sale_block_no_stock/wizard/sale_order_block_wizard_views.xml
Executable file
108
sale_block_no_stock/wizard/sale_order_block_wizard_views.xml
Executable file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="sale_order_block_wizard_view" model="ir.ui.view">
|
||||
<field name="name">Sale Order Block</field>
|
||||
<field name="model">sale.order.block.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Sale Order Block">
|
||||
<field name="confirmation_allowed" invisible="1" />
|
||||
<field name="is_uom_adjustable" invisible="1" />
|
||||
<field name="is_packaging_adjustable" invisible="1" />
|
||||
<p class="text-muted">
|
||||
This order cannot be confirmed because it contains products that are not in stock. Please manage the following products before confirming the order.
|
||||
</p>
|
||||
<group
|
||||
name="blocked_lines_group"
|
||||
staction_create_sale_orderring="Blocked lines"
|
||||
>
|
||||
<field name="sale_line_block_ids" nolabel="1" colspan="2">
|
||||
<list
|
||||
decoration-danger="product_uom_allowed_max_qty <= 0.0"
|
||||
create="false"
|
||||
edit="false"
|
||||
no_open="true"
|
||||
>
|
||||
<field name="wizard_id" column_invisible="1" />
|
||||
<field name="sale_line_id" column_invisible="1" />
|
||||
<field name="company_id" column_invisible="1" />
|
||||
<field name="order_id" optional="hide" />
|
||||
<field name="product_id" />
|
||||
<field name="product_uom_qty" optional="show" />
|
||||
<field name="product_uom_allowed_max_qty" optional="show" />
|
||||
<field name="product_uom" optional="show" />
|
||||
<field
|
||||
name="product_packaging_qty"
|
||||
optional="show"
|
||||
invisible="not product_packaging_id"
|
||||
groups="product.group_stock_packaging"
|
||||
/>
|
||||
<field
|
||||
name="product_packaging_allowed_max_qty"
|
||||
optional="show"
|
||||
invisible="not product_packaging_id"
|
||||
groups="product.group_stock_packaging"
|
||||
/>
|
||||
<field
|
||||
name="product_packaging_id"
|
||||
optional="show"
|
||||
invisible="not product_packaging_id"
|
||||
groups="product.group_stock_packaging"
|
||||
/>
|
||||
</list>
|
||||
</field>
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
name="action_adjust_uom_quantity"
|
||||
string="Adjust UoM Quantity"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="not is_uom_adjustable or is_packaging_adjustable or not sale_line_block_ids"
|
||||
/>
|
||||
<button
|
||||
name="action_adjust_packaging_quantity"
|
||||
string="Adjust Packaging Quantity"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="not(is_packaging_adjustable and sale_line_block_ids)"
|
||||
groups="product.group_stock_packaging"
|
||||
/>
|
||||
<button
|
||||
name="action_move_to_new_order"
|
||||
string="Move to New Order"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="is_uom_adjustable or not sale_line_block_ids"
|
||||
confirm="You are going to move pending lines to a new order"
|
||||
/>
|
||||
<button
|
||||
name="action_move_to_new_order"
|
||||
string="Move to New Order"
|
||||
type="object"
|
||||
class="btn-secondary"
|
||||
invisible="not(is_uom_adjustable and sale_line_block_ids)"
|
||||
confirm="You are going to move pending lines to a new order"
|
||||
/>
|
||||
<button
|
||||
name="confirm"
|
||||
string="Confirm anyway"
|
||||
type="object"
|
||||
class="btn-secondary"
|
||||
invisible="not(confirmation_allowed and sale_line_block_ids)"
|
||||
confirm="You are going to confirm the Sale Order with not solved lines"
|
||||
/>
|
||||
<p class="m-2">or</p>
|
||||
<button string="Close" class="btn-secondary" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_block_wizard_action" model="ir.actions.act_window">
|
||||
<field name="name">Sale Order Blocked to Confirm</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">sale.order.block.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user