mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
1
setup/stock_reserve_sale/odoo/addons/stock_reserve_sale
Symbolic link
1
setup/stock_reserve_sale/odoo/addons/stock_reserve_sale
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../stock_reserve_sale
|
||||
6
setup/stock_reserve_sale/setup.py
Normal file
6
setup/stock_reserve_sale/setup.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
||||
114
stock_reserve_sale/README.rst
Normal file
114
stock_reserve_sale/README.rst
Normal file
@@ -0,0 +1,114 @@
|
||||
===================
|
||||
Stock Reserve Sales
|
||||
===================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
|
||||
:target: https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_reserve_sale
|
||||
:alt: OCA/stock-logistics-warehouse
|
||||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
|
||||
:target: https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_reserve_sale
|
||||
:alt: Translate me on Weblate
|
||||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
|
||||
:target: https://runbot.odoo-community.org/runbot/153/13.0
|
||||
:alt: Try me on Runbot
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4| |badge5|
|
||||
|
||||
Allows to create stock reservations for quotation lines before the
|
||||
confirmation of the quotation. The reservations might have a validity
|
||||
date and in any case they are lifted when the quotation is canceled or
|
||||
confirmed.
|
||||
|
||||
Reservations can be done only on "make to stock" and stockable products.
|
||||
|
||||
The reserved products are subtracted from the virtual stock. It means
|
||||
that if you reserved a quantity of products which bring the virtual
|
||||
stock below the minimum, the orderpoint will be triggered and new
|
||||
purchase orders will be generated. It also implies that the max may be
|
||||
exceeded if the reservations are canceled.
|
||||
|
||||
If you want to prevent sales orders to be confirmed when the stock is
|
||||
insufficient at the order date, you may want to install the
|
||||
`sale_exception_nostock` module.
|
||||
|
||||
Additionally, if the sale_owner_stock_sourcing module is installed, the owner
|
||||
specified on the sale order line will be proposed as owner of the reservation.
|
||||
If you try to make a reservation for an order whose lines have different, you
|
||||
will get a message suggesting to reserve each line individually. There is no
|
||||
module dependency: this modules is fully functional even without ownership
|
||||
management.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
#. Create a new Sale Order
|
||||
#. Add lines to the Order
|
||||
|
||||
Now you can reserve all the lines by clicking on *Reserve Stock* or you can reserve each
|
||||
one by pressing on the lock icon at the lines.
|
||||
|
||||
Once they where reserved, you can release the reserves by clicking at *Cancell all*
|
||||
button or by clicking the undo icon on the lines.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-warehouse/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_reserve_sale%0Aversion:%2013.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
|
||||
~~~~~~~
|
||||
|
||||
* Camptocamp
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Leonardo Pistone <leonardo.pistone@camptocamp.com>
|
||||
* Alexandre Fayolle <alexandre.fayolle@camptocamp.com>
|
||||
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||
|
||||
* `Tecnativa <https://www.tecnativa.com>`_:
|
||||
|
||||
* Carlos Roca
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.
|
||||
|
||||
This module is part of the `OCA/stock-logistics-warehouse <https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_reserve_sale>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
4
stock_reserve_sale/__init__.py
Normal file
4
stock_reserve_sale/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import model
|
||||
from . import wizard
|
||||
19
stock_reserve_sale/__manifest__.py
Normal file
19
stock_reserve_sale/__manifest__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
{
|
||||
"name": "Stock Reserve Sales",
|
||||
"version": "13.0.1.0.0",
|
||||
"author": "Camptocamp, Odoo Community Association (OCA)",
|
||||
"category": "Warehouse",
|
||||
"license": "AGPL-3",
|
||||
"complexity": "normal",
|
||||
"website": "https://github.com/stock-logistics-warehouse",
|
||||
"depends": ["sale_stock", "stock_reserve"],
|
||||
"data": [
|
||||
"wizard/sale_stock_reserve_view.xml",
|
||||
"view/sale.xml",
|
||||
"view/stock_reserve.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"auto_install": False,
|
||||
}
|
||||
237
stock_reserve_sale/i18n/es.po
Normal file
237
stock_reserve_sale/i18n/es.po
Normal file
@@ -0,0 +1,237 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_reserve_sale
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-07-27 07:47+0000\n"
|
||||
"PO-Revision-Date: 2021-07-27 09:58+0200\n"
|
||||
"Last-Translator: Carlos <carlos.roca@tecnativa.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/oca/OCA-stock-logistics-"
|
||||
"warehouse-8-0/language/es/)\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 2.0.6\n"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid ""
|
||||
"A stock reservation will be created for the products\n"
|
||||
" of the selected quotation lines. If a validity date is "
|
||||
"specified,\n"
|
||||
" the reservation will be released once the date has "
|
||||
"passed."
|
||||
msgstr ""
|
||||
"Una reserva de stock va a ser creada para los productos\n"
|
||||
" de la orden de venta seleccionada. Si una fecha de "
|
||||
"validez está\n"
|
||||
"\t\t especificada, la reserva va a ser liberada cuando la fecha pase."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__is_stock_reservable
|
||||
msgid "Can Have Stock Reservations"
|
||||
msgstr "Puede tener reservas de stock"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__is_stock_reservable
|
||||
msgid "Can be reserved"
|
||||
msgstr "Puede ser reservado"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Cancell all"
|
||||
msgstr "Cancelar todo"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_uid
|
||||
msgid "Created by"
|
||||
msgstr "Creado por"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_date
|
||||
msgid "Created on"
|
||||
msgstr "Creado el"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nombre mostrado"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__has_stock_reservation
|
||||
msgid "Has Stock Reservations"
|
||||
msgstr "Tiene reservas de stock"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__id
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__date_validity
|
||||
msgid ""
|
||||
"If a date is given, the reservations will be released at the end of the "
|
||||
"validity."
|
||||
msgstr ""
|
||||
"Si la fecha de validez está asignada, la reserva va a ser liberada al final "
|
||||
"de esta."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Última modificación el"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr "Actualizado por última vez por"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr "Actualizado por última vez el"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
|
||||
msgid "Location where the system will reserve the products."
|
||||
msgstr "Localización donde el sistema va a reservar los productos."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__note
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Notes"
|
||||
msgstr "Notas"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Pre-book products from stock"
|
||||
msgstr "Pre-reservar productos en stock"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Release Reservation"
|
||||
msgstr "Liberar"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
|
||||
msgid "Reservation Location"
|
||||
msgstr "Localización de la reserva"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve"
|
||||
msgstr "Reservar"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve Stock"
|
||||
msgstr "Reservar stock"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
|
||||
msgid "Reserve Stock for Quotation Lines"
|
||||
msgstr "Reservar stock para las lineas del pedido"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_id
|
||||
msgid "Sale Order"
|
||||
msgstr "Pedido de venta"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_line_id
|
||||
msgid "Sale Order Line"
|
||||
msgstr "Linea de venta"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_stock_reservation_form
|
||||
msgid "Sales"
|
||||
msgstr "Ventas"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Pedido"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
|
||||
msgid "Sales Order Line"
|
||||
msgstr "Líneas de pedidos de venta"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Several stock reservations are linked with the line. Impossible to adjust "
|
||||
"their quantity. Please release the reservation before changing the quantity."
|
||||
msgstr ""
|
||||
"Algunas reservas de stock están asociadas a la linea. Imposible ajustar la "
|
||||
"cantidad. Por favor, libera la reserva antes de cambiar la cantidad."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_id
|
||||
msgid "Source Location"
|
||||
msgstr "Ubicación origen"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__owner_id
|
||||
msgid "Stock Owner"
|
||||
msgstr "Propietario"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__reservation_ids
|
||||
msgid "Stock Reservation"
|
||||
msgstr "Reserva de existencias"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/wizard/sale_stock_reserve.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The lines have different owners. Please reserve them\n"
|
||||
" individually with the reserve button on each one."
|
||||
msgstr ""
|
||||
"Las lineas tienen distintos propietarios. Por favor, reservalas\n"
|
||||
" individualmente con el botón de reserva de cada una."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__date_validity
|
||||
msgid "Validity Date"
|
||||
msgstr "Fecha de validez"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You cannot change the product or unit of measure of lines with a stock "
|
||||
"reservation. Release the reservation before changing the product."
|
||||
msgstr ""
|
||||
"No puedes cambiar el producto o la unidad de medida de las lineas con una "
|
||||
"reserva de stock. Libera la reserva antes de cambiar el producto."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "or"
|
||||
msgstr "o"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_stock_reserve
|
||||
msgid "sale.stock.reserve"
|
||||
msgstr ""
|
||||
211
stock_reserve_sale/i18n/fi.po
Normal file
211
stock_reserve_sale/i18n/fi.po
Normal file
@@ -0,0 +1,211 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_reserve_sale
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-04-23 15:55+0000\n"
|
||||
"PO-Revision-Date: 2015-04-23 20:35+0200\n"
|
||||
"Last-Translator: Miku Laitinen <miku.laitinen@ninjaware.fi>\n"
|
||||
"Language-Team: Avoin.Systems <miku@avoin.systems>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"Language: Finnish\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid ""
|
||||
"A stock reservation will be created for the products\n"
|
||||
" of the selected quotation lines. If a validity date "
|
||||
"is specified,\n"
|
||||
" the reservation will be released once the date has "
|
||||
"passed."
|
||||
msgstr ""
|
||||
"Tuotevaraus luodaan valittujen rivien tuotteille.\n"
|
||||
"Jos vapautuspäivä on määritetty, varaus peruutetaan automaattisesti "
|
||||
"kyseisenä päivänä."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:179
|
||||
#, python-format
|
||||
msgid ""
|
||||
"As you changed the quantity of the line, the quantity of the stock "
|
||||
"reservation will be automatically adjusted to %.2f."
|
||||
msgstr ""
|
||||
"Muuttaessasi rivin kappalemäärää, tuotevarauksen kappalemäärä päivitetään "
|
||||
"automaattisesti arvoon %.2f."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.order,is_stock_reservable:0
|
||||
msgid "Can Have Stock Reservations"
|
||||
msgstr "Voi sisältää tuotevarauksia"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Cancel"
|
||||
msgstr "Peruuta"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:188
|
||||
#, python-format
|
||||
msgid "Configuration Error!"
|
||||
msgstr "Konfiguraatiovirhe."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr "Luonut"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr "Luotu"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:210
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:222
|
||||
#, python-format
|
||||
msgid "Error"
|
||||
msgstr "Virhe"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.order,has_stock_reservation:0
|
||||
msgid "Has Stock Reservations"
|
||||
msgstr "Sisältää tuotevarauksia"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,id:0
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: help:sale.stock.reserve,date_validity:0
|
||||
msgid ""
|
||||
"If a date is given, the reservations will be released at the end of the "
|
||||
"validity."
|
||||
msgstr ""
|
||||
"Jos vapautuspäivä on määritetty, varaukset perutaan kyseisenä päivänä "
|
||||
"automaattisesti."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr "Viimeksi päivittänyt"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr "Viimeksi päivitetty"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: help:sale.stock.reserve,location_dest_id:0
|
||||
msgid "Location where the system will reserve the products."
|
||||
msgstr "Sijainti, jonne tuotteet varataan."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
#: field:sale.stock.reserve,note:0
|
||||
msgid "Notes"
|
||||
msgstr "Huomautukset"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Pre-book products from stock"
|
||||
msgstr "Varaa tuotteita varastosta"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Release Reservation"
|
||||
msgstr "Peru varaus"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,location_dest_id:0
|
||||
msgid "Reservation Location"
|
||||
msgstr "Varauspaikka"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve"
|
||||
msgstr "Varaa"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve Stock"
|
||||
msgstr "Varaa tuotteet"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
|
||||
msgid "Reserve Stock for Quotation Lines"
|
||||
msgstr "Rivien tuotteiden varaus"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:stock.reservation,sale_line_id:0
|
||||
msgid "Sale Order Line"
|
||||
msgstr "Myyntitilausrivi"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
|
||||
msgid "Sales"
|
||||
msgstr "Myynti"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr "Myyntitilaus"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
|
||||
msgid "Sales Order Line"
|
||||
msgstr "Myyntitilausrivi"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:223
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Several stock reservations are linked with the line. Impossible to adjust "
|
||||
"their quantity. Please release the reservation before changing the quantity."
|
||||
msgstr ""
|
||||
"Riviin on linkitetty useita tuotevarauksia. Kappalemäärien muokkaaminen ei "
|
||||
"ole mahdollista. Ole hyvä ja peruuta varaus ennen määrien muokkaamista."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,location_id:0
|
||||
msgid "Source Location"
|
||||
msgstr "Lähtöpaikka"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
|
||||
#: field:sale.order.line,reservation_ids:0
|
||||
msgid "Stock Reservation"
|
||||
msgstr "Tuotevaraus"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,date_validity:0
|
||||
msgid "Validity Date"
|
||||
msgstr "Vapautuspäivä"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:211
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You cannot change the product or unit of measure of lines with a stock "
|
||||
"reservation. Release the reservation before changing the product."
|
||||
msgstr ""
|
||||
"Et voi vaihtaa tuotetta tai tuotteen yksikköä, jos rivillä on tuotevaraus. "
|
||||
"Peruuta varaus ennen tuotteen vaihtamista."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "cancel all"
|
||||
msgstr "peru kaikki"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "{\"reload_on_button\": 1}"
|
||||
msgstr "{\"reload_on_button\": 1}"
|
||||
209
stock_reserve_sale/i18n/fr.po
Normal file
209
stock_reserve_sale/i18n/fr.po
Normal file
@@ -0,0 +1,209 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_reserve_sale
|
||||
#
|
||||
# Translators:
|
||||
# Pierre Verkest <pverkest@anybox.fr>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: stock-logistics-warehouse (8.0)\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-09-23 20:23+0000\n"
|
||||
"PO-Revision-Date: 2015-09-27 21:09+0000\n"
|
||||
"Last-Translator: Pierre Verkest <pverkest@anybox.fr>\n"
|
||||
"Language-Team: French (http://www.transifex.com/oca/OCA-stock-logistics-warehouse-8-0/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid ""
|
||||
"A stock reservation will be created for the products\n"
|
||||
" of the selected quotation lines. If a validity date is specified,\n"
|
||||
" the reservation will be released once the date has passed."
|
||||
msgstr "Une réservation de stock sera créée pour les produits\ndes lignes de devis sélectionnées. Si une date de validité est\nspécifiée, la réservation sera annulée une fois cette date dépassée."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:179
|
||||
#, python-format
|
||||
msgid ""
|
||||
"As you changed the quantity of the line, the quantity of the stock "
|
||||
"reservation will be automatically adjusted to %.2f."
|
||||
msgstr "Suite au changement de quantité de la ligne, la quantité de stock réservée va être ajusté à %.2f."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.order,is_stock_reservable:0
|
||||
msgid "Can Have Stock Reservations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:188
|
||||
#, python-format
|
||||
msgid "Configuration Error!"
|
||||
msgstr "Erreur de configuration!"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:210
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:222
|
||||
#, python-format
|
||||
msgid "Error"
|
||||
msgstr "Erreur"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.order,has_stock_reservation:0
|
||||
msgid "Has Stock Reservations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,id:0
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: help:sale.stock.reserve,date_validity:0
|
||||
msgid ""
|
||||
"If a date is given, the reservations will be released at the end of the "
|
||||
"validity."
|
||||
msgstr "Si une date est donnée, la réservation sera annulée à la fin de cette date de validité."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr "Dernière màj par"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr "Dernière màj le"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: help:sale.stock.reserve,location_dest_id:0
|
||||
msgid "Location where the system will reserve the products."
|
||||
msgstr "Emplacement de stock où sont réservés les produits (pour le système)."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
#: field:sale.stock.reserve,note:0
|
||||
msgid "Notes"
|
||||
msgstr "Notes"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Pre-book products from stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Release Reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,location_dest_id:0
|
||||
msgid "Reservation Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve"
|
||||
msgstr "Réserver"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve Stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
|
||||
msgid "Reserve Stock for Quotation Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:stock.reservation,sale_line_id:0
|
||||
msgid "Sale Order Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:stock.reservation:stock_reserve_sale.view_stock_reservation_form
|
||||
msgid "Sales"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
|
||||
msgid "Sales Order Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:223
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Several stock reservations are linked with the line. Impossible to adjust "
|
||||
"their quantity. Please release the reservation before changing the quantity."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,location_id:0
|
||||
msgid "Source Location"
|
||||
msgstr "Emplacement Source"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,owner_id:0
|
||||
msgid "Stock Owner"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
|
||||
#: field:sale.order.line,reservation_ids:0
|
||||
msgid "Stock Reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: field:sale.stock.reserve,date_validity:0
|
||||
msgid "Validity Date"
|
||||
msgstr "Date de validité"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:211
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You cannot change the product or unit of measure of lines with a stock "
|
||||
"reservation. Release the reservation before changing the product."
|
||||
msgstr "Vous ne pouvez pas modifier le produit ou l'unité de mesure des lignes avec une réservation en stock. Veuillez annuler les réservations avant de modifier la ligne."
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "cancel all"
|
||||
msgstr "tout annuler"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.stock.reserve:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "or"
|
||||
msgstr "ou"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: view:sale.order:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "{\"reload_on_button\": 1}"
|
||||
msgstr ""
|
||||
220
stock_reserve_sale/i18n/stock_reserve_sale.pot
Normal file
220
stock_reserve_sale/i18n/stock_reserve_sale.pot
Normal file
@@ -0,0 +1,220 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * stock_reserve_sale
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 13.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-07-27 07:47+0000\n"
|
||||
"PO-Revision-Date: 2021-07-27 07:47+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid ""
|
||||
"A stock reservation will be created for the products\n"
|
||||
" of the selected quotation lines. If a validity date is specified,\n"
|
||||
" the reservation will be released once the date has passed."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__is_stock_reservable
|
||||
msgid "Can Have Stock Reservations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__is_stock_reservable
|
||||
msgid "Can be reserved"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Cancell all"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order__has_stock_reservation
|
||||
msgid "Has Stock Reservations"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__date_validity
|
||||
msgid ""
|
||||
"If a date is given, the reservations will be released at the end of the "
|
||||
"validity."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,help:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
|
||||
msgid "Location where the system will reserve the products."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__note
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Pre-book products from stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
msgid "Release Reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_dest_id
|
||||
msgid "Reservation Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_order_form_reserve
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "Reserve Stock"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.actions.act_window,name:stock_reserve_sale.action_sale_stock_reserve
|
||||
msgid "Reserve Stock for Quotation Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_id
|
||||
msgid "Sale Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_stock_reservation__sale_line_id
|
||||
msgid "Sale Order Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_stock_reservation_form
|
||||
msgid "Sales"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order
|
||||
msgid "Sales Order"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_order_line
|
||||
msgid "Sales Order Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Several stock reservations are linked with the line. Impossible to adjust "
|
||||
"their quantity. Please release the reservation before changing the quantity."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__location_id
|
||||
msgid "Source Location"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__owner_id
|
||||
msgid "Stock Owner"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_stock_reservation
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_order_line__reservation_ids
|
||||
msgid "Stock Reservation"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/wizard/sale_stock_reserve.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The lines have different owners. Please reserve them\n"
|
||||
" individually with the reserve button on each one."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model.fields,field_description:stock_reserve_sale.field_sale_stock_reserve__date_validity
|
||||
msgid "Validity Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: code:addons/stock_reserve_sale/model/sale.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You cannot change the product or unit of measure of lines with a stock "
|
||||
"reservation. Release the reservation before changing the product."
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model_terms:ir.ui.view,arch_db:stock_reserve_sale.view_sale_stock_reserve_form
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#. module: stock_reserve_sale
|
||||
#: model:ir.model,name:stock_reserve_sale.model_sale_stock_reserve
|
||||
msgid "sale.stock.reserve"
|
||||
msgstr ""
|
||||
4
stock_reserve_sale/model/__init__.py
Normal file
4
stock_reserve_sale/model/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import sale
|
||||
from . import stock_reserve
|
||||
245
stock_reserve_sale/model/sale.py
Normal file
245
stock_reserve_sale/model/sale.py
Normal file
@@ -0,0 +1,245 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError, except_orm
|
||||
from odoo.tools.translate import _
|
||||
|
||||
_LINE_KEYS = ["product_id", "product_uom_qty"]
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
@api.depends(
|
||||
"state", "order_line.reservation_ids", "order_line.is_stock_reservable"
|
||||
)
|
||||
def _compute_stock_reservation(self):
|
||||
for sale in self:
|
||||
has_stock_reservation = False
|
||||
is_stock_reservable = False
|
||||
for line in sale.order_line:
|
||||
if line.reservation_ids:
|
||||
has_stock_reservation = True
|
||||
if line.is_stock_reservable:
|
||||
is_stock_reservable = True
|
||||
if sale.state not in ("draft", "sent"):
|
||||
is_stock_reservable = False
|
||||
sale.is_stock_reservable = is_stock_reservable
|
||||
sale.has_stock_reservation = has_stock_reservation
|
||||
|
||||
has_stock_reservation = fields.Boolean(
|
||||
compute="_compute_stock_reservation",
|
||||
readonly=True,
|
||||
multi="stock_reservation",
|
||||
store=True,
|
||||
string="Has Stock Reservations",
|
||||
)
|
||||
is_stock_reservable = fields.Boolean(
|
||||
compute="_compute_stock_reservation",
|
||||
readonly=True,
|
||||
multi="stock_reservation",
|
||||
store=True,
|
||||
string="Can Have Stock Reservations",
|
||||
)
|
||||
|
||||
def release_all_stock_reservation(self):
|
||||
line_ids = [line.id for order in self for line in order.order_line]
|
||||
lines = self.env["sale.order.line"].browse(line_ids)
|
||||
lines.release_stock_reservation()
|
||||
return True
|
||||
|
||||
def action_confirm(self):
|
||||
self.release_all_stock_reservation()
|
||||
return super().action_confirm()
|
||||
|
||||
def action_cancel(self):
|
||||
self.release_all_stock_reservation()
|
||||
return super().action_cancel()
|
||||
|
||||
def write(self, vals):
|
||||
old_lines = self.mapped("order_line")
|
||||
dict_old_lines = {}
|
||||
for line in old_lines:
|
||||
dict_old_lines[line.id] = {
|
||||
"product_id": line.product_id,
|
||||
"product_uom_qty": line.product_uom_qty,
|
||||
}
|
||||
res = super().write(vals)
|
||||
for order in self:
|
||||
body = ""
|
||||
for line in vals.get("order_line", []):
|
||||
if line[0] == 1 and list(set(line[2].keys()).intersection(_LINE_KEYS)):
|
||||
body += order.get_message(dict_old_lines.get(line[1]), line[2])
|
||||
if body != "":
|
||||
order.message_post(body=body)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def get_message(self, old_vals, new_vals):
|
||||
ProductProduct = self.env["product.product"]
|
||||
body = _("<p>Modified Order line data</p>")
|
||||
if "product_id" in new_vals:
|
||||
old_product = old_vals["product_id"].display_name
|
||||
new_product = ProductProduct.browse(new_vals["product_id"]).display_name
|
||||
body += _("<div> <b>Product</b>: ")
|
||||
body += "{} → {}</div>".format(old_product, new_product)
|
||||
if "product_uom_qty" in new_vals:
|
||||
if "product_id" not in new_vals:
|
||||
body += _("<div> <b>Product</b>: %s") % (
|
||||
old_vals["product_id"].display_name
|
||||
)
|
||||
body += _("<div> <b>Product qty.</b>: ")
|
||||
body += "{} → {}</div>".format(
|
||||
old_vals["product_uom_qty"], float(new_vals["product_uom_qty"]),
|
||||
)
|
||||
body += "<br/>"
|
||||
return body
|
||||
|
||||
def unlink(self):
|
||||
for order in self:
|
||||
if order.has_stock_reservation:
|
||||
raise UserError(
|
||||
_(
|
||||
"Sale Order %s has some reserved lines.\n"
|
||||
"Please unreserve this lines before delete the order."
|
||||
)
|
||||
% (order.name)
|
||||
)
|
||||
return super().unlink()
|
||||
|
||||
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
def _get_line_rule(self):
|
||||
""" Get applicable rule for this product
|
||||
|
||||
Reproduce get suitable rule from procurement
|
||||
to predict source location """
|
||||
StockRule = self.env["stock.rule"]
|
||||
product = self.product_id
|
||||
product_route_ids = [
|
||||
x.id for x in product.route_ids + product.categ_id.total_route_ids
|
||||
]
|
||||
rules = StockRule.search(
|
||||
[("route_id", "in", product_route_ids)],
|
||||
order="route_sequence, sequence",
|
||||
limit=1,
|
||||
)
|
||||
|
||||
if not rules:
|
||||
warehouse = self.order_id.warehouse_id
|
||||
wh_routes = warehouse.route_ids
|
||||
wh_route_ids = [route.id for route in wh_routes]
|
||||
domain = [
|
||||
"|",
|
||||
("warehouse_id", "=", warehouse.id),
|
||||
("warehouse_id", "=", False),
|
||||
("route_id", "in", wh_route_ids),
|
||||
]
|
||||
|
||||
rules = StockRule.search(domain, order="route_sequence, sequence")
|
||||
|
||||
if rules:
|
||||
fields.first(rules)
|
||||
return False
|
||||
|
||||
def _get_procure_method(self):
|
||||
""" Get procure_method depending on product routes """
|
||||
rule = self._get_line_rule()
|
||||
if rule:
|
||||
return rule.procure_method
|
||||
return False
|
||||
|
||||
@api.depends("state", "product_id.route_ids", "product_id.type")
|
||||
def _compute_is_stock_reservable(self):
|
||||
for line in self:
|
||||
reservable = False
|
||||
if (
|
||||
not (
|
||||
line.state != "draft"
|
||||
or line._get_procure_method() == "make_to_order"
|
||||
or not line.product_id
|
||||
or line.product_id.type == "service"
|
||||
)
|
||||
and not line.reservation_ids
|
||||
):
|
||||
reservable = True
|
||||
line.is_stock_reservable = reservable
|
||||
|
||||
@api.depends("order_id.state", "reservation_ids")
|
||||
def _compute_is_readonly(self):
|
||||
for line in self:
|
||||
line.is_readonly = (
|
||||
len(line.reservation_ids) > 0 or line.order_id.state != "draft"
|
||||
)
|
||||
|
||||
reservation_ids = fields.One2many(
|
||||
"stock.reservation", "sale_line_id", string="Stock Reservation", copy=False
|
||||
)
|
||||
is_stock_reservable = fields.Boolean(
|
||||
compute="_compute_is_stock_reservable", readonly=True, string="Can be reserved"
|
||||
)
|
||||
is_readonly = fields.Boolean(compute="_compute_is_readonly", store=False)
|
||||
|
||||
def release_stock_reservation(self):
|
||||
reserv_ids = [reserv.id for line in self for reserv in line.reservation_ids]
|
||||
reservations = self.env["stock.reservation"].browse(reserv_ids)
|
||||
reservations.release_reserve()
|
||||
return True
|
||||
|
||||
def write(self, vals):
|
||||
block_on_reserve = ("product_id", "product_uom", "type")
|
||||
update_on_reserve = ("price_unit", "product_uom_qty")
|
||||
keys = set(vals.keys())
|
||||
test_block = keys.intersection(block_on_reserve)
|
||||
test_update = keys.intersection(update_on_reserve)
|
||||
if test_block:
|
||||
for line in self:
|
||||
if not line.reservation_ids:
|
||||
continue
|
||||
raise except_orm(
|
||||
_("Error"),
|
||||
_(
|
||||
"You cannot change the product or unit of measure "
|
||||
"of lines with a stock reservation. "
|
||||
"Release the reservation "
|
||||
"before changing the product."
|
||||
),
|
||||
)
|
||||
res = super().write(vals)
|
||||
if test_update:
|
||||
for line in self:
|
||||
if not line.reservation_ids:
|
||||
continue
|
||||
if len(line.reservation_ids) > 1:
|
||||
raise except_orm(
|
||||
_("Error"),
|
||||
_(
|
||||
"Several stock reservations are linked with the "
|
||||
"line. Impossible to adjust their quantity. "
|
||||
"Please release the reservation "
|
||||
"before changing the quantity."
|
||||
),
|
||||
)
|
||||
|
||||
line.reservation_ids.write(
|
||||
{
|
||||
"price_unit": line.price_unit,
|
||||
"product_uom_qty": line.product_uom_qty,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
for line in self:
|
||||
if line.reservation_ids:
|
||||
raise UserError(
|
||||
_(
|
||||
'Sale order line "[%s] %s" has a related reservation.\n'
|
||||
"Please unreserve this line before "
|
||||
"delete the line"
|
||||
)
|
||||
% (line.order_id.name, line.name)
|
||||
)
|
||||
return super().unlink()
|
||||
19
stock_reserve_sale/model/stock_reserve.py
Normal file
19
stock_reserve_sale/model/stock_reserve.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StockReservation(models.Model):
|
||||
_inherit = "stock.reservation"
|
||||
|
||||
sale_line_id = fields.Many2one(
|
||||
"sale.order.line", string="Sale Order Line", ondelete="cascade", copy=False
|
||||
)
|
||||
sale_id = fields.Many2one(
|
||||
"sale.order", string="Sale Order", related="sale_line_id.order_id"
|
||||
)
|
||||
|
||||
def release_reserve(self):
|
||||
for rec in self:
|
||||
rec.sale_line_id = False
|
||||
return super().release_reserve()
|
||||
8
stock_reserve_sale/readme/CONTRIBUTORS.rst
Normal file
8
stock_reserve_sale/readme/CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
* Leonardo Pistone <leonardo.pistone@camptocamp.com>
|
||||
* Alexandre Fayolle <alexandre.fayolle@camptocamp.com>
|
||||
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
|
||||
|
||||
* `Tecnativa <https://www.tecnativa.com>`_:
|
||||
|
||||
* Carlos Roca
|
||||
23
stock_reserve_sale/readme/DESCRIPTION.rst
Normal file
23
stock_reserve_sale/readme/DESCRIPTION.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
Allows to create stock reservations for quotation lines before the
|
||||
confirmation of the quotation. The reservations might have a validity
|
||||
date and in any case they are lifted when the quotation is canceled or
|
||||
confirmed.
|
||||
|
||||
Reservations can be done only on "make to stock" and stockable products.
|
||||
|
||||
The reserved products are subtracted from the virtual stock. It means
|
||||
that if you reserved a quantity of products which bring the virtual
|
||||
stock below the minimum, the orderpoint will be triggered and new
|
||||
purchase orders will be generated. It also implies that the max may be
|
||||
exceeded if the reservations are canceled.
|
||||
|
||||
If you want to prevent sales orders to be confirmed when the stock is
|
||||
insufficient at the order date, you may want to install the
|
||||
`sale_exception_nostock` module.
|
||||
|
||||
Additionally, if the sale_owner_stock_sourcing module is installed, the owner
|
||||
specified on the sale order line will be proposed as owner of the reservation.
|
||||
If you try to make a reservation for an order whose lines have different, you
|
||||
will get a message suggesting to reserve each line individually. There is no
|
||||
module dependency: this modules is fully functional even without ownership
|
||||
management.
|
||||
8
stock_reserve_sale/readme/USAGE.rst
Normal file
8
stock_reserve_sale/readme/USAGE.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
#. Create a new Sale Order
|
||||
#. Add lines to the Order
|
||||
|
||||
Now you can reserve all the lines by clicking on *Reserve Stock* or you can reserve each
|
||||
one by pressing on the lock icon at the lines.
|
||||
|
||||
Once they where reserved, you can release the reserves by clicking at *Cancell all*
|
||||
button or by clicking the undo icon on the lines.
|
||||
456
stock_reserve_sale/static/description/index.html
Normal file
456
stock_reserve_sale/static/description/index.html
Normal file
@@ -0,0 +1,456 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!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: http://docutils.sourceforge.net/" />
|
||||
<title>Stock Reserve Sales</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/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: grey; } /* 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 {
|
||||
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="stock-reserve-sales">
|
||||
<h1 class="title">Stock Reserve Sales</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_reserve_sale"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-13-0/stock-logistics-warehouse-13-0-stock_reserve_sale"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/153/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
|
||||
<p>Allows to create stock reservations for quotation lines before the
|
||||
confirmation of the quotation. The reservations might have a validity
|
||||
date and in any case they are lifted when the quotation is canceled or
|
||||
confirmed.</p>
|
||||
<p>Reservations can be done only on “make to stock” and stockable products.</p>
|
||||
<p>The reserved products are subtracted from the virtual stock. It means
|
||||
that if you reserved a quantity of products which bring the virtual
|
||||
stock below the minimum, the orderpoint will be triggered and new
|
||||
purchase orders will be generated. It also implies that the max may be
|
||||
exceeded if the reservations are canceled.</p>
|
||||
<p>If you want to prevent sales orders to be confirmed when the stock is
|
||||
insufficient at the order date, you may want to install the
|
||||
<cite>sale_exception_nostock</cite> module.</p>
|
||||
<p>Additionally, if the sale_owner_stock_sourcing module is installed, the owner
|
||||
specified on the sale order line will be proposed as owner of the reservation.
|
||||
If you try to make a reservation for an order whose lines have different, you
|
||||
will get a message suggesting to reserve each line individually. There is no
|
||||
module dependency: this modules is fully functional even without ownership
|
||||
management.</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#usage" id="id1">Usage</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id5">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#id1">Usage</a></h1>
|
||||
<ol class="arabic simple">
|
||||
<li>Create a new Sale Order</li>
|
||||
<li>Add lines to the Order</li>
|
||||
</ol>
|
||||
<p>Now you can reserve all the lines by clicking on <em>Reserve Stock</em> or you can reserve each
|
||||
one by pressing on the lock icon at the lines.</p>
|
||||
<p>Once they where reserved, you can release the reserves by clicking at <em>Cancell all</em>
|
||||
button or by clicking the undo icon on the lines.</p>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/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 smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_reserve_sale%0Aversion:%2013.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="#id3">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Camptocamp</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id5">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Leonardo Pistone <<a class="reference external" href="mailto:leonardo.pistone@camptocamp.com">leonardo.pistone@camptocamp.com</a>></li>
|
||||
<li>Alexandre Fayolle <<a class="reference external" href="mailto:alexandre.fayolle@camptocamp.com">alexandre.fayolle@camptocamp.com</a>></li>
|
||||
<li>Yannick Vaucher <<a class="reference external" href="mailto:yannick.vaucher@camptocamp.com">yannick.vaucher@camptocamp.com</a>></li>
|
||||
<li>Guewen Baconnier <<a class="reference external" href="mailto:guewen.baconnier@camptocamp.com">guewen.baconnier@camptocamp.com</a>></li>
|
||||
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
|
||||
<li>Carlos Roca</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id6">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>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/tree/13.0/stock_reserve_sale">OCA/stock-logistics-warehouse</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
stock_reserve_sale/tests/__init__.py
Normal file
1
stock_reserve_sale/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_stock_reserve_sale
|
||||
138
stock_reserve_sale/tests/test_stock_reserve_sale.py
Normal file
138
stock_reserve_sale/tests/test_stock_reserve_sale.py
Normal file
@@ -0,0 +1,138 @@
|
||||
# Copyright 2021 Tecnativa - Carlos Roca
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import Form, common
|
||||
|
||||
|
||||
class TestStockReserveSale(common.SavepointCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
partner_form = Form(self.env["res.partner"])
|
||||
partner_form.name = "Test partner"
|
||||
partner_form.country_id = self.env.ref("base.es")
|
||||
self.partner = partner_form.save()
|
||||
warehouse_form = Form(self.env["stock.warehouse"])
|
||||
warehouse_form.name = "Test warehouse"
|
||||
warehouse_form.code = "TEST"
|
||||
self.warehouse = warehouse_form.save()
|
||||
product_form = Form(self.env["product.product"])
|
||||
product_form.name = "Test Product 1"
|
||||
product_form.type = "product"
|
||||
self.product_1 = product_form.save()
|
||||
product_form = Form(self.env["product.product"])
|
||||
product_form.name = "Test Product 2"
|
||||
product_form.type = "product"
|
||||
self.product_2 = product_form.save()
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product_1.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"quantity": 10.0,
|
||||
}
|
||||
)
|
||||
self.env["stock.quant"].create(
|
||||
{
|
||||
"product_id": self.product_2.id,
|
||||
"location_id": self.warehouse.lot_stock_id.id,
|
||||
"quantity": 10.0,
|
||||
}
|
||||
)
|
||||
|
||||
def test_reserve_01_tree_reserve_release(self):
|
||||
sale_order_form = Form(self.env["sale.order"])
|
||||
sale_order_form.partner_id = self.partner
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_1
|
||||
order_line_form.product_uom_qty = 3
|
||||
so = sale_order_form.save()
|
||||
wiz = Form(
|
||||
self.env["sale.stock.reserve"].with_context(
|
||||
active_model="sale.order.line", active_ids=so.order_line.ids
|
||||
)
|
||||
).save()
|
||||
wiz.button_reserve()
|
||||
self.assertEquals(self.product_1.virtual_available, 7)
|
||||
so.order_line.release_stock_reservation()
|
||||
self.assertEquals(self.product_1.virtual_available, 10)
|
||||
|
||||
def test_reserve_02_all_form_reserve_release(self):
|
||||
sale_order_form = Form(self.env["sale.order"])
|
||||
sale_order_form.partner_id = self.partner
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_1
|
||||
order_line_form.product_uom_qty = 3
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_2
|
||||
order_line_form.product_uom_qty = 5
|
||||
so = sale_order_form.save()
|
||||
wiz = Form(
|
||||
self.env["sale.stock.reserve"].with_context(
|
||||
active_model="sale.order", active_id=so.id, active_ids=so.ids
|
||||
)
|
||||
).save()
|
||||
wiz.button_reserve()
|
||||
self.assertEquals(self.product_1.virtual_available, 7)
|
||||
self.assertEquals(self.product_2.virtual_available, 5)
|
||||
so.release_all_stock_reservation()
|
||||
self.assertEquals(self.product_1.virtual_available, 10)
|
||||
self.assertEquals(self.product_2.virtual_available, 10)
|
||||
|
||||
def test_reserve_03_confirm_order_release(self):
|
||||
sale_order_form = Form(self.env["sale.order"])
|
||||
sale_order_form.partner_id = self.partner
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_1
|
||||
order_line_form.product_uom_qty = 3
|
||||
so = sale_order_form.save()
|
||||
wiz = Form(
|
||||
self.env["sale.stock.reserve"].with_context(
|
||||
active_model="sale.order.line", active_ids=so.order_line.ids
|
||||
)
|
||||
).save()
|
||||
wiz.button_reserve()
|
||||
self.assertEquals(self.product_1.virtual_available, 7)
|
||||
so.action_confirm()
|
||||
cancelled_reservation = self.env["stock.reservation"].search(
|
||||
[("product_id", "=", self.product_1.id), ("state", "=", "cancel")]
|
||||
)
|
||||
self.assertEquals(len(cancelled_reservation), 1)
|
||||
self.assertEquals(self.product_1.virtual_available, 7)
|
||||
|
||||
def test_reserve_04_cancel_order_release(self):
|
||||
sale_order_form = Form(self.env["sale.order"])
|
||||
sale_order_form.partner_id = self.partner
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_1
|
||||
order_line_form.product_uom_qty = 3
|
||||
so = sale_order_form.save()
|
||||
wiz = Form(
|
||||
self.env["sale.stock.reserve"].with_context(
|
||||
active_model="sale.order.line", active_ids=so.order_line.ids
|
||||
)
|
||||
).save()
|
||||
wiz.button_reserve()
|
||||
self.assertEquals(self.product_1.virtual_available, 7)
|
||||
so.action_cancel()
|
||||
cancelled_reservation = self.env["stock.reservation"].search(
|
||||
[("product_id", "=", self.product_1.id), ("state", "=", "cancel")]
|
||||
)
|
||||
self.assertEquals(len(cancelled_reservation), 1)
|
||||
self.assertEquals(self.product_1.virtual_available, 10)
|
||||
|
||||
def test_reserve_05_unlink_order(self):
|
||||
sale_order_form = Form(self.env["sale.order"])
|
||||
sale_order_form.partner_id = self.partner
|
||||
with sale_order_form.order_line.new() as order_line_form:
|
||||
order_line_form.product_id = self.product_1
|
||||
order_line_form.product_uom_qty = 3
|
||||
so = sale_order_form.save()
|
||||
wiz = Form(
|
||||
self.env["sale.stock.reserve"].with_context(
|
||||
active_model="sale.order.line", active_ids=so.order_line.ids
|
||||
)
|
||||
).save()
|
||||
wiz.button_reserve()
|
||||
with self.assertRaises(UserError):
|
||||
so.unlink()
|
||||
with self.assertRaises(UserError):
|
||||
so.order_line.unlink()
|
||||
122
stock_reserve_sale/view/sale.xml
Normal file
122
stock_reserve_sale/view/sale.xml
Normal file
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_order_form_reserve" model="ir.ui.view">
|
||||
<field name="name">sale.order.form.reserve</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_stock.view_order_form_inherit_sale_stock" />
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_quotation_send" position="before">
|
||||
<field name="is_stock_reservable" invisible="1" />
|
||||
<button
|
||||
name="%(action_sale_stock_reserve)d"
|
||||
type="action"
|
||||
string="Reserve Stock"
|
||||
help="Pre-book products from stock"
|
||||
attrs="{'invisible': [('is_stock_reservable', '=', False)]}"
|
||||
/>
|
||||
</button>
|
||||
<field name="order_line" position="attributes">
|
||||
<attribute name="options">{"reload_on_button": 1}</attribute>
|
||||
</field>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/form//field[@name='state']"
|
||||
position="before"
|
||||
>
|
||||
<field name="reservation_ids" invisible="1" />
|
||||
<button
|
||||
name="%(action_sale_stock_reserve)d"
|
||||
type="action"
|
||||
string="Reserve Stock"
|
||||
attrs="{'invisible': ['|', ('reservation_ids', '!=', []),
|
||||
('state', '!=', 'draft')]}"
|
||||
/>
|
||||
<button
|
||||
name="release_stock_reservation"
|
||||
type="object"
|
||||
string="Release Reservation"
|
||||
attrs="{'invisible': ['|', ('reservation_ids', '=', []),
|
||||
('state', '!=', 'draft')]}"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/tree/field[@name='price_subtotal']"
|
||||
position="after"
|
||||
>
|
||||
<field name="reservation_ids" invisible="1" />
|
||||
<field name="is_stock_reservable" invisible="1" />
|
||||
<button
|
||||
name="%(action_sale_stock_reserve)d"
|
||||
type="action"
|
||||
string="Reserve Stock"
|
||||
icon="fa-lock"
|
||||
attrs="{'invisible': [('is_stock_reservable', '=', False)]}"
|
||||
/>
|
||||
<button
|
||||
name="release_stock_reservation"
|
||||
type="object"
|
||||
string="Release Reservation"
|
||||
icon="fa-undo"
|
||||
attrs="{'invisible': [('reservation_ids', '=', [])]}"
|
||||
/>
|
||||
</xpath>
|
||||
<field name="user_id" position="before">
|
||||
<field name="has_stock_reservation" invisible="1" />
|
||||
</field>
|
||||
<field name="order_line" position="after">
|
||||
<div class="text-right">
|
||||
<button
|
||||
name="release_all_stock_reservation"
|
||||
string="Cancell all"
|
||||
type="object"
|
||||
attrs="{'invisible': [('has_stock_reservation', '=', False)]}"
|
||||
/>
|
||||
</div>
|
||||
</field>
|
||||
<!-- Make readonly the fields quantity and product_id when they are reserved -->
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/form//field[@name='product_id']"
|
||||
position="after"
|
||||
>
|
||||
<field name="is_readonly" invisible="True" />
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/form//field[@name='product_uom_qty']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'readonly': [('is_readonly', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/form//field[@name='product_id']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'readonly': [('is_readonly', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/tree/field[@name='product_id']"
|
||||
position="after"
|
||||
>
|
||||
<field name="is_readonly" invisible="True" />
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'readonly': [('is_readonly', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
<xpath
|
||||
expr="//field[@name='order_line']/tree/field[@name='product_id']"
|
||||
position="attributes"
|
||||
>
|
||||
<attribute
|
||||
name="attrs"
|
||||
>{'readonly': [('is_readonly', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
26
stock_reserve_sale/view/stock_reserve.xml
Normal file
26
stock_reserve_sale/view/stock_reserve.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_stock_reservation_form" model="ir.ui.view">
|
||||
<field name="name">stock.reservation.form</field>
|
||||
<field name="model">stock.reservation</field>
|
||||
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_form" />
|
||||
<field name="arch" type="xml">
|
||||
<group name="location" position="after">
|
||||
<group name="sale" string="Sales">
|
||||
<field name="sale_id" />
|
||||
<field name="sale_line_id" />
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_stock_reservation_tree" model="ir.ui.view">
|
||||
<field name="name">stock.reservation.tree</field>
|
||||
<field name="model">stock.reservation</field>
|
||||
<field name="inherit_id" ref="stock_reserve.view_stock_reservation_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_id" position="before">
|
||||
<field name="sale_id" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
3
stock_reserve_sale/wizard/__init__.py
Normal file
3
stock_reserve_sale/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import sale_stock_reserve
|
||||
112
stock_reserve_sale/wizard/sale_stock_reserve.py
Normal file
112
stock_reserve_sale/wizard/sale_stock_reserve.py
Normal file
@@ -0,0 +1,112 @@
|
||||
# Copyright 2013 Camptocamp SA - Guewen Baconnier
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import _, api, exceptions, fields, models
|
||||
|
||||
|
||||
class SaleStockReserve(models.TransientModel):
|
||||
_name = "sale.stock.reserve"
|
||||
_description = "Sale Stock Reserve"
|
||||
|
||||
@api.model
|
||||
def _default_location_id(self):
|
||||
return self.env["stock.reservation"].get_location_from_ref(
|
||||
"stock.stock_location_stock"
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _default_location_dest_id(self):
|
||||
return self.env["stock.reservation"]._default_location_dest_id()
|
||||
|
||||
def _default_owner(self):
|
||||
"""If sale_owner_stock_sourcing is installed, it adds an owner field
|
||||
on sale order lines. Use it.
|
||||
|
||||
"""
|
||||
model = self.env[self.env.context["active_model"]]
|
||||
if model._name == "sale.order":
|
||||
lines = model.browse(self.env.context["active_id"]).order_line
|
||||
else:
|
||||
lines = model.browse(self.env.context["active_ids"])
|
||||
|
||||
try:
|
||||
owners = {l.stock_owner_id for l in lines}
|
||||
except AttributeError:
|
||||
return self.env["res.partner"]
|
||||
# module sale_owner_stock_sourcing not installed, fine
|
||||
|
||||
if len(owners) == 1:
|
||||
return owners.pop()
|
||||
elif len(owners) > 1:
|
||||
raise exceptions.Warning(
|
||||
_(
|
||||
"""The lines have different owners. Please reserve them
|
||||
individually with the reserve button on each one."""
|
||||
)
|
||||
)
|
||||
|
||||
return self.env["res.partner"]
|
||||
|
||||
location_id = fields.Many2one(
|
||||
"stock.location", "Source Location", required=True, default=_default_location_id
|
||||
)
|
||||
location_dest_id = fields.Many2one(
|
||||
"stock.location",
|
||||
"Reservation Location",
|
||||
required=True,
|
||||
help="Location where the system will reserve the " "products.",
|
||||
default=_default_location_dest_id,
|
||||
)
|
||||
date_validity = fields.Date(
|
||||
"Validity Date",
|
||||
help="If a date is given, the reservations will be released "
|
||||
"at the end of the validity.",
|
||||
)
|
||||
note = fields.Text("Notes")
|
||||
owner_id = fields.Many2one("res.partner", "Stock Owner", default=_default_owner)
|
||||
|
||||
def _prepare_stock_reservation(self, line):
|
||||
self.ensure_one()
|
||||
return {
|
||||
"product_id": line.product_id.id,
|
||||
"product_uom": line.product_uom.id,
|
||||
"product_uom_qty": line.product_uom_qty,
|
||||
"date_validity": self.date_validity,
|
||||
"name": "{} ({})".format(line.order_id.name, line.name),
|
||||
"location_id": self.location_id.id,
|
||||
"location_dest_id": self.location_dest_id.id,
|
||||
"note": self.note,
|
||||
"price_unit": line.price_unit,
|
||||
"sale_line_id": line.id,
|
||||
"restrict_partner_id": self.owner_id.id,
|
||||
}
|
||||
|
||||
def stock_reserve(self, line_ids):
|
||||
self.ensure_one()
|
||||
|
||||
lines = self.env["sale.order.line"].browse(line_ids)
|
||||
for line in lines:
|
||||
if not line.is_stock_reservable:
|
||||
continue
|
||||
vals = self._prepare_stock_reservation(line)
|
||||
reserv = self.env["stock.reservation"].create(vals)
|
||||
reserv.reserve()
|
||||
return True
|
||||
|
||||
def button_reserve(self):
|
||||
env = self.env
|
||||
self.ensure_one()
|
||||
close = {"type": "ir.actions.act_window_close"}
|
||||
active_model = env.context.get("active_model")
|
||||
active_ids = env.context.get("active_ids")
|
||||
if not (active_model and active_ids):
|
||||
return close
|
||||
|
||||
if active_model == "sale.order":
|
||||
sales = env["sale.order"].browse(active_ids)
|
||||
line_ids = [line.id for sale in sales for line in sale.order_line]
|
||||
|
||||
if active_model == "sale.order.line":
|
||||
line_ids = active_ids
|
||||
|
||||
self.stock_reserve(line_ids)
|
||||
return close
|
||||
42
stock_reserve_sale/wizard/sale_stock_reserve_view.xml
Normal file
42
stock_reserve_sale/wizard/sale_stock_reserve_view.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_sale_stock_reserve_form" model="ir.ui.view">
|
||||
<field name="name">sale.stock.reserve.form</field>
|
||||
<field name="model">sale.stock.reserve</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Reserve Stock">
|
||||
<p class="oe_grey">
|
||||
A stock reservation will be created for the products
|
||||
of the selected quotation lines. If a validity date is specified,
|
||||
the reservation will be released once the date has passed.
|
||||
</p>
|
||||
<group>
|
||||
<field name="location_id" />
|
||||
<field name="location_dest_id" />
|
||||
<field name="date_validity" />
|
||||
<field name="owner_id" groups="stock.group_tracking_owner" />
|
||||
</group>
|
||||
<group name="note" string="Notes">
|
||||
<field name="note" nolabel="1" />
|
||||
</group>
|
||||
<footer>
|
||||
<button
|
||||
string="Reserve"
|
||||
name="button_reserve"
|
||||
type="object"
|
||||
class="oe_highlight"
|
||||
/>
|
||||
or
|
||||
<button special="cancel" class="oe_link" string="Cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_sale_stock_reserve" model="ir.actions.act_window">
|
||||
<field name="name">Reserve Stock for Quotation Lines</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">sale.stock.reserve</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user