Voilà j'ai les classes suivantes "arbre" et "emplacement" qui sont
historisées en "evol_arbre" et "evol_emplacement". J'ai une classe
"station" qui contient les emplacements qui contiennent les arbres. lorsque
je modifie/crée un nouvel arbre ou un nouvel emplacement la table history
ne contient que la seule modification apportée à arbre ou à emplacement.
Par contre quand je modifie dans la vue station un arbre ou un emplacement,
la vue historisée "arbre" ou "emplacement" contient tous les arbres et tous
les emplacements de la station qu'il aient été modifié ou pas.
Ma question comment n'avoir que l'arbre ou l'emplacement qui a été modifié
dans la table historisée ?
Voici les classes ci-dessous :
class arbre(Mapable, ModelSQL, ModelView):
u'Arbres'
__name__ = 'cg.arbre'
_rec_name ='essence'
_history = True
evolution = fields.One2Many(
'cg.arbre.history',
'arbre',
string=u'Évolutions',
help=u'Évolutions de l\'arbre',
)
station = fields.Many2One(
'cg.station',
ondelete='CASCADE',
string=u'Code Station',
help=u'Code de la station',
required = True,
states=STATES,
depends=DEPENDS,
)
@staticmethod
def default_station():
return Transaction().context.get('station')
emplacement = fields.Many2One(
'cg.emplacement',
ondelete='CASCADE',
string=u'ID Emplacement',
help=u'Identifiant de l\'emplacement de référence',
required = True,
states=STATES,
depends=DEPENDS,
)
class evol_arbre(ModelSQL, ModelView):
u'Évolution d\'un arbre'
__name__ = 'cg.arbre.history'
date = fields.DateTime(
string = u'Date',
help=u'Date de création du constat ou de sa mise à jour',
readonly=True,
)
emplacement = fields.Many2One(
'cg.emplacement',
string=u'Emplacement',
help=u'Code de l\'emplacement de référence',
readonly=True,
)
station = fields.Many2One(
'cg.station',
string=u'Code Station',
help=u'Code de la station',
readonly=True,
)
arbre = fields.Many2One(
'cg.arbre',
string=u'ID Arbre',
help=u'Identifiant de l\'arbre',
readonly=True,
)
code = fields.Char(
string = u'ID Arbre',
help=u'Identifiant de l\'arbre',
readonly=True,
)
travaux = fields.Function(
fields.One2Many(
'cg.travaux',
None,
string=u'Travaux',
help=u'travaux',
readonly=True,
),
'get_travaux',
)
@classmethod
def _table_query_fields(cls):
Arbre = Pool().get('cg.arbre')
table = '%s__history' % Arbre._table
return [
'MIN("%s".__id) AS id' % table,
'"%s".id AS arbre' % table,
('MIN(COALESCE("%s".write_date, "%s".create_date)) AS date'
% (table, table)),
('COALESCE("%s".write_uid, "%s".create_uid) AS user'
% (table, table)),
] + ['"%s"."%s"' % (table, name)
for name, field in cls._fields.iteritems()
if name not in ('id', 'arbre', 'date', 'user')
and not hasattr(field, 'set')]
@classmethod
def _table_query_group(cls):
Arbre = Pool().get('cg.arbre')
table = '%s__history' % Arbre._table
return [
'"%s".id' % table,
'COALESCE("%s".write_uid, "%s".create_uid)' % (table, table),
] + ['"%s"."%s"' % (table, name)
for name, field in cls._fields.iteritems()
if (name not in ('id', 'arbre', 'date', 'user')
and not hasattr(field, 'set'))]
@classmethod
def table_query(cls):
Arbre = Pool().get('cg.arbre')
return (('SELECT ' + (', '.join(cls._table_query_fields()))
+ ' FROM "%s__history" GROUP BY '
+ (', '.join(cls._table_query_group())))
% Arbre._table, [])
def get_travaux(self, name):
Line = Pool().get('cg.arbre.travaux')
# We will always have only one id per call due to datetime_field
lines = Line.search([
('arbre', '=', self.arbre.id),
])
return [l.id for l in lines]
@classmethod
def read(cls, ids, fields_names=None):
res = super(evol_arbre, cls).read(ids,
fields_names=fields_names)
# Remove microsecond from timestamp
for values in res:
if 'date' in values:
if isinstance(values['date'], basestring):
values['date'] = datetime.datetime(
*time.strptime(values['date'],
'%Y-%m-%d %H:%M:%S.%f')[:6])
values['date'] = values['date'].replace(microsecond=0)
return res
class emplacement(Mapable, ModelSQL, ModelView):
u'Emplacement'
__name__ = 'cg.emplacement'
_history = True
station = fields.Many2One(
'cg.station',
ondelete='CASCADE',
string=u'Code Station',
help=u'Code de la station',
required = True,
states=STATES,
depends=DEPENDS,
)
evolution = fields.One2Many(
'cg.emplacement.history',
'emplacement',
string=u'Évolutions',
help=u'Évolutions de l\'emplacement',
states=STATES,
depends=DEPENDS,
)
arbres = fields.One2Many(
'cg.arbre',
'emplacement',
string=u'Arbres',
help=u'Arbres présents sur cet emplacement',
states=STATES,
depends=DEPENDS,
)
class evol_emplacement(ModelSQL, ModelView):
u'Évolution d\'un emplacement'
__name__ = 'cg.emplacement.history'
date = fields.DateTime(
string = u'Date de création',
help=u'Date de création ou de mise à jour du constat',
readonly=True,
)
station = fields.Many2One(
'cg.station',
string=u'Code Station',
help=u'Code de la station',
readonly=True,
)
emplacement = fields.Many2One(
'cg.emplacement',
string=u'Emplacement',
help=u'Emplacement',
readonly=True,
)
arbres = fields.Function(
fields.One2Many(
'cg.arbre',
'emplacement',
string=u'Arbres',
help=u'Arbres présents sur cet emplacement',
),
'get_arbres',
)
@classmethod
def _table_query_fields(cls):
Emplacement = Pool().get('cg.emplacement')
table = '%s__history' % Emplacement._table
return [
'MIN("%s".__id) AS id' % table,
'"%s".id AS emplacement' % table,
('MIN(COALESCE("%s".write_date, "%s".create_date)) AS date'
% (table, table)),
('COALESCE("%s".write_uid, "%s".create_uid) AS user'
% (table, table)),
] + ['"%s"."%s"' % (table, name)
for name, field in cls._fields.iteritems()
if name not in ('id', 'emplacement', 'date', 'user')
and not hasattr(field, 'set')]
@classmethod
def _table_query_group(cls):
Emplacement = Pool().get('cg.emplacement')
table = '%s__history' % Emplacement._table
return [
'"%s".id' % table,
'COALESCE("%s".write_uid, "%s".create_uid)' % (table, table),
] + ['"%s"."%s"' % (table, name)
for name, field in cls._fields.iteritems()
if (name not in ('id', 'emplacement', 'date', 'user')
and not hasattr(field, 'set'))]
@classmethod
def table_query(cls):
Emplacement = Pool().get('cg.emplacement')
return (('SELECT ' + (', '.join(cls._table_query_fields()))
+ ' FROM "%s__history" GROUP BY '
+ (', '.join(cls._table_query_group())))
% Emplacement._table, [])
def get_arbres(self, name):
Line = Pool().get('cg.emplacement.arbre')
# We will always have only one id per call due to datetime_field
lines = Line.search([
('emplacement', '=', self.emplacement.id),
])
return [l.id for l in lines]
@classmethod
def read(cls, ids, fields_names=None):
res = super(evol_emplacement, cls).read(ids,
fields_names=fields_names)
# Remove microsecond from timestamp
for values in res:
if 'date' in values:
if isinstance(values['date'], basestring):
values['date'] = datetime.datetime(
*time.strptime(values['date'],
'%Y-%m-%d %H:%M:%S.%f')[:6])
values['date'] = values['date'].replace(microsecond=0)
return res
class station(Mapable, ModelSQL, ModelView):
u'Stations'
__name__ = 'cg.station'
_rec_name = 'code'
code = fields.Char(
string = u'Code station',
help=u'Code de la station',
required = True,
states=STATES,
depends=DEPENDS,
)
emplacement = fields.One2Many(
'cg.emplacement',
'station',
string=u'Emplacements',
help=u'Emplacements de la station',
required=False,
states=STATES,
depends=DEPENDS,
)
arbre = fields.One2Many(
'cg.arbre',
'station',
string=u'Arbres',
help=u'Arbres de la station',
required=False,
states=STATES,
depends=DEPENDS,
)