[REF] base/all: Update modifier syntax: remove 'states' from fields
These changes are made as a result of simplifying attrs and 'states' in views. However, they should have remained in a separate commit. When applying the script making the xml changes (used later for the migration script), the script checked the definition of the python fields in order to convert the information into a python expression. Therefore, this commit is not applied when the script is applied to xml changes. During this attribute deletion pre-existing errors were found. Part of the code was using the boolean values of 'states' and another part of the code was not. The behavior could therefore be different (in cases where readonly on the field had the same value as the ballan in 'states'). Following the deletion of 'states' and without the application of the view migration, the js tests (tower) were no longer functional. Tests using the Form view suffered the same effect. There are few tests that had to be adapted, including two tests in business accounting (updated by the accounting team). A test for column_invisible did not work. Test checking if the test system triggers an error if we try to write on an invisible field. It turns out that Form was testing on the value of invisible but not taking into account if the column was invisible. The test system fix is applied separately because there were a lot of tests that were incorrect. Part-of: odoo/odoo#104741
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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')],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)]",
|
||||
|
||||
@@ -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 ===#
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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"""
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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')
|
||||
|
||||
+2
-6
@@ -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
|
||||
|
||||
############################################################################
|
||||
#
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
Reference in New Issue
Block a user