diff options
| author | Thibault Delavallée <tde@odoo.com> | 2018-09-21 11:23:31 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@odoo.com> | 2018-09-21 11:23:31 +0200 |
| commit | 68b2a8c5357e2ad2c867bce236c04f339b71e205 (patch) | |
| tree | 8150357526f91a58d4c1aba0f6bf086c71c7cd24 /addons | |
| parent | da03aa31386d50e7f8a5853daabf29ce75e7eaf8 (diff) | |
| parent | 22e33a7a3d57e1fac63585703ff4cd3a39d4b3e1 (diff) | |
[MERGE] crm: enforce lost / restore / won flow instead of active / inactive
Leads should not be active / inactive. Purpose of this merge is to use
lost / restore flow and hide all active-based filters and buttons. See
separate commits for more details.
This merge is linked to task ID 1880051 and closes PR #26977 .
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/crm/models/crm_lead.py | 18 | ||||
| -rw-r--r-- | addons/crm/report/crm_opportunity_report_views.xml | 3 | ||||
| -rw-r--r-- | addons/crm/views/crm_lead_views.xml | 37 | ||||
| -rw-r--r-- | addons/crm_project/views/crm_lead_views.xml | 2 | ||||
| -rw-r--r-- | addons/sale_crm/views/crm_lead_views.xml | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_column.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/kanban/kanban_view.js | 1 | ||||
| -rw-r--r-- | addons/web/static/src/xml/kanban.xml | 2 | ||||
| -rw-r--r-- | addons/web/static/tests/views/kanban_tests.js | 71 |
9 files changed, 107 insertions, 31 deletions
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index a68cc5ae48d..b6829a25708 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -66,7 +66,7 @@ class Lead(models.Model): name = fields.Char('Opportunity', required=True, index=True) partner_id = fields.Many2one('res.partner', string='Customer', track_visibility='onchange', track_sequence=1, index=True, help="Linked partner (optional). Usually created when converting the lead.") - active = fields.Boolean('Active', default=True) + active = fields.Boolean('Active', default=True, track_visibility=True) date_action_last = fields.Datetime('Last Action', readonly=True) email_from = fields.Char('Email', help="Email address of the contact", track_visibility='onchange', track_sequence=4, index=True) website = fields.Char('Website', index=True, help="Website of the contact") @@ -355,14 +355,6 @@ class Lead(models.Model): return self.write({'probability': 0, 'active': False}) @api.multi - def action_set_active(self): - return self.write({'active': True}) - - @api.multi - def action_set_unactive(self): - return self.write({'active': False}) - - @api.multi def action_set_won(self): """ Won semantic: probability = 100 (active untouched) """ for lead in self: @@ -459,6 +451,14 @@ class Lead(models.Model): 'context': {'default_type': 'opportunity'} } + def toggle_active(self): + """ When re-activating leads and opportunities set their probability + to the default stage one. """ + res = super(Lead, self).toggle_active() + for lead in self.filtered(lambda lead: lead.active and lead.stage_id.probability): + lead.probability = lead.stage_id.probability + return res + # ---------------------------------------- # Business Methods # ---------------------------------------- diff --git a/addons/crm/report/crm_opportunity_report_views.xml b/addons/crm/report/crm_opportunity_report_views.xml index 07329f850bb..d263b5bc8b0 100644 --- a/addons/crm/report/crm_opportunity_report_views.xml +++ b/addons/crm/report/crm_opportunity_report_views.xml @@ -75,9 +75,6 @@ <filter string="Creation Date" name="filter_create_date" date="create_date"/> <filter string="Expected Closing" name="filter_date_deadline" date="date_deadline"/> <filter string="Date Closed" name="date_closed_filter" date="date_closed"/> - <separator/> - <filter string="Current" name="current" domain="[('active', '=', True)]"/> - <filter string="Archived" name="archived" domain="[('active', '=', False)]"/> <group expand="0" string="Extended Filters"> <field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/> <field name="stage_id" widget="selection" domain="['|', ('team_id', '=', False), ('team_id', '=', 'team_id')]"/> diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml index 5813b5a7378..f4a5ba6ca19 100644 --- a/addons/crm/views/crm_lead_views.xml +++ b/addons/crm/views/crm_lead_views.xml @@ -45,14 +45,21 @@ <header> <button name="%(crm.action_crm_lead2opportunity_partner)d" string="Convert to Opportunity" type="action" help="Convert to Opportunity" class="oe_highlight" attrs="{'invisible': [('type', '=', 'opportunity')]}"/> + <button name="toggle_active" + string="Restore" + type="object" + attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}"/> + <button name="action_set_lost" + string="Mark as Lost" + type="object" + attrs="{'invisible': ['&', ('probability', '=', 0), ('active', '=', False)]}"/> </header> <sheet> + <field name="active" invisible="1"/> <div class="oe_button_box" name="button_box"> - <button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive"> - <field name="active" widget="boolean_button" options='{"terminology": "archive"}'/> - </button> </div> - <div class="badge badge-success float-right" attrs="{'invisible': [('probability', '<', 100)]}">Won</div> + <div class="badge-pill badge-danger float-right" attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}">Lost</div> + <div class="badge-pill badge-success float-right" attrs="{'invisible': [('probability', '<', 100)]}">Won</div> <div class="oe_title"> <label for="name" class="oe_edit_only" string="Lead"/> <h1><field name="name" placeholder="Describe the lead..."/></h1> @@ -169,7 +176,7 @@ <field name="model">crm.lead</field> <field name="priority" eval="100"/> <field name="arch" type="xml"> - <kanban class="o_kanban_mobile"> + <kanban class="o_kanban_mobile" archivable="false"> <field name="name"/> <field name="contact_name"/> <field name="priority"/> @@ -306,7 +313,8 @@ <field name="model">crm.lead</field> <field name="priority" eval="1"/> <field name="arch" type="xml"> - <kanban default_group_by="stage_id" class="o_kanban_small_column o_opportunity_kanban" on_create="quick_create" quick_create_view="crm.quick_create_opportunity_form"> + <kanban default_group_by="stage_id" class="o_kanban_small_column o_opportunity_kanban" on_create="quick_create" quick_create_view="crm.quick_create_opportunity_form" + archivable="false"> <field name="stage_id" options='{"group_by_tooltip": {"requirements": "Description", "legend_priority": "Use of stars"}}'/> <field name="color"/> <field name="priority"/> @@ -335,8 +343,6 @@ <div class="dropdown-menu" role="menu"> <t t-if="widget.editable"><a role="menuitem" type="edit" class="dropdown-item">Edit</a></t> <t t-if="widget.deletable"><a role="menuitem" type="delete" class="dropdown-item">Delete</a></t> - <a t-if="! record.active.value" role="menuitem" name="action_set_active" type="object" class="dropdown-item">Restore</a> - <a t-if="record.active.value" role="menuitem" name="action_set_unactive" type="object" class="dropdown-item">Archive</a> <ul class="oe_kanban_colorpicker" data-field="color"/> </div> </div> @@ -400,7 +406,7 @@ <filter string="Won" name="won" domain="[('probability', '=', 100)]"/> <filter string="Lost" name="lost" - domain="[('probability', '=', 0), ('active', '=', False)]"/> + domain="['&', ('probability', '=', 0), ('active', '=', False)]"/> <group expand="0" string="Group By"> <filter string="Salesperson" name="salesperson" context="{'group_by':'user_id'}"/> <filter string="Sales Channel" name="saleschannel" context="{'group_by':'team_id'}"/> @@ -439,12 +445,17 @@ type="action" class="oe_highlight" context="{'default_lead_id': active_id}" attrs="{'invisible': [('active', '=', False),('probability', '<', 100)]}"/> + <button name="toggle_active" + string="Restore" + type="object" + attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}"/> <field name="stage_id" widget="statusbar" options="{'clickable': '1', 'fold_field': 'fold'}" domain="['|', ('team_id', '=', team_id), ('team_id', '=', False)]" attrs="{'invisible': [('active', '=', False)]}"/> </header> <sheet> + <field name="active" invisible="1"/> <div class="oe_button_box" name="button_box"> <button class="oe_stat_button" type="object" context="{'partner_id': partner_id}" @@ -455,13 +466,9 @@ <span class="o_stat_text" attrs="{'invisible': [('meeting_count', '>', 1)]}"> Meeting</span> </div> </button> - <button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive" - attrs="{'invisible': [('active', '=', True), ('probability', '<', 100)]}"> - <field name="active" widget="boolean_button" options='{"terminology": "archive"}'/> - </button> </div> - <div class="badge badge-danger float-right" attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}">Lost</div> - <div class="badge badge-success float-right" attrs="{'invisible': [('probability', '<', 100)]}">Won</div> + <div class="badge-pill badge-danger float-right" attrs="{'invisible': ['|', ('probability', '>', 0), ('active', '=', True)]}">Lost</div> + <div class="badge-pill badge-success float-right" attrs="{'invisible': [('probability', '<', 100)]}">Won</div> <div class="oe_title"> <label for="name" class="oe_edit_only"/> <h1><field name="name" placeholder="e.g. Product Pricing"/></h1> diff --git a/addons/crm_project/views/crm_lead_views.xml b/addons/crm_project/views/crm_lead_views.xml index 874c9afb997..530f5160f74 100644 --- a/addons/crm_project/views/crm_lead_views.xml +++ b/addons/crm_project/views/crm_lead_views.xml @@ -7,7 +7,7 @@ <field name="model">crm.lead</field> <field name="inherit_id" ref="crm.crm_case_form_view_leads" /> <field name="arch" type="xml"> - <xpath expr="//button[@name='toggle_active']" position="before"> + <xpath expr="//div[@name='button_box']" position="inside"> <button class="oe_stat_button" type="action" name="%(crm_lead_convert2task_action)d" icon="fa-bug" help="Convert to Task"> <div class="o_field_widget o_stat_info"> <span class="o_stat_text">Convert To</span> diff --git a/addons/sale_crm/views/crm_lead_views.xml b/addons/sale_crm/views/crm_lead_views.xml index 5efb023bfd3..8cf8fd91386 100644 --- a/addons/sale_crm/views/crm_lead_views.xml +++ b/addons/sale_crm/views/crm_lead_views.xml @@ -8,6 +8,7 @@ <field name="arch" type="xml"> <xpath expr="//button[@name='action_set_won_rainbowman']" position="before"> <button string="New Quotation" name="%(sale_action_quotations_new)d" type="action" class="oe_highlight" + attrs="{'invisible': ['&', ('probability', '=', 0), ('active', '=', False)]}" context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id, 'default_team_id': team_id, @@ -16,7 +17,7 @@ 'default_origin': name, 'default_source_id': source_id}"/> </xpath> - <button name="toggle_active" position="before"> + <button name="action_schedule_meeting" position="after"> <button class="oe_stat_button" type="action" name="%(sale_action_quotations)d" icon="fa-pencil-square-o" context="{'default_partner_id': partner_id, 'search_default_draft': 1}"> diff --git a/addons/web/static/src/js/views/kanban/kanban_column.js b/addons/web/static/src/js/views/kanban/kanban_column.js index 6fea1c36d32..ef75caca8c0 100644 --- a/addons/web/static/src/js/views/kanban/kanban_column.js +++ b/addons/web/static/src/js/views/kanban/kanban_column.js @@ -53,6 +53,7 @@ var KanbanColumn = Widget.extend({ this.grouped_by_m2o = options.grouped_by_m2o; this.editable = options.editable; this.deletable = options.deletable; + this.archivable = options.archivable; this.draggable = options.draggable; this.KanbanRecord = options.KanbanRecord || KanbanRecord; // the KanbanRecord class to use this.records_editable = options.records_editable; diff --git a/addons/web/static/src/js/views/kanban/kanban_view.js b/addons/web/static/src/js/views/kanban/kanban_view.js index 99be6175da3..791e3664668 100644 --- a/addons/web/static/src/js/views/kanban/kanban_view.js +++ b/addons/web/static/src/js/views/kanban/kanban_view.js @@ -61,6 +61,7 @@ var KanbanView = BasicView.extend({ this.rendererParams.column_options = { editable: activeActions.group_edit, deletable: activeActions.group_delete, + archivable: this.arch.attrs.archivable ? JSON.parse(this.arch.attrs.archivable) : true, group_creatable: activeActions.group_create && !config.device.isMobile, quick_create: params.isQuickCreateEnabled || this._isQuickCreateEnabled(), quickCreateView: this.arch.attrs.quick_create_view || null, diff --git a/addons/web/static/src/xml/kanban.xml b/addons/web/static/src/xml/kanban.xml index adc213999f2..b91b8844752 100644 --- a/addons/web/static/src/xml/kanban.xml +++ b/addons/web/static/src/xml/kanban.xml @@ -23,7 +23,7 @@ <a t-if="widget.editable and widget.id" role="menuitem" class="dropdown-item o_column_edit" href="#">Edit Stage</a> <a t-if="widget.deletable and widget.id" role="menuitem" class="dropdown-item o_column_delete" href="#">Delete</a> </t> - <t t-if="widget.has_active_field"> + <t t-if="widget.has_active_field and widget.archivable"> <a href="#" class="dropdown-item o_column_archive_records">Archive All</a> <a href="#" class="dropdown-item o_column_unarchive_records">Unarchive All</a> </t> diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index c967b42a332..1fbe683187d 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -148,7 +148,7 @@ QUnit.module('Views', { kanban.destroy(); }); - QUnit.test('basic grouped rendering with active field', function (assert) { + QUnit.test('basic grouped rendering with active field (archivable by default)', function (assert) { assert.expect(9); // add active field on partner model and make all records active @@ -193,6 +193,75 @@ QUnit.module('Views', { kanban.destroy(); }); + QUnit.test('basic grouped rendering with active field and archive enabled (archivable true)', function (assert) { + assert.expect(7); + + // add active field on partner model and make all records active + this.data.partner.fields.active = {string: 'Active', type: 'char', default: true}; + + var envIDs = [1, 2, 3, 4]; // the ids that should be in the environment during this test + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '<kanban class="o_kanban_test" archivable="true">' + + '<field name="active"/>' + + '<field name="bar"/>' + + '<templates><t t-name="kanban-box">' + + '<div><field name="foo"/></div>' + + '</t></templates></kanban>', + groupBy: ['bar'], + }); + + // check archive/restore all actions in kanban header's config dropdown + assert.ok(kanban.$('.o_kanban_header:first .o_kanban_config .o_column_archive_records').length, "should be able to archive all the records"); + assert.ok(kanban.$('.o_kanban_header:first .o_kanban_config .o_column_unarchive_records').length, "should be able to restore all the records"); + + // archive the records of the first column + assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 3, + "last column should contain 3 records"); + envIDs = [4]; + kanban.$('.o_kanban_group:last .o_column_archive_records').click(); // Click on 'Archive All' + assert.ok($('.modal').length, 'a confirm modal should be displayed'); + $('.modal-footer .btn-secondary').click(); // Click on 'Cancel' + assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 3, "still last column should contain 3 records"); + kanban.$('.o_kanban_group:last .o_column_archive_records').click(); + assert.ok($('.modal').length, 'a confirm modal should be displayed'); + $('.modal-footer .btn-primary').click(); // Click on 'Ok' + assert.strictEqual(kanban.$('.o_kanban_group:last .o_kanban_record').length, 0, "last column should not contain any records"); + kanban.destroy(); + }); + + QUnit.test('basic grouped rendering with active field and hidden archive buttons (archivable false)', function (assert) { + assert.expect(2); + + // add active field on partner model and make all records active + this.data.partner.fields.active = {string: 'Active', type: 'char', default: true}; + + var envIDs = [1, 2, 3, 4]; // the ids that should be in the environment during this test + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '<kanban class="o_kanban_test" archivable="false">' + + '<field name="active"/>' + + '<field name="bar"/>' + + '<templates><t t-name="kanban-box">' + + '<div><field name="foo"/></div>' + + '</t></templates></kanban>', + groupBy: ['bar'], + }); + + // check archive/restore all actions in kanban header's config dropdown + assert.strictEqual( + kanban.$('.o_kanban_header:first .o_kanban_config .o_column_archive_records').length, 0, + "should not be able to archive all the records"); + assert.strictEqual( + kanban.$('.o_kanban_header:first .o_kanban_config .o_column_unarchive_records').length, 0, + "should not be able to restore all the records"); + kanban.destroy(); + }); + QUnit.test('pager should be hidden in grouped mode', function (assert) { assert.expect(1); |
