diff options
| author | Antoine Prieels (ANP) <anp@odoo.com> | 2018-11-21 11:53:01 +0000 |
|---|---|---|
| committer | Antoine Prieels (ANP) <anp@odoo.com> | 2018-11-28 10:32:20 +0000 |
| commit | 8b930c648d15b8b873d4ee4a8042f95825d28896 (patch) | |
| tree | fa5be1336f53e754cb8f3818bffe645b420366e8 | |
| parent | fea93a9dd6154961f4dcdb652bc580ec0d6a83ef (diff) | |
[IMP] partner_autocomplete: Notify when user out of credits
closes odoo/odoo#29309
7 files changed, 206 insertions, 75 deletions
diff --git a/addons/partner_autocomplete/i18n/partner_autocomplete.pot b/addons/partner_autocomplete/i18n/partner_autocomplete.pot index 8e5c9128d12..3e4b56c2e00 100644 --- a/addons/partner_autocomplete/i18n/partner_autocomplete.pot +++ b/addons/partner_autocomplete/i18n/partner_autocomplete.pot @@ -4,10 +4,10 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server saas~11.5\n" +"Project-Id-Version: Odoo Server 13.0alpha1+e\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-02 10:06+0000\n" -"PO-Revision-Date: 2018-10-02 10:06+0000\n" +"POT-Creation-Date: 2018-11-21 11:55+0000\n" +"PO-Revision-Date: 2018-11-21 11:55+0000\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -102,6 +102,13 @@ msgid "Additional info" msgstr "" #. module: partner_autocomplete +#. openerp-web +#: code:addons/partner_autocomplete/static/src/xml/partner_autocomplete.xml:18 +#, python-format +msgid "Buy more credits" +msgstr "" + +#. module: partner_autocomplete #: model_terms:ir.ui.view,arch_db:partner_autocomplete.res_config_settings_view_form msgid "Close" msgstr "" @@ -173,6 +180,13 @@ msgid "Last Updated on" msgstr "" #. module: partner_autocomplete +#. openerp-web +#: code:addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js:357 +#, python-format +msgid "Not enough credits for Partner Autocomplete" +msgstr "" + +#. module: partner_autocomplete #: model:ir.model.fields,field_description:partner_autocomplete.field_res_partner_autocomplete_sync__partner_id msgid "Partner" msgstr "" diff --git a/addons/partner_autocomplete/models/res_partner.py b/addons/partner_autocomplete/models/res_partner.py index c7d5be75fc2..9d357fec6d8 100644 --- a/addons/partner_autocomplete/models/res_partner.py +++ b/addons/partner_autocomplete/models/res_partner.py @@ -123,9 +123,17 @@ class ResPartner(models.Model): 'vat': vat, }) if response and response.get('company_data'): - return self._format_data_company(response.get('company_data')) + result = self._format_data_company(response.get('company_data')) else: - return {} + result = {} + + if error: + result.update({ + 'error': True, + 'error_message': error + }) + + return result @api.model def read_by_vat(self, vat): diff --git a/addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js b/addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js index a5f4188615b..c36d2f1a29c 100644 --- a/addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js +++ b/addons/partner_autocomplete/static/src/js/partner_autocomplete_core.js @@ -1,14 +1,20 @@ -odoo.define('partner.autocomplete.core', function (require) { +odoo.define('partner.autocomplete.Mixin', function (require) { 'use strict'; -var rpc = require('web.rpc'); var concurrency = require('web.concurrency'); -return { +var core = require('web.core'); +var Qweb = core.qweb; +var _t = core._t; + +/** + * This mixin only works with classes having EventDispatcherMixin in 'web.mixins' + */ +var PartnerAutocompleteMixin = { _dropPreviousOdoo: new concurrency.DropPrevious(), _dropPreviousClearbit: new concurrency.DropPrevious(), _timeout : 1000, // Timeout for Clearbit autocomplete in ms - + //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- @@ -20,7 +26,7 @@ return { * @returns {Deferred} * @private */ - autocomplete: function (value) { + _autocomplete: function (value) { value = value.trim(); var def = $.Deferred(), isVAT = this._isVAT(value), @@ -62,11 +68,14 @@ return { * Get enrichment data * * @param {Object} company + * @param {string} company.website + * @param {string} company.partner_gid + * @param {string} company.vat * @returns {Deferred} * @private */ - enrichCompany: function (company) { - return rpc.query({ + _enrichCompany: function (company) { + return this._rpc({ model: 'res.partner', method: 'enrich_company', args: [company.website, company.partner_gid, company.vat], @@ -80,7 +89,7 @@ return { * @returns {Deferred} * @private */ - getCompanyLogo: function (url) { + _getCompanyLogo: function (url) { return this._getBase64Image(url).then(function (base64Image) { // base64Image equals "data:" if image not available on given url return base64Image ? base64Image.replace(/^data:image[^;]*;base64,?/, '') : false; @@ -93,7 +102,9 @@ return { * @param {Object} company * @returns {Deferred} */ - getCreateData: function (company) { + _getCreateData: function (company) { + var self = this; + var removeUselessFields = function (company) { var fields = 'label,description,domain,logo,legal_name'.split(','); fields.forEach(function (field) { @@ -109,10 +120,10 @@ return { var def = $.Deferred(); // Fetch additional company info via Autocomplete Enrichment API - var enrichPromise = this.enrichCompany(company); + var enrichPromise = this._enrichCompany(company); // Get logo - var logoPromise = company.logo ? this.getCompanyLogo(company.logo) : false; + var logoPromise = company.logo ? this._getCompanyLogo(company.logo) : false; this._whenAll([enrichPromise, logoPromise]).always(function (company_data, logo_data){ if (Array.isArray(company_data)) company_data = company_data[0]; @@ -121,6 +132,11 @@ return { if (Array.isArray(logo_data)) logo_data = logo_data[0]; else logo_data = ''; + if (company_data.error && company_data.error_message === 'Insufficient Credit'){ + self._notifyNoCredits(); + company_data = company; + } + if (_.isEmpty(company_data)) company_data = company; // Delete attribute to avoid "Field_changed" errors @@ -142,7 +158,7 @@ return { * * @returns {boolean} */ - isOnline: function () { + _isOnline: function () { return navigator && navigator.onLine; }, @@ -154,7 +170,7 @@ return { * @returns {boolean} * @private */ - validateSearchTerm: function (search_val, onlyVAT) { + _validateSearchTerm: function (search_val, onlyVAT) { if (onlyVAT) return this._isVAT(search_val); else return search_val && search_val.length > 2; }, @@ -226,7 +242,7 @@ return { _getOdooSuggestions: function (value, isVAT) { var method = isVAT ? 'read_by_vat' : 'autocomplete'; - var def = rpc.query({ + var def = this._rpc({ model: 'res.partner', method: method, args: [value], @@ -334,5 +350,27 @@ return { return deferred.promise(); }, + + /** + * @private + * @returns {$.Promise} + */ + _notifyNoCredits: function () { + var self = this; + this._rpc({ + model: 'iap.account', + method: 'get_credits_url', + args: ['partner_autocomplete'], + }).then(function (url) { + var title = _t('Not enough credits for Partner Autocomplete'); + var content = Qweb.render('partner_autocomplete.insufficient_credit_notification', { + credits_url: url + }); + self.do_notify(title, content, false, 'o_partner_autocomplete_no_credits_notify'); + }); + }, }; + +return PartnerAutocompleteMixin; + }); diff --git a/addons/partner_autocomplete/static/src/js/partner_autocomplete_fieldchar.js b/addons/partner_autocomplete/static/src/js/partner_autocomplete_fieldchar.js index b1843ec8de1..3a6374de5fc 100644 --- a/addons/partner_autocomplete/static/src/js/partner_autocomplete_fieldchar.js +++ b/addons/partner_autocomplete/static/src/js/partner_autocomplete_fieldchar.js @@ -4,7 +4,7 @@ odoo.define('partner.autocomplete.fieldchar', function (require) { var basic_fields = require('web.basic_fields'); var core = require('web.core'); var field_registry = require('web.field_registry'); -var Autocomplete = require('partner.autocomplete.core'); +var AutocompleteMixin = require('partner.autocomplete.Mixin'); var QWeb = core.qweb; @@ -15,7 +15,7 @@ var FieldChar = basic_fields.FieldChar; * name on a res.partner view (indeed, it is designed to change the "name", * "website" and "image" fields of records of this model). */ -var FieldAutocomplete = FieldChar.extend({ +var FieldAutocomplete = FieldChar.extend(AutocompleteMixin, { className: 'o_field_partner_autocomplete', debounceSuggestions: 400, resetOnAnyFieldChange: true, @@ -112,7 +112,7 @@ var FieldAutocomplete = FieldChar.extend({ */ _selectCompany: function (company) { var self = this; - Autocomplete.getCreateData(company).then(function (data) { + this._getCreateData(company).then(function (data) { if (data.logo) { var logoField = self.model === 'res.partner' ? 'image' : 'logo'; data.company[logoField] = data.logo; @@ -190,8 +190,8 @@ var FieldAutocomplete = FieldChar.extend({ */ _suggestCompanies: function (value) { var self = this; - if (Autocomplete.validateSearchTerm(value, this.onlyVAT) && Autocomplete.isOnline()) { - return Autocomplete.autocomplete(value).then(function (suggestions) { + if (this._validateSearchTerm(value, this.onlyVAT) && this._isOnline()) { + return this._autocomplete(value).then(function (suggestions) { if (suggestions && suggestions.length) { self.suggestions = suggestions; self._showDropdown(); diff --git a/addons/partner_autocomplete/static/src/js/partner_autocomplete_many2one.js b/addons/partner_autocomplete/static/src/js/partner_autocomplete_many2one.js index 83f2ce9ce0b..5a3334e8094 100644 --- a/addons/partner_autocomplete/static/src/js/partner_autocomplete_many2one.js +++ b/addons/partner_autocomplete/static/src/js/partner_autocomplete_many2one.js @@ -3,12 +3,12 @@ odoo.define('partner.autocomplete.many2one', function (require) { var FieldMany2One = require('web.relational_fields').FieldMany2One; var core = require('web.core'); -var Autocomplete = require('partner.autocomplete.core'); +var AutocompleteMixin = require('partner.autocomplete.Mixin'); var field_registry = require('web.field_registry'); var _t = core._t; -var PartnerField = FieldMany2One.extend({ +var PartnerField = FieldMany2One.extend(AutocompleteMixin, { jsLibs: [ '/partner_autocomplete/static/lib/jsvat.js' ], @@ -21,7 +21,7 @@ var PartnerField = FieldMany2One.extend({ this._addAutocompleteSource(this._searchSuggestions, { placeholder: _t('Searching Autocomplete...'), order: 20, - validation: Autocomplete.validateSearchTerm, + validation: this._validateSearchTerm, }); this.additionalContext['show_vat'] = true; @@ -42,7 +42,7 @@ var PartnerField = FieldMany2One.extend({ var self = this; self.$('input').val(''); - return Autocomplete.getCreateData(company).then(function (data){ + return self._getCreateData(company).then(function (data){ var context = { 'default_is_company': true }; @@ -120,10 +120,10 @@ var PartnerField = FieldMany2One.extend({ _searchSuggestions: function (search_val) { var def = $.Deferred(); - if (Autocomplete.isOnline()) { + if (this._isOnline()) { var self = this; - Autocomplete.autocomplete(search_val).then(function (suggestions) { + self._autocomplete(search_val).then(function (suggestions) { var choices = []; if (suggestions && suggestions.length) { _.each(suggestions, function (suggestion) { diff --git a/addons/partner_autocomplete/static/src/xml/partner_autocomplete.xml b/addons/partner_autocomplete/static/src/xml/partner_autocomplete.xml index c85969882ad..6020e9537cc 100644 --- a/addons/partner_autocomplete/static/src/xml/partner_autocomplete.xml +++ b/addons/partner_autocomplete/static/src/xml/partner_autocomplete.xml @@ -13,4 +13,11 @@ </a> </t> </div> + + <!-- + @param {string} credits_url + --> + <div t-name="partner_autocomplete.insufficient_credit_notification" class=""> + <a class="btn btn-link" t-att-href="credits_url"><i class="fa fa-arrow-right"/> Buy more credits</a> + </div> </templates> diff --git a/addons/partner_autocomplete/static/tests/partner_autocomplete_tests.js b/addons/partner_autocomplete/static/tests/partner_autocomplete_tests.js index 52dcde5370f..bae95b395a5 100644 --- a/addons/partner_autocomplete/static/tests/partner_autocomplete_tests.js +++ b/addons/partner_autocomplete/static/tests/partner_autocomplete_tests.js @@ -4,9 +4,9 @@ odoo.define('partner_autocomplete.tests', function (require) { var FormView = require('web.FormView'); var concurrency = require('web.concurrency'); var testUtils = require("web.test_utils"); - var AutocompleteCore = require('partner.autocomplete.core'); var AutocompleteField = require('partner.autocomplete.fieldchar'); var PartnerField = require('partner.autocomplete.many2one'); + var NotificationService = require('web.NotificationService'); var createView = testUtils.createAsyncView; @@ -36,13 +36,67 @@ odoo.define('partner_autocomplete.tests', function (require) { }); } + var suggestions = [{ + name: "Odoo", + website: "odoo.com", + domain: "odoo.com", + logo: "odoo.com/logo.png", + vat: "BE0477472701" + }]; + + var enrichData = {}; + + var createData = {}; + QUnit.module('partner_autocomplete', { before: function () { - var suggestions = [ - {name: "Odoo", website: "odoo.com", domain: "odoo.com", logo: "odoo.com/logo.png", vat: "BE0477472701"} - ]; + var fieldsToPatch = [PartnerField, AutocompleteField]; + _.each(fieldsToPatch, function (fieldToPatch) { + testUtils.mock.patch(fieldToPatch, { + _getBase64Image: function (url) { + return $.when(url === "odoo.com/logo.png" ? "odoobase64" : ""); + }, + _isOnline: function () { + return true; + }, + _getCreateData: function (company) { + var def = this._super.apply(this, arguments); + def.then(function (data) { + createData = data.company; + }); + return def; + }, + _enrichCompany: function (company) { + return $.when(enrichData); + }, + _getOdooSuggestions: function (value, isVAT) { + var results = _.filter(suggestions, function (suggestion) { + value = value ? value.toLowerCase() : ''; + if (isVAT) return (suggestion.vat.toLowerCase().indexOf(value) >= 0); + else return (suggestion.name.toLowerCase().indexOf(value) >= 0); + }); + return $.when(results); + }, + _getClearbitSuggestions: function (value) { + return this._getOdooSuggestions(value); + }, + do_notify: function (title, message, sticky, className) { + return this.call('notification', 'notify', { + title: title, + message: message, + sticky: true, + className: 'o_partner_autocomplete_test_notify' + }); + }, + }); + }); - var enrich_data = { + testUtils.mock.patch(AutocompleteField, { + debounceSuggestions: 0, + }); + }, + beforeEach: function () { + enrichData = { country_id: 20, state_id: false, partner_gid: 1, @@ -56,42 +110,6 @@ odoo.define('partner_autocomplete.tests', function (require) { vat: "BE0477472701", }; - testUtils.mock.patch(AutocompleteCore, { - _getBase64Image: function (url) { - return $.when(url === "odoo.com/logo.png" ? "odoobase64" : ""); - }, - isOnline: function () { - return true; - }, - getCreateData: function (company) { - var self = this; - var def = this._super.apply(this, arguments); - def.then(function (data) { - self._createData = data.company; - }); - return def; - }, - enrichCompany: function (company) { - return $.when(enrich_data); - }, - _getOdooSuggestions(value, isVAT) { - var results = _.filter(suggestions, function (suggestion) { - value = value ? value.toLowerCase() : ''; - if (isVAT) return (suggestion.vat.toLowerCase().indexOf(value) >= 0); - else return (suggestion.name.toLowerCase().indexOf(value) >= 0); - }); - return $.when(results); - }, - _getClearbitSuggestions(value) { - return this._getOdooSuggestions(value); - }, - }); - - testUtils.mock.patch(AutocompleteField, { - debounceSuggestions: 0, - }); - }, - beforeEach: function () { this.data = { 'res.partner': { fields: { @@ -128,7 +146,7 @@ odoo.define('partner_autocomplete.tests', function (require) { }, after: function () { testUtils.mock.unpatch(AutocompleteField); - testUtils.mock.unpatch(AutocompleteCore); + testUtils.mock.unpatch(PartnerField); }, }); @@ -223,7 +241,7 @@ odoo.define('partner_autocomplete.tests', function (require) { assert.strictEqual($input.val(), "Odoo", "Input value should have been updated to \"Odoo\""); assert.strictEqual(form.$("input.o_field_widget").val(), "odoo.com", "website value should have been updated to \"odoo.com\""); - _compareResultFields(assert, form, fields, AutocompleteCore._createData); + _compareResultFields(assert, form, fields, createData); // Try suggestion with bullshit query testUtils.fields.editInput($input, "ZZZZZZZZZZZZZZZZZZZZZZ") @@ -309,7 +327,7 @@ odoo.define('partner_autocomplete.tests', function (require) { $input = form.$(".o_field_partner_autocomplete > input"); assert.strictEqual($input.val(), "Odoo", "Input value should have been updated to \"Odoo\""); - _compareResultFields(assert, form, fields, AutocompleteCore._createData); + _compareResultFields(assert, form, fields, createData); // Set complete VAT and assert changes // Second suggestion (only vat + clearbit result) @@ -323,7 +341,7 @@ odoo.define('partner_autocomplete.tests', function (require) { $input = form.$(".o_field_partner_autocomplete > input"); assert.strictEqual($input.val(), "Odoo", "Input value should have been updated to \"Odoo\""); - _compareResultFields(assert, form, fields, AutocompleteCore._createData); + _compareResultFields(assert, form, fields, createData); // Test if dropdown closes on focusout $input.trigger("focusout"); @@ -371,4 +389,50 @@ odoo.define('partner_autocomplete.tests', function (require) { }); }); }); + + QUnit.test("Partner autocomplete : Notify not enough credits", function (assert) { + assert.expect(1); + var done = assert.async(); + + enrichData = { + error: true, + error_message: 'Insufficient Credit', + }; + + createView({ + View: FormView, + model: 'res.partner', + data: this.data, + arch: + '<form>' + + '<field name="company_type"/>' + + '<field name="name" widget="field_partner_autocomplete"/>' + + '</form>', + services: { + notification: NotificationService, + }, + mockRPC: function (route, args) { + if (args.method === "get_credits_url"){ + return $.when('credits_url'); + } + return this._super.apply(this, arguments); + }, + }).then(function (form){ + // Set company type to Company + var $company_type = form.$("select[name='company_type']"); + testUtils.fields.editSelect($company_type, '"company"'); + + var $input = form.$(".o_field_partner_autocomplete > input:visible"); + testUtils.fields.editInput($input, "BE0477472701"); + + var $dropdown = form.$(".o_field_partner_autocomplete .dropdown-menu:visible"); + testUtils.dom.click($dropdown.find("a").first()); + + var $notify = $(".o_partner_autocomplete_test_notify"); + assert.isVisible($notify, "there should be an 'Insufficient Credit' notification"); + + form.destroy(); + done(); + }); + }); }); |
