diff --git a/partner_revision/__openerp__.py b/partner_revision/__openerp__.py index 0494543ce..9588a7081 100644 --- a/partner_revision/__openerp__.py +++ b/partner_revision/__openerp__.py @@ -27,7 +27,8 @@ 'depends': ['base', ], 'website': 'http://www.camptocamp.com', - 'data': ['views/res_partner_revision_views.xml', + 'data': ['views/menu.xml', + 'views/res_partner_revision_views.xml', 'views/revision_behavior_views.xml', ], 'test': [], diff --git a/partner_revision/models/res_partner_revision.py b/partner_revision/models/res_partner_revision.py index 62e4a8286..12612284b 100644 --- a/partner_revision/models/res_partner_revision.py +++ b/partner_revision/models/res_partner_revision.py @@ -19,7 +19,10 @@ # # -from openerp import models, fields, api +from lxml import etree + +from openerp import models, fields, api, exceptions, _ +from openerp.osv.orm import setup_modifiers class ResPartnerRevision(models.Model): @@ -35,12 +38,18 @@ class ResPartnerRevision(models.Model): inverse_name='revision_id', string='Changes') date = fields.Datetime(default=fields.Datetime.now) + # TODO: add a revision state, done when all lines are done or + # canceled note = fields.Text() @api.multi def apply(self): self.mapped('change_ids').apply() + @api.multi + def cancel(self): + self.mapped('change_ids').cancel() + @api.multi def add_revision(self, record, values): """ Add a revision on a partner @@ -103,6 +112,18 @@ class ResPartnerRevisionChange(models.Model): field_id = fields.Many2one(comodel_name='ir.model.fields', string='Field', required=True) + field_type = fields.Selection(related='field_id.ttype', + string='Field Type', + readonly=True) + + current_value_display = fields.Char( + string='Current', + compute='_compute_value_display', + ) + new_value_display = fields.Char( + string='New', + compute='_compute_value_display', + ) current_value_char = fields.Char(string='Current') current_value_date = fields.Date(string='Current') @@ -138,18 +159,36 @@ class ResPartnerRevisionChange(models.Model): models = self.env['ir.model'].search([]) return [(model.model, model.name) for model in models] - _type_to_field = { - 'char': 'char', - 'date': 'date', - 'datetime': 'datetime', - 'float': 'float', - 'integer': 'integer', - 'text': 'text', - 'boolean': 'boolean', - 'many2one': 'reference', - 'selection': 'char', + _suffix_to_types = { + 'char': ('char', 'selection'), + 'date': ('date',), + 'datetime': ('datetime',), + 'float': ('float',), + 'integer': ('integer',), + 'text': ('text',), + 'boolean': ('boolean',), + 'reference': ('many2one',), } + _type_to_suffix = {ftype: suffix + for suffix, ftypes in _suffix_to_types.iteritems() + for ftype in ftypes} + + _current_value_fields = ['current_value_%s' % suffix + for suffix in _suffix_to_types] + _new_value_fields = ['new_value_%s' % suffix + for suffix in _suffix_to_types] + _value_fields = _current_value_fields + _new_value_fields + + @api.one + @api.depends(lambda self: self._value_fields) + def _compute_value_display(self): + for prefix in ('current', 'new'): + value = getattr(self, 'get_%s_value' % prefix)() + if self.field_id.ttype == 'many2one' and value: + value = value.display_name + setattr(self, '%s_value_display' % prefix, value) + @api.model def create(self, vals): vals = vals.copy() @@ -169,9 +208,8 @@ class ResPartnerRevisionChange(models.Model): @api.model def get_field_for_type(self, field, current_or_new): assert current_or_new in ('new', 'current') - field_type = self._type_to_field.get(field.ttype) + field_type = self._type_to_suffix.get(field.ttype) if not field_type: - # TODO: prevent to create unsupported types from the views raise NotImplementedError( 'field type %s is not supported' % field_type ) @@ -191,6 +229,7 @@ class ResPartnerRevisionChange(models.Model): @api.multi def apply(self): + # TODO: optimize with 1 write for all fields, group by revision for change in self: if change.state in ('cancel', 'done'): continue @@ -199,6 +238,15 @@ class ResPartnerRevisionChange(models.Model): change.get_new_value() ) partner.write({change.field_id.name: value_for_write}) + change.write({'state': 'done'}) + + @api.multi + def cancel(self): + if any(change.state == 'done' for change in self): + raise exceptions.Warning( + _('This change has already be applied.') + ) + self.write({'state': 'cancel'}) @api.model def _has_field_changed(self, record, field, value): @@ -261,3 +309,23 @@ class ResPartnerRevisionChange(models.Model): change['state'] = 'cancel' pop_value = True # change never applied return change, pop_value + + def fields_view_get(self, *args, **kwargs): + _super = super(ResPartnerRevisionChange, self) + result = _super.fields_view_get(*args, **kwargs) + if result['type'] != 'form': + return + doc = etree.XML(result['arch']) + for suffix, ftypes in self._suffix_to_types.iteritems(): + for prefix in ('current', 'new'): + field_name = '%s_value_%s' % (prefix, suffix) + field_nodes = doc.xpath("//field[@name='%s']" % field_name) + for node in field_nodes: + node.set( + 'attrs', + "{'invisible': " + "[('field_type', 'not in', %s)]}" % (ftypes,) + ) + setup_modifiers(node) + result['arch'] = etree.tostring(doc) + return result diff --git a/partner_revision/tests/test_revision_flow.py b/partner_revision/tests/test_revision_flow.py index 3fedcc678..b56c370fb 100644 --- a/partner_revision/tests/test_revision_flow.py +++ b/partner_revision/tests/test_revision_flow.py @@ -127,6 +127,7 @@ class TestRevisionFlow(RevisionMixin, common.TransactionCase): revision = self._create_revision(self.partner, changes) revision.change_ids.apply() self.assertEqual(self.partner.name, 'Y') + self.assertEqual(revision.change_ids.state, 'done') def test_apply_done_change(self): """ Done changes do not apply (already applied) """ diff --git a/partner_revision/views/menu.xml b/partner_revision/views/menu.xml new file mode 100644 index 000000000..a0137e792 --- /dev/null +++ b/partner_revision/views/menu.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/partner_revision/views/res_partner_revision_views.xml b/partner_revision/views/res_partner_revision_views.xml index 8dd8c880e..8d44348e0 100644 --- a/partner_revision/views/res_partner_revision_views.xml +++ b/partner_revision/views/res_partner_revision_views.xml @@ -22,20 +22,82 @@ - - - - + - + - - - + + + + + +