Add unit loads to internal shipment.
This commit is contained in:
parent
e1dfb7b701
commit
8f72f35be7
|
@ -8,7 +8,7 @@ from .unit_load import (UnitLoad, UnitLoadMove, MoveUnitLoad,
|
|||
BatchDropUnitLoad, BatchDropUnitLoadData, BatchDropUnitLoadConfirm)
|
||||
from .stock import (Move, UnitLoadsByLocations,
|
||||
UnitLoadsByLocationsStart)
|
||||
from .shipment import ShipmentOut
|
||||
from .shipment import ShipmentOut, ShipmentInternal
|
||||
|
||||
|
||||
def register():
|
||||
|
@ -23,6 +23,7 @@ def register():
|
|||
DropUnitLoadFailedProduct,
|
||||
UnitLoadsByLocationsStart,
|
||||
ShipmentOut,
|
||||
ShipmentInternal,
|
||||
BatchDropUnitLoadData,
|
||||
BatchDropUnitLoadConfirm,
|
||||
module='stock_unit_load', type_='model')
|
||||
|
|
|
@ -538,10 +538,22 @@ msgctxt "view:stock.unit_loads_by_locations.start:"
|
|||
msgid "Unit loads by Locations"
|
||||
msgstr "Unidades de carga por ubicación"
|
||||
|
||||
msgctxt "field:stock.shipment.out,unit_loads:"
|
||||
msgid "Unit loads"
|
||||
msgstr "Unidades de carga"
|
||||
|
||||
msgctxt "view:stock.shipment.out:"
|
||||
msgid "ULs"
|
||||
msgstr "UdCs"
|
||||
|
||||
msgctxt "field:stock.shipment.internal,unit_loads:"
|
||||
msgid "Unit loads"
|
||||
msgstr "Unidades de carga"
|
||||
|
||||
msgctxt "view:stock.shipment.internal:"
|
||||
msgid "ULs"
|
||||
msgstr "UdCs"
|
||||
|
||||
msgctxt "view:stock.unit_load.move:"
|
||||
msgid "Start Time"
|
||||
msgstr "Hora inicio"
|
||||
|
|
61
shipment.py
61
shipment.py
|
@ -5,7 +5,7 @@ from trytond.model import fields
|
|||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.pyson import Eval
|
||||
|
||||
__all__ = ['ShipmentOut']
|
||||
__all__ = ['ShipmentOut', 'ShipmentInternal']
|
||||
|
||||
|
||||
class ShipmentOut:
|
||||
|
@ -69,4 +69,61 @@ class ShipmentOut:
|
|||
location = move.unit_load.get_location([move.unit_load], type='storage')[move.unit_load.id]
|
||||
res.from_location = location
|
||||
res.unit_load = move.unit_load
|
||||
return res
|
||||
return res
|
||||
|
||||
|
||||
class ShipmentInternal:
|
||||
__name__ = 'stock.shipment.internal'
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
unit_loads = fields.Function(
|
||||
fields.One2Many('stock.unit_load', None, 'Unit loads',
|
||||
states={'readonly': Eval('state') != 'draft'},
|
||||
depends=['state']),
|
||||
'get_unit_loads', setter='set_unit_loads', searcher='search_unit_loads')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super(ShipmentInternal, cls).__setup__()
|
||||
for _field_name in ('moves', ):
|
||||
_field = getattr(cls, _field_name)
|
||||
if _field.states.get('readonly'):
|
||||
_field.states['readonly'] |= Eval('unit_loads')
|
||||
else:
|
||||
_field.states['readonly'] = Eval('unit_loads')
|
||||
if 'unit_loads' not in _field.depends:
|
||||
_field.depends.append('unit_loads')
|
||||
|
||||
def get_unit_loads(self, name=None):
|
||||
if not self.moves:
|
||||
return []
|
||||
uls = set(m.unit_load.id for m in self.moves if m.unit_load)
|
||||
return list(uls)
|
||||
|
||||
@classmethod
|
||||
def set_unit_loads(cls, records, name, value):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def search_unit_loads(cls, name, clause):
|
||||
_field = 'moves.unit_load'
|
||||
if '.' in name:
|
||||
_field += '.%s' % name[10:]
|
||||
return [(_field,) + tuple(clause[1:])]
|
||||
|
||||
@fields.depends('unit_loads', 'moves', 'date_time_',
|
||||
'from_location', 'to_location')
|
||||
def on_change_unit_loads(self):
|
||||
moves = []
|
||||
ul_ids = [ul.id for ul in self.unit_loads]
|
||||
if self.moves:
|
||||
moves.extend(
|
||||
[m for m in self.moves if m.unit_load.id in ul_ids])
|
||||
for ul in self.unit_loads:
|
||||
if ul.id in [m.unit_load.id for m in moves]:
|
||||
continue
|
||||
new_moves = ul._move(self.to_location,
|
||||
self.date_time_,
|
||||
from_location=self.from_location)
|
||||
moves.extend(new_moves)
|
||||
self.moves = moves
|
||||
|
|
|
@ -10,6 +10,13 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<field name="inherit" ref="stock.shipment_out_view_form"/>
|
||||
</record>
|
||||
|
||||
<!-- Shipment internal -->
|
||||
<record model="ir.ui.view" id="shipment_internal_view_form">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="name">shipment_internal_form</field>
|
||||
<field name="inherit" ref="stock.shipment_internal_view_form"/>
|
||||
</record>
|
||||
|
||||
<!-- form relate -->
|
||||
<record model="ir.action.act_window" id="act_unit_loads_shipment_out">
|
||||
<field name="name">Shipment Out</field>
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
========================
|
||||
Check unit load creation
|
||||
========================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import datetime
|
||||
>>> from proteus import config, Model, Wizard, Report
|
||||
>>> from dateutil.relativedelta import relativedelta
|
||||
>>> from decimal import Decimal
|
||||
>>> from trytond.modules.company.tests.tools import create_company, \
|
||||
... get_company
|
||||
>>> today = datetime.date.today()
|
||||
>>> tomorrow = today + relativedelta(days=1)
|
||||
>>> time_ = datetime.datetime.now().time()
|
||||
>>> time_ = time_.replace(microsecond=0)
|
||||
|
||||
Create database::
|
||||
|
||||
>>> config = config.set_trytond()
|
||||
>>> config.pool.test = True
|
||||
|
||||
Install unit load Module::
|
||||
|
||||
>>> Module = Model.get('ir.module')
|
||||
>>> module, = Module.find([('name', '=', 'stock_unit_load')])
|
||||
>>> module.click('install')
|
||||
>>> Wizard('ir.module.install_upgrade').execute('upgrade')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
>>> company = get_company()
|
||||
|
||||
Reload the context::
|
||||
|
||||
>>> User = Model.get('res.user')
|
||||
>>> Group = Model.get('res.group')
|
||||
>>> config._context = User.get_preferences(True, config.context)
|
||||
|
||||
Create product::
|
||||
|
||||
>>> ProductUom = Model.get('product.uom')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> Product = Model.get('product.product')
|
||||
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
|
||||
>>> product = Product()
|
||||
>>> template = ProductTemplate()
|
||||
>>> template.name = 'Product'
|
||||
>>> template.default_uom = unit
|
||||
>>> template.type = 'goods'
|
||||
>>> template.list_price = Decimal('20')
|
||||
>>> template.cost_price = Decimal('8')
|
||||
>>> template.save()
|
||||
>>> product.template = template
|
||||
>>> product.save()
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> production_loc, = Location.find([('type', '=', 'production')])
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
>>> wh2, = warehouse_loc.duplicate()
|
||||
>>> wh2.name = 'Warehouse 2'
|
||||
>>> wh2.code = 'WH2'
|
||||
>>> wh2.save()
|
||||
|
||||
Create an unit load::
|
||||
|
||||
>>> UnitLoad = Model.get('stock.unit_load')
|
||||
>>> unit_load = UnitLoad()
|
||||
>>> unit_load.company != None
|
||||
True
|
||||
>>> unit_load.start_date != None
|
||||
True
|
||||
>>> unit_load.end_date != None
|
||||
True
|
||||
>>> unit_load.end_date = unit_load.start_date + relativedelta(minutes=5)
|
||||
>>> unit_load.production_type = 'location'
|
||||
>>> unit_load.production_location = output_loc
|
||||
>>> unit_load.product = product
|
||||
>>> unit_load.cases_quantity = 5
|
||||
>>> len(unit_load.production_moves)
|
||||
0
|
||||
>>> unit_load.save() # doctest: +IGNORE_EXCEPTION_DETAIL
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
UserError: ...
|
||||
>>> unit_load.production_location = production_loc
|
||||
>>> unit_load.save()
|
||||
>>> unit_load.code != None
|
||||
True
|
||||
|
||||
Add moves::
|
||||
|
||||
>>> unit_load.production_state
|
||||
'running'
|
||||
>>> unit_load.quantity = Decimal('35.0')
|
||||
>>> len(unit_load.production_moves)
|
||||
1
|
||||
>>> move = unit_load.production_moves[0]
|
||||
>>> move.planned_date == today
|
||||
True
|
||||
>>> move.product == unit_load.product
|
||||
True
|
||||
>>> move.quantity
|
||||
35.0
|
||||
>>> move.from_location == production_loc
|
||||
True
|
||||
>>> not move.to_location
|
||||
True
|
||||
>>> move.to_location = storage_loc
|
||||
>>> move.currency == unit_load.company.currency
|
||||
True
|
||||
>>> unit_load.save()
|
||||
>>> unit_load.state
|
||||
u'draft'
|
||||
>>> unit_load.production_state
|
||||
'running'
|
||||
>>> len(unit_load.moves)
|
||||
1
|
||||
>>> len(unit_load.production_moves)
|
||||
1
|
||||
>>> unit_load.production_moves[0].state
|
||||
u'draft'
|
||||
>>> unit_load.internal_quantity
|
||||
35.0
|
||||
>>> unit_load.quantity_per_case
|
||||
7.0
|
||||
|
||||
Check computed fields::
|
||||
|
||||
>>> unit_load.location.code
|
||||
u'STO'
|
||||
>>> len(unit_load.last_moves) == 1
|
||||
True
|
||||
>>> unit_load.click('assign')
|
||||
>>> unit_load.state
|
||||
u'assigned'
|
||||
>>> unit_load.moves[0].state
|
||||
u'assigned'
|
||||
>>> unit_load.production_state
|
||||
'running'
|
||||
>>> len(unit_load.ul_moves)
|
||||
1
|
||||
>>> unit_load.uom.rec_name
|
||||
u'Unit'
|
||||
>>> unit_load.save()
|
||||
>>> unit_load.click('do')
|
||||
|
||||
Create a shipment internal::
|
||||
|
||||
>>> ShipmentInternal = Model.get('stock.shipment.internal')
|
||||
>>> shipment_internal = ShipmentInternal()
|
||||
>>> shipment_internal.company = company
|
||||
>>> shipment_internal.date_time_ = datetime.datetime.now() + relativedelta(minutes=10)
|
||||
>>> shipment_internal.from_location = unit_load.location
|
||||
>>> shipment_internal.to_location = wh2.storage_location
|
||||
|
||||
Add Unit load::
|
||||
|
||||
>>> shipment_internal.unit_loads.append(unit_load)
|
||||
>>> len(shipment_internal.moves)
|
||||
1
|
||||
>>> shipment_internal.moves[0].unit_load.id == unit_load.id
|
||||
True
|
||||
>>> shipment_internal.save()
|
||||
>>> shipment_internal.click('wait')
|
||||
>>> len(shipment_internal.moves)
|
||||
1
|
||||
>>> shipment_internal.moves[0].unit_load.id == unit_load.id
|
||||
True
|
||||
>>> shipment_internal.click('assign_try')
|
||||
True
|
||||
>>> shipment_internal.click('done')
|
||||
|
||||
Check unit load state::
|
||||
|
||||
>>> unit_load.reload()
|
||||
>>> len(unit_load.ul_moves)
|
||||
2
|
||||
>>> unit_load.state
|
||||
u'done'
|
||||
>>> unit_load.location.id == wh2.storage_location.id
|
||||
True
|
||||
|
|
@ -30,5 +30,9 @@ def suite():
|
|||
'scenario_batch_drop.rst',
|
||||
setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
suite.addTests(doctest.DocFileSuite(
|
||||
'scenario_shipment_internal.rst',
|
||||
setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',
|
||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
||||
# TODO: uls by locations wizard
|
||||
return suite
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?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/field[@name='moves']" position="replace">
|
||||
<notebook>
|
||||
<page id="uls" string="ULs">
|
||||
<field name="unit_loads" colspan="4" widget="many2many"/>
|
||||
</page>
|
||||
<page id="moves" string="Moves">
|
||||
<field name="moves" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</xpath>
|
||||
</data>
|
Loading…
Reference in New Issue