def validate_iban(iban): iban = normalize_iban(iban) if not iban: raise ValidationError(_("No IBAN !")) country_code = iban[:2].lower() if country_code not in _map_iban_template: raise ValidationError( _("The IBAN is invalid, it should begin with the country code")) iban_template = _map_iban_template[country_code] if len(iban) != len(iban_template.replace(' ', '')): raise ValidationError( _("The IBAN does not seem to be correct. You should have entered something like this %s\n" "Where B = National bank code, S = Branch code, C = Account No, k = Check digit" ) % iban_template) check_chars = iban[4:] + iban[:4] digits = int(''.join( str(int(char, 36)) for char in check_chars)) # BASE 36: 0..9,A..Z -> 0..35 if digits % 97 != 1: raise ValidationError( _("This IBAN does not pass the validation check, please verify it." ))
def _check_model(self): for action in self: if action.res_model not in self.env: raise ValidationError( _('Invalid model name %r in action definition.') % action.res_model) if action.src_model and action.src_model not in self.env: raise ValidationError( _('Invalid model name %r in action definition.') % action.src_model)
def check_complete_move(self, move, theorical_lines): for aml in move.line_ids: line = (aml.name, round(aml.debit, 2), round(aml.credit, 2)) if line in theorical_lines: theorical_lines.remove(line) else: raise ValidationError('Unexpected journal item. (label: %s, debit: %s, credit: %s)' % (aml.name, round(aml.debit, 2), round(aml.credit, 2))) if theorical_lines: raise ValidationError('Remaining theorical line (not found). %s)' % ([(aml[0], aml[1], aml[2]) for aml in theorical_lines])) return True
def _check_currencies(self): if self.pricelist_id not in self.available_pricelist_ids: raise ValidationError(_("The default pricelist must be included in the available pricelists.")) if any(self.available_pricelist_ids.mapped(lambda pricelist: pricelist.currency_id != self.currency_id)): raise ValidationError(_("All available pricelists must be in the same currency as the company or" " as the Sales Journal set on this point of sale if you use" " the Accounting application.")) if self.invoice_journal_id.currency_id and self.invoice_journal_id.currency_id != self.currency_id: raise ValidationError(_("The invoice journal must be in the same currency as the Sales Journal or the company currency if that is not set.")) if any(self.journal_ids.mapped(lambda journal: journal.currency_id and journal.currency_id != self.currency_id)): raise ValidationError(_("All payment methods must be in the same currency as the Sales Journal or the company currency if that is not set."))
def _check_grouping(self): warning = _( 'The Separator Format should be like [,n] where 0 < n :starting from Unit digit. ' '-1 will end the separation. e.g. [3,2,-1] will represent 106500 to be 1,06,500;' '[1,2,-1] will represent it to be 106,50,0;[3] will represent it as 106,500. ' 'Provided as the thousand separator in each case.') for lang in self: try: if not all( isinstance(x, int) for x in json.loads(lang.grouping)): raise ValidationError(warning) except Exception: raise ValidationError(warning)
def set(self, model_name, field_name, value, user_id=False, company_id=False, condition=False): """ Defines a default value for the given field. Any entry for the same scope (field, user, company) will be replaced. The value is encoded in JSON to be stored to the database. :param user_id: may be ``False`` for all users, ``True`` for the current user, or any user id :param company_id: may be ``False`` for all companies, ``True`` for the current user's company, or any company id :param condition: optional condition that restricts the applicability of the default value; this is an opaque string, but the client typically uses single-field conditions in the form ``'key=val'``. """ if user_id is True: user_id = self.env.uid if company_id is True: company_id = self.env.user.company_id.id # check consistency of model_name, field_name, and value try: model = self.env[model_name] field = model._fields[field_name] field.convert_to_cache(value, model) json_value = json.dumps(value, ensure_ascii=False) except KeyError: raise ValidationError(_("Invalid field %s.%s") % (model_name, field_name)) except Exception: raise ValidationError(_("Invalid value for %s.%s: %s") % (model_name, field_name, value)) # update existing default for the same scope, or create one field = self.env['ir.model.fields']._get(model_name, field_name) default = self.search([ ('field_id', '=', field.id), ('user_id', '=', user_id), ('company_id', '=', company_id), ('condition', '=', condition), ]) if default: default.write({'json_value': json_value}) else: self.create({ 'field_id': field.id, 'user_id': user_id, 'company_id': company_id, 'condition': condition, 'json_value': json_value, }) return True
def _check_alias_defaults(self): try: dict(safe_eval(self.alias_defaults)) except Exception: raise ValidationError( _('Invalid expression, it must be a literal python dictionary definition e.g. "{\'field\': \'value\'}"' ))
def _check_product_recursion(self): for bom in self: if bom.bom_line_ids.filtered(lambda x: x.product_id.product_tmpl_id == bom.product_tmpl_id): raise ValidationError( _('BoM line product %s should not be same as BoM product.') % bom.display_name)
def _check_timesheet_generate(self): for holiday_status in self: if holiday_status.timesheet_generate: if not holiday_status.timesheet_project_id or not holiday_status.timesheet_task_id: raise ValidationError( _('For the leaves to generate timesheet, the internal project and task are requried.' ))
def _check_pos_config(self): if self.search_count([ ('state', '!=', 'closed'), ('config_id', '=', self.config_id.id), ('rescue', '=', False) ]) > 1: raise ValidationError(_("Another session is already opened for this point of sale."))
def _check_recursion_associate_member(self): level = 100 while self: self = self.associate_member if not level: raise ValidationError(_('Error ! You cannot create recursive associated members.')) level -= 1
def action_capture(self): if any(self.mapped(lambda tx: tx.state != 'authorized')): raise ValidationError( _('Only transactions in the Authorized status can be captured.' )) for tx in self: tx.s2s_capture_transaction()
def _check_uom(self): if any(template.uom_id and template.uom_po_id and template.uom_id.category_id != template.uom_po_id.category_id for template in self): raise ValidationError( _('Error: The default Unit of Measure and the purchase Unit of Measure must be in the same category.' )) return True
def _check_unicity(self): # open if there is no session in 'opening_control', 'opened', 'closing_control' for one user if self.search_count([ ('state', 'not in', ('closed', 'closing_control')), ('user_id', '=', self.user_id.id), ('rescue', '=', False) ]) > 1: raise ValidationError(_("You cannot create two active sessions with the same responsible!"))
def _check_main_currency_rounding(self): if any(precision.name == 'Account' and tools.float_compare( self.env.user.company_id.currency_id.rounding, 10**-precision.digits, precision_digits=6) == -1 for precision in self): raise ValidationError( _("You cannot define the decimal precision of 'Account' as greater than the rounding factor of the company's main currency" )) return True
def _check_date(self): """ Prevents the user to create an order in the past """ date_order = datetime.datetime.strptime(self.date, '%Y-%m-%d') date_today = datetime.datetime.strptime( fields.Date.context_today(self), '%Y-%m-%d') if (date_order < date_today): raise ValidationError(_('The date of your order is in the past.'))
def _check_format(self): for lang in self: for pattern in lang._disallowed_datetime_patterns: if (lang.time_format and pattern in lang.time_format) or \ (lang.date_format and pattern in lang.date_format): raise ValidationError( _('Invalid date/time format directive specified. ' 'Please refer to the list of allowed directives, ' 'displayed when you edit a language.'))
def _check_communication(self, payment_method_id, communication): super(AccountPayment, self)._check_communication(payment_method_id, communication) if payment_method_id == self.env.ref( 'account_check_printing.account_payment_method_check').id: if not communication: return if len(communication) > 60: raise ValidationError( _("A check memo cannot exceed 60 characters."))
def _check_serving_attachments(self): # restrict writing on attachments that could be served by the # ir.http's dispatch exception handling if self.env.user._is_superuser(): return if self.type == 'binary' and self.url: has_group = self.env.user.has_group if not any([has_group(g) for g in self.get_serving_groups()]): raise ValidationError( "Sorry, you are not allowed to write on this document")
def _check_account_ids(self, vals): # Raise an error to prevent the account.budget.post to have not specified account_ids. # This check is done on create because require=True doesn't work on Many2many fields. if 'account_ids' in vals: account_ids = self.resolve_2many_commands('account_ids', vals['account_ids']) else: account_ids = self.account_ids if not account_ids: raise ValidationError( _('The budget must have at least one account.'))
def _check_attribute_value_ids(self): for product in self: attributes = self.env['product.attribute'] for value in product.attribute_value_ids: if value.attribute_id in attributes: raise ValidationError( _('Error! It is not allowed to choose more than one value for a given attribute.' )) if value.attribute_id.create_variant: attributes |= value.attribute_id return True
def post(self): """ Create the journal items for the payment and update the payment's state to 'posted'. A journal entry is created containing an item in the source liquidity account (selected journal's default_debit or default_credit) and another in the destination reconciliable account (see _compute_destination_account_id). If invoice_ids is not empty, there will be one reconciliable move line per invoice to reconcile with. If the payment is a transfer, a second journal entry is created in the destination journal to receive money from the transfer account. """ for rec in self: if rec.state != 'draft': raise UserError(_("Only a draft payment can be posted.")) if any(inv.state != 'open' for inv in rec.invoice_ids): raise ValidationError( _("The payment cannot be processed because the invoice is not open!" )) # Use the right sequence to set the name if rec.payment_type == 'transfer': sequence_code = 'account.payment.transfer' else: if rec.partner_type == 'customer': if rec.payment_type == 'inbound': sequence_code = 'account.payment.customer.invoice' if rec.payment_type == 'outbound': sequence_code = 'account.payment.customer.refund' if rec.partner_type == 'supplier': if rec.payment_type == 'inbound': sequence_code = 'account.payment.supplier.refund' if rec.payment_type == 'outbound': sequence_code = 'account.payment.supplier.invoice' rec.name = self.env['ir.sequence'].with_context( ir_sequence_date=rec.payment_date).next_by_code(sequence_code) if not rec.name and rec.payment_type != 'transfer': raise UserError( _("You have to define a sequence for %s in your company.") % (sequence_code, )) # Create the journal entry amount = rec.amount * (rec.payment_type in ('outbound', 'transfer') and 1 or -1) move = rec._create_payment_entry(amount) # In case of a transfer, the first journal entry created debited the source liquidity account and credited # the transfer account. Now we debit the transfer account and credit the destination liquidity account. if rec.payment_type == 'transfer': transfer_credit_aml = move.line_ids.filtered( lambda r: r.account_id == rec.company_id. transfer_account_id) transfer_debit_aml = rec._create_transfer_entry(amount) (transfer_credit_aml + transfer_debit_aml).reconcile() rec.write({'state': 'posted', 'move_name': move.name}) return True
def _validate_fiscalyear_lock(self, values): if values.get('fiscalyear_lock_date'): nb_draft_entries = self.env['account.move'].search([ ('company_id', 'in', [c.id for c in self]), ('state', '=', 'draft'), ('date', '<=', values['fiscalyear_lock_date']) ]) if nb_draft_entries: raise ValidationError( _('There are still unposted entries in the period you want to lock. You should either post or delete them.' ))
def _check_holidays(self): for holiday in self: if holiday.holiday_type != 'employee' or holiday.type != 'remove' or not holiday.employee_id or holiday.holiday_status_id.limit: continue leave_days = holiday.holiday_status_id.get_days( holiday.employee_id.id)[holiday.holiday_status_id.id] if float_compare(leave_days['remaining_leaves'], 0, precision_digits=2) == -1 or \ float_compare(leave_days['virtual_remaining_leaves'], 0, precision_digits=2) == -1: raise ValidationError( _('The number of remaining leaves is not sufficient for this leave type.\n' 'Please verify also the leaves waiting for validation.'))
def _do_payment(self): if self.payment_token_id.acquirer_id.capture_manually: raise ValidationError(_('This feature is not available for payment acquirers set to the "Authorize" mode.\n' 'Please use a token from another provider than %s.') % self.payment_token_id.acquirer_id.name) reference = "P-%s-%s" % (self.id, datetime.datetime.now().strftime('%y%m%d_%H%M%S')) tx = self.env['payment.transaction'].create({ 'amount': self.amount, 'acquirer_id': self.payment_token_id.acquirer_id.id, 'type': 'server2server', 'currency_id': self.currency_id.id, 'reference': reference, 'payment_token_id': self.payment_token_id.id, 'partner_id': self.partner_id.id, 'partner_country_id': self.partner_id.country_id.id, }) s2s_result = tx.s2s_do_transaction() if not s2s_result or tx.state != 'done': raise ValidationError(_("Payment transaction failed (%s)") % tx.state_message) self.payment_transaction_id = tx
def _check_required_if_provider(self): """ If the field has 'required_if_provider="<provider>"' attribute, then it required if record.provider is <provider>. """ empty_field = [] for acquirer in self: for k, f in acquirer._fields.items(): if getattr(f, 'required_if_provider', None) == acquirer.provider and not acquirer[k]: empty_field.append(self.env['ir.model.fields'].search([ ('name', '=', k), ('model', '=', acquirer._name) ]).field_description) if empty_field: raise ValidationError((', ').join(empty_field)) return True
def base_on_rule_send_shipping(self, pickings): res = [] for p in pickings: carrier = self._match_address(p.partner_id) if not carrier: raise ValidationError(_('Error: no matching grid.')) res = res + [{ 'exact_price': p.carrier_id._get_price_available(p.sale_id) if p.sale_id else 0.0, # TODO cleanme 'tracking_number': False }] return res
def _check_date(self): for holiday in self: domain = [ ('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from), ('employee_id', '=', holiday.employee_id.id), ('id', '!=', holiday.id), ('type', '=', holiday.type), ('state', 'not in', ['cancel', 'refuse']), ] nholidays = self.search_count(domain) if nholidays: raise ValidationError( _('You can not have 2 leaves that overlaps on same day!'))
def _check_pattern(self): p = self.pattern.replace("\\\\", "X").replace("\{", "X").replace("\}", "X") findall = re.findall("[{]|[}]", p) # p does not contain escaped { or } if len(findall) == 2: if not re.search("[{][N]*[D]*[}]", p): raise ValidationError( _("There is a syntax error in the barcode pattern ") + self.pattern + _(": braces can only contain N's followed by D's.")) elif re.search("[{][}]", p): raise ValidationError( _("There is a syntax error in the barcode pattern ") + self.pattern + _(": empty braces.")) elif len(findall) != 0: raise ValidationError( _("There is a syntax error in the barcode pattern ") + self.pattern + _(": a rule can only contain one pair of braces.")) elif p == '*': raise ValidationError( _(" '*' is not a valid Regex Barcode Pattern. Did you mean '.*' ?" ))
def isr_print(self): """ Triggered by the 'Print ISR' button. """ self.ensure_one() if self.l10n_ch_isr_valid: self.l10n_ch_isr_sent = True return self.env.ref('l10n_ch.l10n_ch_isr_report').report_action( self) else: raise ValidationError( _("""You cannot generate an ISR yet.\n For this, you need to :\n - set a valid postal account number (or an IBAN referencing one) for your company\n - define its bank\n - associate this bank with a postal reference for the currency used in this invoice\n - fill the 'bank account' field of the invoice with the postal to be used to receive the related payment. A default account will be automatically set for all invoices created after you defined a postal account for your company.""" ))