[REF] mail: use tracking models rather than fields
Introducing tracking_value and tracking_value_item models for tracking value. task-2817111 closes odoo/odoo#88547 Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -844,20 +844,6 @@ class Message(models.Model):
|
||||
else:
|
||||
author = (0, message_sudo.email_from)
|
||||
|
||||
# Tracking values
|
||||
tracking_value_ids = []
|
||||
for tracking in message_sudo.tracking_value_ids:
|
||||
groups = tracking.field_groups
|
||||
if not groups or self.env.is_superuser() or self.user_has_groups(groups):
|
||||
tracking_value_ids.append({
|
||||
'id': tracking.id,
|
||||
'changed_field': tracking.field_desc,
|
||||
'old_value': tracking.get_old_display_value()[0],
|
||||
'new_value': tracking.get_new_display_value()[0],
|
||||
'field_type': tracking.field_type,
|
||||
'currency_id': tracking.currency_id.id,
|
||||
})
|
||||
|
||||
if message_sudo.model and message_sudo.res_id:
|
||||
record_name = self.env[message_sudo.model] \
|
||||
.browse(message_sudo.res_id) \
|
||||
@@ -886,10 +872,11 @@ class Message(models.Model):
|
||||
} for content, reactions in reactions_per_content.items()])]
|
||||
if format_reply and message_sudo.model == 'mail.channel' and message_sudo.parent_id:
|
||||
vals['parentMessage'] = message_sudo.parent_id.message_format(format_reply=False)[0]
|
||||
allowed_tracking_ids = message_sudo.tracking_value_ids.filtered(lambda tracking: not tracking.field_groups or self.env.is_superuser() or self.user_has_groups(tracking.field_groups))
|
||||
vals.update({
|
||||
'notifications': message_sudo.notification_ids._filtered_for_web_client()._notification_format(),
|
||||
'attachment_ids': message_sudo.attachment_ids._attachment_format(),
|
||||
'tracking_value_ids': tracking_value_ids,
|
||||
'trackingValues': [('insert-and-replace', allowed_tracking_ids._tracking_value_format())],
|
||||
'messageReactionGroups': reaction_groups,
|
||||
'record_name': record_name,
|
||||
})
|
||||
@@ -930,12 +917,20 @@ class Message(models.Model):
|
||||
],
|
||||
'needaction_partner_ids': [], # list of partner ids
|
||||
'res_id': 7,
|
||||
'tracking_value_ids': [
|
||||
'trackingValues': [('insert-and-replace',
|
||||
{
|
||||
'old_value': "",
|
||||
'changed_field': "Customer",
|
||||
'changedField': "Customer",
|
||||
'id': 2965,
|
||||
'new_value': "Axelor"
|
||||
'newValue': [('insert-and-replace', {
|
||||
'currencyId': "",
|
||||
'fieldType': 'char',
|
||||
'value': "Axelor",
|
||||
})],
|
||||
'oldValue': [('insert-and-replace', {
|
||||
'currencyId': "",
|
||||
'fieldType': 'char',
|
||||
'value': "",
|
||||
})],
|
||||
}
|
||||
],
|
||||
'author_id': (3, u'Administrator'),
|
||||
|
||||
@@ -2580,8 +2580,8 @@ class MailThread(models.AbstractModel):
|
||||
groups = tracking_value.field_groups
|
||||
if not groups or self.env.is_superuser() or self.user_has_groups(groups):
|
||||
tracking.append((tracking_value.field_desc,
|
||||
tracking_value.get_old_display_value()[0],
|
||||
tracking_value.get_new_display_value()[0]))
|
||||
tracking_value._get_old_display_value()[0],
|
||||
tracking_value._get_new_display_value()[0]))
|
||||
|
||||
subtype_id = msg_vals.get('subtype_id') if msg_vals and 'subtype_id' in msg_vals else message.subtype_id.id
|
||||
is_discussion = subtype_id == self.env['ir.model.data']._xmlid_to_res_id('mail.mt_comment')
|
||||
|
||||
@@ -88,34 +88,49 @@ class MailTracking(models.Model):
|
||||
return values
|
||||
return {}
|
||||
|
||||
def get_display_value(self, type):
|
||||
assert type in ('new', 'old')
|
||||
def _tracking_value_format(self):
|
||||
tracking_values = [{
|
||||
'changedField': tracking.field_desc,
|
||||
'id': tracking.id,
|
||||
'newValue': [('insert-and-replace', {
|
||||
'currencyId': tracking.currency_id.id,
|
||||
'fieldType': tracking.field_type,
|
||||
'value': tracking._get_new_display_value()[0]})],
|
||||
'oldValue': [('insert-and-replace', {
|
||||
'currencyId': tracking.currency_id.id,
|
||||
'fieldType': tracking.field_type,
|
||||
'value': tracking._get_old_display_value()[0]})],
|
||||
} for tracking in self]
|
||||
return tracking_values
|
||||
|
||||
def _get_display_value(self, prefix):
|
||||
assert prefix in ('new', 'old')
|
||||
result = []
|
||||
for record in self:
|
||||
if record.field_type in ['integer', 'float', 'char', 'text', 'monetary']:
|
||||
result.append(getattr(record, '%s_value_%s' % (type, record.field_type)))
|
||||
result.append(record[f'{prefix}_value_{record.field_type}'])
|
||||
elif record.field_type == 'datetime':
|
||||
if record['%s_value_datetime' % type]:
|
||||
new_datetime = getattr(record, '%s_value_datetime' % type)
|
||||
result.append('%sZ' % new_datetime)
|
||||
if record[f'{prefix}_value_datetime']:
|
||||
new_datetime = record[f'{prefix}_value_datetime']
|
||||
result.append(f'{new_datetime}Z')
|
||||
else:
|
||||
result.append(record['%s_value_datetime' % type])
|
||||
result.append(record[f'{prefix}_value_datetime'])
|
||||
elif record.field_type == 'date':
|
||||
if record['%s_value_datetime' % type]:
|
||||
new_date = record['%s_value_datetime' % type]
|
||||
if record[f'{prefix}_value_datetime']:
|
||||
new_date = record[f'{prefix}_value_datetime']
|
||||
result.append(fields.Date.to_string(new_date))
|
||||
else:
|
||||
result.append(record['%s_value_datetime' % type])
|
||||
result.append(record[f'{prefix}_value_datetime'])
|
||||
elif record.field_type == 'boolean':
|
||||
result.append(bool(record['%s_value_integer' % type]))
|
||||
result.append(bool(record[f'{prefix}_value_integer']))
|
||||
else:
|
||||
result.append(record['%s_value_char' % type])
|
||||
result.append(record[f'{prefix}_value_char'])
|
||||
return result
|
||||
|
||||
def get_old_display_value(self):
|
||||
def _get_old_display_value(self):
|
||||
# grep : # old_value_integer | old_value_datetime | old_value_char
|
||||
return self.get_display_value('old')
|
||||
return self._get_display_value('old')
|
||||
|
||||
def get_new_display_value(self):
|
||||
def _get_new_display_value(self):
|
||||
# grep : # new_value_integer | new_value_datetime | new_value_char
|
||||
return self.get_display_value('new')
|
||||
return self._get_display_value('new')
|
||||
|
||||
@@ -147,8 +147,10 @@
|
||||
</t>
|
||||
<t t-if="messageView.message.trackingValues.length > 0">
|
||||
<ul class="o_Message_trackingValues mt-2">
|
||||
<t t-foreach="messageView.message.trackingValues" t-as="value" t-key="value.id">
|
||||
<TrackingValue value="value"/>
|
||||
<t t-foreach="messageView.message.trackingValues" t-as="trackingValue" t-key="trackingValue.id">
|
||||
<li>
|
||||
<TrackingValue value="trackingValue"/>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
@@ -4,7 +4,16 @@ import { registerMessagingComponent } from '@mail/utils/messaging_component';
|
||||
|
||||
const { Component } = owl;
|
||||
|
||||
export class TrackingValue extends Component {}
|
||||
export class TrackingValue extends Component {
|
||||
|
||||
/**
|
||||
* @returns {TrackingValue}
|
||||
*/
|
||||
get trackingValue() {
|
||||
return this.props.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign(TrackingValue, {
|
||||
props: { value: Object },
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
.o_TrackingValue_item {
|
||||
// Could be replaced by "me-1" after the migration to BS5
|
||||
// for the backend AND the frontend
|
||||
margin-inline-end: map-get($spacers, 1);
|
||||
}
|
||||
@@ -1,21 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="mail.TrackingValue" owl="1">
|
||||
<li class="o_TrackingValue" t-attf-class="{{ className }}" t-ref="root">
|
||||
<div class="o_TrackingValue_container d-flex align-items-center flex-wrap">
|
||||
<div class="o_TrackingValue_fieldName o_TrackingValue_item" t-esc="props.value.changed_field"/>
|
||||
<t t-if="props.value.old_value">
|
||||
<div class="o_TrackingValue_oldValue o_TrackingValue_item" t-esc="props.value.old_value"/>
|
||||
</t>
|
||||
<i t-else="" class="mr-2">None</i>
|
||||
<div class="o_TrackingValue_separator o_TrackingValue_item fa fa-long-arrow-right" title="Changed" role="img"/>
|
||||
<t t-if="props.value.new_value">
|
||||
<div class="o_TrackingValue_newValue o_TrackingValue_item" t-esc="props.value.new_value"/>
|
||||
</t>
|
||||
<i t-else="">None</i>
|
||||
</div>
|
||||
</li>
|
||||
<div class="o_TrackingValue d-inline-block d-flex align-items-center flex-wrap" t-attf-class="{{ className }}" t-ref="root">
|
||||
<span class="o_TrackingValue_fieldName mr-1" t-esc="trackingValue.formattedChangedField"/>
|
||||
<span class="o_TrackingValue_oldValue mr-1" t-esc="trackingValue.oldValue.formattedValueOrNone" t-att-class="{ 'font-italic': !trackingValue.oldValue.formattedValue }"/>
|
||||
<i class="o_TrackingValue_separator fa fa-long-arrow-right mx-1" title="Changed" role="img"/>
|
||||
<span class="o_TrackingValue_newValue mr-1" t-esc="trackingValue.newValue.formattedValueOrNone" t-att-class="{ 'font-italic': !trackingValue.newValue.formattedValue }"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
</templates>
|
||||
|
||||
@@ -7,9 +7,7 @@ import emojis from '@mail/js/emojis';
|
||||
import { addLink, htmlToTextContentInline, parseAndTransform } from '@mail/js/utils';
|
||||
|
||||
import { session } from '@web/session';
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
import { format } from 'web.field_utils';
|
||||
import { getLangDatetimeFormat, str_to_datetime } from 'web.time';
|
||||
|
||||
const { markup } = owl;
|
||||
@@ -125,8 +123,8 @@ registerModel({
|
||||
if ('subtype_id' in data) {
|
||||
data2.subtype_id = data.subtype_id;
|
||||
}
|
||||
if ('tracking_value_ids' in data) {
|
||||
data2.tracking_value_ids = data.tracking_value_ids;
|
||||
if ('trackingValues' in data) {
|
||||
data2.trackingValues = data.trackingValues;
|
||||
}
|
||||
|
||||
return data2;
|
||||
@@ -333,7 +331,7 @@ registerModel({
|
||||
if (!this.originThread) {
|
||||
return false;
|
||||
}
|
||||
if (this.tracking_value_ids.length > 0) {
|
||||
if (this.trackingValues.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.message_type !== 'comment') {
|
||||
@@ -479,7 +477,7 @@ registerModel({
|
||||
return (
|
||||
this.isBodyEmpty &&
|
||||
!this.hasAttachments &&
|
||||
this.tracking_value_ids.length === 0 &&
|
||||
this.trackingValues.length === 0 &&
|
||||
!this.subtype_description
|
||||
);
|
||||
},
|
||||
@@ -599,88 +597,6 @@ registerModel({
|
||||
}
|
||||
return replace(threads);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
_computeTrackingValues() {
|
||||
return this.tracking_value_ids.map(trackingValue => {
|
||||
const value = Object.assign({}, trackingValue);
|
||||
value.changed_field = sprintf(this.env._t("%s:"), value.changed_field);
|
||||
/**
|
||||
* Maps tracked field type to a JS formatter. Tracking values are
|
||||
* not always stored in the same field type as their origin type.
|
||||
* Field types that are not listed here are not supported by
|
||||
* tracking in Python. Also see `create_tracking_values` in Python.
|
||||
*/
|
||||
switch (value.field_type) {
|
||||
case 'boolean':
|
||||
value.old_value = value.old_value ? this.env._t('Yes') : this.env._t('No');
|
||||
value.new_value = value.new_value ? this.env._t('Yes') : this.env._t('No');
|
||||
break;
|
||||
/**
|
||||
* many2one formatter exists but is expecting id/name_get or data
|
||||
* object but only the target record name is known in this context.
|
||||
*
|
||||
* Selection formatter exists but requires knowing all
|
||||
* possibilities and they are not given in this context.
|
||||
*/
|
||||
case 'char':
|
||||
case 'many2one':
|
||||
case 'selection':
|
||||
value.old_value = format.char(value.old_value);
|
||||
value.new_value = format.char(value.new_value);
|
||||
break;
|
||||
case 'date':
|
||||
if (value.old_value) {
|
||||
value.old_value = moment.utc(value.old_value);
|
||||
}
|
||||
if (value.new_value) {
|
||||
value.new_value = moment.utc(value.new_value);
|
||||
}
|
||||
value.old_value = format.date(value.old_value);
|
||||
value.new_value = format.date(value.new_value);
|
||||
break;
|
||||
case 'datetime':
|
||||
if (value.old_value) {
|
||||
value.old_value = moment.utc(value.old_value);
|
||||
}
|
||||
if (value.new_value) {
|
||||
value.new_value = moment.utc(value.new_value);
|
||||
}
|
||||
value.old_value = format.datetime(value.old_value);
|
||||
value.new_value = format.datetime(value.new_value);
|
||||
break;
|
||||
case 'float':
|
||||
value.old_value = format.float(value.old_value);
|
||||
value.new_value = format.float(value.new_value);
|
||||
break;
|
||||
case 'integer':
|
||||
value.old_value = format.integer(value.old_value);
|
||||
value.new_value = format.integer(value.new_value);
|
||||
break;
|
||||
case 'monetary':
|
||||
value.old_value = format.monetary(value.old_value, undefined, {
|
||||
currency: value.currency_id
|
||||
? this.env.session.currencies[value.currency_id]
|
||||
: undefined,
|
||||
forceString: true,
|
||||
});
|
||||
value.new_value = format.monetary(value.new_value, undefined, {
|
||||
currency: value.currency_id
|
||||
? this.env.session.currencies[value.currency_id]
|
||||
: undefined,
|
||||
forceString: true,
|
||||
});
|
||||
break;
|
||||
case 'text':
|
||||
value.old_value = format.text(value.old_value);
|
||||
value.new_value = format.text(value.new_value);
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
});
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
authorName: attr({
|
||||
@@ -922,11 +838,9 @@ registerModel({
|
||||
compute: '_computeThreads',
|
||||
inverse: 'messages',
|
||||
}),
|
||||
trackingValues: attr({
|
||||
compute: '_computeTrackingValues',
|
||||
}),
|
||||
tracking_value_ids: attr({
|
||||
default: [],
|
||||
trackingValues: many('TrackingValue', {
|
||||
inverse: 'messageOwner',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { attr, one } from '@mail/model/model_field';
|
||||
import { sprintf } from '@web/core/utils/strings';
|
||||
|
||||
registerModel({
|
||||
name: 'TrackingValue',
|
||||
identifyingFields: ['id'],
|
||||
recordMethods: {
|
||||
/**
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
_computeFormattedChangedField() {
|
||||
return sprintf(this.env._t("%s:"), this.changedField);
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
/**
|
||||
* States the original field of changed tracking value, such as "Status", "Date".
|
||||
*/
|
||||
changedField: attr({
|
||||
required: true,
|
||||
}),
|
||||
/**
|
||||
* The translated `changedFiled` according to the language setting.
|
||||
*/
|
||||
formattedChangedField: attr({
|
||||
compute: '_computeFormattedChangedField',
|
||||
}),
|
||||
id: attr({
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
messageOwner: one('Message', {
|
||||
inverse: 'trackingValues',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
newValue: one('TrackingValueItem', {
|
||||
inverse: 'trackingValueAsNewValue',
|
||||
isCausal: true,
|
||||
}),
|
||||
oldValue: one('TrackingValueItem', {
|
||||
inverse: 'trackingValueAsOldValue',
|
||||
isCausal: true,
|
||||
}),
|
||||
}});
|
||||
@@ -0,0 +1,100 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerModel } from '@mail/model/model_core';
|
||||
import { attr, one } from '@mail/model/model_field';
|
||||
|
||||
import { format } from 'web.field_utils';
|
||||
|
||||
registerModel({
|
||||
name: 'TrackingValueItem',
|
||||
identifyingFields: [['trackingValueAsNewValue','trackingValueAsOldValue']],
|
||||
recordMethods: {
|
||||
/**
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
_computeFormattedValue() {
|
||||
/**
|
||||
* Maps tracked field type to a JS formatter. Tracking values are
|
||||
* not always stored in the same field type as their origin type.
|
||||
* Field types that are not listed here are not supported by
|
||||
* tracking in Python. Also see `create_tracking_values` in Python.
|
||||
*/
|
||||
switch (this.fieldType) {
|
||||
case 'boolean':
|
||||
return this.value ? this.env._t("Yes") : this.env._t("No");
|
||||
/**
|
||||
* many2one formatter exists but is expecting id/name_get or data
|
||||
* object but only the target record name is known in this context.
|
||||
*
|
||||
* Selection formatter exists but requires knowing all
|
||||
* possibilities and they are not given in this context.
|
||||
*/
|
||||
case 'char':
|
||||
case 'many2one':
|
||||
case 'selection':
|
||||
return format.char(this.value);
|
||||
case 'date':
|
||||
if (this.value) {
|
||||
return format.date(moment.utc(this.value));
|
||||
}
|
||||
return format.date(this.value);
|
||||
case 'datetime':
|
||||
if (this.value) {
|
||||
return format.datetime(moment.utc(this.value));
|
||||
}
|
||||
return format.datetime(this.value);
|
||||
case 'float':
|
||||
return format.float(this.value);
|
||||
case 'integer':
|
||||
return format.integer(this.value);
|
||||
case 'text':
|
||||
return format.text(this.value);
|
||||
case 'monetary':
|
||||
return format.monetary(this.value, undefined, {
|
||||
currency: this.currencyId
|
||||
? this.env.session.currencies[this.currencyId]
|
||||
: undefined,
|
||||
forceString: true,
|
||||
});
|
||||
default :
|
||||
return this.value;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
_computeFormattedValueOrNone() {
|
||||
return this.formattedValue || this.env._t("None");
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
/**
|
||||
* Used when the currency changes as the tracking value. This only makes sense for field of type monetary.
|
||||
*/
|
||||
currencyId: attr(),
|
||||
/**
|
||||
* Indicates the type of the tracking value item.
|
||||
* The supported types are: boolean, char, many2one, selection, date, datetime, float, integer, text, monetary.
|
||||
*/
|
||||
fieldType: attr(),
|
||||
formattedValue: attr({
|
||||
compute: '_computeFormattedValue',
|
||||
}),
|
||||
formattedValueOrNone: attr({
|
||||
compute: '_computeFormattedValueOrNone',
|
||||
}),
|
||||
trackingValueAsNewValue: one('TrackingValue', {
|
||||
inverse: 'newValue',
|
||||
readonly: true,
|
||||
}),
|
||||
trackingValueAsOldValue: one('TrackingValue', {
|
||||
inverse: 'oldValue',
|
||||
readonly: true,
|
||||
}),
|
||||
/**
|
||||
* The original value of the tracking value item.
|
||||
*/
|
||||
value: attr(),
|
||||
}});
|
||||
@@ -1515,13 +1515,7 @@ MockServer.include({
|
||||
const trackingValueIds = this.getRecords('mail.tracking.value', [
|
||||
['id', 'in', message.tracking_value_ids],
|
||||
]);
|
||||
const formattedTrackingValues = trackingValueIds.map(tracking => ({
|
||||
changed_field: tracking.field_desc,
|
||||
field_type: tracking.field_type,
|
||||
id: tracking.id,
|
||||
new_value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'new'),
|
||||
old_value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'old'),
|
||||
}));
|
||||
const formattedTrackingValues = [['insert-and-replace', this._mockMailTrackingValue_TrackingValueFormat(trackingValueIds)]];
|
||||
const partners = this.getRecords(
|
||||
'res.partner',
|
||||
[['id', 'in', message.partner_ids]],
|
||||
@@ -1535,7 +1529,7 @@ MockServer.include({
|
||||
parentMessage: message.parent_id ? this._mockMailMessageMessageFormat([message.parent_id])[0] : false,
|
||||
recipients: partners.map(p => ({ id: p.id, name: p.name })),
|
||||
record_name: thread && (thread.name !== undefined ? thread.name : thread.display_name),
|
||||
tracking_value_ids: formattedTrackingValues,
|
||||
trackingValues: formattedTrackingValues,
|
||||
});
|
||||
if (message.subtype_id) {
|
||||
const subtype = this.getRecords('mail.message.subtype', [
|
||||
@@ -2087,7 +2081,25 @@ MockServer.include({
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* Simulates `get_display_value` on `mail.tracking.value`
|
||||
* Simulates `_tracking_value_format` on `mail.tracking.value`
|
||||
*/
|
||||
_mockMailTrackingValue_TrackingValueFormat(tracking_value_ids) {
|
||||
const trackingValues = tracking_value_ids.map(tracking => ({
|
||||
changedField: tracking.field_desc,
|
||||
id: tracking.id,
|
||||
newValue: [['insert-and-replace', {
|
||||
fieldType: tracking.field_type,
|
||||
value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'new')
|
||||
}]],
|
||||
oldValue: [['insert-and-replace', {
|
||||
fieldType: tracking.field_type,
|
||||
value: this._mockMailTrackingValue_GetDisplayValue(tracking, 'old')
|
||||
}]],
|
||||
}));
|
||||
return trackingValues;
|
||||
},
|
||||
/**
|
||||
* Simulates `_get_display_value` on `mail.tracking.value`
|
||||
*/
|
||||
_mockMailTrackingValue_GetDisplayValue(record, type) {
|
||||
switch (record.field_type) {
|
||||
|
||||
@@ -346,8 +346,23 @@ class TestTrackingInternals(TestMailCommon):
|
||||
|
||||
msg_emp = self.record.message_ids.message_format()
|
||||
msg_sudo = self.record.sudo().message_ids.message_format()
|
||||
self.assertFalse(msg_emp[0].get('tracking_value_ids'), "should not have protected tracking values")
|
||||
self.assertTrue(msg_sudo[0].get('tracking_value_ids'), "should have protected tracking values")
|
||||
tracking_values = self.env['mail.tracking.value'].search([('mail_message_id', '=', self.record.message_ids.id)])
|
||||
formattedTrackingValues = [('insert-and-replace', [{
|
||||
'changedField': 'Email From',
|
||||
'id': tracking_values[0]['id'],
|
||||
'newValue': [('insert-and-replace', {
|
||||
'currencyId': False,
|
||||
'fieldType': 'char',
|
||||
'value': 'X',
|
||||
})],
|
||||
'oldValue': [('insert-and-replace', {
|
||||
'currencyId': False,
|
||||
'fieldType': 'char',
|
||||
'value': False,
|
||||
})],
|
||||
}])]
|
||||
self.assertEqual(msg_emp[0].get('trackingValues'), [('insert-and-replace', [])], "should not have protected tracking values")
|
||||
self.assertEqual(msg_sudo[0].get('trackingValues'), formattedTrackingValues, "should have protected tracking values")
|
||||
|
||||
msg_emp = self.record._notify_by_email_prepare_rendering_context(self.record.message_ids, {})
|
||||
msg_sudo = self.record.sudo()._notify_by_email_prepare_rendering_context(self.record.message_ids, {})
|
||||
|
||||
Reference in New Issue
Block a user