diff options
Diffstat (limited to 'odoo/service')
| -rw-r--r-- | odoo/service/model.py | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/odoo/service/model.py b/odoo/service/model.py index 61f63c68155..ca997d0f730 100644 --- a/odoo/service/model.py +++ b/odoo/service/model.py @@ -118,22 +118,40 @@ def check(f): if key in inst.pgerror: raise ValidationError(tr(registry._sql_error[key], 'sql_constraint') or inst.pgerror) if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION): - msg = _('The operation cannot be completed, probably due to the following:\n- deletion: you may be trying to delete a record while other records still reference it\n- creation/update: a mandatory field is not correctly set') + msg = _('The operation cannot be completed:') _logger.debug("IntegrityError", exc_info=True) try: - errortxt = inst.pgerror.replace('«','"').replace('»','"') - if '"public".' in errortxt: - context = errortxt.split('"public".')[1] - model_name = table = context.split('"')[1] - else: - last_quote_end = errortxt.rfind('"') - last_quote_begin = errortxt.rfind('"', 0, last_quote_end) - model_name = table = errortxt[last_quote_begin+1:last_quote_end].strip() - model = table.replace("_",".") - if model in registry: - model_class = registry[model] - model_name = model_class._description or model_class._name - msg += _('\n\n[object with reference: %s - %s]') % (model_name, model) + # Get corresponding model and field + model = field = None + for name, rclass in registry.items(): + if inst.diag.table_name == rclass._table: + model = rclass + field = model._fields.get(inst.diag.column_name) + break + if inst.pgcode == errorcodes.NOT_NULL_VIOLATION: + # This is raised when a field is set with `required=True`. 2 cases: + # - Create/update: a mandatory field is not set. + # - Delete: another model has a not nullable using the deleted record. + msg += '\n' + msg += _( + '- Create/update: a mandatory field is not set.\n' + '- Delete: another model requires the record being deleted. If possible, archive it instead.' + ) + if model: + msg += '\n\n{} {} ({}), {} {} ({})'.format( + _('Model:'), model._description, model._name, + _('Field:'), field.string if field else _('Unknown'), field.name if field else _('Unknown'), + ) + elif inst.pgcode == errorcodes.FOREIGN_KEY_VIOLATION: + # This is raised when a field is set with `ondelete='restrict'`, at + # unlink only. + msg += _(' another model requires the record being deleted. If possible, archive it instead.') + constraint = inst.diag.constraint_name + if model or constraint: + msg += '\n\n{} {} ({}), {} {}'.format( + _('Model:'), model._description if model else _('Unknown'), model._name if model else _('Unknown'), + _('Constraint:'), constraint if constraint else _('Unknown'), + ) except Exception: pass raise ValidationError(msg) |
