pass functionality to product and remove dependencies from stock_lot and product_unique variant

This commit is contained in:
Àngel Àlvarez 2022-05-18 12:32:51 +02:00
parent f1cc3268ac
commit eccec1f8aa
6 changed files with 127 additions and 131 deletions

View File

@ -11,7 +11,7 @@ def register():
Pool.register(
product.ExtraProductPackaging,
product.Product,
product.TemplateProductPackaging,
product.ProductProductPackaging,
product.Template,
stock.StockMove,
module=module, type_='model')

View File

@ -6,16 +6,13 @@ from trytond.pyson import Eval, Bool, Id
from trytond.transaction import Transaction
from decimal import Decimal
__all__ = ['Template', 'Product', 'TemplateProductPackaging',
'ExtraProductPackaging']
NON_MEASURABLE = ['service']
class TemplateProductPackaging(ModelSQL, ModelView):
"Template - Product Packaging"
__name__ = 'product.template-product.packaging'
packaging_product = fields.Many2One('product.template', 'Packaging Product',
class ProductProductPackaging(ModelSQL, ModelView):
"Product - Product Packaging"
__name__ = 'product.product-product.packaging'
packaging_product = fields.Many2One('product.product', 'Packaging Product',
required=True, ondelete='CASCADE',
states = {
'readonly': Bool(Eval('packaged_product')),
@ -23,23 +20,22 @@ class TemplateProductPackaging(ModelSQL, ModelView):
domain=[
('packaging', '=', True),
])
product = fields.Many2One('product.template', 'Product', required=True)
product = fields.Many2One('product.product', 'Product', required=True)
packaged_product = fields.Many2One('product.template', 'Packaged Product',
states = {
'readonly': True,
},
)
class ExtraProductPackaging(ModelSQL, ModelView):
"Template - Product Packaging"
__name__ = 'product.template-extra.product'
extra_product = fields.Many2One('product.template', 'Extra Product',
__name__ = 'product.product-extra.product'
extra_product = fields.Many2One('product.product', 'Extra Product',
required=True, ondelete='CASCADE',
states = {
'readonly': Bool(Eval('packaged_product')),
})
product = fields.Many2One('product.template', 'Product', required=True)
product = fields.Many2One('product.product', 'Product', required=True)
unit_digits = fields.Function(fields.Integer('Unit Digits'),
'on_change_with_unit_digits')
quantity = fields.Float('Quantity',
@ -56,27 +52,42 @@ class ExtraProductPackaging(ModelSQL, ModelView):
class Template(metaclass=PoolMeta):
__name__ = 'product.template'
density = fields.Float('Density (kg/m3)',
digits=(16, Eval('weight_digits', 2)),
depends=['weight_digits'])
bulk_type = fields.Boolean('Bulk')
bulk_quantity = fields.Function(fields.Float('Bulk Quantity',
help="The amount of bulk stock in the location."),
'sum_product')
def sum_product(self, name):
if name in ('bulk_quantity'):
sum_ = 0.
for product in self.products:
sum_ += getattr(product, name)
return sum_
return super().sum_product(name)
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
bulk_type = fields.Function(fields.Boolean('Bulk'), 'get_bulk')
bulk_product = fields.Many2One('product.product', 'Bulk Product',
domain=[
('bulk_type', '=', True),
('template.bulk_type', '=', True),
],
states= {
'readonly': (~Eval('active', True) | Eval('bulk_type') == True),
}, depends=['bulk_type'])
bulk_quantity = fields.Function(fields.Float('Bulk Quantity',
help="The amount of bulk stock in the location."),
'sum_product')
'get_bulk_quantity', searcher='search_bulk_quantity')
packaging = fields.Boolean('Packaging')
packaging_products = fields.One2Many('product.template-product.packaging',
packaging_products = fields.One2Many('product.product-product.packaging',
'product', 'Packaging Products',
states = {
'readonly': (~Eval('active', True) | Eval('bulk_type') != True),
})
capacity = fields.Float('Capacity', digits=(16, Eval('capacity_digits', 2)),
capacity_pkg = fields.Float('Capacity', digits=(16, Eval('capacity_digits', 2)),
states={
'invisible': Eval('type').in_(NON_MEASURABLE),
},
@ -105,7 +116,7 @@ class Template(metaclass=PoolMeta):
depends=['type', 'netweight'])
netweight_digits = fields.Function(fields.Integer('Net Weight Digits'),
'on_change_with_netweight_digits')
extra_products = fields.One2Many('product.template-extra.product',
extra_products = fields.One2Many('product.product-extra.product',
'product', 'Extra Products',
states = {
'readonly': (~Eval('active', True) | Eval('bulk_type') != True),
@ -113,11 +124,11 @@ class Template(metaclass=PoolMeta):
@classmethod
def __setup__(cls):
super(Template, cls).__setup__()
cls._modify_no_move += [
('bulk_type', 'product_bulk.msg_product_bulk_type_has_stock'),
('bulk_product', 'product_bulk.msg_product_bulk_product_has_stock'),
]
super().__setup__()
# cls._modify_no_move += [
# ('bulk_type', 'product_bulk.msg_product_bulk_type_has_stock'),
# ('bulk_product', 'product_bulk.msg_product_bulk_product_has_stock'),
# ]
cls._buttons.update({
'create_packaging_products': {
'invisible': (~Eval('active', True)
@ -125,18 +136,6 @@ class Template(metaclass=PoolMeta):
},
})
def sum_product(self, name):
if name in ('bulk_quantity'):
sum_ = 0.
for product in self.products:
sum_ += getattr(product, name)
return sum_
return super().sum_product(name)
@staticmethod
def default_density():
return 0.
@fields.depends('capacity_uom')
def on_change_with_capacity_digits(self, name=None):
return (self.capacity_uom.digits if self.capacity_uom
@ -163,6 +162,9 @@ class Template(metaclass=PoolMeta):
def default_netweight_digits():
return 2
def get_bulk(self, name=None):
return self.template.bulk_type
@classmethod
@ModelView.button
def create_packaging_products(cls, products):
@ -172,7 +174,7 @@ class Template(metaclass=PoolMeta):
BOMInput = Pool().get('production.bom.input')
BOMOutput = Pool().get('production.bom.output')
Uom = Pool().get('product.uom')
ProductPackaging = Pool().get('product.template-product.packaging')
ProductPackaging = Pool().get('product.product-product.packaging')
ProductBom = Pool().get('product.product-production.bom')
uom_unit, = Uom.search([('symbol', 'like', 'u')])
@ -187,18 +189,19 @@ class Template(metaclass=PoolMeta):
if package_product.packaged_product:
continue
new_code = ((bulk_product.products[0].code
if bulk_product.products[0].code else '') + '' +
new_code = ((bulk_product.code
if bulk_product.code else '') + '' +
('-' + package_product.packaging_product.code if
package_product.packaging_product.code else ''))
new_name = (bulk_product.name +
' (' + package_product.packaging_product.name + ')')
netweight = (bulk_product.density *
(package_product.packaging_product.capacity / 1000))
weight = (netweight +
capacity = package_product.packaging_product.capacity_pkg
netweight = round(capacity/ 1000, uom_kg.digits)
weight = round(netweight +
(package_product.packaging_product.weight
if package_product.packaging_product.weight else 0))
if package_product.packaging_product.weight else 0),
uom_kg.digits)
output_template = Template()
output_template.name = new_name
@ -208,27 +211,20 @@ class Template(metaclass=PoolMeta):
output_template.sale_uom = uom_unit
output_template.default_uom = uom_unit
output_template.list_price = Decimal(0)
output_template.netweight = netweight
output_template.netweight_uom = uom_kg
output_template.weight = weight
output_template.weight_uom = uom_kg
output_template.unique_variant = True
output_template.bulk_product = bulk_product.id
output_template.type = bulk_product.type
output_template.account_category = bulk_product.account_category
output_template.categories = bulk_product.categories
output_template.lot_sequence = bulk_product.lot_sequence
output_template.lot_required = bulk_product.lot_required
output_template.expiration_state = bulk_product.expiration_state
output_template.expiration_time = bulk_product.expiration_time
output_template.shelf_life_state = bulk_product.shelf_life_state
output_template.shelf_life_time = bulk_product.shelf_life_time
output_template.capacity = package_product.packaging_product.capacity
output_template.save()
output_product = Product()
output_product.code = new_code
output_product.template = output_template
output_product.capacity_pkg = package_product.packaging_product.capacity
output_product.netweight = netweight
output_product.netweight_uom = uom_kg
output_product.bulk_product = bulk_product.id
output_product.save()
@ -238,13 +234,13 @@ class Template(metaclass=PoolMeta):
bom = Bom(name=new_name)
bulk_input = BOMInput(
bom=bom,
product=bulk_product.products[0],
product=bulk_product,
uom=bulk_product.default_uom,
quantity=netweight)
inputs.append(bulk_input)
package_input = BOMInput(
bom=bom,
product=package_product.packaging_product.products[0],
product=package_product.packaging_product,
uom=package_product.packaging_product.default_uom,
quantity=1.0)
inputs.append(package_input)
@ -253,7 +249,7 @@ class Template(metaclass=PoolMeta):
for extra in bulk_product.extra_products:
extra_input = BOMInput(
bom=bom,
product=extra.extra_product.products[0],
product=extra.extra_product,
uom=extra.extra_product.default_uom,
quantity=extra.quantity)
inputs.append(extra_input)
@ -278,13 +274,6 @@ class Template(metaclass=PoolMeta):
ProductPackaging.save(output_to_save)
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
bulk_quantity = fields.Function(fields.Float('Bulk Quantity',
help="The amount of bulk stock in the location."),
'get_bulk_quantity', searcher='search_bulk_quantity')
@classmethod
def get_bulk_quantity(cls, products, name):
pool = Pool()
@ -298,33 +287,33 @@ class Product(metaclass=PoolMeta):
for product in products:
res[product.id] = 0
location_ids = Transaction().context.get('locations')
if not location_ids:
locations = Location.search(['type', '=', 'warehouse'])
location_ids = [x.storage_location.id for x in locations
if x.storage_location]
# location_ids = Transaction().context.get('locations')
# if not location_ids:
# locations = Location.search(['type', '=', 'warehouse'])
# location_ids = [x.storage_location.id for x in locations
# if x.storage_location]
output_products = Product.search([
('template.bulk_product', 'in', products)
])
output_products_ids = [x.id for x in output_products]
# output_products = Product.search([
# ('bulk_product', 'in', products)
# ])
# output_products_ids = [x.id for x in output_products]
products_ids += [x.id for x in products]
# products_ids += [x.id for x in products]
with Transaction().set_context(locations=location_ids,
stock_date_end=today,
_check_access=False):
# with Transaction().set_context(locations=location_ids,
# stock_date_end=today,
# _check_access=False):
bulk_quantity = cls._get_quantity(output_products, 'quantity',
location_ids, grouping=('product',),
grouping_filter=(output_products_ids,))
quantity = cls._get_quantity(products, 'quantity', location_ids,
grouping=('product',) , grouping_filter=(products_ids,))
# bulk_quantity = cls._get_quantity(output_products, 'quantity',
# location_ids, grouping=('product',),
# grouping_filter=(output_products_ids,))
# quantity = cls._get_quantity(products, 'quantity', location_ids,
# grouping=('product',) , grouping_filter=(products_ids,))
res.update(quantity)
for product in output_products:
res[product.bulk_product.id] += (bulk_quantity.get(product.id,0)
* product.netweight if product.netweight else 0.0)
# res.update(quantity)
# for product in output_products:
# res[product.bulk_product.id] += (bulk_quantity.get(product.id,0)
# * product.netweight if product.netweight else 0.0)
return res
@classmethod

View File

@ -9,7 +9,11 @@
<field name="inherit" ref="product.template_view_form"/>
<field name="name">template_form</field>
</record>
<record model="ir.ui.view" id="product_view_form">
<field name="model">product.product</field>
<field name="inherit" ref="product.product_view_form"/>
<field name="name">product_form</field>
</record>
<!-- relate bulk products -->
<record model="ir.action.act_window" id="act_bulk_product_related">
<field name="name">Bulk products</field>
@ -23,19 +27,19 @@
</record>
<record model="ir.action.act_window" id="act_bulk_product_related_2">
<field name="name">Bulk products</field>
<field name="res_model">product.template</field>
<field name="res_model">product.product</field>
<field name="domain" eval="[('bulk_product.id', '=', Eval('active_id'))]" pyson="1"/>
</record>
<record model="ir.action.keyword" id="act_bulk_product_keyword_2">
<field name="keyword">form_relate</field>
<field name="model">product.template,-1</field>
<field name="model">product.product,-1</field>
<field name="action" ref="act_bulk_product_related_2"/>
</record>
<record model="ir.model.button" id="create_packaging_products_button">
<field name="name">create_packaging_products</field>
<field name="string">Create packaging products</field>
<field name="model" search="[('model', '=', 'product.template')]"/>
<field name="model" search="[('model', '=', 'product.product')]"/>
</record>
<record model="ir.ui.view" id="product_bulk_view_list">
@ -46,7 +50,7 @@
<record model="ir.action.act_window" id="act_product_bulk_stock">
<field name="name">Bulk Products</field>
<field name="res_model">product.template</field>
<field name="res_model">product.product</field>
<field name="domain" eval="[('bulk_type', '=', True)]" pyson="1"/>
</record>
@ -76,14 +80,14 @@
</record>
<record model="ir.ui.view" id="product_packaging_view_list">
<field name="model">product.template-product.packaging</field>
<field name="model">product.product-product.packaging</field>
<field name="type">tree</field>
<field name="name">product_packaging_list</field>
</record>
<record model="ir.ui.view" id="product_extra_packaging_view_list">
<!-- <record model="ir.ui.view" id="product_extra_packaging_view_list">
<field name="model">product.template-extra.product</field>
<field name="type">tree</field>
<field name="name">product_extra_packaging_list</field>
</record>
</record> -->
</data>
</tryton>

View File

@ -4,13 +4,11 @@ depends:
ir
product
product_measurements
product_variant_unique
# product_variant_unique
product_template_form_quantity
production
sale
stock
stock_lot_sequence
stock_lot_sled
xml:
message.xml
product.xml

36
view/product_form.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='general']/field[@name='forecast_quantity']"
position="after">
<label name="bulk_product"/>
<field name="bulk_product"/>
<label name="bulk_quantity"/>
<field name="bulk_quantity"/>
<newline/>
</xpath>
<xpath expr="/form/notebook/page[@id='general']/group[@id='checkboxes']"
position="inside">
<label name="packaging"/>
<field name="packaging" xexpand="0" width="25"/>
</xpath>
<xpath expr="/form/notebook/page[@id='measurements']" position="inside">
<label name="netweight"/>
<field name="netweight"/>
<field name="netweight_uom"/>
<label name="capacity_pkg"/>
<field name="capacity_pkg"/>
<field name="capacity_uom"/>
</xpath>
<xpath expr="/form/notebook" position="inside">
<page id="packaging_products" string="Packaging Products">
<field name="packaging_products" colspan="4"/>
<newline/>
<field name="extra_products" colspan="4"/>
<newline/>
<button name="create_packaging_products"
string="Create packaging products" colspan="2"/>
</page>
</xpath>
</data>

View File

@ -2,40 +2,9 @@
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='general']/field[@name='products']"
position="before">
<label name="density"/>
<field name="density"/>
<label name="bulk_quantity"/>
<field name="bulk_quantity"/>
<newline/>
<label name="bulk_product"/>
<field name="bulk_product"/>
<newline/>
</xpath>
<xpath expr="/form/notebook/page[@id='general']/group[@id='checkboxes']"
position="inside">
<label name="bulk_type"/>
<field name="bulk_type" xexpand="0" width="25"/>
<label name="packaging"/>
<field name="packaging" xexpand="0" width="25"/>
</xpath>
<xpath expr="/form/notebook/page[@id='measurements']" position="inside">
<label name="netweight"/>
<field name="netweight"/>
<field name="netweight_uom"/>
<label name="capacity"/>
<field name="capacity"/>
<field name="capacity_uom"/>
</xpath>
<xpath expr="/form/notebook" position="inside">
<page id="packaging_products" string="Packaging Products">
<field name="packaging_products" colspan="4"/>
<newline/>
<field name="extra_products" colspan="4"/>
<newline/>
<button name="create_packaging_products"
string="Create packaging products" colspan="2"/>
</page>
</xpath>
</data>