Odoo18-Base/addons/spreadsheet/static/tests/helpers/data.js
2025-03-04 12:23:19 +07:00

584 lines
14 KiB
JavaScript

import {
MockServer,
defineActions,
defineModels,
fields,
models,
serverState,
webModels,
} from "@web/../tests/web_test_helpers";
import { mailModels } from "@mail/../tests/mail_test_helpers";
/**
* @typedef {object} ServerData
* @property {object} [models]
* @property {object} [views]
* @property {object} [menus]
* @property {object} [actions]
*/
/**
* Get a basic arch for a pivot, which is compatible with the data given by
* getBasicData().
*
* Here is the pivot created:
* A B C D E F
* 1 1 2 12 17 Total
* 2 Proba Proba Proba Proba Proba
* 3 false 15 15
* 4 true 11 10 95 116
* 5 Total 11 15 10 95 131
*/
export function getBasicPivotArch() {
return /* xml */ `
<pivot string="Partners">
<field name="foo" type="col"/>
<field name="bar" type="row"/>
<field name="probability" type="measure"/>
</pivot>`;
}
/**
* Get a basic arch for a list, which is compatible with the data given by
* getBasicData().
*
* Here is the list created:
* A B C D
* 1 Foo bar Date Product
* 2 12 True 2016-04-14 xphone
* 3 1 True 2016-10-26 xpad
* 4 17 True 2016-12-15 xpad
* 5 2 False 2016-12-11 xpad
*/
export function getBasicListArch() {
return /* xml */ `
<list string="Partners">
<field name="foo"/>
<field name="bar"/>
<field name="date"/>
<field name="product_id"/>
</list>
`;
}
export function getBasicGraphArch() {
return /* xml */ `
<graph string="PartnerGraph">
<field name="bar" />
</graph>
`;
}
/**
* @returns {ServerData}
*/
export function getBasicServerData() {
return {
models: getBasicData(),
views: {},
};
}
/**
*
* @param {string} model
* @param {Array<string>} columns
*
* @returns { {definition: Object, columns: Array<Object>}}
*/
export function generateListDefinition(model, columns) {
const cols = [];
for (const name of columns) {
const PyModel = Object.values(SpreadsheetModels).find((m) => m._name === model);
cols.push({
name,
type: PyModel._fields[name].type,
});
}
return {
definition: {
metaData: {
resModel: model,
columns,
},
searchParams: {
domain: [],
context: {},
orderBy: [],
},
name: "List",
},
columns: cols,
};
}
export function getBasicListArchs() {
return {
"partner,false,list": getBasicListArch(),
"partner,false,search": /* xml */ `<search/>`,
"partner,false,form": /* xml */ `<form/>`,
};
}
export function defineSpreadsheetModels() {
defineModels(SpreadsheetModels);
}
export function defineSpreadsheetActions() {
defineActions([
{
id: 1,
name: "partner Action",
res_model: "partner",
xml_id: "spreadsheet.partner_action",
views: [
[false, "list"],
[false, "pivot"],
[false, "graph"],
[false, "search"],
[false, "form"],
],
},
]);
}
export class IrModel extends webModels.IrModel {
display_name_for(models) {
const records = this.env["ir.model"].search_read([["model", "in", models]]);
return records.map((record) => ({
model: record.model,
display_name: record.name,
}));
}
_records = [
{
id: 37,
name: "Product",
model: "product",
},
{
id: 40,
name: "Partner",
model: "partner",
},
{
id: 55,
name: "Users",
model: "res.users",
},
];
}
export class IrUIMenu extends models.Model {
_name = "ir.ui.menu";
name = fields.Char({ string: "Name" });
action = fields.Char({ string: "Action" });
groups_id = fields.Many2many({ string: "Groups", relation: "res.group" });
}
export class IrActions extends models.Model {
_name = "ir.actions";
}
export class ResGroup extends models.Model {
_name = "res.group";
name = fields.Char({ string: "Name" });
}
export class ResUsers extends mailModels.ResUsers {
_name = "res.users";
name = fields.Char({ string: "Name" });
groups_id = fields.Many2many({ string: "Groups", relation: "res.group" });
}
export class SpreadsheetMixin extends models.Model {
_name = "spreadsheet.mixin";
spreadsheet_binary_data = fields.Binary({ string: "Spreadsheet file" });
spreadsheet_data = fields.Text();
thumbnail = fields.Binary();
get_display_names_for_spreadsheet(args) {
const result = [];
for (const { model, id } of args) {
const record = this.env[model].search_read([["id", "=", id]])[0];
result.push(record?.display_name ?? null);
}
return result;
}
get_selector_spreadsheet_models() {
return [
{
model: "documents.document",
display_name: "Spreadsheets",
allow_create: true,
},
];
}
}
export class ResCurrency extends models.Model {
_name = "res.currency";
name = fields.Char({ string: "Code" });
symbol = fields.Char({ string: "Symbol" });
position = fields.Selection({
string: "Position",
selection: [
["after", "A"],
["before", "B"],
],
});
decimal_places = fields.Integer({ string: "decimal" });
get_company_currency_for_spreadsheet() {
return {
code: "EUR",
symbol: "€",
position: "after",
decimalPlaces: 2,
};
}
_records = [
{
id: 1,
name: "EUR",
symbol: "€",
position: "after",
decimal_places: 2,
},
{
id: 2,
name: "USD",
symbol: "$",
position: "before",
decimal_places: 2,
},
];
}
export class Partner extends models.Model {
_name = "partner";
foo = fields.Integer({
string: "Foo",
store: true,
searchable: true,
aggregator: "sum",
groupable: false,
});
bar = fields.Boolean({
string: "Bar",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
name = fields.Char({
string: "name",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
date = fields.Date({
string: "Date",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
create_date = fields.Datetime({
string: "Creation Date",
store: true,
sortable: true,
groupable: true,
});
active = fields.Boolean({
string: "Active",
default: true,
searchable: true,
groupable: false,
});
product_id = fields.Many2one({
string: "Product",
relation: "product",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
tag_ids = fields.Many2many({
string: "Tags",
relation: "tag",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
probability = fields.Float({
string: "Probability",
searchable: true,
store: true,
aggregator: "avg",
groupable: false,
});
field_with_array_agg = fields.Integer({
string: "field_with_array_agg",
searchable: true,
groupable: false,
aggregator: "array_agg",
});
currency_id = fields.Many2one({
string: "Currency",
relation: "res.currency",
store: true,
sortable: true,
groupable: true,
searchable: true,
});
pognon = fields.Monetary({
string: "Money!",
currency_field: "currency_id",
store: true,
sortable: true,
aggregator: "avg",
groupable: true,
searchable: true,
});
partner_properties = fields.Properties({
string: "Properties",
store: true,
sortable: true,
groupable: true,
searchable: true,
definition_record: "product_id",
definition_record_field: "properties_definitions",
});
jsonField = fields.Json({ string: "Json Field", store: true, groupable: false });
user_ids = fields.Many2many({
relation: "res.users",
string: "Users",
searchable: true,
groupable: false,
});
_records = [
{
id: 1,
foo: 12,
bar: true,
date: "2016-04-14",
create_date: "2016-04-03 00:00:00",
product_id: 37,
probability: 10,
field_with_array_agg: 1,
tag_ids: [42, 67],
currency_id: 1,
pognon: 74.4,
},
{
id: 2,
foo: 1,
bar: true,
date: "2016-10-26",
create_date: "2014-04-03 00:05:32",
product_id: 41,
probability: 11,
field_with_array_agg: 2,
tag_ids: [42, 67],
currency_id: 2,
pognon: 74.8,
},
{
id: 3,
foo: 17,
bar: true,
date: "2016-12-15",
create_date: "2006-01-03 11:30:50",
product_id: 41,
probability: 95,
field_with_array_agg: 3,
tag_ids: [],
currency_id: 1,
pognon: 4,
},
{
id: 4,
foo: 2,
bar: false,
date: "2016-12-11",
create_date: "2016-12-10 21:59:59",
product_id: 41,
probability: 15,
field_with_array_agg: 4,
tag_ids: [42],
currency_id: 2,
pognon: 1000,
},
];
// TODO: check which views are actually needed in the tests
_views = {
list: getBasicListArch(),
pivot: getBasicPivotArch(),
graph: getBasicGraphArch(),
form: /* xml */ `<Form/>`,
search: /* xml */ `<search/>`,
};
}
export class Product extends models.Model {
_name = "product";
name = fields.Char({ string: "Product Name" });
display_name = fields.Char({ string: "Product Name" });
active = fields.Boolean({ string: "Active", default: true });
properties_definitions = fields.PropertiesDefinition();
_records = [
{
id: 37,
display_name: "xphone",
name: "xphone",
},
{
id: 41,
display_name: "xpad",
name: "xpad",
},
];
}
export class Tag extends models.Model {
_name = "tag";
name = fields.Char({ string: "Tag Name" });
_records = [
{
id: 42,
name: "isCool",
},
{
id: 67,
name: "Growing",
},
];
}
export function getBasicData() {
return {
"documents.document": {},
"ir.model": {},
"ir.embedded.actions": {},
"documents.tag": {},
"spreadsheet.template": {},
"res.currency": {},
"res.users": {},
partner: {},
product: {},
tag: {},
};
}
export const SpreadsheetModels = {
...webModels,
...mailModels,
IrModel,
IrUIMenu,
IrActions,
ResGroup,
ResUsers,
SpreadsheetMixin,
ResCurrency,
Partner,
Product,
Tag,
};
/**
* Add the records inside serverData in the MockServer
*
* @param {ServerData} serverData
*/
export function addRecordsFromServerData(serverData) {
for (const modelName of Object.keys(serverData.models)) {
const records = serverData.models[modelName].records;
if (!records) {
continue;
}
const PyModel = getSpreadsheetModel(modelName);
if (!PyModel) {
throw new Error(`Model ${modelName} not found inside SpreadsheetModels`);
}
checkRecordsValidity(modelName, records);
PyModel._records = records;
}
}
/**
* Add the views inside serverData in the MockServer
*
* @param {ServerData} serverData
*
* @example
* addViewsFromServerData({ "partner,false,search": "<search/>" });
* Will set the default search view for the partner model
*/
export function addViewsFromServerData(serverData) {
for (const fullViewKey of Object.keys(serverData.views)) {
const viewArch = serverData.views[fullViewKey];
const splitted = fullViewKey.split(",");
const modelName = splitted[0];
const viewType = splitted[2];
const recordId = splitted[1];
const PyModel = getSpreadsheetModel(modelName);
if (!PyModel) {
throw new Error(`Model ${modelName} not found inside SpreadsheetModels`);
}
const viewKey = viewType + "," + recordId;
PyModel._views[viewKey] = viewArch;
}
}
/**
* Check if the records are valid.
* This is mainly to avoid the mail's service crashing if the res.users are not correctly set.
*/
function checkRecordsValidity(modelName, records) {
if (modelName === "res.users") {
const serverUserId = serverState.userId;
const currentUser = records.find((record) => record.id === serverUserId);
if (!currentUser) {
throw new Error(
`The current user (${serverUserId}) is not in the records. did you forget to set serverState.userId ?`
);
}
if (!currentUser.active) {
throw new Error(`The current user (${serverUserId}) is not active`);
}
if (!currentUser.partner_id) {
throw new Error(
`The current user (${serverUserId}) has no partner_id. It should be set to serverState.partnerId`
);
}
}
}
export function getPyEnv() {
const mockServer = MockServer.current;
if (!mockServer) {
throw new Error("No mock server found");
}
return mockServer.env;
}
export function getSpreadsheetModel(modelName) {
return Object.values(SpreadsheetModels).find((model) => model._name === modelName);
}