Files
enterprise-addons/sale_planning/static/tests/planning_gantt_patch.test.js
T

344 lines
11 KiB
JavaScript

import { click } from "@mail/../tests/mail_test_helpers";
import { beforeEach, describe, expect, test } from "@odoo/hoot";
import { animationFrame, mockDate, mockTimeZone } from "@odoo/hoot-mock";
import { queryAll, queryAllTexts } from "@odoo/hoot-dom";
import {
contains,
defineModels,
fields,
models,
mountWithCleanup,
onRpc,
patchWithCleanup,
selectFieldDropdownItem,
} from "@web/../tests/web_test_helpers";
import {
clickCell,
editPill,
hoverGridCell,
getGridContent,
mountGanttView,
SELECTORS,
selectRange,
} from "@web_gantt/../tests/web_gantt_test_helpers";
import { Component, onWillStart, useState, xml } from "@odoo/owl";
import { PlanningGanttRenderer } from "@planning/views/planning_gantt/planning_gantt_renderer";
import { Domain } from "@web/core/domain";
import { useService } from "@web/core/utils/hooks";
import { View } from "@web/views/view";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
import { definePlanningModels, planningModels } from "@planning/../tests/planning_mock_models";
describe.current.tags("desktop");
class PlanningSlot extends planningModels.PlanningSlot {
_records = [
{
id: 1,
name: "Shift 1",
role_id: 1,
sale_line_id: 1,
resource_id: false,
start_datetime: "2021-10-12 08:00:00",
end_datetime: "2021-10-12 12:00:00",
allocated_percentage: 0.5,
},
];
}
class PlanningRole extends planningModels.PlanningRole {
_records = [
{ id: 1, name: "Developer" },
{ id: 2, name: "Support Tech" },
];
}
class Resource extends planningModels.ResourceResource {
_records = [
{ id: 1, name: "Chaganlal" },
{ id: 2, name: "Jarvo" },
];
}
class SaleOrderLine extends models.Model {
_name = "sale.order.line";
name = fields.Char();
_records = [{ id: 1, name: "Computer Configuration" }];
}
planningModels.PlanningSlot = PlanningSlot;
planningModels.PlanningRole = PlanningRole;
planningModels.ResourceResource = Resource;
definePlanningModels();
defineModels([SaleOrderLine]);
beforeEach(() => {
mockDate("2021-10-10 07:00:00", +1);
onRpc("has_group", () => false);
});
test("Process domain for plan dialog", async function () {
let renderer;
patchWithCleanup(PlanningGanttRenderer.prototype, {
setup() {
super.setup(...arguments);
renderer = this;
},
});
class Parent extends Component {
static template = xml`<View t-props="state"/>`;
static components = { View };
static props = ["*"];
setup() {
this.state = useState({
arch: `<gantt js_class="planning_gantt" date_start="start_datetime" date_stop="end_datetime" default_scale="week"/>`,
resModel: "planning.slot",
type: "gantt",
domain: [
["start_datetime", "!=", false],
["end_datetime", "!=", false],
],
});
this.field = useService("field");
onWillStart(async () => {
this.state.fields = await this.field.loadFields("planning.slot");
});
}
}
const parent = await mountWithCleanup(Parent);
await animationFrame();
let expectedDomain = Domain.and([
Domain.and([
new Domain(["&", ...Domain.TRUE.toList({}), ...Domain.TRUE.toList({})]),
["|", ["start_datetime", "=", false], ["end_datetime", "=", false]],
]),
[["sale_line_id.state", "!=", "cancel"]],
[["sale_line_id", "!=", false]],
]);
expect(renderer.getPlanDialogDomain()).toEqual(expectedDomain.toList());
parent.state.domain = [
"|",
["role_id", "=", false],
"&",
["resource_id", "!=", false],
["start_datetime", "=", false],
];
await animationFrame();
expectedDomain = Domain.and([
Domain.and([
new Domain([
"|",
["role_id", "=", false],
"&",
["resource_id", "!=", false],
...Domain.TRUE.toList({}),
]),
["|", ["start_datetime", "=", false], ["end_datetime", "=", false]],
]),
[["sale_line_id.state", "!=", "cancel"]],
[["sale_line_id", "!=", false]],
]);
expect(renderer.getPlanDialogDomain()).toEqual(expectedDomain.toList());
parent.state.domain = ["|", ["start_datetime", "=", false], ["end_datetime", "=", false]];
await animationFrame();
expectedDomain = Domain.and([
Domain.and([
Domain.TRUE,
["|", ["start_datetime", "=", false], ["end_datetime", "=", false]],
]),
[["sale_line_id.state", "!=", "cancel"]],
[["sale_line_id", "!=", false]],
]);
expect(renderer.getPlanDialogDomain()).toEqual(expectedDomain.toList());
});
test("check default planned dates on the plan dialog", async function () {
expect.assertions(4);
mockTimeZone(0);
patchWithCleanup(SelectCreateDialog.prototype, {
setup() {
super.setup(...arguments);
expect(this.props.context.default_start_datetime).toMatch(/^2021-10-11/);
expect(this.props.context.default_end_datetime).toMatch(/^2021-10-12/);
expect(this.props.context.focus_date).toMatch(/^2021-10-13/);
expect(this.props.context.scale).toBe("week");
},
});
PlanningSlot._records.push({
id: 2,
role_id: 1,
sale_line_id: 1,
resource_id: false,
start_datetime: false,
end_datetime: false,
});
await mountGanttView({
resModel: "planning.slot",
arch: `<gantt js_class="planning_gantt" date_start="start_datetime" date_stop="end_datetime" default_scale="week"/>`,
});
await clickCell("Monday 11", "Week 41, Oct 10 - Oct 16");
});
test("Show shift form dialog only when shifts to plan", async function () {
// Additionally to 'Shift 1', we create a new unplanned shift 'Shift 2' which has a sale_line_id, no start_datetime and no end_datetime values
PlanningSlot._records.push({
id: 2,
name: "Shift 2",
role_id: 1,
sale_line_id: 1,
});
PlanningSlot._views = {
form: `<form js_class="planning_form"><field name="name"/></form>`,
list: `<list><field name="name"/></list>`,
};
await mountGanttView({
resModel: "planning.slot",
arch: `<gantt js_class="planning_gantt" date_start="start_datetime" date_stop="end_datetime" default_scale="week"/>`,
});
await hoverGridCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
await clickCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
expect(".o_dialog").toHaveCount(1);
expect(".modal-title").toHaveText("Plan");
expect(".o_data_cell").toHaveText("Shift 2");
await click(".o_data_cell");
await animationFrame();
const { rows } = getGridContent();
expect(rows).toEqual([
{
pills: [
{
colSpan:
"Tuesday 12 Week 41, Oct 10 - Oct 16 -> Tuesday 12 Week 41, Oct 10 - Oct 16",
level: 0,
title: "Shift 1",
},
{
colSpan:
"Wednesday 13 Week 41, Oct 10 - Oct 16 -> Wednesday 13 Week 41, Oct 10 - Oct 16",
level: 0,
title: "Shift 2",
},
],
},
]);
await hoverGridCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
await clickCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
expect(".o_dialog").toHaveCount(1);
expect(".modal-title").toHaveText("Add Shift");
});
test("Open a dialog to schedule a plan using Open Shift", async function () {
PlanningSlot._records.push({
id: 2,
sale_line_id: 1,
});
PlanningSlot._views = {
list: `<list><field name="sale_line_id"/></list>`,
form: `
<form>
<field name="resource_id"/>
<field name="start_datetime"/>
<field name="end_datetime"/>
<field name="name"/>
</form>
`,
};
await mountGanttView({
resModel: "planning.slot",
arch: '<gantt js_class="planning_gantt" date_start="start_datetime" date_stop="end_datetime" default_scale="week"/>',
groupBy: ["resource_id"],
});
await hoverGridCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
await clickCell("Wednesday 13", "Week 41, Oct 10 - Oct 16");
await click(".modal-footer .o_create_button");
await selectFieldDropdownItem("resource_id", "Jarvo");
await contains(`[name='name'] input`).edit("Shift-2");
await contains(`[name='start_datetime'] button`).click();
await contains(`[name='start_datetime'] input`).edit("2021-10-12 09:00:00");
await contains(`[name='end_datetime'] button`).click();
await contains(`[name='end_datetime'] input`).edit("2021-10-12 12:00:00");
await click(".o_form_button_save");
await animationFrame();
const shift2Pill = queryAll(SELECTORS.pill)[1];
await contains(shift2Pill).click();
expect(queryAllTexts`.o_popover .popover-body span`).toEqual([
"Shift-2",
"10/12/2021, 9:00 AM",
"10/12/2021, 12:00 PM",
]);
await editPill("Shift-2");
expect(".o_field_widget[name=resource_id] input").toHaveValue("Jarvo");
});
test("auto plan on gantt view: default end_datetime should cover full range including last day", async function () {
mockTimeZone(0);
mockDate("2026-08-14 18:00:00");
const ranges = [
["Day", "2026-08-14 23:59:59"],
["Week", "2026-08-15 23:59:59"],
["Month", "2026-08-31 23:59:59"],
["Quarter", "2026-09-30 23:59:59"],
["Year", "2026-12-31 23:59:59"],
];
PlanningSlot._records.push({
id: 2,
name: "Slot to plan",
sale_line_id: 1,
resource_id: false,
});
let currentExpectedDate = null;
onRpc("auto_plan_ids", function (params) {
expect(params.kwargs.context.default_end_datetime).toBe(currentExpectedDate);
return { open_shift_assigned: [2] };
});
await mountGanttView({
resModel: "planning.slot",
arch: `
<gantt
js_class="planning_gantt"
date_start="start_datetime"
date_stop="end_datetime"
default_group_by="sale_line_id"
/>
`,
});
for (const [label, date] of ranges) {
currentExpectedDate = date;
await selectRange(label);
await click(".o_control_panel_main_buttons button > i.fa-caret-down");
await animationFrame();
await click(".o_gantt_button_auto_plan");
await animationFrame();
}
});