[FIX] *: compute methods mixing stored and non-stored fields

closes odoo/odoo#98565

Related: odoo/upgrade#5158
Related: odoo/enterprise#47508
Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
Raphael Collet
2023-09-19 16:37:03 +00:00
parent f012e33769
commit 23faf6f7ef
7 changed files with 71 additions and 43 deletions
@@ -11,14 +11,14 @@ class DataRecycleRecord(models.Model):
_description = 'Recycling Record' _description = 'Recycling Record'
active = fields.Boolean('Active', default=True) active = fields.Boolean('Active', default=True)
name = fields.Char('Record Name', compute='_compute_values', compute_sudo=True) name = fields.Char('Record Name', compute='_compute_name', compute_sudo=True)
recycle_model_id = fields.Many2one('data_recycle.model', string='Recycle Model', ondelete='cascade') recycle_model_id = fields.Many2one('data_recycle.model', string='Recycle Model', ondelete='cascade')
res_id = fields.Integer('Record ID', index=True) res_id = fields.Integer('Record ID', index=True)
res_model_id = fields.Many2one(related='recycle_model_id.res_model_id', store=True, readonly=True) res_model_id = fields.Many2one(related='recycle_model_id.res_model_id', store=True, readonly=True)
res_model_name = fields.Char(related='recycle_model_id.res_model_name', store=True, readonly=True) res_model_name = fields.Char(related='recycle_model_id.res_model_name', store=True, readonly=True)
company_id = fields.Many2one('res.company', compute='_compute_values', store=True) company_id = fields.Many2one('res.company', compute='_compute_company_id', store=True)
@api.model @api.model
def _get_company_id(self, record): def _get_company_id(self, record):
@@ -28,17 +28,25 @@ class DataRecycleRecord(models.Model):
return company_id return company_id
@api.depends('res_id') @api.depends('res_id')
def _compute_values(self): def _compute_name(self):
original_records = {'%s_%s' % (r._name, r.id): r for r in self._original_records()} original_records = {(r._name, r.id): r for r in self._original_records()}
for record in self: for record in self:
original_record = original_records.get('%s_%s' % (record.res_model_name, record.res_id)) original_record = original_records.get((record.res_model_name, record.res_id))
if original_record: if original_record:
record.company_id = self._get_company_id(original_record)
record.name = original_record.display_name or _('Undefined Name') record.name = original_record.display_name or _('Undefined Name')
else: else:
record.company_id = self.env['res.company']
record.name = _('**Record Deleted**') record.name = _('**Record Deleted**')
@api.depends('res_id')
def _compute_company_id(self):
original_records = {(r._name, r.id): r for r in self._original_records()}
for record in self:
original_record = original_records.get((record.res_model_name, record.res_id))
if original_record:
record.company_id = self._get_company_id(original_record)
else:
record.company_id = self.env['res.company']
def _original_records(self): def _original_records(self):
if not self: if not self:
return [] return []
+8 -2
View File
@@ -76,7 +76,7 @@ class Applicant(models.Model):
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", tracking=True) domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", tracking=True)
day_open = fields.Float(compute='_compute_day', string="Days to Open", compute_sudo=True) day_open = fields.Float(compute='_compute_day', string="Days to Open", compute_sudo=True)
day_close = fields.Float(compute='_compute_day', string="Days to Close", compute_sudo=True) day_close = fields.Float(compute='_compute_day', string="Days to Close", compute_sudo=True)
delay_close = fields.Float(compute="_compute_day", string='Delay to Close', readonly=True, group_operator="avg", help="Number of days to close", store=True) delay_close = fields.Float(compute="_compute_delay", string='Delay to Close', readonly=True, group_operator="avg", help="Number of days to close", store=True)
color = fields.Integer("Color Index", default=0) color = fields.Integer("Color Index", default=0)
emp_id = fields.Many2one('hr.employee', string="Employee", help="Employee linked to the applicant.", copy=False) emp_id = fields.Many2one('hr.employee', string="Employee", help="Employee linked to the applicant.", copy=False)
emp_is_active = fields.Boolean(string="Employee Active", related='emp_id.active') emp_is_active = fields.Boolean(string="Employee Active", related='emp_id.active')
@@ -131,9 +131,15 @@ class Applicant(models.Model):
date_create = applicant.create_date date_create = applicant.create_date
date_closed = applicant.date_closed date_closed = applicant.date_closed
applicant.day_close = (date_closed - date_create).total_seconds() / (24.0 * 3600) applicant.day_close = (date_closed - date_create).total_seconds() / (24.0 * 3600)
applicant.delay_close = applicant.day_close - applicant.day_open
else: else:
applicant.day_close = False applicant.day_close = False
@api.depends('day_open', 'day_close')
def _compute_delay(self):
for applicant in self:
if applicant.date_open and applicant.day_close:
applicant.delay_close = applicant.day_close - applicant.day_open
else:
applicant.delay_close = False applicant.delay_close = False
@api.depends('email_from', 'partner_phone', 'partner_mobile') @api.depends('email_from', 'partner_phone', 'partner_mobile')
+13 -8
View File
@@ -55,8 +55,8 @@ class PosSession(models.Model):
opening_notes = fields.Text(string="Opening Notes") opening_notes = fields.Text(string="Opening Notes")
closing_notes = fields.Text(string="Closing Notes") closing_notes = fields.Text(string="Closing Notes")
cash_control = fields.Boolean(compute='_compute_cash_all', string='Has Cash Control', compute_sudo=True) cash_control = fields.Boolean(compute='_compute_cash_control', string='Has Cash Control')
cash_journal_id = fields.Many2one('account.journal', compute='_compute_cash_all', string='Cash Journal', store=True) cash_journal_id = fields.Many2one('account.journal', compute='_compute_cash_journal', string='Cash Journal', store=True)
cash_register_balance_end_real = fields.Monetary( cash_register_balance_end_real = fields.Monetary(
string="Ending Balance", string="Ending Balance",
@@ -154,15 +154,20 @@ class PosSession(models.Model):
action['domain'] = [('id', 'in', self.picking_ids.ids)] action['domain'] = [('id', 'in', self.picking_ids.ids)]
return action return action
@api.depends('config_id', 'payment_method_ids') @api.depends('cash_journal_id')
def _compute_cash_all(self): def _compute_cash_control(self):
# Only one cash register is supported by point_of_sale.
for session in self:
if session.cash_journal_id:
session.cash_control = session.config_id.cash_control
else:
session.cash_control = False
@api.depends('config_id', 'payment_method_ids')
def _compute_cash_journal(self):
# Only one cash register is supported by point_of_sale. # Only one cash register is supported by point_of_sale.
for session in self: for session in self:
session.cash_journal_id = session.cash_control = False
cash_journal = session.payment_method_ids.filtered('is_cash_count')[:1].journal_id cash_journal = session.payment_method_ids.filtered('is_cash_count')[:1].journal_id
if not cash_journal:
continue
session.cash_control = session.config_id.cash_control
session.cash_journal_id = cash_journal session.cash_journal_id = cash_journal
@api.constrains('config_id') @api.constrains('config_id')
@@ -39,7 +39,6 @@ class ResConfigSettings(models.TransientModel):
module_pos_preparation_display = fields.Boolean(string="Preparation Display", help="Show orders on the preparation display screen.") module_pos_preparation_display = fields.Boolean(string="Preparation Display", help="Show orders on the preparation display screen.")
update_stock_quantities = fields.Selection(related="company_id.point_of_sale_update_stock_quantities", readonly=False) update_stock_quantities = fields.Selection(related="company_id.point_of_sale_update_stock_quantities", readonly=False)
account_default_pos_receivable_account_id = fields.Many2one(string='Default Account Receivable (PoS)', related='company_id.account_default_pos_receivable_account_id', readonly=False) account_default_pos_receivable_account_id = fields.Many2one(string='Default Account Receivable (PoS)', related='company_id.account_default_pos_receivable_account_id', readonly=False)
is_default_pricelist_displayed = fields.Boolean(compute="_compute_pos_pricelist_id", compute_sudo=True)
barcode_nomenclature_id = fields.Many2one('barcode.nomenclature', related='company_id.nomenclature_id', readonly=False) barcode_nomenclature_id = fields.Many2one('barcode.nomenclature', related='company_id.nomenclature_id', readonly=False)
is_kiosk_mode = fields.Boolean(string="Is Kiosk Mode", default=False) is_kiosk_mode = fields.Boolean(string="Is Kiosk Mode", default=False)
@@ -273,9 +272,6 @@ class ResConfigSettings(models.TransientModel):
res_config.pos_available_pricelist_ids = res_config.pos_config_id.available_pricelist_ids res_config.pos_available_pricelist_ids = res_config.pos_config_id.available_pricelist_ids
res_config.pos_pricelist_id = res_config.pos_config_id.pricelist_id res_config.pos_pricelist_id = res_config.pos_config_id.pricelist_id
# TODO: Remove this field in master because it's always True.
res_config.is_default_pricelist_displayed = True
@api.depends('pos_available_pricelist_ids', 'pos_use_pricelist') @api.depends('pos_available_pricelist_ids', 'pos_use_pricelist')
def _compute_pos_allowed_pricelist_ids(self): def _compute_pos_allowed_pricelist_ids(self):
for res_config in self: for res_config in self:
@@ -15,7 +15,6 @@
<field name="pos_cash_control" invisible="1"/> <field name="pos_cash_control" invisible="1"/>
<field name="pos_iface_print_via_proxy" invisible="1"/> <field name="pos_iface_print_via_proxy" invisible="1"/>
<field name="pos_company_has_template" invisible="1"/> <field name="pos_company_has_template" invisible="1"/>
<field name="is_default_pricelist_displayed" invisible="1"/>
<field name="group_cash_rounding" invisible="1"/> <field name="group_cash_rounding" invisible="1"/>
</t> </t>
@@ -213,7 +212,7 @@
<label string="Available" for="pos_available_pricelist_ids" class="col-lg-3 o_light_label"/> <label string="Available" for="pos_available_pricelist_ids" class="col-lg-3 o_light_label"/>
<field name="pos_available_pricelist_ids" widget="many2many_tags" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]" readonly="pos_has_active_session"/> <field name="pos_available_pricelist_ids" widget="many2many_tags" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]" readonly="pos_has_active_session"/>
</div> </div>
<div class="row mt16" invisible="not is_default_pricelist_displayed"> <div class="row mt16">
<label string="Default" for="pos_pricelist_id" class="col-lg-3 o_light_label"/> <label string="Default" for="pos_pricelist_id" class="col-lg-3 o_light_label"/>
<field name="pos_pricelist_id" domain="[('id', 'in', pos_allowed_pricelist_ids)]" options="{'no_create': True}"/> <field name="pos_pricelist_id" domain="[('id', 'in', pos_allowed_pricelist_ids)]" options="{'no_create': True}"/>
</div> </div>
+18 -9
View File
@@ -51,10 +51,10 @@ class SendSMS(models.TransientModel):
# recipients # recipients
recipient_valid_count = fields.Integer('# Valid recipients', compute='_compute_recipients', compute_sudo=False) recipient_valid_count = fields.Integer('# Valid recipients', compute='_compute_recipients', compute_sudo=False)
recipient_invalid_count = fields.Integer('# Invalid recipients', compute='_compute_recipients', compute_sudo=False) recipient_invalid_count = fields.Integer('# Invalid recipients', compute='_compute_recipients', compute_sudo=False)
recipient_single_description = fields.Text('Recipients (Partners)', compute='_compute_recipient_single', compute_sudo=False) recipient_single_description = fields.Text('Recipients (Partners)', compute='_compute_recipient_single_non_stored', compute_sudo=False)
recipient_single_number = fields.Char('Stored Recipient Number', compute='_compute_recipient_single', compute_sudo=False) recipient_single_number = fields.Char('Stored Recipient Number', compute='_compute_recipient_single_non_stored', compute_sudo=False)
recipient_single_number_itf = fields.Char( recipient_single_number_itf = fields.Char(
'Recipient Number', compute='_compute_recipient_single', 'Recipient Number', compute='_compute_recipient_single_stored',
readonly=False, compute_sudo=False, store=True, readonly=False, compute_sudo=False, store=True,
help='Phone number of the recipient. If changed, it will be recorded on recipient\'s profile.') help='Phone number of the recipient. If changed, it will be recorded on recipient\'s profile.')
recipient_single_valid = fields.Boolean("Is valid", compute='_compute_recipient_single_valid', compute_sudo=False) recipient_single_valid = fields.Boolean("Is valid", compute='_compute_recipient_single_valid', compute_sudo=False)
@@ -113,22 +113,31 @@ class SendSMS(models.TransientModel):
) else 1 ) else 1
@api.depends('res_model', 'number_field_name') @api.depends('res_model', 'number_field_name')
def _compute_recipient_single(self): def _compute_recipient_single_stored(self):
for composer in self:
records = composer._get_records()
if not records or not issubclass(type(records), self.pool['mail.thread']) or not composer.comment_single_recipient:
composer.recipient_single_number_itf = ''
continue
records.ensure_one()
res = records._sms_get_recipients_info(force_field=composer.number_field_name, partner_fallback=False)
if not composer.recipient_single_number_itf:
composer.recipient_single_number_itf = res[records.id]['number'] or ''
if not composer.number_field_name:
composer.number_field_name = res[records.id]['field_store']
@api.depends('res_model', 'number_field_name')
def _compute_recipient_single_non_stored(self):
for composer in self: for composer in self:
records = composer._get_records() records = composer._get_records()
if not records or not issubclass(type(records), self.pool['mail.thread']) or not composer.comment_single_recipient: if not records or not issubclass(type(records), self.pool['mail.thread']) or not composer.comment_single_recipient:
composer.recipient_single_description = False composer.recipient_single_description = False
composer.recipient_single_number = '' composer.recipient_single_number = ''
composer.recipient_single_number_itf = ''
continue continue
records.ensure_one() records.ensure_one()
res = records._sms_get_recipients_info(force_field=composer.number_field_name, partner_fallback=False) res = records._sms_get_recipients_info(force_field=composer.number_field_name, partner_fallback=False)
composer.recipient_single_description = res[records.id]['partner'].name or records._mail_get_partners()[records[0].id].display_name composer.recipient_single_description = res[records.id]['partner'].name or records._mail_get_partners()[records[0].id].display_name
composer.recipient_single_number = res[records.id]['number'] or '' composer.recipient_single_number = res[records.id]['number'] or ''
if not composer.recipient_single_number_itf:
composer.recipient_single_number_itf = res[records.id]['number'] or ''
if not composer.number_field_name:
composer.number_field_name = res[records.id]['field_store']
@api.depends('recipient_single_number', 'recipient_single_number_itf') @api.depends('recipient_single_number', 'recipient_single_number_itf')
def _compute_recipient_single_valid(self): def _compute_recipient_single_valid(self):
+16 -11
View File
@@ -1355,8 +1355,8 @@ class QuantPackage(models.Model):
'res.company', 'Company', compute='_compute_package_info', 'res.company', 'Company', compute='_compute_package_info',
index=True, readonly=True, store=True) index=True, readonly=True, store=True)
owner_id = fields.Many2one( owner_id = fields.Many2one(
'res.partner', 'Owner', compute='_compute_package_info', search='_search_owner', 'res.partner', 'Owner', compute='_compute_owner_id', search='_search_owner',
index='btree_not_null', readonly=True, compute_sudo=True) readonly=True, compute_sudo=True)
package_use = fields.Selection([ package_use = fields.Selection([
('disposable', 'Disposable Box'), ('disposable', 'Disposable Box'),
('reusable', 'Reusable Box'), ('reusable', 'Reusable Box'),
@@ -1366,19 +1366,24 @@ class QuantPackage(models.Model):
valid_sscc = fields.Boolean('Package name is valid SSCC', compute='_compute_valid_sscc') valid_sscc = fields.Boolean('Package name is valid SSCC', compute='_compute_valid_sscc')
pack_date = fields.Date('Pack Date', default=fields.Date.today) pack_date = fields.Date('Pack Date', default=fields.Date.today)
@api.depends('quant_ids.package_id', 'quant_ids.location_id', 'quant_ids.company_id', 'quant_ids.owner_id', 'quant_ids.quantity', 'quant_ids.reserved_quantity') @api.depends('quant_ids.location_id', 'quant_ids.company_id')
def _compute_package_info(self): def _compute_package_info(self):
for package in self: for package in self:
values = {'location_id': False, 'owner_id': False} package.location_id = False
package.company_id = False
if package.quant_ids: if package.quant_ids:
values['location_id'] = package.quant_ids[0].location_id package.location_id = package.quant_ids[0].location_id
if all(q.owner_id == package.quant_ids[0].owner_id for q in package.quant_ids):
values['owner_id'] = package.quant_ids[0].owner_id
if all(q.company_id == package.quant_ids[0].company_id for q in package.quant_ids): if all(q.company_id == package.quant_ids[0].company_id for q in package.quant_ids):
values['company_id'] = package.quant_ids[0].company_id package.company_id = package.quant_ids[0].company_id
package.location_id = values['location_id']
package.company_id = values.get('company_id') @api.depends('quant_ids.owner_id')
package.owner_id = values['owner_id'] def _compute_owner_id(self):
for package in self:
package.owner_id = False
if package.quant_ids and all(
q.owner_id == package.quant_ids[0].owner_id for q in package.quant_ids
):
package.owner_id = package.quant_ids[0].owner_id
@api.depends('name') @api.depends('name')
def _compute_valid_sscc(self): def _compute_valid_sscc(self):