Files
tryton/modules/stock_split/stock.py
T

200 lines
6.4 KiB
Python
Raw Normal View History

2014-12-02 12:56:13 +01:00
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
2012-09-24 22:18:23 +02:00
from trytond.model import ModelView, fields
from trytond.pool import Pool, PoolMeta
2021-12-11 17:58:44 +01:00
from trytond.pyson import Eval
2012-05-13 23:16:11 +02:00
from trytond.transaction import Transaction
2021-12-11 17:58:44 +01:00
from trytond.wizard import Button, StateTransition, StateView, Wizard
2012-05-13 23:16:11 +02:00
2018-06-26 19:11:57 +02:00
class Move(metaclass=PoolMeta):
2012-09-24 22:18:23 +02:00
__name__ = 'stock.move'
@classmethod
def __setup__(cls):
super(Move, cls).__setup__()
cls._buttons.update({
2012-09-10 15:28:47 +02:00
'split_wizard': {
'readonly': ~Eval('state').in_(['draft', 'assigned']),
2018-02-19 11:42:21 +01:00
'depends': ['state'],
2012-09-10 15:28:47 +02:00
},
})
2012-09-24 22:18:23 +02:00
@classmethod
2012-09-10 15:28:47 +02:00
@ModelView.button_action('stock_split.wizard_split_move')
2012-09-24 22:18:23 +02:00
def split_wizard(cls, moves):
2012-09-10 15:28:47 +02:00
pass
2023-08-22 13:18:33 +02:00
def split(self, quantity, unit, count=None):
2012-05-13 23:16:11 +02:00
"""
Split the move into moves of quantity.
If count is not defined, the move will be split until the remainder is
less than quantity.
2012-09-24 22:18:23 +02:00
Return the split moves
2012-05-13 23:16:11 +02:00
"""
pool = Pool()
2012-09-24 22:18:23 +02:00
Uom = pool.get('product.uom')
2012-05-13 23:16:11 +02:00
2012-09-24 22:18:23 +02:00
moves = [self]
2023-08-22 13:18:33 +02:00
remainder = Uom.compute_qty(self.unit, self.quantity, unit)
2012-05-13 23:16:11 +02:00
if remainder <= quantity:
return moves
2012-09-24 22:18:23 +02:00
state = self.state
self.write([self], {
2012-05-13 23:16:11 +02:00
'state': 'draft',
})
2012-09-24 22:18:23 +02:00
self.write([self], {
2012-05-13 23:16:11 +02:00
'quantity': quantity,
2023-08-22 13:18:33 +02:00
'unit': unit.id,
2012-05-13 23:16:11 +02:00
})
remainder -= quantity
if count:
count -= 1
while (remainder > quantity
and (count or count is None)):
with Transaction().set_context(_stock_move_split=True):
moves.extend(self.copy([self], {
'quantity': quantity,
2023-08-22 13:18:33 +02:00
'unit': unit.id,
}))
2012-05-13 23:16:11 +02:00
remainder -= quantity
if count:
count -= 1
2023-08-22 13:18:33 +02:00
remainder = unit.round(remainder)
2012-05-13 23:16:11 +02:00
assert remainder >= 0
if remainder:
with Transaction().set_context(_stock_move_split=True):
moves.extend(self.copy([self], {
'quantity': remainder,
2023-08-22 13:18:33 +02:00
'unit': unit.id,
2012-05-13 23:16:11 +02:00
}))
2013-03-13 17:38:24 +01:00
self.write(moves, {
'state': state,
})
2012-05-13 23:16:11 +02:00
return moves
class SplitMoveStart(ModelView):
'Split Move'
2012-09-24 22:18:23 +02:00
__name__ = 'stock.move.split.start'
2019-09-30 09:40:07 +02:00
count = fields.Integer('Counts', help='The limit number of moves.')
2023-08-22 13:18:33 +02:00
quantity = fields.Float("Quantity", digits='unit', required=True)
unit = fields.Many2One(
'product.uom', "Unit", required=True,
2012-05-13 23:16:11 +02:00
domain=[
('category', '=', Eval('uom_category')),
])
2023-08-20 12:17:27 +02:00
uom_category = fields.Many2One(
'product.uom.category', "UoM Category", readonly=True,
help="The category of Unit of Measure.")
2012-05-13 23:16:11 +02:00
class SplitMove(Wizard):
'Split Move'
2012-09-24 22:18:23 +02:00
__name__ = 'stock.move.split'
2012-05-13 23:16:11 +02:00
start = StateView('stock.move.split.start',
'stock_split.split_start_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
2012-06-27 17:40:22 +00:00
Button('Split', 'split', 'tryton-ok', default=True),
2012-05-13 23:16:11 +02:00
])
split = StateTransition()
2012-09-24 22:18:23 +02:00
def default_start(self, fields):
return {
2023-08-22 13:18:33 +02:00
'unit': self.record.unit.id,
'uom_category': self.record.unit.category.id,
}
2012-05-13 23:16:11 +02:00
2012-09-24 22:18:23 +02:00
def transition_split(self):
self.record.split(
2023-08-22 13:18:33 +02:00
self.start.quantity, self.start.unit, self.start.count)
2012-05-13 23:16:11 +02:00
return 'end'
2017-09-07 18:42:26 +02:00
class _ShipmentSplit(ModelView):
@classmethod
def __setup__(cls):
super(_ShipmentSplit, cls).__setup__()
cls._buttons.update({
'split_wizard': {
'readonly': Eval('state') != 'draft',
'invisible': Eval('state') != 'draft',
2018-02-19 11:42:21 +01:00
'depends': ['state'],
2017-09-07 18:42:26 +02:00
},
})
@classmethod
@ModelView.button_action('stock_split.wizard_split_shipment')
def split_wizard(cls, shipments):
pass
2018-06-26 19:11:57 +02:00
class ShipmentInReturn(_ShipmentSplit, metaclass=PoolMeta):
2017-09-07 18:42:26 +02:00
__name__ = 'stock.shipment.in.return'
2018-06-26 19:11:57 +02:00
class ShipmentOut(_ShipmentSplit, metaclass=PoolMeta):
2017-09-07 18:42:26 +02:00
__name__ = 'stock.shipment.out'
2018-06-26 19:11:57 +02:00
class ShipmentInternal(_ShipmentSplit, metaclass=PoolMeta):
2017-09-07 18:42:26 +02:00
__name__ = 'stock.shipment.internal'
class SplitShipment(Wizard):
"Split Shipment"
__name__ = 'stock.shipment.split'
start = StateView('stock.shipment.split.start',
'stock_split.shipment_split_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Split", 'split', 'tryton-ok', default=True),
])
split = StateTransition()
def get_moves(self, shipment):
if shipment.__name__ == 'stock.shipment.out':
return shipment.outgoing_moves
elif shipment.__name__ in {
'stock.shipment.in.return',
'stock.shipment.internal',
}:
return shipment.moves
def default_start(self, fields):
moves = self.get_moves(self.record)
2018-06-26 19:11:57 +02:00
move_ids = [m.id for m in moves if m.state == 'draft']
2017-09-07 18:42:26 +02:00
return {
2018-06-26 19:11:57 +02:00
'domain_moves': move_ids,
2017-09-07 18:42:26 +02:00
}
def transition_split(self):
pool = Pool()
Move = pool.get('stock.move')
shipment = self.record
Shipment = self.model
2017-09-07 18:42:26 +02:00
if shipment.state != 'draft':
raise ValueError("Wrong shipment state")
if not set(self.start.moves).issubset(self.start.domain_moves):
raise ValueError("Invalid moves, %s != %s" % (self.start.moves,
self.start.domain_moves))
if Shipment.__name__ == 'stock.shipment.out':
Move.draft(shipment.inventory_moves)
Move.delete(
2018-06-26 19:11:57 +02:00
[m for m in shipment.inventory_moves if m.state == 'draft'])
2017-09-07 18:42:26 +02:00
shipment, = Shipment.copy([shipment], default={'moves': None})
2017-09-07 18:42:26 +02:00
Move.write(list(self.start.moves), {'shipment': str(shipment)})
return 'end'
class SplitShipmentStart(ModelView):
"Split Shipment"
__name__ = 'stock.shipment.split.start'
moves = fields.Many2Many(
'stock.move', None, None, "Moves",
domain=[('id', 'in', Eval('domain_moves'))],
help="The selected moves will be sent in the new shipment.")
domain_moves = fields.Many2Many('stock.move', None, None, "Domain Moves")