mirror of
https://github.com/NaN-tic/trytond-agronomics.git
synced 2023-12-14 05:33:01 +01:00
production template #045158
This commit is contained in:
parent
e813e592eb
commit
da0e5ee7a6
|
@ -7,7 +7,7 @@ from . import plot
|
||||||
from . import product
|
from . import product
|
||||||
from . import weighing
|
from . import weighing
|
||||||
from . import quality
|
from . import quality
|
||||||
|
from . import production
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
|
@ -37,6 +37,13 @@ def register():
|
||||||
quality.QualityTest,
|
quality.QualityTest,
|
||||||
quality.QuantitativeTestLine,
|
quality.QuantitativeTestLine,
|
||||||
quality.QualitativeTestLine,
|
quality.QualitativeTestLine,
|
||||||
|
production.ProductionTemplate,
|
||||||
|
production.ProductionTemplateLine,
|
||||||
|
production.ProductionTemplateInputsProductTemplate,
|
||||||
|
production.ProductionTemplateOutputsProductTemplate,
|
||||||
|
production.Production,
|
||||||
|
production.OutputDistribution,
|
||||||
|
production.ProductionEnologyProduct,
|
||||||
module='agronomics', type_='model')
|
module='agronomics', type_='model')
|
||||||
Pool.register(
|
Pool.register(
|
||||||
module='agronomics', type_='wizard')
|
module='agronomics', type_='wizard')
|
||||||
|
|
21
product.py
21
product.py
|
@ -64,13 +64,21 @@ class Template(metaclass=PoolMeta):
|
||||||
return [('container.capacity',) + tuple(clause[1:])]
|
return [('container.capacity',) + tuple(clause[1:])]
|
||||||
|
|
||||||
|
|
||||||
|
class ProductVariety(ModelSQL, ModelView):
|
||||||
|
'Product Variety'
|
||||||
|
__name__ = 'product.variety'
|
||||||
|
|
||||||
|
variety = fields.Many2One('product.taxon', 'Variety', required=True)
|
||||||
|
percent = fields.Float('Percent', digits=(16, 4), required=True)
|
||||||
|
product = fields.Many2One('product.product', 'Product', required=True)
|
||||||
|
|
||||||
|
|
||||||
class Product(WineMixin, metaclass=PoolMeta):
|
class Product(WineMixin, metaclass=PoolMeta):
|
||||||
__name__ = 'product.product'
|
__name__ = 'product.product'
|
||||||
|
|
||||||
vintages = fields.Many2Many('product.product-agronomics.crop', 'product',
|
vintages = fields.Many2Many('product.product-agronomics.crop', 'product',
|
||||||
'crop', 'Vintages')
|
'crop', 'Vintages')
|
||||||
varieties = fields.Many2Many('product.product-product.taxon', 'product',
|
varieties = fields.One2Many('product.variety', 'product', 'Varieties')
|
||||||
'variety', 'Varieties')
|
|
||||||
denominations_of_origin = fields.Many2Many(
|
denominations_of_origin = fields.Many2Many(
|
||||||
'product.product-agronomics.denomination_of_origin', 'product',
|
'product.product-agronomics.denomination_of_origin', 'product',
|
||||||
'do', 'DOs',
|
'do', 'DOs',
|
||||||
|
@ -131,15 +139,6 @@ class ProductCrop(ModelSQL):
|
||||||
ondelete='CASCADE', select=True, required=True)
|
ondelete='CASCADE', select=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
class ProductVariety(ModelSQL):
|
|
||||||
"Product - Variety"
|
|
||||||
__name__ = 'product.product-product.taxon'
|
|
||||||
product = fields.Many2One('product.product', 'Product',
|
|
||||||
ondelete='CASCADE', select=True, required=True)
|
|
||||||
variety = fields.Many2One('product.taxon', 'Variety',
|
|
||||||
ondelete='CASCADE', select=True, required=True)
|
|
||||||
|
|
||||||
|
|
||||||
class ProductDO(ModelSQL):
|
class ProductDO(ModelSQL):
|
||||||
"Product - DO"
|
"Product - DO"
|
||||||
__name__ = 'product.product-agronomics.denomination_of_origin'
|
__name__ = 'product.product-agronomics.denomination_of_origin'
|
||||||
|
|
339
production.py
Normal file
339
production.py
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
# 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.model import ModelSQL, ModelView, fields
|
||||||
|
from trytond.pool import PoolMeta, Pool
|
||||||
|
from trytond.pyson import Eval, Bool
|
||||||
|
from trytond.exceptions import UserError
|
||||||
|
from trytond.i18n import gettext
|
||||||
|
from decimal import Decimal
|
||||||
|
from trytond.transaction import Transaction
|
||||||
|
|
||||||
|
class ProductionTemplate(ModelSQL, ModelView):
|
||||||
|
"Produciton Template"
|
||||||
|
__name__ = 'production.template'
|
||||||
|
|
||||||
|
name = fields.Char('Name', required=True)
|
||||||
|
uom = fields.Many2One('product.uom', 'Uom', required=True)
|
||||||
|
unit_digits = fields.Function(fields.Integer('Unit Digits'),
|
||||||
|
'on_change_with_unit_digits')
|
||||||
|
quantity = fields.Float('Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'])
|
||||||
|
|
||||||
|
inputs = fields.Many2Many('production.template.inputs-product.template',
|
||||||
|
'production_template', 'template', "Inputs")
|
||||||
|
|
||||||
|
outputs = fields.Many2Many('production.template.outputs-product.template',
|
||||||
|
'production_template', 'template', "Outputs")
|
||||||
|
|
||||||
|
enology_products = fields.One2Many('production.template.line',
|
||||||
|
'production_template', 'Production Template')
|
||||||
|
pass_feature = fields.Boolean('Pass on Feature')
|
||||||
|
|
||||||
|
@fields.depends('uom')
|
||||||
|
def on_change_with_unit_digits(self, name=None):
|
||||||
|
if self.uom:
|
||||||
|
return self.uom.digits
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def check_input_uoms(cls, records):
|
||||||
|
for record in records:
|
||||||
|
category_uom = record.uom.category
|
||||||
|
uoms = [i.default_uom.category for i in record.inputs]
|
||||||
|
if not all(uoms+[category_uom]):
|
||||||
|
raise UserError(gettext('agronomics.msg_uom_not_fit',
|
||||||
|
production=record.rec_name,
|
||||||
|
uom=record.uom.rec_name,
|
||||||
|
uoms=",".join([x.rec_name for x in set(uoms)])))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(cls, records):
|
||||||
|
super().validate(records)
|
||||||
|
cls.check_input_uoms(records)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductionTemplateInputsProductTemplate(ModelSQL):
|
||||||
|
'Production Template Inputs- Product Template'
|
||||||
|
__name__ = 'production.template.inputs-product.template'
|
||||||
|
production_template = fields.Many2One('production.template',
|
||||||
|
'Production Template', ondelete='CASCADE', required=True, select=True)
|
||||||
|
template = fields.Many2One('product.template', 'Template',
|
||||||
|
ondelete='CASCADE', required=True, select=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductionTemplateOutputsProductTemplate(ModelSQL):
|
||||||
|
'Production Template Inputs- Product Template'
|
||||||
|
__name__ = 'production.template.outputs-product.template'
|
||||||
|
production_template = fields.Many2One('production.template',
|
||||||
|
'Production Template', ondelete='CASCADE', required=True, select=True)
|
||||||
|
template = fields.Many2One('product.template', 'Product',
|
||||||
|
ondelete='CASCADE', required=True, select=True)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductionTemplateLine(ModelSQL, ModelView):
|
||||||
|
"Production Template Line"
|
||||||
|
__name__ = 'production.template.line'
|
||||||
|
|
||||||
|
product = fields.Many2One('product.product', 'Producte', required=True)
|
||||||
|
uom = fields.Many2One('product.uom', 'Uom')
|
||||||
|
unit_digits = fields.Function(fields.Integer('Unit Digits'),
|
||||||
|
'on_change_with_unit_digits')
|
||||||
|
quantity = fields.Float('Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'])
|
||||||
|
production_template = fields.Many2One('production.template',
|
||||||
|
'Production Template')
|
||||||
|
|
||||||
|
@fields.depends('uom')
|
||||||
|
def on_change_with_unit_digits(self, name=None):
|
||||||
|
if self.uom:
|
||||||
|
return self.uom.digits
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@fields.depends('product')
|
||||||
|
def on_change_with_uom(self):
|
||||||
|
if not self.product:
|
||||||
|
return
|
||||||
|
return self.product.default_uom and self.product.default_uom.id
|
||||||
|
|
||||||
|
|
||||||
|
class Production(metaclass=PoolMeta):
|
||||||
|
__name__ = 'production'
|
||||||
|
|
||||||
|
production_template = fields.Many2One('production.template',
|
||||||
|
'Production Template')
|
||||||
|
enology_products = fields.One2Many('production.enology.product',
|
||||||
|
'production', "Enology Products",
|
||||||
|
domain=[('product', 'in', Eval('allowed_enology_products')),
|
||||||
|
('product.quantity', '>', 0)],
|
||||||
|
states={
|
||||||
|
'invisible': ~Bool(Eval('production_template'))
|
||||||
|
}, depends=['allowed_enology_products'])
|
||||||
|
output_distribution = fields.One2Many('production.output.distribution',
|
||||||
|
'production', 'Output Distribution',
|
||||||
|
# domain=[('product', 'in', Eval('allowed_ouput_products'))],
|
||||||
|
states={
|
||||||
|
'invisible': ~Bool(Eval('production_template'))
|
||||||
|
}, depends=['allowed_output_products'])
|
||||||
|
allowed_enology_products = fields.Function(fields.One2Many(
|
||||||
|
'product.product', None, 'Allowed Enology Products', readonly=True),
|
||||||
|
'on_change_with_allowed_enology_products',
|
||||||
|
setter='set_allowed_products')
|
||||||
|
allowed_output_products = fields.Function(fields.One2Many(
|
||||||
|
'product.template', None, 'Allowed Output Products', readonly=True),
|
||||||
|
'on_change_with_allowed_output_products',
|
||||||
|
setter='set_allowed_products')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_allowed_products(cls, productions, name, value):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@fields.depends('production_template')
|
||||||
|
def on_change_with_allowed_enology_products(self, name=None):
|
||||||
|
products = []
|
||||||
|
if not self.production_template:
|
||||||
|
return []
|
||||||
|
for template in self.production_template.inputs:
|
||||||
|
products += template.products
|
||||||
|
return [x.id for x in products]
|
||||||
|
|
||||||
|
@fields.depends('production_template')
|
||||||
|
def on_change_with_allowed_output_products(self, name=None):
|
||||||
|
if not self.production_template:
|
||||||
|
return []
|
||||||
|
return [x.id for x in self.production_template.outputs]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def wait(cls, productions):
|
||||||
|
Move = Pool().get('stock.move')
|
||||||
|
Uom = Pool().get('product.uom')
|
||||||
|
moves = []
|
||||||
|
delete = []
|
||||||
|
for production in productions:
|
||||||
|
delete = [x for x in production.inputs]
|
||||||
|
input_quantity = 0
|
||||||
|
for enology in production.enology_products:
|
||||||
|
move = production._move(production.picking_location,
|
||||||
|
production.location,
|
||||||
|
production.company,
|
||||||
|
enology.product,
|
||||||
|
enology.uom.id,
|
||||||
|
enology.quantity)
|
||||||
|
move.production_input = production
|
||||||
|
moves.append(move)
|
||||||
|
input_quantity += Uom.compute_qty(enology.uom, enology.quantity,
|
||||||
|
production.production_template.uom)
|
||||||
|
enology_products = (production.production_template and
|
||||||
|
production.production_template.enology_products or [])
|
||||||
|
for enology in enology_products:
|
||||||
|
quantity = Uom.compute_qty(enology.uom, enology.quantity,
|
||||||
|
production.production_template.uom)
|
||||||
|
ratio = quantity / (input_quantity or 1)
|
||||||
|
qty = Decimal(str(input_quantity*ratio))
|
||||||
|
move = production._move(production.picking_location,
|
||||||
|
production.location,
|
||||||
|
production.company,
|
||||||
|
enology.product,
|
||||||
|
enology.uom.id,
|
||||||
|
float(qty))
|
||||||
|
move.production_input = production
|
||||||
|
moves.append(move)
|
||||||
|
|
||||||
|
Move.save(moves)
|
||||||
|
Move.delete(delete)
|
||||||
|
super().wait(productions)
|
||||||
|
|
||||||
|
def create_variant(self, template, pass_feature):
|
||||||
|
Product = Pool().get('product.product')
|
||||||
|
product = Product()
|
||||||
|
product.template = template
|
||||||
|
return product
|
||||||
|
|
||||||
|
def pass_feature(self, product):
|
||||||
|
Variety = Pool().get('product.variety')
|
||||||
|
Uom = Pool().get('product.uom')
|
||||||
|
total_output = sum([Uom.compute_qty(x.uom, x.quantity,
|
||||||
|
x.product.default_uom)
|
||||||
|
for x in self.inputs])
|
||||||
|
vintages = []
|
||||||
|
do = []
|
||||||
|
ecologicals = []
|
||||||
|
for input in self.inputs:
|
||||||
|
vintages += input.product.vintages
|
||||||
|
do += input.product.denominations_of_origin
|
||||||
|
ecologicals = input.product.ecologicals
|
||||||
|
|
||||||
|
product.denominations_of_origin = list(set(do))
|
||||||
|
product.ecologicals = list(set(ecologicals))
|
||||||
|
product.vintages = list(set(vintages))
|
||||||
|
varieties = {}
|
||||||
|
for input in self.inputs:
|
||||||
|
percent = round(input.quantity/total_output, 2)
|
||||||
|
for variety in input.product.varieties:
|
||||||
|
new_variety = varieties.get(variety.variety)
|
||||||
|
if not new_variety:
|
||||||
|
new_variety = Variety()
|
||||||
|
new_variety.percent = 0
|
||||||
|
new_variety.variety = variety.variety
|
||||||
|
new_variety.percent += variety.percent/100*percent
|
||||||
|
varieties[new_variety.variety] = new_variety
|
||||||
|
for key, variety in varieties.items():
|
||||||
|
variety.percent = "%.4f" % round(100*variety.percent, 4)
|
||||||
|
product.varieties = varieties.values()
|
||||||
|
return product
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def done(cls, productions):
|
||||||
|
Move = Pool().get('stock.move')
|
||||||
|
moves = []
|
||||||
|
for production in productions:
|
||||||
|
for distrib in production.output_distribution:
|
||||||
|
product = production.create_variant(distrib.product,
|
||||||
|
production.production_template.pass_feature)
|
||||||
|
product = production.pass_feature(product)
|
||||||
|
move = production._move(production.location,
|
||||||
|
distrib.location,
|
||||||
|
production.company,
|
||||||
|
product,
|
||||||
|
distrib.uom,
|
||||||
|
distrib.produced_quantity)
|
||||||
|
move.production_output = production
|
||||||
|
move.unit_price = Decimal(0)
|
||||||
|
moves.append(move)
|
||||||
|
Move.save(moves)
|
||||||
|
super().done(productions)
|
||||||
|
|
||||||
|
class OutputDistribution(ModelSQL, ModelView):
|
||||||
|
'Output Distribution'
|
||||||
|
__name__ = 'production.output.distribution'
|
||||||
|
|
||||||
|
production = fields.Many2One('production', 'Production',
|
||||||
|
required=True)
|
||||||
|
product = fields.Many2One('product.template', 'Template', required=True)
|
||||||
|
location = fields.Many2One('stock.location', 'Location', required=True)
|
||||||
|
uom = fields.Many2One('product.uom', 'Uom')
|
||||||
|
unit_digits = fields.Function(fields.Integer('Unit Digits'),
|
||||||
|
'on_change_with_unit_digits')
|
||||||
|
initial_quantity = fields.Float('Initial Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'], readonly=True)
|
||||||
|
final_quantity = fields.Float('Final Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'], readonly=True)
|
||||||
|
produced_quantity = fields.Float('Produced Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'])
|
||||||
|
|
||||||
|
@fields.depends('product')
|
||||||
|
def on_change_with_uom(self):
|
||||||
|
if not self.product:
|
||||||
|
return
|
||||||
|
return self.product.default_uom and self.product.default_uom.id
|
||||||
|
|
||||||
|
@fields.depends('uom')
|
||||||
|
def on_change_with_unit_digits(self, name=None):
|
||||||
|
if self.uom:
|
||||||
|
return self.uom.digits
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@fields.depends('initial_quantity', 'final_quantity', 'produced_quantity',
|
||||||
|
'location', 'product')
|
||||||
|
def on_change_product(self):
|
||||||
|
Product = Pool().get('product.product')
|
||||||
|
if not self.product:
|
||||||
|
self.initial_quantity = 0
|
||||||
|
self.final_quantity = self.produced_quantity
|
||||||
|
return
|
||||||
|
if not self.location:
|
||||||
|
return
|
||||||
|
context = Transaction().context
|
||||||
|
context['locations'] = [self.location.id]
|
||||||
|
with Transaction().set_context(context):
|
||||||
|
quantities = Product.get_quantity(self.product.products, 'quantity')
|
||||||
|
|
||||||
|
self.initial_quantity = sum(quantities.values())
|
||||||
|
self.final_quantity = self.initial_quantity + (self.produced_quantity
|
||||||
|
or 0)
|
||||||
|
|
||||||
|
@fields.depends('location', methods=['on_change_product'])
|
||||||
|
def on_change_location(self):
|
||||||
|
if not self.location:
|
||||||
|
return
|
||||||
|
self.on_change_product()
|
||||||
|
|
||||||
|
@fields.depends('produced_quantity', 'final_quantity', 'initial_quantity')
|
||||||
|
def on_change_produced_quantity(self):
|
||||||
|
self.final_quantity = ((self.initial_quantity or 0) +
|
||||||
|
(self.produced_quantity or 0))
|
||||||
|
|
||||||
|
class ProductionEnologyProduct(ModelSQL, ModelView):
|
||||||
|
'Production Enology Product'
|
||||||
|
__name__ = 'production.enology.product'
|
||||||
|
production = fields.Many2One('production', 'Production',
|
||||||
|
select=True)
|
||||||
|
product = fields.Many2One('product.product', 'Product', required=True)
|
||||||
|
uom = fields.Many2One('product.uom', 'Uom')
|
||||||
|
unit_digits = fields.Function(fields.Integer('Unit Digits'),
|
||||||
|
'on_change_with_unit_digits')
|
||||||
|
quantity = fields.Float('Quantity',
|
||||||
|
digits=(16, Eval('unit_digits', 2)),
|
||||||
|
depends=['unit_digits'])
|
||||||
|
|
||||||
|
@fields.depends('uom')
|
||||||
|
def on_change_with_unit_digits(self, name=None):
|
||||||
|
if self.uom:
|
||||||
|
return self.uom.digits
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@fields.depends('product')
|
||||||
|
def on_change_with_uom(self):
|
||||||
|
if not self.product:
|
||||||
|
return
|
||||||
|
return self.product.default_uom and self.product.default_uom.id
|
||||||
|
|
||||||
|
@fields.depends('product')
|
||||||
|
def on_change_product(self):
|
||||||
|
if not self.product:
|
||||||
|
return
|
||||||
|
self.quantity = self.product.quantity
|
114
production.xml
Normal file
114
production.xml
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<tryton>
|
||||||
|
<data>
|
||||||
|
<!-- Production Template -->
|
||||||
|
<record model="ir.ui.view" id="production_template_view_form">
|
||||||
|
<field name="model">production.template</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">production_template_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="production_template_view_tree">
|
||||||
|
<field name="model">production.template</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="priority" eval="20"/>
|
||||||
|
<field name="name">production_template_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_production_template_tree">
|
||||||
|
<field name="name">Production Template</field>
|
||||||
|
<field name="res_model">production.template</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window.view" id="act_production_template_tree_view">
|
||||||
|
<field name="sequence" eval="10"/>
|
||||||
|
<field name="view" ref="production_template_view_tree"/>
|
||||||
|
<field name="act_window" ref="act_production_template_tree"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.action.act_window.view" id="act_production_template_form_view">
|
||||||
|
<field name="sequence" eval="20"/>
|
||||||
|
<field name="view" ref="production_template_view_form"/>
|
||||||
|
<field name="act_window" ref="act_production_template_tree"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem parent="production.menu_configuration" sequence="1"
|
||||||
|
action="act_production_template_tree" id="menu_production_template_list"/>
|
||||||
|
|
||||||
|
<record model="ir.ui.menu-res.group"
|
||||||
|
id="menu_production_template_list_group_productions">
|
||||||
|
<field name="menu" ref="menu_production_template_list"/>
|
||||||
|
<field name="group" ref="production.group_production"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.menu-res.group"
|
||||||
|
id="menu_production_template_list_group_productions_admin">
|
||||||
|
<field name="menu" ref="menu_production_template_list"/>
|
||||||
|
<field name="group" ref="production.group_production_admin"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Production Template Line -->
|
||||||
|
<record model="ir.ui.view" id="production_template_line_view_form">
|
||||||
|
<field name="model">production.template.line</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">production_template_line_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="production_template_line_view_tree">
|
||||||
|
<field name="model">production.template.line</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="priority" eval="20"/>
|
||||||
|
<field name="name">production_template_line_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_production_template_line_tree">
|
||||||
|
<field name="name">Production Template Line</field>
|
||||||
|
<field name="res_model">production.template.line</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Production Output Distribution -->
|
||||||
|
<record model="ir.ui.view" id="production_output_distribution_view_form">
|
||||||
|
<field name="model">production.output.distribution</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">production_output_distribution_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="production_output_distribution_view_tree">
|
||||||
|
<field name="model">production.output.distribution</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="priority" eval="20"/>
|
||||||
|
<field name="name">production_output_distribution_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_production_output_distribution_tree">
|
||||||
|
<field name="name">Production Output Distribution</field>
|
||||||
|
<field name="res_model">production.output.distribution</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Production Enology -->
|
||||||
|
<record model="ir.ui.view" id="production_enology_product_view_form">
|
||||||
|
<field name="model">production.enology.product</field>
|
||||||
|
<field name="type">form</field>
|
||||||
|
<field name="name">production_enology_product_form</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.ui.view" id="production_enology_product_view_tree">
|
||||||
|
<field name="model">production.enology.product</field>
|
||||||
|
<field name="type">tree</field>
|
||||||
|
<field name="priority" eval="20"/>
|
||||||
|
<field name="name">production_enology_product_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.action.act_window" id="act_production_enology_product_tree">
|
||||||
|
<field name="name">Production Enology Product</field>
|
||||||
|
<field name="res_model">production.enology.product</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="production_view_form">
|
||||||
|
<field name="model">production</field>
|
||||||
|
<field name="inherit" ref="production.production_view_form"/>
|
||||||
|
<field name="name">production_form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="production_view_list">
|
||||||
|
<field name="model">production</field>
|
||||||
|
<field name="inherit" ref="production.production_view_list"/>
|
||||||
|
<field name="name">production_list</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</tryton>
|
329
tests/scenario_production_template.rst
Normal file
329
tests/scenario_production_template.rst
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
===================
|
||||||
|
Production Scenario
|
||||||
|
===================
|
||||||
|
|
||||||
|
Imports::
|
||||||
|
|
||||||
|
>>> import datetime
|
||||||
|
>>> from dateutil.relativedelta import relativedelta
|
||||||
|
>>> from decimal import Decimal
|
||||||
|
>>> from proteus import Model, Wizard
|
||||||
|
>>> from trytond.tests.tools import activate_modules
|
||||||
|
>>> from trytond.modules.company.tests.tools import create_company, \
|
||||||
|
... get_company
|
||||||
|
>>> from trytond.modules.production.production import BOM_CHANGES
|
||||||
|
>>> today = datetime.date.today()
|
||||||
|
>>> yesterday = today - relativedelta(days=1)
|
||||||
|
>>> before_yesterday = yesterday - relativedelta(days=1)
|
||||||
|
|
||||||
|
Activate modules::
|
||||||
|
|
||||||
|
>>> config = activate_modules('agronomics')
|
||||||
|
|
||||||
|
Create company::
|
||||||
|
|
||||||
|
>>> _ = create_company()
|
||||||
|
>>> company = get_company()
|
||||||
|
|
||||||
|
|
||||||
|
Create product::
|
||||||
|
|
||||||
|
>>> ProductUom = Model.get('product.uom')
|
||||||
|
>>> liter, = ProductUom.find([('name', '=', 'Liter')])
|
||||||
|
>>> kg, = ProductUom.find([('name', '=', 'Kilogram')])
|
||||||
|
|
||||||
|
>>> ProductTemplate = Model.get('product.template')
|
||||||
|
>>> Product = Model.get('product.product')
|
||||||
|
>>> Taxon = Model.get('product.taxon')
|
||||||
|
>>> DO = Model.get('agronomics.denomination_of_origin')
|
||||||
|
>>> Ecological = Model.get('agronomics.ecological')
|
||||||
|
|
||||||
|
Create Denomination Of Origin::
|
||||||
|
|
||||||
|
>>> catalunya = DO()
|
||||||
|
>>> catalunya.name = 'Catalunya'
|
||||||
|
>>> catalunya.save()
|
||||||
|
|
||||||
|
>>> barcelona = DO()
|
||||||
|
>>> barcelona.name = 'Barcelona'
|
||||||
|
>>> barcelona.save()
|
||||||
|
|
||||||
|
Create Taxon::
|
||||||
|
|
||||||
|
>>> macabeu = Taxon()
|
||||||
|
>>> macabeu.rank = 'variety'
|
||||||
|
>>> macabeu.name = 'Macabeu'
|
||||||
|
>>> macabeu.save()
|
||||||
|
|
||||||
|
>>> parellada = Taxon()
|
||||||
|
>>> parellada.rank = 'variety'
|
||||||
|
>>> parellada.name = 'Parellada'
|
||||||
|
>>> parellada.save()
|
||||||
|
|
||||||
|
Create Ecological::
|
||||||
|
|
||||||
|
>>> ecological = Ecological()
|
||||||
|
>>> ecological.name = 'Ecological'
|
||||||
|
>>> ecological.save()
|
||||||
|
|
||||||
|
# Raim Blanc
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'Raim Blanc'
|
||||||
|
>>> template.default_uom = kg
|
||||||
|
>>> template.type = 'goods'
|
||||||
|
>>> template.producible = True
|
||||||
|
>>> template.list_price = Decimal(0)
|
||||||
|
>>> product, = template.products
|
||||||
|
>>> product.cost_price = Decimal(10)
|
||||||
|
>>> template.save()
|
||||||
|
>>> product, = template.products
|
||||||
|
>>> productA = Product()
|
||||||
|
>>> productA.code = "A"
|
||||||
|
>>> productA.template = template
|
||||||
|
>>> productA.denominations_of_origin.append(catalunya)
|
||||||
|
>>> productA.save()
|
||||||
|
>>> catalunya, = DO.find([('name', '=', 'Catalunya')])
|
||||||
|
>>> productB = Product()
|
||||||
|
>>> productB.code = "B"
|
||||||
|
>>> productB.template = template
|
||||||
|
>>> productB.denominations_of_origin.append(catalunya)
|
||||||
|
>>> productB.save()
|
||||||
|
>>> catalunya, = DO.find([('name', '=' , 'Catalunya')])
|
||||||
|
>>> productC = Product()
|
||||||
|
>>> productC.code = "C"
|
||||||
|
>>> productC.template = template
|
||||||
|
>>> productC.denominations_of_origin.append(catalunya)
|
||||||
|
>>> productC.save()
|
||||||
|
|
||||||
|
Create Variety::
|
||||||
|
|
||||||
|
>>> Variety = Model.get('product.variety')
|
||||||
|
>>> AM = Variety()
|
||||||
|
>>> AM.variety = macabeu
|
||||||
|
>>> AM.percent = 100.0
|
||||||
|
>>> AM.product = productA
|
||||||
|
>>> AM.save()
|
||||||
|
|
||||||
|
>>> BM = Variety()
|
||||||
|
>>> BM.variety = macabeu
|
||||||
|
>>> BM.percent = 100.0
|
||||||
|
>>> BM.product = productB
|
||||||
|
>>> BM.save()
|
||||||
|
|
||||||
|
>>> CP = Variety()
|
||||||
|
>>> CP.variety = parellada
|
||||||
|
>>> CP.percent = 100.0
|
||||||
|
>>> CP.product = productC
|
||||||
|
>>> CP.save()
|
||||||
|
|
||||||
|
# Sulforos
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'Sulforos'
|
||||||
|
>>> template.default_uom = kg
|
||||||
|
>>> template.type = 'goods'
|
||||||
|
>>> template.producible = True
|
||||||
|
>>> template.list_price = Decimal(0)
|
||||||
|
>>> product2, = template.products
|
||||||
|
>>> product2.cost_price = Decimal(10)
|
||||||
|
>>> template.save()
|
||||||
|
>>> product2, = template.products
|
||||||
|
|
||||||
|
# Encims
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'Encims'
|
||||||
|
>>> template.default_uom = kg
|
||||||
|
>>> template.type = 'goods'
|
||||||
|
>>> template.producible = True
|
||||||
|
>>> template.list_price = Decimal(0)
|
||||||
|
>>> product3, = template.products
|
||||||
|
>>> product3.cost_price = Decimal(10)
|
||||||
|
>>> template.save()
|
||||||
|
>>> product3, = template.products
|
||||||
|
|
||||||
|
# Carbo actiu
|
||||||
|
>>> template = ProductTemplate()
|
||||||
|
>>> template.name = 'Carbo actiu'
|
||||||
|
>>> template.default_uom = kg
|
||||||
|
>>> template.type = 'goods'
|
||||||
|
>>> template.producible = True
|
||||||
|
>>> template.list_price = Decimal(0)
|
||||||
|
>>> product4, = template.products
|
||||||
|
>>> product4.cost_price = Decimal(10)
|
||||||
|
>>> template.save()
|
||||||
|
>>> product4, = template.products
|
||||||
|
|
||||||
|
# Most flor
|
||||||
|
>>> mostflor = ProductTemplate()
|
||||||
|
>>> mostflor.name = 'Most Flor'
|
||||||
|
>>> mostflor.default_uom = liter
|
||||||
|
>>> mostflor.type = 'goods'
|
||||||
|
>>> mostflor.producible = True
|
||||||
|
>>> mostflor.list_price = Decimal(0)
|
||||||
|
>>> mostflor.save()
|
||||||
|
>>> product5, = mostflor.products
|
||||||
|
>>> product5.cost_price = Decimal(0)
|
||||||
|
>>> product5.save()
|
||||||
|
|
||||||
|
# Most Primeres
|
||||||
|
>>> mostprimeres = ProductTemplate()
|
||||||
|
>>> mostprimeres.name = 'Most Primeres'
|
||||||
|
>>> mostprimeres.default_uom = liter
|
||||||
|
>>> mostprimeres.type = 'goods'
|
||||||
|
>>> mostprimeres.producible = True
|
||||||
|
>>> mostprimeres.list_price = Decimal(0)
|
||||||
|
>>> mostprimeres.save()
|
||||||
|
>>> product6, = mostprimeres.products
|
||||||
|
>>> product6.cost_price = Decimal(0)
|
||||||
|
>>> product6.save()
|
||||||
|
|
||||||
|
Create Production Template::
|
||||||
|
|
||||||
|
>>> ProductionTemplate = Model.get('production.template')
|
||||||
|
>>> ProductionTemplateLine = Model.get("production.template.line")
|
||||||
|
>>> production_template = ProductionTemplate()
|
||||||
|
>>> production_template.name = 'Premsat i desfangat de raim blanc'
|
||||||
|
>>> production_template.uom = kg
|
||||||
|
>>> production_template.quantity = 10000
|
||||||
|
>>> production_template.pass_feature = True
|
||||||
|
>>> production_template.inputs.append(product.template)
|
||||||
|
>>> production_template.outputs.append(mostflor)
|
||||||
|
>>> production_template.outputs.append(mostprimeres)
|
||||||
|
>>> line = ProductionTemplateLine()
|
||||||
|
>>> line.product = product2
|
||||||
|
>>> line.quantity = 100
|
||||||
|
>>> production_template.enology_products.append(line)
|
||||||
|
>>> line = ProductionTemplateLine()
|
||||||
|
>>> line.product = product3
|
||||||
|
>>> line.quantity = 50
|
||||||
|
>>> production_template.enology_products.append(line)
|
||||||
|
>>> line = ProductionTemplateLine()
|
||||||
|
>>> line.product = product4
|
||||||
|
>>> line.quantity =150
|
||||||
|
>>> production_template.enology_products.append(line)
|
||||||
|
>>> production_template.save()
|
||||||
|
|
||||||
|
|
||||||
|
Create an Inventory::
|
||||||
|
|
||||||
|
>>> Inventory = Model.get('stock.inventory')
|
||||||
|
>>> InventoryLine = Model.get('stock.inventory.line')
|
||||||
|
>>> Location = Model.get('stock.location')
|
||||||
|
>>> storage, = Location.find([
|
||||||
|
... ('code', '=', 'STO'),
|
||||||
|
... ])
|
||||||
|
>>> inventory = Inventory()
|
||||||
|
>>> inventory.location = storage
|
||||||
|
>>> inventory_line1 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line1)
|
||||||
|
>>> inventory_line1.product = productA
|
||||||
|
>>> inventory_line1.quantity = 5000
|
||||||
|
>>> inventory_line2 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line2)
|
||||||
|
>>> inventory_line2.product = productB
|
||||||
|
>>> inventory_line2.quantity = 10000
|
||||||
|
>>> inventory_line3 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line3)
|
||||||
|
>>> inventory_line3.product = productC
|
||||||
|
>>> inventory_line3.quantity = 3000
|
||||||
|
|
||||||
|
>>> inventory_line3 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line3)
|
||||||
|
>>> inventory_line3.product = product2
|
||||||
|
>>> inventory_line3.quantity = 1000
|
||||||
|
|
||||||
|
>>> inventory_line3 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line3)
|
||||||
|
>>> inventory_line3.product = product3
|
||||||
|
>>> inventory_line3.quantity = 1000
|
||||||
|
|
||||||
|
>>> inventory_line3 = InventoryLine()
|
||||||
|
>>> inventory.lines.append(inventory_line3)
|
||||||
|
>>> inventory_line3.product = product4
|
||||||
|
>>> inventory_line3.quantity = 1000
|
||||||
|
|
||||||
|
>>> inventory.click('confirm')
|
||||||
|
>>> inventory.state
|
||||||
|
'done'
|
||||||
|
|
||||||
|
Create Production
|
||||||
|
|
||||||
|
>>> Production = Model.get('production')
|
||||||
|
>>> EnologyProduct = Model.get('production.enology.product')
|
||||||
|
>>> production = Production()
|
||||||
|
>>> production.production_template = production_template
|
||||||
|
>>> production.save()
|
||||||
|
>>> line = EnologyProduct()
|
||||||
|
>>> line.product = productA
|
||||||
|
>>> line.production = production
|
||||||
|
>>> line.quantity = 5000
|
||||||
|
>>> line.save()
|
||||||
|
>>> # production.enology_products.append(productA)
|
||||||
|
>>> line = EnologyProduct()
|
||||||
|
>>> line.product = productB
|
||||||
|
>>> line.quantity = 10000
|
||||||
|
>>> line.production = production
|
||||||
|
>>> line.save()
|
||||||
|
>>> # production.enology_products.append(productB)
|
||||||
|
>>> line = EnologyProduct()
|
||||||
|
>>> line.product = productC
|
||||||
|
>>> line.quantity = 3000
|
||||||
|
>>> line.production = production
|
||||||
|
>>> line.save()
|
||||||
|
>>> # production.enology_products.append(productC)
|
||||||
|
>>> production.reload()
|
||||||
|
>>> production.click('wait')
|
||||||
|
>>> production.state
|
||||||
|
'waiting'
|
||||||
|
>>> len(production.inputs)
|
||||||
|
6
|
||||||
|
>>> input, = [i for i in production.inputs if i.product == product2]
|
||||||
|
>>> input.quantity
|
||||||
|
100.0
|
||||||
|
>>> input, = [i for i in production.inputs if i.product == product3]
|
||||||
|
>>> input.quantity
|
||||||
|
50.0
|
||||||
|
>>> input, = [i for i in production.inputs if i.product == product4]
|
||||||
|
>>> input.quantity
|
||||||
|
150.0
|
||||||
|
|
||||||
|
>>> OutputDistribution = Model.get('production.output.distribution')
|
||||||
|
>>> m1 = OutputDistribution()
|
||||||
|
>>> m1.production = production
|
||||||
|
>>> m1.product = mostflor
|
||||||
|
>>> m1.location = storage
|
||||||
|
>>> m1.produced_quantity = 3000
|
||||||
|
>>> production.output_distribution.append(m1)
|
||||||
|
|
||||||
|
>>> m2 = OutputDistribution()
|
||||||
|
>>> m2.production = production
|
||||||
|
>>> m2.product = mostflor
|
||||||
|
>>> m2.location = storage
|
||||||
|
>>> m2.produced_quantity = 1500
|
||||||
|
>>> production.output_distribution.append(m2)
|
||||||
|
|
||||||
|
>>> m3 = OutputDistribution()
|
||||||
|
>>> m3.production = production
|
||||||
|
>>> m3.product = mostprimeres
|
||||||
|
>>> m3.location = storage
|
||||||
|
>>> m3.produced_quantity = 3500
|
||||||
|
>>> production.output_distribution.append(m3)
|
||||||
|
>>> #import pdb; pdb.set_trace()
|
||||||
|
>>> production.save()
|
||||||
|
>>> production.reload()
|
||||||
|
>>> len(production.output_distribution)
|
||||||
|
3
|
||||||
|
>>> #[x.name for x in production.allowed_output_products]
|
||||||
|
>>> #[x.name for x in production.production_template.outputs]
|
||||||
|
>>> production.click('assign_try')
|
||||||
|
True
|
||||||
|
>>> production.click('run')
|
||||||
|
>>> production.click('done')
|
||||||
|
>>> len(production.outputs)
|
||||||
|
3
|
||||||
|
>>> most = production.outputs[0]
|
||||||
|
>>> len(most.product.varieties)
|
||||||
|
2
|
||||||
|
>>> [(x.variety.name, x.percent) for x in most.product.varieties]
|
||||||
|
[('Parellada', 16.0), ('Macabeu', 82.0)]
|
||||||
|
>>> [x.name for x in most.product.denominations_of_origin]
|
||||||
|
['Catalunya']
|
|
@ -2,10 +2,11 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains
|
# The COPYRIGHT file at the top level of this repository contains
|
||||||
# the full copyright notices and license terms.
|
# the full copyright notices and license terms.
|
||||||
import unittest
|
import unittest
|
||||||
|
import doctest
|
||||||
|
|
||||||
from trytond.tests.test_tryton import ModuleTestCase
|
from trytond.tests.test_tryton import ModuleTestCase
|
||||||
from trytond.tests.test_tryton import suite as test_suite
|
from trytond.tests.test_tryton import suite as test_suite
|
||||||
|
from trytond.tests.test_tryton import doctest_teardown
|
||||||
|
from trytond.tests.test_tryton import doctest_checker
|
||||||
|
|
||||||
|
|
||||||
class AgronomicsTestCase(ModuleTestCase):
|
class AgronomicsTestCase(ModuleTestCase):
|
||||||
|
@ -17,4 +18,8 @@ def suite():
|
||||||
suite = test_suite()
|
suite = test_suite()
|
||||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
|
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
|
||||||
AgronomicsTestCase))
|
AgronomicsTestCase))
|
||||||
|
suite.addTests(doctest.DocFileSuite('scenario_production_template.rst',
|
||||||
|
tearDown=doctest_teardown, encoding='utf-8',
|
||||||
|
checker=doctest_checker,
|
||||||
|
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||||
return suite
|
return suite
|
||||||
|
|
|
@ -6,8 +6,10 @@ depends:
|
||||||
party
|
party
|
||||||
product_classification
|
product_classification
|
||||||
product_classification_taxonomic
|
product_classification_taxonomic
|
||||||
|
product_template_form_quantity
|
||||||
quality_control_sample
|
quality_control_sample
|
||||||
purchase_contract
|
purchase_contract
|
||||||
|
production
|
||||||
xml:
|
xml:
|
||||||
plot.xml
|
plot.xml
|
||||||
party.xml
|
party.xml
|
||||||
|
@ -15,3 +17,4 @@ xml:
|
||||||
weighning.xml
|
weighning.xml
|
||||||
wine.xml
|
wine.xml
|
||||||
message.xml
|
message.xml
|
||||||
|
production.xml
|
||||||
|
|
8
view/production_enology_product_form.xml
Normal file
8
view/production_enology_product_form.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<form>
|
||||||
|
<label name="product"/>
|
||||||
|
<field name="product"/>
|
||||||
|
<label name="quantity"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<label name="uom"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
</form>
|
5
view/production_enology_product_list.xml
Normal file
5
view/production_enology_product_list.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<tree>
|
||||||
|
<field name="product"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
</tree>
|
19
view/production_form.xml
Normal file
19
view/production_form.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?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="/form/label[@name='bom']" position="before">
|
||||||
|
<label name="production_template"/>
|
||||||
|
<field name="production_template"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="/form/notebook" position="inside">
|
||||||
|
<page name="enology_products">
|
||||||
|
<field name="enology_products" colspan="4"/>
|
||||||
|
<field name="allowed_enology_products" colspan="4" invisible="1"/>
|
||||||
|
</page>
|
||||||
|
<page name="output_distribution">
|
||||||
|
<field name="output_distribution" colspan="4"/>
|
||||||
|
<field name="allowed_output_products" colspan="4" invisible="1"/>
|
||||||
|
</page>
|
||||||
|
</xpath>
|
||||||
|
</data>
|
8
view/production_list.xml
Normal file
8
view/production_list.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?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="/tree/field[@name='state']" position="before">
|
||||||
|
<field name="cost" sum="Total"/>
|
||||||
|
</xpath>
|
||||||
|
</data>
|
17
view/production_output_distribution_form.xml
Normal file
17
view/production_output_distribution_form.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?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. -->
|
||||||
|
<form>
|
||||||
|
<label name="product"/>
|
||||||
|
<field name="product"/>
|
||||||
|
<label name="location"/>
|
||||||
|
<field name="location"/>
|
||||||
|
<label name="uom"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
<label name="initial_quantity"/>
|
||||||
|
<field name="initial_quantity"/>
|
||||||
|
<label name="final_quantity"/>
|
||||||
|
<field name="final_quantity"/>
|
||||||
|
<label name="produced_quantity"/>
|
||||||
|
<field name="produced_quantity"/>
|
||||||
|
</form>
|
11
view/production_output_distribution_list.xml
Normal file
11
view/production_output_distribution_list.xml
Normal 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. -->
|
||||||
|
<tree>
|
||||||
|
<field name="product"/>
|
||||||
|
<field name="location"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
<field name="initial_quantity"/>
|
||||||
|
<field name="final_quantity"/>
|
||||||
|
<field name="produced_quantity"/>
|
||||||
|
</tree>
|
16
view/production_template_form.xml
Normal file
16
view/production_template_form.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?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. -->
|
||||||
|
<form>
|
||||||
|
<label name="name"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<label name="pass_feature"/>
|
||||||
|
<field name="pass_feature"/>
|
||||||
|
<label name="quantity"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<label name="uom"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
<field name="inputs" colspan="2"/>
|
||||||
|
<field name="outputs" colspan="2"/>
|
||||||
|
<field name="enology_products" colspan="4"/>
|
||||||
|
</form>
|
11
view/production_template_line_form.xml
Normal file
11
view/production_template_line_form.xml
Normal 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. -->
|
||||||
|
<form>
|
||||||
|
<label name="product"/>
|
||||||
|
<field name="product"/>
|
||||||
|
<label name="uom"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
<label name="quantity"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
</form>
|
8
view/production_template_line_list.xml
Normal file
8
view/production_template_line_list.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?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. -->
|
||||||
|
<tree editable="1">
|
||||||
|
<field name="product"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
</tree>
|
9
view/production_template_list.xml
Normal file
9
view/production_template_list.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?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. -->
|
||||||
|
<tree>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="pass_feature"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<field name="uom"/>
|
||||||
|
</tree>
|
|
@ -1,3 +1,6 @@
|
||||||
|
<?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>
|
<data>
|
||||||
<xpath expr="/form/notebook/page[@id='general']/field[@name='cost_price_method']" position="after">
|
<xpath expr="/form/notebook/page[@id='general']/field[@name='cost_price_method']" position="after">
|
||||||
<label name="agronomic_type"/>
|
<label name="agronomic_type"/>
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
<?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>
|
<data>
|
||||||
<xpath expr="/tree" position="inside">
|
<xpath expr="/tree" position="inside">
|
||||||
<field name="agronomic_type" tree_invisible="1"/>
|
<field name="agronomic_type" tree_invisible="1"/>
|
||||||
|
|
Loading…
Reference in a new issue