Add infrastructure cost to productions
This commit is contained in:
parent
15632ed8d9
commit
17c84eb262
|
@ -7,6 +7,7 @@ from .production import *
|
|||
|
||||
def register():
|
||||
Pool.register(
|
||||
BOM,
|
||||
Lot,
|
||||
Production,
|
||||
module='production_lot_cost', type_='model')
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:production.bom,infrastructure_cost:"
|
||||
msgid "Infrastructure Cost"
|
||||
msgstr "Cost d'infraestructura"
|
||||
|
||||
msgctxt "help:production.bom,infrastructure_cost:"
|
||||
msgid "Infrastructure cost per lot unit"
|
||||
msgstr "Cost d'infraestructura per unitat del lot"
|
||||
|
||||
msgctxt "model:stock.lot.cost_category,name:cost_category_infrastructure_cost"
|
||||
msgid "Infrastructure Cost"
|
||||
msgstr "Cost d'infraestructura"
|
||||
|
||||
msgctxt "model:stock.lot.cost_category,name:cost_category_inputs_cost"
|
||||
msgid "Inputs Cost"
|
||||
msgstr "Cost moviments entrada"
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:production.bom,infrastructure_cost:"
|
||||
msgid "Infrastructure Cost"
|
||||
msgstr "Coste infraestructura"
|
||||
|
||||
msgctxt "help:production.bom,infrastructure_cost:"
|
||||
msgid "Infrastructure cost per lot unit"
|
||||
msgstr "Coste infraestructura por unidad del lote"
|
||||
|
||||
msgctxt "model:stock.lot.cost_category,name:cost_category_infrastructure_cost"
|
||||
msgid "Infrastructure Cost"
|
||||
msgstr "Coste infraestructura"
|
||||
|
||||
msgctxt "model:stock.lot.cost_category,name:cost_category_inputs_cost"
|
||||
msgid "Inputs Cost"
|
||||
msgstr "Coste movimientos entrada"
|
115
production.py
115
production.py
|
@ -1,13 +1,21 @@
|
|||
#The COPYRIGHT file at the top level of this repository contains the full
|
||||
#copyright notices and license terms.
|
||||
from trytond.model import ModelView, Workflow
|
||||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from trytond.model import ModelView, Workflow, fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
__all__ = ['Lot', 'Production']
|
||||
__all__ = ['BOM', 'Lot', 'Production']
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
|
||||
class BOM:
|
||||
__name__ = 'production.bom'
|
||||
infrastructure_cost = fields.Numeric('Infrastructure Cost',
|
||||
digits=(16, 4),
|
||||
help='Infrastructure cost per lot unit')
|
||||
|
||||
|
||||
class Lot:
|
||||
__name__ = 'stock.lot'
|
||||
|
||||
|
@ -27,35 +35,94 @@ class Lot:
|
|||
class Production:
|
||||
__name__ = 'production'
|
||||
|
||||
@property
|
||||
def infrastructure_cost(self):
|
||||
if self.product and self.bom and self.bom.infrastructure_cost:
|
||||
return self.bom.infrastructure_cost
|
||||
|
||||
def get_cost(self, name):
|
||||
cost = super(Production, self).get_cost(name)
|
||||
if not self.infrastructure_cost:
|
||||
return cost
|
||||
for output in self.outputs:
|
||||
if not output.lot:
|
||||
continue
|
||||
if output.product == self.product:
|
||||
cost += (Decimal(str(output.internal_quantity)) *
|
||||
self.infrastructure_cost)
|
||||
return cost
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('done')
|
||||
def done(cls, productions):
|
||||
pool = Pool()
|
||||
LotCostLine = pool.get('stock.lot.cost_line')
|
||||
|
||||
to_create = []
|
||||
for production in productions:
|
||||
for output in production.outputs:
|
||||
if (production.infrastructure_cost and
|
||||
output.product == production.product):
|
||||
output.unit_price += production.infrastructure_cost
|
||||
output.save()
|
||||
if not output.lot:
|
||||
continue
|
||||
if not output.lot.cost_lines:
|
||||
cost_lines = production._get_output_lot_cost_lines(output,
|
||||
added_infrastructure_cost=True)
|
||||
output.lot.cost_lines = cost_lines
|
||||
output.lot.save()
|
||||
|
||||
LotCostLine.create(to_create)
|
||||
super(Production, cls).done(productions)
|
||||
|
||||
for production in productions:
|
||||
for out_move in production.outputs:
|
||||
if out_move.state != 'done' or not out_move.lot:
|
||||
continue
|
||||
cost_line_vals = production._get_lot_cost_line_vals(out_move)
|
||||
if cost_line_vals:
|
||||
LotCostLine.create(cost_line_vals)
|
||||
def get_output_lot(self, output):
|
||||
pool = Pool()
|
||||
Config = pool.get('production.configuration')
|
||||
config = Config(1)
|
||||
|
||||
def _get_lot_cost_line_vals(self, output_move):
|
||||
lot = super(Production, self).get_output_lot(output)
|
||||
cost_lines = self._get_output_lot_cost_lines(output,
|
||||
config.output_lot_creation == 'done')
|
||||
if cost_lines and not getattr(lot, 'cost_lines', False):
|
||||
lot.cost_lines = cost_lines
|
||||
return lot
|
||||
|
||||
def _get_output_lot_cost_lines(self, output_move,
|
||||
added_infrastructure_cost=False):
|
||||
'''
|
||||
Return a list of unpersistent stock.lot.cost_line instances to be
|
||||
writen in cost_lines field of output_move's lot (the returned lines
|
||||
doesn't have the lot's field)
|
||||
'''
|
||||
pool = Pool()
|
||||
ModelData = pool.get('ir.model.data')
|
||||
|
||||
if not output_move.lot:
|
||||
return None
|
||||
inputs_category_id = ModelData.get_id('production_lot_cost',
|
||||
'cost_category_inputs_cost')
|
||||
infrastructure_category_id = ModelData.get_id('production_lot_cost',
|
||||
'cost_category_infrastructure_cost')
|
||||
|
||||
category_id = ModelData.get_id('stock_lot_cost',
|
||||
'cost_category_standard_price')
|
||||
return [{
|
||||
'lot': output_move.lot.id,
|
||||
'category': category_id,
|
||||
'unit_price': output_move.unit_price,
|
||||
'origin': 'stock.move,%s'%output_move.id
|
||||
}]
|
||||
unit_price = output_move.unit_price
|
||||
#Infrastructure cost already added before so we must rest it.
|
||||
if (added_infrastructure_cost and self.infrastructure_cost and
|
||||
output_move.product == self.product):
|
||||
unit_price -= self.infrastructure_cost
|
||||
res = [
|
||||
self._get_output_lot_cost_line(output_move, inputs_category_id,
|
||||
unit_price),
|
||||
]
|
||||
|
||||
if self.product == output_move.product and self.infrastructure_cost:
|
||||
infrastructure_cost = self._get_output_lot_cost_line(output_move,
|
||||
infrastructure_category_id, self.infrastructure_cost)
|
||||
res.append(infrastructure_cost)
|
||||
return res
|
||||
|
||||
def _get_output_lot_cost_line(self, output_move, category_id, cost):
|
||||
pool = Pool()
|
||||
LotCostLine = pool.get('stock.lot.cost_line')
|
||||
return LotCostLine(
|
||||
category=category_id,
|
||||
unit_price=cost,
|
||||
origin=str(output_move)
|
||||
)
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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="bom_view_form">
|
||||
<field name="model">production.bom</field>
|
||||
<field name="inherit" ref="production.bom_view_form"/>
|
||||
<field name="name">bom_form</field>
|
||||
</record>
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
<record model="stock.lot.cost_category"
|
||||
id="cost_category_inputs_cost">
|
||||
<field name="name">Inputs Cost</field>
|
||||
</record>
|
||||
<record model="stock.lot.cost_category"
|
||||
id="cost_category_infrastructure_cost">
|
||||
<field name="name">Infrastructure Cost</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
|
@ -145,11 +145,11 @@ Create an Inventory::
|
|||
>>> inventory_line1 = InventoryLine()
|
||||
>>> inventory.lines.append(inventory_line1)
|
||||
>>> inventory_line1.product = component1
|
||||
>>> inventory_line1.quantity = 10
|
||||
>>> inventory_line1.quantity = 20
|
||||
>>> inventory_line2 = InventoryLine()
|
||||
>>> inventory.lines.append(inventory_line2)
|
||||
>>> inventory_line2.product = component2
|
||||
>>> inventory_line2.quantity = 5
|
||||
>>> inventory_line2.quantity = 10
|
||||
>>> inventory.save()
|
||||
>>> Inventory.confirm([inventory.id], config.context)
|
||||
>>> inventory.state
|
||||
|
@ -207,3 +207,53 @@ Make the production::
|
|||
u'done'
|
||||
>>> output.lot.cost_price == Decimal('12.5')
|
||||
True
|
||||
|
||||
Make a production with infrastructure cost::
|
||||
|
||||
>>> bom.infrastructure_cost = Decimal('1.0')
|
||||
>>> bom.save()
|
||||
>>> production = Production()
|
||||
>>> production.product = product
|
||||
>>> production.bom = bom
|
||||
>>> production.quantity = 2
|
||||
>>> sorted([i.quantity for i in production.inputs]) == [10, 300]
|
||||
True
|
||||
>>> output, = production.outputs
|
||||
>>> output.quantity == 2
|
||||
True
|
||||
>>> production.cost == Decimal('25')
|
||||
True
|
||||
>>> output.unit_price == Decimal('12.5')
|
||||
True
|
||||
>>> production.save()
|
||||
>>> output, = production.outputs
|
||||
>>> config._context['from_move'] = output.id
|
||||
>>> Lot = Model.get('stock.lot')
|
||||
>>> lot = Lot(number='2')
|
||||
>>> lot.product = product
|
||||
>>> lot.cost_price
|
||||
>>> lot.save()
|
||||
>>> output.lot = lot
|
||||
>>> output.save()
|
||||
>>> del config._context['from_move']
|
||||
>>> Production.wait([production.id], config.context)
|
||||
>>> production.state
|
||||
u'waiting'
|
||||
>>> Production.assign_try([production.id], config.context)
|
||||
True
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'assigned' for i in production.inputs)
|
||||
True
|
||||
>>> Production.run([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'done' for i in production.inputs)
|
||||
True
|
||||
>>> Production.done([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> output, = production.outputs
|
||||
>>> output.state
|
||||
u'done'
|
||||
>>> len(output.lot.cost_lines)
|
||||
2
|
||||
>>> output.lot.cost_price == Decimal('13.5')
|
||||
True
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
============================
|
||||
Production Lot Cost Scenario
|
||||
============================
|
||||
|
||||
=============
|
||||
General Setup
|
||||
=============
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime
|
||||
>>> from dateutil.relativedelta import relativedelta
|
||||
>>> from decimal import Decimal
|
||||
>>> from proteus import config, Model, Wizard
|
||||
>>> today = datetime.date.today()
|
||||
|
||||
Create database::
|
||||
|
||||
>>> config = config.set_trytond()
|
||||
>>> config.pool.test = True
|
||||
|
||||
Install production_lot_cost Module::
|
||||
|
||||
>>> Module = Model.get('ir.module.module')
|
||||
>>> modules = Module.find([
|
||||
... ('name', 'in', ['production_lot_cost', 'production_output_lot']),
|
||||
... ])
|
||||
>>> Module.install([x.id for x in modules], config.context)
|
||||
>>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> Currency = Model.get('currency.currency')
|
||||
>>> CurrencyRate = Model.get('currency.currency.rate')
|
||||
>>> Company = Model.get('company.company')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> company_config = Wizard('company.company.config')
|
||||
>>> company_config.execute('company')
|
||||
>>> company = company_config.form
|
||||
>>> party = Party(name='Dunder Mifflin')
|
||||
>>> party.save()
|
||||
>>> company.party = party
|
||||
>>> currencies = Currency.find([('code', '=', 'USD')])
|
||||
>>> if not currencies:
|
||||
... currency = Currency(name='Euro', symbol=u'$', code='USD',
|
||||
... rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
|
||||
... mon_decimal_point=',')
|
||||
... currency.save()
|
||||
... CurrencyRate(date=today + relativedelta(month=1, day=1),
|
||||
... rate=Decimal('1.0'), currency=currency).save()
|
||||
... else:
|
||||
... currency, = currencies
|
||||
>>> company.currency = currency
|
||||
>>> company_config.execute('add')
|
||||
>>> company, = Company.find()
|
||||
|
||||
Reload the context::
|
||||
|
||||
>>> User = Model.get('res.user')
|
||||
>>> config._context = User.get_preferences(True, config.context)
|
||||
|
||||
Configuration production location::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> warehouse, = Location.find([('code', '=', 'WH')])
|
||||
>>> production_location, = Location.find([('code', '=', 'PROD')])
|
||||
>>> warehouse.production_location = production_location
|
||||
>>> warehouse.save()
|
||||
|
||||
Create lot sequence type and produced lots sequence::
|
||||
|
||||
>>> user = User(config.user)
|
||||
>>> SequenceType = Model.get('ir.sequence.type')
|
||||
>>> SequenceType(name='Lot',
|
||||
... code='stock.lot',
|
||||
... groups=[user.groups[0].id]).save()
|
||||
>>> Sequence = Model.get('ir.sequence')
|
||||
>>> lot_sequence = Sequence(name='Produced Lots',
|
||||
... code='stock.lot',
|
||||
... company=company)
|
||||
>>> lot_sequence.save()
|
||||
|
||||
Create product with lots required::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> LotType = Model.get('stock.lot.type')
|
||||
>>> lot_types = LotType.find([])
|
||||
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> product = Product()
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal(30)
|
||||
>>> template.cost_price = Decimal(20)
|
||||
>>> template.lot_required.extend(lot_types)
|
||||
>>> template.save()
|
||||
|
||||
>>> product.template = template
|
||||
>>> product.save()
|
||||
|
||||
Create Components::
|
||||
|
||||
>>> component1 = Product()
|
||||
>>> template1 = ProductTemplate()
|
||||
>>> template1.name = 'component 1'
|
||||
>>> template1.default_uom = unit
|
||||
>>> template1.type = 'goods'
|
||||
>>> template1.list_price = Decimal(5)
|
||||
>>> template1.cost_price = Decimal(1)
|
||||
>>> template1.save()
|
||||
>>> component1.template = template1
|
||||
>>> component1.save()
|
||||
|
||||
>>> meter, = ProductUom.find([('name', '=', 'Meter')])
|
||||
>>> centimeter, = ProductUom.find([('name', '=', 'centimeter')])
|
||||
>>> component2 = Product()
|
||||
>>> template2 = ProductTemplate()
|
||||
>>> template2.name = 'component 2'
|
||||
>>> template2.default_uom = meter
|
||||
>>> template2.type = 'goods'
|
||||
>>> template2.list_price = Decimal(7)
|
||||
>>> template2.cost_price = Decimal(5)
|
||||
>>> template2.save()
|
||||
>>> component2.template = template2
|
||||
>>> component2.save()
|
||||
|
||||
Create Bill of Material with infrastructure cost::
|
||||
|
||||
>>> BOM = Model.get('production.bom')
|
||||
>>> BOMInput = Model.get('production.bom.input')
|
||||
>>> BOMOutput = Model.get('production.bom.output')
|
||||
>>> bom = BOM(name='product')
|
||||
>>> input1 = BOMInput()
|
||||
>>> bom.inputs.append(input1)
|
||||
>>> input1.product = component1
|
||||
>>> input1.quantity = 5
|
||||
>>> input2 = BOMInput()
|
||||
>>> bom.inputs.append(input2)
|
||||
>>> input2.product = component2
|
||||
>>> input2.quantity = 150
|
||||
>>> input2.uom = centimeter
|
||||
>>> output = BOMOutput()
|
||||
>>> bom.outputs.append(output)
|
||||
>>> output.product = product
|
||||
>>> output.quantity = 1
|
||||
>>> bom.infrastructure_cost = Decimal('1.0')
|
||||
>>> bom.save()
|
||||
|
||||
>>> ProductBom = Model.get('product.product-production.bom')
|
||||
>>> product.boms.append(ProductBom(bom=bom))
|
||||
>>> product.save()
|
||||
|
||||
Create an Inventory::
|
||||
|
||||
>>> Inventory = Model.get('stock.inventory')
|
||||
>>> InventoryLine = Model.get('stock.inventory.line')
|
||||
>>> storage, = Location.find([
|
||||
... ('code', '=', 'STO'),
|
||||
... ])
|
||||
>>> inventory = Inventory()
|
||||
>>> inventory.location = storage
|
||||
>>> inventory_line1 = InventoryLine()
|
||||
>>> inventory.lines.append(inventory_line1)
|
||||
>>> inventory_line1.product = component1
|
||||
>>> inventory_line1.quantity = 20
|
||||
>>> inventory_line2 = InventoryLine()
|
||||
>>> inventory.lines.append(inventory_line2)
|
||||
>>> inventory_line2.product = component2
|
||||
>>> inventory_line2.quantity = 10
|
||||
>>> inventory.save()
|
||||
>>> Inventory.confirm([inventory.id], config.context)
|
||||
>>> inventory.state
|
||||
u'done'
|
||||
|
||||
Configure production to automatically create lots on running state::
|
||||
|
||||
>>> ProductionConfig = Model.get('production.configuration')
|
||||
>>> production_config = ProductionConfig(1)
|
||||
>>> production_config.output_lot_creation = 'running'
|
||||
>>> production_config.output_lot_sequence = lot_sequence
|
||||
>>> production_config.save()
|
||||
|
||||
Make a production with infrastructure cost and lots automatically created when
|
||||
production is Running::
|
||||
|
||||
>>> Production = Model.get('production')
|
||||
>>> production = Production()
|
||||
>>> production.product = product
|
||||
>>> production.bom = bom
|
||||
>>> production.quantity = 2
|
||||
>>> sorted([i.quantity for i in production.inputs]) == [10, 300]
|
||||
True
|
||||
>>> output, = production.outputs
|
||||
>>> output.quantity == 2
|
||||
True
|
||||
>>> production.cost == Decimal('25')
|
||||
True
|
||||
>>> output.unit_price == Decimal('12.5')
|
||||
True
|
||||
>>> production.save()
|
||||
>>> Production.wait([production.id], config.context)
|
||||
>>> production.state
|
||||
u'waiting'
|
||||
>>> Production.assign_try([production.id], config.context)
|
||||
True
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'assigned' for i in production.inputs)
|
||||
True
|
||||
>>> Production.run([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'done' for i in production.inputs)
|
||||
True
|
||||
>>> output, = production.outputs
|
||||
>>> output.reload()
|
||||
>>> output.lot != None
|
||||
True
|
||||
>>> Production.done([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> output, = production.outputs
|
||||
>>> output.state
|
||||
u'done'
|
||||
>>> len(output.lot.cost_lines)
|
||||
2
|
||||
>>> output.lot.cost_price == Decimal('13.5')
|
||||
True
|
||||
|
||||
Configure production to automatically create lots on done state::
|
||||
|
||||
>>> production_config.output_lot_creation = 'done'
|
||||
>>> production_config.save()
|
||||
|
||||
Make a production with infrastructure cost and lots automatically created when
|
||||
production is done::
|
||||
|
||||
>>> production = Production()
|
||||
>>> production.product = product
|
||||
>>> production.bom = bom
|
||||
>>> production.quantity = 2
|
||||
>>> sorted([i.quantity for i in production.inputs]) == [10, 300]
|
||||
True
|
||||
>>> output, = production.outputs
|
||||
>>> output.quantity == 2
|
||||
True
|
||||
>>> production.cost == Decimal('25')
|
||||
True
|
||||
>>> output.unit_price == Decimal('12.5')
|
||||
True
|
||||
>>> production.save()
|
||||
>>> Production.wait([production.id], config.context)
|
||||
>>> production.state
|
||||
u'waiting'
|
||||
>>> Production.assign_try([production.id], config.context)
|
||||
True
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'assigned' for i in production.inputs)
|
||||
True
|
||||
>>> Production.run([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> all(i.state == 'done' for i in production.inputs)
|
||||
True
|
||||
>>> output, = production.outputs
|
||||
>>> output.lot
|
||||
>>> Production.done([production.id], config.context)
|
||||
>>> production.reload()
|
||||
>>> output, = production.outputs
|
||||
>>> output.state
|
||||
u'done'
|
||||
>>> output.lot != None
|
||||
True
|
||||
>>> len(output.lot.cost_lines)
|
||||
2
|
||||
>>> output.lot.cost_price == Decimal('13.5')
|
||||
True
|
|
@ -12,7 +12,7 @@ if os.path.isdir(DIR):
|
|||
import unittest
|
||||
import doctest
|
||||
import trytond.tests.test_tryton
|
||||
from trytond.tests.test_tryton import test_depends
|
||||
from trytond.tests.test_tryton import test_depends, test_view
|
||||
from trytond.backend.sqlite.database import Database as SQLiteDatabase
|
||||
|
||||
|
||||
|
@ -24,6 +24,12 @@ class TestCase(unittest.TestCase):
|
|||
def setUp(self):
|
||||
trytond.tests.test_tryton.install_module('production_lot_cost')
|
||||
|
||||
def test0005views(self):
|
||||
'''
|
||||
Test views.
|
||||
'''
|
||||
test_view('production')
|
||||
|
||||
def test0006depends(self):
|
||||
'''
|
||||
Test depends.
|
||||
|
@ -47,6 +53,10 @@ def suite():
|
|||
suite.addTests(doctest.DocFileSuite('scenario_production_lot_cost.rst',
|
||||
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
suite.addTests(doctest.DocFileSuite(
|
||||
'scenario_production_lot_cost_with_output_lot.rst',
|
||||
setUp=doctest_dropdb, tearDown=doctest_dropdb, encoding='utf-8',
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
return suite
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -6,3 +6,4 @@ depends:
|
|||
extras_depend:
|
||||
production_output_lot
|
||||
xml:
|
||||
production.xml
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?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" position="before">
|
||||
<label name="infrastructure_cost"/>
|
||||
<field name="infrastructure_cost"/>
|
||||
</xpath>
|
||||
</data>
|
Loading…
Reference in New Issue