diff --git a/tryton/common/common.py b/tryton/common/common.py index f48d6e1ce1..778a31e748 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -794,17 +794,21 @@ def process_exception(exception, parent, obj='', method='', *args): method, *args) return True - if exception.args[0] == 'ConcurrencyException' \ - and len(args) > 4: - if concurrency(args[0], args[2][0], args[4], parent): - if '_timestamp' in args[4]: - del args[4]['_timestamp'] - try: - return rpc.execute(obj, method, *args) - except Exception, exception: - return process_exception(exception, parent, obj, - method, *args) - return False + if exception.args[0] == 'ConcurrencyException': + if len(args) > 4: + if concurrency(args[0], args[2][0], args[4], parent): + if '_timestamp' in args[4]: + del args[4]['_timestamp'] + try: + return rpc.execute(obj, method, *args) + except Exception, exception: + return process_exception(exception, parent, obj, + method, *args) + return False + else: + message(_('Concurrency Exception'), parent, + msg_type=gtk.MESSAGE_ERROR) + return False if exception.args[0] == 'UserWarning': msg = '' diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index fa51d933d6..0ce73c238f 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -154,6 +154,9 @@ class CharField(object): model.state_attrs[self.name]['readonly'] = True return model.state_attrs[self.name] + def get_timestamp(self, model): + return {} + class SelectionField(CharField): @@ -438,9 +441,21 @@ class O2MField(CharField): result.append(('create', model2.get(check_load=check_load, get_readonly=readonly))) if model.value[self.name].model_removed: - result.append(('unlink', model.value[self.name].model_removed)) + result.append(('unlink', [x.id for x in \ + model.value[self.name].model_removed])) if model.value[self.name].model_deleted: - result.append(('delete', model.value[self.name].model_deleted)) + result.append(('delete', [x.id for x in \ + model.value[self.name].model_deleted])) + return result + + def get_timestamp(self, model): + if not model.value[self.name]: + return {} + result = {} + for model2 in (model.value[self.name].models \ + + model.value[self.name].model_removed \ + + model.value[self.name].model_deleted): + result.update(model2.get_timestamp()) return result def get_eval(self, model, check_load=True): @@ -568,7 +583,7 @@ class O2MField(CharField): model.value[self.name].readonly = False def get_removed_ids(self, model): - return model.value[self.name].model_removed + return [x.id for x in model.value[self.name].model_removed] class ReferenceField(CharField): diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py index 10869f4f18..c08e6e9a60 100644 --- a/tryton/gui/window/view_form/model/group.py +++ b/tryton/gui/window/view_form/model/group.py @@ -160,10 +160,12 @@ class ModelRecordGroup(SignalEvent): newmods.append(newmod) newmod.signal_connect(self, 'record-changed', self._record_changed) newmod.signal_connect(self, 'record-modified', self._record_modified) - if id in self.model_removed: - self.model_removed.remove(id) - if id in self.model_deleted: - self.model_deleted.remove(id) + for model in list(self.model_removed): + if model.id == id: + self.model_removed.remove(model) + for model in list(self.model_deleted): + if model.id == id: + self.model_deleted.remove(model) if len(ids) > 10: self.models.lock_signal = False self.signal('record-cleared') @@ -296,9 +298,9 @@ class ModelRecordGroup(SignalEvent): idx = self.models.index(model) if self.models[idx].id > 0: if remove: - self.model_removed.append(self.models[idx].id) + self.model_removed.append(self.models[idx]) else: - self.model_deleted.append(self.models[idx].id) + self.model_deleted.append(self.models[idx]) if model.parent: model.parent.modified = True if modified: diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index 6f0263362f..38d956fd78 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -155,6 +155,12 @@ class ModelRecord(SignalEvent): self._loaded = False self.reload() + def get_timestamp(self): + result = {self.resource + ',' + str(self.id): self._timestamp} + for name, mfield in self.mgroup.mfields.items(): + result.update(mfield.get_timestamp(self)) + return result + def save(self, force_reload=True): self._check_load() if self.id < 0: @@ -174,8 +180,7 @@ class ModelRecord(SignalEvent): value = self.get(get_readonly=False, get_modifiedonly=True) context = self.context_get() context = context.copy() - context['_timestamp'] = {} - context['_timestamp'][self.id] = self._timestamp + context['_timestamp'] = self.get_timestamp() args = ('object', 'execute', self.resource, 'write', [self.id], value, context) try: diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index b25e48bed8..ee024837a4 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -470,11 +470,15 @@ class Screen(SignalEvent): if self.current_view.view_type == 'form' and self.current_model: obj_id = self.current_model.id if delete and obj_id > 0: + context = {} + context.update(rpc.CONTEXT) + context.update(self.context) + context['_timestamp'] = self.current_model.get_timestamp() try: reload_ids = self.models.on_write_ids(obj_id) if reload_ids and obj_id in reload_ids: reload_ids.remove(obj_id) - if not self.rpc.delete([obj_id], rpc.CONTEXT): + if not self.rpc.delete([obj_id], context): return False except Exception, exception: common.process_exception(exception, self.window) @@ -495,13 +499,20 @@ class Screen(SignalEvent): if self.current_view.view_type == 'tree': ids = self.current_view.sel_ids_get() if delete and ids: + context = {} + context.update(rpc.CONTEXT) + context.update(self.context) + context['_timestamp'] = {} + for obj_id in ids: + model = self.models.get_by_id(obj_id) + context['_timestamp'].update(model.get_timestamp()) try: reload_ids = self.models.on_write_ids(ids) if reload_ids: for obj_id in ids: if obj_id in reload_ids: reload_ids.remove(obj_id) - if not self.rpc.delete(ids, rpc.CONTEXT): + if not self.rpc.delete(ids, context): return False except Exception, exception: common.process_exception(exception, self.window)