diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 6968bb4ba18..f895ca159c1 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -100,7 +100,6 @@ class AccountMove(models.Model): string='Date', index=True, compute='_compute_date', store=True, required=True, readonly=False, precompute=True, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, copy=False, tracking=True, ) @@ -144,7 +143,6 @@ class AccountMove(models.Model): string='Journal', compute='_compute_journal_id', inverse='_inverse_journal_id', store=True, readonly=False, precompute=True, required=True, - states={'draft': [('readonly', False)]}, check_company=True, domain="[('id', 'in', suitable_journal_ids)]", ) @@ -159,8 +157,6 @@ class AccountMove(models.Model): 'move_id', string='Journal Items', copy=True, - readonly=True, - states={'draft': [('readonly', False)]}, ) # === Payment fields === # @@ -266,40 +262,32 @@ class AccountMove(models.Model): 'move_id', string='Invoice lines', copy=False, - readonly=True, domain=[('display_type', 'in', ('product', 'line_section', 'line_note'))], - states={'draft': [('readonly', False)]}, ) # === Date fields === # invoice_date = fields.Date( string='Invoice/Bill Date', - readonly=True, - states={'draft': [('readonly', False)]}, index=True, copy=False, ) invoice_date_due = fields.Date( string='Due Date', compute='_compute_invoice_date_due', store=True, readonly=False, - states={'draft': [('readonly', False)]}, index=True, copy=False, ) delivery_date = fields.Date( string='Delivery Date', copy=False, - readonly=True, store=True, compute='_compute_delivery_date', - states={'draft': [('readonly', False)]}, ) show_delivery_date = fields.Boolean(compute='_compute_show_delivery_date') invoice_payment_term_id = fields.Many2one( comodel_name='account.payment.term', string='Payment Terms', compute='_compute_invoice_payment_term_id', store=True, readonly=False, precompute=True, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, check_company=True, ) needed_terms = fields.Binary(compute='_compute_needed_terms') @@ -311,9 +299,8 @@ class AccountMove(models.Model): partner_id = fields.Many2one( 'res.partner', string='Partner', - readonly=True, + readonly=False, tracking=True, - states={'draft': [('readonly', False)]}, inverse='_inverse_partner_id', check_company=True, change_default=True, @@ -348,7 +335,6 @@ class AccountMove(models.Model): string='Fiscal Position', check_company=True, compute='_compute_fiscal_position_id', store=True, readonly=False, precompute=True, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, ondelete="restrict", help="Fiscal positions are used to adapt taxes and accounts for particular " "customers or sales orders/invoices. The default value comes from the customer.", @@ -402,7 +388,6 @@ class AccountMove(models.Model): tracking=True, required=True, compute='_compute_currency_id', inverse='_inverse_currency_id', store=True, readonly=False, precompute=True, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, ) # === Amount fields === # @@ -551,8 +536,6 @@ class AccountMove(models.Model): invoice_cash_rounding_id = fields.Many2one( comodel_name='account.cash.rounding', string='Cash Rounding Method', - readonly=True, - states={'draft': [('readonly', False)]}, help='Defines the smallest coinage of the currency that can be used to pay by cash.', ) invoice_pdf_report_id = fields.Many2one( diff --git a/addons/event/models/event_registration.py b/addons/event/models/event_registration.py index 44261ae5b86..760116d24c7 100644 --- a/addons/event/models/event_registration.py +++ b/addons/event/models/event_registration.py @@ -16,11 +16,9 @@ class EventRegistration(models.Model): # event event_id = fields.Many2one( - 'event.event', string='Event', required=True, - readonly=True, states={'draft': [('readonly', False)]}) + 'event.event', string='Event', required=True) event_ticket_id = fields.Many2one( - 'event.event.ticket', string='Event Ticket', readonly=True, ondelete='restrict', - states={'draft': [('readonly', False)]}) + 'event.event.ticket', string='Event Ticket', ondelete='restrict') active = fields.Boolean(default=True) # utm informations utm_campaign_id = fields.Many2one('utm.campaign', 'Campaign', index=True, ondelete='set null') @@ -46,7 +44,7 @@ class EventRegistration(models.Model): event_user_id = fields.Many2one(string='Event Responsible', related='event_id.user_id', readonly=True) company_id = fields.Many2one( 'res.company', string='Company', related='event_id.company_id', - store=True, readonly=True, states={'draft': [('readonly', False)]}) + store=True, readonly=False) state = fields.Selection([ ('draft', 'Unconfirmed'), ('cancel', 'Cancelled'), ('open', 'Confirmed'), ('done', 'Attended')], diff --git a/addons/event_booth_sale/models/event_booth.py b/addons/event_booth_sale/models/event_booth.py index 1e00e4a6d09..ecf1ea26f48 100644 --- a/addons/event_booth_sale/models/event_booth.py +++ b/addons/event_booth_sale/models/event_booth.py @@ -17,7 +17,7 @@ class EventBooth(models.Model): groups='sales_team.group_sale_salesman', copy=False) sale_order_line_id = fields.Many2one( 'sale.order.line', string='Final Sale Order Line', ondelete='set null', - readonly=True, states={'available': [('readonly', False)]}, + readonly=False, groups='sales_team.group_sale_salesman', copy=False) sale_order_id = fields.Many2one( related='sale_order_line_id.order_id', store='True', readonly=True, diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 6d27704a239..6b835b19eee 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -46,20 +46,17 @@ class HrExpense(models.Model): res = [('id', '=', employee.id), '|', ('company_id', '=', False), ('company_id', '=', employee.company_id.id)] return res - name = fields.Char('Description', compute='_compute_name', readonly=False, store=True, precompute=True, required=True, copy=True, - states={'done': [('readonly', True)]}) - date = fields.Date(states={'done': [('readonly', True)]}, default=fields.Date.context_today, string="Expense Date") + name = fields.Char('Description', compute='_compute_name', readonly=False, store=True, precompute=True, required=True, copy=True) + date = fields.Date(default=fields.Date.context_today, string="Expense Date") accounting_date = fields.Date(string="Accounting Date", related='sheet_id.accounting_date', store=True, groups='account.group_account_invoice,account.group_account_readonly') employee_id = fields.Many2one('hr.employee', compute='_compute_employee_id', string="Employee", store=True, required=True, readonly=False, tracking=True, - states={'approved': [('readonly', True)], 'done': [('readonly', True)]}, default=_default_employee_id, domain=lambda self: self._get_employee_id_domain(), check_company=True) # product_id not required to allow create an expense without product via mail alias, but should be required on the view. product_id = fields.Many2one( 'product.product', string='Category', tracking=True, - states={'done': [('readonly', True)]}, check_company=True, domain="[('can_be_expensed', '=', True)]", ondelete='restrict', @@ -70,9 +67,9 @@ class HrExpense(models.Model): domain="[('category_id', '=', product_uom_category_id)]") product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id', readonly=True, string="UoM Category") unit_amount = fields.Float("Unit Price", compute='_compute_unit_amount', readonly=False, store=True, precompute=True, required=True, copy=True, - states={'done': [('readonly', True)]}, digits='Product Price') + digits='Product Price') unit_amount_display = fields.Float("Unit Price Display", compute='_compute_unit_amount_display') - quantity = fields.Float(required=True, states={'done': [('readonly', True)]}, digits='Product Unit of Measure', default=1) + quantity = fields.Float(required=True, digits='Product Unit of Measure', default=1) tax_ids = fields.Many2many('account.tax', 'expense_tax', 'expense_id', 'tax_id', compute='_compute_tax_ids', store=True, readonly=False, precompute=True, check_company=True, @@ -85,8 +82,9 @@ class HrExpense(models.Model): company_currency_id = fields.Many2one('res.currency', string="Report Company Currency", related='company_id.currency_id', readonly=True) total_amount_company = fields.Monetary('Total', tracking=True, compute='_compute_total_amount_company', inverse='_inverse_total_amount_company', store=True, currency_field='company_currency_id', readonly=False) - company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.company) - currency_id = fields.Many2one('res.currency', string='Currency', required=True, readonly=False, store=True, states={'reported': [('readonly', True)], 'approved': [('readonly', True)], 'done': [('readonly', True)]}, compute='_compute_currency_id', default=lambda self: self.env.company.currency_id) + company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company) + currency_id = fields.Many2one('res.currency', string='Currency', required=True, store=True, readonly=False, + compute='_compute_currency_id', default=lambda self: self.env.company.currency_id) currency_rate = fields.Float(compute='_compute_currency_rate', tracking=True) account_id = fields.Many2one( 'account.account', @@ -96,11 +94,11 @@ class HrExpense(models.Model): domain="[('account_type', 'not in', ('asset_receivable','liability_payable','asset_cash','liability_credit_card'))]", help="An expense account is expected", ) - description = fields.Text('Internal Notes', readonly=True, states={'draft': [('readonly', False)], 'reported': [('readonly', False)], 'refused': [('readonly', False)]}) + description = fields.Text('Internal Notes') payment_mode = fields.Selection([ ("own_account", "Employee (to reimburse)"), ("company_account", "Company") - ], default='own_account', tracking=True, states={'done': [('readonly', True)], 'approved': [('readonly', True)], 'reported': [('readonly', True)]}, string="Paid By") + ], default='own_account', tracking=True, string="Paid By") attachment_number = fields.Integer('Number of Attachments', compute='_compute_attachment_number') state = fields.Selection( selection=[ @@ -1000,12 +998,12 @@ class HrExpenseSheet(models.Model): ], copy=False) approval_date = fields.Datetime('Approval Date', readonly=True) - company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, states={'draft': [('readonly', False)]}, default=lambda self: self.env.company) + company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company) company_currency_id = fields.Many2one(comodel_name='res.currency', string="Report Company Currency", related='company_id.currency_id') - employee_id = fields.Many2one('hr.employee', string="Employee", required=True, readonly=True, tracking=True, states={'draft': [('readonly', False)]}, default=_default_employee_id, check_company=True, domain=lambda self: self.env['hr.expense']._get_employee_id_domain()) + employee_id = fields.Many2one('hr.employee', string="Employee", required=True, tracking=True, default=_default_employee_id, check_company=True, domain=lambda self: self.env['hr.expense']._get_employee_id_domain()) address_id = fields.Many2one('res.partner', compute='_compute_from_employee_id', store=True, readonly=False, copy=True, string="Employee Home Address", check_company=True) - department_id = fields.Many2one('hr.department', compute='_compute_from_employee_id', store=True, readonly=False, copy=False, string='Department', states={'post': [('readonly', True)], 'done': [('readonly', True)]}) - user_id = fields.Many2one('res.users', 'Manager', compute='_compute_from_employee_id', store=True, readonly=True, copy=False, states={'draft': [('readonly', False)]}, tracking=True, domain=lambda self: [('groups_id', 'in', self.env.ref('hr_expense.group_hr_expense_team_approver').id)]) + department_id = fields.Many2one('hr.department', compute='_compute_from_employee_id', store=True, readonly=False, copy=False, string='Department') + user_id = fields.Many2one('res.users', 'Manager', compute='_compute_from_employee_id', store=True, readonly=False, copy=False, tracking=True, domain=lambda self: [('groups_id', 'in', self.env.ref('hr_expense.group_hr_expense_team_approver').id)]) # === Amount fields === # total_amount = fields.Monetary('Total', currency_field='company_currency_id', compute='_compute_amount', store=True, tracking=True) @@ -1014,8 +1012,7 @@ class HrExpenseSheet(models.Model): amount_residual = fields.Monetary(string="Amount Due", currency_field='company_currency_id', compute='_compute_from_account_move_ids', store=True) - currency_id = fields.Many2one('res.currency', string='Currency', states={'draft': [('readonly', False)]}, - compute='_compute_currency_id', store=True, readonly=True) + currency_id = fields.Many2one('res.currency', string='Currency', compute='_compute_currency_id', store=True, readonly=False) is_multiple_currency = fields.Boolean("Handle lines with different currencies", compute='_compute_is_multiple_currency') # === Account fields === # @@ -1032,7 +1029,6 @@ class HrExpenseSheet(models.Model): employee_journal_id = fields.Many2one( 'account.journal', string='Journal', - states={'done': [('readonly', True)], 'post': [('readonly', True)]}, check_company=True, domain="[('type', '=', 'purchase')]", default=_default_journal_id, diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 339fe5000c6..da166f15ce7 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -153,7 +153,6 @@ class HolidaysRequest(models.Model): # leave type configuration holiday_status_id = fields.Many2one( "hr.leave.type", compute='_compute_from_employee_id', store=True, string="Time Off Type", required=True, readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}, domain="[('company_id', '?=', employee_company_id), '|', ('requires_allocation', '=', 'no'), ('has_valid_allocation', '=', True)]", tracking=True) holiday_allocation_id = fields.Many2one( 'hr.leave.allocation', compute='_compute_from_holiday_status_id', string="Allocation", store=True, readonly=False) @@ -163,23 +162,19 @@ class HolidaysRequest(models.Model): employee_id = fields.Many2one( 'hr.employee', compute='_compute_from_employee_ids', store=True, string='Employee', index=True, readonly=False, ondelete="restrict", - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}, tracking=True, compute_sudo=False) employee_company_id = fields.Many2one(related='employee_id.company_id', readonly=True, store=True) active_employee = fields.Boolean(related='employee_id.active', string='Employee Active', readonly=True) tz_mismatch = fields.Boolean(compute='_compute_tz_mismatch') tz = fields.Selection(_tz_get, compute='_compute_tz') department_id = fields.Many2one( - 'hr.department', compute='_compute_department_id', store=True, string='Department', readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}) - notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + 'hr.department', compute='_compute_department_id', store=True, string='Department', readonly=False) + notes = fields.Text('Reasons', readonly=False) # duration date_from = fields.Datetime( - 'Start Date', compute='_compute_date_from_to', store=True, readonly=False, index=True, copy=False, required=True, tracking=True, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}) + 'Start Date', compute='_compute_date_from_to', store=True, readonly=False, index=True, copy=False, required=True, tracking=True) date_to = fields.Datetime( - 'End Date', compute='_compute_date_from_to', store=True, readonly=False, copy=False, required=True, tracking=True, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}) + 'End Date', compute='_compute_date_from_to', store=True, readonly=False, copy=False, required=True, tracking=True) number_of_days = fields.Float( 'Duration (Days)', compute='_compute_number_of_days', store=True, readonly=False, copy=False, tracking=True, help='Number of days of the time off request. Used in the calculation. To manually correct the duration, use this field.') @@ -201,21 +196,19 @@ class HolidaysRequest(models.Model): ('company', 'By Company'), ('department', 'By Department'), ('category', 'By Employee Tag')], - string='Allocation Mode', readonly=True, required=True, default='employee', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + string='Allocation Mode', readonly=False, required=True, default='employee', help='By Employee: Allocation/Request for individual Employee, By Employee Tag: Allocation/Request for group of employees in category') employee_ids = fields.Many2many( - 'hr.employee', compute='_compute_from_holiday_type', store=True, string='Employees', readonly=False, groups="hr_holidays.group_hr_holidays_user", - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}) + 'hr.employee', compute='_compute_from_holiday_type', store=True, string='Employees', readonly=False, groups="hr_holidays.group_hr_holidays_user") multi_employee = fields.Boolean( compute='_compute_from_employee_ids', store=True, compute_sudo=False, help='Holds whether this allocation concerns more than 1 employee') category_id = fields.Many2one( 'hr.employee.category', compute='_compute_from_holiday_type', store=True, string='Employee Tag', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee') + readonly=False, help='Category of Employee') mode_company_id = fields.Many2one( 'res.company', compute='_compute_from_holiday_type', store=True, string='Company Mode', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + readonly=False) first_approver_id = fields.Many2one( 'hr.employee', string='First Approval', readonly=True, copy=False, help='This area is automatically filled by the user who validate the time off') diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 2a75c88164b..25aad9dc6a7 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -57,28 +57,25 @@ class HolidaysAllocation(models.Model): "\nThe status is 'Refused', when an allocation request is refused by manager." + "\nThe status is 'Approved', when an allocation request is approved by manager.") date_from = fields.Date('Start Date', index=True, copy=False, default=fields.Date.context_today, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, tracking=True, required=True) - date_to = fields.Date('End Date', copy=False, tracking=True, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}) + tracking=True, required=True) + date_to = fields.Date('End Date', copy=False, tracking=True) holiday_status_id = fields.Many2one( "hr.leave.type", compute='_compute_holiday_status_id', store=True, string="Time Off Type", required=True, readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate1': [('readonly', True)], 'validate': [('readonly', True)]}, domain=_domain_holiday_status_id, default=_default_holiday_status_id) employee_id = fields.Many2one( - 'hr.employee', compute='_compute_from_employee_ids', store=True, string='Employee', index=True, readonly=False, ondelete="restrict", tracking=True, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate': [('readonly', True)]}) + 'hr.employee', compute='_compute_from_employee_ids', store=True, string='Employee', index=True, readonly=False, ondelete="restrict", tracking=True) employee_company_id = fields.Many2one(related='employee_id.company_id', readonly=True, store=True) active_employee = fields.Boolean('Active Employee', related='employee_id.active', readonly=True) manager_id = fields.Many2one('hr.employee', compute='_compute_manager_id', store=True, string='Manager') - notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + notes = fields.Text('Reasons', readonly=False) # duration number_of_days = fields.Float( 'Number of Days', compute='_compute_from_holiday_status_id', store=True, readonly=False, tracking=True, default=1, help='Duration in days. Reference field to use when necessary.') number_of_days_display = fields.Float( 'Duration (days)', compute='_compute_number_of_days_display', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + readonly=False, help="If Accrual Allocation: Number of days allocated in addition to the ones you will get via the accrual' system.") number_of_hours_display = fields.Float( 'Duration (hours)', compute='_compute_number_of_hours_display', @@ -101,27 +98,23 @@ class HolidaysAllocation(models.Model): ('company', 'By Company'), ('department', 'By Department'), ('category', 'By Employee Tag')], - string='Allocation Mode', readonly=True, required=True, default='employee', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + string='Allocation Mode', readonly=False, required=True, default='employee', help="Allow to create requests in batchs:\n- By Employee: for a specific employee" "\n- By Company: all employees of the specified company" "\n- By Department: all employees of the specified department" "\n- By Employee Tag: all employees of the specific employee group category") employee_ids = fields.Many2many( - 'hr.employee', compute='_compute_from_holiday_type', store=True, string='Employees', readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate': [('readonly', True)]}) + 'hr.employee', compute='_compute_from_holiday_type', store=True, string='Employees', readonly=False) multi_employee = fields.Boolean( compute='_compute_from_employee_ids', store=True, help='Holds whether this allocation concerns more than 1 employee') mode_company_id = fields.Many2one( - 'res.company', compute='_compute_from_holiday_type', store=True, string='Company Mode', readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate': [('readonly', True)]}) + 'res.company', compute='_compute_from_holiday_type', store=True, string='Company Mode', readonly=False) department_id = fields.Many2one( 'hr.department', compute='_compute_department_id', store=True, string='Department', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + readonly=False) category_id = fields.Many2one( - 'hr.employee.category', compute='_compute_from_holiday_type', store=True, string='Employee Tag', readonly=False, - states={'cancel': [('readonly', True)], 'refuse': [('readonly', True)], 'validate': [('readonly', True)]}) + 'hr.employee.category', compute='_compute_from_holiday_type', store=True, string='Employee Tag', readonly=False) # accrual configuration lastcall = fields.Date("Date of the last accrual allocation", readonly=True, default=fields.Date.context_today) nextcall = fields.Date("Date of the next accrual allocation", default=False, readonly=True) @@ -129,8 +122,7 @@ class HolidaysAllocation(models.Model): [ ('regular', 'Regular Allocation'), ('accrual', 'Accrual Allocation') - ], string="Allocation Type", default="regular", required=True, readonly=True, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + ], string="Allocation Type", default="regular", required=True, readonly=False) is_officer = fields.Boolean(compute='_compute_is_officer') accrual_plan_id = fields.Many2one('hr.leave.accrual.plan', compute="_compute_from_holiday_status_id", store=True, readonly=False, domain="['|', ('time_off_type_id', '=', False), ('time_off_type_id', '=', holiday_status_id)]", tracking=True) max_leaves = fields.Float(compute='_compute_leaves') diff --git a/addons/l10n_ar/models/account_move.py b/addons/l10n_ar/models/account_move.py index ab5fbb0afc5..c56a6c70976 100644 --- a/addons/l10n_ar/models/account_move.py +++ b/addons/l10n_ar/models/account_move.py @@ -32,8 +32,8 @@ class AccountMove(models.Model): compute='_compute_l10n_ar_afip_concept', selection='_get_afip_invoice_concepts', string="AFIP Concept", help="A concept is suggested regarding the type of the products on the invoice but it is allowed to force a" " different type if required.") - l10n_ar_afip_service_start = fields.Date(string='AFIP Service Start Date', readonly=True, states={'draft': [('readonly', False)]}) - l10n_ar_afip_service_end = fields.Date(string='AFIP Service End Date', readonly=True, states={'draft': [('readonly', False)]}) + l10n_ar_afip_service_start = fields.Date(string='AFIP Service Start Date') + l10n_ar_afip_service_end = fields.Date(string='AFIP Service End Date') def _is_manual_document_number(self): """ Document number should be manual input by user when the journal use documents and diff --git a/addons/l10n_id_efaktur/models/account_move.py b/addons/l10n_id_efaktur/models/account_move.py index 6844e3b412b..6d66a359b9f 100644 --- a/addons/l10n_id_efaktur/models/account_move.py +++ b/addons/l10n_id_efaktur/models/account_move.py @@ -36,7 +36,7 @@ class AccountMove(models.Model): ('08', '08 Penyerahan yang PPN-nya Dibebaskan (Impor Barang Tertentu)'), ('09', '09 Penyerahan Aktiva ( Pasal 16D UU PPN )'), ], string='Kode Transaksi', help='Dua digit pertama nomor pajak', - readonly=False, states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, copy=False, + readonly=False, copy=False, compute="_compute_kode_transaksi", store=True) l10n_id_need_kode_transaksi = fields.Boolean(compute='_compute_need_kode_transaksi') diff --git a/addons/l10n_in/models/account_invoice.py b/addons/l10n_in/models/account_invoice.py index a7b30a97541..8aec7e1bf5c 100644 --- a/addons/l10n_in/models/account_invoice.py +++ b/addons/l10n_in/models/account_invoice.py @@ -26,10 +26,10 @@ class AccountMove(models.Model): l10n_in_state_id = fields.Many2one('res.country.state', string="Place of supply", compute="_compute_l10n_in_state_id", store=True, readonly=False) l10n_in_gstin = fields.Char(string="GSTIN") # For Export invoice this data is need in GSTR report - l10n_in_shipping_bill_number = fields.Char('Shipping bill number', readonly=True, states={'draft': [('readonly', False)]}) - l10n_in_shipping_bill_date = fields.Date('Shipping bill date', readonly=True, states={'draft': [('readonly', False)]}) - l10n_in_shipping_port_code_id = fields.Many2one('l10n_in.port.code', 'Port code', readonly=True, states={'draft': [('readonly', False)]}) - l10n_in_reseller_partner_id = fields.Many2one('res.partner', 'Reseller', domain=[('vat', '!=', False)], help="Only Registered Reseller", readonly=True, states={'draft': [('readonly', False)]}) + l10n_in_shipping_bill_number = fields.Char('Shipping bill number') + l10n_in_shipping_bill_date = fields.Date('Shipping bill date') + l10n_in_shipping_port_code_id = fields.Many2one('l10n_in.port.code', 'Port code') + l10n_in_reseller_partner_id = fields.Many2one('res.partner', 'Reseller', domain=[('vat', '!=', False)], help="Only Registered Reseller") l10n_in_journal_type = fields.Selection(string="Journal Type", related='journal_id.type') @api.depends('amount_total') diff --git a/addons/l10n_in_purchase/models/purchase_order.py b/addons/l10n_in_purchase/models/purchase_order.py index 5e131817732..f1cb38979ba 100644 --- a/addons/l10n_in_purchase/models/purchase_order.py +++ b/addons/l10n_in_purchase/models/purchase_order.py @@ -17,7 +17,7 @@ class PurchaseOrder(models.Model): ('special_economic_zone', 'Special Economic Zone'), ('deemed_export', 'Deemed Export'), ('uin_holders', 'UIN Holders'), - ], string="GST Treatment", states=Purchase.READONLY_STATES, compute="_compute_l10n_in_gst_treatment", store=True) + ], string="GST Treatment", compute="_compute_l10n_in_gst_treatment", store=True) @api.depends('partner_id') def _compute_l10n_in_gst_treatment(self): diff --git a/addons/l10n_in_sale/models/sale_order.py b/addons/l10n_in_sale/models/sale_order.py index 02276e2b618..51cf937dc99 100644 --- a/addons/l10n_in_sale/models/sale_order.py +++ b/addons/l10n_in_sale/models/sale_order.py @@ -8,7 +8,7 @@ class SaleOrder(models.Model): _inherit = "sale.order" l10n_in_reseller_partner_id = fields.Many2one('res.partner', - string='Reseller', domain="[('vat', '!=', False), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}) + string='Reseller', domain="[('vat', '!=', False), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", readonly=False) l10n_in_gst_treatment = fields.Selection([ ('regular', 'Registered Business - Regular'), ('composition', 'Registered Business - Composition'), @@ -18,7 +18,7 @@ class SaleOrder(models.Model): ('special_economic_zone', 'Special Economic Zone'), ('deemed_export', 'Deemed Export'), ('uin_holders', 'UIN Holders'), - ], string="GST Treatment", readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, compute="_compute_l10n_in_gst_treatment", store=True) + ], string="GST Treatment", readonly=False, compute="_compute_l10n_in_gst_treatment", store=True) @api.depends('partner_id') def _compute_l10n_in_gst_treatment(self): diff --git a/addons/l10n_it_edi/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py index 2b7389f5a99..a027660f788 100644 --- a/addons/l10n_it_edi/models/account_invoice.py +++ b/addons/l10n_it_edi/models/account_invoice.py @@ -24,8 +24,8 @@ class AccountMove(models.Model): l10n_it_edi_transaction = fields.Char(copy=False, string="FatturaPA Transaction") l10n_it_edi_attachment_id = fields.Many2one('ir.attachment', copy=False, string="FatturaPA Attachment", ondelete="restrict") - l10n_it_stamp_duty = fields.Float(default=0, string="Dati Bollo", readonly=True, states={'draft': [('readonly', False)]}) - l10n_it_ddt_id = fields.Many2one('l10n_it.ddt', string='DDT', readonly=True, states={'draft': [('readonly', False)]}, copy=False) + l10n_it_stamp_duty = fields.Float(default=0, string="Dati Bollo") + l10n_it_ddt_id = fields.Many2one('l10n_it.ddt', string='DDT', copy=False) l10n_it_einvoice_name = fields.Char(compute='_compute_l10n_it_einvoice') l10n_it_einvoice_id = fields.Many2one('ir.attachment', string="Electronic invoice", compute='_compute_l10n_it_einvoice') diff --git a/addons/l10n_latam_check/models/account_payment.py b/addons/l10n_latam_check/models/account_payment.py index 0964502c42b..ddc37f3a4e5 100644 --- a/addons/l10n_latam_check/models/account_payment.py +++ b/addons/l10n_latam_check/models/account_payment.py @@ -13,7 +13,6 @@ class AccountPayment(models.Model): l10n_latam_check_id = fields.Many2one( comodel_name='account.payment', string='Check', - readonly=True, states={'draft': [('readonly', False)]}, copy=False, check_company=True, ) @@ -40,17 +39,15 @@ class AccountPayment(models.Model): comodel_name='res.bank', string='Check Bank', compute='_compute_l10n_latam_check_bank_id', store=True, readonly=False, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, ) l10n_latam_check_issuer_vat = fields.Char( string='Check Issuer VAT', compute='_compute_l10n_latam_check_issuer_vat', store=True, readonly=False, - states={'posted': [('readonly', True)], 'cancel': [('readonly', True)]}, ) l10n_latam_check_payment_date = fields.Date( string='Check Cash-In Date', help="Date from when you can cash in the check, turn the check into cash", - readonly=True, states={'draft': [('readonly', False)]}, + readonly=False, ) # This is a technical field for the view only diff --git a/addons/l10n_latam_invoice_document/models/account_move.py b/addons/l10n_latam_invoice_document/models/account_move.py index 99a7ed74144..d76fab5416e 100644 --- a/addons/l10n_latam_invoice_document/models/account_move.py +++ b/addons/l10n_latam_invoice_document/models/account_move.py @@ -64,11 +64,10 @@ class AccountMove(models.Model): l10n_latam_available_document_type_ids = fields.Many2many('l10n_latam.document.type', compute='_compute_l10n_latam_available_document_types') l10n_latam_document_type_id = fields.Many2one( - 'l10n_latam.document.type', string='Document Type', readonly=False, auto_join=True, index='btree_not_null', - states={'posted': [('readonly', True)]}, compute='_compute_l10n_latam_document_type', store=True) + 'l10n_latam.document.type', string='Document Type', readonly=False, auto_join=True, index='btree_not_null', compute='_compute_l10n_latam_document_type', store=True) l10n_latam_document_number = fields.Char( compute='_compute_l10n_latam_document_number', inverse='_inverse_l10n_latam_document_number', - string='Document Number', readonly=True, states={'draft': [('readonly', False)]}) + string='Document Number', readonly=False) l10n_latam_use_documents = fields.Boolean(related='journal_id.l10n_latam_use_documents') l10n_latam_manual_document_number = fields.Boolean(compute='_compute_l10n_latam_manual_document_number', string='Manual Number') l10n_latam_document_type_id_code = fields.Char(related='l10n_latam_document_type_id.code', string='Doc Type') diff --git a/addons/lunch/models/lunch_order.py b/addons/lunch/models/lunch_order.py index 8d40087ced0..9e9538f34f0 100644 --- a/addons/lunch/models/lunch_order.py +++ b/addons/lunch/models/lunch_order.py @@ -18,15 +18,13 @@ class LunchOrder(models.Model): product_id = fields.Many2one('lunch.product', string="Product", required=True) category_id = fields.Many2one( string='Product Category', related='product_id.category_id', store=True) - date = fields.Date('Order Date', required=True, readonly=True, - states={'new': [('readonly', False)]}, + date = fields.Date('Order Date', required=True, readonly=False, default=fields.Date.context_today) supplier_id = fields.Many2one( string='Vendor', related='product_id.supplier_id', store=True, index=True) available_today = fields.Boolean(related='supplier_id.available_today') order_deadline_passed = fields.Boolean(related='supplier_id.order_deadline_passed') - user_id = fields.Many2one('res.users', 'User', readonly=True, - states={'new': [('readonly', False)]}, + user_id = fields.Many2one('res.users', 'User', readonly=False, default=lambda self: self.env.uid) lunch_location_id = fields.Many2one('lunch.location', default=lambda self: self.env.user.last_lunch_location_id) note = fields.Text('Notes') diff --git a/addons/mail/models/fetchmail.py b/addons/mail/models/fetchmail.py index c3ba19c8ddd..7a3c9c6d333 100644 --- a/addons/mail/models/fetchmail.py +++ b/addons/mail/models/fetchmail.py @@ -40,8 +40,8 @@ class FetchmailServer(models.Model): ('draft', 'Not Confirmed'), ('done', 'Confirmed'), ], string='Status', index=True, readonly=True, copy=False, default='draft') - server = fields.Char(string='Server Name', readonly=True, help="Hostname or IP of the mail server", states={'draft': [('readonly', False)]}) - port = fields.Integer(readonly=True, states={'draft': [('readonly', False)]}) + server = fields.Char(string='Server Name', readonly=False, help="Hostname or IP of the mail server") + port = fields.Integer() server_type = fields.Selection([ ('imap', 'IMAP Server'), ('pop', 'POP Server'), @@ -54,13 +54,13 @@ class FetchmailServer(models.Model): original = fields.Boolean('Keep Original', help="Whether a full original copy of each email should be kept for reference " "and attached to each processed message. This will usually double the size of your message database.") date = fields.Datetime(string='Last Fetch Date', readonly=True) - user = fields.Char(string='Username', readonly=True, states={'draft': [('readonly', False)]}) - password = fields.Char(readonly=True, states={'draft': [('readonly', False)]}) + user = fields.Char(string='Username', readonly=False) + password = fields.Char() object_id = fields.Many2one('ir.model', string="Create a New Record", help="Process each incoming mail as part of a conversation " "corresponding to this document type. This will create " "new documents for new conversations, or attach follow-up " "emails to the existing conversations (documents).") - priority = fields.Integer(string='Server Priority', readonly=True, states={'draft': [('readonly', False)]}, help="Defines the order of processing, lower values mean higher priority", default=5) + priority = fields.Integer(string='Server Priority', readonly=False, help="Defines the order of processing, lower values mean higher priority", default=5) message_ids = fields.One2many('mail.mail', 'fetchmail_server_id', string='Messages', readonly=True) configuration = fields.Text('Configuration', readonly=True) script = fields.Char(readonly=True, default='/mail/static/scripts/odoo-mailgate.py') diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index f8fe8b266a0..635d4a40158 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -99,13 +99,11 @@ class MassMailing(models.Model): schedule_type = fields.Selection( [('now', 'Send now'), ('scheduled', 'Send on')], string='Schedule', default='now', - readonly=True, required=True, - states={'draft': [('readonly', False)], 'in_queue': [('readonly', False)]}) + readonly=False, required=True) schedule_date = fields.Datetime( string='Scheduled for', - compute='_compute_schedule_date', readonly=True, store=True, - copy=True, tracking=True, - states={'draft': [('readonly', False)], 'in_queue': [('readonly', False)]}) + compute='_compute_schedule_date', readonly=False, store=True, + copy=True, tracking=True) calendar_date = fields.Datetime( 'Calendar Date', compute='_compute_calendar_date', store=True, diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 7859d37cb71..ac558c8744b 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -55,15 +55,13 @@ class MrpProduction(models.Model): backorder_sequence = fields.Integer("Backorder Sequence", default=0, copy=False, help="Backorder sequence, if equals to 0 means there is not related backorder") origin = fields.Char( 'Source', copy=False, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="Reference of the document that generated this production order request.") product_id = fields.Many2one( 'product.product', 'Product', domain="[('type', 'in', ['product', 'consu'])]", compute='_compute_product_id', store=True, copy=True, precompute=True, - readonly=True, required=True, check_company=True, - states={'draft': [('readonly', False)]}) + readonly=False, required=True, check_company=True) product_variant_attributes = fields.Many2many('product.template.attribute.value', related='product_id.product_template_attribute_value_ids') workcenter_id = fields.Many2one('mrp.workcenter', store=False) # Only used for search in view_mrp_production_filter product_tracking = fields.Selection(related='product_id.tracking') @@ -163,7 +161,7 @@ class MrpProduction(models.Model): move_raw_ids = fields.One2many( 'stock.move', 'raw_material_production_id', 'Components', compute='_compute_move_raw_ids', store=True, readonly=False, - copy=False, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + copy=False, domain=[('scrapped', '=', False)]) move_finished_ids = fields.One2many( 'stock.move', 'production_id', 'Finished Products', readonly=False, @@ -187,7 +185,6 @@ class MrpProduction(models.Model): help='Technical field to check when we can reserve quantities') user_id = fields.Many2one( 'res.users', 'Responsible', default=lambda self: self.env.user, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, domain=lambda self: [('groups_id', 'in', self.env.ref('mrp.group_mrp_user').id)]) company_id = fields.Many2one( 'res.company', 'Company', default=lambda self: self.env.company, diff --git a/addons/mrp/models/mrp_unbuild.py b/addons/mrp/models/mrp_unbuild.py index b5bfa888da6..f6d4c321c06 100644 --- a/addons/mrp/models/mrp_unbuild.py +++ b/addons/mrp/models/mrp_unbuild.py @@ -19,18 +19,18 @@ class MrpUnbuild(models.Model): product_id = fields.Many2one( 'product.product', 'Product', check_company=True, domain="[('type', 'in', ['product', 'consu'])]", - required=True, states={'done': [('readonly', True)]}) + required=True) company_id = fields.Many2one( 'res.company', 'Company', default=lambda s: s.env.company, - required=True, index=True, states={'done': [('readonly', True)]}) + required=True, index=True) product_qty = fields.Float( 'Quantity', default=1.0, - required=True, states={'done': [('readonly', True)]}) + required=True) product_uom_id = fields.Many2one( 'uom.uom', 'Unit of Measure', compute='_compute_product_uom_id', store=True, readonly=False, precompute=True, - required=True, states={'done': [('readonly', True)]}) + required=True) bom_id = fields.Many2one( 'mrp.bom', 'Bill of Material', domain="""[ @@ -43,13 +43,12 @@ class MrpUnbuild(models.Model): '|', ('company_id', '=', company_id), ('company_id', '=', False) - ] -""", - states={'done': [('readonly', True)]}, check_company=True) + ]""", + check_company=True) mo_id = fields.Many2one( 'mrp.production', 'Manufacturing Order', domain="[('state', '=', 'done'), ('product_id', '=?', product_id), ('bom_id', '=?', bom_id)]", - states={'done': [('readonly', True)]}, check_company=True) + check_company=True) mo_bom_id = fields.Many2one('mrp.bom', 'Bill of Material used on the Production Order', related='mo_id.bom_id') lot_id = fields.Many2one( 'stock.lot', 'Lot/Serial Number', @@ -60,13 +59,13 @@ class MrpUnbuild(models.Model): domain="[('usage','=','internal')]", check_company=True, compute='_compute_location_id', store=True, readonly=False, precompute=True, - required=True, states={'done': [('readonly', True)]}, help="Location where the product you want to unbuild is.") + required=True, help="Location where the product you want to unbuild is.") location_dest_id = fields.Many2one( 'stock.location', 'Destination Location', domain="[('usage','=','internal')]", check_company=True, compute='_compute_location_id', store=True, readonly=False, precompute=True, - required=True, states={'done': [('readonly', True)]}, help="Location where you want to send the components resulting from the unbuild order.") + required=True, help="Location where you want to send the components resulting from the unbuild order.") consume_line_ids = fields.One2many( 'stock.move', 'consume_unbuild_id', readonly=True, string='Consumed Disassembly Lines') diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 14832aaa567..05cc4dcecd5 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -22,12 +22,10 @@ class MrpWorkorder(models.Model): return workcenters.browse(workcenter_ids) name = fields.Char( - 'Work Order', required=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}) + 'Work Order', required=True) barcode = fields.Char(compute='_compute_barcode', store=True) workcenter_id = fields.Many2one( 'mrp.workcenter', 'Work Center', required=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)], 'progress': [('readonly', True)]}, group_expand='_read_group_workcenter_id', check_company=True) working_state = fields.Selection( string='Workcenter Status', related='workcenter_id.working_state') # technical: used in views only @@ -73,17 +71,16 @@ class MrpWorkorder(models.Model): 'Start', compute='_compute_dates', inverse='_set_dates', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + readonly=False, store=True, copy=False) date_finished = fields.Datetime( 'End', compute='_compute_dates', inverse='_set_dates', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + readonly=False, store=True, copy=False) duration_expected = fields.Float( 'Expected Duration', digits=(16, 2), compute='_compute_duration_expected', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, readonly=False, store=True) # in minutes duration = fields.Float( 'Real Duration', compute='_compute_duration', inverse='_set_duration', diff --git a/addons/mrp/models/stock_scrap.py b/addons/mrp/models/stock_scrap.py index b8f4184c8de..5484e9a2ca0 100644 --- a/addons/mrp/models/stock_scrap.py +++ b/addons/mrp/models/stock_scrap.py @@ -8,17 +8,16 @@ class StockScrap(models.Model): production_id = fields.Many2one( 'mrp.production', 'Manufacturing Order', - states={'done': [('readonly', True)]}, check_company=True) + check_company=True) workorder_id = fields.Many2one( 'mrp.workorder', 'Work Order', - states={'done': [('readonly', True)]}, check_company=True) # Not to restrict or prefer quants, but informative product_is_kit = fields.Boolean(related='product_id.is_kits') product_template = fields.Many2one(related='product_id.product_tmpl_id') bom_id = fields.Many2one( 'mrp.bom', 'Kit', domain="[('type', '=', 'phantom'), '|', ('product_id', '=', product_id), '&', ('product_id', '=', False), ('product_tmpl_id', '=', product_template)]", - states={'done': [('readonly', True)]}, check_company=True) + check_company=True) @api.onchange('workorder_id') def _onchange_workorder_id(self): diff --git a/addons/mrp_landed_costs/models/stock_landed_cost.py b/addons/mrp_landed_costs/models/stock_landed_cost.py index cb6d9c10304..edc6b5d40d8 100644 --- a/addons/mrp_landed_costs/models/stock_landed_cost.py +++ b/addons/mrp_landed_costs/models/stock_landed_cost.py @@ -12,7 +12,7 @@ class StockLandedCost(models.Model): ], ondelete={'manufacturing': 'set default'}) mrp_production_ids = fields.Many2many( 'mrp.production', string='Manufacturing order', - copy=False, states={'done': [('readonly', True)]}, groups='stock.group_stock_manager') + copy=False, groups='stock.group_stock_manager') @api.onchange('target_model') def _onchange_target_model(self): diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 0399d09e901..c5fbd097c21 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -255,28 +255,24 @@ class PosOrder(models.Model): comodel_name='res.users', string='Responsible', help="Person who uses the cash register. It can be a reliever, a student or an interim employee.", default=lambda self: self.env.uid, - states={'done': [('readonly', True)], 'invoiced': [('readonly', True)]}, ) amount_tax = fields.Float(string='Taxes', digits=0, readonly=True, required=True) amount_total = fields.Float(string='Total', digits=0, readonly=True, required=True) - amount_paid = fields.Float(string='Paid', states={'draft': [('readonly', False)]}, - readonly=True, digits=0, required=True) + amount_paid = fields.Float(string='Paid', digits=0, required=True) amount_return = fields.Float(string='Returned', digits=0, required=True, readonly=True) margin = fields.Monetary(string="Margin", compute='_compute_margin') margin_percent = fields.Float(string="Margin (%)", compute='_compute_margin', digits=(12, 4)) is_total_cost_computed = fields.Boolean(compute='_compute_is_total_cost_computed', help="Allows to know if all the total cost of the order lines have already been computed") - lines = fields.One2many('pos.order.line', 'order_id', string='Order Lines', states={'draft': [('readonly', False)]}, readonly=True, copy=True) + lines = fields.One2many('pos.order.line', 'order_id', string='Order Lines', copy=True) company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True) - pricelist_id = fields.Many2one('product.pricelist', string='Pricelist', states={ - 'draft': [('readonly', False)]}, readonly=True) - partner_id = fields.Many2one('res.partner', string='Customer', change_default=True, index='btree_not_null', states={'draft': [('readonly', False)], 'paid': [('readonly', False)]}) + pricelist_id = fields.Many2one('product.pricelist', string='Pricelist') + partner_id = fields.Many2one('res.partner', string='Customer', change_default=True, index='btree_not_null') sequence_number = fields.Integer(string='Sequence Number', help='A session-unique sequence number for the order', default=1) session_id = fields.Many2one( 'pos.session', string='Session', required=True, index=True, - domain="[('state', '=', 'opened')]", states={'draft': [('readonly', False)]}, - readonly=True) + domain="[('state', '=', 'opened')]") config_id = fields.Many2one('pos.config', related='session_id.config_id', string="Point of Sale", readonly=False) currency_id = fields.Many2one('res.currency', related='config_id.currency_id', string="Currency") currency_rate = fields.Float("Currency Rate", compute='_compute_currency_rate', compute_sudo=True, store=True, digits=0, readonly=True, @@ -299,8 +295,7 @@ class PosOrder(models.Model): sale_journal = fields.Many2one('account.journal', related='session_id.config_id.journal_id', string='Sales Journal', store=True, readonly=True, ondelete='restrict') fiscal_position_id = fields.Many2one( comodel_name='account.fiscal.position', string='Fiscal Position', - readonly=True, - states={'draft': [('readonly', False)]}, + readonly=False, ) payment_ids = fields.One2many('pos.payment', 'pos_order_id', string='Payments', readonly=True) session_move_id = fields.Many2one('account.move', string='Session Journal Entry', related='session_id.move_id', readonly=True, copy=False) diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index 51751632848..72f7ec32801 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -37,8 +37,7 @@ class PosSession(models.Model): 'res.users', string='Opened By', required=True, index=True, - readonly=True, - states={'opening_control': [('readonly', False)]}, + readonly=False, default=lambda self: self.env.uid, ondelete='restrict') currency_id = fields.Many2one('res.currency', related='config_id.currency_id', string="Currency", readonly=False) diff --git a/addons/pos_hr/models/pos_order.py b/addons/pos_hr/models/pos_order.py index f11c6c2e2d2..49e28e5d5ac 100644 --- a/addons/pos_hr/models/pos_order.py +++ b/addons/pos_hr/models/pos_order.py @@ -5,7 +5,7 @@ from odoo import models, fields, api class PosOrder(models.Model): _inherit = "pos.order" - employee_id = fields.Many2one('hr.employee', help="Person who uses the cash register. It can be a reliever, a student or an interim employee.", states={'done': [('readonly', True)], 'invoiced': [('readonly', True)]}) + employee_id = fields.Many2one('hr.employee', help="Person who uses the cash register. It can be a reliever, a student or an interim employee.") cashier = fields.Char(string="Cashier", compute="_compute_cashier", store=True) @api.model diff --git a/addons/pos_online_payment/models/pos_order.py b/addons/pos_online_payment/models/pos_order.py index b5d1810f67a..e49c56ba4c7 100644 --- a/addons/pos_online_payment/models/pos_order.py +++ b/addons/pos_online_payment/models/pos_order.py @@ -8,7 +8,7 @@ class PosOrder(models.Model): _inherit = 'pos.order' online_payment_method_id = fields.Many2one('pos.payment.method', compute="_compute_online_payment_method_id") - next_online_payment_amount = fields.Float(string='Next online payment amount to pay', states={'draft': [('readonly', False)]}, readonly=True, digits=0, required=False) # unlimited precision + next_online_payment_amount = fields.Float(string='Next online payment amount to pay', digits=0, required=False) # unlimited precision @api.depends('config_id.payment_method_ids') def _compute_online_payment_method_id(self): diff --git a/addons/purchase/models/account_invoice.py b/addons/purchase/models/account_invoice.py index b71325a7a67..316160042e0 100644 --- a/addons/purchase/models/account_invoice.py +++ b/addons/purchase/models/account_invoice.py @@ -15,12 +15,10 @@ TOLERANCE = 0.02 # tolerance applied to the total when searching for a matching class AccountMove(models.Model): _inherit = 'account.move' - purchase_vendor_bill_id = fields.Many2one('purchase.bill.union', store=False, readonly=True, - states={'draft': [('readonly', False)]}, + purchase_vendor_bill_id = fields.Many2one('purchase.bill.union', store=False, readonly=False, string='Auto-complete', help="Auto-complete from a past bill / purchase order.") - purchase_id = fields.Many2one('purchase.order', store=False, readonly=True, - states={'draft': [('readonly', False)]}, + purchase_id = fields.Many2one('purchase.order', store=False, readonly=False, string='Purchase Order', help="Auto-complete from a past purchase order.") purchase_order_count = fields.Integer(compute="_compute_origin_po_count", string='Purchase Order Count') diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py index ad1f9dd5372..b7f9639d388 100644 --- a/addons/purchase/models/purchase.py +++ b/addons/purchase/models/purchase.py @@ -73,12 +73,6 @@ class PurchaseOrder(models.Model): order.invoice_ids = invoices order.invoice_count = len(invoices) - READONLY_STATES = { - 'purchase': [('readonly', True)], - 'done': [('readonly', True)], - 'cancel': [('readonly', True)], - } - name = fields.Char('Order Reference', required=True, index='trigram', copy=False, default='New') priority = fields.Selection( [('0', 'Normal'), ('1', 'Urgent')], 'Priority', default='0', index=True) @@ -90,14 +84,14 @@ class PurchaseOrder(models.Model): "It's used to do the matching when you receive the " "products as this reference is usually written on the " "delivery order sent by your vendor.") - date_order = fields.Datetime('Order Deadline', required=True, states=READONLY_STATES, index=True, copy=False, default=fields.Datetime.now, + date_order = fields.Datetime('Order Deadline', required=True, index=True, copy=False, default=fields.Datetime.now, help="Depicts the date within which the Quotation should be confirmed and converted into a purchase order.") date_approve = fields.Datetime('Confirmation Date', readonly=True, index=True, copy=False) - partner_id = fields.Many2one('res.partner', string='Vendor', required=True, states=READONLY_STATES, change_default=True, tracking=True, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", help="You can find a vendor by its Name, TIN, Email or Internal Reference.") - dest_address_id = fields.Many2one('res.partner', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", string='Dropship Address', states=READONLY_STATES, + partner_id = fields.Many2one('res.partner', string='Vendor', required=True, change_default=True, tracking=True, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", help="You can find a vendor by its Name, TIN, Email or Internal Reference.") + dest_address_id = fields.Many2one('res.partner', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", string='Dropship Address', help="Put an address if you want to deliver directly from the vendor to the customer. " "Otherwise, keep empty to deliver to your own company.") - currency_id = fields.Many2one('res.currency', 'Currency', required=True, states=READONLY_STATES, + currency_id = fields.Many2one('res.currency', 'Currency', required=True, default=lambda self: self.env.company.currency_id.id) state = fields.Selection([ ('draft', 'RFQ'), @@ -107,7 +101,7 @@ class PurchaseOrder(models.Model): ('done', 'Locked'), ('cancel', 'Cancelled') ], string='Status', readonly=True, index=True, copy=False, default='draft', tracking=True) - order_line = fields.One2many('purchase.order.line', 'order_id', string='Order Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True) + order_line = fields.One2many('purchase.order.line', 'order_id', string='Order Lines', copy=True) notes = fields.Html('Terms and Conditions') invoice_count = fields.Integer(compute="_compute_invoice", string='Bill Count', copy=False, default=0, store=True) @@ -138,13 +132,13 @@ class PurchaseOrder(models.Model): related='company_id.tax_calculation_rounding_method', string='Tax calculation rounding method', readonly=True) payment_term_id = fields.Many2one('account.payment.term', 'Payment Terms', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") - incoterm_id = fields.Many2one('account.incoterms', 'Incoterm', states={'done': [('readonly', True)]}, help="International Commercial Terms are a series of predefined commercial terms used in international transactions.") + incoterm_id = fields.Many2one('account.incoterms', 'Incoterm', help="International Commercial Terms are a series of predefined commercial terms used in international transactions.") product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product') user_id = fields.Many2one( 'res.users', string='Buyer', index=True, tracking=True, default=lambda self: self.env.user, check_company=True) - company_id = fields.Many2one('res.company', 'Company', required=True, index=True, states=READONLY_STATES, default=lambda self: self.env.company.id) + company_id = fields.Many2one('res.company', 'Company', required=True, index=True, default=lambda self: self.env.company.id) country_code = fields.Char(related='company_id.account_fiscal_country_id.code', string="Country code") currency_rate = fields.Float("Currency Rate", compute='_compute_currency_rate', compute_sudo=True, store=True, readonly=True, help='Ratio between the purchase order currency and the company currency') diff --git a/addons/purchase_requisition/models/purchase_requisition.py b/addons/purchase_requisition/models/purchase_requisition.py index 606f2ad26e1..db23c16253f 100644 --- a/addons/purchase_requisition/models/purchase_requisition.py +++ b/addons/purchase_requisition/models/purchase_requisition.py @@ -59,8 +59,8 @@ class PurchaseRequisition(models.Model): default=lambda self: self.env.user, check_company=True) description = fields.Html() company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env.company) - purchase_ids = fields.One2many('purchase.order', 'requisition_id', string='Purchase Orders', states={'done': [('readonly', True)]}) - line_ids = fields.One2many('purchase.requisition.line', 'requisition_id', string='Products to Purchase', states={'done': [('readonly', True)]}, copy=True) + purchase_ids = fields.One2many('purchase.order', 'requisition_id', string='Purchase Orders') + line_ids = fields.One2many('purchase.requisition.line', 'requisition_id', string='Products to Purchase', copy=True) product_id = fields.Many2one('product.product', related='line_ids.product_id', string='Product') state = fields.Selection(PURCHASE_REQUISITION_STATES, 'Status', tracking=True, required=True, diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index b9cb60d66c9..19c85e5a0df 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -17,11 +17,11 @@ class PurchaseOrder(models.Model): def _default_picking_type(self): return self._get_picking_type(self.env.context.get('company_id') or self.env.company.id) - incoterm_location = fields.Char(string='Incoterm Location', states={'done': [('readonly', True)]}) + incoterm_location = fields.Char(string='Incoterm Location') incoming_picking_count = fields.Integer("Incoming Shipment count", compute='_compute_incoming_picking_count') picking_ids = fields.Many2many('stock.picking', compute='_compute_picking_ids', string='Receptions', copy=False, store=True) dest_address_id = fields.Many2one('res.partner', compute='_compute_dest_address_id', store=True, readonly=False) - picking_type_id = fields.Many2one('stock.picking.type', 'Deliver To', states=Purchase.READONLY_STATES, required=True, default=_default_picking_type, domain="['|', ('warehouse_id', '=', False), ('warehouse_id.company_id', '=', company_id)]", + picking_type_id = fields.Many2one('stock.picking.type', 'Deliver To', required=True, default=_default_picking_type, domain="['|', ('warehouse_id', '=', False), ('warehouse_id.company_id', '=', company_id)]", help="This will determine operation type of incoming shipment") default_location_dest_id_usage = fields.Selection(related='picking_type_id.default_location_dest_id.usage', string='Destination Location Type', help="Technical field used to display the Drop Ship Address", readonly=True) diff --git a/addons/repair/models/repair.py b/addons/repair/models/repair.py index 4facb47b95a..166e3464c56 100644 --- a/addons/repair/models/repair.py +++ b/addons/repair/models/repair.py @@ -61,8 +61,7 @@ class Repair(models.Model): tag_ids = fields.Many2many('repair.tags', string="Tags") under_warranty = fields.Boolean( 'Under Warranty', - help='If ticked, the sales price will be set to 0 for all products transferred from the repair order.', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}) + help='If ticked, the sales price will be set to 0 for all products transferred from the repair order.') schedule_date = fields.Datetime("Scheduled Date", default=fields.Datetime.now, index=True, required=True, copy=False) # Product To Repair @@ -72,15 +71,14 @@ class Repair(models.Model): product_id = fields.Many2one( 'product.product', string='Product to Repair', domain="[('type', 'in', ['product', 'consu']), '|', ('company_id', '=', company_id), ('company_id', '=', False)]", - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, check_company=True) + check_company=True) product_qty = fields.Float( 'Product Quantity', - default=1.0, digits='Product Unit of Measure', - readonly=True, states={'draft': [('readonly', False)]}) + default=1.0, digits='Product Unit of Measure') product_uom = fields.Many2one( 'uom.uom', 'Product Unit of Measure', compute='compute_product_uom', store=True, precompute=True, - readonly=True, states={'draft': [('readonly', False)]}, domain="[('category_id', '=', product_uom_category_id)]") + domain="[('category_id', '=', product_uom_category_id)]") product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id') lot_id = fields.Many2one( 'stock.lot', 'Lot/Serial', diff --git a/addons/sale/models/sale_order.py b/addons/sale/models/sale_order.py index 6533dec7d96..353ccdc956a 100644 --- a/addons/sale/models/sale_order.py +++ b/addons/sale/models/sale_order.py @@ -12,11 +12,6 @@ from odoo.tools.sql import create_index from odoo.addons.payment import utils as payment_utils -READONLY_FIELD_STATES = { - state: [('readonly', True)] - for state in {'sale', 'cancel'} -} - INVOICE_STATUS = [ ('upselling', 'Upselling Opportunity'), ('invoiced', 'Fully Invoiced'), @@ -55,9 +50,8 @@ class SaleOrder(models.Model): name = fields.Char( string="Order Reference", - required=True, copy=False, readonly=True, + required=True, copy=False, readonly=False, index='trigram', - states={'draft': [('readonly', False)]}, default=lambda self: _('New')) company_id = fields.Many2one( @@ -67,9 +61,8 @@ class SaleOrder(models.Model): partner_id = fields.Many2one( comodel_name='res.partner', string="Customer", - required=True, readonly=False, change_default=True, index=True, + required=True, change_default=True, index=True, tracking=1, - states=READONLY_FIELD_STATES, domain="[('company_id', 'in', (False, company_id))]") state = fields.Selection( selection=SALE_ORDER_STATE, @@ -89,8 +82,7 @@ class SaleOrder(models.Model): "this date rather than product lead times.") date_order = fields.Datetime( string="Order Date", - required=True, readonly=False, copy=False, - states=READONLY_FIELD_STATES, + required=True, copy=False, help="Creation date of draft/sent orders,\nConfirmation date of confirmed orders.", default=fields.Datetime.now) origin = fields.Char( @@ -105,13 +97,11 @@ class SaleOrder(models.Model): string="Online Signature", compute='_compute_require_signature', store=True, readonly=False, precompute=True, - states=READONLY_FIELD_STATES, help="Request a online signature and/or payment to the customer in order to confirm orders automatically.") require_payment = fields.Boolean( string="Online Payment", compute='_compute_require_payment', - store=True, readonly=False, precompute=True, - states=READONLY_FIELD_STATES) + store=True, readonly=False, precompute=True) signature = fields.Image( string="Signature", @@ -124,8 +114,7 @@ class SaleOrder(models.Model): validity_date = fields.Date( string="Expiration", compute='_compute_validity_date', - store=True, readonly=False, copy=False, precompute=True, - states=READONLY_FIELD_STATES) + store=True, readonly=False, copy=False, precompute=True) # Partner-based computes note = fields.Html( @@ -159,14 +148,12 @@ class SaleOrder(models.Model): string="Payment Terms", compute='_compute_payment_term_id', store=True, readonly=False, precompute=True, check_company=True, # Unrequired company - states=READONLY_FIELD_STATES, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") pricelist_id = fields.Many2one( comodel_name='product.pricelist', string="Pricelist", compute='_compute_pricelist_id', store=True, readonly=False, precompute=True, check_company=True, # Unrequired company - states=READONLY_FIELD_STATES, tracking=1, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", help="If you change the pricelist, only newly added lines will be affected.") @@ -250,7 +237,6 @@ class SaleOrder(models.Model): comodel_name='account.analytic.account', string="Analytic Account", copy=False, check_company=True, # Unrequired company - states=READONLY_FIELD_STATES, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") tag_ids = fields.Many2many( comodel_name='crm.tag', diff --git a/addons/sale/models/utm_campaign.py b/addons/sale/models/utm_campaign.py index cc7de72b68f..33af74d87e7 100644 --- a/addons/sale/models/utm_campaign.py +++ b/addons/sale/models/utm_campaign.py @@ -11,7 +11,7 @@ class UtmCampaign(models.Model): compute="_compute_quotation_count", compute_sudo=True, groups='sales_team.group_sale_salesman') invoiced_amount = fields.Integer(string="Revenues generated by the campaign", compute="_compute_sale_invoiced_amount", compute_sudo=True, groups='sales_team.group_sale_salesman') - company_id = fields.Many2one('res.company', string='Company', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.company) + company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company) currency_id = fields.Many2one('res.currency', related='company_id.currency_id', string='Currency') def _compute_quotation_count(self): diff --git a/addons/sale_expense/models/hr_expense.py b/addons/sale_expense/models/hr_expense.py index 536cd75cea6..cc40a78aa12 100644 --- a/addons/sale_expense/models/hr_expense.py +++ b/addons/sale_expense/models/hr_expense.py @@ -8,7 +8,6 @@ class Expense(models.Model): _inherit = "hr.expense" sale_order_id = fields.Many2one('sale.order', compute='_compute_sale_order_id', store=True, string='Customer to Reinvoice', readonly=False, tracking=True, - states={'done': [('readonly', True)], 'refused': [('readonly', True)]}, # NOTE: only confirmed SO can be selected, but this domain in activated throught the name search with the `sale_expense_all_order` # context key. So, this domain is not the one applied. domain="[('state', '=', 'sale'), ('company_id', '=', company_id)]", diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py index 8b2a6d40def..f9bae843163 100644 --- a/addons/sale_management/models/sale_order.py +++ b/addons/sale_management/models/sale_order.py @@ -7,8 +7,6 @@ from odoo import SUPERUSER_ID, api, fields, models, _ from odoo.exceptions import ValidationError from odoo.tools import is_html_empty -from odoo.addons.sale.models.sale_order import READONLY_FIELD_STATES - class SaleOrder(models.Model): _inherit = 'sale.order' @@ -18,12 +16,10 @@ class SaleOrder(models.Model): string="Quotation Template", compute='_compute_sale_order_template_id', store=True, readonly=False, check_company=True, precompute=True, - states=READONLY_FIELD_STATES, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") sale_order_option_ids = fields.One2many( comodel_name='sale.order.option', inverse_name='order_id', string="Optional Products Lines", - states=READONLY_FIELD_STATES, copy=True) #=== COMPUTE METHODS ===# diff --git a/addons/sale_project/models/sale_order.py b/addons/sale_project/models/sale_order.py index db4b6f9224b..ec477f7a9dc 100644 --- a/addons/sale_project/models/sale_order.py +++ b/addons/sale_project/models/sale_order.py @@ -15,8 +15,7 @@ class SaleOrder(models.Model): tasks_count = fields.Integer(string='Tasks', compute='_compute_tasks_ids', groups="project.group_project_user") visible_project = fields.Boolean('Display project', compute='_compute_visible_project', readonly=True) - project_id = fields.Many2one( - 'project.project', 'Project', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, + project_id = fields.Many2one('project.project', 'Project', help='Select a non billable project on which tasks can be created.') project_ids = fields.Many2many('project.project', compute="_compute_project_ids", string='Projects', copy=False, groups="project.group_project_user", help="Projects used in this sales order.") project_count = fields.Integer(string='Number of Projects', compute='_compute_project_ids', groups='project.group_project_user') diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index 04d669bab17..8979822cb3c 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -20,14 +20,12 @@ class SaleOrder(models.Model): picking_policy = fields.Selection([ ('direct', 'As soon as possible'), ('one', 'When all products are ready')], - string='Shipping Policy', required=True, readonly=True, default='direct', - states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, + string='Shipping Policy', required=True, default='direct', help="If you deliver all products at once, the delivery order will be scheduled based on the greatest " "product lead time. Otherwise, it will be based on the shortest.") warehouse_id = fields.Many2one( 'stock.warehouse', string='Warehouse', required=True, compute='_compute_warehouse_id', store=True, readonly=False, precompute=True, - states={'sale': [('readonly', True)], 'cancel': [('readonly', False)]}, check_company=True) picking_ids = fields.One2many('stock.picking', 'sale_id', string='Transfers') delivery_count = fields.Integer(string='Delivery Orders', compute='_compute_picking_ids') diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 1401bdd8c0b..0a0182a09c7 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -45,17 +45,16 @@ class StockMove(models.Model): product_id = fields.Many2one( 'product.product', 'Product', check_company=True, - domain="[('type', 'in', ['product', 'consu'])]", index=True, required=True, - states={'done': [('readonly', True)]}) + domain="[('type', 'in', ['product', 'consu'])]", index=True, required=True) description_picking = fields.Text('Description of Picking') product_qty = fields.Float( - 'Real Quantity', compute='_compute_product_qty', inverse='_set_product_qty', + 'Real Quantity', compute='_compute_product_qty', digits=0, store=True, compute_sudo=True, help='Quantity in the default UoM of the product') product_uom_qty = fields.Float( 'Demand', digits='Product Unit of Measure', - default=0, required=True, states={'done': [('readonly', True)]}, + default=0, required=True, help="This is the quantity of products from an inventory " "point of view. For moves in the state 'done', this is the " "quantity of products that were actually moved. For other " @@ -86,7 +85,6 @@ class StockMove(models.Model): location_dest_usage = fields.Selection(string="Destination Location Type", related='location_dest_id.usage') partner_id = fields.Many2one( 'res.partner', 'Destination Address ', - states={'done': [('readonly', True)]}, help="Optional address where goods are to be delivered, specifically used for allotment", compute='_compute_partner_id', store=True, readonly=False) move_dest_ids = fields.Many2many( @@ -97,7 +95,7 @@ class StockMove(models.Model): 'stock.move', 'stock_move_move_rel', 'move_dest_id', 'move_orig_id', 'Original Move', copy=False, help="Optional: previous stock move when chaining them") - picking_id = fields.Many2one('stock.picking', 'Transfer', index=True, states={'done': [('readonly', True)]}, check_company=True) + picking_id = fields.Many2one('stock.picking', 'Transfer', index=True, check_company=True) state = fields.Selection([ ('draft', 'New'), ('waiting', 'Waiting Another Move'), diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 3407d239c7e..e9c20d541d8 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -294,7 +294,6 @@ class Picking(models.Model): copy=False, index='trigram', readonly=True) origin = fields.Char( 'Source Document', index='trigram', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="Reference of the document") note = fields.Html('Notes') backorder_id = fields.Many2one( @@ -311,7 +310,6 @@ class Picking(models.Model): move_type = fields.Selection([ ('direct', 'As soon as possible'), ('one', 'When all products are ready')], 'Shipping Policy', default='direct', required=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="It specifies goods to be deliver partially or all at once") state = fields.Selection([ ('draft', 'Draft'), @@ -337,7 +335,7 @@ class Picking(models.Model): scheduled_date = fields.Datetime( 'Scheduled Date', compute='_compute_scheduled_date', inverse='_set_scheduled_date', store=True, index=True, default=fields.Datetime.now, tracking=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + readonly=False, help="Scheduled time for the first part of the shipment to be processed. Setting manually a value here would set it as expected date for all the stock moves.") date_deadline = fields.Datetime( "Deadline", compute='_compute_date_deadline', store=True, @@ -348,7 +346,6 @@ class Picking(models.Model): date = fields.Datetime( 'Creation Date', default=fields.Datetime.now, tracking=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="Creation Date, usually the time of the order") date_done = fields.Datetime('Date of Transfer', copy=False, readonly=True, help="Date at which the transfer has been processed or cancelled.") delay_alert_date = fields.Datetime('Delay Alert Date', compute='_compute_delay_alert_date', search='_search_delay_alert_date') @@ -356,13 +353,11 @@ class Picking(models.Model): location_id = fields.Many2one( 'stock.location', "Source Location", compute="_compute_location_id", store=True, precompute=True, readonly=False, - check_company=True, required=True, - states={'done': [('readonly', True)]}) + check_company=True, required=True) location_dest_id = fields.Many2one( 'stock.location', "Destination Location", compute="_compute_location_id", store=True, precompute=True, readonly=False, - check_company=True, required=True, - states={'done': [('readonly', True)]}) + check_company=True, required=True) move_ids = fields.One2many('stock.move', 'picking_id', string="Stock Moves", copy=True) move_ids_without_package = fields.One2many( 'stock.move', 'picking_id', string="Stock moves not in package", compute='_compute_move_without_package', @@ -382,15 +377,13 @@ class Picking(models.Model): hide_picking_type = fields.Boolean(compute='_compute_hide_picking_type') partner_id = fields.Many2one( 'res.partner', 'Contact', - check_company=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}) + check_company=True) company_id = fields.Many2one( 'res.company', string='Company', related='picking_type_id.company_id', readonly=True, store=True, index=True) user_id = fields.Many2one( 'res.users', 'Responsible', tracking=True, domain=lambda self: [('groups_id', 'in', self.env.ref('stock.group_stock_user').id)], - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, default=lambda self: self.env.user) move_line_ids = fields.One2many('stock.move.line', 'picking_id', 'Operations') move_line_ids_without_package = fields.One2many('stock.move.line', 'picking_id', 'Operations without package', domain=['|',('package_level_id', '=', False), ('picking_type_entire_packs', '=', False)]) @@ -414,7 +407,6 @@ class Picking(models.Model): help='Technical Field used to decide whether the button "Allocation" should be displayed.') owner_id = fields.Many2one( 'res.partner', 'Assign Owner', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, check_company=True, help="When validating the transfer, the products will be assigned to this owner.") printed = fields.Boolean('Printed', copy=False) diff --git a/addons/stock/models/stock_scrap.py b/addons/stock/models/stock_scrap.py index ac8566cf92b..a51b5674b44 100644 --- a/addons/stock/models/stock_scrap.py +++ b/addons/stock/models/stock_scrap.py @@ -15,45 +15,44 @@ class StockScrap(models.Model): name = fields.Char( 'Reference', default=lambda self: _('New'), - copy=False, readonly=True, required=True, - states={'done': [('readonly', True)]}) - company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company, required=True, states={'done': [('readonly', True)]}) + copy=False, required=True) + company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company, required=True) origin = fields.Char(string='Source Document') product_id = fields.Many2one( 'product.product', 'Product', domain="[('type', 'in', ['product', 'consu'])]", - required=True, states={'done': [('readonly', True)]}, check_company=True) + required=True, check_company=True) product_uom_id = fields.Many2one( 'uom.uom', 'Unit of Measure', compute="_compute_product_uom_id", store=True, readonly=False, precompute=True, - required=True, states={'done': [('readonly', True)]}, domain="[('category_id', '=', product_uom_category_id)]") + required=True, domain="[('category_id', '=', product_uom_category_id)]") product_uom_category_id = fields.Many2one(related='product_id.uom_id.category_id') tracking = fields.Selection(string='Product Tracking', readonly=True, related="product_id.tracking") lot_id = fields.Many2one( 'stock.lot', 'Lot/Serial', - states={'done': [('readonly', True)]}, domain="[('product_id', '=', product_id)]", check_company=True) + domain="[('product_id', '=', product_id)]", check_company=True) package_id = fields.Many2one( 'stock.quant.package', 'Package', - states={'done': [('readonly', True)]}, check_company=True) - owner_id = fields.Many2one('res.partner', 'Owner', states={'done': [('readonly', True)]}, check_company=True) + check_company=True) + owner_id = fields.Many2one('res.partner', 'Owner', check_company=True) move_ids = fields.One2many('stock.move', 'scrap_id') - picking_id = fields.Many2one('stock.picking', 'Picking', states={'done': [('readonly', True)]}, check_company=True) + picking_id = fields.Many2one('stock.picking', 'Picking', check_company=True) location_id = fields.Many2one( 'stock.location', 'Source Location', - compute='_compute_location_id', store=True, required=True, precompute=True, states={'done': [('readonly', True)]}, + compute='_compute_location_id', store=True, required=True, precompute=True, domain="[('usage', '=', 'internal')]", check_company=True, readonly=False) scrap_location_id = fields.Many2one( 'stock.location', 'Scrap Location', - compute='_compute_scrap_location_id', store=True, required=True, precompute=True, states={'done': [('readonly', True)]}, + compute='_compute_scrap_location_id', store=True, required=True, precompute=True, domain="[('scrap_location', '=', True)]", check_company=True, readonly=False) scrap_qty = fields.Float( - 'Quantity', required=True, states={'done': [('readonly', True)]}, digits='Product Unit of Measure', + 'Quantity', required=True, digits='Product Unit of Measure', compute='_compute_scrap_qty', default=0.0, readonly=False, store=True) state = fields.Selection([ ('draft', 'Draft'), ('done', 'Done')], string='Status', default="draft", readonly=True, tracking=True) date_done = fields.Datetime('Date', readonly=True) - should_replenish = fields.Boolean(string='Replenish Scrapped Quantities', states={'done': [('readonly', True)]}) + should_replenish = fields.Boolean(string='Replenish Scrapped Quantities') @api.depends('product_id') def _compute_product_uom_id(self): diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py index f0a03097918..0bd746bff12 100644 --- a/addons/stock_landed_costs/models/stock_landed_cost.py +++ b/addons/stock_landed_costs/models/stock_landed_cost.py @@ -37,22 +37,21 @@ class StockLandedCost(models.Model): copy=False, readonly=True, tracking=True) date = fields.Date( 'Date', default=fields.Date.context_today, - copy=False, required=True, states={'done': [('readonly', True)]}, tracking=True) + copy=False, required=True, tracking=True) target_model = fields.Selection( [('picking', 'Transfers')], string="Apply On", required=True, default='picking', - copy=False, states={'done': [('readonly', True)]}) + copy=False) picking_ids = fields.Many2many( 'stock.picking', string='Transfers', - copy=False, states={'done': [('readonly', True)]}) + copy=False) cost_lines = fields.One2many( 'stock.landed.cost.lines', 'cost_id', 'Cost Lines', - copy=True, states={'done': [('readonly', True)]}) + copy=True) valuation_adjustment_lines = fields.One2many( - 'stock.valuation.adjustment.lines', 'cost_id', 'Valuation Adjustments', - states={'done': [('readonly', True)]}) + 'stock.valuation.adjustment.lines', 'cost_id', 'Valuation Adjustments',) description = fields.Text( - 'Item Description', states={'done': [('readonly', True)]}) + 'Item Description') amount_total = fields.Monetary( 'Total', compute='_compute_total_amount', store=True, tracking=True) @@ -66,7 +65,7 @@ class StockLandedCost(models.Model): copy=False, readonly=True) account_journal_id = fields.Many2one( 'account.journal', 'Account Journal', - required=True, states={'done': [('readonly', True)]}, default=lambda self: self._default_account_journal_id()) + required=True, default=lambda self: self._default_account_journal_id()) company_id = fields.Many2one('res.company', string="Company", related='account_journal_id.company_id') stock_valuation_layer_ids = fields.One2many('stock.valuation.layer', 'stock_landed_cost_id') diff --git a/addons/stock_picking_batch/models/stock_picking.py b/addons/stock_picking_batch/models/stock_picking.py index dbeb3ef1852..8523dbf5b74 100644 --- a/addons/stock_picking_batch/models/stock_picking.py +++ b/addons/stock_picking_batch/models/stock_picking.py @@ -65,7 +65,6 @@ class StockPicking(models.Model): batch_id = fields.Many2one( 'stock.picking.batch', string='Batch Transfer', check_company=True, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help='Batch associated to this transfer', index=True, copy=False) @api.model_create_multi diff --git a/addons/stock_picking_batch/models/stock_picking_batch.py b/addons/stock_picking_batch/models/stock_picking_batch.py index 598cf65ea7b..7be6d982a24 100644 --- a/addons/stock_picking_batch/models/stock_picking_batch.py +++ b/addons/stock_picking_batch/models/stock_picking_batch.py @@ -19,14 +19,13 @@ class StockPickingBatch(models.Model): copy=False, required=True, readonly=True) user_id = fields.Many2one( 'res.users', string='Responsible', tracking=True, check_company=True, - readonly=True, states={'draft': [('readonly', False)], 'in_progress': [('readonly', False)]}) + readonly=False) company_id = fields.Many2one( 'res.company', string="Company", required=True, readonly=True, index=True, default=lambda self: self.env.company) picking_ids = fields.One2many( - 'stock.picking', 'batch_id', string='Transfers', readonly=True, + 'stock.picking', 'batch_id', string='Transfers', readonly=False, domain="[('id', 'in', allowed_picking_ids)]", check_company=True, - states={'draft': [('readonly', False)], 'in_progress': [('readonly', False)]}, help='List of transfers associated to this batch') show_check_availability = fields.Boolean( compute='_compute_move_ids', @@ -42,8 +41,7 @@ class StockPickingBatch(models.Model): 'stock.move', string="Stock moves", compute='_compute_move_ids') move_line_ids = fields.One2many( 'stock.move.line', string='Stock move lines', - compute='_compute_move_ids', inverse='_set_move_line_ids', readonly=True, - states={'draft': [('readonly', False)], 'in_progress': [('readonly', False)]}) + compute='_compute_move_ids', inverse='_set_move_line_ids', readonly=False) state = fields.Selection([ ('draft', 'Draft'), ('in_progress', 'In progress'), @@ -53,12 +51,11 @@ class StockPickingBatch(models.Model): copy=False, tracking=True, required=True, readonly=True, index=True) picking_type_id = fields.Many2one( 'stock.picking.type', 'Operation Type', check_company=True, copy=False, - readonly=True, index=True, states={'draft': [('readonly', False)]}) + index=True) picking_type_code = fields.Selection( related='picking_type_id.code') scheduled_date = fields.Datetime( 'Scheduled Date', copy=False, store=True, readonly=False, compute="_compute_scheduled_date", - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="""Scheduled date for the transfers to be processed. - If manually set then scheduled date for all transfers in batch will automatically update to this date. - If not manually changed and transfers are added/removed/updated then this will be their earliest scheduled date diff --git a/addons/test_base_import/models/test_base_import.py b/addons/test_base_import/models/test_base_import.py index e2441db2330..61cad456a99 100644 --- a/addons/test_base_import/models/test_base_import.py +++ b/addons/test_base_import/models/test_base_import.py @@ -23,23 +23,17 @@ class CharReadonly(models.Model): value = fields.Char(readonly=True) -class CharStates(models.Model): - _name = model('char.states') - _description = 'Tests: Base Import Model, Character states' - - value = fields.Char(readonly=True, states={'draft': [('readonly', False)]}) - class CharNoreadonly(models.Model): _name = model('char.noreadonly') _description = 'Tests: Base Import Model, Character No readonly' - value = fields.Char(readonly=True, states={'draft': [('invisible', True)]}) + value = fields.Char(readonly=True) class CharStillreadonly(models.Model): _name = model('char.stillreadonly') _description = 'Tests: Base Import Model, Character still readonly' - value = fields.Char(readonly=True, states={'draft': [('readonly', True)]}) + value = fields.Char(readonly=True) # TODO: complex field (m2m, o2m, m2o) class M2o(models.Model): diff --git a/addons/test_base_import/security/ir.model.access.csv b/addons/test_base_import/security/ir.model.access.csv index 902d9fbaa1d..673198575b7 100644 --- a/addons/test_base_import/security/ir.model.access.csv +++ b/addons/test_base_import/security/ir.model.access.csv @@ -2,7 +2,6 @@ access_test_base_import_char,base.import.tests.models.char,model_base_import_char,base.group_user,1,1,1,1 access_test_base_import_char_required,base.import.tests.models.char.required,model_base_import_char_required,base.group_user,1,1,1,1 access_test_base_import_char_readonly,base.import.tests.models.char.readonly,model_base_import_char_readonly,base.group_user,1,1,1,1 -access_test_base_import_char_states,base.import.tests.models.char.states,model_base_import_char_states,base.group_user,1,1,1,1 access_test_base_import_char_noreadonly,base.import.tests.models.char.noreadonly,model_base_import_char_noreadonly,base.group_user,1,1,1,1 access_test_base_import_char_stillreadonly,base.import.tests.models.char.stillreadonly,model_base_import_char_stillreadonly,base.group_user,1,1,1,1 access_test_base_import_m2o,base.import.tests.models.m2o,model_base_import_m2o,base.group_user,1,1,1,1 diff --git a/addons/test_base_import/tests/test_base_import.py b/addons/test_base_import/tests/test_base_import.py index de585651e88..d5d407dbf99 100644 --- a/addons/test_base_import/tests/test_base_import.py +++ b/addons/test_base_import/tests/test_base_import.py @@ -71,10 +71,6 @@ class TestBasicFields(BaseImportCase): """ Readonly fields should be filtered out""" self.assertEqualFields(self.get_fields('char.readonly'), [ID_FIELD]) - def test_readonly_states(self): - """ Readonly fields with states should not be filtered out""" - self.assertEqualFields(self.get_fields('char.states'), make_field(field_type='char', model_name=base_import_model('char.states'))) - def test_readonly_states_noreadonly(self): """ Readonly fields with states having nothing to do with readonly should still be filtered out""" diff --git a/odoo/addons/test_new_api/models/test_new_api.py b/odoo/addons/test_new_api/models/test_new_api.py index cfdd3f927d9..17c875fa9bf 100644 --- a/odoo/addons/test_new_api/models/test_new_api.py +++ b/odoo/addons/test_new_api/models/test_new_api.py @@ -1638,9 +1638,7 @@ class PrecomputeReadonly(models.Model): ('confirmed', 'Confirmed'), ], default='draft') bar = fields.Char(compute='_compute_bar', precompute=True, store=True, readonly=True) - baz = fields.Char( - compute='_compute_baz', precompute=True, store=True, readonly=True, states={'draft': [('readonly', False)]} - ) + baz = fields.Char(compute='_compute_baz', precompute=True, store=True, readonly=False) @api.depends('foo') def _compute_bar(self): diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index 2e3f3fc227b..294a3edf0e1 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -4605,7 +4605,7 @@ class TestPrecompute(common.TransactionCase): but with a states attributes changing the readonly of the field according to the state of the record, can be altered by the user. The `bar` field is store=True, precompute=True, readonly=True - The `baz` field is store=True, precompute=True, readonly=True, states={'draft': [('readonly', False)]} + The `baz` field is store=True, precompute=True, readonly=False, """ model = self.env['test_new_api.precompute.readonly'] @@ -4621,7 +4621,7 @@ class TestPrecompute(common.TransactionCase): self.assertEqual(record.baz, 'COMPUTED') # no value for bar, value for baz - # baz is readonly=True but states={'draft': [('readonly', False)]} + # baz is readonly=False # the value for baz must be taken into account record = model.create({'foo': 'foo', 'baz': 'baz'}) self.assertEqual(record.bar, 'COMPUTED') diff --git a/odoo/fields.py b/odoo/fields.py index b786688a63b..32a25080f2b 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -544,7 +544,7 @@ class Field(MetaField('DummyField', (object,), {})): warnings.warn(f'Property {self}.readonly should be a boolean ({self.readonly}).') if self.states: - warnings.warn(f'"states" property on the field "{self}" is no longer used', DeprecationWarning) + warnings.warn(f'Since Odoo 17, property {self}.states is no longer supported.') self._setup_done = True @@ -648,8 +648,6 @@ class Field(MetaField('DummyField', (object,), {})): # special cases of inherited fields if self.inherited: self.inherited_field = field - if not self.states: - self.states = field.states if field.required: self.required = True # add modules from delegate and target fields; the first one ensures @@ -904,9 +902,7 @@ class Field(MetaField('DummyField', (object,), {})): def is_editable(self): """ Return whether the field can be editable in a view. """ - return not self.readonly or self.states and any( - 'readonly' in item for items in self.states.values() for item in items - ) + return not self.readonly ############################################################################ # diff --git a/odoo/models.py b/odoo/models.py index 84e41db0cd4..85a9014c358 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -4326,19 +4326,6 @@ class BaseModel(metaclass=MetaModel): fname for fname, field in self._fields.items() if field.precompute and field.readonly - # ignore `readonly=True` when it's combined with the `states` attribute, - # making the field readonly according to the record state. - # e.g. - # product_uom = fields.Many2one( - # 'uom.uom', 'Product Unit of Measure', - # compute='_compute_product_uom', store=True, precompute=True, - # readonly=True, required=True, states={'draft': [('readonly', False)]}, - # ) - and (not field.states or not any( - modifier == 'readonly' - for modifiers in field.states.values() - for modifier, _value in modifiers - )) ) result_vals_list = []