Вместе с нашей командой мы хотели бы реализовать функцию, при которой пользователь будет предупрежден, когда запись, которую он / она обновляет, также была обновлена одним из его коллег с тех пор, как он / она открыла запись.
Мы копались в исходном коде, потому что не нашли никакой официальной документации, а только некоторые модули, которые не подходили к нашей версии Odoo (11).
Мы нашли в файле /odoo/odoo/models.py метод def _check_concurrency(self): со следующим кодом:
@api.multi
def _check_concurrency(self):
if not (self._log_access and self._context.get(self.CONCURRENCY_CHECK_FIELD)):
return
check_clause = "(id = %s AND %s < COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp)"
for sub_ids in self._cr.split_for_in_conditions(self.ids):
nclauses = 0
params = []
for id in sub_ids:
id_ref = "%s,%s" % (self._name, id)
update_date = self._context[self.CONCURRENCY_CHECK_FIELD].pop(id_ref, None)
if update_date:
nclauses += 1
params.extend([id, update_date])
if not nclauses:
continue
query = "SELECT id FROM %s WHERE %s" % (self._table, " OR ".join([check_clause] * nclauses))
self._cr.execute(query, tuple(params))
res = self._cr.fetchone()
if res:
# mention the first one only to keep the error message readable
raise ValidationError(_('A document was modified since you last viewed it (%s:%d)') % (self._description, res[0]))
=> Этот метод вызывается перед любой "записью". Он сравнивает:
значение __last_update записи на момент write
со значением __last_update получить из контекста, который, следовательно, должен был быть установлен в context заранее
ПРОБЛЕМА
Мы не нашли нигде в коде (python или javascript) значение, установленное в контексте => НИЧЕГО НЕ ПРОИСХОДИТ! Функция возвращается с самого начала.
Когда мы попытались жестко закодировать его в контексте, функция check_concurrency, похоже, работает правильно.
ВОПРОС
Кто-нибудь знает, где установлен __last_update или ДОЛЖЕН БЫТЬ установлен в контексте? И как ? Я бы, например, представьте себе установку как-нибудь при нажатии на кнопку редактирования записи ??? Или во время чтения ??






CONCURRENCY_CHECK_FIELD = '__last_update'
поле параллелизма - это динамическое поле, метод вычислений которого определяется динамически, и вы также можете видеть, что оно обновляется
last_modified_name = 'compute_concurrency_field_with_access' или last_modified_name = 'compute_concurrency_field' в зависимости от доступа и позже добавлены в класс. Следующие функции будут участвовать в обходном пути.
@api.model
def _add_magic_fields(self):
""" Introduce magic fields on the current class
* id is a "normal" field (with a specific getter)
* create_uid, create_date, write_uid and write_date have become
"normal" fields
* $CONCURRENCY_CHECK_FIELD is a computed field with its computing
method defined dynamically. Uses ``str(datetime.datetime.utcnow())``
to get the same structure as the previous
``(now() at time zone 'UTC')::timestamp``::
# select (now() at time zone 'UTC')::timestamp;
timezone
----------------------------
2013-06-18 08:30:37.292809
>>> str(datetime.datetime.utcnow())
'2013-06-18 08:31:32.821177'
"""
def add(name, field):
""" add ``field`` with the given ``name`` if it does not exist yet """
if name not in self._fields:
self._add_field(name, field)
# cyclic import
from . import fields
# this field 'id' must override any other column or field
self._add_field('id', fields.Id(automatic=True))
add('display_name', fields.Char(string='Display Name', automatic=True,
compute='_compute_display_name'))
if self._log_access:
add('create_uid', fields.Many2one('res.users', string='Created by', automatic=True))
add('create_date', fields.Datetime(string='Created on', automatic=True))
add('write_uid', fields.Many2one('res.users', string='Last Updated by', automatic=True))
add('write_date', fields.Datetime(string='Last Updated on', automatic=True))
last_modified_name = 'compute_concurrency_field_with_access'
else:
last_modified_name = 'compute_concurrency_field'
# this field must override any other column or field
self._add_field(self.CONCURRENCY_CHECK_FIELD, fields.Datetime(
string='Last Modified on', compute=last_modified_name, automatic=True))
def compute_concurrency_field(self):
for record in self:
record[self.CONCURRENCY_CHECK_FIELD] = odoo.fields.Datetime.now()
@api.depends('create_date', 'write_date')
def compute_concurrency_field_with_access(self):
for record in self:
record[self.CONCURRENCY_CHECK_FIELD] = \
record.write_date or record.create_date or odoo.fields.Datetime.now()
Мы также заметили этот файл как часть процесса проверки параллелизма. Однако, похоже, нам не хватает конфигурации, чтобы этот метод действительно определял одновременный доступ. Не могли бы вы сообщить мне, как я могу настроить, скажем, модель
Contact, чтобы включить проверку параллелизма при обновлении на этой модели?