first commit

This commit is contained in:
root
2026-03-14 09:42:12 +00:00
commit 0adbd20c2c
10991 changed files with 1646955 additions and 0 deletions

View 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.

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Digits de la quantitat"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Quantitat mínima"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Arrodoniment de la quantitat"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Nachkommastellen Menge"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Mindestbestellmenge"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Rundungsmenge"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Dígitos cantidad"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Cantidad mínima"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Redondeo cantidad"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Décimales de quantité"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Quantité minimale"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Quantité d'arrondi"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Decimali della quantità"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Quantità minima"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Arrotondamento della quantità"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Decimalen aantal"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Minimaal aantal"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Afrondingshoeveelheid"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,16 @@
#
#, fuzzy
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Quantidade de Dígitos"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Quantidade Mínima"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Quantidade Arredondada"

View File

@@ -0,0 +1,16 @@
#
#, fuzzy
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr "Zecimale Cantitate"
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr "Cantitate Minima"
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr "Rotunjire Cantitate"

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,15 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:purchase.product_supplier,quantity_digits:"
msgid "Quantity Digits"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_minimal:"
msgid "Minimal Quantity"
msgstr ""
msgctxt "field:purchase.product_supplier,quantity_rounding:"
msgid "Rounding Quantity"
msgstr ""

View File

@@ -0,0 +1,65 @@
# 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 builtins
from decimal import Decimal
from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval
class ProductSupplier(metaclass=PoolMeta):
__name__ = 'purchase.product_supplier'
quantity_minimal = fields.Float(
"Minimal Quantity",
digits=(None, Eval('quantity_digits', None)),
domain=['OR',
('quantity_minimal', '=', None),
('quantity_minimal', '>', 0),
])
quantity_rounding = fields.Float(
"Rounding Quantity",
digits=(None, Eval('quantity_digits', None)),
domain=['OR',
('quantity_rounding', '=', None),
('quantity_rounding', '>', 0),
])
quantity_digits = fields.Function(
fields.Integer("Quantity Digits"),
'on_change_with_quantity_digits')
@fields.depends(
'unit',
'product', '_parent_product.default_uom',
'template', '_parent_template.default_uom')
def on_change_with_quantity_digits(self, name=None):
pool = Pool()
Uom = pool.get('product.uom')
if self.product and self.product.default_uom:
default_uom = self.product.default_uom
elif self.template and self.template.default_uom:
default_uom = self.template.default_uom
else:
return
rounding = default_uom.rounding
if self.unit:
rounding = Uom.compute_qty(
default_uom, rounding, self.unit, round=False)
return -Decimal(str(rounding)).as_tuple().exponent
def adapt_quantity(self, quantity, unit, round=True):
pool = Pool()
Uom = pool.get('product.uom')
quantity = Uom.compute_qty(unit, quantity, self.unit, round=False)
if self.quantity_minimal:
if quantity < self.quantity_minimal:
quantity = self.quantity_minimal
if self.quantity_rounding:
remainder = builtins.round(
quantity % self.quantity_rounding, self.quantity_digits)
if remainder and remainder != self.quantity_rounding:
quantity += (self.quantity_rounding - remainder)
quantity = Uom.compute_qty(self.unit, quantity, unit, round=round)
return quantity

View File

@@ -0,0 +1,12 @@
<?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="ir.ui.view" id="product_supplier_view_form">
<field name="model">purchase.product_supplier</field>
<field name="inherit" ref="purchase.product_supplier_view_form"/>
<field name="name">product_supplier_form</field>
</record>
</data>
</tryton>

View File

@@ -0,0 +1,16 @@
# 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.pool import PoolMeta
class RequestCreatePurchase(metaclass=PoolMeta):
__name__ = 'purchase.request.create_purchase'
@classmethod
def compute_quantity(cls, requests, line, purchase):
quantity = super().compute_quantity(requests, line, purchase)
if line.product_supplier:
quantity = line.product_supplier.adapt_quantity(
quantity, line.unit, round=False)
return quantity

View 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.

View File

@@ -0,0 +1,119 @@
==================================
Purchase Product Quantity Scenario
==================================
Imports::
>>> from decimal import Decimal
>>> from proteus import Model, Wizard
>>> from trytond.modules.account.tests.tools import create_chart, get_accounts
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.tests.tools import activate_modules, assertEqual, set_user
Activate modules::
>>> config = activate_modules(
... ['purchase_product_quantity', 'purchase_request'],
... create_company, create_chart)
>>> Location = Model.get('stock.location')
>>> Party = Model.get('party.party')
>>> ProductCategory = Model.get('product.category')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> PurchaseRequest = Model.get('purchase.request')
Get accounts::
>>> accounts = get_accounts()
Create parties::
>>> supplier = Party(name="Supplier")
>>> supplier.save()
Create account category::
>>> account_category = ProductCategory(name="Account Category")
>>> account_category.accounting = True
>>> account_category.account_expense = accounts['expense']
>>> account_category.save()
Create product::
>>> gr, = ProductUom.find([('name', '=', "Gram")])
>>> kg, = ProductUom.find([('name', '=', "Kilogram")])
>>> template = ProductTemplate()
>>> template.name = 'Product'
>>> template.default_uom = gr
>>> template.type = 'goods'
>>> template.list_price = Decimal('20')
>>> template.account_category = account_category
>>> template.purchasable = True
>>> template.purchase_uom = kg
>>> product_supplier = template.product_suppliers.new()
>>> product_supplier.party = supplier
>>> product_supplier.quantity_minimal = 0.1
>>> product_supplier.quantity_rounding = 0.05
>>> product, = template.products
>>> product.cost_price = Decimal('8')
>>> template.save()
>>> product, = template.products
Get stock locations::
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
Create the purchase request below minimal::
>>> ctx = config.context
>>> set_user(0)
>>> pr_id, = PurchaseRequest.create([{
... 'product': product.id,
... 'quantity': 30,
... 'unit': gr,
... 'warehouse': warehouse_loc.id,
... }], ctx)
>>> set_user()
>>> purchase_request = PurchaseRequest(pr_id)
Create purchase::
>>> create_purchase = Wizard(
... 'purchase.request.create_purchase', [purchase_request])
>>> create_purchase.form.party = supplier
>>> create_purchase.execute('start')
>>> purchase_request.state
'purchased'
>>> assertEqual(purchase_request.purchase_line.unit, gr)
>>> purchase_request.purchase_line.quantity
100.0
Create the purchase request wrong rounding::
>>> ctx = config.context
>>> set_user(0)
>>> pr_id, = PurchaseRequest.create([{
... 'product': product.id,
... 'quantity': 1001,
... 'unit': gr,
... 'warehouse': warehouse_loc.id,
... }], ctx)
>>> set_user()
>>> purchase_request = PurchaseRequest(pr_id)
Create purchase::
>>> create_purchase = Wizard(
... 'purchase.request.create_purchase', [purchase_request])
>>> create_purchase.form.party = supplier
>>> create_purchase.execute('start')
>>> purchase_request.state
'purchased'
>>> assertEqual(purchase_request.purchase_line.unit, gr)
>>> purchase_request.purchase_line.quantity
1050.0

View 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 PurchaseProductQuantityTestCase(ModuleTestCase):
'Test Purchase Product Quantity module'
module = 'purchase_product_quantity'
del ModuleTestCase

View 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)

View File

@@ -0,0 +1,15 @@
[tryton]
version=7.8.0
depends:
ir
product
purchase
purchase_request
xml:
product.xml
[register]
model:
product.ProductSupplier
wizard:
purchase.RequestCreatePurchase

View File

@@ -0,0 +1,11 @@
<?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. -->
<data>
<xpath expr="//label[@name='currency']" position="before">
<label name="quantity_minimal"/>
<field name="quantity_minimal" symbol="unit"/>
<label name="quantity_rounding"/>
<field name="quantity_rounding" symbol="unit"/>
</xpath>
</data>