diff --git a/addons/hr_timesheet/static/src/components/task_with_hours/task_with_hours.js b/addons/hr_timesheet/static/src/components/task_with_hours/task_with_hours.js index 22e1464d48b..ba82247cede 100644 --- a/addons/hr_timesheet/static/src/components/task_with_hours/task_with_hours.js +++ b/addons/hr_timesheet/static/src/components/task_with_hours/task_with_hours.js @@ -6,14 +6,6 @@ import { Many2OneField } from "@web/views/fields/many2one/many2one_field"; class TaskWithHours extends Many2OneField { - setup() { - super.setup(); - const activeActions = this.state.activeActions; - activeActions.canCreate = activeActions.canCreate && this.canCreate; - activeActions.canQuickCreate = activeActions.canQuickCreate || this.canCreate; - activeActions.canCreateEdit = activeActions.canCreate; - } - get canCreate() { return Boolean(this.context.default_project_id); } @@ -44,6 +36,16 @@ class TaskWithHours extends Many2OneField { return props; } + /** + * @override + */ + computeActiveActions(props) { + super.computeActiveActions(props); + const activeActions = this.state.activeActions; + activeActions.create = activeActions.create && this.canCreate; + activeActions.createEdit = activeActions.create; + } + } registry.category("fields").add("task_with_hours", TaskWithHours); diff --git a/addons/hr_timesheet/static/tests/hr_timesheet_common_tests.js b/addons/hr_timesheet/static/tests/hr_timesheet_common_tests.js new file mode 100644 index 00000000000..2973e580364 --- /dev/null +++ b/addons/hr_timesheet/static/tests/hr_timesheet_common_tests.js @@ -0,0 +1,130 @@ +/** @odoo-module */ + +import { registry } from "@web/core/registry"; +import { session } from "@web/session"; +import { companyService } from "@web/webclient/company_service"; + +import { patchWithCleanup } from "@web/../tests/helpers/utils"; +import { setupViewRegistries } from "@web/../tests/views/helpers"; + + +export const getServerData = () => JSON.parse(JSON.stringify({ + models: { + 'account.analytic.line': { + fields: { + project_id: { string: "Project", type: "many2one", relation: "project.project" }, + task_id: { string: "Task", type: "many2one", relation: "project.task" }, + unit_amount: { string: "Unit Amount", type: "integer" }, + }, + records: [ + { id: 1, project_id: 1, task_id: 3, unit_amount: 1 }, + { id: 2, project_id: 1, task_id: false, unit_amount: 1 }, + { id: 3, project_id: false, task_id: false, unit_amount: 1 }, + ], + }, + 'project.project': { + fields: { + name: { string: "Name", type: "string" }, + }, + records: [ + { id: 1, name: "Project 1" }, + ], + }, + 'project.task': { + fields: { + name: { string: "Name", type: "string" }, + project_id: { string: "Project", type: "many2one", relation: "project.project" }, + }, + records: [ + { id: 1, name: "Task 1\u00A0AdditionalInfo", project_id: 1 }, + { id: 2, name: "Task 2\u00A0AdditionalInfo", project_id: 1 }, + { id: 3, name: "Task 3\u00A0AdditionalInfo", project_id: 1 }, + ], + }, + }, + views: { + "account.analytic.line,false,form": ` +
+ + + + + `, + "account.analytic.line,false,list": ` + + + + + + `, + }, +})); + +export function updateArch(serverData, fieldNameWidgetNameMapping = {}, fieldNameContextMapping = {}) { + for (const viewKey in serverData.views) { + for (const [fieldName, widgetName] of Object.entries(fieldNameWidgetNameMapping)) { + serverData.views[viewKey] = serverData.views[viewKey].replace( + `name="${fieldName}"`, + `name="${fieldName}" widget="${widgetName}"` + ); + } + for (const [fieldName, context] of Object.entries(fieldNameContextMapping)) { + serverData.views[viewKey] = serverData.views[viewKey].replace( + `name="${fieldName}"`, + `name="${fieldName}" context="${context}"` + ); + } + } +} + +export function addFieldsInArch(serverData, fields, beforeField) { + let fieldsArch = ""; + for (const field of fields) { + fieldsArch += ` + `; + } + for (const viewKey in serverData.views) { + serverData.views[viewKey] = serverData.views[viewKey].replace( + `').addClass('i_am_a_timesheet_time_widget'); + this.$el.append($widgetIdentification); + }, + }); + FieldTimesheetToggleBackup = TimesheetUOM.FieldTimesheetToggle; + TimesheetUOM.FieldTimesheetToggle.include({ + _render: function () { + const $widgetIdentification = $('
').addClass('i_am_a_timesheet_toggle_widget'); + this.$el.append($widgetIdentification); + }, + }); + }); + hooks.afterEach(async function (hooks) { + // Restores the widgets and trigger reload in FieldRegistry. + TimesheetUOM.FieldTimesheetTime = FieldTimesheetTimeBackup; + TimesheetUOM.FieldTimesheetToggle = FieldTimesheetToggleBackup; + await env.patchSessionAndStartServices({ }, true); + }); + QUnit.test('the timesheet_uom widget added to the fieldRegistry is company related', async function (assert) { + assert.expect(2); + + let view = await env.createView(); + assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when company uom is hour'); + view.destroy(); + + let option = { + session: { + user_context: env.singleCompanyDayUOMUser, + }, + }; + view = await env.createView(option); + assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when company uom is day'); + view.destroy(); + }); + QUnit.test('the timesheet_uom widget added to the fieldRegistry in a multi company environment is the current company', async function (assert) { + assert.expect(2); + + let option = { + session: { + user_context: env.multiCompanyHourUOMUser, + }, + }; + let view = await env.createView(option); + assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when current company uom is hour'); + view.destroy(); + + option = { + session: { + user_context: env.multiCompanyDayUOMUser, + }, + }; + view = await env.createView(option); + assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when current company uom is day'); + view.destroy(); + }); + }); + QUnit.module('timesheet_uom_factor', function (hooks) { + QUnit.test('the timesheet_uom_factor usage in formatters and parsers is company related', async function (assert) { + assert.expect(4); + + await env.patchSessionAndStartServices(); + assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account'); + assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account'); + + const sessionToApply = { + user_context: env.singleCompanyDayUOMUser, + }; + await env.patchSessionAndStartServices(sessionToApply); + assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account'); + assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account'); + }); + QUnit.test('the timesheet_uom_factor taken into account in a multi company environment is the current company', async function (assert) { + assert.expect(4); + + let sessionToApply = { + user_context: env.multiCompanyHourUOMUser, + }; + await env.patchSessionAndStartServices(sessionToApply); + assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account'); + assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account'); + + sessionToApply.user_context = env.singleCompanyDayUOMUser; + await env.patchSessionAndStartServices(sessionToApply); + assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account'); + assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account'); + }); + }); + }); +}); +}); diff --git a/addons/hr_timesheet/static/tests/timesheet_uom_widgets_tests.js b/addons/hr_timesheet/static/tests/legacy/timesheet_uom_widgets_tests.js similarity index 100% rename from addons/hr_timesheet/static/tests/timesheet_uom_widgets_tests.js rename to addons/hr_timesheet/static/tests/legacy/timesheet_uom_widgets_tests.js diff --git a/addons/hr_timesheet/static/tests/task_with_hours_tests.js b/addons/hr_timesheet/static/tests/task_with_hours_tests.js new file mode 100644 index 00000000000..629ba20f766 --- /dev/null +++ b/addons/hr_timesheet/static/tests/task_with_hours_tests.js @@ -0,0 +1,67 @@ +/** @odoo-module */ + +import { makeView } from "@web/../tests/views/helpers"; +import { click, clickDropdown, editInput, getFixture } from "@web/../tests/helpers/utils"; + +import { getServerData, updateArch, setupTestEnv } from "./hr_timesheet_common_tests"; + + +QUnit.module("hr_timesheet", (hooks) => { + let target; + let serverData; + hooks.beforeEach(async function (assert) { + setupTestEnv(); + serverData = getServerData(); + updateArch( + serverData, + { task_id: "task_with_hours" }, + { task_id: "{ 'default_project_id': project_id }" }); + target = getFixture(); + }); + + QUnit.module("task_with_hours"); + + async function _testCreateAndEdit(target, visible, assert) { + await click(target, ".o_list_many2one[name=task_id]"); + await click(target, ".o_list_many2one[name=task_id] input"); + await editInput(target, ".o_list_many2one[name=task_id] input", "NonExistingTask"); + await click(target, ".o_list_many2one[name=task_id] input"); + await clickDropdown(target, "task_id"); + const testFunction = visible ? assert.containsOnce : assert.containsNone; + testFunction(target, '.o_list_many2one[name=task_id] .dropdown ul li:contains("Create and edit...")'); + } + + QUnit.test("quick create is enabled when project_id is set", async function (assert) { + await makeView({ + serverData, + type: "list", + resModel: "account.analytic.line", + }); + const secondRow = target.querySelector(".o_list_table .o_data_row:nth-of-type(2)"); + await _testCreateAndEdit(secondRow, true, assert); + }); + + QUnit.test("quick create is no enabled when project_id is not set", async function (assert) { + await makeView({ + serverData, + type: "list", + resModel: "account.analytic.line", + }); + const thirdRow = target.querySelector(".o_list_table .o_data_row:nth-of-type(3)"); + await _testCreateAndEdit(thirdRow, false, assert); + }); + + QUnit.test("the text of the task includes hours in the drop down but not in the line", async function (assert) { + await makeView({ + serverData, + type: "list", + resModel: "account.analytic.line", + }); + const firstRow = target.querySelector(".o_list_table .o_data_row:first-of-type"); + assert.containsNone(firstRow, '.o_list_many2one[name=task_id]:contains("AdditionalInfo")'); + await click(firstRow, ".o_list_many2one[name=task_id]"); + await clickDropdown(firstRow, "task_id"); + assert.containsN(firstRow, '.o_list_many2one[name=task_id] .dropdown ul li:contains("AdditionalInfo")', 3); + }); + +}); diff --git a/addons/hr_timesheet/static/tests/timesheet_graph_tests.js b/addons/hr_timesheet/static/tests/timesheet_graph_tests.js index 972294c7715..91092343897 100644 --- a/addons/hr_timesheet/static/tests/timesheet_graph_tests.js +++ b/addons/hr_timesheet/static/tests/timesheet_graph_tests.js @@ -11,7 +11,7 @@ import { setupControlPanelServiceRegistry } from "@web/../tests/search/helpers"; const serviceRegistry = registry.category("services"); -QUnit.module('Views', function (hooks) { +QUnit.module('hr_timesheet', function (hooks) { let serverData; hooks.beforeEach(() => { serverData = { @@ -40,7 +40,7 @@ QUnit.module('Views', function (hooks) { serviceRegistry.add("dialog", dialogService); }); - QUnit.module("hrTimesheetGraphView"); + QUnit.module("hr_timesheet_graphview"); QUnit.test('the timesheet graph view data are not multiplied by a factor that is company related (factor = 1)', async function (assert) { assert.expect(1); diff --git a/addons/hr_timesheet/static/tests/timesheet_uom_no_toggle_tests.js b/addons/hr_timesheet/static/tests/timesheet_uom_no_toggle_tests.js new file mode 100644 index 00000000000..98d0b20d8d6 --- /dev/null +++ b/addons/hr_timesheet/static/tests/timesheet_uom_no_toggle_tests.js @@ -0,0 +1,86 @@ +/** @odoo-module */ + +import { session } from "@web/session"; + +import { makeView } from "@web/../tests/views/helpers"; +import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; + +import { getServerData, updateArch, setupTestEnv } from "./hr_timesheet_common_tests"; + + +QUnit.module("hr_timesheet", (hooks) => { + let target; + let serverData; + hooks.beforeEach(async function (assert) { + setupTestEnv(); + serverData = getServerData(); + updateArch(serverData, { unit_amount: "timesheet_uom_no_toggle" }); + target = getFixture(); + }); + + QUnit.module("timesheet_uom_no_toggle"); + + QUnit.test("FloatTimeField is used when current company uom uses float_time widget", async function (assert) { + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "01:00", "unit_amount is displayed as time"); + }); + + QUnit.test("FloatTimeField is not dependent of timesheet_uom_factor of the current company when current company uom uses float_time widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_factor: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "01:00", "timesheet_uom_factor is not taken into account"); + }); + + QUnit.test("FloatToggleField is not used when current company uom uses float_toggle widget, FloatFactorField is used instead", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + assert.containsNone(target, 'div[name="unit_amount"] .o_field_float_toggle', "unit_amount is not displayed as float toggle"); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float"); + assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time"); + }); + + QUnit.test("FloatFactorField is used when the current_company uom is not part of the session uom", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy' }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float"); + assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time"); + assert.containsNone(target, 'div[name="unit_amount"].o_field_float_toggle', "unit_amount is not displayed as float toggle"); + }); + + QUnit.test("FloatFactorField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy', timesheet_uom_factor: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "2.00", "timesheet_uom_factor is taken into account"); + }); + +}); diff --git a/addons/hr_timesheet/static/tests/timesheet_uom_tests.js b/addons/hr_timesheet/static/tests/timesheet_uom_tests.js index 2482cdad4d0..0e3f37fad7d 100644 --- a/addons/hr_timesheet/static/tests/timesheet_uom_tests.js +++ b/addons/hr_timesheet/static/tests/timesheet_uom_tests.js @@ -1,140 +1,94 @@ -odoo.define("hr_timesheet.timesheet_uom_tests", function (require) { -"use strict"; +/** @odoo-module */ -const session = require('web.session'); -const SetupTimesheetUOMWidgetsTestEnvironment = require('hr_timesheet.timesheet_uom_tests_env'); -const fieldUtils = require('web.field_utils'); -const TimesheetUOM = require('hr_timesheet.timesheet_uom'); +import { session } from "@web/session"; -QUnit.module('Timesheet UOM Widgets', function (hooks) { - let env; - let sessionUserCompaniesBackup; - let sessionUserContextBackup; - let sessionUOMIdsBackup; - let sessionUIDBackup; +import { makeView } from "@web/../tests/views/helpers"; +import { getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; + +import { getServerData, updateArch, setupTestEnv } from "./hr_timesheet_common_tests"; + + +QUnit.module("hr_timesheet", (hooks) => { + let target; + let serverData; hooks.beforeEach(async function (assert) { - env = new SetupTimesheetUOMWidgetsTestEnvironment(); - // Backups session parts that this testing module will alter in order to restore it at the end. - sessionUserCompaniesBackup = session.user_companies || false; - sessionUserContextBackup = session.user_context || false; - sessionUOMIdsBackup = session.uom_ids || false; - sessionUIDBackup = session.uid || false; + setupTestEnv(); + serverData = getServerData(); + updateArch(serverData, { unit_amount: "timesheet_uom" }); + target = getFixture(); }); - hooks.afterEach(async function (assert) { - // Restores the session - const sessionToApply = Object.assign( - { }, - sessionUserCompaniesBackup && { - user_companies: sessionUserCompaniesBackup, - } || { }, - sessionUserContextBackup && { - user_context: sessionUserContextBackup, - } || { }, - sessionUOMIdsBackup && { - uom_ids: sessionUOMIdsBackup, - } || { }, - sessionUIDBackup && { - uid: sessionUIDBackup, - } || { }); - await env.patchSessionAndStartServices(sessionToApply, true); - }); - QUnit.module('timesheet_uom', function (hooks) { - QUnit.module('fieldRegistry', function (hooks) { - let FieldTimesheetTimeBackup; - let FieldTimesheetToggleBackup; - hooks.beforeEach(function (assert) { - // Backups the FieldTimesheetTime widget as it will be altered in this testing module - // in order to to ease testing. - FieldTimesheetTimeBackup = TimesheetUOM.FieldTimesheetTime; - TimesheetUOM.FieldTimesheetTime.include({ - _render: function () { - const $widgetIdentification = $('
').addClass('i_am_a_timesheet_time_widget'); - this.$el.append($widgetIdentification); - }, - }); - FieldTimesheetToggleBackup = TimesheetUOM.FieldTimesheetToggle; - TimesheetUOM.FieldTimesheetToggle.include({ - _render: function () { - const $widgetIdentification = $('
').addClass('i_am_a_timesheet_toggle_widget'); - this.$el.append($widgetIdentification); - }, - }); - }); - hooks.afterEach(async function (hooks) { - // Restores the widgets and trigger reload in FieldRegistry. - TimesheetUOM.FieldTimesheetTime = FieldTimesheetTimeBackup; - TimesheetUOM.FieldTimesheetToggle = FieldTimesheetToggleBackup; - await env.patchSessionAndStartServices({ }, true); - }); - QUnit.test('the timesheet_uom widget added to the fieldRegistry is company related', async function (assert) { - assert.expect(2); - let view = await env.createView(); - assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when company uom is hour'); - view.destroy(); + QUnit.module("timesheet_uom"); - let option = { - session: { - user_context: env.singleCompanyDayUOMUser, - }, - }; - view = await env.createView(option); - assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when company uom is day'); - view.destroy(); - }); - QUnit.test('the timesheet_uom widget added to the fieldRegistry in a multi company environment is the current company', async function (assert) { - assert.expect(2); - - let option = { - session: { - user_context: env.multiCompanyHourUOMUser, - }, - }; - let view = await env.createView(option); - assert.ok(view.$('.i_am_a_timesheet_time_widget').length, 'FieldTimesheetTime is rendered when current company uom is hour'); - view.destroy(); - - option = { - session: { - user_context: env.multiCompanyDayUOMUser, - }, - }; - view = await env.createView(option); - assert.ok(view.$('.i_am_a_timesheet_toggle_widget').length, 'FieldTimesheetToggle is rendered when current company uom is day'); - view.destroy(); - }); - }); - QUnit.module('timesheet_uom_factor', function (hooks) { - QUnit.test('the timesheet_uom_factor usage in formatters and parsers is company related', async function (assert) { - assert.expect(4); - - await env.patchSessionAndStartServices(); - assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account'); - assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account'); - - const sessionToApply = { - user_context: env.singleCompanyDayUOMUser, - }; - await env.patchSessionAndStartServices(sessionToApply); - assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account'); - assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account'); - }); - QUnit.test('the timesheet_uom_factor taken into account in a multi company environment is the current company', async function (assert) { - assert.expect(4); - - let sessionToApply = { - user_context: env.multiCompanyHourUOMUser, - }; - await env.patchSessionAndStartServices(sessionToApply); - assert.strictEqual(fieldUtils.format.timesheet_uom(1), '01:00', 'The format is taking the timesheet_uom_factor into account'); - assert.strictEqual(fieldUtils.parse.timesheet_uom('01:00'), 1, 'The parsing is taking the timesheet_uom_factor into account'); - - sessionToApply.user_context = env.singleCompanyDayUOMUser; - await env.patchSessionAndStartServices(sessionToApply); - assert.strictEqual(fieldUtils.format.timesheet_uom(8), '1.00', 'The format is taking the timesheet_uom_factor into account'); - assert.strictEqual(fieldUtils.parse.timesheet_uom('1.00'), 8, 'The parsing is taking the timesheet_uom_factor into account'); - }); + QUnit.test("FloatTimeField is used when current company uom uses float_time widget", async function (assert) { + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "01:00", "unit_amount is displayed as time"); }); -}); + + QUnit.test("FloatTimeField is not dependent of timesheet_uom_factor of the current company when current company uom uses float_time widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_factor: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "01:00", "timesheet_uom_factor is not taken into account"); + }); + + QUnit.test("FloatToggleField is used when current company uom uses float_toggle widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + assert.containsOnce(target, 'div[name="unit_amount"] .o_field_float_toggle', "unit_amount is displayed as float toggle"); + }); + + QUnit.test("FloatToggleField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 2, timesheet_uom_factor: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + assert.containsOnce(target, 'div[name="unit_amount"] .o_field_float_toggle:contains("2.00")', "timesheet_uom_factor is taken into account"); + }); + + QUnit.test("FloatFactorField is used when the current_company uom is not part of the session uom", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy' }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.containsOnce(target, 'div[name="unit_amount"] input[inputmode="numeric"]', "unit_amount is displayed as float"); + assert.equal(unitAmountInput.value, "1.00", "unit_amount is not displayed as float and not as time"); + assert.containsNone(target, 'div[name="unit_amount"].o_field_float_toggle', "unit_amount is not displayed as float toggle"); + }); + + QUnit.test("FloatFactorField is dependent of timesheet_uom_factor of the current company when current company uom uses float_toggle widget", async function (assert) { + patchWithCleanup(session.user_companies.allowed_companies[1], { timesheet_uom_id: 'dummy', timesheet_uom_factor: 2 }); + await makeView({ + serverData, + type: "form", + resModel: "account.analytic.line", + resId: 1, + }); + const unitAmountInput = target.querySelector('div[name="unit_amount"] input'); + assert.equal(unitAmountInput.value, "2.00", "timesheet_uom_factor is taken into account"); + }); + }); diff --git a/addons/web/static/src/views/fields/many2one/many2one_field.js b/addons/web/static/src/views/fields/many2one/many2one_field.js index 3cb54051d29..57406b8a44d 100644 --- a/addons/web/static/src/views/fields/many2one/many2one_field.js +++ b/addons/web/static/src/views/fields/many2one/many2one_field.js @@ -51,18 +51,10 @@ export class Many2OneField extends Component { this.autocompleteContainerRef.el.querySelector("input").focus(); }; - const computeActiveActions = (props) => { - this.state.activeActions = { - create: props.canCreate, - createEdit: props.canCreateEdit, - write: props.canWrite, - }; - }; - this.state = useState({ isFloating: !this.props.value, }); - computeActiveActions(this.props); + this.computeActiveActions(this.props); this.openMany2X = useOpenMany2XRecord({ resModel: this.relation, @@ -102,7 +94,7 @@ export class Many2OneField extends Component { onWillUpdateProps(async (nextProps) => { this.state.isFloating = !nextProps.value; - computeActiveActions(nextProps); + this.computeActiveActions(nextProps); }); } @@ -151,6 +143,13 @@ export class Many2OneField extends Component { autocomplete_container: this.autocompleteContainerRef, }; } + computeActiveActions(props) { + this.state.activeActions = { + create: props.canCreate, + createEdit: props.canCreateEdit, + write: props.canWrite, + }; + } getDomain() { return this.domain.toList(this.context); }