[IMP] *: Convert single create method into multi
Taskid: 2703085 Part-of: odoo/odoo#80824 Co-authored-by: Victor Feyens <vfe@odoo.com>
This commit is contained in:
co-authored by
Victor Feyens
parent
b403c7e068
commit
18952cdc76
@@ -639,21 +639,22 @@ class AccountJournal(models.Model):
|
||||
if 'refund_sequence' not in vals:
|
||||
vals['refund_sequence'] = vals['type'] in ('sale', 'purchase')
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# OVERRIDE
|
||||
self._fill_missing_values(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
self._fill_missing_values(vals)
|
||||
|
||||
journal = super(AccountJournal, self.with_context(mail_create_nolog=True)).create(vals)
|
||||
journals = super(AccountJournal, self.with_context(mail_create_nolog=True)).create(vals_list)
|
||||
|
||||
if 'alias_name' in vals:
|
||||
journal._update_mail_alias(vals)
|
||||
for journal, vals in zip(journals, vals_list):
|
||||
if 'alias_name' in vals:
|
||||
journal._update_mail_alias(vals)
|
||||
|
||||
# Create the bank_account_id if necessary
|
||||
if journal.type == 'bank' and not journal.bank_account_id and vals.get('bank_acc_number'):
|
||||
journal.set_bank_account(vals.get('bank_acc_number'), vals.get('bank_id'))
|
||||
# Create the bank_account_id if necessary
|
||||
if journal.type == 'bank' and not journal.bank_account_id and vals.get('bank_acc_number'):
|
||||
journal.set_bank_account(vals.get('bank_acc_number'), vals.get('bank_id'))
|
||||
|
||||
return journal
|
||||
return journals
|
||||
|
||||
def set_bank_account(self, acc_number, bank_id=None):
|
||||
""" Create a res.partner.bank (if not exists) and set it as value of the field bank_account_id """
|
||||
|
||||
@@ -156,10 +156,11 @@ class AccountPaymentMethodLine(models.Model):
|
||||
account.reconcile = True
|
||||
return super().write(vals)
|
||||
|
||||
@api.model
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
if 'payment_account_id' in vals_list:
|
||||
account = self.env['account.account'].browse(vals_list['payment_account_id'])
|
||||
if not account.reconcile:
|
||||
account.reconcile = True
|
||||
for vals in vals_list:
|
||||
if 'payment_account_id' in vals:
|
||||
account = self.env['account.account'].browse(vals['payment_account_id'])
|
||||
if not account.reconcile:
|
||||
account.reconcile = True
|
||||
return super().create(vals_list)
|
||||
|
||||
@@ -1187,25 +1187,26 @@ class AccountTaxRepartitionLineTemplate(models.Model):
|
||||
plus_report_line_ids = fields.Many2many(string="Plus Tax Report Lines", relation='account_tax_repartition_plus_report_line', comodel_name='account.tax.report.line', copy=True, help="Tax report lines whose '+' tag will be assigned to move lines by this repartition line")
|
||||
minus_report_line_ids = fields.Many2many(string="Minus Report Lines", relation='account_tax_repartition_minus_report_line', comodel_name='account.tax.report.line', copy=True, help="Tax report lines whose '-' tag will be assigned to move lines by this repartition line")
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('plus_report_line_ids'):
|
||||
vals['plus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['plus_report_line_ids'])
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('plus_report_line_ids'):
|
||||
vals['plus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['plus_report_line_ids'])
|
||||
|
||||
if vals.get('minus_report_line_ids'):
|
||||
vals['minus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['minus_report_line_ids'])
|
||||
if vals.get('minus_report_line_ids'):
|
||||
vals['minus_report_line_ids'] = self._convert_tag_syntax_to_orm(vals['minus_report_line_ids'])
|
||||
|
||||
if vals.get('tag_ids'):
|
||||
vals['tag_ids'] = self._convert_tag_syntax_to_orm(vals['tag_ids'])
|
||||
if vals.get('tag_ids'):
|
||||
vals['tag_ids'] = self._convert_tag_syntax_to_orm(vals['tag_ids'])
|
||||
|
||||
if vals.get('use_in_tax_closing') is None:
|
||||
if not vals.get('account_id'):
|
||||
vals['use_in_tax_closing'] = False
|
||||
else:
|
||||
internal_group = self.env['account.account.template'].browse(vals.get('account_id')).user_type_id.internal_group
|
||||
vals['use_in_tax_closing'] = not (internal_group == 'income' or internal_group == 'expense')
|
||||
if vals.get('use_in_tax_closing') is None:
|
||||
if not vals.get('account_id'):
|
||||
vals['use_in_tax_closing'] = False
|
||||
else:
|
||||
internal_group = self.env['account.account.template'].browse(vals.get('account_id')).user_type_id.internal_group
|
||||
vals['use_in_tax_closing'] = not (internal_group == 'income' or internal_group == 'expense')
|
||||
|
||||
return super(AccountTaxRepartitionLineTemplate, self).create(vals)
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.model
|
||||
def _convert_tag_syntax_to_orm(self, tags_list):
|
||||
|
||||
@@ -148,13 +148,14 @@ class AccountFiscalPosition(models.Model):
|
||||
zip_to = zip_to.rjust(max_length, '0')
|
||||
return zip_from, zip_to
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
zip_from = vals.get('zip_from')
|
||||
zip_to = vals.get('zip_to')
|
||||
if zip_from and zip_to:
|
||||
vals['zip_from'], vals['zip_to'] = self._convert_zip_values(zip_from, zip_to)
|
||||
return super(AccountFiscalPosition, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
zip_from = vals.get('zip_from')
|
||||
zip_to = vals.get('zip_to')
|
||||
if zip_from and zip_to:
|
||||
vals['zip_from'], vals['zip_to'] = self._convert_zip_values(zip_from, zip_to)
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
zip_from = vals.get('zip_from')
|
||||
|
||||
@@ -87,21 +87,22 @@ class SetupBarBankConfigWizard(models.TransientModel):
|
||||
for record in self:
|
||||
record.new_journal_name = record.acc_number
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" This wizard is only used to setup an account for the current active
|
||||
company, so we always inject the corresponding partner when creating
|
||||
the model.
|
||||
"""
|
||||
vals['partner_id'] = self.env.company.partner_id.id
|
||||
vals['new_journal_name'] = vals['acc_number']
|
||||
for vals in vals_list:
|
||||
vals['partner_id'] = self.env.company.partner_id.id
|
||||
vals['new_journal_name'] = vals['acc_number']
|
||||
|
||||
# If no bank has been selected, but we have a bic, we are using it to find or create the bank
|
||||
if not vals['bank_id'] and vals['bank_bic']:
|
||||
vals['bank_id'] = self.env['res.bank'].search([('bic', '=', vals['bank_bic'])], limit=1).id \
|
||||
or self.env['res.bank'].create({'name': vals['bank_bic'], 'bic': vals['bank_bic']}).id
|
||||
# If no bank has been selected, but we have a bic, we are using it to find or create the bank
|
||||
if not vals['bank_id'] and vals['bank_bic']:
|
||||
vals['bank_id'] = self.env['res.bank'].search([('bic', '=', vals['bank_bic'])], limit=1).id \
|
||||
or self.env['res.bank'].create({'name': vals['bank_bic'], 'bic': vals['bank_bic']}).id
|
||||
|
||||
return super(SetupBarBankConfigWizard, self).create(vals)
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.onchange('linked_journal_id')
|
||||
def _onchange_new_journal_related_data(self):
|
||||
|
||||
@@ -57,12 +57,11 @@ class AccountJournal(models.Model):
|
||||
journal.check_sequence_id.sudo().number_next_actual = int(journal.check_next_number)
|
||||
journal.check_sequence_id.sudo().padding = len(journal.check_next_number)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
rec = super(AccountJournal, self).create(vals)
|
||||
if not rec.check_sequence_id:
|
||||
rec._create_check_sequence()
|
||||
return rec
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
journals = super().create(vals_list)
|
||||
journals.filtered(lambda j: not j.check_sequence_id)._create_check_sequence()
|
||||
return journals
|
||||
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def copy(self, default=None):
|
||||
|
||||
@@ -53,21 +53,22 @@ class TestStreetFields(TransactionCase):
|
||||
|
||||
# test street -> street values (compute)
|
||||
for idx, (company_values, expected_vals) in enumerate(zip(input_values, expected)):
|
||||
company_values['name'] = 'Test-%2d' % idx
|
||||
company = self.env['res.company'].create(company_values)
|
||||
values = dict(company_values, name='Test-%2d' % idx)
|
||||
company = self.env['res.company'].create(values)
|
||||
self.assertStreetVals(company, expected_vals)
|
||||
self.assertStreetVals(company.partner_id, expected_vals)
|
||||
|
||||
# test street_values -> street (inverse)
|
||||
for idx, (company_values, expected_vals) in enumerate(zip(input_values, expected)):
|
||||
company_values['name'] = 'TestNew-%2d' % idx
|
||||
expected_street = company_values.pop('street')
|
||||
company_values.update(expected_vals)
|
||||
company = self.env['res.company'].create(company_values)
|
||||
values = dict(company_values)
|
||||
values['name'] = 'TestNew-%2d' % idx
|
||||
expected_street = values.pop('street')
|
||||
values.update(expected_vals)
|
||||
company = self.env['res.company'].create(values)
|
||||
self.assertEqual(company.street, expected_street)
|
||||
self.assertStreetVals(company, company_values)
|
||||
self.assertStreetVals(company, values)
|
||||
self.assertEqual(company.partner_id.street, expected_street)
|
||||
self.assertStreetVals(company.partner_id, company_values)
|
||||
self.assertStreetVals(company.partner_id, values)
|
||||
|
||||
def test_company_write(self):
|
||||
""" Will test the compute and inverse methods of street fields when updating partner records. """
|
||||
|
||||
@@ -83,14 +83,16 @@ class CouponProgram(models.Model):
|
||||
if self.discount_type == 'fixed_amount':
|
||||
self.discount_apply_on = 'on_order'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
program = super(CouponProgram, self).create(vals)
|
||||
if not vals.get('discount_line_product_id', False):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
programs = super().create(vals_list)
|
||||
for program in programs:
|
||||
if program.discount_line_product_id:
|
||||
continue
|
||||
values = program._get_discount_product_values()
|
||||
discount_line_product_id = self.env['product.product'].create(values)
|
||||
program.write({'discount_line_product_id': discount_line_product_id.id})
|
||||
return program
|
||||
return programs
|
||||
|
||||
def write(self, vals):
|
||||
res = super(CouponProgram, self).write(vals)
|
||||
|
||||
@@ -237,26 +237,30 @@ class FleetVehicle(models.Model):
|
||||
res.append(('id', search_operator, res_ids))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# Fleet administrator may not have rights to create the plan_to_change_car value when the driver_id is a res.user
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# Fleet administrator may not have rights to create the plan_to_change_car
|
||||
# value when the driver_id is a res.user.
|
||||
# This trick is used to prevent access right error.
|
||||
ptc_value = 'plan_to_change_car' in vals.keys() and {'plan_to_change_car': vals.pop('plan_to_change_car')}
|
||||
res = super(FleetVehicle, self).create(vals)
|
||||
if ptc_value:
|
||||
res.sudo().write(ptc_value)
|
||||
if 'driver_id' in vals and vals['driver_id']:
|
||||
res.create_driver_history(vals)
|
||||
if 'future_driver_id' in vals and vals['future_driver_id']:
|
||||
state_waiting_list = self.env.ref('fleet.fleet_vehicle_state_waiting_list', raise_if_not_found=False)
|
||||
states = res.mapped('state_id').ids
|
||||
if not state_waiting_list or state_waiting_list.id not in states:
|
||||
future_driver = self.env['res.partner'].browse(vals['future_driver_id'])
|
||||
if self.vehicle_type == 'bike':
|
||||
future_driver.sudo().write({'plan_to_change_bike': True})
|
||||
if self.vehicle_type == 'car':
|
||||
future_driver.sudo().write({'plan_to_change_car': True})
|
||||
return res
|
||||
ptc_values = [
|
||||
'plan_to_change_car' in vals.keys() and {'plan_to_change_car': vals.pop('plan_to_change_car')} for vals in vals_list
|
||||
]
|
||||
vehicles = super().create(vals_list)
|
||||
for vehicle, vals, ptc_value in zip(vehicles, vals_list, ptc_values):
|
||||
if ptc_value:
|
||||
vehicle.sudo().write(ptc_value)
|
||||
if 'driver_id' in vals and vals['driver_id']:
|
||||
vehicle.create_driver_history(vals)
|
||||
if 'future_driver_id' in vals and vals['future_driver_id']:
|
||||
state_waiting_list = self.env.ref('fleet.fleet_vehicle_state_waiting_list', raise_if_not_found=False)
|
||||
states = vehicle.mapped('state_id').ids
|
||||
if not state_waiting_list or state_waiting_list.id not in states:
|
||||
future_driver = self.env['res.partner'].browse(vals['future_driver_id'])
|
||||
if self.vehicle_type == 'bike':
|
||||
future_driver.sudo().write({'plan_to_change_bike': True})
|
||||
if self.vehicle_type == 'car':
|
||||
future_driver.sudo().write({'plan_to_change_car': True})
|
||||
return vehicles
|
||||
|
||||
def write(self, vals):
|
||||
if 'driver_id' in vals and vals['driver_id']:
|
||||
|
||||
@@ -53,16 +53,17 @@ class Department(models.Model):
|
||||
if not self._check_recursion():
|
||||
raise ValidationError(_('You cannot create recursive departments.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# TDE note: auto-subscription of manager done by hand, because currently
|
||||
# the tracking allows to track+subscribe fields linked to a res.user record
|
||||
# An update of the limited behavior should come, but not currently done.
|
||||
department = super(Department, self.with_context(mail_create_nosubscribe=True)).create(vals)
|
||||
manager = self.env['hr.employee'].browse(vals.get("manager_id"))
|
||||
if manager.user_id:
|
||||
department.message_subscribe(partner_ids=manager.user_id.partner_id.ids)
|
||||
return department
|
||||
departments = super(Department, self.with_context(mail_create_nosubscribe=True)).create(vals_list)
|
||||
for department, vals in zip(departments, vals_list):
|
||||
manager = self.env['hr.employee'].browse(vals.get("manager_id"))
|
||||
if manager.user_id:
|
||||
department.message_subscribe(partner_ids=manager.user_id.partner_id.ids)
|
||||
return departments
|
||||
|
||||
def write(self, vals):
|
||||
""" If updating manager of a department, we need to update all the employees
|
||||
|
||||
@@ -277,26 +277,28 @@ class HrEmployeePrivate(models.Model):
|
||||
vals['tz'] = user.tz
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('user_id'):
|
||||
user = self.env['res.users'].browse(vals['user_id'])
|
||||
vals.update(self._sync_user(user, bool(vals.get('image_1920'))))
|
||||
vals['name'] = vals.get('name', user.name)
|
||||
employee = super(HrEmployeePrivate, self).create(vals)
|
||||
if employee.department_id:
|
||||
self.env['mail.channel'].sudo().search([
|
||||
('subscription_department_ids', 'in', employee.department_id.id)
|
||||
])._subscribe_users_automatically()
|
||||
# Launch onboarding plans
|
||||
url = '/web#%s' % url_encode({
|
||||
'action': 'hr.plan_wizard_action',
|
||||
'active_id': employee.id,
|
||||
'active_model': 'hr.employee',
|
||||
'menu_id': self.env.ref('hr.menu_hr_root').id,
|
||||
})
|
||||
employee._message_log(body=_('<b>Congratulations!</b> May I recommend you to setup an <a href="%s">onboarding plan?</a>') % (url))
|
||||
return employee
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('user_id'):
|
||||
user = self.env['res.users'].browse(vals['user_id'])
|
||||
vals.update(self._sync_user(user, bool(vals.get('image_1920'))))
|
||||
vals['name'] = vals.get('name', user.name)
|
||||
employees = super().create(vals_list)
|
||||
for employee in employees:
|
||||
if employee.department_id:
|
||||
self.env['mail.channel'].sudo().search([
|
||||
('subscription_department_ids', 'in', employee.department_id.id)
|
||||
])._subscribe_users_automatically()
|
||||
# Launch onboarding plans
|
||||
url = '/web#%s' % url_encode({
|
||||
'action': 'hr.plan_wizard_action',
|
||||
'active_id': employee.id,
|
||||
'active_model': 'hr.employee',
|
||||
'menu_id': self.env.ref('hr.menu_hr_root').id,
|
||||
})
|
||||
employee._message_log(body=_('<b>Congratulations!</b> May I recommend you to setup an <a href="%s">onboarding plan?</a>') % (url))
|
||||
return employees
|
||||
|
||||
def write(self, vals):
|
||||
if 'address_home_id' in vals:
|
||||
|
||||
@@ -44,10 +44,10 @@ class Job(models.Model):
|
||||
job.no_of_employee = result.get(job.id, 0)
|
||||
job.expected_employees = result.get(job.id, 0) + job.no_of_recruitment
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" We don't want the current user to be follower of all created job """
|
||||
return super(Job, self.with_context(mail_create_nosubscribe=True)).create(values)
|
||||
return super(Job, self.with_context(mail_create_nosubscribe=True)).create(vals_list)
|
||||
|
||||
@api.returns('self', lambda value: value.id)
|
||||
def copy(self, default=None):
|
||||
|
||||
@@ -229,11 +229,10 @@ class Contract(models.Model):
|
||||
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
contracts = super(Contract, self).create(vals)
|
||||
if vals.get('state') == 'open':
|
||||
contracts._assign_open_contract()
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
contracts = super().create(vals_list)
|
||||
contracts.filtered(lambda c: c.state == 'open')._assign_open_contract()
|
||||
open_contracts = contracts.filtered(lambda c: c.state == 'open' or c.state == 'draft' and c.kanban_state == 'done')
|
||||
# sync contract calendar -> calendar employee
|
||||
for contract in open_contracts.filtered(lambda c: c.employee_id and c.resource_calendar_id):
|
||||
|
||||
@@ -946,16 +946,16 @@ class HrExpenseSheet(models.Model):
|
||||
if any(expense.company_id != sheet.company_id for expense in sheet.expense_line_ids):
|
||||
raise ValidationError(_('An expense report must contain only lines from the same company.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
context = clean_context(self.env.context)
|
||||
context.update({
|
||||
'mail_create_nosubscribe': True,
|
||||
'mail_auto_subscribe_no_notify': True
|
||||
})
|
||||
sheet = super(HrExpenseSheet, self.with_context(context)).create(vals)
|
||||
sheet.activity_update()
|
||||
return sheet
|
||||
sheets = super(HrExpenseSheet, self.with_context(context)).create(vals_list)
|
||||
sheets.activity_update()
|
||||
return sheets
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_posted_or_paid(self):
|
||||
@@ -1134,12 +1134,21 @@ class HrExpenseSheet(models.Model):
|
||||
return self.env['res.users']
|
||||
|
||||
def activity_update(self):
|
||||
for expense_report in self.filtered(lambda hol: hol.state == 'submit'):
|
||||
self.activity_schedule(
|
||||
'hr_expense.mail_act_expense_approval',
|
||||
user_id=expense_report.sudo()._get_responsible_for_approval().id or self.env.user.id)
|
||||
self.filtered(lambda hol: hol.state == 'approve').activity_feedback(['hr_expense.mail_act_expense_approval'])
|
||||
self.filtered(lambda hol: hol.state in ('draft', 'cancel')).activity_unlink(['hr_expense.mail_act_expense_approval'])
|
||||
reports_requiring_feedback = self.env['hr.expense.sheet']
|
||||
reports_activity_unlink = self.env['hr.expense.sheet']
|
||||
for expense_report in self:
|
||||
if expense_report.state == 'submit':
|
||||
expense_report.activity_schedule(
|
||||
'hr_expense.mail_act_expense_approval',
|
||||
user_id=expense_report.sudo()._get_responsible_for_approval().id or self.env.user.id)
|
||||
elif expense_report.state == 'approve':
|
||||
reports_requiring_feedback |= expense_report
|
||||
elif expense_report.state in ('draft', 'cancel'):
|
||||
reports_activity_unlink |= expense_report
|
||||
if reports_requiring_feedback:
|
||||
reports_requiring_feedback.activity_feedback(['hr_expense.mail_act_expense_approval'])
|
||||
if reports_activity_unlink:
|
||||
reports_activity_unlink.activity_unlink(['hr_expense.mail_act_expense_approval'])
|
||||
|
||||
def action_register_payment(self):
|
||||
''' Open the account.payment.register wizard to pay the selected journal entries.
|
||||
|
||||
@@ -90,10 +90,11 @@ class FleetVehicle(models.Model):
|
||||
employee = employee_ids[0].id
|
||||
vals['future_driver_employee_id'] = employee
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
self._update_create_write_vals(vals)
|
||||
return super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
self._update_create_write_vals(vals)
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
self._update_create_write_vals(vals)
|
||||
|
||||
@@ -182,16 +182,19 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
])
|
||||
return [('id', 'in', holidays.mapped('employee_id').ids)]
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'parent_id' in values:
|
||||
manager = self.env['hr.employee'].browse(values['parent_id']).user_id
|
||||
values['leave_manager_id'] = values.get('leave_manager_id', manager.id)
|
||||
if values.get('leave_manager_id', False):
|
||||
approver_group = self.env.ref('hr_holidays.group_hr_holidays_responsible', raise_if_not_found=False)
|
||||
if approver_group:
|
||||
approver_group.sudo().write({'users': [(4, values['leave_manager_id'])]})
|
||||
return super(HrEmployeeBase, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
approver_group = self.env.ref('hr_holidays.group_hr_holidays_responsible', raise_if_not_found=False)
|
||||
group_updates = []
|
||||
for vals in vals_list:
|
||||
if 'parent_id' in vals:
|
||||
manager = self.env['hr.employee'].browse(vals['parent_id']).user_id
|
||||
vals['leave_manager_id'] = vals.get('leave_manager_id', manager.id)
|
||||
if approver_group and vals.get('leave_manager_id'):
|
||||
group_updates.append((4, vals['leave_manager_id']))
|
||||
if group_updates:
|
||||
approver_group.sudo().write({'users': group_updates})
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, values):
|
||||
if 'parent_id' in values:
|
||||
|
||||
@@ -41,18 +41,19 @@ class MaintenanceEquipment(models.Model):
|
||||
equipment.employee_id = equipment.employee_id
|
||||
equipment.assign_date = fields.Date.context_today(self)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
equipment = super(MaintenanceEquipment, self).create(vals)
|
||||
# subscribe employee or department manager when equipment assign to him.
|
||||
partner_ids = []
|
||||
if equipment.employee_id and equipment.employee_id.user_id:
|
||||
partner_ids.append(equipment.employee_id.user_id.partner_id.id)
|
||||
if equipment.department_id and equipment.department_id.manager_id and equipment.department_id.manager_id.user_id:
|
||||
partner_ids.append(equipment.department_id.manager_id.user_id.partner_id.id)
|
||||
if partner_ids:
|
||||
equipment.message_subscribe(partner_ids=partner_ids)
|
||||
return equipment
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
equipments = super().create(vals_list)
|
||||
for equipment in equipments:
|
||||
# subscribe employee or department manager when equipment assign to him.
|
||||
partner_ids = []
|
||||
if equipment.employee_id and equipment.employee_id.user_id:
|
||||
partner_ids.append(equipment.employee_id.user_id.partner_id.id)
|
||||
if equipment.department_id and equipment.department_id.manager_id and equipment.department_id.manager_id.user_id:
|
||||
partner_ids.append(equipment.department_id.manager_id.user_id.partner_id.id)
|
||||
if partner_ids:
|
||||
equipment.message_subscribe(partner_ids=partner_ids)
|
||||
return equipments
|
||||
|
||||
def write(self, vals):
|
||||
partner_ids = []
|
||||
@@ -95,12 +96,13 @@ class MaintenanceRequest(models.Model):
|
||||
else:
|
||||
r.owner_user_id = False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
result = super(MaintenanceRequest, self).create(vals)
|
||||
if result.employee_id.user_id:
|
||||
result.message_subscribe(partner_ids=[result.employee_id.user_id.partner_id.id])
|
||||
return result
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
requests = super().create(vals_list)
|
||||
for request in requests:
|
||||
if request.employee_id.user_id:
|
||||
request.message_subscribe(partner_ids=[request.employee_id.user_id.partner_id.id])
|
||||
return requests
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('employee_id'):
|
||||
|
||||
@@ -23,12 +23,13 @@ class HrEmployee(models.Model):
|
||||
])
|
||||
return [('id', 'in', employees.ids)]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
new_employee = super(HrEmployee, self).create(vals)
|
||||
if new_employee.applicant_id:
|
||||
new_employee.applicant_id.message_post_with_view(
|
||||
'hr_recruitment.applicant_hired_template',
|
||||
values={'applicant': new_employee.applicant_id},
|
||||
subtype_id=self.env.ref("hr_recruitment.mt_applicant_hired").id)
|
||||
return new_employee
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
employees = super().create(vals_list)
|
||||
for employee in employees:
|
||||
if employee.applicant_id:
|
||||
employee.applicant_id.message_post_with_view(
|
||||
'hr_recruitment.applicant_hired_template',
|
||||
values={'applicant': employee.applicant_id},
|
||||
subtype_id=self.env.ref("hr_recruitment.mt_applicant_hired").id)
|
||||
return employees
|
||||
|
||||
@@ -120,18 +120,19 @@ class Job(models.Model):
|
||||
})
|
||||
return values
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
vals['favorite_user_ids'] = vals.get('favorite_user_ids', []) + [(4, self.env.uid)]
|
||||
new_job = super(Job, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
vals['favorite_user_ids'] = vals.get('favorite_user_ids', []) + [(4, self.env.uid)]
|
||||
jobs = super().create(vals_list)
|
||||
utm_linkedin = self.env.ref("utm.utm_source_linkedin", raise_if_not_found=False)
|
||||
if utm_linkedin:
|
||||
source_vals = {
|
||||
source_vals = [{
|
||||
'source_id': utm_linkedin.id,
|
||||
'job_id': new_job.id,
|
||||
}
|
||||
'job_id': job.id,
|
||||
} for job in jobs]
|
||||
self.env['hr.recruitment.source'].create(source_vals)
|
||||
return new_job
|
||||
return jobs
|
||||
|
||||
def write(self, vals):
|
||||
res = super().write(vals)
|
||||
|
||||
@@ -340,31 +340,30 @@ class Applicant(models.Model):
|
||||
if not applicant.stage_id.hired_stage:
|
||||
applicant.date_closed = False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('department_id') and not self._context.get('default_department_id'):
|
||||
self = self.with_context(default_department_id=vals.get('department_id'))
|
||||
if vals.get('user_id'):
|
||||
vals['date_open'] = fields.Datetime.now()
|
||||
if vals.get('email_from'):
|
||||
vals['email_from'] = vals['email_from'].strip()
|
||||
res = super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('user_id'):
|
||||
vals['date_open'] = fields.Datetime.now()
|
||||
if vals.get('email_from'):
|
||||
vals['email_from'] = vals['email_from'].strip()
|
||||
applicants = super().create(vals_list)
|
||||
# Record creation through calendar, creates the calendar event directly, it will also create the activity.
|
||||
if 'default_activity_date_deadline' in self.env.context:
|
||||
deadline = fields.Datetime.to_datetime(self.env.context.get('default_activity_date_deadline'))
|
||||
partners = res.partner_id | res.user_id.partner_id | res.department_id.manager_id.user_id.partner_id
|
||||
|
||||
category = self.env.ref('hr_recruitment.categ_meet_interview')
|
||||
self.env['calendar.event'].sudo().with_context(default_applicant_id=res.id).create({
|
||||
'applicant_id': res.id,
|
||||
'partner_ids': [(6, 0, partners.ids)],
|
||||
'user_id': self.env.uid,
|
||||
'name': res.name,
|
||||
'categ_ids': [category.id],
|
||||
'start': deadline,
|
||||
'stop': deadline + relativedelta(minutes=30),
|
||||
})
|
||||
return res
|
||||
for applicant in applicants:
|
||||
partners = applicant.partner_id | applicant.user_id.partner_id | applicant.department_id.manager_id.user_id.partner_id
|
||||
self.env['calendar.event'].sudo().with_context(default_applicant_id=applicant.id).create({
|
||||
'applicant_id': applicant.id,
|
||||
'partner_ids': [(6, 0, partners.ids)],
|
||||
'user_id': self.env.uid,
|
||||
'name': applicant.name,
|
||||
'categ_ids': [category.id],
|
||||
'start': deadline,
|
||||
'stop': deadline + relativedelta(minutes=30),
|
||||
})
|
||||
return applicants
|
||||
|
||||
def write(self, vals):
|
||||
# user_id change: update date_open
|
||||
|
||||
@@ -167,13 +167,13 @@ class Project(models.Model):
|
||||
Note: create it before calling super() to avoid raising the ValidationError from _check_allow_timesheet
|
||||
"""
|
||||
defaults = self.default_get(['allow_timesheets', 'analytic_account_id'])
|
||||
for values in vals_list:
|
||||
allow_timesheets = values.get('allow_timesheets', defaults.get('allow_timesheets'))
|
||||
analytic_account_id = values.get('analytic_account_id', defaults.get('analytic_account_id'))
|
||||
for vals in vals_list:
|
||||
allow_timesheets = vals.get('allow_timesheets', defaults.get('allow_timesheets'))
|
||||
analytic_account_id = vals.get('analytic_account_id', defaults.get('analytic_account_id'))
|
||||
if allow_timesheets and not analytic_account_id:
|
||||
analytic_account = self._create_analytic_account_from_values(values)
|
||||
values['analytic_account_id'] = analytic_account.id
|
||||
return super(Project, self).create(vals_list)
|
||||
analytic_account = self._create_analytic_account_from_values(vals)
|
||||
vals['analytic_account_id'] = analytic_account.id
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, values):
|
||||
# create the AA for project still allowing timesheet
|
||||
|
||||
@@ -150,12 +150,13 @@ class ResPartnerBank(models.Model):
|
||||
else:
|
||||
record.l10n_ch_qr_iban = None
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('l10n_ch_qr_iban'):
|
||||
validate_qr_iban(vals['l10n_ch_qr_iban'])
|
||||
vals['l10n_ch_qr_iban'] = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
|
||||
return super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('l10n_ch_qr_iban'):
|
||||
validate_qr_iban(vals['l10n_ch_qr_iban'])
|
||||
vals['l10n_ch_qr_iban'] = pretty_iban(normalize_iban(vals['l10n_ch_qr_iban']))
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('l10n_ch_qr_iban'):
|
||||
|
||||
@@ -47,11 +47,12 @@ class ResPartner(models.Model):
|
||||
n_vat, n_dv = vat_l[0], vat_l[1]
|
||||
return '%s-%s' % (format(int(n_vat), ',d').replace(',', '.'), n_dv)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if values.get('vat'):
|
||||
values['vat'] = self._format_vat_cl(values)
|
||||
return super().create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('vat'):
|
||||
vals['vat'] = self._format_vat_cl(vals)
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, values):
|
||||
if any(field in values for field in ['vat', 'l10n_latam_identification_type_id', 'country_id']):
|
||||
|
||||
@@ -61,27 +61,28 @@ class Certificate(models.Model):
|
||||
# LOW-LEVEL METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
record = super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
certificates = super().create(vals_list)
|
||||
|
||||
spain_tz = timezone('Europe/Madrid')
|
||||
spain_dt = self._get_es_current_datetime()
|
||||
try:
|
||||
_pem_certificate, _pem_private_key, certificate = record._decode_certificate()
|
||||
cert_date_start = spain_tz.localize(certificate.not_valid_before)
|
||||
cert_date_end = spain_tz.localize(certificate.not_valid_after)
|
||||
except Exception:
|
||||
raise ValidationError(_(
|
||||
"There has been a problem with the certificate, some usual problems can be:\n"
|
||||
"- The password given or the certificate are not valid.\n"
|
||||
"- The certificate content is invalid."
|
||||
))
|
||||
# Assign extracted values from the certificate
|
||||
record.write({
|
||||
'date_start': fields.Datetime.to_string(cert_date_start),
|
||||
'date_end': fields.Datetime.to_string(cert_date_end),
|
||||
})
|
||||
if spain_dt > cert_date_end:
|
||||
raise ValidationError(_("The certificate is expired since %s", record.date_end))
|
||||
return record
|
||||
for certificate in certificates:
|
||||
try:
|
||||
_pem_certificate, _pem_private_key, certif = certificate._decode_certificate()
|
||||
cert_date_start = spain_tz.localize(certif.not_valid_before)
|
||||
cert_date_end = spain_tz.localize(certif.not_valid_after)
|
||||
except Exception:
|
||||
raise ValidationError(_(
|
||||
"There has been a problem with the certificate, some usual problems can be:\n"
|
||||
"- The password given or the certificate are not valid.\n"
|
||||
"- The certificate content is invalid."
|
||||
))
|
||||
# Assign extracted values from the certificate
|
||||
certificate.write({
|
||||
'date_start': fields.Datetime.to_string(cert_date_start),
|
||||
'date_end': fields.Datetime.to_string(cert_date_end),
|
||||
})
|
||||
if spain_dt > cert_date_end:
|
||||
raise ValidationError(_("The certificate is expired since %s", certificate.date_end))
|
||||
return certificates
|
||||
|
||||
@@ -43,20 +43,21 @@ class StockPickingType(models.Model):
|
||||
ir_seq_prefix = sequence_code + '/DDT'
|
||||
return ir_seq_name, ir_seq_prefix
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
company = self.env['res.company'].browse(vals['company_id'])
|
||||
if 'l10n_it_ddt_sequence_id' not in vals or not vals['l10n_it_ddt_sequence_id'] and vals['code'] == 'outgoing' \
|
||||
and company.country_id.code == 'IT':
|
||||
ir_seq_name, ir_seq_prefix = self._get_dtt_ir_seq_vals(vals.get('warehouse_id'), vals['sequence_code'])
|
||||
vals['l10n_it_ddt_sequence_id'] = self.env['ir.sequence'].create({
|
||||
'name': ir_seq_name,
|
||||
'prefix': ir_seq_prefix,
|
||||
'padding': 5,
|
||||
'company_id': vals['company_id'],
|
||||
'implementation': 'no_gap',
|
||||
}).id
|
||||
return super(StockPickingType, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
company = self.env['res.company'].browse(vals['company_id'])
|
||||
if 'l10n_it_ddt_sequence_id' not in vals or not vals['l10n_it_ddt_sequence_id'] and vals['code'] == 'outgoing' \
|
||||
and company.country_id.code == 'IT':
|
||||
ir_seq_name, ir_seq_prefix = self._get_dtt_ir_seq_vals(vals.get('warehouse_id'), vals['sequence_code'])
|
||||
vals['l10n_it_ddt_sequence_id'] = self.env['ir.sequence'].create({
|
||||
'name': ir_seq_name,
|
||||
'prefix': ir_seq_prefix,
|
||||
'padding': 5,
|
||||
'company_id': vals['company_id'],
|
||||
'implementation': 'no_gap',
|
||||
}).id
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if 'sequence_code' in vals:
|
||||
|
||||
@@ -6,13 +6,15 @@ from odoo import models, fields, api
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" If exists, use specific vat identification.type for the country of the company """
|
||||
country_id = vals.get('country_id')
|
||||
if country_id:
|
||||
companies = super().create(vals_list)
|
||||
for company in companies:
|
||||
if not company.country_id:
|
||||
continue
|
||||
country_vat_type = self.env['l10n_latam.identification.type'].search(
|
||||
[('is_vat', '=', True), ('country_id', '=', country_id)], limit=1)
|
||||
[('is_vat', '=', True), ('country_id', '=', company.country_id.id)], limit=1)
|
||||
if country_vat_type:
|
||||
self = self.with_context(default_l10n_latam_identification_type_id=country_vat_type.id)
|
||||
return super().create(vals)
|
||||
company.partner_id.l10n_latam_identification_type_id = country_vat_type
|
||||
return companies
|
||||
|
||||
@@ -116,18 +116,22 @@ class LunchOrder(models.Model):
|
||||
if not check:
|
||||
raise ValidationError(errors[quantity] % label)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
lines = self._find_matching_lines({
|
||||
**values,
|
||||
'toppings': self._extract_toppings(values),
|
||||
})
|
||||
if lines:
|
||||
# YTI FIXME This will update multiple lines in the case there are multiple
|
||||
# matching lines which should not happen through the interface
|
||||
lines.update_quantity(1)
|
||||
return lines[:1]
|
||||
return super().create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
orders = self.env['lunch.order']
|
||||
for vals in vals_list:
|
||||
lines = self._find_matching_lines({
|
||||
**vals,
|
||||
'toppings': self._extract_toppings(vals),
|
||||
})
|
||||
if lines:
|
||||
# YTI FIXME This will update multiple lines in the case there are multiple
|
||||
# matching lines which should not happen through the interface
|
||||
lines.update_quantity(1)
|
||||
orders |= lines[:1]
|
||||
else:
|
||||
orders |= super().create(vals)
|
||||
return orders
|
||||
|
||||
def write(self, values):
|
||||
merge_needed = 'note' in values or 'topping_ids_1' in values or 'topping_ids_2' in values or 'topping_ids_3' in values
|
||||
|
||||
@@ -27,20 +27,18 @@ class ResPartner(models.Model):
|
||||
partner.iap_enrich_info = False
|
||||
partner.iap_search_domain = False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
partner = super(ResPartner, self).create(vals)
|
||||
|
||||
if vals.get('iap_enrich_info') or vals.get('iap_search_domain'):
|
||||
# Not done with inverse method so we do not need to search
|
||||
# for existing <res.partner.iap>
|
||||
self.env['res.partner.iap'].sudo().create({
|
||||
'partner_id': partner.id,
|
||||
'iap_enrich_info': vals.get('iap_enrich_info'),
|
||||
'iap_search_domain': vals.get('iap_search_domain'),
|
||||
})
|
||||
|
||||
return partner
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
partners = super().create(vals_list)
|
||||
# Not done with inverse method so we do not need to search
|
||||
# for existing <res.partner.iap>
|
||||
partner_iap_vals_list = [{
|
||||
'partner_id': partner.id,
|
||||
'iap_enrich_info': vals.get('iap_enrich_info'),
|
||||
'iap_search_domain': vals.get('iap_search_domain'),
|
||||
} for partner, vals in zip(partners, vals_list) if vals.get('iap_enrich_info') or vals.get('iap_search_domain')]
|
||||
self.env['res.partner.iap'].sudo().create(partner_iap_vals_list)
|
||||
return partners
|
||||
|
||||
def write(self, vals):
|
||||
super(ResPartner, self).write(vals)
|
||||
|
||||
@@ -200,12 +200,13 @@ class MaintenanceEquipment(models.Model):
|
||||
('serial_no', 'unique(serial_no)', "Another asset already exists with this serial number!"),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
equipment = super(MaintenanceEquipment, self).create(vals)
|
||||
if equipment.owner_user_id:
|
||||
equipment.message_subscribe(partner_ids=[equipment.owner_user_id.partner_id.id])
|
||||
return equipment
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
equipments = super().create(vals_list)
|
||||
for equipment in equipments:
|
||||
if equipment.owner_user_id:
|
||||
equipment.message_subscribe(partner_ids=[equipment.owner_user_id.partner_id.id])
|
||||
return equipments
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('owner_user_id'):
|
||||
@@ -331,16 +332,17 @@ class MaintenanceRequest(models.Model):
|
||||
if not self.user_id or not self.equipment_id or (self.user_id and not self.equipment_id.technician_user_id):
|
||||
self.user_id = self.category_id.technician_user_id
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# context: no_log, because subtype already handle this
|
||||
request = super(MaintenanceRequest, self).create(vals)
|
||||
if request.owner_user_id or request.user_id:
|
||||
request._add_followers()
|
||||
if request.equipment_id and not request.maintenance_team_id:
|
||||
request.maintenance_team_id = request.equipment_id.maintenance_team_id
|
||||
request.activity_update()
|
||||
return request
|
||||
maintenance_requests = super().create(vals_list)
|
||||
for request in maintenance_requests:
|
||||
if request.owner_user_id or request.user_id:
|
||||
request._add_followers()
|
||||
if request.equipment_id and not request.maintenance_team_id:
|
||||
request.maintenance_team_id = request.equipment_id.maintenance_team_id
|
||||
maintenance_requests.activity_update()
|
||||
return maintenance_requests
|
||||
|
||||
def write(self, vals):
|
||||
# Overridden to reset the kanban_state to normal whenever
|
||||
|
||||
@@ -88,12 +88,14 @@ class Mailing(models.Model):
|
||||
# ORM OVERRIDES
|
||||
# --------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
# Get subject from "sms_subject" field when SMS installed (used to build the name of record in the super 'create' method)
|
||||
if values.get('mailing_type') == 'sms' and values.get('sms_subject'):
|
||||
values['subject'] = values['sms_subject']
|
||||
return super(Mailing, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
# Get subject from "sms_subject" field when SMS installed (used to
|
||||
# build the name of record in the super 'create' method)
|
||||
if vals.get('mailing_type') == 'sms' and vals.get('sms_subject'):
|
||||
vals['subject'] = vals['sms_subject']
|
||||
return super().create(vals_list)
|
||||
|
||||
# --------------------------------------------------
|
||||
# BUSINESS / VIEWS ACTIONS
|
||||
|
||||
@@ -765,37 +765,39 @@ class MrpProduction(models.Model):
|
||||
production.date_planned_finished = new_date_planned_start + datetime.timedelta(hours=1)
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
# Remove from `move_finished_ids` the by-product moves and then move `move_byproduct_ids`
|
||||
# into `move_finished_ids` to avoid duplicate and inconsistency.
|
||||
if values.get('move_finished_ids', False):
|
||||
values['move_finished_ids'] = list(filter(lambda move: move[2]['byproduct_id'] is False, values['move_finished_ids']))
|
||||
if values.get('move_byproduct_ids', False):
|
||||
values['move_finished_ids'] = values.get('move_finished_ids', []) + values['move_byproduct_ids']
|
||||
del values['move_byproduct_ids']
|
||||
if not values.get('name', False) or values['name'] == _('New'):
|
||||
picking_type_id = values.get('picking_type_id') or self._get_default_picking_type()
|
||||
picking_type_id = self.env['stock.picking.type'].browse(picking_type_id)
|
||||
if picking_type_id:
|
||||
values['name'] = picking_type_id.sequence_id.next_by_id()
|
||||
else:
|
||||
values['name'] = self.env['ir.sequence'].next_by_code('mrp.production') or _('New')
|
||||
if not values.get('procurement_group_id'):
|
||||
procurement_group_vals = self._prepare_procurement_group_vals(values)
|
||||
values['procurement_group_id'] = self.env["procurement.group"].create(procurement_group_vals).id
|
||||
production = super(MrpProduction, self).create(values)
|
||||
(production.move_raw_ids | production.move_finished_ids).write({
|
||||
'group_id': production.procurement_group_id.id,
|
||||
'origin': production.name
|
||||
})
|
||||
production.move_raw_ids.write({'date': production.date_planned_start})
|
||||
production.move_finished_ids.write({'date': production.date_planned_finished})
|
||||
# Trigger move_raw creation when importing a file
|
||||
if 'import_file' in self.env.context:
|
||||
production._onchange_move_raw()
|
||||
production._onchange_move_finished()
|
||||
return production
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
# Remove from `move_finished_ids` the by-product moves and then move `move_byproduct_ids`
|
||||
# into `move_finished_ids` to avoid duplicate and inconsistency.
|
||||
if vals.get('move_finished_ids', False):
|
||||
vals['move_finished_ids'] = list(filter(lambda move: move[2]['byproduct_id'] is False, vals['move_finished_ids']))
|
||||
if vals.get('move_byproduct_ids', False):
|
||||
vals['move_finished_ids'] = vals.get('move_finished_ids', []) + vals['move_byproduct_ids']
|
||||
del vals['move_byproduct_ids']
|
||||
if not vals.get('name', False) or vals['name'] == _('New'):
|
||||
picking_type_id = vals.get('picking_type_id') or self._get_default_picking_type()
|
||||
picking_type_id = self.env['stock.picking.type'].browse(picking_type_id)
|
||||
if picking_type_id:
|
||||
vals['name'] = picking_type_id.sequence_id.next_by_id()
|
||||
else:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('mrp.production') or _('New')
|
||||
if not vals.get('procurement_group_id'):
|
||||
procurement_group_vals = self._prepare_procurement_group_vals(vals)
|
||||
vals['procurement_group_id'] = self.env["procurement.group"].create(procurement_group_vals).id
|
||||
productions = super().create(vals_list)
|
||||
for production in productions:
|
||||
(production.move_raw_ids | production.move_finished_ids).write({
|
||||
'group_id': production.procurement_group_id.id,
|
||||
'origin': production.name
|
||||
})
|
||||
production.move_raw_ids.write({'date': production.date_planned_start})
|
||||
production.move_finished_ids.write({'date': production.date_planned_finished})
|
||||
# Trigger move_raw creation when importing a file
|
||||
if 'import_file' in self.env.context:
|
||||
production._onchange_move_raw()
|
||||
production._onchange_move_finished()
|
||||
return productions
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_done(self):
|
||||
|
||||
@@ -108,11 +108,12 @@ class MrpUnbuild(models.Model):
|
||||
if unbuild.product_qty <= 0:
|
||||
raise ValueError(_('Unbuild Order product quantity has to be strictly positive.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if not vals.get('name') or vals['name'] == _('New'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('mrp.unbuild') or _('New')
|
||||
return super(MrpUnbuild, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if not vals.get('name') or vals['name'] == _('New'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('mrp.unbuild') or _('New')
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_except_done(self):
|
||||
|
||||
@@ -6,11 +6,11 @@ from odoo import api, models
|
||||
class Repair(models.Model):
|
||||
_inherit = 'repair.order'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super().create(vals)
|
||||
res.action_explode()
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
orders = super().create(vals_list)
|
||||
orders.action_explode()
|
||||
return orders
|
||||
|
||||
def write(self, vals):
|
||||
res = super().write(vals)
|
||||
|
||||
@@ -435,26 +435,27 @@ class PosConfig(models.Model):
|
||||
result.append((config.id, "%s (%s)" % (config.name, last_session.user_id.name)))
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
IrSequence = self.env['ir.sequence'].sudo()
|
||||
val = {
|
||||
'name': _('POS Order %s', values['name']),
|
||||
'padding': 4,
|
||||
'prefix': "%s/" % values['name'],
|
||||
'code': "pos.order",
|
||||
'company_id': values.get('company_id', False),
|
||||
}
|
||||
# force sequence_id field to new pos.order sequence
|
||||
values['sequence_id'] = IrSequence.create(val).id
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
IrSequence = self.env['ir.sequence'].sudo()
|
||||
val = {
|
||||
'name': _('POS Order %s', vals['name']),
|
||||
'padding': 4,
|
||||
'prefix': "%s/" % vals['name'],
|
||||
'code': "pos.order",
|
||||
'company_id': vals.get('company_id', False),
|
||||
}
|
||||
# force sequence_id field to new pos.order sequence
|
||||
vals['sequence_id'] = IrSequence.create(val).id
|
||||
|
||||
val.update(name=_('POS order line %s', values['name']), code='pos.order.line')
|
||||
values['sequence_line_id'] = IrSequence.create(val).id
|
||||
pos_config = super(PosConfig, self).create(values)
|
||||
pos_config.sudo()._check_modules_to_install()
|
||||
pos_config.sudo()._check_groups_implied()
|
||||
val.update(name=_('POS order line %s', vals['name']), code='pos.order.line')
|
||||
vals['sequence_line_id'] = IrSequence.create(val).id
|
||||
pos_configs = super().create(vals_list)
|
||||
pos_configs.sudo()._check_modules_to_install()
|
||||
pos_configs.sudo()._check_groups_implied()
|
||||
# If you plan to add something after this, use a new environment. The one above is no longer valid after the modules install.
|
||||
return pos_config
|
||||
return pos_configs
|
||||
|
||||
def write(self, vals):
|
||||
opened_session = self.mapped('session_ids').filtered(lambda s: s.state != 'closed')
|
||||
|
||||
@@ -406,11 +406,12 @@ class PosOrder(models.Model):
|
||||
for pos_order in self.filtered(lambda pos_order: pos_order.state not in ['draft', 'cancel']):
|
||||
raise UserError(_('In order to delete a sale, it must be new or cancelled.'))
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
session = self.env['pos.session'].browse(values['session_id'])
|
||||
values = self._complete_values_from_session(session, values)
|
||||
return super(PosOrder, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
session = self.env['pos.session'].browse(vals['session_id'])
|
||||
vals = self._complete_values_from_session(session, vals)
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.model
|
||||
def _complete_values_from_session(self, session, values):
|
||||
@@ -936,17 +937,18 @@ class PosOrderLine(models.Model):
|
||||
'refunded_orderline_id': self.id,
|
||||
}
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if values.get('order_id') and not values.get('name'):
|
||||
# set name based on the sequence specified on the config
|
||||
config = self.env['pos.order'].browse(values['order_id']).session_id.config_id
|
||||
if config.sequence_line_id:
|
||||
values['name'] = config.sequence_line_id._next()
|
||||
if not values.get('name'):
|
||||
# fallback on any pos.order sequence
|
||||
values['name'] = self.env['ir.sequence'].next_by_code('pos.order.line')
|
||||
return super(PosOrderLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('order_id') and not vals.get('name'):
|
||||
# set name based on the sequence specified on the config
|
||||
config = self.env['pos.order'].browse(vals['order_id']).session_id.config_id
|
||||
if config.sequence_line_id:
|
||||
vals['name'] = config.sequence_line_id._next()
|
||||
if not vals.get('name'):
|
||||
# fallback on any pos.order sequence
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('pos.order.line')
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, values):
|
||||
if values.get('pack_lot_line_ids'):
|
||||
|
||||
@@ -199,52 +199,52 @@ class PosSession(models.Model):
|
||||
['%s - %s' % (invoice.name, invoice.state) for invoice in
|
||||
unposted_invoices]))
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
config_id = values.get('config_id') or self.env.context.get('default_config_id')
|
||||
if not config_id:
|
||||
raise UserError(_("You should assign a Point of Sale to your session."))
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
config_id = vals.get('config_id') or self.env.context.get('default_config_id')
|
||||
if not config_id:
|
||||
raise UserError(_("You should assign a Point of Sale to your session."))
|
||||
|
||||
# journal_id is not required on the pos_config because it does not
|
||||
# exists at the installation. If nothing is configured at the
|
||||
# installation we do the minimal configuration. Impossible to do in
|
||||
# the .xml files as the CoA is not yet installed.
|
||||
pos_config = self.env['pos.config'].browse(config_id)
|
||||
ctx = dict(self.env.context, company_id=pos_config.company_id.id)
|
||||
# journal_id is not required on the pos_config because it does not
|
||||
# exists at the installation. If nothing is configured at the
|
||||
# installation we do the minimal configuration. Impossible to do in
|
||||
# the .xml files as the CoA is not yet installed.
|
||||
pos_config = self.env['pos.config'].browse(config_id)
|
||||
ctx = dict(self.env.context, company_id=pos_config.company_id.id)
|
||||
|
||||
pos_name = self.env['ir.sequence'].with_context(ctx).next_by_code('pos.session')
|
||||
if values.get('name'):
|
||||
pos_name += ' ' + values['name']
|
||||
pos_name = self.env['ir.sequence'].with_context(ctx).next_by_code('pos.session')
|
||||
if vals.get('name'):
|
||||
pos_name += ' ' + vals['name']
|
||||
|
||||
cash_payment_methods = pos_config.payment_method_ids.filtered(lambda pm: pm.is_cash_count)
|
||||
statement_ids = self.env['account.bank.statement']
|
||||
if self.user_has_groups('point_of_sale.group_pos_user'):
|
||||
statement_ids = statement_ids.sudo()
|
||||
for cash_journal in cash_payment_methods.mapped('journal_id'):
|
||||
ctx['journal_id'] = cash_journal.id if pos_config.cash_control and cash_journal.type == 'cash' else False
|
||||
st_values = {
|
||||
'journal_id': cash_journal.id,
|
||||
'user_id': self.env.user.id,
|
||||
cash_payment_methods = pos_config.payment_method_ids.filtered(lambda pm: pm.is_cash_count)
|
||||
statement_ids = self.env['account.bank.statement']
|
||||
if self.user_has_groups('point_of_sale.group_pos_user'):
|
||||
statement_ids = statement_ids.sudo()
|
||||
for cash_journal in cash_payment_methods.mapped('journal_id'):
|
||||
ctx['journal_id'] = cash_journal.id if pos_config.cash_control and cash_journal.type == 'cash' else False
|
||||
st_vals = {
|
||||
'journal_id': cash_journal.id,
|
||||
'user_id': self.env.user.id,
|
||||
'name': pos_name,
|
||||
}
|
||||
statement_ids |= statement_ids.with_context(ctx).create(st_vals)
|
||||
|
||||
update_stock_at_closing = pos_config.company_id.point_of_sale_update_stock_quantities == "closing"
|
||||
|
||||
vals.update({
|
||||
'name': pos_name,
|
||||
}
|
||||
statement_ids |= statement_ids.with_context(ctx).create(st_values)
|
||||
|
||||
update_stock_at_closing = pos_config.company_id.point_of_sale_update_stock_quantities == "closing"
|
||||
|
||||
values.update({
|
||||
'name': pos_name,
|
||||
'statement_ids': [(6, 0, statement_ids.ids)],
|
||||
'config_id': config_id,
|
||||
'update_stock_at_closing': update_stock_at_closing,
|
||||
})
|
||||
'statement_ids': [(6, 0, statement_ids.ids)],
|
||||
'config_id': config_id,
|
||||
'update_stock_at_closing': update_stock_at_closing,
|
||||
})
|
||||
|
||||
if self.user_has_groups('point_of_sale.group_pos_user'):
|
||||
res = super(PosSession, self.with_context(ctx).sudo()).create(values)
|
||||
sessions = super(PosSession, self.with_context(ctx).sudo()).create(vals_list)
|
||||
else:
|
||||
res = super(PosSession, self.with_context(ctx)).create(values)
|
||||
res.action_pos_session_open()
|
||||
|
||||
return res
|
||||
sessions = super(PosSession, self.with_context(ctx)).create(vals_list)
|
||||
sessions.action_pos_session_open()
|
||||
return sessions
|
||||
|
||||
def unlink(self):
|
||||
for session in self.filtered(lambda s: s.statement_ids):
|
||||
|
||||
@@ -481,14 +481,15 @@ class Project(models.Model):
|
||||
self.browse(res[0]).type_ids += self.env['project.task.type'].sudo().create({'name': _('New')})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# Prevent double project creation
|
||||
self = self.with_context(mail_create_nosubscribe=True)
|
||||
project = super(Project, self).create(vals)
|
||||
if project.privacy_visibility == 'portal' and project.partner_id:
|
||||
project.message_subscribe(project.partner_id.ids)
|
||||
return project
|
||||
projects = super().create(vals_list)
|
||||
for project in projects:
|
||||
if project.privacy_visibility == 'portal' and project.partner_id:
|
||||
project.message_subscribe(project.partner_id.ids)
|
||||
return projects
|
||||
|
||||
def write(self, vals):
|
||||
# directly compute is_favorite to dodge allow write access right
|
||||
|
||||
@@ -276,13 +276,14 @@ class ProjectTaskRecurrence(models.Model):
|
||||
recurrence.recurrence_left -= 1
|
||||
recurring_today._set_next_recurrence_date()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('repeat_number'):
|
||||
vals['recurrence_left'] = vals.get('repeat_number')
|
||||
res = super(ProjectTaskRecurrence, self).create(vals)
|
||||
res._set_next_recurrence_date()
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('repeat_number'):
|
||||
vals['recurrence_left'] = vals.get('repeat_number')
|
||||
recurrences = super().create(vals_list)
|
||||
recurrences._set_next_recurrence_date()
|
||||
return recurrences
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('repeat_number'):
|
||||
|
||||
@@ -75,11 +75,12 @@ class ProjectUpdate(models.Model):
|
||||
# ---------------------------------
|
||||
# ORM Override
|
||||
# ---------------------------------
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
update = super().create(vals)
|
||||
update.project_id.sudo().last_update_id = update
|
||||
return update
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
updates = super().create(vals_list)
|
||||
for update in updates:
|
||||
update.project_id.sudo().last_update_id = update
|
||||
return updates
|
||||
|
||||
def unlink(self):
|
||||
projects = self.project_id
|
||||
|
||||
@@ -7,29 +7,30 @@ from odoo import api, fields, models
|
||||
class Employee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
result = super(Employee, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
employees = super().create(vals_list)
|
||||
|
||||
# We need to create timesheet entries for the global time off that are already created
|
||||
# and are planned for after this employee creation date
|
||||
|
||||
# First we look for the global time off that are already planned after today
|
||||
today = fields.Datetime.today()
|
||||
global_leaves = result.resource_calendar_id.global_leave_ids.filtered(lambda l: l.date_from >= today)
|
||||
work_hours_data = global_leaves._work_time_per_day()
|
||||
lines_vals = []
|
||||
for employee in employees:
|
||||
global_leaves = employee.resource_calendar_id.global_leave_ids.filtered(lambda l: l.date_from >= today)
|
||||
work_hours_data = global_leaves._work_time_per_day()
|
||||
|
||||
vals_list = []
|
||||
for global_time_off in global_leaves:
|
||||
for index, (day_date, work_hours_count) in enumerate(work_hours_data[global_time_off.id]):
|
||||
vals_list.append(
|
||||
global_time_off._timesheet_prepare_line_values(
|
||||
index,
|
||||
result,
|
||||
work_hours_data[global_time_off.id],
|
||||
day_date,
|
||||
work_hours_count
|
||||
for global_time_off in global_leaves:
|
||||
for index, (day_date, work_hours_count) in enumerate(work_hours_data[global_time_off.id]):
|
||||
lines_vals.append(
|
||||
global_time_off._timesheet_prepare_line_values(
|
||||
index,
|
||||
employee,
|
||||
work_hours_data[global_time_off.id],
|
||||
day_date,
|
||||
work_hours_count
|
||||
)
|
||||
)
|
||||
)
|
||||
self.env['account.analytic.line'].sudo().create(vals_list)
|
||||
return result
|
||||
self.env['account.analytic.line'].sudo().create(lines_vals)
|
||||
return employees
|
||||
|
||||
@@ -231,21 +231,26 @@ class PurchaseOrder(models.Model):
|
||||
self.partner_id.sudo().write(partner_vals) # Because the purchase user doesn't have write on `res.partner`
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
company_id = vals.get('company_id', self.default_get(['company_id'])['company_id'])
|
||||
# Ensures default picking type and currency are taken from the right company.
|
||||
self_comp = self.with_company(company_id)
|
||||
if vals.get('name', 'New') == 'New':
|
||||
seq_date = None
|
||||
if 'date_order' in vals:
|
||||
seq_date = fields.Datetime.context_timestamp(self, fields.Datetime.to_datetime(vals['date_order']))
|
||||
vals['name'] = self_comp.env['ir.sequence'].next_by_code('purchase.order', sequence_date=seq_date) or '/'
|
||||
vals, partner_vals = self._write_partner_values(vals)
|
||||
res = super(PurchaseOrder, self_comp).create(vals)
|
||||
if partner_vals:
|
||||
res.sudo().write(partner_vals) # Because the purchase user doesn't have write on `res.partner`
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
orders = self.browse()
|
||||
partner_vals_list = []
|
||||
for vals in vals_list:
|
||||
company_id = vals.get('company_id', self.default_get(['company_id'])['company_id'])
|
||||
# Ensures default picking type and currency are taken from the right company.
|
||||
self_comp = self.with_company(company_id)
|
||||
if vals.get('name', 'New') == 'New':
|
||||
seq_date = None
|
||||
if 'date_order' in vals:
|
||||
seq_date = fields.Datetime.context_timestamp(self, fields.Datetime.to_datetime(vals['date_order']))
|
||||
vals['name'] = self_comp.env['ir.sequence'].next_by_code('purchase.order', sequence_date=seq_date) or '/'
|
||||
vals, partner_vals = self._write_partner_values(vals)
|
||||
partner_vals_list.append(partner_vals)
|
||||
orders |= super(PurchaseOrder, self_comp).create(vals)
|
||||
for order, partner_vals in zip(orders, partner_vals_list):
|
||||
if partner_vals:
|
||||
order.sudo().write(partner_vals) # Because the purchase user doesn't have write on `res.partner`
|
||||
return orders
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_if_cancelled(self):
|
||||
|
||||
@@ -88,14 +88,17 @@ class PurchaseOrder(models.Model):
|
||||
po.requisition_id.action_done()
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
purchase = super(PurchaseOrder, self).create(vals)
|
||||
if purchase.requisition_id:
|
||||
purchase.message_post_with_view('mail.message_origin_link',
|
||||
values={'self': purchase, 'origin': purchase.requisition_id},
|
||||
subtype_id=self.env['ir.model.data']._xmlid_to_res_id('mail.mt_note'))
|
||||
return purchase
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
orders = super().create(vals_list)
|
||||
mt_note = self.env['ir.model.data']._xmlid_to_res_id('mail.mt_note')
|
||||
for order in orders:
|
||||
if order.requisition_id:
|
||||
order.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': order, 'origin': order.requisition_id},
|
||||
subtype_id=mt_note)
|
||||
return orders
|
||||
|
||||
def write(self, vals):
|
||||
result = super(PurchaseOrder, self).write(vals)
|
||||
|
||||
@@ -183,19 +183,20 @@ class PurchaseRequisitionLine(models.Model):
|
||||
schedule_date = fields.Date(string='Scheduled Date')
|
||||
supplier_info_ids = fields.One2many('product.supplierinfo', 'purchase_requisition_line_id')
|
||||
|
||||
@api.model
|
||||
def create(self,vals):
|
||||
res = super(PurchaseRequisitionLine, self).create(vals)
|
||||
if res.requisition_id.state not in ['draft', 'cancel', 'done'] and res.requisition_id.is_quantity_copy == 'none':
|
||||
supplier_infos = self.env['product.supplierinfo'].search([
|
||||
('product_id', '=', vals.get('product_id')),
|
||||
('partner_id', '=', res.requisition_id.vendor_id.id),
|
||||
])
|
||||
if not any(s.purchase_requisition_id for s in supplier_infos):
|
||||
res.create_supplier_info()
|
||||
if vals['price_unit'] <= 0.0:
|
||||
raise UserError(_('You cannot confirm the blanket order without price.'))
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
lines = super().create(vals_list)
|
||||
for line, vals in zip(lines, vals_list):
|
||||
if line.requisition_id.state not in ['draft', 'cancel', 'done'] and line.requisition_id.is_quantity_copy == 'none':
|
||||
supplier_infos = self.env['product.supplierinfo'].search([
|
||||
('product_id', '=', vals.get('product_id')),
|
||||
('partner_id', '=', line.requisition_id.vendor_id.id),
|
||||
])
|
||||
if not any(s.purchase_requisition_id for s in supplier_infos):
|
||||
line.create_supplier_info()
|
||||
if vals['price_unit'] <= 0.0:
|
||||
raise UserError(_('You cannot confirm the blanket order without price.'))
|
||||
return lines
|
||||
|
||||
def write(self, vals):
|
||||
res = super(PurchaseRequisitionLine, self).write(vals)
|
||||
|
||||
@@ -211,11 +211,12 @@ class Repair(models.Model):
|
||||
if order.state not in ('draft', 'cancel'):
|
||||
raise UserError(_('You can not delete a repair order once it has been confirmed. You must first cancel it.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# We generate a standard reference
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('repair.order') or '/'
|
||||
return super(Repair, self).create(vals)
|
||||
for vals in vals_list:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('repair.order') or '/'
|
||||
return super().create(vals_list)
|
||||
|
||||
def button_dummy(self):
|
||||
# TDE FIXME: this button is very interesting
|
||||
|
||||
@@ -23,12 +23,14 @@ class ResCompany(models.Model):
|
||||
'company_id': company.id
|
||||
}).id
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
company = super(ResCompany, self).create(values)
|
||||
if not company.resource_calendar_id:
|
||||
company.sudo()._create_resource_calendar()
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
companies = super().create(vals_list)
|
||||
companies_without_calendar = companies.filtered(lambda c: not c.resource_calendar_id)
|
||||
if companies_without_calendar:
|
||||
companies_without_calendar.sudo()._create_resource_calendar()
|
||||
# calendar created from form view: no company_id set because record was still not created
|
||||
if not company.resource_calendar_id.company_id:
|
||||
company.resource_calendar_id.company_id = company.id
|
||||
return company
|
||||
for company in companies:
|
||||
if not company.resource_calendar_id.company_id:
|
||||
company.resource_calendar_id.company_id = company.id
|
||||
return companies
|
||||
|
||||
@@ -33,17 +33,24 @@ class ResourceMixin(models.AbstractModel):
|
||||
string='Timezone', related='resource_id.tz', readonly=False,
|
||||
help="This field is used in order to define in which timezone the resources will work.")
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if not values.get('resource_id'):
|
||||
resource_vals = {'name': values.get(self._rec_name)}
|
||||
tz = (values.pop('tz', False) or
|
||||
self.env['resource.calendar'].browse(values.get('resource_calendar_id')).tz)
|
||||
if tz:
|
||||
resource_vals['tz'] = tz
|
||||
resource = self.env['resource.resource'].create(resource_vals)
|
||||
values['resource_id'] = resource.id
|
||||
return super(ResourceMixin, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
resources_vals_list = []
|
||||
calendar_ids = [vals['resource_calendar_id'] for vals in vals_list if vals.get('resource_calendar_id')]
|
||||
calendars_tz = {calendar.id: calendar.tz for calendar in self.env['resource.calendar'].browse(calendar_ids)}
|
||||
for vals in vals_list:
|
||||
if not vals.get('resource_id'):
|
||||
resource_vals = {'name': vals.get(self._rec_name)}
|
||||
tz = vals.pop('tz', False) or calendars_tz.get(vals.get('resource_calendar_id'))
|
||||
if tz:
|
||||
resource_vals['tz'] = tz
|
||||
resources_vals_list.append(resource_vals)
|
||||
resources = self.env['resource.resource'].create(resources_vals_list)
|
||||
resources_iter = iter(resources.ids)
|
||||
for vals in vals_list:
|
||||
if not vals.get('resource_id'):
|
||||
vals['resource_id'] = next(resources_iter)
|
||||
return super().create(vals_list)
|
||||
|
||||
def copy_data(self, default=None):
|
||||
if default is None:
|
||||
|
||||
@@ -49,28 +49,22 @@
|
||||
|
||||
<record id="sale_order_line_1" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_2" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_02"/>
|
||||
<field name="product_uom_qty">5</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">145.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_3" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_01"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">65.00</field>
|
||||
</record>
|
||||
|
||||
@@ -90,19 +84,15 @@
|
||||
|
||||
<record id="sale_order_line_4" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_2"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_1').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_1"/>
|
||||
<field name="product_uom_qty">24</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">75.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_5" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_2"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_2').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_2"/>
|
||||
<field name="product_uom_qty">30</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">38.25</field>
|
||||
</record>
|
||||
|
||||
@@ -121,20 +111,14 @@
|
||||
|
||||
<record id="sale_order_line_6" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_3"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_1').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_1"/>
|
||||
<field name="product_uom_qty">10</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">30.75</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_7" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_3"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_01"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">70.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_4" model="sale.order">
|
||||
@@ -151,38 +135,29 @@
|
||||
|
||||
<record id="sale_order_line_8" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_4"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_1').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_1"/>
|
||||
<field name="product_uom_qty">16</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">75.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_9" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_4"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_02"/>
|
||||
<field name="product_uom_qty">10</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">45.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_10" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_4"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.consu_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.consu_delivery_02"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">150.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_11" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_4"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_01"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">70.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_5" model="sale.order">
|
||||
@@ -200,10 +175,7 @@
|
||||
|
||||
<record id="sale_order_line_12" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_5"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_02"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">405.00</field>
|
||||
</record>
|
||||
|
||||
@@ -222,10 +194,7 @@
|
||||
|
||||
<record id="sale_order_line_15" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_6"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_4').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_4"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">750.00</field>
|
||||
</record>
|
||||
|
||||
@@ -244,37 +213,26 @@
|
||||
|
||||
<record id="sale_order_line_16" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_7"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">5</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_17" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_7"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.consu_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.consu_delivery_01"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">173.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_18" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_7"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_02"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">40.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_19" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_7"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_01"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">18.00</field>
|
||||
</record>
|
||||
|
||||
@@ -293,19 +251,15 @@
|
||||
|
||||
<record id="sale_order_line_20" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_8"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_27').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_27"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">110.50</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_21" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_8"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -326,19 +280,15 @@
|
||||
|
||||
<record id="sale_order_line_22" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_9"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_27').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_27"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">97.50</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_23" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_9"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -358,19 +308,15 @@
|
||||
|
||||
<record id="sale_order_line_24" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_10"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">255.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_25" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_10"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -390,19 +336,15 @@
|
||||
|
||||
<record id="sale_order_line_26" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_11"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">245.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_27" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_11"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -422,19 +364,14 @@
|
||||
|
||||
<record id="sale_order_line_28" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_12"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">315.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_29" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_12"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -453,19 +390,13 @@
|
||||
|
||||
<record id="sale_order_line_30" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_13"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_31" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_13"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">1</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -484,19 +415,15 @@
|
||||
|
||||
<record id="sale_order_line_32" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_14"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">4</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">275.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_33" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_14"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">4</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -515,19 +442,15 @@
|
||||
|
||||
<record id="sale_order_line_34" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_15"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">4</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_35" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_15"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -546,19 +469,15 @@
|
||||
|
||||
<record id="sale_order_line_36" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_16"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">275.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_37" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_16"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -577,19 +496,15 @@
|
||||
|
||||
<record id="sale_order_line_38" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_17"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">355.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_39" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_17"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -608,19 +523,15 @@
|
||||
|
||||
<record id="sale_order_line_40" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_18"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_41" model="sale.order.line">
|
||||
<field name="order_id" ref="sale_order_18"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_12').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_12"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">120.50</field>
|
||||
</record>
|
||||
|
||||
@@ -729,28 +640,22 @@ Thanks!</field>
|
||||
|
||||
<record id="portal_sale_order_line_1" model="sale.order.line">
|
||||
<field name="order_id" ref="portal_sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_25').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field name="product_uom_qty">3</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">295.00</field>
|
||||
</record>
|
||||
|
||||
<record id="portal_sale_order_line_2" model="sale.order.line">
|
||||
<field name="order_id" ref="portal_sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_02').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_02"/>
|
||||
<field name="product_uom_qty">5</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">145.00</field>
|
||||
</record>
|
||||
|
||||
<record id="portal_sale_order_line_3" model="sale.order.line">
|
||||
<field name="order_id" ref="portal_sale_order_1"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_delivery_01').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_delivery_01"/>
|
||||
<field name="product_uom_qty">2</field>
|
||||
<field name="product_uom" ref="uom.product_uom_unit"/>
|
||||
<field name="price_unit">65.00</field>
|
||||
</record>
|
||||
|
||||
@@ -767,19 +672,15 @@ Thanks!</field>
|
||||
|
||||
<record id="portal_sale_order_line_4" model="sale.order.line">
|
||||
<field name="order_id" ref="portal_sale_order_2"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_1').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_1"/>
|
||||
<field name="product_uom_qty">24</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">75.00</field>
|
||||
</record>
|
||||
|
||||
<record id="portal_sale_order_line_5" model="sale.order.line">
|
||||
<field name="order_id" ref="portal_sale_order_2"/>
|
||||
<field name="name" model="sale.order.line" eval="obj().env.ref('product.product_product_2').get_product_multiline_description_sale()"/>
|
||||
<field name="product_id" ref="product.product_product_2"/>
|
||||
<field name="product_uom_qty">30</field>
|
||||
<field name="product_uom" ref="uom.product_uom_hour"/>
|
||||
<field name="price_unit">38.25</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from . import test_access_rights
|
||||
from . import test_accrued_sale_orders
|
||||
from . import test_onchange
|
||||
from . import test_payment_flow
|
||||
from . import test_performance
|
||||
from . import test_reinvoice
|
||||
from . import test_sale_flow
|
||||
from . import test_sale_order
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
from odoo.tests import tagged
|
||||
|
||||
from odoo.addons.base.tests.common import PerformanceCommon
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSalePerformance(PerformanceCommon):
|
||||
|
||||
def test_batch_creation_sale_orders(self):
|
||||
"""Enforce sale.order create overrides always support batch creation"""
|
||||
self.assertModelCreateMulti('sale.order')
|
||||
|
||||
def test_batch_creation_sale_order_line(self):
|
||||
"""Enforce sale.order.line create overrides always support batch creation"""
|
||||
self.assertModelCreateMulti('sale.order.line')
|
||||
@@ -127,11 +127,12 @@ class SaleOrderTemplateLine(models.Model):
|
||||
self.product_uom_id = self.product_id.uom_id.id
|
||||
self.name = self.product_id.get_product_multiline_description_sale()
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if values.get('display_type', self.default_get(['display_type'])['display_type']):
|
||||
values.update(product_id=False, product_uom_qty=0, product_uom_id=False)
|
||||
return super(SaleOrderTemplateLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('display_type', self.default_get(['display_type'])['display_type']):
|
||||
vals.update(product_id=False, product_uom_qty=0, product_uom_id=False)
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, values):
|
||||
if 'display_type' in values and self.filtered(lambda line: line.display_type != values.get('display_type')):
|
||||
|
||||
@@ -65,11 +65,11 @@ class ProjectProductEmployeeMap(models.Model):
|
||||
for map_entry in self:
|
||||
map_entry.is_cost_changed = map_entry.employee_id and map_entry.cost != map_entry.employee_id.timesheet_cost
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
res = super(ProjectProductEmployeeMap, self).create(values)
|
||||
res._update_project_timesheet()
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
maps = super().create(vals_list)
|
||||
maps._update_project_timesheet()
|
||||
return maps
|
||||
|
||||
def write(self, values):
|
||||
res = super(ProjectProductEmployeeMap, self).write(values)
|
||||
|
||||
@@ -191,17 +191,18 @@ class Company(models.Model):
|
||||
def _create_per_company_rules(self):
|
||||
self.ensure_one()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
company = super(Company, self).create(vals)
|
||||
company.sudo()._create_per_company_locations()
|
||||
company.sudo()._create_per_company_sequences()
|
||||
company.sudo()._create_per_company_picking_types()
|
||||
company.sudo()._create_per_company_rules()
|
||||
self.env['stock.warehouse'].sudo().create({
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
companies = super().create(vals_list)
|
||||
for company in companies:
|
||||
company.sudo()._create_per_company_locations()
|
||||
company.sudo()._create_per_company_sequences()
|
||||
company.sudo()._create_per_company_picking_types()
|
||||
company.sudo()._create_per_company_rules()
|
||||
self.env['stock.warehouse'].sudo().create([{
|
||||
'name': company.name,
|
||||
'code': self.env.context.get('default_code') or company.name[:5],
|
||||
'company_id': company.id,
|
||||
'partner_id': company.partner_id.id
|
||||
})
|
||||
return company
|
||||
} for company in companies])
|
||||
return companies
|
||||
|
||||
@@ -139,13 +139,14 @@ class StockPackageLevel(models.Model):
|
||||
'company_id': package_level.company_id.id,
|
||||
})
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
result = super(StockPackageLevel, self).create(vals)
|
||||
if vals.get('location_dest_id'):
|
||||
result.mapped('move_line_ids').write({'location_dest_id': vals['location_dest_id']})
|
||||
result.mapped('move_ids').write({'location_dest_id': vals['location_dest_id']})
|
||||
return result
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
package_levels = super().create(vals_list)
|
||||
for package_level, vals in zip(package_levels, vals_list):
|
||||
if vals.get('location_dest_id'):
|
||||
package_level.move_line_ids.write({'location_dest_id': vals['location_dest_id']})
|
||||
package_level.move_ids.write({'location_dest_id': vals['location_dest_id']})
|
||||
return package_levels
|
||||
|
||||
def write(self, vals):
|
||||
result = super(StockPackageLevel, self).write(vals)
|
||||
|
||||
@@ -88,25 +88,24 @@ class PickingType(models.Model):
|
||||
'res.company', 'Company', required=True,
|
||||
default=lambda s: s.env.company.id, index=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'sequence_id' not in vals or not vals['sequence_id']:
|
||||
if vals['warehouse_id']:
|
||||
wh = self.env['stock.warehouse'].browse(vals['warehouse_id'])
|
||||
vals['sequence_id'] = self.env['ir.sequence'].sudo().create({
|
||||
'name': wh.name + ' ' + _('Sequence') + ' ' + vals['sequence_code'],
|
||||
'prefix': wh.code + '/' + vals['sequence_code'] + '/', 'padding': 5,
|
||||
'company_id': wh.company_id.id,
|
||||
}).id
|
||||
else:
|
||||
vals['sequence_id'] = self.env['ir.sequence'].sudo().create({
|
||||
'name': _('Sequence') + ' ' + vals['sequence_code'],
|
||||
'prefix': vals['sequence_code'], 'padding': 5,
|
||||
'company_id': vals.get('company_id') or self.env.company.id,
|
||||
}).id
|
||||
|
||||
picking_type = super(PickingType, self).create(vals)
|
||||
return picking_type
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if 'sequence_id' not in vals or not vals['sequence_id']:
|
||||
if vals['warehouse_id']:
|
||||
wh = self.env['stock.warehouse'].browse(vals['warehouse_id'])
|
||||
vals['sequence_id'] = self.env['ir.sequence'].sudo().create({
|
||||
'name': wh.name + ' ' + _('Sequence') + ' ' + vals['sequence_code'],
|
||||
'prefix': wh.code + '/' + vals['sequence_code'] + '/', 'padding': 5,
|
||||
'company_id': wh.company_id.id,
|
||||
}).id
|
||||
else:
|
||||
vals['sequence_id'] = self.env['ir.sequence'].sudo().create({
|
||||
'name': _('Sequence') + ' ' + vals['sequence_code'],
|
||||
'prefix': vals['sequence_code'], 'padding': 5,
|
||||
'company_id': vals.get('company_id') or self.env.company.id,
|
||||
}).id
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
if 'company_id' in vals:
|
||||
@@ -724,32 +723,37 @@ class Picking(models.Model):
|
||||
"location_dest_id": self.location_dest_id
|
||||
})
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
defaults = self.default_get(['name', 'picking_type_id'])
|
||||
picking_type = self.env['stock.picking.type'].browse(vals.get('picking_type_id', defaults.get('picking_type_id')))
|
||||
if vals.get('name', '/') == '/' and defaults.get('name', '/') == '/' and vals.get('picking_type_id', defaults.get('picking_type_id')):
|
||||
if picking_type.sequence_id:
|
||||
vals['name'] = picking_type.sequence_id.next_by_id()
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
scheduled_dates = []
|
||||
for vals in vals_list:
|
||||
defaults = self.default_get(['name', 'picking_type_id'])
|
||||
picking_type = self.env['stock.picking.type'].browse(vals.get('picking_type_id', defaults.get('picking_type_id')))
|
||||
if vals.get('name', '/') == '/' and defaults.get('name', '/') == '/' and vals.get('picking_type_id', defaults.get('picking_type_id')):
|
||||
if picking_type.sequence_id:
|
||||
vals['name'] = picking_type.sequence_id.next_by_id()
|
||||
|
||||
# make sure to write `schedule_date` *after* the `stock.move` creation in
|
||||
# order to get a determinist execution of `_set_scheduled_date`
|
||||
scheduled_date = vals.pop('scheduled_date', False)
|
||||
res = super(Picking, self).create(vals)
|
||||
if scheduled_date:
|
||||
res.with_context(mail_notrack=True).write({'scheduled_date': scheduled_date})
|
||||
res._autoconfirm_picking()
|
||||
# make sure to write `schedule_date` *after* the `stock.move` creation in
|
||||
# order to get a determinist execution of `_set_scheduled_date`
|
||||
scheduled_dates.append(vals.pop('scheduled_date', False))
|
||||
|
||||
# set partner as follower
|
||||
if vals.get('partner_id'):
|
||||
for picking in res.filtered(lambda p: p.location_id.usage == 'supplier' or p.location_dest_id.usage == 'customer'):
|
||||
picking.message_subscribe([vals.get('partner_id')])
|
||||
if vals.get('picking_type_id'):
|
||||
for move in res.move_ids:
|
||||
if not move.description_picking:
|
||||
move.description_picking = move.product_id.with_context(lang=move._get_lang())._get_description(move.picking_id.picking_type_id)
|
||||
pickings = super().create(vals_list)
|
||||
|
||||
return res
|
||||
for picking, scheduled_date in zip(pickings, scheduled_dates):
|
||||
if scheduled_date:
|
||||
picking.with_context(mail_notrack=True).write({'scheduled_date': scheduled_date})
|
||||
pickings._autoconfirm_picking()
|
||||
|
||||
for picking, vals in zip(pickings, vals_list):
|
||||
# set partner as follower
|
||||
if vals.get('partner_id'):
|
||||
if picking.location_id.usage == 'supplier' or picking.location_dest_id.usage == 'customer':
|
||||
picking.message_subscribe([vals.get('partner_id')])
|
||||
if vals.get('picking_type_id'):
|
||||
for move in picking.move_ids:
|
||||
if not move.description_picking:
|
||||
move.description_picking = move.product_id.with_context(lang=move._get_lang())._get_description(move.picking_id.picking_type_id)
|
||||
return pickings
|
||||
|
||||
def write(self, vals):
|
||||
if vals.get('picking_type_id') and any(picking.state != 'draft' for picking in self):
|
||||
|
||||
@@ -170,40 +170,43 @@ class StockQuant(models.Model):
|
||||
domain_operator = 'in'
|
||||
return [('id', domain_operator, quant_query)]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" Override to handle the "inventory mode" and create a quant as
|
||||
superuser the conditions are met.
|
||||
"""
|
||||
if self._is_inventory_mode() and any(f in vals for f in ['inventory_quantity', 'inventory_quantity_auto_apply']):
|
||||
allowed_fields = self._get_inventory_fields_create()
|
||||
if any(field for field in vals.keys() if field not in allowed_fields):
|
||||
raise UserError(_("Quant's creation is restricted, you can't do this operation."))
|
||||
quants = self.env['stock.quant']
|
||||
is_inventory_mode = self._is_inventory_mode()
|
||||
allowed_fields = self._get_inventory_fields_create()
|
||||
for vals in vals_list:
|
||||
if is_inventory_mode and any(f in vals for f in ['inventory_quantity', 'inventory_quantity_auto_apply']):
|
||||
if any(field for field in vals.keys() if field not in allowed_fields):
|
||||
raise UserError(_("Quant's creation is restricted, you can't do this operation."))
|
||||
inventory_quantity = vals.pop('inventory_quantity', False) or vals.pop(
|
||||
'inventory_quantity_auto_apply', False) or 0
|
||||
# Create an empty quant or write on a similar one.
|
||||
product = self.env['product.product'].browse(vals['product_id'])
|
||||
location = self.env['stock.location'].browse(vals['location_id'])
|
||||
lot_id = self.env['stock.lot'].browse(vals.get('lot_id'))
|
||||
package_id = self.env['stock.quant.package'].browse(vals.get('package_id'))
|
||||
owner_id = self.env['res.partner'].browse(vals.get('owner_id'))
|
||||
quant = self._gather(product, location, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True)
|
||||
|
||||
inventory_quantity = vals.pop('inventory_quantity', False) or vals.pop(
|
||||
'inventory_quantity_auto_apply', False) or 0
|
||||
# Create an empty quant or write on a similar one.
|
||||
product = self.env['product.product'].browse(vals['product_id'])
|
||||
location = self.env['stock.location'].browse(vals['location_id'])
|
||||
lot_id = self.env['stock.lot'].browse(vals.get('lot_id'))
|
||||
package_id = self.env['stock.quant.package'].browse(vals.get('package_id'))
|
||||
owner_id = self.env['res.partner'].browse(vals.get('owner_id'))
|
||||
quant = self._gather(product, location, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True)
|
||||
|
||||
if quant:
|
||||
quant = quant[0].sudo()
|
||||
if quant:
|
||||
quant = quant[0].sudo()
|
||||
else:
|
||||
quant = self.sudo().create(vals)
|
||||
# Set the `inventory_quantity` field to create the necessary move.
|
||||
quant.inventory_quantity = inventory_quantity
|
||||
quant.user_id = vals.get('user_id', self.env.user.id)
|
||||
quant.inventory_date = fields.Date.today()
|
||||
quants |= quant
|
||||
else:
|
||||
quant = self.sudo().create(vals)
|
||||
# Set the `inventory_quantity` field to create the necessary move.
|
||||
quant.inventory_quantity = inventory_quantity
|
||||
quant.user_id = vals.get('user_id', self.env.user.id)
|
||||
quant.inventory_date = fields.Date.today()
|
||||
|
||||
return quant
|
||||
res = super(StockQuant, self).create(vals)
|
||||
if self._is_inventory_mode():
|
||||
res._check_company()
|
||||
return res
|
||||
quant = super().create(vals)
|
||||
quants |= quant
|
||||
if self._is_inventory_mode():
|
||||
quant._check_company()
|
||||
return quants
|
||||
|
||||
def _load_records_create(self, values):
|
||||
""" Add default location if import file did not fill it"""
|
||||
|
||||
@@ -106,44 +106,47 @@ class Warehouse(models.Model):
|
||||
}
|
||||
}
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# create view location for warehouse then create all locations
|
||||
loc_vals = {'name': vals.get('code'), 'usage': 'view',
|
||||
'location_id': self.env.ref('stock.stock_location_locations').id}
|
||||
if vals.get('company_id'):
|
||||
loc_vals['company_id'] = vals.get('company_id')
|
||||
vals['view_location_id'] = self.env['stock.location'].create(loc_vals).id
|
||||
sub_locations = self._get_locations_values(vals)
|
||||
|
||||
for field_name, values in sub_locations.items():
|
||||
values['location_id'] = vals['view_location_id']
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
# create view location for warehouse then create all locations
|
||||
loc_vals = {'name': vals.get('code'), 'usage': 'view',
|
||||
'location_id': self.env.ref('stock.stock_location_locations').id}
|
||||
if vals.get('company_id'):
|
||||
values['company_id'] = vals.get('company_id')
|
||||
vals[field_name] = self.env['stock.location'].with_context(active_test=False).create(values).id
|
||||
loc_vals['company_id'] = vals.get('company_id')
|
||||
vals['view_location_id'] = self.env['stock.location'].create(loc_vals).id
|
||||
sub_locations = self._get_locations_values(vals)
|
||||
|
||||
for field_name, values in sub_locations.items():
|
||||
values['location_id'] = vals['view_location_id']
|
||||
if vals.get('company_id'):
|
||||
values['company_id'] = vals.get('company_id')
|
||||
vals[field_name] = self.env['stock.location'].with_context(active_test=False).create(values).id
|
||||
|
||||
# actually create WH
|
||||
warehouse = super(Warehouse, self).create(vals)
|
||||
# create sequences and operation types
|
||||
new_vals = warehouse._create_or_update_sequences_and_picking_types()
|
||||
warehouse.write(new_vals) # TDE FIXME: use super ?
|
||||
# create routes and push/stock rules
|
||||
route_vals = warehouse._create_or_update_route()
|
||||
warehouse.write(route_vals)
|
||||
warehouses = super().create(vals_list)
|
||||
|
||||
# Update global route with specific warehouse rule.
|
||||
warehouse._create_or_update_global_routes_rules()
|
||||
for warehouse, vals in zip(warehouses, vals_list):
|
||||
# create sequences and operation types
|
||||
new_vals = warehouse._create_or_update_sequences_and_picking_types()
|
||||
warehouse.write(new_vals) # TDE FIXME: use super ?
|
||||
# create routes and push/stock rules
|
||||
route_vals = warehouse._create_or_update_route()
|
||||
warehouse.write(route_vals)
|
||||
|
||||
# create route selectable on the product to resupply the warehouse from another one
|
||||
warehouse.create_resupply_routes(warehouse.resupply_wh_ids)
|
||||
# Update global route with specific warehouse rule.
|
||||
warehouse._create_or_update_global_routes_rules()
|
||||
|
||||
# update partner data if partner assigned
|
||||
if vals.get('partner_id'):
|
||||
self._update_partner_data(vals['partner_id'], vals.get('company_id'))
|
||||
# create route selectable on the product to resupply the warehouse from another one
|
||||
warehouse.create_resupply_routes(warehouse.resupply_wh_ids)
|
||||
|
||||
# update partner data if partner assigned
|
||||
if vals.get('partner_id'):
|
||||
self._update_partner_data(vals['partner_id'], vals.get('company_id'))
|
||||
|
||||
self._check_multiwarehouse_group()
|
||||
|
||||
return warehouse
|
||||
return warehouses
|
||||
|
||||
def write(self, vals):
|
||||
if 'company_id' in vals:
|
||||
|
||||
@@ -300,7 +300,7 @@ class TestInventory(TransactionCase):
|
||||
after an adjustment.
|
||||
"""
|
||||
# Set product quantity to 42.
|
||||
inventory_quant = self.env['stock.quant'].create(vals={
|
||||
inventory_quant = self.env['stock.quant'].create({
|
||||
'product_id': self.product1.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'inventory_quantity': 42,
|
||||
|
||||
@@ -83,11 +83,12 @@ class StockLandedCost(models.Model):
|
||||
if self.target_model != 'picking':
|
||||
self.picking_ids = False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('name', _('New')) == _('New'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('stock.landed.cost')
|
||||
return super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('name', _('New')) == _('New'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('stock.landed.cost')
|
||||
return super().create(vals_list)
|
||||
|
||||
def unlink(self):
|
||||
self.button_cancel()
|
||||
|
||||
@@ -43,12 +43,13 @@ class StockPicking(models.Model):
|
||||
states={'done': [('readonly', True)], 'cancel': [('readonly', True)]},
|
||||
help='Batch associated to this transfer', copy=False)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super().create(vals)
|
||||
if vals.get('batch_id'):
|
||||
res.batch_id._sanity_check()
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
pickings = super().create(vals_list)
|
||||
for picking, vals in zip(pickings, vals_list):
|
||||
if vals.get('batch_id'):
|
||||
picking.batch_id._sanity_check()
|
||||
return pickings
|
||||
|
||||
def write(self, vals):
|
||||
batches = self.batch_id
|
||||
|
||||
@@ -152,14 +152,16 @@ class StockPickingBatch(models.Model):
|
||||
# -------------------------------------------------------------------------
|
||||
# CRUD
|
||||
# -------------------------------------------------------------------------
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('name', '/') == '/':
|
||||
if vals.get('is_wave'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('picking.wave') or '/'
|
||||
else:
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('picking.batch') or '/'
|
||||
return super().create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('name', '/') == '/':
|
||||
company_id = vals.get('company_id', self.env.company.id)
|
||||
if vals.get('is_wave'):
|
||||
vals['name'] = self.env['ir.sequence'].with_company(company_id).next_by_code('picking.wave') or '/'
|
||||
else:
|
||||
vals['name'] = self.env['ir.sequence'].with_company(company_id).next_by_code('picking.batch') or '/'
|
||||
return super().create(vals_list)
|
||||
|
||||
def write(self, vals):
|
||||
res = super().write(vals)
|
||||
|
||||
@@ -17,12 +17,13 @@ class Attachment(models.Model):
|
||||
key = fields.Char(help='Technical field used to resolve multiple attachments in a multi-website environment.')
|
||||
website_id = fields.Many2one('website')
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
website = self.env['website'].get_current_website(fallback=False)
|
||||
if website and 'website_id' not in vals and 'not_force_website_id' not in self.env.context:
|
||||
vals['website_id'] = website.id
|
||||
return super(Attachment, self).create(vals)
|
||||
for vals in vals_list:
|
||||
if website and 'website_id' not in vals and 'not_force_website_id' not in self.env.context:
|
||||
vals['website_id'] = website.id
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.model
|
||||
def get_serving_groups(self):
|
||||
|
||||
@@ -174,24 +174,26 @@ class Website(models.Model):
|
||||
def _get_menu_ids(self):
|
||||
return self.env['website.menu'].search([('website_id', '=', self.id)]).ids
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
self._handle_create_write(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
self._handle_create_write(vals)
|
||||
|
||||
if 'user_id' not in vals:
|
||||
company = self.env['res.company'].browse(vals.get('company_id'))
|
||||
vals['user_id'] = company._get_public_user().id if company else self.env.ref('base.public_user').id
|
||||
if 'user_id' not in vals:
|
||||
company = self.env['res.company'].browse(vals.get('company_id'))
|
||||
vals['user_id'] = company._get_public_user().id if company else self.env.ref('base.public_user').id
|
||||
|
||||
res = super(Website, self).create(vals)
|
||||
res.company_id._compute_website_id()
|
||||
res._bootstrap_homepage()
|
||||
websites = super().create(vals_list)
|
||||
websites.company_id._compute_website_id()
|
||||
for website in websites:
|
||||
website._bootstrap_homepage()
|
||||
|
||||
if not self.env.user.has_group('website.group_multi_website') and self.search_count([]) > 1:
|
||||
all_user_groups = 'base.group_portal,base.group_user,base.group_public'
|
||||
groups = self.env['res.groups'].concat(*(self.env.ref(it) for it in all_user_groups.split(',')))
|
||||
groups.write({'implied_ids': [(4, self.env.ref('website.group_multi_website').id)]})
|
||||
|
||||
return res
|
||||
return websites
|
||||
|
||||
def write(self, values):
|
||||
public_user_to_change_websites = self.env['website']
|
||||
|
||||
@@ -61,8 +61,8 @@ class Menu(models.Model):
|
||||
res.append((menu.id, menu_name))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
''' In case a menu without a website_id is trying to be created, we duplicate
|
||||
it for every website.
|
||||
Note: Particulary useful when installing a module that adds a menu like
|
||||
@@ -72,27 +72,32 @@ class Menu(models.Model):
|
||||
'''
|
||||
self.clear_caches()
|
||||
# Only used when creating website_data.xml default menu
|
||||
if vals.get('url') == '/default-main-menu':
|
||||
return super(Menu, self).create(vals)
|
||||
|
||||
if 'website_id' in vals:
|
||||
return super(Menu, self).create(vals)
|
||||
elif self._context.get('website_id'):
|
||||
vals['website_id'] = self._context.get('website_id')
|
||||
return super(Menu, self).create(vals)
|
||||
else:
|
||||
# create for every site
|
||||
for website in self.env['website'].search([]):
|
||||
w_vals = dict(vals, **{
|
||||
menus = self.env['website.menu']
|
||||
for vals in vals_list:
|
||||
if vals.get('url') == '/default-main-menu':
|
||||
menus |= super().create(vals)
|
||||
continue
|
||||
if 'website_id' in vals:
|
||||
menus |= super().create(vals)
|
||||
continue
|
||||
elif self._context.get('website_id'):
|
||||
vals['website_id'] = self._context.get('website_id')
|
||||
menus |= super().create(vals)
|
||||
continue
|
||||
else:
|
||||
# create for every site
|
||||
w_vals = [dict(vals, **{
|
||||
'website_id': website.id,
|
||||
'parent_id': website.menu_id.id,
|
||||
})
|
||||
res = super(Menu, self).create(w_vals)
|
||||
# if creating a default menu, we should also save it as such
|
||||
default_menu = self.env.ref('website.main_menu', raise_if_not_found=False)
|
||||
if default_menu and vals.get('parent_id') == default_menu.id:
|
||||
res = super(Menu, self).create(vals)
|
||||
return res # Only one record is returned but multiple could have been created
|
||||
}) for website in self.env['website'].search([])]
|
||||
new_menu = super().create(w_vals)[-1:] # take the last one
|
||||
# if creating a default menu, we should also save it as such
|
||||
default_menu = self.env.ref('website.main_menu', raise_if_not_found=False)
|
||||
if default_menu and vals.get('parent_id') == default_menu.id:
|
||||
new_menu = super().create(vals)
|
||||
menus |= new_menu
|
||||
# Only one record per vals is returned but multiple could have been created
|
||||
return menus
|
||||
|
||||
def write(self, values):
|
||||
res = super().write(values)
|
||||
|
||||
@@ -108,11 +108,11 @@ class WebsiteRewrite(models.Model):
|
||||
result.append((rewrite.id, name))
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(WebsiteRewrite, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
rewrites = super().create(vals_list)
|
||||
self._invalidate_routing()
|
||||
return res
|
||||
return rewrites
|
||||
|
||||
def write(self, vals):
|
||||
res = super(WebsiteRewrite, self).write(vals)
|
||||
|
||||
@@ -229,11 +229,12 @@ class BlogPost(models.Model):
|
||||
return True
|
||||
return False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
post_id = super(BlogPost, self.with_context(mail_create_nolog=True)).create(vals)
|
||||
post_id._check_for_publication(vals)
|
||||
return post_id
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
posts = super(BlogPost, self.with_context(mail_create_nolog=True)).create(vals_list)
|
||||
for post, vals in zip(posts, vals_list):
|
||||
post._check_for_publication(vals)
|
||||
return posts
|
||||
|
||||
def write(self, vals):
|
||||
result = True
|
||||
|
||||
@@ -532,28 +532,31 @@ class Post(models.Model):
|
||||
if not self._check_recursion():
|
||||
raise ValidationError(_('You cannot create recursive forum posts.'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'content' in vals and vals.get('forum_id'):
|
||||
vals['content'] = self._update_content(vals['content'], vals['forum_id'])
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if 'content' in vals and vals.get('forum_id'):
|
||||
vals['content'] = self._update_content(vals['content'], vals['forum_id'])
|
||||
|
||||
post = super(Post, self.with_context(mail_create_nolog=True)).create(vals)
|
||||
# deleted or closed questions
|
||||
if post.parent_id and (post.parent_id.state == 'close' or post.parent_id.active is False):
|
||||
raise UserError(_('Posting answer on a [Deleted] or [Closed] question is not possible.'))
|
||||
# karma-based access
|
||||
if not post.parent_id and not post.can_ask:
|
||||
raise AccessError(_('%d karma required to create a new question.', post.forum_id.karma_ask))
|
||||
elif post.parent_id and not post.can_answer:
|
||||
raise AccessError(_('%d karma required to answer a question.', post.forum_id.karma_answer))
|
||||
if not post.parent_id and not post.can_post:
|
||||
post.sudo().state = 'pending'
|
||||
posts = super(Post, self.with_context(mail_create_nolog=True)).create(vals_list)
|
||||
|
||||
# add karma for posting new questions
|
||||
if not post.parent_id and post.state == 'active':
|
||||
self.env.user.sudo().add_karma(post.forum_id.karma_gen_question_new)
|
||||
post.post_notification()
|
||||
return post
|
||||
for post in posts:
|
||||
# deleted or closed questions
|
||||
if post.parent_id and (post.parent_id.state == 'close' or post.parent_id.active is False):
|
||||
raise UserError(_('Posting answer on a [Deleted] or [Closed] question is not possible.'))
|
||||
# karma-based access
|
||||
if not post.parent_id and not post.can_ask:
|
||||
raise AccessError(_('%d karma required to create a new question.', post.forum_id.karma_ask))
|
||||
elif post.parent_id and not post.can_answer:
|
||||
raise AccessError(_('%d karma required to answer a question.', post.forum_id.karma_answer))
|
||||
if not post.parent_id and not post.can_post:
|
||||
post.sudo().state = 'pending'
|
||||
|
||||
# add karma for posting new questions
|
||||
if not post.parent_id and post.state == 'active':
|
||||
self.env.user.sudo().add_karma(post.forum_id.karma_gen_question_new)
|
||||
posts.post_notification()
|
||||
return posts
|
||||
|
||||
@api.model
|
||||
def _get_mail_message_access(self, res_ids, operation, model_name=None):
|
||||
@@ -1077,20 +1080,22 @@ class Vote(models.Model):
|
||||
}
|
||||
return _karma_upd[old_vote][new_vote]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# can't modify owner of a vote
|
||||
if not self.env.is_admin():
|
||||
vals.pop('user_id', None)
|
||||
for vals in vals_list:
|
||||
vals.pop('user_id', None)
|
||||
|
||||
vote = super(Vote, self).create(vals)
|
||||
votes = super(Vote, self).create(vals_list)
|
||||
|
||||
vote._check_general_rights()
|
||||
vote._check_karma_rights(vote.vote == '1')
|
||||
for vote in votes:
|
||||
vote._check_general_rights()
|
||||
vote._check_karma_rights(vote.vote == '1')
|
||||
|
||||
# karma update
|
||||
vote._vote_update_karma('0', vote.vote)
|
||||
return vote
|
||||
# karma update
|
||||
vote._vote_update_karma('0', vote.vote)
|
||||
return votes
|
||||
|
||||
def write(self, values):
|
||||
# can't modify owner of a vote
|
||||
@@ -1160,9 +1165,10 @@ class Tags(models.Model):
|
||||
for tag in self:
|
||||
tag.posts_count = len(tag.post_ids)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
forum = self.env['forum.forum'].browse(vals.get('forum_id'))
|
||||
if self.env.user.karma < forum.karma_tag_create:
|
||||
raise AccessError(_('%d karma required to create a new Tag.', forum.karma_tag_create))
|
||||
return super(Tags, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
forum = self.env['forum.forum'].browse(vals.get('forum_id'))
|
||||
if self.env.user.karma < forum.karma_tag_create:
|
||||
raise AccessError(_('%d karma required to create a new Tag.', forum.karma_tag_create))
|
||||
return super(Tags, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(vals_list)
|
||||
|
||||
@@ -44,16 +44,19 @@ class ProductPricelist(models.Model):
|
||||
website = self.env['website']
|
||||
website._get_pl_partner_order.clear_cache(website)
|
||||
|
||||
@api.model
|
||||
def create(self, data):
|
||||
if data.get('company_id') and not data.get('website_id'):
|
||||
# l10n modules install will change the company currency, creating a
|
||||
# pricelist for that currency. Do not use user's company in that
|
||||
# case as module install are done with OdooBot (company 1)
|
||||
self = self.with_context(default_company_id=data['company_id'])
|
||||
res = super(ProductPricelist, self).create(data)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('company_id') and not vals.get('website_id'):
|
||||
# l10n modules install will change the company currency, creating a
|
||||
# pricelist for that currency. Do not use user's company in that
|
||||
# case as module install are done with OdooBot (company 1)
|
||||
# YTI FIXME: The fix is not at the correct place
|
||||
# It be set when we actually create the pricelist
|
||||
self = self.with_context(default_company_id=vals['company_id'])
|
||||
pricelists = super().create(vals_list)
|
||||
self.clear_cache()
|
||||
return res
|
||||
return pricelists
|
||||
|
||||
def write(self, data):
|
||||
res = super(ProductPricelist, self).write(data)
|
||||
|
||||
@@ -447,23 +447,26 @@ class Channel(models.Model):
|
||||
""" % {'table_name': self._table}
|
||||
self.env.cr.execute(query)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# Ensure creator is member of its channel it is easier for him to manage it (unless it is odoobot)
|
||||
if not vals.get('channel_partner_ids') and not self.env.is_superuser():
|
||||
vals['channel_partner_ids'] = [(0, 0, {
|
||||
'partner_id': self.env.user.partner_id.id
|
||||
})]
|
||||
if not is_html_empty(vals.get('description')) and is_html_empty(vals.get('description_short')):
|
||||
vals['description_short'] = vals['description']
|
||||
channel = super(Channel, self.with_context(mail_create_nosubscribe=True)).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
# Ensure creator is member of its channel it is easier for him to manage it (unless it is odoobot)
|
||||
if not vals.get('channel_partner_ids') and not self.env.is_superuser():
|
||||
vals['channel_partner_ids'] = [(0, 0, {
|
||||
'partner_id': self.env.user.partner_id.id
|
||||
})]
|
||||
if not is_html_empty(vals.get('description')) and is_html_empty(vals.get('description_short')):
|
||||
vals['description_short'] = vals['description']
|
||||
|
||||
if channel.user_id:
|
||||
channel._action_add_members(channel.user_id.partner_id)
|
||||
if 'enroll_group_ids' in vals:
|
||||
channel._add_groups_members()
|
||||
channels = super(Channel, self.with_context(mail_create_nosubscribe=True)).create(vals_list)
|
||||
|
||||
return channel
|
||||
for channel in channels:
|
||||
if channel.user_id:
|
||||
channel._action_add_members(channel.user_id.partner_id)
|
||||
if channel.enroll_group_ids:
|
||||
channel._add_groups_members()
|
||||
|
||||
return channels
|
||||
|
||||
def write(self, vals):
|
||||
# If description_short wasn't manually modified, there is an implicit link between this field and description.
|
||||
|
||||
@@ -546,38 +546,41 @@ class Slide(models.Model):
|
||||
# ORM Overrides
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
# Do not publish slide if user has not publisher rights
|
||||
channel = self.env['slide.channel'].browse(values['channel_id'])
|
||||
if not channel.can_publish:
|
||||
# 'website_published' is handled by mixin
|
||||
values['date_published'] = False
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
channel_ids = [vals['channel_id'] for vals in vals_list]
|
||||
can_publish_channel_ids = self.env['slide.channel'].browse(channel_ids).filtered(lambda c: c.can_publish).ids
|
||||
for vals in vals_list:
|
||||
# Do not publish slide if user has not publisher rights
|
||||
if vals['channel_id'] not in can_publish_channel_ids:
|
||||
# 'website_published' is handled by mixin
|
||||
vals['date_published'] = False
|
||||
|
||||
if values.get('is_category'):
|
||||
values['is_preview'] = True
|
||||
values['is_published'] = True
|
||||
if values.get('is_published') and not values.get('date_published'):
|
||||
values['date_published'] = datetime.datetime.now()
|
||||
if vals.get('is_category'):
|
||||
vals['is_preview'] = True
|
||||
vals['is_published'] = True
|
||||
if vals.get('is_published') and not vals.get('date_published'):
|
||||
vals['date_published'] = datetime.datetime.now()
|
||||
|
||||
slide = super(Slide, self).create(values)
|
||||
slides = super().create(vals_list)
|
||||
|
||||
# avoid fetching external metadata when installing the module (i.e. for demo data)
|
||||
# we also support a context key if you don't want to fetch the metadata when creating a slide
|
||||
if any(values.get(url_param) for url_param in ['url', 'video_url', 'document_google_url', 'image_google_url']) \
|
||||
and not self.env.context.get('install_mode') \
|
||||
and not self.env.context.get('website_slides_skip_fetch_metadata'):
|
||||
slide_metadata, _error = slide._fetch_external_metadata()
|
||||
if slide_metadata:
|
||||
# only update keys that are not set in the incoming values
|
||||
slide.update({key: value for key, value in slide_metadata.items() if key not in values.keys()})
|
||||
for slide, vals in zip(slides, vals_list):
|
||||
# avoid fetching external metadata when installing the module (i.e. for demo data)
|
||||
# we also support a context key if you don't want to fetch the metadata when creating a slide
|
||||
if any(vals.get(url_param) for url_param in ['url', 'video_url', 'document_google_url', 'image_google_url']) \
|
||||
and not self.env.context.get('install_mode') \
|
||||
and not self.env.context.get('website_slides_skip_fetch_metadata'):
|
||||
slide_metadata, _error = slide._fetch_external_metadata()
|
||||
if slide_metadata:
|
||||
# only update keys that are not set in the incoming vals
|
||||
slide.update({key: value for key, value in slide_metadata.items() if key not in vals.keys()})
|
||||
|
||||
if not 'completion_time' not in values:
|
||||
slide._on_change_document_binary_content()
|
||||
if not 'completion_time' not in vals:
|
||||
slide._on_change_document_binary_content()
|
||||
|
||||
if slide.is_published and not slide.is_category:
|
||||
slide._post_publication()
|
||||
return slide
|
||||
if slide.is_published and not slide.is_category:
|
||||
slide._post_publication()
|
||||
return slides
|
||||
|
||||
def write(self, values):
|
||||
if values.get('is_category'):
|
||||
|
||||
@@ -64,14 +64,13 @@ class Slide(models.Model):
|
||||
if slide.slide_category == 'certification':
|
||||
slide.slide_type = 'certification'
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
rec = super(Slide, self).create(values)
|
||||
if rec.survey_id:
|
||||
rec.slide_category = 'certification'
|
||||
if 'survey_id' in values:
|
||||
rec._ensure_challenge_category()
|
||||
return rec
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
slides = super().create(vals_list)
|
||||
slides_with_survey = slides.filtered('survey_id')
|
||||
slides_with_survey.slide_category = 'certification'
|
||||
slides_with_survey._ensure_challenge_category()
|
||||
return slides
|
||||
|
||||
def write(self, values):
|
||||
old_surveys = self.mapped('survey_id')
|
||||
@@ -94,7 +93,7 @@ class Slide(models.Model):
|
||||
old_certification_challenges = old_surveys.mapped('certification_badge_id').challenge_ids
|
||||
old_certification_challenges.write({'challenge_category': 'certification'})
|
||||
if not unlink:
|
||||
certification_challenges = self.mapped('survey_id').mapped('certification_badge_id').challenge_ids
|
||||
certification_challenges = self.survey_id.certification_badge_id.challenge_ids
|
||||
certification_challenges.write({'challenge_category': 'slides'})
|
||||
|
||||
def _generate_certification_url(self):
|
||||
|
||||
@@ -61,12 +61,13 @@ class ResConfigSettings(models.TransientModel):
|
||||
_logger.info('Please double-check your Twitter API Key and Secret!', exc_info=True)
|
||||
raise UserError(_('Twitter authorization error! Please double-check your Twitter API Key and Secret!'))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
TwitterConfig = super(ResConfigSettings, self).create(vals)
|
||||
if vals.get('twitter_api_key') or vals.get('twitter_api_secret') or vals.get('twitter_screen_name'):
|
||||
TwitterConfig._check_twitter_authorization()
|
||||
return TwitterConfig
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
configs = super().create(vals_list)
|
||||
for config in configs:
|
||||
if config.twitter_api_key or config.twitter_api_secret or config.twitter_screen_name:
|
||||
config._check_twitter_authorization()
|
||||
return configs
|
||||
|
||||
def write(self, vals):
|
||||
TwitterConfig = super(ResConfigSettings, self).write(vals)
|
||||
|
||||
@@ -621,7 +621,7 @@ class IrAttachment(models.Model):
|
||||
for record_tuple in record_tuple_set:
|
||||
(res_model, res_id) = record_tuple
|
||||
self.check('create', values={'res_model':res_model, 'res_id':res_id})
|
||||
return super(IrAttachment, self).create(vals_list)
|
||||
return super().create(vals_list)
|
||||
|
||||
def _post_add_create(self):
|
||||
pass
|
||||
|
||||
@@ -65,12 +65,13 @@ class ir_cron(models.Model):
|
||||
lastcall = fields.Datetime(string='Last Execution Date', help="Previous time the cron ran successfully, provided to the job through the context on the `lastcall` key")
|
||||
priority = fields.Integer(default=5, help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
values['usage'] = 'ir_cron'
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
vals['usage'] = 'ir_cron'
|
||||
if os.getenv('ODOO_NOTIFY_CRON_CHANGES'):
|
||||
self._cr.postcommit.add(self._notifydb)
|
||||
return super(ir_cron, self).create(values)
|
||||
return super().create(vals_list)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
|
||||
@@ -724,18 +724,18 @@ class Module(models.Model):
|
||||
'to_buy': False
|
||||
}
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
new = super(Module, self).create(vals)
|
||||
module_metadata = {
|
||||
'name': 'module_%s' % vals['name'],
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
modules = super().create(vals_list)
|
||||
module_metadata_list = [{
|
||||
'name': 'module_%s' % module.name,
|
||||
'model': 'ir.module.module',
|
||||
'module': 'base',
|
||||
'res_id': new.id,
|
||||
'res_id': module.id,
|
||||
'noupdate': True,
|
||||
}
|
||||
self.env['ir.model.data'].create(module_metadata)
|
||||
return new
|
||||
} for module in modules]
|
||||
self.env['ir.model.data'].create(module_metadata_list)
|
||||
return modules
|
||||
|
||||
# update the list of available packages
|
||||
@assert_log_admin_access
|
||||
|
||||
@@ -150,14 +150,15 @@ class IrSequence(models.Model):
|
||||
use_date_range = fields.Boolean(string='Use subsequences per date_range')
|
||||
date_range_ids = fields.One2many('ir.sequence.date_range', 'sequence_id', string='Subsequences')
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" Create a sequence, in implementation == standard a fast gaps-allowed PostgreSQL sequence is used.
|
||||
"""
|
||||
seq = super(IrSequence, self).create(values)
|
||||
if values.get('implementation', 'standard') == 'standard':
|
||||
_create_sequence(self._cr, "ir_sequence_%03d" % seq.id, values.get('number_increment', 1), values.get('number_next', 1))
|
||||
return seq
|
||||
seqs = super().create(vals_list)
|
||||
for seq in seqs:
|
||||
if seq.implementation == 'standard':
|
||||
_create_sequence(self._cr, "ir_sequence_%03d" % seq.id, seq.number_increment or 1, seq.number_next or 1)
|
||||
return seqs
|
||||
|
||||
def unlink(self):
|
||||
_drop_sequences(self._cr, ["ir_sequence_%03d" % x.id for x in self])
|
||||
@@ -356,15 +357,16 @@ class IrSequenceDateRange(models.Model):
|
||||
for seq in self:
|
||||
_alter_sequence(self._cr, "ir_sequence_%03d_%03d" % (seq.sequence_id.id, seq.id), number_increment=number_increment, number_next=number_next)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" Create a sequence, in implementation == standard a fast gaps-allowed PostgreSQL sequence is used.
|
||||
"""
|
||||
seq = super(IrSequenceDateRange, self).create(values)
|
||||
main_seq = seq.sequence_id
|
||||
if main_seq.implementation == 'standard':
|
||||
_create_sequence(self._cr, "ir_sequence_%03d_%03d" % (main_seq.id, seq.id), main_seq.number_increment, values.get('number_next_actual', 1))
|
||||
return seq
|
||||
seqs = super().create(vals_list)
|
||||
for seq in seqs:
|
||||
main_seq = seq.sequence_id
|
||||
if main_seq.implementation == 'standard':
|
||||
_create_sequence(self._cr, "ir_sequence_%03d_%03d" % (main_seq.id, seq.id), main_seq.number_increment, seq.number_next_actual or 1)
|
||||
return seqs
|
||||
|
||||
def unlink(self):
|
||||
_drop_sequences(self._cr, ["ir_sequence_%03d_%03d" % (x.sequence_id.id, x.id) for x in self])
|
||||
|
||||
@@ -198,37 +198,51 @@ class Company(models.Model):
|
||||
def cache_restart(self):
|
||||
self.clear_caches()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if not vals.get('favicon'):
|
||||
vals['favicon'] = self._get_default_favicon()
|
||||
if not vals.get('name') or vals.get('partner_id'):
|
||||
self.clear_caches()
|
||||
return super(Company, self).create(vals)
|
||||
partner = self.env['res.partner'].create({
|
||||
'name': vals['name'],
|
||||
'is_company': True,
|
||||
'image_1920': vals.get('logo'),
|
||||
'email': vals.get('email'),
|
||||
'phone': vals.get('phone'),
|
||||
'website': vals.get('website'),
|
||||
'vat': vals.get('vat'),
|
||||
'country_id': vals.get('country_id'),
|
||||
})
|
||||
# compute stored fields, for example address dependent fields
|
||||
partner.flush()
|
||||
vals['partner_id'] = partner.id
|
||||
self.clear_caches()
|
||||
company = super(Company, self).create(vals)
|
||||
# The write is made on the user to set it automatically in the multi company group.
|
||||
self.env.user.write({'company_ids': [Command.link(company.id)]})
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# add default favicon
|
||||
for vals in vals_list:
|
||||
if not vals.get('favicon'):
|
||||
vals['favicon'] = self._get_default_favicon()
|
||||
|
||||
# Make sure that the selected currency is enabled
|
||||
if vals.get('currency_id'):
|
||||
currency = self.env['res.currency'].browse(vals['currency_id'])
|
||||
if not currency.active:
|
||||
currency.write({'active': True})
|
||||
return company
|
||||
# create missing partners
|
||||
no_partner_vals_list = [
|
||||
vals
|
||||
for vals in vals_list
|
||||
if vals.get('name') and not vals.get('partner_id')
|
||||
]
|
||||
if no_partner_vals_list:
|
||||
partners = self.env['res.partner'].create([
|
||||
{
|
||||
'name': vals['name'],
|
||||
'is_company': True,
|
||||
'image_1920': vals.get('logo'),
|
||||
'email': vals.get('email'),
|
||||
'phone': vals.get('phone'),
|
||||
'website': vals.get('website'),
|
||||
'vat': vals.get('vat'),
|
||||
'country_id': vals.get('country_id'),
|
||||
}
|
||||
for vals in no_partner_vals_list
|
||||
])
|
||||
# compute stored fields, for example address dependent fields
|
||||
partners.flush()
|
||||
for vals, partner in zip(no_partner_vals_list, partners):
|
||||
vals['partner_id'] = partner.id
|
||||
|
||||
self.clear_caches()
|
||||
companies = super().create(vals_list)
|
||||
|
||||
# The write is made on the user to set it automatically in the multi company group.
|
||||
if companies:
|
||||
self.env.user.write({
|
||||
'company_ids': [Command.link(company.id) for company in companies],
|
||||
})
|
||||
|
||||
# Make sure that the selected currencies are enabled
|
||||
companies.currency_id.sudo().filtered(lambda c: not c.active).active = True
|
||||
|
||||
return companies
|
||||
|
||||
def write(self, values):
|
||||
self.clear_caches()
|
||||
|
||||
@@ -765,34 +765,35 @@ class ResConfigSettings(models.TransientModel, ResConfigModuleInstallationMixin)
|
||||
return RedirectWarning(msg % values, action_id, _('Go to the configuration panel'))
|
||||
return UserError(msg % values)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# Optimisation: saving a res.config.settings even without changing any
|
||||
# values will trigger the write of all related values. This in turn may
|
||||
# trigger chain of further recomputation. To avoid it, delete values
|
||||
# that were not changed.
|
||||
for field in self._fields.values():
|
||||
if not (field.name in values and field.related and not field.readonly):
|
||||
continue
|
||||
# we write on a related field like
|
||||
# qr_code = fields.Boolean(related='company_id.qr_code', readonly=False)
|
||||
fname0, *fnames = field.related.split(".")
|
||||
if fname0 not in values:
|
||||
continue
|
||||
for vals in vals_list:
|
||||
for field in self._fields.values():
|
||||
if not (field.name in vals and field.related and not field.readonly):
|
||||
continue
|
||||
# we write on a related field like
|
||||
# qr_code = fields.Boolean(related='company_id.qr_code', readonly=False)
|
||||
fname0, *fnames = field.related.split(".")
|
||||
if fname0 not in vals:
|
||||
continue
|
||||
|
||||
# determine the current value
|
||||
field0 = self._fields[fname0]
|
||||
old_value = field0.convert_to_record(
|
||||
field0.convert_to_cache(values[fname0], self), self)
|
||||
for fname in fnames:
|
||||
old_value = next(iter(old_value), old_value)[fname]
|
||||
# determine the current value
|
||||
field0 = self._fields[fname0]
|
||||
old_value = field0.convert_to_record(
|
||||
field0.convert_to_cache(vals[fname0], self), self)
|
||||
for fname in fnames:
|
||||
old_value = next(iter(old_value), old_value)[fname]
|
||||
|
||||
# determine the new value
|
||||
new_value = field.convert_to_record(
|
||||
field.convert_to_cache(values[field.name], self), self)
|
||||
# determine the new value
|
||||
new_value = field.convert_to_record(
|
||||
field.convert_to_cache(vals[field.name], self), self)
|
||||
|
||||
# drop if the value is the same
|
||||
if old_value == new_value:
|
||||
values.pop(field.name)
|
||||
# drop if the value is the same
|
||||
if old_value == new_value:
|
||||
vals.pop(field.name)
|
||||
|
||||
return super(ResConfigSettings, self).create(values)
|
||||
return super().create(vals_list)
|
||||
|
||||
@@ -1162,13 +1162,13 @@ class UsersImplied(models.Model):
|
||||
class GroupsView(models.Model):
|
||||
_inherit = 'res.groups'
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
user = super(GroupsView, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
groups = super().create(vals_list)
|
||||
self._update_user_groups_view()
|
||||
# actions.get_bindings() depends on action records
|
||||
self.env['ir.actions.actions'].clear_caches()
|
||||
return user
|
||||
return groups
|
||||
|
||||
def write(self, values):
|
||||
# determine which values the "user groups view" depends on
|
||||
|
||||
@@ -8,27 +8,6 @@ from odoo.tests.common import TransactionCase, HttpCase
|
||||
from odoo import Command
|
||||
|
||||
|
||||
class PerformanceCommon(TransactionCase):
|
||||
|
||||
def assertModelCreateMulti(self, model_name, vals_list=None):
|
||||
"""Ensures model_name records can be created in batch.
|
||||
|
||||
:param str model_name: name of the model on which batch record creation should be verified
|
||||
:param list vals_list: example list of values, if needed
|
||||
"""
|
||||
vals_list = vals_list or [dict(), dict()]
|
||||
if not isinstance(vals_list, list):
|
||||
raise ValueError("Invalid arguments for assertModelCreateMulti")
|
||||
assert len(vals_list) > 1, "Batch creation cannot be tested with only one value."
|
||||
def patched_create(self, values_list):
|
||||
if len(values_list) != len(vals_list):
|
||||
raise ValueError(f"Model {model_name} doesn't support batch records creation.")
|
||||
# Do not create anything
|
||||
return self
|
||||
with patch('odoo.models.BaseModel.create', patched_create):
|
||||
self.env[model_name].create(vals_list)
|
||||
|
||||
|
||||
class TransactionCaseWithUserDemo(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -738,10 +738,10 @@ class TestAssetsBundleWithIRAMock(FileTouchable):
|
||||
origin_create = IrAttachment.create
|
||||
origin_unlink = IrAttachment.unlink
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
counter.update(['create'])
|
||||
return origin_create(self, vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
counter.update(['create'] * len(vals_list))
|
||||
return origin_create(self, vals_list)
|
||||
|
||||
def unlink(self):
|
||||
counter.update(['unlink'])
|
||||
|
||||
@@ -401,6 +401,7 @@ def model_create_single(method):
|
||||
record = model.create(vals)
|
||||
records = model.create([vals, ...])
|
||||
"""
|
||||
_create_logger.warning("The model %s is not overriding the create method in batch", method.__module__)
|
||||
wrapper = decorate(method, _model_create_single)
|
||||
wrapper._api = 'model_create'
|
||||
return wrapper
|
||||
|
||||
Reference in New Issue
Block a user