Files
odoo_source/addons/mail/static/src/models/user.js
T
Louis Wicket (wil) e16976ddfc [IMP] mail, *: move up model files
Move model definition files from `models/thing/thing.js` to
`models/thing.js` and remove the now empty intermediate directory.

Task-2759582
 * = calendar, crm_livechat, hr, im_livechat, mail_bot, sms, snailmail,
     website_livechat, website_slides

closes odoo/odoo#86464

Related: odoo/enterprise#25291
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
2022-03-17 11:27:59 +01:00

199 lines
6.8 KiB
JavaScript

/** @odoo-module **/
import { registerModel } from '@mail/model/model_core';
import { attr, one } from '@mail/model/model_field';
import { insert, unlink } from '@mail/model/model_field_command';
registerModel({
name: 'User',
identifyingFields: ['id'],
modelMethods: {
/**
* @param {Object} data
* @returns {Object}
*/
convertData(data) {
const data2 = {};
if ('id' in data) {
data2.id = data.id;
}
if ('partner_id' in data) {
if (!data.partner_id) {
data2.partner = unlink();
} else {
const partnerNameGet = data['partner_id'];
const partnerData = {
display_name: partnerNameGet[1],
id: partnerNameGet[0],
};
data2.partner = insert(partnerData);
}
}
return data2;
},
/**
* Performs the `read` RPC on `res.users`.
*
* @param {Object} param0
* @param {Object} param0.context
* @param {string[]} param0.fields
* @param {integer[]} param0.ids
*/
async performRpcRead({ context, fields, ids }) {
const usersData = await this.env.services.rpc({
model: 'res.users',
method: 'read',
args: [ids],
kwargs: {
context,
fields,
},
}, { shadow: true });
return this.messaging.models['User'].insert(usersData.map(userData =>
this.messaging.models['User'].convertData(userData)
));
},
},
recordMethods: {
/**
* Fetches the partner of this user.
*/
async fetchPartner() {
return this.messaging.models['User'].performRpcRead({
ids: [this.id],
fields: ['partner_id'],
context: { active_test: false },
});
},
/**
* Gets the chat between this user and the current user.
*
* If a chat is not appropriate, a notification is displayed instead.
*
* @returns {Thread|undefined}
*/
async getChat() {
if (!this.partner) {
await this.async(() => this.fetchPartner());
}
if (!this.partner) {
// This user has been deleted from the server or never existed:
// - Validity of id is not verified at insert.
// - There is no bus notification in case of user delete from
// another tab or by another user.
this.env.services['notification'].notify({
message: this.env._t("You can only chat with existing users."),
type: 'warning',
});
return;
}
// in other cases a chat would be valid, find it or try to create it
let chat = this.messaging.models['Thread'].find(thread =>
thread.channel_type === 'chat' &&
thread.correspondent === this.partner &&
thread.model === 'mail.channel' &&
thread.public === 'private'
);
if (!chat || !chat.isPinned) {
// if chat is not pinned then it has to be pinned client-side
// and server-side, which is a side effect of following rpc
chat = await this.async(() =>
this.messaging.models['Thread'].performRpcCreateChat({
partnerIds: [this.partner.id],
})
);
}
if (!chat) {
this.env.services['notification'].notify({
message: this.env._t("An unexpected error occurred during the creation of the chat."),
type: 'warning',
});
return;
}
return chat;
},
/**
* Opens a chat between this user and the current user and returns it.
*
* If a chat is not appropriate, a notification is displayed instead.
*
* @param {Object} [options] forwarded to @see `Thread:open()`
* @returns {Thread|undefined}
*/
async openChat(options) {
const chat = await this.async(() => this.getChat());
if (!chat) {
return;
}
await this.async(() => chat.open(options));
return chat;
},
/**
* Opens the most appropriate view that is a profile for this user.
* Because user is a rather technical model to allow login, it's the
* partner profile that contains the most useful information.
*
* @override
*/
async openProfile() {
if (!this.partner) {
await this.async(() => this.fetchPartner());
}
if (!this.partner) {
// This user has been deleted from the server or never existed:
// - Validity of id is not verified at insert.
// - There is no bus notification in case of user delete from
// another tab or by another user.
this.env.services['notification'].notify({
message: this.env._t("You can only open the profile of existing users."),
type: 'warning',
});
return;
}
return this.partner.openProfile();
},
/**
* @private
* @returns {string|undefined}
*/
_computeDisplayName() {
return this.display_name || this.partner && this.partner.display_name;
},
/**
* @private
* @returns {string|undefined}
*/
_computeNameOrDisplayName() {
return this.partner && this.partner.nameOrDisplayName || this.display_name;
},
},
fields: {
id: attr({
readonly: true,
required: true,
}),
/**
* Determines whether this user is an internal user. An internal user is
* a member of the group `base.group_user`. This is the inverse of the
* `share` field in python.
*/
isInternalUser: attr(),
display_name: attr({
compute: '_computeDisplayName',
}),
model: attr({
default: 'res.user',
}),
nameOrDisplayName: attr({
compute: '_computeNameOrDisplayName',
}),
partner: one('Partner', {
inverse: 'user',
}),
/**
* Id of this user's res.users.settings record.
*/
resUsersSettingsId: attr(),
},
});