Use a single assign wizard
issue9422 review299961011
This commit is contained in:
1 parent
0915d89979
commit
f6eb3790f3
6 files changed
+152
-214
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Use a single assign wizard for all shipments
|
||||
* Add access rules to product quantities by warehouse
|
||||
* Add moves for product quantities by warehouse
|
||||
* Enforce filling cost price of move
|
||||
|
||||
+2
-6
@@ -30,11 +30,9 @@ def register():
|
||||
shipment.ShipmentInReturn,
|
||||
shipment.ShipmentOut,
|
||||
shipment.ShipmentOutReturn,
|
||||
shipment.AssignShipmentOutAssignFailed,
|
||||
shipment.ShipmentInternal,
|
||||
shipment.AssignPartial,
|
||||
shipment.Address,
|
||||
shipment.AssignShipmentInternalAssignFailed,
|
||||
shipment.AssignShipmentInReturnAssignFailed,
|
||||
period.Period,
|
||||
period.Cache,
|
||||
product.Template,
|
||||
@@ -57,9 +55,7 @@ def register():
|
||||
res.User,
|
||||
module='stock', type_='model')
|
||||
Pool.register(
|
||||
shipment.AssignShipmentOut,
|
||||
shipment.AssignShipmentInternal,
|
||||
shipment.AssignShipmentInReturn,
|
||||
shipment.Assign,
|
||||
product.OpenProductQuantitiesByWarehouse,
|
||||
product.RecomputeCostPrice,
|
||||
product.ModifyCostPrice,
|
||||
|
||||
+107
-161
@@ -8,7 +8,7 @@ from functools import partial
|
||||
from sql import Null
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields
|
||||
from trytond.model import Workflow, ModelView, ModelSQL, fields, dualmethod
|
||||
from trytond.model.exceptions import AccessError
|
||||
from trytond.modules.company import CompanyReport
|
||||
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
||||
@@ -28,6 +28,43 @@ class ShipmentMixin:
|
||||
]
|
||||
|
||||
|
||||
class ShipmentAssignMixin(ShipmentMixin):
|
||||
|
||||
@classmethod
|
||||
def assign_wizard(cls, shipments):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def assign_moves(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@dualmethod
|
||||
@ModelView.button
|
||||
def assign_try(cls, shipments):
|
||||
raise NotImplementedError
|
||||
|
||||
@dualmethod
|
||||
def assign_reset(cls, shipments):
|
||||
cls.wait(shipments)
|
||||
|
||||
@dualmethod
|
||||
@ModelView.button
|
||||
def assign_force(cls, shipments):
|
||||
cls.assign(shipments)
|
||||
|
||||
@dualmethod
|
||||
def assign_ignore(cls, shipments):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Move.write([
|
||||
m for s in shipments for m in s.assign_moves
|
||||
if m.assignation_required
|
||||
and m.state in {'staging', 'draft'}], {
|
||||
'quantity': 0,
|
||||
})
|
||||
cls.assign(shipments)
|
||||
|
||||
|
||||
class ShipmentIn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
"Supplier Shipment"
|
||||
__name__ = 'stock.shipment.in'
|
||||
@@ -457,7 +494,7 @@ class ShipmentIn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
})
|
||||
|
||||
|
||||
class ShipmentInReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
class ShipmentInReturn(ShipmentAssignMixin, Workflow, ModelSQL, ModelView):
|
||||
"Supplier Return Shipment"
|
||||
__name__ = 'stock.shipment.in.return'
|
||||
_rec_name = 'number'
|
||||
@@ -736,7 +773,7 @@ class ShipmentInReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
@set_employee('assigned_by')
|
||||
def assign(cls, shipments):
|
||||
Move = Pool().get('stock.move')
|
||||
Move.assign([m for s in shipments for m in s.moves])
|
||||
Move.assign([m for s in shipments for m in s.assign_moves])
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@@ -764,7 +801,11 @@ class ShipmentInReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
def assign_wizard(cls, shipments):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@property
|
||||
def assign_moves(self):
|
||||
return self.moves
|
||||
|
||||
@dualmethod
|
||||
@ModelView.button
|
||||
def assign_try(cls, shipments, with_childs=None):
|
||||
pool = Pool()
|
||||
@@ -772,7 +813,7 @@ class ShipmentInReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
to_assign = defaultdict(list)
|
||||
for shipment in shipments:
|
||||
location_type = shipment.from_location.type
|
||||
for move in shipment.moves:
|
||||
for move in shipment.assign_moves:
|
||||
if move.assignation_required:
|
||||
to_assign[location_type].append(move)
|
||||
success = True
|
||||
@@ -789,13 +830,8 @@ class ShipmentInReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
cls.assign(shipments)
|
||||
return success
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def assign_force(cls, shipments):
|
||||
cls.assign(shipments)
|
||||
|
||||
|
||||
class ShipmentOut(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
class ShipmentOut(ShipmentAssignMixin, Workflow, ModelSQL, ModelView):
|
||||
"Customer Shipment"
|
||||
__name__ = 'stock.shipment.out'
|
||||
_rec_name = 'number'
|
||||
@@ -1134,6 +1170,9 @@ class ShipmentOut(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
@Workflow.transition('assigned')
|
||||
@set_employee('assigned_by')
|
||||
def assign(cls, shipments):
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Move.assign([m for s in shipments for m in s.assign_moves])
|
||||
cls._sync_inventory_to_outgoing(shipments, quantity=False)
|
||||
|
||||
@classmethod
|
||||
@@ -1347,11 +1386,16 @@ class ShipmentOut(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
def assign_wizard(cls, shipments):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@property
|
||||
def assign_moves(self):
|
||||
return self.inventory_moves
|
||||
|
||||
@dualmethod
|
||||
@ModelView.button
|
||||
def assign_try(cls, shipments):
|
||||
Move = Pool().get('stock.move')
|
||||
to_assign = [m for s in shipments for m in s.inventory_moves
|
||||
to_assign = [
|
||||
m for s in shipments for m in s.assign_moves
|
||||
if m.assignation_required]
|
||||
if Move.assign_try(to_assign):
|
||||
cls.assign(shipments)
|
||||
@@ -1359,13 +1403,6 @@ class ShipmentOut(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
else:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def assign_force(cls, shipments):
|
||||
Move = Pool().get('stock.move')
|
||||
Move.assign([m for s in shipments for m in s.inventory_moves])
|
||||
cls.assign(shipments)
|
||||
|
||||
|
||||
class ShipmentOutReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
"Customer Return Shipment"
|
||||
@@ -1774,56 +1811,7 @@ class ShipmentOutReturn(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
cls.save(shipments)
|
||||
|
||||
|
||||
class AssignShipmentOutAssignFailed(ModelView):
|
||||
'Assign Customer Shipment'
|
||||
__name__ = 'stock.shipment.out.assign.failed'
|
||||
inventory_moves = fields.Many2Many('stock.move', None, None,
|
||||
'Inventory Moves', readonly=True,
|
||||
help="The inventory moves that were not assigned.")
|
||||
|
||||
@staticmethod
|
||||
def default_inventory_moves():
|
||||
ShipmentOut = Pool().get('stock.shipment.out')
|
||||
shipment_id = Transaction().context.get('active_id')
|
||||
if not shipment_id:
|
||||
return []
|
||||
shipment = ShipmentOut(shipment_id)
|
||||
return [x.id for x in shipment.inventory_moves if x.state == 'draft']
|
||||
|
||||
|
||||
class AssignShipmentOut(Wizard):
|
||||
'Assign Customer Shipment'
|
||||
__name__ = 'stock.shipment.out.assign'
|
||||
start = StateTransition()
|
||||
failed = StateView('stock.shipment.out.assign.failed',
|
||||
'stock.shipment_out_assign_failed_view_form', [
|
||||
Button('Force Assign', 'force', 'tryton-forward',
|
||||
states={
|
||||
'invisible': ~Id('stock',
|
||||
'group_stock_force_assignment').in_(
|
||||
Eval('context', {}).get('groups', [])),
|
||||
}),
|
||||
Button('OK', 'end', 'tryton-ok', True),
|
||||
])
|
||||
force = StateTransition()
|
||||
|
||||
def transition_start(self):
|
||||
pool = Pool()
|
||||
Shipment = pool.get('stock.shipment.out')
|
||||
|
||||
if Shipment.assign_try([Shipment(Transaction().context['active_id'])]):
|
||||
return 'end'
|
||||
else:
|
||||
return 'failed'
|
||||
|
||||
def transition_force(self):
|
||||
Shipment = Pool().get('stock.shipment.out')
|
||||
|
||||
Shipment.assign_force([Shipment(Transaction().context['active_id'])])
|
||||
return 'end'
|
||||
|
||||
|
||||
class ShipmentInternal(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
class ShipmentInternal(ShipmentAssignMixin, Workflow, ModelSQL, ModelView):
|
||||
"Internal Shipment"
|
||||
__name__ = 'stock.shipment.internal'
|
||||
_rec_name = 'number'
|
||||
@@ -2353,7 +2341,9 @@ class ShipmentInternal(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
@Workflow.transition('assigned')
|
||||
@set_employee('assigned_by')
|
||||
def assign(cls, shipments):
|
||||
pass
|
||||
pool = Pool()
|
||||
Move = pool.get('stock.move')
|
||||
Move.assign([m for s in shipments for m in s.assign_moves])
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@@ -2394,11 +2384,16 @@ class ShipmentInternal(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
def assign_wizard(cls, shipments):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
@property
|
||||
def assign_moves(self):
|
||||
return self.outgoing_moves
|
||||
|
||||
@dualmethod
|
||||
@ModelView.button
|
||||
def assign_try(cls, shipments):
|
||||
Move = Pool().get('stock.move')
|
||||
to_assign = [m for s in shipments for m in s.outgoing_moves
|
||||
to_assign = [
|
||||
m for s in shipments for m in s.assign_moves
|
||||
if m.assignation_required]
|
||||
if not to_assign or Move.assign_try(to_assign):
|
||||
cls.assign(shipments)
|
||||
@@ -2406,13 +2401,6 @@ class ShipmentInternal(ShipmentMixin, Workflow, ModelSQL, ModelView):
|
||||
else:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def assign_force(cls, shipments):
|
||||
Move = Pool().get('stock.move')
|
||||
Move.assign([m for s in shipments for m in s.outgoing_moves])
|
||||
cls.assign(shipments)
|
||||
|
||||
@property
|
||||
def _move_planned_date(self):
|
||||
'''
|
||||
@@ -2457,103 +2445,61 @@ class Address(metaclass=PoolMeta):
|
||||
help="Check to send deliveries to the address.")
|
||||
|
||||
|
||||
class AssignShipmentInternalAssignFailed(ModelView):
|
||||
'Assign Shipment Internal'
|
||||
__name__ = 'stock.shipment.internal.assign.failed'
|
||||
moves = fields.Many2Many('stock.move', None, None, 'Moves',
|
||||
readonly=True,
|
||||
help="The moves that were not assigned.")
|
||||
|
||||
@staticmethod
|
||||
def default_moves():
|
||||
ShipmentInternal = Pool().get('stock.shipment.internal')
|
||||
shipment_id = Transaction().context.get('active_id')
|
||||
if not shipment_id:
|
||||
return []
|
||||
shipment = ShipmentInternal(shipment_id)
|
||||
return [x.id for x in shipment.outgoing_moves if x.state == 'draft']
|
||||
|
||||
|
||||
class AssignShipmentInternal(Wizard):
|
||||
'Assign Shipment Internal'
|
||||
__name__ = 'stock.shipment.internal.assign'
|
||||
class Assign(Wizard):
|
||||
"Assign Shipment"
|
||||
__name__ = 'stock.shipment.assign'
|
||||
start = StateTransition()
|
||||
failed = StateView('stock.shipment.internal.assign.failed',
|
||||
'stock.shipment_internal_assign_failed_view_form', [
|
||||
Button('Force Assign', 'force', 'tryton-forward',
|
||||
states={
|
||||
'invisible': ~Id('stock',
|
||||
'group_stock_force_assignment').in_(
|
||||
Eval('context', {}).get('groups', [])),
|
||||
}),
|
||||
Button('OK', 'end', 'tryton-ok', True),
|
||||
])
|
||||
force = StateTransition()
|
||||
|
||||
def transition_start(self):
|
||||
pool = Pool()
|
||||
Shipment = pool.get('stock.shipment.internal')
|
||||
|
||||
if Shipment.assign_try([Shipment(Transaction().context['active_id'])]):
|
||||
return 'end'
|
||||
else:
|
||||
return 'failed'
|
||||
|
||||
def transition_force(self):
|
||||
Shipment = Pool().get('stock.shipment.internal')
|
||||
|
||||
Shipment.assign_force([Shipment(Transaction().context['active_id'])])
|
||||
return 'end'
|
||||
|
||||
|
||||
class AssignShipmentInReturnAssignFailed(ModelView):
|
||||
'Assign Supplier Return Shipment'
|
||||
__name__ = 'stock.shipment.in.return.assign.failed'
|
||||
moves = fields.Many2Many('stock.move', None, None, 'Moves',
|
||||
readonly=True,
|
||||
help="The moves that were not assigned.")
|
||||
|
||||
@staticmethod
|
||||
def default_moves():
|
||||
ShipmentInternal = Pool().get('stock.shipment.in.return')
|
||||
shipment_id = Transaction().context.get('active_id')
|
||||
if not shipment_id:
|
||||
return []
|
||||
shipment = ShipmentInternal(shipment_id)
|
||||
return [x.id for x in shipment.moves if x.state == 'draft']
|
||||
|
||||
|
||||
class AssignShipmentInReturn(Wizard):
|
||||
'Assign Supplier Return Shipment'
|
||||
__name__ = 'stock.shipment.in.return.assign'
|
||||
start = StateTransition()
|
||||
failed = StateView('stock.shipment.in.return.assign.failed',
|
||||
'stock.shipment_in_return_assign_failed_view_form', [
|
||||
Button('Force Assign', 'force', 'tryton-forward',
|
||||
partial = StateView(
|
||||
'stock.shipment.assign.partial',
|
||||
'stock.shipment_assign_partial_view_form', [
|
||||
Button("Cancel", 'cancel', 'tryton-cancel'),
|
||||
Button("Wait", 'end', 'tryton-ok', True),
|
||||
Button("Ignore", 'ignore', 'tryton-forward'),
|
||||
Button("Force", 'force', 'tryton-forward',
|
||||
states={
|
||||
'invisible': ~Id('stock',
|
||||
'group_stock_force_assignment').in_(
|
||||
Eval('context', {}).get('groups', [])),
|
||||
}),
|
||||
Button('OK', 'end', 'tryton-ok', True),
|
||||
])
|
||||
cancel = StateTransition()
|
||||
force = StateTransition()
|
||||
ignore = StateTransition()
|
||||
|
||||
def transition_start(self):
|
||||
pool = Pool()
|
||||
Shipment = pool.get('stock.shipment.in.return')
|
||||
|
||||
if Shipment.assign_try([Shipment(Transaction().context['active_id'])]):
|
||||
if self.record.assign_try():
|
||||
return 'end'
|
||||
else:
|
||||
return 'failed'
|
||||
return 'partial'
|
||||
|
||||
def default_partial(self, fields):
|
||||
values = {}
|
||||
if 'moves' in fields:
|
||||
values['moves'] = [
|
||||
m.id for m in self.record.assign_moves
|
||||
if m.state in {'staging', 'draft'}]
|
||||
return values
|
||||
|
||||
def transition_cancel(self):
|
||||
self.record.assign_reset()
|
||||
return 'end'
|
||||
|
||||
def transition_force(self):
|
||||
Shipment = Pool().get('stock.shipment.in.return')
|
||||
|
||||
Shipment.assign_force([Shipment(Transaction().context['active_id'])])
|
||||
self.record.assign_force()
|
||||
return 'end'
|
||||
|
||||
def transition_ignore(self):
|
||||
self.record.assign_ignore()
|
||||
return 'end'
|
||||
|
||||
|
||||
class AssignPartial(ModelView):
|
||||
"Assign Shipment"
|
||||
__name__ = 'stock.shipment.assign.partial'
|
||||
moves = fields.Many2Many(
|
||||
'stock.move', None, None, "Moves", readonly=True,
|
||||
help="The moves that were not assigned.")
|
||||
|
||||
|
||||
class DeliveryNote(CompanyReport):
|
||||
'Delivery Note'
|
||||
|
||||
+23
-36
@@ -54,12 +54,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<menuitem parent="menu_stock" sequence="20"
|
||||
action="act_shipment_in_form" id="menu_shipment_in_form"/>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_shipment_in_return_assign">
|
||||
<field name="name">Assign Purchase Return Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.in.return.assign</field>
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_in_return_view_form">
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
<field name="type">form</field>
|
||||
@@ -122,18 +116,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
action="act_shipment_in_return_form"
|
||||
id="menu_shipment_in_return_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_in_return_assign_failed_view_form">
|
||||
<field name="model">stock.shipment.in.return.assign.failed</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_in_return_assign_failed_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_shipment_out_assign">
|
||||
<field name="name">Assign Customer Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.out.assign</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_out_view_form">
|
||||
<field name="model">stock.shipment.out</field>
|
||||
<field name="type">form</field>
|
||||
@@ -199,18 +181,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<menuitem parent="menu_stock" sequence="30"
|
||||
action="act_shipment_out_form" id="menu_shipment_out_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_out_assign_failed_view_form">
|
||||
<field name="model">stock.shipment.out.assign.failed</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_out_assign_failed_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_shipment_internal_assign">
|
||||
<field name="name">Assign Shipment Internal</field>
|
||||
<field name="wiz_name">stock.shipment.internal.assign</field>
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_internal_view_form">
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
<field name="type">form</field>
|
||||
@@ -288,12 +258,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
action="act_shipment_internal_form"
|
||||
id="menu_shipment_internal_form"/>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_internal_assign_failed_view_form">
|
||||
<field name="model">stock.shipment.internal.assign.failed</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_internal_assign_failed_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_out_return_view_form">
|
||||
<field name="model">stock.shipment.out.return</field>
|
||||
<field name="type">form</field>
|
||||
@@ -1069,5 +1033,28 @@ this repository contains the full copyright notices and license terms. -->
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_shipment_internal"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="shipment_assign_partial_view_form">
|
||||
<field name="model">stock.shipment.assign.partial</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">shipment_assign_partial_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.wizard" id="wizard_shipment_in_return_assign">
|
||||
<field name="name">Assign Supplier Return Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.in.return</field>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="wizard_shipment_out_assign">
|
||||
<field name="name">Assign Customer Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.out</field>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="wizard_shipment_internal_assign">
|
||||
<field name="name">Assign Internal Shipment</field>
|
||||
<field name="wiz_name">stock.shipment.assign</field>
|
||||
<field name="model">stock.shipment.internal</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -132,8 +132,10 @@ Make 1 unit of the product available::
|
||||
|
||||
Assign the shipment now::
|
||||
|
||||
>>> shipment_out.click('assign_try')
|
||||
False
|
||||
>>> shipment_assign = Wizard('stock.shipment.assign', [shipment_out])
|
||||
>>> len(shipment_assign.form.moves)
|
||||
1
|
||||
>>> shipment_assign.execute('end')
|
||||
>>> shipment_out.reload()
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
@@ -152,14 +154,12 @@ Assign the shipment now::
|
||||
>>> len(set(planned_dates))
|
||||
1
|
||||
|
||||
Delete the draft move, assign and pack shipment::
|
||||
Ignore non assigned moves and pack shipment::
|
||||
|
||||
>>> for move in shipment_out.inventory_moves:
|
||||
... if move.state == 'draft':
|
||||
... break
|
||||
>>> shipment_out.inventory_moves.remove(move)
|
||||
>>> shipment_out.click('assign_try')
|
||||
True
|
||||
>>> shipment_assign = Wizard('stock.shipment.assign', [shipment_out])
|
||||
>>> shipment_assign.execute('ignore')
|
||||
>>> sorted([m.quantity for m in shipment_out.inventory_moves])
|
||||
[0.0, 1.0]
|
||||
>>> shipment_out.assigned_by == employee
|
||||
True
|
||||
>>> shipment_out.packed_by
|
||||
@@ -174,7 +174,7 @@ Delete the draft move, assign and pack shipment::
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
2
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> sum([m.quantity for m in shipment_out.inventory_moves]) == \
|
||||
@@ -199,7 +199,7 @@ Set the state as Done::
|
||||
>>> len(shipment_out.outgoing_moves)
|
||||
2
|
||||
>>> len(shipment_out.inventory_moves)
|
||||
1
|
||||
2
|
||||
>>> shipment_out.inventory_moves[0].state
|
||||
'done'
|
||||
>>> sum([m.quantity for m in shipment_out.inventory_moves]) == \
|
||||
|
||||
@@ -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. -->
|
||||
<form col="2">
|
||||
<image name="tryton-warning" xexpand="0" xfill="0"/>
|
||||
<separator string="Unable to assign these products:" id="unable"/>
|
||||
<field name="moves" colspan="2" view_ids="stock.move_view_tree_simple"/>
|
||||
</form>
|
||||
Reference in new issue
Block a user