mirror of
https://github.com/bringout/oca-ocb-report.git
synced 2026-04-22 15:21:59 +02:00
19.0 vanilla
This commit is contained in:
parent
62d197ac8b
commit
184bb0e321
667 changed files with 691406 additions and 239886 deletions
|
|
@ -0,0 +1,693 @@
|
|||
import {
|
||||
MockServer,
|
||||
defineActions,
|
||||
defineModels,
|
||||
fields,
|
||||
models,
|
||||
onRpc,
|
||||
serverState,
|
||||
webModels,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
import { RPCError } from "@web/core/network/rpc";
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param {{name: string, asc: boolean}[]} orderBy
|
||||
*
|
||||
* @returns { {definition: Object, columns: Array<Object>}}
|
||||
*/
|
||||
export function generateListDefinition(model, columns, actionXmlId, orderBy = []) {
|
||||
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",
|
||||
actionXmlId,
|
||||
},
|
||||
columns: cols,
|
||||
};
|
||||
}
|
||||
|
||||
export function getBasicListArchs() {
|
||||
return {
|
||||
"partner,false,list": getBasicListArch(),
|
||||
};
|
||||
}
|
||||
|
||||
function mockSpreadsheetDataController(_request, { res_model, res_id }) {
|
||||
const [record] = this.env[res_model].search_read([["id", "=", parseInt(res_id)]]);
|
||||
if (!record) {
|
||||
const error = new RPCError(`Spreadsheet ${res_id} does not exist`);
|
||||
error.data = {};
|
||||
throw error;
|
||||
}
|
||||
return {
|
||||
data: JSON.parse(record.spreadsheet_data),
|
||||
name: record.name,
|
||||
revisions: [],
|
||||
isReadonly: false,
|
||||
writable_rec_name_field: "name",
|
||||
};
|
||||
}
|
||||
|
||||
onRpc("/spreadsheet/data/<string:res_model>/<int:res_id>", mockSpreadsheetDataController);
|
||||
|
||||
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]],
|
||||
["name", "model"]
|
||||
);
|
||||
const result = [];
|
||||
for (const model of models) {
|
||||
const record = records.find((record) => record.model === model);
|
||||
if (record) {
|
||||
result.push({ model: model, display_name: record.name });
|
||||
} else {
|
||||
result.push({ model: model, display_name: model });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} modelNames
|
||||
*/
|
||||
has_searchable_parent_relation(modelNames) {
|
||||
return Object.fromEntries(modelNames.map((modelName) => [modelName, false]));
|
||||
}
|
||||
|
||||
get_available_models() {
|
||||
return this.env["ir.model"].search_read([], ["display_name", "model"]);
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 37,
|
||||
name: "Product",
|
||||
model: "product",
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
name: "Partner",
|
||||
model: "partner",
|
||||
},
|
||||
{
|
||||
id: 55,
|
||||
name: "Users",
|
||||
model: "res.users",
|
||||
},
|
||||
{
|
||||
id: 56,
|
||||
name: "Currency",
|
||||
model: "res.currency",
|
||||
},
|
||||
{
|
||||
id: 57,
|
||||
name: "Tag",
|
||||
model: "tag",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export class IrUIMenu extends models.Model {
|
||||
_name = "ir.ui.menu";
|
||||
|
||||
name = fields.Char({ string: "Name" });
|
||||
action = fields.Char({ string: "Action" });
|
||||
group_ids = 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" });
|
||||
group_ids = 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();
|
||||
display_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 ResCountry extends webModels.ResCountry {
|
||||
_name = "res.country";
|
||||
name = fields.Char({ string: "Country" });
|
||||
code = fields.Char({ string: "Code" });
|
||||
|
||||
_records = [
|
||||
{ id: 1, name: "Belgium", code: "BE" },
|
||||
{ id: 2, name: "France", code: "FR" },
|
||||
{ id: 3, name: "United States", code: "US" },
|
||||
];
|
||||
}
|
||||
|
||||
export class ResCountryState extends models.Model {
|
||||
_name = "res.country.state";
|
||||
name = fields.Char({ string: "Name" });
|
||||
code = fields.Char({ string: "Code" });
|
||||
country_id = fields.Many2one({ relation: "res.country" });
|
||||
display_name = fields.Char({ string: "Display Name" });
|
||||
|
||||
_records = [
|
||||
{ id: 1, name: "California", code: "CA", country_id: 3, display_name: "California (US)" },
|
||||
{ id: 2, name: "New York", code: "NY", country_id: 3, display_name: "New York (US)" },
|
||||
{ id: 3, name: "Texas", code: "TX", country_id: 3, display_name: "Texas (US)" },
|
||||
];
|
||||
}
|
||||
|
||||
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,
|
||||
name: "Raoul",
|
||||
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,
|
||||
name: "Steven",
|
||||
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,
|
||||
name: "Taylor",
|
||||
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,
|
||||
name: "Zara",
|
||||
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(),
|
||||
};
|
||||
}
|
||||
|
||||
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 });
|
||||
template_id = fields.Many2one({
|
||||
string: "Template",
|
||||
relation: "product",
|
||||
store: true,
|
||||
sortable: true,
|
||||
groupable: true,
|
||||
searchable: true,
|
||||
});
|
||||
properties_definitions = fields.PropertiesDefinition();
|
||||
pognon = fields.Monetary({
|
||||
string: "Money!",
|
||||
currency_field: "currency_id",
|
||||
store: true,
|
||||
sortable: true,
|
||||
aggregator: "avg",
|
||||
groupable: true,
|
||||
searchable: true,
|
||||
});
|
||||
currency_id = fields.Many2one({
|
||||
string: "Currency",
|
||||
relation: "res.currency",
|
||||
store: true,
|
||||
sortable: true,
|
||||
groupable: true,
|
||||
searchable: true,
|
||||
});
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 37,
|
||||
display_name: "xphone",
|
||||
name: "xphone",
|
||||
currency_id: 2,
|
||||
pognon: 699.99,
|
||||
},
|
||||
{
|
||||
id: 41,
|
||||
display_name: "xpad",
|
||||
template_id: 37,
|
||||
name: "xpad",
|
||||
currency_id: 2,
|
||||
pognon: 599.99,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
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,
|
||||
ResCountry,
|
||||
ResCountryState,
|
||||
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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue