Initial commit: Sale packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:49 +02:00
commit 14e3d26998
6469 changed files with 2479670 additions and 0 deletions

View file

@ -0,0 +1,127 @@
/** @odoo-module **/
import {
getFixture,
patchWithCleanup,
addRow,
editInput,
triggerHotkey,
nextTick
} from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { browser } from "@web/core/browser/browser";
let serverData;
let target;
QUnit.module("Fields", (hooks) => {
hooks.beforeEach(() => {
target = getFixture();
serverData = {
models: {
'sale.order': {
fields: {
display_name: { string: "Displayed name", type: "char" },
order_line: {
string: "order lines",
type: "one2many",
relation: "sale.order.line",
relation_field: "order_id",
},
},
records: [
{
id: 1,
display_name: "first record",
order_line: [],
},
],
onchanges: {},
},
'sale.order.line': {
fields: {
product_template_id: {
string: "Product",
type: "many2one",
relation: "product.template",
},
},
records: [
],
},
'product.template': {
fields: {
display_name: { string: "Partner Type", type: "char" },
name: { string: "Partner Type", type: "char" },
},
records: [
{ id: 12, display_name: "desk" },
],
methods: {
get_single_product_variant() {
return Promise.resolve({product_id: 12});
}
}
},
user: {
fields: {
name: { string: "Name", type: "char" },
partner_ids: {
string: "one2many partners field",
type: "one2many",
relation: "partner",
relation_field: "user_id",
},
},
records: [
],
},
},
};
setupViewRegistries();
patchWithCleanup(browser, {
setTimeout: (fn) => fn(),
});
});
QUnit.module("Sale product field");
QUnit.test("pressing tab with incomplete text will create a product", async function (assert) {
await makeView({
type: "form",
resModel: "sale.order",
serverData,
arch: `
<form>
<sheet>
<field name="order_line">
<tree editable="bottom" >
<field name="product_template_id" widget="sol_product_many2one" />
</tree>
</field>
</sheet>
</form>`,
mockRPC(route, args) {
assert.step(args.method);
}
});
// add a line and enter new product name
await addRow(target, ".o_field_x2many_list");
await editInput(target, "[name='product_template_id'] input", "new product");
await triggerHotkey("tab");
await nextTick();
assert.verifySteps([
"get_views",
"onchange",
"onchange",
"name_search",
"name_create",
"get_single_product_variant",
]);
});
});

View file

@ -0,0 +1,90 @@
/** @odoo-module **/
import { click, getFixture } from "@web/../tests/helpers/utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { registry } from "@web/core/registry";
const serviceRegistry = registry.category("services");
let serverData;
let target;
QUnit.module("Sales Team Dashboard", {
beforeEach() {
target = getFixture();
serverData = {
models: {
"crm.team": {
fields: {
foo: { string: "Foo", type: "char" },
invoiced: { string: "Invoiced", type: "integer" },
invoiced_target: { string: "Invoiced_target", type: "integer" },
},
records: [{ id: 1, foo: "yop", invoiced: 0, invoiced_target: 0 }],
},
},
};
setupViewRegistries();
},
});
QUnit.test("edit target with several o_kanban_primary_bottom divs", async (assert) => {
assert.expect(4);
const fakeActionService = {
start: () => ({
async doAction(action) {
assert.deepEqual(
action,
{
res_model: "crm.team",
target: "current",
type: "ir.actions.act_window",
method: "get_formview_action",
},
"should trigger do_action with the correct args"
);
return true;
},
}),
};
serviceRegistry.add("action", fakeActionService, { force: true });
await makeView({
serverData,
type: "kanban",
resModel: "crm.team",
arch: /* xml */`
<kanban>
<field name="invoiced_target"/>
<templates>
<div t-name="kanban-box" class="container o_kanban_card_content">
<field name="invoiced" widget="sales_team_progressbar" options="{'current_value': 'invoiced', 'max_value': 'invoiced_target', 'editable': true, 'edit_max_value': true}"/>
<div class="col-12 o_kanban_primary_bottom"/>
<div class="col-12 o_kanban_primary_bottom bottom_block"/>
</div>
</templates>
</kanban>`,
resId: 1,
async mockRPC(route, { method, model }) {
if (route === "/web/dataset/call_kw/crm.team/get_formview_action") {
return {
method,
res_model: model,
target: "current",
type: "ir.actions.act_window",
};
}
},
});
assert.containsOnce(
target,
".o_field_sales_team_progressbar:contains(Click to define an invoicing target)"
);
assert.containsN(target, ".o_kanban_primary_bottom", 2);
assert.containsNone(target, ".o_progressbar input");
await click(target, ".sale_progressbar_form_link"); // should trigger a do_action
});

View file

@ -0,0 +1,51 @@
odoo.define('sale.tour_sale_signature', function (require) {
'use strict';
var tour = require('web_tour.tour');
// This tour relies on data created on the Python test.
tour.register('sale_signature', {
test: true,
url: '/my/quotes',
},
[
{
content: "open the test SO",
trigger: 'a:containsExact("test SO")',
},
{
content: "click sign",
trigger: 'a:contains("Sign")',
},
{
content: "check submit is enabled",
trigger: '.o_portal_sign_submit:enabled',
run: function () {},
},
{
content: "click select style",
trigger: '.o_web_sign_auto_select_style a',
},
{
content: "click style 4",
trigger: '.o_web_sign_auto_font_selection a:eq(3)',
},
{
content: "click submit",
trigger: '.o_portal_sign_submit:enabled',
},
{
content: "check it's confirmed",
trigger: '#quote_content:contains("Thank You")',
}, {
trigger: '#quote_content',
run: function () {
window.location.href = window.location.origin + '/web';
}, // Avoid race condition at the end of the tour by returning to the home page.
},
{
trigger: 'nav',
run: function() {},
}
]);
});