first commit
This commit is contained in:
2
modules/sale_stock_quantity/__init__.py
Normal file
2
modules/sale_stock_quantity/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
BIN
modules/sale_stock_quantity/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
modules/sale_stock_quantity/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
modules/sale_stock_quantity/__pycache__/sale.cpython-311.pyc
Normal file
BIN
modules/sale_stock_quantity/__pycache__/sale.cpython-311.pyc
Normal file
Binary file not shown.
12
modules/sale_stock_quantity/exceptions.py
Normal file
12
modules/sale_stock_quantity/exceptions.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.exceptions import UserError, UserWarning
|
||||
|
||||
|
||||
class StockQuantityError(UserError):
|
||||
pass
|
||||
|
||||
|
||||
class StockQuantityWarning(UserWarning):
|
||||
pass
|
||||
21
modules/sale_stock_quantity/locale/bg.po
Normal file
21
modules/sale_stock_quantity/locale/bg.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/ca.po
Normal file
25
modules/sale_stock_quantity/locale/ca.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantitat prevista %(forecast_quantity)s)s del producte\"%(product)s\" és"
|
||||
" menor que la seva quantitat (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantitat prevista %(forecast_quantity)s de la línia \"%(line)s\" és "
|
||||
"menor que la seva quantitat (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Força quantitat d'existències en venda"
|
||||
21
modules/sale_stock_quantity/locale/cs.po
Normal file
21
modules/sale_stock_quantity/locale/cs.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/de.po
Normal file
25
modules/sale_stock_quantity/locale/de.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Die erwartete Menge (%(forecast_quantity)s) des Artikels \"%(product)s\" ist"
|
||||
" geringer als die Menge (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Die erwartete Menge (%(forecast_quantity)s) für die Warenbewegung "
|
||||
"\"%(line)s\" ist geringer als die zu bewegende Menge (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Verkauf Lagerbestand"
|
||||
25
modules/sale_stock_quantity/locale/es.po
Normal file
25
modules/sale_stock_quantity/locale/es.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La cantidad prevista (%(forecast_quantity)s) del producto\"%(product)s\" es "
|
||||
"menor que su cantidad (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La cantidad prevista (%(forecast_quantity)s) de la linea \"%(line)s\" es "
|
||||
"menor que su cantidad (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Forzar cantidad de existencias en venta"
|
||||
21
modules/sale_stock_quantity/locale/es_419.po
Normal file
21
modules/sale_stock_quantity/locale/es_419.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr ""
|
||||
25
modules/sale_stock_quantity/locale/et.po
Normal file
25
modules/sale_stock_quantity/locale/et.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Prognoositav kogus (%(forecast_quantity)s%(default_uom)s) reale \"%(line)s\""
|
||||
" on väiksem, kui rida (%(quantity)s%(unit)s)."
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Prognoositav kogus (%(forecast_quantity)s%(default_uom)s) reale \"%(line)s\""
|
||||
" on väiksem, kui rida (%(quantity)s%(unit)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Vaba laoseis"
|
||||
25
modules/sale_stock_quantity/locale/fa.po
Normal file
25
modules/sale_stock_quantity/locale/fa.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"مقدار پیش بینی: \"%s\" با واحداندازه گیری پیش فرض: \"%s\" از سطر: \"%s\" ، "
|
||||
"کمتر از مقدار : \"%s\" با واحد : \"%s\" میباشد."
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"مقدار پیش بینی: \"%s\" با واحداندازه گیری پیش فرض: \"%s\" از سطر: \"%s\" ، "
|
||||
"کمتر از مقدار : \"%s\" با واحد : \"%s\" میباشد."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "مقدار فروش موجودی"
|
||||
21
modules/sale_stock_quantity/locale/fi.po
Normal file
21
modules/sale_stock_quantity/locale/fi.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/fr.po
Normal file
25
modules/sale_stock_quantity/locale/fr.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantité prévisionnelle (%(forecast_quantity)s) du produit "
|
||||
"« %(product)s » est plus petite que la quantité (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantité prévisionnelle (%(forecast_quantity)s) de la ligne « %(line)s » "
|
||||
"est plus petite que sa quantité (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Quantité de stock de vente"
|
||||
21
modules/sale_stock_quantity/locale/hu.po
Normal file
21
modules/sale_stock_quantity/locale/hu.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/id.po
Normal file
25
modules/sale_stock_quantity/locale/id.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Jumlah perkiraan (%(forecast_quantity)s%(default_uom)s) pada baris "
|
||||
"\"%(line)s\" lebih rendah dari jumlah (%(quantity)s%(unit)s)."
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Jumlah perkiraan (%(forecast_quantity)s%(default_uom)s) pada baris "
|
||||
"\"%(line)s\" lebih rendah dari jumlah (%(quantity)s%(unit)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr ""
|
||||
25
modules/sale_stock_quantity/locale/it.po
Normal file
25
modules/sale_stock_quantity/locale/it.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantita prevista (%(forecast_quantity)s) del prodotto \"%(product)s\" è "
|
||||
"inferiore alla quantità (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"La quantita prevista (%(forecast_quantity)s) per la riga \"%(line)s\" è "
|
||||
"inferiore alla quantità (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Quantità stock in vendita"
|
||||
26
modules/sale_stock_quantity/locale/lo.po
Normal file
26
modules/sale_stock_quantity/locale/lo.po
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"ການຄາດຄະເນຈຳນວນ %(forecast_quantity)s%(default_uom)s ຂອງ \"%(line)s\" "
|
||||
"ຕໍ່າກວ່າ %(quantity)s%(unit)s."
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"ການຄາດຄະເນຈຳນວນ %(forecast_quantity)s%(default_uom)s ຂອງ \"%(line)s\" "
|
||||
"ຕໍ່າກວ່າ %(quantity)s%(unit)s."
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
21
modules/sale_stock_quantity/locale/lt.po
Normal file
21
modules/sale_stock_quantity/locale/lt.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/nl.po
Normal file
25
modules/sale_stock_quantity/locale/nl.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"De verwachte hoeveelheid (%(forecast_quantity)s) van product \"%(product)s\""
|
||||
" is lager dan de hoeveelheid (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"De verwachte hoeveelheid (%(forecast_quantity)s) voor regel \"%(line)s\" is "
|
||||
"lager dan de hoeveelheid (%(quantity)s) van de regel zelf."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Verkoop Voorraad Aantal"
|
||||
21
modules/sale_stock_quantity/locale/pl.po
Normal file
21
modules/sale_stock_quantity/locale/pl.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
25
modules/sale_stock_quantity/locale/pt.po
Normal file
25
modules/sale_stock_quantity/locale/pt.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"A quantidade prevista %(forecast_quantity)s do produto \"%(product)s\" é "
|
||||
"menor do que (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"A quantidade prevista (%(forecast_quantity)s) para a linha \"%(line)s\" é "
|
||||
"menor do que (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Quantidade em Estoque"
|
||||
25
modules/sale_stock_quantity/locale/ro.po
Normal file
25
modules/sale_stock_quantity/locale/ro.po
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Cantitatea estimata (%(forecast_quantity)s) din produsul \"%(product)s\" "
|
||||
"este mai mică decât cantitatea (%(quantity)s)."
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Cantitatea estimata (%(forecast_quantity)s) pentru rândul \"%(line)s\" este "
|
||||
"mai mică decât cantitatea proprie (%(quantity)s)."
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Vânzare Cantitate Stoc"
|
||||
21
modules/sale_stock_quantity/locale/ru.po
Normal file
21
modules/sale_stock_quantity/locale/ru.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
26
modules/sale_stock_quantity/locale/sl.po
Normal file
26
modules/sale_stock_quantity/locale/sl.po
Normal file
@@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Predvidena količina %(forecast_quantity)s%(default_uom)s postavke "
|
||||
"\"%(line)s\" je manjša kot %(quantity)s%(unit)s."
|
||||
|
||||
#, fuzzy, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
"Predvidena količina %(forecast_quantity)s%(default_uom)s postavke "
|
||||
"\"%(line)s\" je manjša kot %(quantity)s%(unit)s."
|
||||
|
||||
#, fuzzy
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
21
modules/sale_stock_quantity/locale/tr.po
Normal file
21
modules/sale_stock_quantity/locale/tr.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
21
modules/sale_stock_quantity/locale/uk.po
Normal file
21
modules/sale_stock_quantity/locale/uk.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr ""
|
||||
21
modules/sale_stock_quantity/locale/zh_CN.po
Normal file
21
modules/sale_stock_quantity/locale/zh_CN.po
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_product_forecast_quantity_lower"
|
||||
msgid ""
|
||||
"The forecast quantity (%(forecast_quantity)s) of product \"%(product)s\" is "
|
||||
"lower than the quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_sale_stock_quantity"
|
||||
msgid ""
|
||||
"The forcast quantity (%(forecast_quantity)s) for line \"%(line)s\" is lower "
|
||||
"than its quantity (%(quantity)s)."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:res.group,name:group_sale_stock_quantity"
|
||||
msgid "Sale Stock Quantity"
|
||||
msgstr "Sale Stock Quantity"
|
||||
13
modules/sale_stock_quantity/message.xml
Normal file
13
modules/sale_stock_quantity/message.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data grouped="1">
|
||||
<record model="ir.message" id="msg_sale_stock_quantity">
|
||||
<field name="text">The forcast quantity (%(forecast_quantity)s) for line "%(line)s" is lower than its quantity (%(quantity)s).</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_product_forecast_quantity_lower">
|
||||
<field name="text">The forecast quantity (%(forecast_quantity)s) of product "%(product)s" is lower than the quantity (%(quantity)s).</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
262
modules/sale_stock_quantity/sale.py
Normal file
262
modules/sale_stock_quantity/sale.py
Normal file
@@ -0,0 +1,262 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import datetime
|
||||
from collections import defaultdict
|
||||
from itertools import groupby
|
||||
from operator import attrgetter
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import ModelView, Workflow, fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.tools import grouped_slice, sortable_values
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from .exceptions import StockQuantityError, StockQuantityWarning
|
||||
|
||||
|
||||
class Sale(metaclass=PoolMeta):
|
||||
__name__ = 'sale.sale'
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('quotation')
|
||||
def quote(cls, sales):
|
||||
# Check before setting the number
|
||||
cls._check_stock_quantity(sales)
|
||||
super().quote(sales)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('confirmed')
|
||||
def confirm(cls, sales):
|
||||
# Check before queueing the process task
|
||||
cls._check_stock_quantity(sales)
|
||||
super().confirm(sales)
|
||||
|
||||
@classmethod
|
||||
def _check_stock_quantity(cls, sales):
|
||||
for sale in sales:
|
||||
sale.check_stock_quantity()
|
||||
|
||||
@classmethod
|
||||
def _stock_quantity_states(cls):
|
||||
return ['quotation', 'confirmed']
|
||||
|
||||
@classmethod
|
||||
def _stock_quantity_next_supply_date(cls, product):
|
||||
pool = Pool()
|
||||
try:
|
||||
PurchaseRequest = pool.get('purchase.request')
|
||||
except KeyError:
|
||||
PurchaseRequest = None
|
||||
|
||||
if (getattr(PurchaseRequest, 'get_supply_dates', None)
|
||||
and product.purchasable):
|
||||
return PurchaseRequest.get_supply_dates(product)[0]
|
||||
else:
|
||||
# TODO compute supply date for production
|
||||
return datetime.date.max
|
||||
|
||||
def check_stock_quantity(self):
|
||||
pool = Pool()
|
||||
Product = pool.get('product.product')
|
||||
Date = pool.get('ir.date')
|
||||
Uom = pool.get('product.uom')
|
||||
Group = pool.get('res.group')
|
||||
User = pool.get('res.user')
|
||||
ModelData = pool.get('ir.model.data')
|
||||
Lang = pool.get('ir.lang')
|
||||
Line = pool.get('sale.line')
|
||||
Warning = pool.get('res.user.warning')
|
||||
|
||||
if not self.warehouse:
|
||||
return
|
||||
|
||||
transaction = Transaction()
|
||||
|
||||
def in_group():
|
||||
group = Group(ModelData.get_id('sale_stock_quantity',
|
||||
'group_sale_stock_quantity'))
|
||||
user_id = transaction.user
|
||||
if user_id == 0:
|
||||
user_id = transaction.context.get('user', user_id)
|
||||
if user_id == 0:
|
||||
return True
|
||||
user = User(user_id)
|
||||
return group in user.groups
|
||||
|
||||
def filter_line(line):
|
||||
return (line.warehouse
|
||||
and line.product
|
||||
and line.product.type == 'goods'
|
||||
and not line.product.consumable
|
||||
and line.quantity > 0
|
||||
# Use getattr as supply_on_sale comes from sale_supply module
|
||||
and not getattr(line, 'supply_on_sale', False))
|
||||
|
||||
def get_delta(date, warehouse, products):
|
||||
'Compute quantity delta at the date'
|
||||
if date in date2delta:
|
||||
return date2delta[warehouse][date]
|
||||
|
||||
with transaction.set_context(forecast=True,
|
||||
stock_date_start=date,
|
||||
stock_date_end=date):
|
||||
pbl = defaultdict(int)
|
||||
for sub_products in grouped_slice(products):
|
||||
sub_product_ids = [p.id for p in sub_products]
|
||||
pbl.update(Product.products_by_location(
|
||||
[warehouse.id],
|
||||
with_childs=True,
|
||||
grouping_filter=(sub_product_ids,)))
|
||||
delta = {}
|
||||
for key, qty in pbl.items():
|
||||
_, product_id = key
|
||||
delta[product_id] = qty
|
||||
date2delta[warehouse][date] = delta
|
||||
return delta
|
||||
date2delta = defaultdict(dict)
|
||||
|
||||
def raise_(line_id, message_values):
|
||||
if not in_group():
|
||||
raise StockQuantityError(
|
||||
gettext('sale_stock_quantity.msg_sale_stock_quantity',
|
||||
**message_values))
|
||||
warning_name = 'stock_quantity_warning_%s' % line_id
|
||||
if Warning.check(warning_name):
|
||||
raise StockQuantityWarning(warning_name,
|
||||
gettext('sale_stock_quantity.msg_sale_stock_quantity',
|
||||
**message_values))
|
||||
|
||||
with Transaction().set_context(company=self.company.id):
|
||||
today = Date.today()
|
||||
lang = Lang.get()
|
||||
|
||||
lines = filter(filter_line, self.lines)
|
||||
lines = list(lines)
|
||||
|
||||
quantities = defaultdict(lambda: defaultdict(int))
|
||||
w_getter = attrgetter('warehouse', 'shipping_date')
|
||||
w_products = {}
|
||||
for (warehouse, shipping_date), w_lines in groupby(
|
||||
sorted(lines, key=sortable_values(w_getter)), key=w_getter):
|
||||
if shipping_date is None:
|
||||
shipping_date = today
|
||||
w_products[warehouse] = products = {l.product for l in w_lines}
|
||||
with transaction.set_context(
|
||||
locations=[warehouse.id],
|
||||
stock_date_end=shipping_date,
|
||||
stock_assign=True):
|
||||
products = Product.browse(products)
|
||||
quantities[warehouse].update(
|
||||
(p, p.forecast_quantity) for p in products)
|
||||
|
||||
# Remove quantities from other sales
|
||||
for sub_products in grouped_slice(products):
|
||||
other_lines = Line.search([
|
||||
('sale.company', '=', self.company.id),
|
||||
('sale.state', 'in', self._stock_quantity_states()),
|
||||
('sale.id', '!=', self.id),
|
||||
('product', 'in', sub_products),
|
||||
('quantity', '>', 0),
|
||||
])
|
||||
for line in other_lines:
|
||||
if line.warehouse != warehouse:
|
||||
continue
|
||||
if (line.shipping_date
|
||||
and line.shipping_date > shipping_date):
|
||||
continue
|
||||
product = line.product
|
||||
date = line.sale.sale_date or today
|
||||
if date > today:
|
||||
continue
|
||||
quantity = Uom.compute_qty(line.unit, line.quantity,
|
||||
product.default_uom, round=False)
|
||||
quantities[line.warehouse][product] -= quantity
|
||||
|
||||
for line in lines:
|
||||
warehouse = line.warehouse
|
||||
product = line.product
|
||||
quantity = Uom.compute_qty(line.unit, line.quantity,
|
||||
product.default_uom, round=False)
|
||||
shipping_date = line.shipping_date or today
|
||||
next_supply_date = self._stock_quantity_next_supply_date(product)
|
||||
message_values = {
|
||||
'line': line.rec_name,
|
||||
'forecast_quantity': lang.format_number_symbol(
|
||||
quantities[warehouse][product],
|
||||
product.default_uom, product.default_uom.digits),
|
||||
'quantity': lang.format_number_symbol(
|
||||
line.quantity, line.unit, line.unit.digits),
|
||||
}
|
||||
if (quantities[warehouse][product] < quantity
|
||||
and shipping_date < next_supply_date):
|
||||
raise_(line.id, message_values)
|
||||
# Update quantities if the same product is many times in lines
|
||||
quantities[warehouse][product] -= quantity
|
||||
|
||||
# Check other dates until next supply date
|
||||
if next_supply_date != datetime.date.max:
|
||||
products = w_products[warehouse]
|
||||
forecast_quantity = quantities[warehouse][product]
|
||||
date = shipping_date + datetime.timedelta(1)
|
||||
while date < next_supply_date:
|
||||
delta = get_delta(date, warehouse, products)
|
||||
forecast_quantity += delta.get(product.id, 0)
|
||||
if forecast_quantity < 0:
|
||||
message_values['forecast_quantity'] = forecast_quantity
|
||||
raise_(line.id, message_values)
|
||||
date += datetime.timedelta(1)
|
||||
|
||||
|
||||
class Line(metaclass=PoolMeta):
|
||||
__name__ = 'sale.line'
|
||||
|
||||
@fields.depends(methods=['_notify_stock_quantity'])
|
||||
def on_change_notify(self):
|
||||
notifications = super().on_change_notify()
|
||||
notifications.extend(self._notify_stock_quantity())
|
||||
return notifications
|
||||
|
||||
@fields.depends(
|
||||
'sale_state', 'product', 'quantity', 'unit', 'company',
|
||||
'shipping_date', 'sale', '_parent_sale.warehouse')
|
||||
def _notify_stock_quantity(self):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
Lang = pool.get('ir.lang')
|
||||
Move = pool.get('stock.move')
|
||||
Product = pool.get('product.product')
|
||||
UoM = pool.get('product.uom')
|
||||
lang = Lang.get()
|
||||
if (self.sale_state == 'draft'
|
||||
and self.sale
|
||||
and self.sale.warehouse
|
||||
and self.product
|
||||
and self.product.type in Move.get_product_types()
|
||||
and self.unit
|
||||
and self.quantity is not None):
|
||||
with Transaction().set_context(
|
||||
company=self.company.id if self.company else None):
|
||||
today = Date.today()
|
||||
shipping_date = self.shipping_date or today
|
||||
locations = [self.sale.warehouse.id]
|
||||
with Transaction().set_context(
|
||||
locations=locations,
|
||||
stock_date_end=shipping_date):
|
||||
product = Product(self.product.id)
|
||||
quantity = UoM.compute_qty(
|
||||
self.unit, self.quantity,
|
||||
product.default_uom, round=False)
|
||||
if product.forecast_quantity < quantity:
|
||||
yield ('warning', gettext(
|
||||
'sale_stock_quantity'
|
||||
'.msg_product_forecast_quantity_lower',
|
||||
forecast_quantity=lang.format_number_symbol(
|
||||
product.forecast_quantity, product.default_uom,
|
||||
product.default_uom.digits),
|
||||
product=self.product.rec_name,
|
||||
quantity=lang.format_number_symbol(
|
||||
self.quantity, self.unit,
|
||||
self.unit.digits)))
|
||||
15
modules/sale_stock_quantity/sale.xml
Normal file
15
modules/sale_stock_quantity/sale.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="res.group" id="group_sale_stock_quantity">
|
||||
<field name="name">Sale Stock Quantity</field>
|
||||
</record>
|
||||
<record model="res.user-res.group"
|
||||
id="user_admin_sale_stock_quantity">
|
||||
<field name="user" ref="res.user_admin"/>
|
||||
<field name="group" ref="group_sale_stock_quantity"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
2
modules/sale_stock_quantity/tests/__init__.py
Normal file
2
modules/sale_stock_quantity/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,205 @@
|
||||
===================
|
||||
Sale Stock Quantity
|
||||
===================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime as dt
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... create_payment_term, set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.modules.stock.exceptions import MoveFutureWarning
|
||||
>>> from trytond.tests.tools import activate_modules
|
||||
|
||||
>>> today = dt.date.today()
|
||||
>>> later = today + dt.timedelta(days=2)
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules(
|
||||
... ['sale_stock_quantity', 'stock_supply'],
|
||||
... create_company, create_chart)
|
||||
|
||||
>>> Warning = Model.get('res.user.warning')
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(
|
||||
... create_fiscalyear(today=(today, later)))
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
>>> revenue = accounts['revenue']
|
||||
>>> expense = accounts['expense']
|
||||
|
||||
Create parties::
|
||||
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> customer = Party(name='Customer')
|
||||
>>> customer.save()
|
||||
>>> supplier = Party(name='Supplier')
|
||||
>>> supplier.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> account_category = ProductCategory(name="Account Category")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = expense
|
||||
>>> account_category.account_revenue = revenue
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.purchasable = True
|
||||
>>> template.salable = True
|
||||
>>> template.list_price = Decimal('10')
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> product, = template.products
|
||||
|
||||
>>> ProductSupplier = Model.get('purchase.product_supplier')
|
||||
>>> product_supplier = ProductSupplier()
|
||||
>>> product_supplier.template = template
|
||||
>>> product_supplier.party = supplier
|
||||
>>> product_supplier.lead_time = dt.timedelta(3)
|
||||
>>> product_supplier.save()
|
||||
|
||||
Create payment term::
|
||||
|
||||
>>> payment_term = create_payment_term()
|
||||
>>> payment_term.save()
|
||||
|
||||
Create an Inventory of 5 products::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> storage, = Location.find([
|
||||
... ('code', '=', 'STO'),
|
||||
... ])
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage
|
||||
>>> inventory_line = inventory.lines.new(product=product)
|
||||
>>> inventory_line.quantity = 5.0
|
||||
>>> inventory_line.expected_quantity = 0.0
|
||||
>>> inventory.click('confirm')
|
||||
>>> inventory.state
|
||||
'done'
|
||||
|
||||
Sale 3 products with enough stock::
|
||||
|
||||
>>> Sale = Model.get('sale.sale')
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 3.0
|
||||
>>> len(sale_line.notifications())
|
||||
0
|
||||
>>> sale.click('quote')
|
||||
|
||||
Sale 1 product with still enough stock::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 1.0
|
||||
>>> len(sale_line.notifications())
|
||||
0
|
||||
>>> sale.click('quote')
|
||||
|
||||
Sale 2 more products with not enough stock::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 2.0
|
||||
>>> len(sale_line.notifications())
|
||||
0
|
||||
>>> sale.click('quote')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
StockQuantityWarning: ...
|
||||
|
||||
Clean sales::
|
||||
|
||||
>>> Sale.click(Sale.find([]), 'draft')
|
||||
>>> Sale.delete(Sale.find([]))
|
||||
|
||||
Sale 6 products with not enough stock::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 6.0
|
||||
>>> len(sale_line.notifications())
|
||||
1
|
||||
>>> sale.click('quote')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
StockQuantityWarning: ...
|
||||
>>> sale.delete()
|
||||
|
||||
Make an inventory of 3 products in 2 days::
|
||||
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage
|
||||
>>> inventory.date = later
|
||||
>>> inventory_line = inventory.lines.new(product=product)
|
||||
>>> inventory_line.quantity = 3.0
|
||||
>>> inventory_line.expected_quantity = 5.0
|
||||
>>> try:
|
||||
... inventory.click('confirm')
|
||||
... except MoveFutureWarning as warning:
|
||||
... Warning(user=config.user, name=warning.name).save()
|
||||
>>> inventory.click('confirm')
|
||||
>>> inventory.state
|
||||
'done'
|
||||
|
||||
Sale 4 products with not enough forecast::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 4.0
|
||||
>>> sale.click('quote')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
StockQuantityWarning: ...
|
||||
>>> sale.delete()
|
||||
|
||||
Sale 2 products with enough forecast::
|
||||
|
||||
>>> sale = Sale()
|
||||
>>> sale.party = customer
|
||||
>>> sale.payment_term = payment_term
|
||||
>>> sale_line = sale.lines.new()
|
||||
>>> sale_line.product = product
|
||||
>>> sale_line.quantity = 2.0
|
||||
>>> sale.click('quote')
|
||||
>>> sale.click('draft')
|
||||
>>> sale.delete()
|
||||
12
modules/sale_stock_quantity/tests/test_module.py
Normal file
12
modules/sale_stock_quantity/tests/test_module.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.tests.test_tryton import ModuleTestCase
|
||||
|
||||
|
||||
class SaleStockQuantityTestCase(ModuleTestCase):
|
||||
'Test Sale Stock Quantity module'
|
||||
module = 'sale_stock_quantity'
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
8
modules/sale_stock_quantity/tests/test_scenario.py
Normal file
8
modules/sale_stock_quantity/tests/test_scenario.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.tests.test_tryton import load_doc_tests
|
||||
|
||||
|
||||
def load_tests(*args, **kwargs):
|
||||
return load_doc_tests(__name__, __file__, *args, **kwargs)
|
||||
17
modules/sale_stock_quantity/tryton.cfg
Normal file
17
modules/sale_stock_quantity/tryton.cfg
Normal file
@@ -0,0 +1,17 @@
|
||||
[tryton]
|
||||
version=7.8.0
|
||||
depends:
|
||||
product
|
||||
sale
|
||||
stock
|
||||
extras_depend:
|
||||
sale_supply
|
||||
stock_supply
|
||||
xml:
|
||||
sale.xml
|
||||
message.xml
|
||||
|
||||
[register]
|
||||
model:
|
||||
sale.Sale
|
||||
sale.Line
|
||||
Reference in New Issue
Block a user