[IMP] mail: make inverses optional when unused
IdentifyingFields and fields marked `required` must have their inverse with `isCausal: true`. This led to having to systematically declare inverses on the related models in order to explicitly add `isCausal: true` to them, even when these inverses are not used for anything else. This commit automatically adds `isCausal: true` to the inverses generated by the framework when they are related to required fields or identifyingFields. Thus, it is no longer necessary to declare inverses if they are not used for anything else. This commit also removes all the inverses that are no longer needed thanks to this change. closes odoo/odoo#81679 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -638,6 +638,9 @@ export class ModelManager {
|
||||
) {
|
||||
throw new Error(`Mismatched relation types: ${field} on ${Model} (${field.relationType}) and ${inverseField} on ${RelatedModel} (${inverseField.relationType}).`);
|
||||
}
|
||||
if (field.required && !inverseField.isCausal) {
|
||||
throw new Error(`${field} on ${Model} is required but its inverse ${inverseField} on ${RelatedModel} is not causal.`);
|
||||
}
|
||||
}
|
||||
for (const identifyingField of Model.__identifyingFieldsFlattened) {
|
||||
const field = Model.__fieldMap[identifyingField];
|
||||
@@ -1070,7 +1073,10 @@ export class ModelManager {
|
||||
relFunc(Model.name, { inverse: field.fieldName }),
|
||||
{
|
||||
fieldName: `_inverse_${Model}/${field.fieldName}`,
|
||||
}
|
||||
// Note that an identifying field is not necessarily defined as
|
||||
// `required` (example: identifyingFields with an OR).
|
||||
isCausal: field.required || Model.__identifyingFieldsFlattened.has(field.fieldName),
|
||||
},
|
||||
));
|
||||
return inverseField;
|
||||
}
|
||||
|
||||
@@ -279,29 +279,12 @@ registerModel({
|
||||
activities: many2many('Activity', {
|
||||
inverse: 'attachments',
|
||||
}),
|
||||
/**
|
||||
* States the attachment cards that are displaying this attachment.
|
||||
*/
|
||||
attachmentCards: one2many('AttachmentCard', {
|
||||
inverse: 'attachment',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* States the attachment images that are displaying this attachment.
|
||||
*/
|
||||
attachmentImages: one2many('AttachmentImage', {
|
||||
inverse: 'attachment',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* States the attachment lists that are displaying this attachment.
|
||||
*/
|
||||
attachmentLists: many2many('AttachmentList', {
|
||||
inverse: 'attachments',
|
||||
}),
|
||||
attachmentViewers: many2many('AttachmentViewer', {
|
||||
inverse: 'attachments',
|
||||
}),
|
||||
checksum: attr(),
|
||||
/**
|
||||
* States on which composer this attachment is currently being created.
|
||||
|
||||
@@ -66,7 +66,6 @@ registerModel({
|
||||
* Determines the attachment of this card.
|
||||
*/
|
||||
attachment: many2one('Attachment', {
|
||||
inverse: 'attachmentCards',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -108,7 +108,6 @@ registerModel({
|
||||
* Determines the attachment of this attachment image..
|
||||
*/
|
||||
attachment: many2one('Attachment', {
|
||||
inverse: 'attachmentImages',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -80,13 +80,6 @@ registerModel({
|
||||
inverse: 'attachmentList',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* Determines the attachment viewers displaying this attachment list (if any).
|
||||
*/
|
||||
attachmentViewers: one2many('AttachmentViewer', {
|
||||
inverse: 'attachmentList',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* Link with a chatter to handle attachments.
|
||||
*/
|
||||
|
||||
@@ -40,12 +40,10 @@ registerModel({
|
||||
}),
|
||||
attachment: many2one('Attachment'),
|
||||
attachmentList: many2one('AttachmentList', {
|
||||
inverse: 'attachmentViewers',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
attachments: many2many('Attachment', {
|
||||
inverse: 'attachmentViewers',
|
||||
related: 'attachmentList.viewableAttachments',
|
||||
}),
|
||||
/**
|
||||
|
||||
@@ -210,10 +210,6 @@ registerModel({
|
||||
inviteButtonText: attr({
|
||||
compute: '_computeInviteButtonText',
|
||||
}),
|
||||
popoverView: one2one('PopoverView', {
|
||||
inverse: 'channelInvitationForm',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* States the OWL ref of the "search" input of this channel invitation
|
||||
* form. Useful to be able to focus it.
|
||||
|
||||
@@ -135,10 +135,6 @@ registerModel({
|
||||
compute: '_computeCanPostMessage',
|
||||
default: false,
|
||||
}),
|
||||
composerViews: one2many('ComposerView', {
|
||||
inverse: 'composer',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* This field determines whether some attachments linked to this
|
||||
* composer are being uploaded.
|
||||
|
||||
@@ -871,7 +871,6 @@ registerModel({
|
||||
*/
|
||||
composer: many2one('Composer', {
|
||||
compute: '_computeComposer',
|
||||
inverse: 'composerViews',
|
||||
required: true,
|
||||
}),
|
||||
/**
|
||||
|
||||
@@ -701,10 +701,6 @@ registerModel({
|
||||
isCausal: true,
|
||||
}),
|
||||
message_type: attr(),
|
||||
messageSeenIndicators: one2many('MessageSeenIndicator', {
|
||||
inverse: 'message',
|
||||
isCausal: true,
|
||||
}),
|
||||
/**
|
||||
* States the views that are displaying this message.
|
||||
*/
|
||||
|
||||
@@ -226,7 +226,6 @@ registerModel({
|
||||
* The message concerned by this seen indicator.
|
||||
*/
|
||||
message: many2one('Message', {
|
||||
inverse: 'messageSeenIndicators',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -446,10 +446,6 @@ registerModel({
|
||||
nameOrDisplayName: attr({
|
||||
compute: '_computeNameOrDisplayName',
|
||||
}),
|
||||
partnerSeenInfos: one2many('ThreadPartnerSeenInfo', {
|
||||
inverse: 'partner',
|
||||
isCausal: true,
|
||||
}),
|
||||
rtcSessions: one2many('RtcSession', {
|
||||
inverse: 'partner',
|
||||
}),
|
||||
|
||||
@@ -68,7 +68,6 @@ registerModel({
|
||||
* The record that represents the content inside the popover view.
|
||||
*/
|
||||
channelInvitationForm: one2one('ChannelInvitationForm', {
|
||||
inverse: 'popoverView',
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
required: true,
|
||||
|
||||
@@ -366,7 +366,6 @@ registerModel({
|
||||
rtcController: one2one('RtcController', {
|
||||
default: insertAndReplace(),
|
||||
readonly: true,
|
||||
required: true,
|
||||
inverse: 'callViewer',
|
||||
isCausal: true,
|
||||
}),
|
||||
|
||||
@@ -87,7 +87,6 @@ registerModel({
|
||||
userSetting: one2one('UserSetting', {
|
||||
inverse: 'rtcConfigurationMenu',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -92,7 +92,6 @@ registerModel({
|
||||
default: insertAndReplace(),
|
||||
inverse: 'rtcController',
|
||||
isCausal: true,
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -403,6 +403,7 @@ registerModel({
|
||||
}),
|
||||
thread: one2one('Thread', {
|
||||
inverse: 'cache',
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -13,7 +13,6 @@ registerModel({
|
||||
* Partner that this seen info is related to.
|
||||
*/
|
||||
partner: many2one('Partner', {
|
||||
inverse: 'partnerSeenInfos',
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
|
||||
@@ -61,10 +61,12 @@ registerModel({
|
||||
fields: {
|
||||
chatter: one2one('Chatter', {
|
||||
inverse: 'threadViewer',
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
}),
|
||||
chatWindow: one2one('ChatWindow', {
|
||||
inverse: 'threadViewer',
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
}),
|
||||
/**
|
||||
@@ -75,6 +77,7 @@ registerModel({
|
||||
}),
|
||||
discuss: one2one('Discuss', {
|
||||
inverse: 'threadViewer',
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
}),
|
||||
discussPublicView: one2one('DiscussPublicView', {
|
||||
|
||||
@@ -255,7 +255,6 @@ registerModel({
|
||||
default: insertAndReplace(),
|
||||
inverse: 'userSetting',
|
||||
isCausal: true,
|
||||
required: true,
|
||||
}),
|
||||
/**
|
||||
* layout of the rtc session display chosen by the user
|
||||
@@ -282,12 +281,5 @@ registerModel({
|
||||
voiceActiveDuration: attr({
|
||||
default: 0,
|
||||
}),
|
||||
/**
|
||||
* Models that represent the volume chosen by the user for each partner.
|
||||
*/
|
||||
volumeSettings: one2many('VolumeSetting', {
|
||||
inverse: 'userSetting',
|
||||
isCausal: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -39,7 +39,6 @@ registerModel({
|
||||
inverse: 'volumeSetting',
|
||||
}),
|
||||
userSetting: many2one('UserSetting', {
|
||||
inverse: 'volumeSettings',
|
||||
required: true,
|
||||
}),
|
||||
volume: attr({
|
||||
|
||||
Reference in New Issue
Block a user