@@ -116,7 +116,7 @@
-
+
@@ -126,7 +126,7 @@
)
-
+
diff --git a/addons/lunch/static/tests/lunch_kanban_mobile_tests.js b/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
index f17bef77f8c..1f2e61ff423 100644
--- a/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
+++ b/addons/lunch/static/tests/lunch_kanban_mobile_tests.js
@@ -4,7 +4,7 @@ odoo.define('lunch.lunchKanbanMobileTests', function (require) {
const LunchKanbanView = require('lunch.LunchKanbanView');
const testUtils = require('web.test_utils');
-const {createLunchKanbanView, mockLunchRPC} = require('lunch.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
QUnit.module('Views');
@@ -61,7 +61,7 @@ QUnit.module('LunchKanbanView Mobile', {
QUnit.test('basic rendering', async function (assert) {
assert.expect(7);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -84,27 +84,27 @@ QUnit.module('LunchKanbanView Mobile', {
"should have 1 records in the renderer");
// check view layout
- assert.containsOnce(kanban, '.o_content > .o_lunch_kanban',
+ assert.containsOnce(kanban, '.o_content > .o_lunch_content',
"should have a 'kanban lunch wrapper' column");
- assert.containsOnce(kanban, '.o_lunch_kanban > .o_kanban_view',
+ assert.containsOnce(kanban, '.o_lunch_content > .o_kanban_view',
"should have a 'classical kanban view' column");
assert.hasClass(kanban.$('.o_kanban_view'), 'o_lunch_kanban_view',
"should have classname 'o_lunch_kanban_view'");
- assert.containsOnce($('.o_lunch_kanban'), '> details',
+ assert.containsOnce($('.o_lunch_content'), '> details',
"should have a 'lunch kanban' details/summary discolure panel");
- assert.hasClass($('.o_lunch_kanban > details'), 'fixed-bottom',
+ assert.hasClass($('.o_lunch_content > details'), 'fixed-bottom',
"should have classname 'fixed-bottom'");
- assert.isNotVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isNotVisible($('.o_lunch_content > details .o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
kanban.destroy();
});
- QUnit.module('LunchKanbanWidget', function () {
+ QUnit.module('LunchWidget', function () {
QUnit.test('toggle', async function (assert) {
assert.expect(6);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -125,8 +125,8 @@ QUnit.module('LunchKanbanView Mobile', {
}),
});
- const $details = $('.o_lunch_kanban > details');
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ const $details = $('.o_lunch_content > details');
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
assert.isVisible($details.find('> summary'),
"should hava a visible cart toggle button");
@@ -136,11 +136,11 @@ QUnit.module('LunchKanbanView Mobile', {
"should have '3.00' in the button text");
await testUtils.dom.click($details.find('> summary'));
- assert.isVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isVisible($details.find('.o_lunch_banner'),
"should have a visible 'lunch kanban' banner");
await testUtils.dom.click($details.find('> summary'));
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
kanban.destroy();
@@ -149,7 +149,7 @@ QUnit.module('LunchKanbanView Mobile', {
QUnit.test('keep open when adding quantities', async function (assert) {
assert.expect(6);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -177,14 +177,14 @@ QUnit.module('LunchKanbanView Mobile', {
}),
});
- const $details = $('.o_lunch_kanban > details');
- assert.isNotVisible($details.find('.o_lunch_kanban_banner'),
+ const $details = $('.o_lunch_content > details');
+ assert.isNotVisible($details.find('.o_lunch_banner'),
"shouldn't have a visible 'lunch kanban' banner");
assert.isVisible($details.find('> summary'),
"should hava a visible cart toggle button");
await testUtils.dom.click($details.find('> summary'));
- assert.isVisible($details.find('.o_lunch_kanban_banner'),
+ assert.isVisible($details.find('.o_lunch_banner'),
"should have a visible 'lunch kanban' banner");
const $widgetSecondColumn = kanban.$('.o_lunch_widget .o_lunch_widget_info:eq(1)');
@@ -195,13 +195,13 @@ QUnit.module('LunchKanbanView Mobile', {
let $firstLine = $widgetSecondColumn.find('.o_lunch_widget_lines > li:first');
await testUtils.dom.click($firstLine.find('button.o_add_product'));
- assert.isVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isVisible($('.o_lunch_content > details .o_lunch_banner'),
"add quantity should keep 'lunch kanban' banner open");
$firstLine = kanban.$('.o_lunch_widget .o_lunch_widget_info:eq(1) .o_lunch_widget_lines > li:first');
await testUtils.dom.click($firstLine.find('button.o_remove_product'));
- assert.isVisible($('.o_lunch_kanban > details .o_lunch_kanban_banner'),
+ assert.isVisible($('.o_lunch_content > details .o_lunch_banner'),
"remove quantity should keep 'lunch kanban' banner open");
kanban.destroy();
diff --git a/addons/lunch/static/tests/lunch_kanban_tests.js b/addons/lunch/static/tests/lunch_kanban_tests.js
index bb2b0beb3f7..d4deade79bb 100644
--- a/addons/lunch/static/tests/lunch_kanban_tests.js
+++ b/addons/lunch/static/tests/lunch_kanban_tests.js
@@ -4,7 +4,7 @@ odoo.define('lunch.lunchKanbanTests', function (require) {
const LunchKanbanView = require('lunch.LunchKanbanView');
const testUtils = require('web.test_utils');
-const {createLunchKanbanView, mockLunchRPC} = require('lunch.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
QUnit.module('Views');
@@ -89,7 +89,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('basic rendering', async function (assert) {
assert.expect(7);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -116,14 +116,14 @@ QUnit.module('LunchKanbanView', {
"should have 2 columns");
assert.containsOnce(kanban, '.o_content > div.o_search_panel',
"should have a 'lunch filters' column");
- assert.containsOnce(kanban, '.o_content > .o_lunch_kanban',
- "should have a 'kanban lunch wrapper' column");
- assert.containsOnce(kanban, '.o_lunch_kanban > .o_kanban_view',
+ assert.containsOnce(kanban, '.o_content > .o_lunch_content',
+ "should have a 'lunch wrapper' column");
+ assert.containsOnce(kanban, '.o_lunch_content > .o_kanban_view',
"should have a 'classical kanban view' column");
assert.hasClass(kanban.$('.o_kanban_view'), 'o_lunch_kanban_view',
"should have classname 'o_lunch_kanban_view'");
- assert.containsOnce(kanban, '.o_lunch_kanban > span > .o_lunch_kanban_banner',
- "should have a 'lunch kanban' banner");
+ assert.containsOnce(kanban, '.o_lunch_content > span > .o_lunch_banner',
+ "should have a 'lunch' banner");
kanban.destroy();
});
@@ -133,7 +133,7 @@ QUnit.module('LunchKanbanView', {
const self = this;
let infosProm = Promise.resolve();
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -175,12 +175,12 @@ QUnit.module('LunchKanbanView', {
kanban.destroy();
});
- QUnit.module('LunchKanbanWidget', function () {
+ QUnit.module('LunchWidget', function () {
QUnit.test('empty cart', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -217,7 +217,7 @@ QUnit.module('LunchKanbanView', {
let locationId = this.data['lunch.location'].records[0].id;
const regularInfos = _.extend({}, this.regularInfos);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -285,7 +285,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(10);
const regularInfos = _.extend({}, this.regularInfos);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -333,7 +333,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('non-empty cart', async function (assert) {
assert.expect(17);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -415,7 +415,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('ordered cart', async function (assert) {
assert.expect(15);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -491,7 +491,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('confirmed cart', async function (assert) {
assert.expect(15);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -567,7 +567,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('regular user', async function (assert) {
assert.expect(11);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -626,7 +626,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('manager user', async function (assert) {
assert.expect(12);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -690,7 +690,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('add a product', async function (assert) {
assert.expect(1);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -732,7 +732,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('add product quantity', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: Object.assign({}, this.data, {
@@ -784,7 +784,7 @@ QUnit.module('LunchKanbanView', {
QUnit.test('remove product quantity', async function (assert) {
assert.expect(3);
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: Object.assign({}, this.data, {
@@ -837,7 +837,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(1);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -883,7 +883,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(1);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
@@ -929,7 +929,7 @@ QUnit.module('LunchKanbanView', {
assert.expect(5);
const self = this;
- const kanban = await createLunchKanbanView({
+ const kanban = await createLunchView({
View: LunchKanbanView,
model: 'product',
data: this.data,
diff --git a/addons/lunch/static/tests/lunch_list_tests.js b/addons/lunch/static/tests/lunch_list_tests.js
new file mode 100644
index 00000000000..cca644a52a9
--- /dev/null
+++ b/addons/lunch/static/tests/lunch_list_tests.js
@@ -0,0 +1,267 @@
+odoo.define('lunch.lunchListTests', function (require) {
+"use strict";
+
+const LunchListView = require('lunch.LunchListView');
+
+const testUtils = require('web.test_utils');
+const {createLunchView, mockLunchRPC} = require('lunch.test_utils');
+
+QUnit.module('Views');
+
+QUnit.module('LunchListView', {
+ beforeEach() {
+ const PORTAL_GROUP_ID = 1234;
+
+ this.data = {
+ 'product': {
+ fields: {
+ is_available_at: {string: 'Product Availability', type: 'many2one', relation: 'lunch.location'},
+ category_id: {string: 'Product Category', type: 'many2one', relation: 'lunch.product.category'},
+ supplier_id: {string: 'Vendor', type: 'many2one', relation: 'lunch.supplier'},
+ },
+ records: [
+ {id: 1, name: 'Tuna sandwich', is_available_at: 1},
+ ],
+ },
+ 'lunch.order': {
+ fields: {},
+ update_quantity() {
+ return Promise.resolve();
+ },
+ },
+ 'lunch.product.category': {
+ fields: {},
+ records: [],
+ },
+ 'lunch.supplier': {
+ fields: {},
+ records: [],
+ },
+ 'ir.model.data': {
+ fields: {},
+ xmlid_to_res_id() {
+ return Promise.resolve(PORTAL_GROUP_ID);
+ },
+ },
+ 'lunch.location': {
+ fields: {
+ name: {string: 'Name', type: 'char'},
+ },
+ records: [
+ {id: 1, name: "Office 1"},
+ {id: 2, name: "Office 2"},
+ ],
+ },
+ 'res.users': {
+ fields: {
+ name: {string: 'Name', type: 'char'},
+ groups_id: {string: 'Groups', type: 'many2many'},
+ },
+ records: [
+ {id: 1, name: "Mitchell Admin", groups_id: []},
+ {id: 2, name: "Marc Demo", groups_id: []},
+ {id: 3, name: "Jean-Luc Portal", groups_id: [PORTAL_GROUP_ID]},
+ ],
+ },
+ };
+ this.regularInfos = {
+ username: "Marc Demo",
+ wallet: 36.5,
+ is_manager: false,
+ currency: {
+ symbol: "\u20ac",
+ position: "after"
+ },
+ user_location: [2, "Office 2"],
+ };
+ },
+}, function () {
+ QUnit.test('basic rendering', async function (assert) {
+ assert.expect(6);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+
+
+
+ `,
+ mockRPC: mockLunchRPC({
+ infos: this.regularInfos,
+ userLocation: this.data['lunch.location'].records[0].id,
+ }),
+ });
+
+ // check view layout
+ assert.containsN(list, '.o_content > div', 2,
+ "should have 2 columns");
+ assert.containsOnce(list, '.o_content > div.o_search_panel',
+ "should have a 'lunch filters' column");
+ assert.containsOnce(list, '.o_content > .o_lunch_content',
+ "should have a 'lunch wrapper' column");
+ assert.containsOnce(list, '.o_lunch_content > .o_list_view',
+ "should have a 'classical list view' column");
+ assert.hasClass(list.$('.o_list_view'), 'o_lunch_list_view',
+ "should have classname 'o_lunch_list_view'");
+ assert.containsOnce(list, '.o_lunch_content > span > .o_lunch_banner',
+ "should have a 'lunch' banner");
+
+ list.destroy();
+ });
+
+ QUnit.module('LunchWidget', function () {
+
+ QUnit.test('search panel domain location', async function (assert) {
+ assert.expect(20);
+ let expectedLocation = 1;
+ let locationId = this.data['lunch.location'].records[0].id;
+ const regularInfos = _.extend({}, this.regularInfos);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+
+
+
+ `,
+ mockRPC: function (route, args) {
+ assert.step(route);
+
+ if (route.startsWith('/lunch')) {
+ if (route === '/lunch/user_location_set') {
+ locationId = args.location_id;
+ return Promise.resolve(true);
+ }
+ return mockLunchRPC({
+ infos: regularInfos,
+ userLocation: locationId,
+ }).apply(this, arguments);
+ }
+ if (args.method === 'search_panel_select_multi_range') {
+ assert.deepEqual(args.kwargs.search_domain, [["is_available_at", "in", [expectedLocation]]],
+ 'The initial domain of the search panel must contain the user location');
+ }
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [["is_available_at", "in", [expectedLocation]]],
+ 'The domain for fetching actual data should be correct');
+ }
+ return this._super.apply(this, arguments);
+ },
+ });
+
+ expectedLocation = 2;
+ await testUtils.fields.many2one.clickOpenDropdown('locations');
+ await testUtils.fields.many2one.clickItem('locations', "Office 2");
+
+ assert.verifySteps([
+ // Initial state
+ '/lunch/user_location_get',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ // Click m2o
+ '/web/dataset/call_kw/lunch.location/name_search',
+ // Click new location
+ '/lunch/user_location_set',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ ]);
+
+ list.destroy();
+ });
+
+ QUnit.test('search panel domain location false: fetch products in all locations', async function (assert) {
+ assert.expect(10);
+ const regularInfos = _.extend({}, this.regularInfos);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+
+
+
+ `,
+ mockRPC: function (route, args) {
+ assert.step(route);
+
+ if (route.startsWith('/lunch')) {
+ return mockLunchRPC({
+ infos: regularInfos,
+ userLocation: false,
+ }).apply(this, arguments);
+ }
+ if (args.method === 'search_panel_select_multi_range') {
+ assert.deepEqual(args.kwargs.search_domain, [],
+ 'The domain should not exist since the location is false.');
+ }
+ if (route === '/web/dataset/search_read') {
+ assert.deepEqual(args.domain, [],
+ 'The domain for fetching actual data should be correct');
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+ assert.verifySteps([
+ '/lunch/user_location_get',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/call_kw/product/search_panel_select_multi_range',
+ '/web/dataset/search_read',
+ '/lunch/infos',
+ '/web/dataset/call_kw/ir.model.data/xmlid_to_res_id',
+ ])
+
+ list.destroy();
+ });
+
+ QUnit.test('add a product', async function (assert) {
+ assert.expect(1);
+
+ const list = await createLunchView({
+ View: LunchListView,
+ model: 'product',
+ data: this.data,
+ arch: `
+
+
+
+ `,
+ mockRPC: mockLunchRPC({
+ infos: this.regularInfos,
+ userLocation: this.data['lunch.location'].records[0].id,
+ }),
+ intercepts: {
+ do_action: function (ev) {
+ assert.deepEqual(ev.data.action, {
+ name: "Configure Your Order",
+ res_model: 'lunch.order',
+ type: 'ir.actions.act_window',
+ views: [[false, 'form']],
+ target: 'new',
+ context: {
+ default_product_id: 1,
+ },
+ },
+ "should open the wizard");
+ },
+ },
+ });
+
+ await testUtils.dom.click(list.$('.o_data_row:first'));
+
+ list.destroy();
+ });
+ });
+});
+
+});
diff --git a/addons/lunch/static/tests/lunch_test_utils.js b/addons/lunch/static/tests/lunch_test_utils.js
index beef94f80a5..a59328a05dd 100644
--- a/addons/lunch/static/tests/lunch_test_utils.js
+++ b/addons/lunch/static/tests/lunch_test_utils.js
@@ -6,11 +6,11 @@ const RamStorage = require('web.RamStorage');
const {createView} = require('web.test_utils');
/**
- * Helper to create a lunch kanban view with searchpanel
+ * Helper to create a lunch view with searchpanel
*
* @param {object} params
*/
-async function createLunchKanbanView(params) {
+async function createLunchView(params) {
params.archs = params.archs || {};
var searchArch = params.archs[`${params.model},false,search`] || '
';
var searchPanelArch = `
@@ -52,7 +52,7 @@ function mockLunchRPC({infos, userLocation}) {
}
return {
- createLunchKanbanView,
+ createLunchView,
mockLunchRPC,
};
diff --git a/addons/lunch/views/lunch_product_views.xml b/addons/lunch/views/lunch_product_views.xml
index 0c5fb5d0319..7764aa19b45 100644
--- a/addons/lunch/views/lunch_product_views.xml
+++ b/addons/lunch/views/lunch_product_views.xml
@@ -91,6 +91,21 @@
+
+ lunch.product.tree
+ lunch.product.report
+ 999
+
+
+
+
+
+
+
+
+
+
+
lunch.product.kanban
@@ -330,7 +345,7 @@
Order Your Lunch
lunch.product.report
- kanban
+ kanban,tree
[('supplier_id.available_today', '=', True), '|', ('user_id', '=', False), ('user_id', '=', uid)]
diff --git a/addons/lunch/views/lunch_templates.xml b/addons/lunch/views/lunch_templates.xml
index 2fbdb1d3df0..2b2ea02973a 100644
--- a/addons/lunch/views/lunch_templates.xml
+++ b/addons/lunch/views/lunch_templates.xml
@@ -2,17 +2,22 @@
+
-
+
+
+
+
-
-
+
+
+
@@ -20,6 +25,7 @@
+