diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/sale_product_matrix/static | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/sale_product_matrix/static')
3 files changed, 346 insertions, 0 deletions
diff --git a/addons/sale_product_matrix/static/src/js/product_matrix_configurator.js b/addons/sale_product_matrix/static/src/js/product_matrix_configurator.js new file mode 100644 index 00000000..7ea00210 --- /dev/null +++ b/addons/sale_product_matrix/static/src/js/product_matrix_configurator.js @@ -0,0 +1,97 @@ +odoo.define('sale_product_matrix.product_configurator', function (require) { +var ProductConfiguratorWidget = require('sale_product_configurator.product_configurator'); + +/** + * Extension of the ProductConfiguratorWidget to support product configuration + * as variant batches to add to the SO.. + * It opens when a configurable product_template is set + * (multiple variants, or custom attributes) + * and its configuration mode is matrix. + * + */ +ProductConfiguratorWidget.include({ + + /** + * @override + */ + _openConfigurator: function (result, productTemplateId, dataPointId) { + var self = this; + var mode = result.mode; + this._super.apply(this, arguments).then(function (configuratorOpened) { + if (!configuratorOpened && mode === 'matrix') { + self._openGridConfigurator(productTemplateId, dataPointId); + return Promise.resolve(true); + } + return Promise.resolve(configuratorOpened); + }); + }, + + _openGridConfigurator: function (productTemplateId, dataPointId, edit) { + var attribs = edit ? this._getPTAVS() : []; + this.trigger_up('open_matrix', { + product_template_id: productTemplateId, + model: 'sale.order', + dataPointId: dataPointId, + edit: edit, + editedCellAttributes: attribs, + }); + }, + + _onEditProductConfiguration: function () { + if (!this.recordData.is_configurable_product) { + // if line should be edited by another configurator + // or simply inline. + this._super.apply(this, arguments); + return; + } + var self = this; + var productTemplateId = this.recordData.product_template_id.data.id; + this._rpc({ + model: 'product.template', + method: 'read', + args: [productTemplateId, ['product_add_mode']], + }).then(function (result) { + if (result && result[0].product_add_mode === 'matrix') { + self._openGridConfigurator(productTemplateId, self.dataPointID, true); + } else { + // Call super only if product_add_mode different than matrix + // to avoid product configurator opening (which is the default case). + self._openProductConfigurator({ + configuratorMode: 'edit', + default_product_template_id: self.recordData.product_template_id.data.id, + default_pricelist_id: self._getPricelistId(), + default_product_template_attribute_value_ids: self._convertFromMany2Many( + self.recordData.product_template_attribute_value_ids + ), + default_product_no_variant_attribute_value_ids: self._convertFromMany2Many( + self.recordData.product_no_variant_attribute_value_ids + ), + default_product_custom_attribute_value_ids: self._convertFromOne2Many( + self.recordData.product_custom_attribute_value_ids + ), + default_quantity: self.recordData.product_uom_qty + }, + self.dataPointID + ); + } + }); + }, + + /** + * Returns the list of attribute ids (product.template.attribute.value) + * from the current SOLine. + */ + _getPTAVS: function () { + var PTAVSIDS = []; + _.each(this.recordData.product_no_variant_attribute_value_ids.res_ids, function (id) { + PTAVSIDS.push(id); + }); + _.each(this.recordData.product_template_attribute_value_ids.res_ids, function (id) { + PTAVSIDS.push(id); + }); + return PTAVSIDS.sort(function (a, b) {return a - b;}); + } + +}); + +}); diff --git a/addons/sale_product_matrix/static/tests/section_and_note_widget_tests.js b/addons/sale_product_matrix/static/tests/section_and_note_widget_tests.js new file mode 100644 index 00000000..939fa2e8 --- /dev/null +++ b/addons/sale_product_matrix/static/tests/section_and_note_widget_tests.js @@ -0,0 +1,106 @@ +odoo.define('sale_product_matrix.section_and_note_widget_tests', function (require) { +"use strict"; + +var FormView = require('web.FormView'); +var testUtils = require('web.test_utils'); +var createView = testUtils.createView; + +QUnit.module('section_and_note: sale_product_matrix', { + beforeEach: function () { + this.data = { + sale_order: { + fields: { + order_line_ids: { + string: "Lines", + type: 'one2many', + relation: 'order_line', + relation_field: 'order_id', + }, + grid: {string: "Grid", type: 'char'}, + }, + }, + order_line: { + fields: { + order_id: {string: "Invoice", type: 'many2one', relation: 'invoice'}, + product_template_id: {string: "Product", type: 'many2one', relation: 'product'}, + }, + }, + product: { + fields: { + name: {string: "Name", type: 'char'}, + }, + records: [ + {id: 1, name: 'A configurable product'}, + ], + }, + }; + + this.grid = JSON.stringify({ + header: [{name: "My Company Tshirt (GRID)"}, {name: "M"}, {name: "L"}], + matrix: [[ + {name: "Men"}, + {ptav_ids: [10, 13], qty: 0, is_possible_combination: true}, + {ptav_ids: [11, 13], qty: 0, is_possible_combination: true}, + ], [ + {name: "Women"}, + {ptav_ids: [10, 14], qty: 0, is_possible_combination: true}, + {ptav_ids: [11, 14], qty: 0, is_possible_combination: true}, + ]], + }); + }, +}, function () { + QUnit.test('can configure a product with the matrix', async function (assert) { + assert.expect(4); + + this.data.sale_order.onchanges = { + order_line_ids: obj => { + obj.grid = this.grid; + }, + grid: () => {}, + }; + var form = await createView({ + View: FormView, + model: 'sale_order', + data: this.data, + arch: `<form> + <field name="grid" invisible="1"/> + <field name="order_line_ids" widget="section_and_note_one2many"> + <tree editable="bottom"> + <field name="product_template_id" widget="product_configurator"/> + </tree> + </field> + </form>`, + mockRPC: function (route, args) { + if (args.method === 'onchange' && args.args[2] === 'grid') { + // should trigger an onchange on the grid field and let the + // business logic create rows according to the matrix content + assert.deepEqual(args.args[1].grid, JSON.stringify({ + changes: [{qty: 2, ptav_ids: [10, 13]}, {qty: 3, ptav_ids: [11, 14]}], + product_template_id: 1, + })); + } + if (args.method === 'get_single_product_variant') { + assert.strictEqual(args.args[0], 1); + return Promise.resolve({mode: 'matrix'}); + } + return this._super.apply(this, arguments); + }, + }); + + await testUtils.dom.click('.o_field_x2many_list_row_add a'); + await testUtils.fields.many2one.searchAndClickItem("product_template_id", {item: 'configurable'}); + + assert.containsOnce(document.body, '.modal .o_product_variant_matrix'); + const $matrix = $('.modal .o_product_variant_matrix'); + assert.strictEqual($matrix.text().replace(/[\n\r\s\u00a0]+/g, ' '), + ' My Company Tshirt (GRID) M L Men Women '); + + // select 2 M-Men and 3 L-Women + await testUtils.fields.editInput($matrix.find('.o_matrix_input[ptav_ids="10,13"]'), '2'); + await testUtils.fields.editInput($matrix.find('.o_matrix_input[ptav_ids="11,14"]'), '3'); + await testUtils.dom.click($('.modal .modal-footer .btn-primary')); + + form.destroy(); + }); +}); +}); diff --git a/addons/sale_product_matrix/static/tests/tours/sale_product_matrix_tour.js b/addons/sale_product_matrix/static/tests/tours/sale_product_matrix_tour.js new file mode 100644 index 00000000..c0158763 --- /dev/null +++ b/addons/sale_product_matrix/static/tests/tours/sale_product_matrix_tour.js @@ -0,0 +1,143 @@ +odoo.define('sale_product_matrix.sale_matrix_tour', function (require) { +"use strict"; + +var tour = require('web_tour.tour'); + +tour.register('sale_matrix_tour', { + url: "/web", + test: true, +}, [tour.stepUtils.showAppsMenuItem(), { + trigger: '.o_app[data-menu-xmlid="sale.sale_menu_root"]', +}, { + trigger: ".o_list_button_add", + extra_trigger: ".o_sale_order" +}, { + trigger: "a:contains('Add a product')" +}, { + trigger: 'div[name="product_template_id"] input', + run: function () { + var $input = $('div[name="product_template_id"] input'); + $input.click(); + $input.val('Matrix'); + var keyDownEvent = jQuery.Event("keydown"); + keyDownEvent.which = 42; + $input.trigger(keyDownEvent); + } +}, { + trigger: 'ul.ui-autocomplete a:contains("Matrix")', + run: 'click' +}, { + trigger: '.o_product_variant_matrix', + run: function () { + // fill the whole matrix with 1's + $('.o_matrix_input').val(1); + } +}, { + trigger: 'span:contains("Confirm")', + run: 'click' +}, { + trigger: 'span:contains("Matrix (PAV11, PAV22, PAV31)\n\nPA4: PAV41")', + extra_trigger: '.o_form_editable', + run: 'click' +}, { + trigger: '.o_edit_product_configuration', + run: 'click' // edit the matrix +}, { + trigger: '.o_product_variant_matrix', + run: function () { + // set all qties to 3 + $('.o_matrix_input').val(3); + } +}, { + trigger: 'span:contains("Confirm")', + run: 'click' // apply the matrix +}, { + trigger: 'span:contains("Matrix (PAV11, PAV22, PAV31)\n\nPA4: PAV41")', + extra_trigger: '.o_form_editable', + run: 'click' +}, { + trigger: '.o_edit_product_configuration', + run: 'click' // edit the matrix +}, { + trigger: '.o_product_variant_matrix', + run: function () { + // reset all qties to 1 + $('.o_matrix_input').val(1); + } +}, { + trigger: 'span:contains("Confirm")', + run: 'click' // apply the matrix +}, { + trigger: ".o_form_editable .o_field_many2one[name='partner_id'] input", + extra_trigger: ".o_sale_order", + run: 'text Agrolait' +}, { + trigger: ".ui-menu-item > a", + auto: true, + in_modal: false, +}, { + trigger: '.o_form_button_save:contains("Save")', + run: 'click' // SAVE Sales Order. +}, +// Open the matrix through the pencil button next to the product in line edit mode. +{ + trigger: '.o_form_button_edit:contains("Edit")', + run: 'click' // Edit Sales Order. +}, { + trigger: 'span:contains("Matrix (PAV11, PAV22, PAV31)\n\nPA4: PAV41")', + extra_trigger: '.o_form_editable', + run: 'click' +}, { + trigger: '.o_edit_product_configuration', + run: 'click' // edit the matrix +}, { + trigger: '.o_product_variant_matrix', + run: function () { + // update some of the matrix values. + $('.o_matrix_input').slice(8, 16).val(4); + } // set the qty to 4 for half of the matrix products. +}, { + trigger: 'span:contains("Confirm")', + run: 'click' // apply the matrix +}, { + trigger: '.o_form_button_save:contains("Save")', + extra_trigger: '.o_field_cell.o_data_cell.o_list_number:contains("4.00")', + run: 'click' // SAVE Sales Order, after matrix has been applied (extra_trigger). +}, { + trigger: '.o_form_button_edit:contains("Edit")', + run: 'click' // Edit Sales Order. +}, +// Ensures the matrix is opened with the values, when adding the same product. +{ + trigger: "a:contains('Add a product')" +}, { + trigger: 'div[name="product_template_id"] input', + run: function () { + var $input = $('div[name="product_template_id"] input'); + $input.click(); + $input.val('Matrix'); + var keyDownEvent = jQuery.Event("keydown"); + keyDownEvent.which = 42; + $input.trigger(keyDownEvent); + } +}, { + trigger: 'ul.ui-autocomplete a:contains("Matrix")', + run: 'click' +}, { + trigger: "input[value='4']", + run: function () { + // update some values of the matrix + $("input[value='4']").slice(0, 4).val(8.2); + } +}, { + trigger: 'span:contains("Confirm")', + run: 'click' // apply the matrix +}, { + trigger: '.o_form_button_save:contains("Save")', + extra_trigger: '.o_field_cell.o_data_cell.o_list_number:contains("8.20")', + run: 'click' // SAVE Sales Order, after matrix has been applied (extra_trigger). +}, +]); + + +}); |
