trytond-stock_lot_expiry/stock.py

166 lines
5.4 KiB
Python
Raw Normal View History

2013-10-16 13:46:10 +02:00
# The COPYRIGHT file at the top level of this repository contains the full
# copyright notices and license terms.
from datetime import date, timedelta
from trytond.model import Workflow, ModelView, fields
from trytond.pool import Pool, PoolMeta
2018-02-02 13:13:15 +01:00
from trytond.pyson import Bool, Eval, If
2013-10-16 13:46:10 +02:00
from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
2013-10-16 13:46:10 +02:00
__all__ = ['Lot', 'Location', 'Move']
2013-10-16 13:46:10 +02:00
class Lot(metaclass=PoolMeta):
2013-10-16 13:46:10 +02:00
__name__ = 'stock.lot'
expired = fields.Function(fields.Boolean('Expired'),
'get_expired', searcher='search_expired')
def get_rec_name(self, name):
rec_name = super(Lot, self).get_rec_name(name)
if self.expired:
rec_name += ' (%s)' % gettext('stock_lot_expiry.expired')
2013-10-16 13:46:10 +02:00
return rec_name
def get_expired(self, name):
pool = Pool()
Date = pool.get('ir.date')
if not self.expiration_date:
2013-10-16 13:46:10 +02:00
return False
context = Transaction().context
date = Date.today()
if context.get('stock_move_date'):
date = context['stock_move_date']
elif context.get('stock_date_end'):
date = context['stock_date_end']
return self.expiration_date <= date
2013-10-16 13:46:10 +02:00
@classmethod
def search_expired(cls, name, domain=None):
pool = Pool()
Date = pool.get('ir.date')
if not domain:
return []
context = Transaction().context
date = Date.today()
if context.get('stock_move_date'):
date = context['stock_move_date']
elif context.get('stock_date_end'):
date = context['stock_date_end']
2014-06-04 11:04:04 +02:00
_, op, operand = domain
2013-10-16 13:46:10 +02:00
search_expired = (op == '=' and operand
or op == '!=' and not operand)
if search_expired:
return [
('expiration_date', '!=', None),
('expiration_date', '<=', date),
2013-10-16 13:46:10 +02:00
]
else:
return [
'OR', [
('expiration_date', '=', None),
2013-10-16 13:46:10 +02:00
], [
('expiration_date', '>', date),
2013-10-16 13:46:10 +02:00
]]
class Location(metaclass=PoolMeta):
2013-10-16 13:46:10 +02:00
__name__ = 'stock.location'
expired = fields.Boolean('Expired Products\' Location',
help='This option identifies this location as a container for expired '
'products (provably it is a temporal location until the product is '
'returned or removed).\n'
'Take care that if you set this location as a child of the Storage '
'location of a Warehouse, the products in this location will be '
'computed as available stock.')
allow_expired = fields.Boolean('Allow Expired', states={
'invisible': Eval('expired', False),
}, depends=['expired'],
help='Check this option to allow move expired lots to this location.')
@fields.depends('expired', 'allow_expired')
2013-10-16 13:46:10 +02:00
def on_change_expired(self):
if self.expired:
2016-07-05 13:24:15 +02:00
self.allow_expired = True
2013-10-16 13:46:10 +02:00
@classmethod
def create(cls, vlist):
for vals in vlist:
if vals.get('expired'):
vals['allow_expired'] = True
return super(Location, cls).create(vlist)
@classmethod
2014-05-21 10:35:13 +02:00
def write(cls, *args):
actions = iter(args)
args = []
for locations, values in zip(actions, actions):
if values.get('expired'):
values['allow_expired'] = True
args.extend((locations, values))
super(Location, cls).write(*args)
2013-10-16 13:46:10 +02:00
class Move(metaclass=PoolMeta):
2013-10-16 13:46:10 +02:00
__name__ = 'stock.move'
to_location_allow_expired = fields.Function(
fields.Boolean('Destination Allow Expired'),
2013-10-16 13:46:10 +02:00
'on_change_with_to_location_allow_expired')
@classmethod
def __setup__(cls):
super(Move, cls).__setup__()
cls.lot.domain.append(
2018-02-02 13:13:15 +01:00
If((Eval('state', 'draft') == 'draft')
& ~Eval('to_location_allow_expired'),
2013-10-16 13:46:10 +02:00
('expired', '=', False),
()),
)
if not cls.lot.context:
cls.lot.context = {}
cls.lot.context['stock_move_date'] = If(
Bool(Eval('effective_date', False)),
Eval('effective_date'),
Eval('planned_date'))
2015-10-04 10:06:08 +02:00
cls.lot.loading = 'lazy'
2018-02-02 13:13:15 +01:00
2013-10-16 13:46:10 +02:00
for fname in ('state', 'to_location_allow_expired', 'effective_date',
'planned_date'):
if fname not in cls.lot.depends:
cls.lot.depends.append(fname)
@fields.depends('to_location')
2013-10-16 13:46:10 +02:00
def on_change_with_to_location_allow_expired(self, name=None):
return self.to_location and self.to_location.allow_expired or False
@classmethod
@ModelView.button
@Workflow.transition('done')
def do(cls, moves):
for move in moves:
move.check_allow_lot_expired()
super(Move, cls).do(moves)
def check_allow_lot_expired(self):
if self.to_location.allow_expired or not self.lot:
return
error = False
with Transaction().set_context(stock_move_date=self.effective_date):
error = not self.to_location.allow_expired and self.lot.expired
if error:
self.raise_user_error('expired_lot_invalid_destination', {
'move': self.rec_name,
'lot': self.lot.rec_name,
'to_location': self.to_location.rec_name,
})