parent
18c66f39c6
commit
d925e23b90
|
@ -17,3 +17,9 @@ class Configuration:
|
|||
domain=[('code', '=', 'stock.unit_load'),
|
||||
('company', 'in',
|
||||
[Eval('context', {}).get('company', -1), None])]))
|
||||
ul_production_type = fields.Property(
|
||||
fields.Selection([('location', 'Location')], 'Production type', required=True))
|
||||
|
||||
@classmethod
|
||||
def default_ul_production_type(cls):
|
||||
return 'location'
|
||||
|
|
|
@ -106,10 +106,6 @@ msgctxt "field:stock.unit_load,uom_digits:"
|
|||
msgid "UOM Digits"
|
||||
msgstr "Dígitos UdM"
|
||||
|
||||
msgctxt "field:stock.unit_load,production_locations:"
|
||||
msgid "Production locations"
|
||||
msgstr "Ubs. de producción"
|
||||
|
||||
msgctxt "field:stock.unit_load,write_date:"
|
||||
msgid "Write Date"
|
||||
msgstr "Fecha modificación"
|
||||
|
|
|
@ -53,38 +53,65 @@ Create product::
|
|||
>>> product.template = template
|
||||
>>> product.save()
|
||||
|
||||
Check sequence for unit load::
|
||||
|
||||
>>> UnitLoad = Model.get('stock.unit_load')
|
||||
>>> unit_load = UnitLoad()
|
||||
>>> unit_load.product = product
|
||||
>>> unit_load.save()
|
||||
>>> unit_load.code
|
||||
u'1'
|
||||
|
||||
Get stock locations::
|
||||
|
||||
>>> Location = Model.get('stock.location')
|
||||
>>> production_loc = Location(name='Production', code='PL')
|
||||
>>> production_loc.type = 'production'
|
||||
>>> production_loc.save()
|
||||
>>> production_loc, = Location.find([('type', '=', 'production')])
|
||||
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
|
||||
>>> storage_loc, = Location.find([('code', '=', 'STO')])
|
||||
>>> output_loc, = Location.find([('code', '=', 'OUT')])
|
||||
|
||||
Create an unit load::
|
||||
|
||||
>>> UnitLoad = Model.get('stock.unit_load')
|
||||
>>> unit_load = UnitLoad()
|
||||
>>> unit_load.company != None
|
||||
True
|
||||
>>> unit_load.production_type = 'location'
|
||||
>>> unit_load.production_location = output_loc
|
||||
>>> unit_load.product = product
|
||||
>>> 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::
|
||||
|
||||
>>> move = unit_load.moves.new()
|
||||
>>> move.planned_date = today
|
||||
>>> move.product = product
|
||||
>>> move.quantity = Decimal(35)
|
||||
>>> move.from_location = production_loc
|
||||
>>> 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 = company.currency
|
||||
>>> move.currency == unit_load.company.currency
|
||||
True
|
||||
>>> unit_load.save()
|
||||
>>> unit_load.state
|
||||
u'draft'
|
||||
>>> unit_load.moves[0].state
|
||||
>>> unit_load.production_state
|
||||
'running'
|
||||
>>> len(unit_load.moves)
|
||||
1
|
||||
>>> len(unit_load.production_moves)
|
||||
1
|
||||
>>> unit_load.production_moves[0].state
|
||||
u'draft'
|
||||
|
||||
Check computed fields::
|
||||
|
@ -98,6 +125,8 @@ Check computed fields::
|
|||
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
|
||||
|
@ -119,6 +148,8 @@ State error::
|
|||
>>> unit_load.click('do')
|
||||
>>> unit_load.state
|
||||
u'done'
|
||||
>>> unit_load.production_state
|
||||
'done'
|
||||
>>> unit_load.quantity
|
||||
35.0
|
||||
>>> unit_load.forecast_quantity
|
||||
|
@ -148,15 +179,6 @@ Date error::
|
|||
>>> unit_load.last_date == tomorrow
|
||||
True
|
||||
|
||||
Production locations::
|
||||
|
||||
>>> unit_load.reload()
|
||||
>>> len(unit_load.production_locations)
|
||||
1
|
||||
>>> unit_load.production_locations[0].code
|
||||
u'PL'
|
||||
|
||||
|
||||
Cancel last move::
|
||||
|
||||
>>> unit_load.location.id == output_loc.id
|
||||
|
|
|
@ -46,13 +46,10 @@ def create_unit_load(config=None, product=None, do_state=True):
|
|||
production_loc.type = 'production'
|
||||
production_loc.save()
|
||||
|
||||
move = unit_load.moves.new()
|
||||
move.planned_date = today
|
||||
move.product = unit_load.product
|
||||
move.quantity = Decimal(35)
|
||||
move.from_location = production_loc
|
||||
unit_load.production_location = production_loc
|
||||
unit_load.quantity = Decimal(35)
|
||||
move = unit_load.production_moves[0]
|
||||
move.to_location = storage_loc
|
||||
move.currency = move.company.currency
|
||||
unit_load.save()
|
||||
if do_state:
|
||||
unit_load.click('do')
|
||||
|
|
|
@ -3,7 +3,7 @@ version=3.6.1
|
|||
depends:
|
||||
ir
|
||||
res
|
||||
stock
|
||||
production
|
||||
|
||||
extras_depend:
|
||||
stock_lot
|
||||
|
|
266
unit_load.py
266
unit_load.py
|
@ -6,11 +6,9 @@ from itertools import groupby
|
|||
from sql import Literal, Null
|
||||
from sql.aggregate import Max
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.functions import Now
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.pyson import Not, Eval, Bool, Or, Equal, Date
|
||||
from trytond.pyson import Not, Eval, Bool, Or, Equal, Date, If
|
||||
from trytond.model import fields, ModelView, ModelSQL
|
||||
from trytond.tools import grouped_slice, reduce_ids
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
||||
|
||||
|
@ -19,8 +17,8 @@ __all__ = ['UnitLoad', 'UnitLoadMove', 'MoveUnitLoad',
|
|||
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
UL_STATES = {'readonly': Bool(Eval('moves', [0]))}
|
||||
UL_DEPENDS = ['moves']
|
||||
MOVE_CHANGES = ['product', 'uom', 'production_type', 'production_location', 'warehouse',
|
||||
'production_moves', 'moves', 'production_state', 'company', 'quantity']
|
||||
|
||||
|
||||
class UnitLoad(ModelView, ModelSQL):
|
||||
|
@ -34,6 +32,11 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
code_readonly = fields.Function(fields.Boolean('Code Readonly'),
|
||||
'get_code_readonly')
|
||||
code_length = fields.Integer('Code Length', select=True, readonly=True)
|
||||
company = fields.Many2One('company.company', 'Company', required=True,
|
||||
states={'readonly': Eval('state') != 'draft'},
|
||||
domain=[('id', If(Eval('context', {}).contains('company'), '=', '!='),
|
||||
Eval('context', {}).get('company', -1))],
|
||||
depends=['state'], select=True)
|
||||
product = fields.Many2One('product.product', 'Product',
|
||||
select=True, required=True,
|
||||
ondelete='RESTRICT')
|
||||
|
@ -41,13 +44,18 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
'on_change_with_uom')
|
||||
uom_digits = fields.Function(fields.Integer('UOM Digits'),
|
||||
'on_change_with_uom_digits')
|
||||
quantity = fields.Function(fields.Float('Quantity'),
|
||||
'get_quantity',
|
||||
searcher='search_quantity')
|
||||
forecast_quantity = fields.Function(fields.Float('Forecast Quantity'),
|
||||
'get_quantity',
|
||||
searcher='search_quantity')
|
||||
moves = fields.One2Many('stock.move', 'unit_load', 'Moves', readonly=True)
|
||||
quantity = fields.Function(fields.Float('Quantity', digits=(16, Eval('uom_digits', 2)),
|
||||
states={'readonly': Eval('production_state') == 'done'},
|
||||
depends=['uom_digits', 'production_state']),
|
||||
'get_quantity', setter='set_quantity', searcher='search_quantity')
|
||||
forecast_quantity = fields.Function(
|
||||
fields.Float('Forecast Quantity', digits=(16, Eval('uom_digits', 2)),
|
||||
depends=['uom_digits']),
|
||||
'get_quantity', searcher='search_quantity')
|
||||
moves = fields.One2Many('stock.move', 'unit_load', 'Moves',
|
||||
readonly=True,
|
||||
domain=[('company', '=', Eval('company', -1))],
|
||||
depends=['company'])
|
||||
location = fields.Function(fields.Many2One('stock.location', 'Location',
|
||||
depends=['moves']),
|
||||
'get_location')
|
||||
|
@ -59,22 +67,61 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
domain=[('unit_load', '=', Eval('id'))],
|
||||
depends=['id']),
|
||||
'get_last_moves')
|
||||
ul_moves = fields.Function(
|
||||
fields.One2Many('stock.unit_load.move', 'unit_load', 'UL moves',
|
||||
readonly=True,
|
||||
context={'unit_load': Eval('id')},
|
||||
depends=['id']),
|
||||
'get_ul_moves')
|
||||
ul_moves = fields.One2Many('stock.unit_load.move', 'unit_load', 'UL moves', readonly=True,
|
||||
states={'invisible': Eval('production_state') != 'done'},
|
||||
depends=['production_state'])
|
||||
state = fields.Function(fields.Selection([
|
||||
('staging', 'Staging'),
|
||||
('draft', 'Draft'),
|
||||
('assigned', 'Assigned'),
|
||||
('done', 'Done'),
|
||||
('cancel', 'Canceled')], 'State', select=True, readonly=True),
|
||||
'get_state', searcher='search_state')
|
||||
production_locations = fields.Function(
|
||||
fields.One2Many('stock.location', None, 'Production locations'),
|
||||
'get_production_locations')
|
||||
'on_change_with_state', searcher='search_state')
|
||||
production_type = fields.Function(
|
||||
fields.Selection([('location', 'Location')], 'Production type',
|
||||
states={'readonly': (Eval('production_state') == 'done')},
|
||||
depends=['production_state']),
|
||||
'get_production_type', setter='set_production_type')
|
||||
warehouse = fields.Many2One('stock.location', 'Warehouse',
|
||||
domain=[('type', '=', 'warehouse')],
|
||||
states={'readonly': Eval('production_state') == 'done'},
|
||||
depends=['production_state'])
|
||||
warehouse_production = fields.Function(
|
||||
fields.Many2One('stock.location', 'Warehouse production',
|
||||
domain=[('type', '=', 'production')]),
|
||||
'on_change_with_warehouse_production')
|
||||
production_location = fields.Many2One('stock.location', 'Production location',
|
||||
domain=[('type', '=', 'production'),
|
||||
If(Bool(Eval('warehouse')),
|
||||
('parent', 'child_of', Eval('warehouse_production')),
|
||||
())],
|
||||
states={'readonly': (Eval('production_state') == 'done'),
|
||||
'required': Eval('production_type') == 'location',
|
||||
'invisible': Eval('production_type') != 'location'},
|
||||
depends=['production_state', 'production_type', 'warehouse',
|
||||
'warehouse_production'])
|
||||
production_state = fields.Function(
|
||||
fields.Selection([('running', 'Running'),
|
||||
('done', 'Done')], 'Production state'),
|
||||
'get_production_state')
|
||||
production_moves = fields.Function(
|
||||
fields.One2Many('stock.move', 'unit_load', 'Production moves',
|
||||
domain=[['OR',
|
||||
[('product', '=', Eval('product')),
|
||||
('from_location.type', '=', 'production'),
|
||||
('to_location.type', '=', 'storage')],
|
||||
[('product', '!=', Eval('product')),
|
||||
['OR',
|
||||
[('from_location.type', '=', 'production'),
|
||||
('to_location.type', '=', 'storage')],
|
||||
[('to_location.type', '=', 'production'),
|
||||
('from_location.type', '=', 'storage')]]
|
||||
]],
|
||||
('company', '=', Eval('company', -1))],
|
||||
states={'readonly': Eval('production_state') == 'done',
|
||||
'invisible': Eval('production_state') == 'done'},
|
||||
depends=['production_state', 'company', 'product']),
|
||||
'get_production_moves', setter='set_production_moves')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
|
@ -89,13 +136,13 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
'move_try': {'icon': 'tryton-go-next',
|
||||
'invisible': Eval('state') != 'done'},
|
||||
'assign': {'icon': 'tryton-go-next',
|
||||
'invisible': Or(Eval('state') != 'draft', Not(Bool(Eval('moves', []))))},
|
||||
'invisible': (Eval('state') != 'draft')},
|
||||
'do': {'icon': 'tryton-ok',
|
||||
'invisible': Eval('state') != 'assigned'},
|
||||
'cancel': {'icon': 'tryton-cancel',
|
||||
'invisible': Or(Eval('state').in_(['cancel', 'done']), Not(Bool(Eval('moves', []))))},
|
||||
'invisible': Eval('state').in_(['cancel', 'done'])},
|
||||
'draft': {'icon': 'tryton-clear',
|
||||
'invisible': Eval('state') != 'cancel'}
|
||||
'invisible': Eval('state') != 'cancel'},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
|
@ -107,6 +154,10 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
def get_code_readonly(self, name):
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def default_company():
|
||||
return Transaction().context.get('company')
|
||||
|
||||
@classmethod
|
||||
def default_state(cls):
|
||||
return 'draft'
|
||||
|
@ -243,6 +294,10 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
location_ids = list(location_ids)
|
||||
return location_ids, wh_to_add, storage_to_remove
|
||||
|
||||
@classmethod
|
||||
def set_quantity(cls, records, name, value):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def search_quantity(cls, name, domain=None):
|
||||
location_ids = Transaction().context.get('locations')
|
||||
|
@ -314,19 +369,13 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
locations[key[-1]] = key[0]
|
||||
return locations
|
||||
|
||||
def get_ul_moves(self, name=None):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.unit_load.move')
|
||||
|
||||
if not Transaction().context.get('unit_load'):
|
||||
Transaction().context['unit_load'] = self.id
|
||||
moves = Move.search([])
|
||||
return [m.id for m in moves]
|
||||
|
||||
def get_last_date(self, name=None):
|
||||
if not self.moves:
|
||||
return None
|
||||
return max(m.effective_date or m.planned_date for m in self.moves if m.state != 'cancel')
|
||||
_moves = [m for m in self.moves if m.state != 'cancel' and m.product.id == self.product.id]
|
||||
if not _moves:
|
||||
return None
|
||||
return max(m.effective_date or m.planned_date for m in _moves)
|
||||
|
||||
def get_last_moves(self, name=None):
|
||||
if not self.moves:
|
||||
|
@ -344,31 +393,52 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
values.append(move.id)
|
||||
return values
|
||||
|
||||
def get_production_type(self, name=None):
|
||||
if self.production_location:
|
||||
return 'location'
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_production_locations(cls, records, name=None):
|
||||
def default_production_type(cls):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Location = pool.get('stock.location')
|
||||
Configuration = pool.get('stock.configuration')
|
||||
return Configuration(1).ul_production_type or 'location'
|
||||
|
||||
move = Move.__table__()
|
||||
ul = cls.__table__()
|
||||
location = Location.__table__()
|
||||
cursor = Transaction().cursor
|
||||
@classmethod
|
||||
def set_production_type(cls, records, name, value):
|
||||
pass
|
||||
|
||||
values = {r.id: [] for r in records}
|
||||
for sub_ids in grouped_slice([r.id for r in records]):
|
||||
red_sql = reduce_ids(ul.id, sub_ids)
|
||||
cursor.execute(*move.join(ul, condition=(move.unit_load == ul.id)
|
||||
).join(location, condition=(move.from_location == location.id)
|
||||
).select(ul.id, move.from_location,
|
||||
where=red_sql & (location.type == 'production') &
|
||||
(move.state != 'cancel'))
|
||||
)
|
||||
for ul, loc in cursor.fetchall():
|
||||
values[ul].append(loc)
|
||||
@fields.depends('warehouse')
|
||||
def on_change_with_warehouse_production(self, name=None):
|
||||
if self.warehouse:
|
||||
return self.warehouse.production_location.id
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def default_production_state(cls):
|
||||
return 'running'
|
||||
|
||||
def get_production_state(self, name=None):
|
||||
if (self.production_moves and
|
||||
all(m.state == 'done' for m in self.production_moves)):
|
||||
return 'done'
|
||||
return 'running'
|
||||
|
||||
def get_production_moves(self, name=None):
|
||||
if not self.moves:
|
||||
return []
|
||||
values = [m.id for m in self.moves if m.from_location.type == 'production'] or []
|
||||
if self.production_type == 'location':
|
||||
values.extend([m.id for m in self.moves if m.to_location.id == self.production_location.id
|
||||
and m.product.id != self.product.id])
|
||||
return values
|
||||
|
||||
@classmethod
|
||||
def set_production_moves(cls, records, name, value):
|
||||
if not value:
|
||||
return
|
||||
cls.write(records, {'moves': value})
|
||||
|
||||
@classmethod
|
||||
def move(cls, records, to_location, at_date=None):
|
||||
pool = Pool()
|
||||
|
@ -433,7 +503,8 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
def _get_group_move_key(self, moves, move):
|
||||
return (move.to_location.id, move.product.id)
|
||||
|
||||
def get_state(self, name=None):
|
||||
@fields.depends('moves')
|
||||
def on_change_with_state(self, name=None):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
|
||||
|
@ -476,53 +547,112 @@ class UnitLoad(ModelView, ModelSQL):
|
|||
moves = [m for r in records for m in r.last_moves]
|
||||
Move.write(moves, {'planned_date': value})
|
||||
|
||||
@classmethod
|
||||
def delete(cls, records):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Move.cancel([m for r in records for m in r.moves])
|
||||
Move.delete([m for r in records for m in r.moves])
|
||||
super(UnitLoad, cls).delete(records)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button_action('stock_unit_load.wizard_move_unit_load')
|
||||
def move_try(cls, records):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def draft(cls, records):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
moves = [m for r in records for m in r.last_moves]
|
||||
moves = [m for r in records for m in r.moves if m.state in ['cancel', 'assigned']]
|
||||
if moves:
|
||||
Move.draft(moves)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def cancel(cls, records):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
moves = [m for r in records for m in r.last_moves]
|
||||
moves = [m for r in records for m in r.moves if m.state in ['draft', 'assigned']]
|
||||
if moves:
|
||||
Move.cancel(moves)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def assign(cls, records):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
moves = [m for r in records for m in r.last_moves]
|
||||
moves = [m for r in records for m in r.moves if m.state == 'draft']
|
||||
cls.check_origin(records)
|
||||
if moves:
|
||||
Move.assign(moves)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def do(cls, records):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
moves = [m for r in records for m in r.last_moves]
|
||||
moves = [m for r in records for m in r.moves if m.state in ['draft', 'assigned']]
|
||||
cls.check_origin(records)
|
||||
if moves:
|
||||
Move.do(moves)
|
||||
|
||||
@classmethod
|
||||
def check_origin(cls, records):
|
||||
moves = [m for r in records for m in r.last_moves]
|
||||
moves = [m for r in records for m in r.moves if m.state in ['draft', 'assigned']]
|
||||
for move in moves:
|
||||
if move.origin:
|
||||
cls.raise_user_error('state_origin', (move.unit_load.rec_name,
|
||||
move.origin.rec_name))
|
||||
|
||||
@fields.depends(*MOVE_CHANGES)
|
||||
def on_change_product(self):
|
||||
self.explode_production_moves()
|
||||
|
||||
@fields.depends(*MOVE_CHANGES)
|
||||
def on_change_quantity(self):
|
||||
self.explode_production_moves()
|
||||
|
||||
@fields.depends(*MOVE_CHANGES)
|
||||
def on_change_production_location(self):
|
||||
self.explode_production_moves()
|
||||
|
||||
@ModelView.button_change(*MOVE_CHANGES)
|
||||
def reset_production_moves(self):
|
||||
self.explode_production_moves()
|
||||
|
||||
def explode_production_moves(self):
|
||||
if self.production_state == 'done':
|
||||
return
|
||||
if not self._check_production_data():
|
||||
self.production_moves = []
|
||||
return
|
||||
move = self._get_production_move()
|
||||
self.production_moves = [move]
|
||||
|
||||
def _get_production_move(self):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Date = pool.get('ir.date')
|
||||
|
||||
move = Move(company=self.company,
|
||||
from_location=self.production_location,
|
||||
product=self.product,
|
||||
quantity=self.quantity,
|
||||
unit_load=self,
|
||||
planned_date=Date.today(),
|
||||
currency=self.company.currency if self.company else None,
|
||||
state='draft')
|
||||
move.on_change_product()
|
||||
return move
|
||||
|
||||
def _check_production_data(self):
|
||||
return not (
|
||||
not self.product or
|
||||
(self.production_type == 'location' and not self.production_location) or
|
||||
not self.quantity)
|
||||
|
||||
|
||||
class UnitLoadMove(ModelSQL, ModelView):
|
||||
"""Unit load movement"""
|
||||
|
@ -550,29 +680,27 @@ class UnitLoadMove(ModelSQL, ModelView):
|
|||
Move = pool.get('stock.move')
|
||||
UL = pool.get('stock.unit_load')
|
||||
move = Move.__table__()
|
||||
ul = UL.__table__()
|
||||
|
||||
ul_id = Transaction().context.get('unit_load')
|
||||
ul = UL(ul_id)
|
||||
where_clause = (move.state != 'cancel')
|
||||
if getattr(ul, 'product', None):
|
||||
where_clause &= (move.product == ul.product.id)
|
||||
date_column = Coalesce(move.effective_date, move.planned_date
|
||||
).as_('date')
|
||||
return move.select(
|
||||
return move.join(ul, condition=(move.product == ul.product)
|
||||
).select(
|
||||
Max(move.id).as_('id'),
|
||||
move.unit_load,
|
||||
move.state,
|
||||
move.from_location,
|
||||
move.to_location,
|
||||
Literal(0).as_('create_uid'),
|
||||
Now().as_('create_date'),
|
||||
Max(move.create_date).as_('create_date'),
|
||||
Literal(None).as_('write_uid'),
|
||||
Literal(None).as_('write_date'),
|
||||
date_column,
|
||||
where=(move.unit_load == ul_id)
|
||||
& (Coalesce(move.effective_date, move.planned_date) != Null)
|
||||
& where_clause,
|
||||
group_by=(date_column, move.unit_load, move.state, move.from_location, move.to_location))
|
||||
where=(Coalesce(move.effective_date, move.planned_date) != Null)
|
||||
& where_clause,
|
||||
group_by=(date_column, move.unit_load, move.state,
|
||||
move.from_location, move.to_location))
|
||||
|
||||
|
||||
class MoveUnitLoadStart(ModelView):
|
||||
|
|
|
@ -5,5 +5,7 @@
|
|||
<xpath expr="/form" position="inside">
|
||||
<label name="unit_load_sequence"/>
|
||||
<field name="unit_load_sequence"/>
|
||||
<label name="ul_production_type"/>
|
||||
<field name="ul_production_type"/>
|
||||
</xpath>
|
||||
</data>
|
|
@ -1,14 +1,28 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<form string="Unit load">
|
||||
<form string="Unit load" col="6" cursor="warehouse">
|
||||
<label name="code"/>
|
||||
<field name="code"/>
|
||||
<label name="company"/>
|
||||
<field name="company"/>
|
||||
<label name="warehouse"/>
|
||||
<field name="warehouse"/>
|
||||
<label name="production_type"/>
|
||||
<field name="production_type"/>
|
||||
<group id="prod_type" colspan="2" col="2">
|
||||
<label name="production_location"/>
|
||||
<field name="production_location"/>
|
||||
</group>
|
||||
<label name="product"/>
|
||||
<field name="product"/>
|
||||
<newline />
|
||||
<notebook>
|
||||
<label name="quantity"/>
|
||||
<field name="quantity"/>
|
||||
<label name="uom"/>
|
||||
<field name="uom"/>
|
||||
<notebook colspan="6">
|
||||
<page id="general" string="General" col="6">
|
||||
<field name="production_moves" colspan="6"/>
|
||||
<field name="ul_moves" colspan="6"/>
|
||||
</page>
|
||||
<page id="moves" string="Product moves">
|
||||
|
@ -16,13 +30,20 @@
|
|||
<field name="last_moves" colspan="4"/>
|
||||
</page>
|
||||
<page id="others" string="Other info">
|
||||
|
||||
<label name="warehouse_production"/>
|
||||
<field name="warehouse_production"/>
|
||||
<label name="location"/>
|
||||
<field name="location"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<group col="4" colspan="6" id="state_buttons">
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
<group col="2" colspan="2" id="states" yfill="1">
|
||||
<label name="state"/>
|
||||
<field name="state"/>
|
||||
<label name="production_state"/>
|
||||
<field name="production_state"/>
|
||||
</group>
|
||||
<group col="5" colspan="2" id="buttons">
|
||||
<button string="Cancel" name="cancel" />
|
||||
<button string="Reset to Draft" name="draft"/>
|
||||
|
|
Loading…
Reference in New Issue