[REF] *: adapt create to work in batch
This commit is contained in:
@@ -1025,59 +1025,53 @@ class AccountMoveLine(models.Model):
|
||||
# CRUD methods
|
||||
####################################################
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" :context's key `check_move_validity`: check data consistency after move line creation. Eg. set to false to disable verification that the move
|
||||
debit-credit == 0 while creating the move lines composing the move.
|
||||
"""
|
||||
amount = vals.get('debit', 0.0) - vals.get('credit', 0.0)
|
||||
move = self.env['account.move'].browse(vals['move_id'])
|
||||
account = self.env['account.account'].browse(vals['account_id'])
|
||||
if account.deprecated:
|
||||
raise UserError(_('The account %s (%s) is deprecated.') %(account.name, account.code))
|
||||
journal = vals.get('journal_id') and self.env['account.journal'].browse(vals['journal_id']) or move.journal_id
|
||||
vals['date_maturity'] = vals.get('date_maturity') or vals.get('date') or move.date
|
||||
ok = not (journal.type_control_ids or journal.account_control_ids)
|
||||
for vals in vals_list:
|
||||
amount = vals.get('debit', 0.0) - vals.get('credit', 0.0)
|
||||
move = self.env['account.move'].browse(vals['move_id'])
|
||||
account = self.env['account.account'].browse(vals['account_id'])
|
||||
if account.deprecated:
|
||||
raise UserError(_('The account %s (%s) is deprecated.') %(account.name, account.code))
|
||||
journal = vals.get('journal_id') and self.env['account.journal'].browse(vals['journal_id']) or move.journal_id
|
||||
vals['date_maturity'] = vals.get('date_maturity') or vals.get('date') or move.date
|
||||
|
||||
if journal.type_control_ids:
|
||||
type = account.user_type_id
|
||||
for t in journal.type_control_ids:
|
||||
if type == t:
|
||||
ok = True
|
||||
break
|
||||
if journal.account_control_ids and not ok:
|
||||
for a in journal.account_control_ids:
|
||||
if a.id == vals['account_id']:
|
||||
ok = True
|
||||
break
|
||||
# Automatically convert in the account's secondary currency if there is one and
|
||||
# the provided values were not already multi-currency
|
||||
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
|
||||
vals['currency_id'] = account.currency_id.id
|
||||
ctx = {}
|
||||
if 'date' in vals:
|
||||
ctx['date'] = vals['date']
|
||||
vals['amount_currency'] = account.company_id.currency_id._convert(amount, account.currency_id, account.company_id, vals.get('date', fields.Date.today()))
|
||||
ok = (
|
||||
(not journal.type_control_ids and not journal.account_control_ids)
|
||||
or account.user_type_id in journal.type_control_ids
|
||||
or account in journal.account_control_ids
|
||||
)
|
||||
if not ok:
|
||||
raise UserError(_('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
|
||||
|
||||
if not ok:
|
||||
raise UserError(_('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
|
||||
# Automatically convert in the account's secondary currency if there is one and
|
||||
# the provided values were not already multi-currency
|
||||
if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id:
|
||||
vals['currency_id'] = account.currency_id.id
|
||||
ctx = {}
|
||||
if 'date' in vals:
|
||||
ctx['date'] = vals['date']
|
||||
vals['amount_currency'] = account.company_id.currency_id._convert(amount, account.currency_id, account.company_id, vals.get('date', fields.Date.today()))
|
||||
|
||||
#Toggle the 'tax_exigible' field to False in case it is not yet given and the tax in 'tax_line_id' or one of
|
||||
#the 'tax_ids' is a cash based tax.
|
||||
taxes = False
|
||||
if vals.get('tax_line_id'):
|
||||
taxes = [{'tax_exigibility': self.env['account.tax'].browse(vals['tax_line_id']).tax_exigibility}]
|
||||
if vals.get('tax_ids'):
|
||||
taxes = self.env['account.move.line'].resolve_2many_commands('tax_ids', vals['tax_ids'])
|
||||
if taxes and any([tax['tax_exigibility'] == 'on_payment' for tax in taxes]) and not vals.get('tax_exigible'):
|
||||
vals['tax_exigible'] = False
|
||||
#Toggle the 'tax_exigible' field to False in case it is not yet given and the tax in 'tax_line_id' or one of
|
||||
#the 'tax_ids' is a cash based tax.
|
||||
taxes = False
|
||||
if vals.get('tax_line_id'):
|
||||
taxes = [{'tax_exigibility': self.env['account.tax'].browse(vals['tax_line_id']).tax_exigibility}]
|
||||
if vals.get('tax_ids'):
|
||||
taxes = self.env['account.move.line'].resolve_2many_commands('tax_ids', vals['tax_ids'])
|
||||
if taxes and any([tax['tax_exigibility'] == 'on_payment' for tax in taxes]) and not vals.get('tax_exigible'):
|
||||
vals['tax_exigible'] = False
|
||||
|
||||
new_line = super(AccountMoveLine, self).create(vals)
|
||||
lines = super(AccountMoveLine, self).create(vals_list)
|
||||
|
||||
if self._context.get('check_move_validity', True):
|
||||
move._post_validate()
|
||||
lines.mapped('move_id')._post_validate()
|
||||
|
||||
return new_line
|
||||
return lines
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
|
||||
@@ -64,15 +64,16 @@ class IrModelFieldsAnonymization(models.Model):
|
||||
return (field.model_id.id, field.id)
|
||||
return (False, False)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# check field state: all should be clear before we can add a new field to anonymize:
|
||||
self._check_write()
|
||||
if vals.get('field_name') and vals.get('model_name'):
|
||||
vals['model_id'], vals['field_id'] = self._get_model_and_field_ids(vals)
|
||||
# check not existing fields:
|
||||
vals['state'] = self._get_global_state() if vals.get('field_id') else 'not_existing'
|
||||
return super(IrModelFieldsAnonymization, self).create(vals)
|
||||
for vals in vals_list:
|
||||
if vals.get('field_name') and vals.get('model_name'):
|
||||
vals['model_id'], vals['field_id'] = self._get_model_and_field_ids(vals)
|
||||
# check not existing fields:
|
||||
vals['state'] = self._get_global_state() if vals.get('field_id') else 'not_existing'
|
||||
return super(IrModelFieldsAnonymization, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -212,16 +212,16 @@ class BaseAutomation(models.Model):
|
||||
|
||||
def make_create():
|
||||
""" Instanciate a create method that processes action rules. """
|
||||
@api.model
|
||||
def create(self, vals, **kw):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list, **kw):
|
||||
# retrieve the action rules to possibly execute
|
||||
actions = self.env['base.automation']._get_actions(self, ['on_create', 'on_create_or_write'])
|
||||
# call original method
|
||||
record = create.origin(self.with_env(actions.env), vals, **kw)
|
||||
records = create.origin(self.with_env(actions.env), vals_list, **kw)
|
||||
# check postconditions, and execute actions on the records that satisfy them
|
||||
for action in actions.with_context(old_values=None):
|
||||
action._process(action._filter_post(record))
|
||||
return record.with_env(self.env)
|
||||
action._process(action._filter_post(records))
|
||||
return records.with_env(self.env)
|
||||
|
||||
return create
|
||||
|
||||
|
||||
@@ -142,14 +142,15 @@ class Attendee(models.Model):
|
||||
""" Make entry on email and availability on change of partner_id field. """
|
||||
self.email = self.partner_id.email
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if not values.get("email") and values.get("common_name"):
|
||||
common_nameval = values.get("common_name").split(':')
|
||||
email = [x for x in common_nameval if '@' in x] # TODO JEM : should be refactored
|
||||
values['email'] = email and email[0] or ''
|
||||
values['common_name'] = values.get("common_name")
|
||||
return super(Attendee, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if not values.get("email") and values.get("common_name"):
|
||||
common_nameval = values.get("common_name").split(':')
|
||||
email = [x for x in common_nameval if '@' in x] # TODO JEM : should be refactored
|
||||
values['email'] = email and email[0] or ''
|
||||
values['common_name'] = values.get("common_name")
|
||||
return super(Attendee, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
@api.returns('self', lambda value: value.id)
|
||||
|
||||
@@ -25,9 +25,9 @@ class DecimalPrecision(models.Model):
|
||||
""" Deprecated, use `clear_caches` instead. """
|
||||
self.clear_caches()
|
||||
|
||||
@api.model
|
||||
def create(self, data):
|
||||
res = super(DecimalPrecision, self).create(data)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
res = super(DecimalPrecision, self).create(vals_list)
|
||||
self.clear_caches()
|
||||
return res
|
||||
|
||||
|
||||
@@ -49,25 +49,26 @@ class FleetVehicleCost(models.Model):
|
||||
})
|
||||
self.odometer_id = odometer
|
||||
|
||||
@api.model
|
||||
def create(self, data):
|
||||
# make sure that the data are consistent with values of parent and contract records given
|
||||
if 'parent_id' in data and data['parent_id']:
|
||||
parent = self.browse(data['parent_id'])
|
||||
data['vehicle_id'] = parent.vehicle_id.id
|
||||
data['date'] = parent.date
|
||||
data['cost_type'] = parent.cost_type
|
||||
if 'contract_id' in data and data['contract_id']:
|
||||
contract = self.env['fleet.vehicle.log.contract'].browse(data['contract_id'])
|
||||
data['vehicle_id'] = contract.vehicle_id.id
|
||||
data['cost_subtype_id'] = contract.cost_subtype_id.id
|
||||
data['cost_type'] = contract.cost_type
|
||||
if 'odometer' in data and not data['odometer']:
|
||||
# if received value for odometer is 0, then remove it from the
|
||||
# data as it would result to the creation of a
|
||||
# odometer log with 0, which is to be avoided
|
||||
del data['odometer']
|
||||
return super(FleetVehicleCost, self).create(data)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for data in vals_list:
|
||||
# make sure that the data are consistent with values of parent and contract records given
|
||||
if 'parent_id' in data and data['parent_id']:
|
||||
parent = self.browse(data['parent_id'])
|
||||
data['vehicle_id'] = parent.vehicle_id.id
|
||||
data['date'] = parent.date
|
||||
data['cost_type'] = parent.cost_type
|
||||
if 'contract_id' in data and data['contract_id']:
|
||||
contract = self.env['fleet.vehicle.log.contract'].browse(data['contract_id'])
|
||||
data['vehicle_id'] = contract.vehicle_id.id
|
||||
data['cost_subtype_id'] = contract.cost_subtype_id.id
|
||||
data['cost_type'] = contract.cost_type
|
||||
if 'odometer' in data and not data['odometer']:
|
||||
# if received value for odometer is 0, then remove it from the
|
||||
# data as it would result to the creation of a
|
||||
# odometer log with 0, which is to be avoided
|
||||
del data['odometer']
|
||||
return super(FleetVehicleCost, self).create(vals_list)
|
||||
|
||||
|
||||
class FleetVehicleLogContract(models.Model):
|
||||
|
||||
@@ -52,10 +52,11 @@ class FleetVehicleModelBrand(models.Model):
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "
|
||||
"Use this field anywhere a small image is required.")
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
tools.image_resize_images(vals)
|
||||
return super(FleetVehicleModelBrand, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
tools.image_resize_images(vals)
|
||||
return super(FleetVehicleModelBrand, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -514,15 +514,16 @@ class HrPayslipLine(models.Model):
|
||||
for line in self:
|
||||
line.total = float(line.quantity) * line.amount * line.rate / 100
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'employee_id' not in values or 'contract_id' not in values:
|
||||
payslip = self.env['hr.payslip'].browse(values.get('slip_id'))
|
||||
values['employee_id'] = values.get('employee_id') or payslip.employee_id.id
|
||||
values['contract_id'] = values.get('contract_id') or payslip.contract_id and payslip.contract_id.id
|
||||
if not values['contract_id']:
|
||||
raise UserError(_('You must set a contract to create a payslip line.'))
|
||||
return super(HrPayslipLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if 'employee_id' not in values or 'contract_id' not in values:
|
||||
payslip = self.env['hr.payslip'].browse(values.get('slip_id'))
|
||||
values['employee_id'] = values.get('employee_id') or payslip.employee_id.id
|
||||
values['contract_id'] = values.get('contract_id') or payslip.contract_id and payslip.contract_id.id
|
||||
if not values['contract_id']:
|
||||
raise UserError(_('You must set a contract to create a payslip line.'))
|
||||
return super(HrPayslipLine, self).create(vals_list)
|
||||
|
||||
|
||||
class HrPayslipWorkedDays(models.Model):
|
||||
|
||||
@@ -46,9 +46,9 @@ class Followers(models.Model):
|
||||
if record.res_id:
|
||||
self.env[record.res_model].invalidate_cache(ids=[record.res_id])
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(Followers, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
res = super(Followers, self).create(vals_list)
|
||||
res._invalidate_documents()
|
||||
return res
|
||||
|
||||
@@ -151,9 +151,11 @@ GROUP BY fol.id%s""" % (
|
||||
new, upd = self._add_default_followers(res_model, res_ids, partner_ids, channel_ids, customer_ids=customer_ids)
|
||||
else:
|
||||
new, upd = self._add_followers(res_model, res_ids, partner_ids, partner_subtypes, channel_ids, channel_subtypes, check_existing=check_existing, existing_policy=existing_policy)
|
||||
for res_id, values_list in new.items():
|
||||
for values in values_list:
|
||||
sudo_self.create(dict(values, res_id=res_id)).id
|
||||
sudo_self.create([
|
||||
dict(values, res_id=res_id)
|
||||
for res_id, values_list in new.items()
|
||||
for values in values_list
|
||||
])
|
||||
for fol_id, values in upd.items():
|
||||
sudo_self.browse(fol_id).write(values)
|
||||
|
||||
|
||||
@@ -238,47 +238,52 @@ class MailThread(models.AbstractModel):
|
||||
# CRUD overrides for automatic subscription and logging
|
||||
# ------------------------------------------------------
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
""" Chatter override :
|
||||
- subscribe uid
|
||||
- subscribe followers of parent
|
||||
- log a creation message
|
||||
"""
|
||||
if self._context.get('tracking_disable'):
|
||||
return super(MailThread, self).create(values)
|
||||
return super(MailThread, self).create(vals_list)
|
||||
|
||||
# subscribe uid unless asked not to
|
||||
if not self._context.get('mail_create_nosubscribe'):
|
||||
message_follower_ids = values.get('message_follower_ids') or []
|
||||
message_follower_ids += [(0, 0, fol_vals) for fol_vals in self.env['mail.followers']._add_default_followers(self._name, [], self.env.user.partner_id.ids, customer_ids=[])[0][0]]
|
||||
values['message_follower_ids'] = message_follower_ids
|
||||
thread = super(MailThread, self).create(values)
|
||||
for values in vals_list:
|
||||
message_follower_ids = values.get('message_follower_ids') or []
|
||||
message_follower_ids += [(0, 0, fol_vals) for fol_vals in self.env['mail.followers']._add_default_followers(self._name, [], self.env.user.partner_id.ids, customer_ids=[])[0][0]]
|
||||
values['message_follower_ids'] = message_follower_ids
|
||||
|
||||
threads = super(MailThread, self).create(vals_list)
|
||||
|
||||
# automatic logging unless asked not to (mainly for various testing purpose)
|
||||
if not self._context.get('mail_create_nolog'):
|
||||
doc_name = self.env['ir.model']._get(self._name).name
|
||||
thread._message_log(body=_('%s created') % doc_name)
|
||||
for thread in threads:
|
||||
thread._message_log(body=_('%s created') % doc_name)
|
||||
|
||||
# auto_subscribe: take values and defaults into account
|
||||
create_values = dict(values)
|
||||
for key, val in self._context.items():
|
||||
if key.startswith('default_') and key[8:] not in create_values:
|
||||
create_values[key[8:]] = val
|
||||
thread._message_auto_subscribe(create_values)
|
||||
for thread, values in pycompat.izip(threads, vals_list):
|
||||
create_values = dict(values)
|
||||
for key, val in self._context.items():
|
||||
if key.startswith('default_') and key[8:] not in create_values:
|
||||
create_values[key[8:]] = val
|
||||
thread._message_auto_subscribe(create_values)
|
||||
|
||||
# track values
|
||||
if not self._context.get('mail_notrack'):
|
||||
if 'lang' not in self._context:
|
||||
track_thread = thread.with_context(lang=self.env.user.lang)
|
||||
track_threads = threads.with_context(lang=self.env.user.lang)
|
||||
else:
|
||||
track_thread = thread
|
||||
tracked_fields = track_thread._get_tracked_fields(list(values))
|
||||
if tracked_fields:
|
||||
initial_values = {thread.id: dict.fromkeys(tracked_fields, False)}
|
||||
track_thread.message_track(tracked_fields, initial_values)
|
||||
track_threads = threads
|
||||
for thread, values in pycompat.izip(track_threads, vals_list):
|
||||
tracked_fields = thread._get_tracked_fields(list(values))
|
||||
if tracked_fields:
|
||||
initial_values = {thread.id: dict.fromkeys(tracked_fields, False)}
|
||||
thread.message_track(tracked_fields, initial_values)
|
||||
|
||||
return thread
|
||||
return threads
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -162,11 +162,12 @@ class MassMailingContact(models.Model):
|
||||
country_id = fields.Many2one('res.country', string='Country')
|
||||
tag_ids = fields.Many2many('res.partner.category', string='Tags')
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'opt_out' in vals:
|
||||
vals['unsubscription_date'] = vals['opt_out'] and fields.Datetime.now()
|
||||
return super(MassMailingContact, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if 'opt_out' in vals:
|
||||
vals['unsubscription_date'] = vals['opt_out'] and fields.Datetime.now()
|
||||
return super(MassMailingContact, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -274,11 +274,12 @@ class MrpBomLine(models.Model):
|
||||
if self.product_id:
|
||||
self.product_uom_id = self.product_id.uom_id.id
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'product_id' in values and 'product_uom_id' not in values:
|
||||
values['product_uom_id'] = self.env['product.product'].browse(values['product_id']).uom_id.id
|
||||
return super(MrpBomLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if 'product_id' in values and 'product_uom_id' not in values:
|
||||
values['product_uom_id'] = self.env['product.product'].browse(values['product_id']).uom_id.id
|
||||
return super(MrpBomLine, self).create(vals_list)
|
||||
|
||||
def _skip_bom_line(self, product):
|
||||
""" Control if a BoM line should be produce, can be inherited for add
|
||||
|
||||
@@ -507,13 +507,14 @@ class PaymentIcon(models.Model):
|
||||
image_payment_form = fields.Binary(
|
||||
"Image displayed on the payment form", attachment=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'image' in vals:
|
||||
image = ustr(vals['image'] or '').encode('utf-8')
|
||||
vals['image_payment_form'] = image_resize_image(image, size=(45,30))
|
||||
vals['image'] = image_resize_image(image, size=(64,64))
|
||||
return super(PaymentIcon, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if 'image' in vals:
|
||||
image = ustr(vals['image'] or '').encode('utf-8')
|
||||
vals['image_payment_form'] = image_resize_image(image, size=(45,30))
|
||||
vals['image'] = image_resize_image(image, size=(64,64))
|
||||
return super(PaymentIcon, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -298,13 +298,14 @@ class ProductProduct(models.Model):
|
||||
if self.uom_id and self.uom_po_id and self.uom_id.category_id != self.uom_po_id.category_id:
|
||||
self.uom_po_id = self.uom_id
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
product = super(ProductProduct, self.with_context(create_product_product=True)).create(vals)
|
||||
# When a unique variant is created from tmpl then the standard price is set by _set_standard_price
|
||||
if not (self.env.context.get('create_from_tmpl') and len(product.product_tmpl_id.product_variant_ids) == 1):
|
||||
product._set_standard_price(vals.get('standard_price') or 0.0)
|
||||
return product
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
products = super(ProductProduct, self.with_context(create_product_product=True)).create(vals_list)
|
||||
for product, vals in pycompat.izip(products, vals_list):
|
||||
# When a unique variant is created from tmpl then the standard price is set by _set_standard_price
|
||||
if not (self.env.context.get('create_from_tmpl') and len(product.product_tmpl_id.product_variant_ids) == 1):
|
||||
product._set_standard_price(vals.get('standard_price') or 0.0)
|
||||
return products
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -309,30 +309,33 @@ class ProductTemplate(models.Model):
|
||||
if self.uom_id:
|
||||
self.uom_po_id = self.uom_id.id
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
''' Store the initial standard price in order to be able to retrieve the cost of a product template for a given date'''
|
||||
# TDE FIXME: context brol
|
||||
tools.image_resize_images(vals)
|
||||
template = super(ProductTemplate, self).create(vals)
|
||||
for vals in vals_list:
|
||||
tools.image_resize_images(vals)
|
||||
templates = super(ProductTemplate, self).create(vals_list)
|
||||
if "create_product_product" not in self._context:
|
||||
template.with_context(create_from_tmpl=True).create_variant_ids()
|
||||
templates.with_context(create_from_tmpl=True).create_variant_ids()
|
||||
|
||||
# This is needed to set given values to first variant after creation
|
||||
related_vals = {}
|
||||
if vals.get('barcode'):
|
||||
related_vals['barcode'] = vals['barcode']
|
||||
if vals.get('default_code'):
|
||||
related_vals['default_code'] = vals['default_code']
|
||||
if vals.get('standard_price'):
|
||||
related_vals['standard_price'] = vals['standard_price']
|
||||
if vals.get('volume'):
|
||||
related_vals['volume'] = vals['volume']
|
||||
if vals.get('weight'):
|
||||
related_vals['weight'] = vals['weight']
|
||||
if related_vals:
|
||||
template.write(related_vals)
|
||||
return template
|
||||
for template, vals in pycompat.izip(templates, vals_list):
|
||||
related_vals = {}
|
||||
if vals.get('barcode'):
|
||||
related_vals['barcode'] = vals['barcode']
|
||||
if vals.get('default_code'):
|
||||
related_vals['default_code'] = vals['default_code']
|
||||
if vals.get('standard_price'):
|
||||
related_vals['standard_price'] = vals['standard_price']
|
||||
if vals.get('volume'):
|
||||
related_vals['volume'] = vals['volume']
|
||||
if vals.get('weight'):
|
||||
related_vals['weight'] = vals['weight']
|
||||
if related_vals:
|
||||
template.write(related_vals)
|
||||
|
||||
return templates
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
@@ -425,6 +428,11 @@ class ProductTemplate(models.Model):
|
||||
def create_variant_ids(self):
|
||||
Product = self.env["product.product"]
|
||||
AttributeValues = self.env['product.attribute.value']
|
||||
|
||||
variants_to_create = []
|
||||
variants_to_activate = []
|
||||
variants_to_unlink = []
|
||||
|
||||
for tmpl_id in self.with_context(active_test=False):
|
||||
# adding an attribute with only one value should not recreate product
|
||||
# write this attribute on every product to make sure we don't lose them
|
||||
@@ -443,39 +451,37 @@ class ProductTemplate(models.Model):
|
||||
existing_variants = {frozenset(variant.attribute_value_ids.filtered(lambda r: r.attribute_id.create_variant).ids) for variant in tmpl_id.product_variant_ids}
|
||||
# -> for each value set, create a recordset of values to create a
|
||||
# variant for if the value set isn't already a variant
|
||||
to_create_variants = [
|
||||
value_ids
|
||||
for value_ids in variant_matrix
|
||||
if set(value_ids.ids) not in existing_variants
|
||||
]
|
||||
for value_ids in variant_matrix:
|
||||
if set(value_ids.ids) not in existing_variants:
|
||||
variants_to_create.append({
|
||||
'product_tmpl_id': tmpl_id.id,
|
||||
'attribute_value_ids': [(6, 0, value_ids.ids)]
|
||||
})
|
||||
|
||||
# check product
|
||||
variants_to_activate = self.env['product.product']
|
||||
variants_to_unlink = self.env['product.product']
|
||||
for product_id in tmpl_id.product_variant_ids:
|
||||
if not product_id.active and product_id.attribute_value_ids.filtered(lambda r: r.attribute_id.create_variant) in variant_matrix:
|
||||
variants_to_activate |= product_id
|
||||
variants_to_activate.append(product_id)
|
||||
elif product_id.attribute_value_ids.filtered(lambda r: r.attribute_id.create_variant) not in variant_matrix:
|
||||
variants_to_unlink |= product_id
|
||||
if variants_to_activate:
|
||||
variants_to_activate.write({'active': True})
|
||||
variants_to_unlink.append(product_id)
|
||||
|
||||
# create new product
|
||||
for variant_ids in to_create_variants:
|
||||
new_variant = Product.create({
|
||||
'product_tmpl_id': tmpl_id.id,
|
||||
'attribute_value_ids': [(6, 0, variant_ids.ids)]
|
||||
})
|
||||
if variants_to_activate:
|
||||
Product.concat(*variants_to_activate).write({'active': True})
|
||||
|
||||
# create new products
|
||||
if variants_to_create:
|
||||
Product.create(variants_to_create)
|
||||
|
||||
# unlink or inactive product
|
||||
for variant in variants_to_unlink:
|
||||
try:
|
||||
with self._cr.savepoint(), tools.mute_logger('odoo.sql_db'):
|
||||
variant.unlink()
|
||||
# We catch all kind of exception to be sure that the operation doesn't fail.
|
||||
except (psycopg2.Error, except_orm):
|
||||
variant.write({'active': False})
|
||||
pass
|
||||
|
||||
# unlink or inactive product
|
||||
for variant in variants_to_unlink:
|
||||
try:
|
||||
with self._cr.savepoint(), tools.mute_logger('odoo.sql_db'):
|
||||
variant.unlink()
|
||||
# We catch all kind of exception to be sure that the operation doesn't fail.
|
||||
except (psycopg2.Error, except_orm):
|
||||
variant.write({'active': False})
|
||||
pass
|
||||
return True
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -172,12 +172,11 @@ class SaleOrderLine(models.Model):
|
||||
qty -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
|
||||
line.qty_delivered = qty
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
line = super(SaleOrderLine, self).create(values)
|
||||
if line.state == 'sale':
|
||||
line._action_launch_stock_rule()
|
||||
return line
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
lines = super(SaleOrderLine, self).create(vals_list)
|
||||
lines.filtered(lambda line: line.state == 'sale')._action_launch_stock_rule()
|
||||
return lines
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -164,18 +164,19 @@ class SaleOrderLine(models.Model):
|
||||
else:
|
||||
super(SaleOrderLine, line)._compute_product_updatable()
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
line = super(SaleOrderLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
lines = super(SaleOrderLine, self).create(vals_list)
|
||||
# Do not generate task/project when expense SO line, but allow
|
||||
# generate task with hours=0.
|
||||
if line.state == 'sale' and not line.is_expense:
|
||||
line.sudo()._timesheet_service_generation()
|
||||
# if the SO line created a task, post a message on the order
|
||||
if line.task_id:
|
||||
msg_body = _("Task Created (%s): <a href=# data-oe-model=project.task data-oe-id=%d>%s</a>") % (line.product_id.name, line.task_id.id, line.task_id.name)
|
||||
line.order_id.message_post(body=msg_body)
|
||||
return line
|
||||
for line in lines:
|
||||
if line.state == 'sale' and not line.is_expense:
|
||||
line.sudo()._timesheet_service_generation()
|
||||
# if the SO line created a task, post a message on the order
|
||||
if line.task_id:
|
||||
msg_body = _("Task Created (%s): <a href=# data-oe-model=project.task data-oe-id=%d>%s</a>") % (line.product_id.name, line.task_id.id, line.task_id.name)
|
||||
line.order_id.message_post(body=msg_body)
|
||||
return lines
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -380,11 +380,12 @@ class InventoryLine(models.Model):
|
||||
self._compute_theoretical_qty()
|
||||
self.product_qty = self.theoretical_qty
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'product_id' in values and 'product_uom_id' not in values:
|
||||
values['product_uom_id'] = self.env['product.product'].browse(values['product_id']).uom_id.id
|
||||
res = super(InventoryLine, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if 'product_id' in values and 'product_uom_id' not in values:
|
||||
values['product_uom_id'] = self.env['product.product'].browse(values['product_id']).uom_id.id
|
||||
res = super(InventoryLine, self).create(vals_list)
|
||||
res._check_no_duplicate_line()
|
||||
return res
|
||||
|
||||
@@ -456,7 +457,7 @@ class InventoryLine(models.Model):
|
||||
}
|
||||
|
||||
def _generate_moves(self):
|
||||
moves = self.env['stock.move']
|
||||
vals_list = []
|
||||
for line in self:
|
||||
if float_utils.float_compare(line.theoretical_qty, line.product_qty, precision_rounding=line.product_id.uom_id.rounding) == 0:
|
||||
continue
|
||||
@@ -465,5 +466,5 @@ class InventoryLine(models.Model):
|
||||
vals = line._get_move_values(abs(diff), line.product_id.property_stock_inventory.id, line.location_id.id, False)
|
||||
else:
|
||||
vals = line._get_move_values(abs(diff), line.location_id.id, line.product_id.property_stock_inventory.id, True)
|
||||
moves |= self.env['stock.move'].create(vals)
|
||||
return moves
|
||||
vals_list.append(vals)
|
||||
return self.env['stock.move'].create(vals_list)
|
||||
|
||||
@@ -376,16 +376,18 @@ class StockMove(models.Model):
|
||||
move.location_id.name, move.location_dest_id.name)))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
# TDE CLEANME: why doing this tracking on picking here ? seems weird
|
||||
perform_tracking = not self.env.context.get('mail_notrack') and vals.get('picking_id')
|
||||
if perform_tracking:
|
||||
picking = self.env['stock.picking'].browse(vals['picking_id'])
|
||||
initial_values = {picking.id: {'state': picking.state}}
|
||||
vals['ordered_qty'] = vals.get('product_uom_qty')
|
||||
res = super(StockMove, self).create(vals)
|
||||
if perform_tracking:
|
||||
tracking = []
|
||||
for vals in vals_list:
|
||||
vals['ordered_qty'] = vals.get('product_uom_qty')
|
||||
if not self.env.context.get('mail_notrack') and vals.get('picking_id'):
|
||||
picking = self.env['stock.picking'].browse(vals['picking_id'])
|
||||
initial_values = {picking.id: {'state': picking.state}}
|
||||
tracking.append((picking, initial_values))
|
||||
res = super(StockMove, self).create(vals_list)
|
||||
for picking, initial_values in tracking:
|
||||
picking.message_track(picking.fields_get(['state']), initial_values)
|
||||
return res
|
||||
|
||||
|
||||
@@ -153,49 +153,53 @@ class StockMoveLine(models.Model):
|
||||
lines |= picking_id.move_line_ids.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name))
|
||||
return lines
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
vals['ordered_qty'] = vals.get('product_uom_qty')
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
vals['ordered_qty'] = vals.get('product_uom_qty')
|
||||
|
||||
# If the move line is directly create on the picking view.
|
||||
# If this picking is already done we should generate an
|
||||
# associated done move.
|
||||
if 'picking_id' in vals and not vals.get('move_id'):
|
||||
picking = self.env['stock.picking'].browse(vals['picking_id'])
|
||||
if picking.state == 'done':
|
||||
product = self.env['product.product'].browse(vals['product_id'])
|
||||
new_move = self.env['stock.move'].create({
|
||||
'name': _('New Move:') + product.display_name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 'qty_done' in vals and vals['qty_done'] or 0,
|
||||
'product_uom': vals['product_uom_id'],
|
||||
'location_id': 'location_id' in vals and vals['location_id'] or picking.location_id.id,
|
||||
'location_dest_id': 'location_dest_id' in vals and vals['location_dest_id'] or picking.location_dest_id.id,
|
||||
'state': 'done',
|
||||
'additional': True,
|
||||
'picking_id': picking.id,
|
||||
})
|
||||
vals['move_id'] = new_move.id
|
||||
# If the move line is directly create on the picking view.
|
||||
# If this picking is already done we should generate an
|
||||
# associated done move.
|
||||
if 'picking_id' in vals and not vals.get('move_id'):
|
||||
picking = self.env['stock.picking'].browse(vals['picking_id'])
|
||||
if picking.state == 'done':
|
||||
product = self.env['product.product'].browse(vals['product_id'])
|
||||
new_move = self.env['stock.move'].create({
|
||||
'name': _('New Move:') + product.display_name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 'qty_done' in vals and vals['qty_done'] or 0,
|
||||
'product_uom': vals['product_uom_id'],
|
||||
'location_id': 'location_id' in vals and vals['location_id'] or picking.location_id.id,
|
||||
'location_dest_id': 'location_dest_id' in vals and vals['location_dest_id'] or picking.location_dest_id.id,
|
||||
'state': 'done',
|
||||
'additional': True,
|
||||
'picking_id': picking.id,
|
||||
})
|
||||
vals['move_id'] = new_move.id
|
||||
|
||||
ml = super(StockMoveLine, self).create(vals)
|
||||
if ml.state == 'done':
|
||||
if ml.product_id.type == 'product':
|
||||
Quant = self.env['stock.quant']
|
||||
quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id,rounding_method='HALF-UP')
|
||||
in_date = None
|
||||
available_qty, in_date = Quant._update_available_quantity(ml.product_id, ml.location_id, -quantity, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
if available_qty < 0 and ml.lot_id:
|
||||
# see if we can compensate the negative quants with some untracked quants
|
||||
untracked_qty = Quant._get_available_quantity(ml.product_id, ml.location_id, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
|
||||
if untracked_qty:
|
||||
taken_from_untracked_qty = min(untracked_qty, abs(quantity))
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_id, -taken_from_untracked_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_id, taken_from_untracked_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_dest_id, quantity, lot_id=ml.lot_id, package_id=ml.result_package_id, owner_id=ml.owner_id, in_date=in_date)
|
||||
next_moves = ml.move_id.move_dest_ids.filtered(lambda move: move.state not in ('done', 'cancel'))
|
||||
next_moves._do_unreserve()
|
||||
next_moves._action_assign()
|
||||
return ml
|
||||
mls = super(StockMoveLine, self).create(vals_list)
|
||||
|
||||
for ml in mls:
|
||||
if ml.state == 'done':
|
||||
if ml.product_id.type == 'product':
|
||||
Quant = self.env['stock.quant']
|
||||
quantity = ml.product_uom_id._compute_quantity(ml.qty_done, ml.move_id.product_id.uom_id,rounding_method='HALF-UP')
|
||||
in_date = None
|
||||
available_qty, in_date = Quant._update_available_quantity(ml.product_id, ml.location_id, -quantity, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
if available_qty < 0 and ml.lot_id:
|
||||
# see if we can compensate the negative quants with some untracked quants
|
||||
untracked_qty = Quant._get_available_quantity(ml.product_id, ml.location_id, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
|
||||
if untracked_qty:
|
||||
taken_from_untracked_qty = min(untracked_qty, abs(quantity))
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_id, -taken_from_untracked_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_id, taken_from_untracked_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id)
|
||||
Quant._update_available_quantity(ml.product_id, ml.location_dest_id, quantity, lot_id=ml.lot_id, package_id=ml.result_package_id, owner_id=ml.owner_id, in_date=in_date)
|
||||
next_moves = ml.move_id.move_dest_ids.filtered(lambda move: move.state not in ('done', 'cancel'))
|
||||
next_moves._do_unreserve()
|
||||
next_moves._action_assign()
|
||||
|
||||
return mls
|
||||
|
||||
def write(self, vals):
|
||||
""" Through the interface, we allow users to change the charateristics of a move line. If a
|
||||
|
||||
@@ -28,14 +28,14 @@ class ProductionLot(models.Model):
|
||||
('name_ref_uniq', 'unique (name, product_id)', 'The combination of serial number and product must be unique !'),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
active_picking_id = self.env.context.get('active_picking_id', False)
|
||||
if active_picking_id:
|
||||
picking_id = self.env['stock.picking'].browse(active_picking_id)
|
||||
if picking_id and not picking_id.picking_type_id.use_create_lots:
|
||||
raise UserError(_("You are not allowed to create a lot for this operation type."))
|
||||
return super(ProductionLot, self).create(vals)
|
||||
return super(ProductionLot, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -62,15 +62,16 @@ class StockLocation(models.Model):
|
||||
class StockMoveLine(models.Model):
|
||||
_inherit = 'stock.move.line'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(StockMoveLine, self).create(vals)
|
||||
move = res.move_id
|
||||
if move.state == 'done':
|
||||
correction_value = move._run_valuation(res.qty_done)
|
||||
if move.product_id.valuation == 'real_time' and (move._is_in() or move._is_out()):
|
||||
move.with_context(force_valuation_amount=correction_value)._account_entry_move()
|
||||
return res
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
lines = super(StockMoveLine, self).create(vals_list)
|
||||
for line in lines:
|
||||
move = line.move_id
|
||||
if move.state == 'done':
|
||||
correction_value = move._run_valuation(line.qty_done)
|
||||
if move.product_id.valuation == 'real_time' and (move._is_in() or move._is_out()):
|
||||
move.with_context(force_valuation_amount=correction_value)._account_entry_move()
|
||||
return lines
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -823,12 +823,13 @@ class SurveyUserInputLine(models.Model):
|
||||
mark = label.quizz_mark if label.exists() else 0.0
|
||||
return mark
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
value_suggested = vals.get('value_suggested')
|
||||
if value_suggested:
|
||||
vals.update({'quizz_mark': self._get_mark(value_suggested)})
|
||||
return super(SurveyUserInputLine, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
value_suggested = vals.get('value_suggested')
|
||||
if value_suggested:
|
||||
vals.update({'quizz_mark': self._get_mark(value_suggested)})
|
||||
return super(SurveyUserInputLine, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -87,12 +87,13 @@ class UoM(models.Model):
|
||||
if uom_data['uom_count'] > 1:
|
||||
raise ValidationError(_("UoM category %s should only have one reference unit of measure.") % (self.env['uom.category'].browse(uom_data['category_id']).name,))
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'factor_inv' in values:
|
||||
factor_inv = values.pop('factor_inv')
|
||||
values['factor'] = factor_inv and (1.0 / factor_inv) or 0.0
|
||||
return super(UoM, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if 'factor_inv' in values:
|
||||
factor_inv = values.pop('factor_inv')
|
||||
values['factor'] = factor_inv and (1.0 / factor_inv) or 0.0
|
||||
return super(UoM, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -43,9 +43,9 @@ class IrActions(models.Model):
|
||||
for record in self:
|
||||
record.xml_id = res.get(record.id)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(IrActions, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
res = super(IrActions, self).create(vals_list)
|
||||
# self.get_bindings() depends on action records
|
||||
self.clear_caches()
|
||||
return res
|
||||
@@ -220,10 +220,10 @@ class IrActionsActWindow(models.Model):
|
||||
record = self.env.ref("%s.%s" % (module, xml_id))
|
||||
return record.read()[0]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.clear_caches()
|
||||
return super(IrActionsActWindow, self).create(vals)
|
||||
return super(IrActionsActWindow, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
@@ -614,12 +614,13 @@ class IrActionsTodo(models.Model):
|
||||
state = fields.Selection([('open', 'To Do'), ('done', 'Done')], string='Status', default='open', required=True)
|
||||
name = fields.Char()
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
todo = super(IrActionsTodo, self).create(vals)
|
||||
if todo.state == "open":
|
||||
self.ensure_one_open_todo()
|
||||
return todo
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
todos = super(IrActionsTodo, self).create(vals_list)
|
||||
for todo in todos:
|
||||
if todo.state == "open":
|
||||
self.ensure_one_open_todo()
|
||||
return todos
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -430,14 +430,15 @@ class IrAttachment(models.Model):
|
||||
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
# remove computed field depending of datas
|
||||
for field in ('file_size', 'checksum'):
|
||||
values.pop(field, False)
|
||||
values = self._check_contents(values)
|
||||
self.browse().check('write', values=values)
|
||||
return super(IrAttachment, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
# remove computed field depending of datas
|
||||
for field in ('file_size', 'checksum'):
|
||||
values.pop(field, False)
|
||||
values = self._check_contents(values)
|
||||
self.browse().check('write', values=values)
|
||||
return super(IrAttachment, self).create(vals_list)
|
||||
|
||||
@api.one
|
||||
def generate_access_token(self):
|
||||
|
||||
@@ -89,10 +89,10 @@ class IrConfigParameter(models.Model):
|
||||
self.create({'key': key, 'value': value})
|
||||
return False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.clear_caches()
|
||||
return super(IrConfigParameter, self).create(vals)
|
||||
return super(IrConfigParameter, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -21,10 +21,10 @@ class IrDefault(models.Model):
|
||||
condition = fields.Char('Condition', help="If set, applies the default upon condition.")
|
||||
json_value = fields.Char('Default Value (JSON format)', required=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.clear_caches()
|
||||
return super(IrDefault, self).create(vals)
|
||||
return super(IrDefault, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -1238,10 +1238,10 @@ class IrModelAccess(models.Model):
|
||||
#
|
||||
# Check rights on actions
|
||||
#
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.call_cache_clearing_methods()
|
||||
return super(IrModelAccess, self).create(values)
|
||||
return super(IrModelAccess, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -89,9 +89,10 @@ class Property(models.Model):
|
||||
def write(self, values):
|
||||
return super(Property, self).write(self._update_values(values))
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
return super(Property, self).create(self._update_values(values))
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
vals_list = [self._update_values(vals) for vals in vals_list]
|
||||
return super(Property, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def get_by_record(self):
|
||||
@@ -221,10 +222,11 @@ class Property(models.Model):
|
||||
prop.write({'value': value})
|
||||
|
||||
# create new properties for records that do not have one yet
|
||||
vals_list = []
|
||||
for ref, id in refs.items():
|
||||
value = clean(values[id])
|
||||
if value != default_value:
|
||||
self.create({
|
||||
vals_list.append({
|
||||
'fields_id': field_id,
|
||||
'company_id': company_id,
|
||||
'res_id': ref,
|
||||
@@ -232,6 +234,7 @@ class Property(models.Model):
|
||||
'value': value,
|
||||
'type': self.env[model]._fields[name].type,
|
||||
})
|
||||
self.create(vals_list)
|
||||
|
||||
@api.model
|
||||
def search_multi(self, name, model, operator, value):
|
||||
|
||||
@@ -121,9 +121,9 @@ class IrRule(models.Model):
|
||||
self.clear_caches()
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
res = super(IrRule, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
res = super(IrRule, self).create(vals_list)
|
||||
self.clear_caches()
|
||||
return res
|
||||
|
||||
|
||||
@@ -323,8 +323,7 @@ class IrTranslation(models.Model):
|
||||
existing_ids = [row[0] for row in self._cr.fetchall()]
|
||||
|
||||
# create missing translations
|
||||
for res_id in set(ids) - set(existing_ids):
|
||||
self.create({
|
||||
self.create([{
|
||||
'lang': lang,
|
||||
'type': tt,
|
||||
'name': name,
|
||||
@@ -332,7 +331,9 @@ class IrTranslation(models.Model):
|
||||
'value': value,
|
||||
'src': src,
|
||||
'state': 'translated',
|
||||
})
|
||||
}
|
||||
for res_id in set(ids) - set(existing_ids)
|
||||
])
|
||||
return len(ids)
|
||||
|
||||
@api.model
|
||||
@@ -557,12 +558,12 @@ class IrTranslation(models.Model):
|
||||
if value2 != value0:
|
||||
raise ValidationError(_("Translation is not valid:\n%s") % val)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
record = super(IrTranslation, self.sudo()).create(vals).with_env(self.env)
|
||||
record.check('create')
|
||||
record._modified()
|
||||
return record
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
records = super(IrTranslation, self.sudo()).create(vals_list).with_env(self.env)
|
||||
records.check('create')
|
||||
records._modified()
|
||||
return records
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -142,12 +142,13 @@ class IrUiMenu(models.Model):
|
||||
def name_get(self):
|
||||
return [(menu.id, menu._get_full_name()) for menu in self]
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.clear_caches()
|
||||
if 'web_icon' in values:
|
||||
values['web_icon_data'] = self._compute_web_icon_data(values.get('web_icon'))
|
||||
return super(IrUiMenu, self).create(values)
|
||||
for values in vals_list:
|
||||
if 'web_icon' in values:
|
||||
values['web_icon_data'] = self._compute_web_icon_data(values.get('web_icon'))
|
||||
return super(IrUiMenu, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
@@ -377,27 +377,28 @@ actual arch.
|
||||
values.setdefault('mode', 'extension' if values['inherit_id'] else 'primary')
|
||||
return values
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if not values.get('type'):
|
||||
if values.get('inherit_id'):
|
||||
values['type'] = self.browse(values['inherit_id']).type
|
||||
else:
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if not values.get('type'):
|
||||
if values.get('inherit_id'):
|
||||
values['type'] = self.browse(values['inherit_id']).type
|
||||
else:
|
||||
|
||||
try:
|
||||
if not values.get('arch') and not values.get('arch_base'):
|
||||
raise ValidationError(_('Missing view architecture.'))
|
||||
values['type'] = etree.fromstring(values.get('arch') or values.get('arch_base')).tag
|
||||
except LxmlError:
|
||||
# don't raise here, the constraint that runs `self._check_xml` will
|
||||
# do the job properly.
|
||||
pass
|
||||
|
||||
if not values.get('name'):
|
||||
values['name'] = "%s %s" % (values.get('model'), values['type'])
|
||||
try:
|
||||
if not values.get('arch') and not values.get('arch_base'):
|
||||
raise ValidationError(_('Missing view architecture.'))
|
||||
values['type'] = etree.fromstring(values.get('arch') or values.get('arch_base')).tag
|
||||
except LxmlError:
|
||||
# don't raise here, the constraint that runs `self._check_xml` will
|
||||
# do the job properly.
|
||||
pass
|
||||
if not values.get('name'):
|
||||
values['name'] = "%s %s" % (values.get('model'), values['type'])
|
||||
values.update(self._compute_defaults(values))
|
||||
|
||||
self.clear_caches()
|
||||
return super(View, self).create(self._compute_defaults(values))
|
||||
return super(View, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -75,11 +75,12 @@ class Country(models.Model):
|
||||
|
||||
name_search = location_name_search
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('code'):
|
||||
vals['code'] = vals['code'].upper()
|
||||
return super(Country, self).create(vals)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('code'):
|
||||
vals['code'] = vals['code'].upper()
|
||||
return super(Country, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -213,10 +213,10 @@ class Lang(models.Model):
|
||||
langs = self.with_context(active_test=True).search([])
|
||||
return sorted([(lang.code, lang.name) for lang in langs], key=itemgetter(1))
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
self.clear_caches()
|
||||
return super(Lang, self).create(vals)
|
||||
return super(Lang, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
|
||||
@@ -17,6 +17,7 @@ from odoo import api, fields, models, tools, SUPERUSER_ID, _
|
||||
from odoo.modules import get_module_resource
|
||||
from odoo.osv.expression import get_unaccent_wrapper
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tools import pycompat
|
||||
|
||||
# Global variables used for the warning fields declared on the res.partner
|
||||
# in the following modules : sale, purchase, account, stock
|
||||
@@ -535,21 +536,23 @@ class Partner(models.Model):
|
||||
partner._fields_sync(vals)
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('website'):
|
||||
vals['website'] = self._clean_website(vals['website'])
|
||||
if vals.get('parent_id'):
|
||||
vals['company_name'] = False
|
||||
# compute default image in create, because computing gravatar in the onchange
|
||||
# cannot be easily performed if default images are in the way
|
||||
if not vals.get('image'):
|
||||
vals['image'] = self._get_default_image(vals.get('type'), vals.get('is_company'), vals.get('parent_id'))
|
||||
tools.image_resize_images(vals, sizes={'image': (1024, None)})
|
||||
partner = super(Partner, self).create(vals)
|
||||
partner._fields_sync(vals)
|
||||
partner._handle_first_contact_creation()
|
||||
return partner
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('website'):
|
||||
vals['website'] = self._clean_website(vals['website'])
|
||||
if vals.get('parent_id'):
|
||||
vals['company_name'] = False
|
||||
# compute default image in create, because computing gravatar in the onchange
|
||||
# cannot be easily performed if default images are in the way
|
||||
if not vals.get('image'):
|
||||
vals['image'] = self._get_default_image(vals.get('type'), vals.get('is_company'), vals.get('parent_id'))
|
||||
tools.image_resize_images(vals, sizes={'image': (1024, None)})
|
||||
partners = super(Partner, self).create(vals_list)
|
||||
for partner, vals in pycompat.izip(partners, vals_list):
|
||||
partner._fields_sync(vals)
|
||||
partner._handle_first_contact_creation()
|
||||
return partners
|
||||
|
||||
@api.multi
|
||||
def create_company(self):
|
||||
|
||||
@@ -404,14 +404,14 @@ class Users(models.Model):
|
||||
return super(Users, self)._search(args, offset=offset, limit=limit, order=order, count=count,
|
||||
access_rights_uid=access_rights_uid)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# import pudb; pudb.set_trace()
|
||||
user = super(Users, self).create(vals)
|
||||
user.partner_id.active = user.active
|
||||
if user.partner_id.company_id:
|
||||
user.partner_id.write({'company_id': user.company_id.id})
|
||||
return user
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
users = super(Users, self).create(vals_list)
|
||||
for user in users:
|
||||
user.partner_id.active = user.active
|
||||
if user.partner_id.company_id:
|
||||
user.partner_id.write({'company_id': user.company_id.id})
|
||||
return users
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
@@ -842,14 +842,15 @@ class GroupsImplied(models.Model):
|
||||
for g in self:
|
||||
g.trans_implied_ids = g.implied_ids | g.mapped('implied_ids.trans_implied_ids')
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
user_ids = values.pop('users', None)
|
||||
group = super(GroupsImplied, self).create(values)
|
||||
if user_ids:
|
||||
# delegate addition of users to add implied groups
|
||||
group.write({'users': user_ids})
|
||||
return group
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
user_ids_list = [vals.pop('users', None) for vals in vals_list]
|
||||
groups = super(GroupsImplied, self).create(vals_list)
|
||||
for group, user_ids in pycompat.izip(groups, user_ids_list):
|
||||
if user_ids:
|
||||
# delegate addition of users to add implied groups
|
||||
group.write({'users': user_ids})
|
||||
return groups
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
@@ -866,14 +867,15 @@ class GroupsImplied(models.Model):
|
||||
class UsersImplied(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'groups_id' in values:
|
||||
# complete 'groups_id' with implied groups
|
||||
user = self.new(values)
|
||||
gs = user.groups_id | user.groups_id.mapped('trans_implied_ids')
|
||||
values['groups_id'] = type(self).groups_id.convert_to_write(gs, user.groups_id)
|
||||
return super(UsersImplied, self).create(values)
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for values in vals_list:
|
||||
if 'groups_id' in values:
|
||||
# complete 'groups_id' with implied groups
|
||||
user = self.new(values)
|
||||
gs = user.groups_id | user.groups_id.mapped('trans_implied_ids')
|
||||
values['groups_id'] = type(self).groups_id.convert_to_write(gs, user.groups_id)
|
||||
return super(UsersImplied, self).create(vals_list)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
|
||||
Reference in New Issue
Block a user