342 lines
13 KiB
Python
342 lines
13 KiB
Python
# The COPYRIGHT file at the top level of this repository contains the full
|
|
# copyright notices and license terms.
|
|
from trytond.model import fields, ModelView, ModelSQL, Workflow, Check, Unique
|
|
from trytond.pyson import And, Bool, Equal, Eval, Id, If, Not, Or
|
|
from trytond.pool import Pool
|
|
from trytond.transaction import Transaction
|
|
from trytond.exceptions import UserError
|
|
from trytond.i18n import gettext
|
|
|
|
from .abstract_event import AbstractEvent, ImportedEventMixin, \
|
|
_STATES_WRITE_DRAFT, _DEPENDS_WRITE_DRAFT, \
|
|
_STATES_VALIDATED, _DEPENDS_VALIDATED
|
|
|
|
|
|
_INVISIBLE_NOT_GROUP = {
|
|
'invisible': ~ (Eval('produced_animal_type') == 'group')
|
|
}
|
|
|
|
|
|
|
|
class FarrowingProblem(ModelSQL, ModelView):
|
|
'''Farrowing Event Problem'''
|
|
__name__ = 'farm.farrowing.problem'
|
|
_order_name = 'name'
|
|
|
|
name = fields.Char('Name', required=True, translate=True)
|
|
|
|
|
|
class FarrowingEvent(AbstractEvent, ImportedEventMixin, ModelSQL, ModelView, Workflow):
|
|
'''Farm Farrowing Event'''
|
|
__name__ = 'farm.farrowing.event'
|
|
_table = 'farm_farrowing_event'
|
|
|
|
live = fields.Integer('Live', states=_STATES_WRITE_DRAFT,
|
|
depends=_DEPENDS_WRITE_DRAFT)
|
|
stillborn = fields.Integer(
|
|
'Stillborn', states={**_STATES_WRITE_DRAFT,**_INVISIBLE_NOT_GROUP},
|
|
depends=_DEPENDS_WRITE_DRAFT + ['produced_animal_type'])
|
|
mummified = fields.Integer(
|
|
'Mummified', states={**_STATES_WRITE_DRAFT,**_INVISIBLE_NOT_GROUP},
|
|
depends=_DEPENDS_WRITE_DRAFT + ['produced_animal_type'])
|
|
dead = fields.Function(fields.Integer('Dead', states={
|
|
'invisible': ~Equal(Eval('produced_animal_type'), 'group')
|
|
}, depends=['produced_animal_type']), 'on_change_with_dead')
|
|
problem = fields.Many2One('farm.farrowing.problem', 'Problem',
|
|
states=_STATES_WRITE_DRAFT,
|
|
depends=_DEPENDS_WRITE_DRAFT)
|
|
female_cycle = fields.One2One(
|
|
'farm.farrowing.event-farm.animal.female_cycle', 'event', 'cycle',
|
|
string='Female Cycle', readonly=True, domain=[
|
|
('animal', '=', Eval('animal')),
|
|
],
|
|
states=_STATES_VALIDATED, depends=_DEPENDS_VALIDATED + ['animal'])
|
|
produced_animal_type = fields.Function(fields.Selection([
|
|
('individual', 'Individual'),
|
|
('group', 'Group'),
|
|
], 'Produced Animal Type'),
|
|
'on_change_with_produced_animal_type')
|
|
produced_animals = fields.One2Many('farm.farrowing.event-farm.animal',
|
|
'event', 'Produced Animals', readonly=True, domain=[
|
|
('specie', '=', Eval('specie')),
|
|
],
|
|
states={
|
|
'required': (
|
|
(Eval('state') == 'validated') & (Bool(Eval('live', 0)))
|
|
& (Not(Eval('imported', False)))
|
|
) & (Eval('produced_animal_type') == 'individual'),
|
|
'invisible': ~Equal(Eval('produced_animal_type'), 'individual')
|
|
},
|
|
depends=['specie', 'live', 'state', 'imported', 'produced_animal_type'])
|
|
produced_group = fields.One2One('farm.farrowing.event-farm.animal.group',
|
|
'event', 'animal_group', string='Produced Group', domain=[
|
|
('specie', '=', Eval('specie', -1)),
|
|
('initial_quantity', '=', Eval('live', -1)),
|
|
], readonly=True,
|
|
states={
|
|
'required': And(And(Equal(Eval('state'), 'validated'),
|
|
Bool(Eval('live', 0))), Not(Eval('imported', False)),
|
|
Equal(Eval('produced_animal_type'), 'group')),
|
|
'invisible': ~Equal(Eval('produced_animal_type'), 'group')
|
|
},
|
|
depends=['specie', 'live', 'state', 'imported', 'produced_animal_type'])
|
|
move = fields.Many2One('stock.move', 'Stock Move', readonly=True, domain=[
|
|
('lot.animal_group', '=', Eval('produced_group')),
|
|
],
|
|
states={
|
|
'required': And(And(Equal(Eval('state'), 'validated'),
|
|
Bool(Eval('live', 0))), Not(Eval('imported', False)),
|
|
Equal(Eval('produced_animal_type'), 'group')),
|
|
'invisible': Or(~Eval('context', {}).get('groups', []).contains(
|
|
Id('farm', 'group_farm_admin')),
|
|
~Equal(Eval('produced_animal_type'), 'group')),
|
|
},
|
|
depends=['produced_group', 'live', 'state', 'imported',
|
|
'produced_animal_type'])
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(FarrowingEvent, cls).__setup__()
|
|
cls.animal.domain += [
|
|
('type', '=', 'female'),
|
|
If(~Eval('imported', True),
|
|
('current_cycle', '!=', None),
|
|
()),
|
|
If(Equal(Eval('state'), 'draft') & ~Eval('imported', True),
|
|
('current_cycle.state', '=', 'pregnant'),
|
|
()),
|
|
]
|
|
if 'imported' not in cls.animal.depends:
|
|
cls.animal.depends.add('imported')
|
|
t = cls.__table__()
|
|
cls._sql_constraints += [
|
|
('live_not_negative', Check(t, t.live >= 0),
|
|
'farm.check_farrowing_live_positive'),
|
|
('stillborn_not_negative', Check(t, t.stillborn >= 0),
|
|
'farm.check_farrowing_stillborn_positive'),
|
|
('mummified_not_negative', Check(t, t.mummified >= 0),
|
|
'farm.check_farrowing_mummified_positive'),
|
|
]
|
|
cls._buttons['validate_event']['readonly'] = And(
|
|
Equal(Eval('live', 0), 0),
|
|
Equal(Eval('dead', 0), 0))
|
|
cls._buttons.update({
|
|
'draft': {
|
|
'invisible': Eval('state') == 'draft',
|
|
},
|
|
})
|
|
|
|
@staticmethod
|
|
def default_animal_type():
|
|
return 'female'
|
|
|
|
@staticmethod
|
|
def valid_animal_types():
|
|
return ['female']
|
|
|
|
def get_rec_name(self, name):
|
|
cycle = (self.female_cycle and self.female_cycle.sequence or
|
|
self.animal.current_cycle and self.animal.current_cycle.sequence
|
|
or None)
|
|
if cycle:
|
|
return "%s on cycle %s %s" % (self.animal.rec_name, cycle,
|
|
self.timestamp)
|
|
return super(FarrowingEvent, self).get_rec_name(name)
|
|
|
|
@fields.depends('stillborn', 'mummified')
|
|
def on_change_with_dead(self, name=None):
|
|
return (self.stillborn or 0) + (self.mummified or 0)
|
|
|
|
@fields.depends('animal_type', 'animal', 'produced_animal_type', 'live')
|
|
def on_change_animal(self):
|
|
if not self.animal:
|
|
return
|
|
super(FarrowingEvent, self).on_change_animal()
|
|
self.female_cycle = self.animal.current_cycle
|
|
if self.animal.specie.produced_animal_type == 'individual':
|
|
self.live = 1
|
|
|
|
@fields.depends('animal')
|
|
def on_change_with_produced_animal_type(self, name=None):
|
|
if self.animal and self.animal.specie:
|
|
return self.animal.specie.produced_animal_type
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('validated')
|
|
def validate_event(cls, events):
|
|
pool = Pool()
|
|
Move = pool.get('stock.move')
|
|
EventAnimal = pool.get('farm.farrowing.event-farm.animal')
|
|
todo_moves = []
|
|
for farrowing_event in events:
|
|
if not farrowing_event.dead and not farrowing_event.live:
|
|
raise UserError(gettext('farm.event_without_dead_nor_live',
|
|
event=farrowing_event.rec_name))
|
|
current_cycle = farrowing_event.animal.current_cycle
|
|
farrowing_event.female_cycle = current_cycle
|
|
|
|
if farrowing_event.live != 0:
|
|
with Transaction().set_context(no_create_stock_move=True):
|
|
if farrowing_event.produced_animal_type == 'individual':
|
|
for i in range(farrowing_event.live):
|
|
produced_animal = farrowing_event._get_produced_animal()
|
|
produced_animal.save()
|
|
move = farrowing_event._get_event_move(
|
|
produced_animal)
|
|
move.save()
|
|
todo_moves.append(move)
|
|
eventAnimal = EventAnimal()
|
|
eventAnimal.animal = produced_animal
|
|
eventAnimal.event = farrowing_event
|
|
eventAnimal.move = move
|
|
eventAnimal.save()
|
|
else:
|
|
produced_group = farrowing_event._get_produced_group()
|
|
produced_group.save()
|
|
farrowing_event.produced_group = produced_group
|
|
|
|
move = farrowing_event._get_event_move()
|
|
move.save()
|
|
farrowing_event.move = move
|
|
todo_moves.append(move)
|
|
farrowing_event.save()
|
|
current_cycle.update_state(farrowing_event)
|
|
Move.assign(todo_moves)
|
|
Move.do(todo_moves)
|
|
|
|
def _get_produced_animal(self):
|
|
"""
|
|
Prepare values to create the produced animal in female's farrowing
|
|
"""
|
|
Animal = Pool().get('farm.animal')
|
|
return Animal(
|
|
specie=self.specie,
|
|
breed=self.animal.breed,
|
|
initial_location=self.animal.location,
|
|
type='individual',
|
|
origin='raised')
|
|
|
|
def _get_produced_group(self):
|
|
"""
|
|
Prepare values to create the produced group in female's farrowing
|
|
"""
|
|
AnimalGroup = Pool().get('farm.animal.group')
|
|
return AnimalGroup(
|
|
specie=self.specie,
|
|
breed=self.animal.breed,
|
|
initial_location=self.animal.location,
|
|
initial_quantity=self.live,
|
|
origin='raised')
|
|
|
|
def _get_event_move(self, animal=None):
|
|
pool = Pool()
|
|
Move = pool.get('stock.move')
|
|
context = Transaction().context
|
|
Company = pool.get('company.company')
|
|
company = Company(context['company'])
|
|
|
|
if self.produced_animal_type == 'individual':
|
|
lot = animal.lot
|
|
live = 1
|
|
product = self.specie.individual_product.id
|
|
uom = self.specie.individual_product.default_uom.id
|
|
else:
|
|
lot = self.produced_group.lot
|
|
product = self.specie.group_product.id
|
|
uom = self.specie.group_product.default_uom.id
|
|
live = self.live
|
|
|
|
return Move(
|
|
product=product,
|
|
uom=uom,
|
|
quantity=live,
|
|
from_location=self.farm.production_location.id,
|
|
to_location=self.animal.location.id,
|
|
planned_date=self.timestamp.date(),
|
|
effective_date=self.timestamp.date(),
|
|
company=company,
|
|
lot=lot.id,
|
|
unit_price=lot.product.cost_price,
|
|
currency=company.currency,
|
|
origin=self)
|
|
|
|
@classmethod
|
|
def copy(cls, records, default=None):
|
|
if default is None:
|
|
default = {}
|
|
else:
|
|
default = default.copy()
|
|
default.update({
|
|
'female_cycle': None,
|
|
'produced_animal': None,
|
|
'produced_group': None,
|
|
'move': None,
|
|
})
|
|
return super(FarrowingEvent, cls).copy(records, default=default)
|
|
|
|
|
|
class FarrowingEventFemaleCycle(ModelSQL):
|
|
"Farrowing Event - Female Cycle"
|
|
__name__ = 'farm.farrowing.event-farm.animal.female_cycle'
|
|
|
|
event = fields.Many2One('farm.farrowing.event', 'Farrowing Event',
|
|
required=True, ondelete='RESTRICT')
|
|
cycle = fields.Many2One('farm.animal.female_cycle', 'Female Cycle',
|
|
required=True, ondelete='RESTRICT')
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(FarrowingEventFemaleCycle, cls).__setup__()
|
|
t = cls.__table__()
|
|
cls._sql_constraints += [
|
|
('event_unique', Unique(t, t.event),
|
|
'farm.farrowing_event_unique'),
|
|
('cycle_unique', Unique(t, t.cycle),
|
|
'farm.farrowing_cycle_unique'),
|
|
]
|
|
|
|
|
|
class FarrowingEventAnimalGroup(ModelSQL):
|
|
"Farrowing Event - AnimalGroup"
|
|
__name__ = 'farm.farrowing.event-farm.animal.group'
|
|
|
|
event = fields.Many2One('farm.farrowing.event', 'Farrowing Event',
|
|
required=True, ondelete='RESTRICT')
|
|
animal_group = fields.Many2One('farm.animal.group', 'Group', required=True,
|
|
ondelete='RESTRICT')
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(FarrowingEventAnimalGroup, cls).__setup__()
|
|
t = cls.__table__()
|
|
cls._sql_constraints += [
|
|
('event_unique', Unique(t, t.event),
|
|
'farm.farrowing_event_unique'),
|
|
('animal_group_unique', Unique(t, t.animal_group),
|
|
'farm.farrowing_animal_group_unique'),
|
|
]
|
|
|
|
|
|
class FarmFarrowingEventAnimal(ModelSQL, ModelView):
|
|
'Farrowing Event - Animal'
|
|
__name__ = 'farm.farrowing.event-farm.animal'
|
|
|
|
event = fields.Many2One('farm.farrowing.event', 'Farrowing Event',
|
|
required=True, ondelete='RESTRICT')
|
|
animal = fields.Many2One('farm.animal', 'Animal', required=True,
|
|
ondelete='RESTRICT')
|
|
move = fields.Many2One('stock.move', 'Move', required=True,
|
|
ondelete='RESTRICT')
|
|
specie = fields.Function(
|
|
fields.Many2One('farm.specie', 'Specie'), 'get_specie',
|
|
searcher='search_specie')
|
|
|
|
def get_specie(self):
|
|
if self.animal and self.animal.specie:
|
|
return self.animal.specie
|
|
|
|
@classmethod
|
|
def search_specie(cls, name, clause):
|
|
return [('animal.specie',) + tuple(clause[1:])]
|