def _prepare_move_line_value(self): self.ensure_one() if self.account_id: account = self.account_id elif self.product_id: account = self.product_id.product_tmpl_id._get_product_accounts( )['expense'] if not account: raise UserError( _("No Expense account found for the product %s (or for its category), please configure one." ) % (self.product_id.name)) else: account = self.env['ir.property'].with_context( force_company=self.company_id.id).get( 'property_account_expense_categ_id', 'product.category') if not account: raise UserError( _('Please configure Default Expense account for Product expense: `property_account_expense_categ_id`.' )) aml_name = self.employee_id.name + ': ' + self.name.split('\n')[0][:64] move_line = { 'type': 'src', 'name': aml_name, 'price_unit': self.unit_amount, 'quantity': self.quantity, 'price': self.total_amount, 'account_id': account.id, 'product_id': self.product_id.id, 'uom_id': self.product_uom_id.id, 'analytic_account_id': self.analytic_account_id.id, 'expense_id': self.id, } return move_line
def _print_report(self, data): res = {} data = self.pre_print_report(data) data['form'].update(self.read(['period_length'])[0]) period_length = data['form']['period_length'] if period_length <= 0: raise UserError(_('You must set a period length greater than 0.')) if not data['form']['date_from']: raise UserError(_('You must set a start date.')) start = datetime.strptime(data['form']['date_from'], "%Y-%m-%d") for i in range(5)[::-1]: stop = start - relativedelta(days=period_length - 1) res[str(i)] = { 'name': (i != 0 and (str( (5 - (i + 1)) * period_length) + '-' + str( (5 - i) * period_length)) or ('+' + str(4 * period_length))), 'stop': start.strftime('%Y-%m-%d'), 'start': (i != 0 and stop.strftime('%Y-%m-%d') or False), } start = stop - relativedelta(days=1) data['form'].update(res) return self.env.ref( 'account.action_report_aged_partner_balance').with_context( landscape=True).report_action(self, data=data)
def write(self, vals): has_been_posted = False for move in self: if move.company_id._is_accounting_unalterable(): # write the hash and the secure_sequence_number when posting an account.move if vals.get('state') == 'posted': has_been_posted = True # restrict the operation in case we are trying to write a forbidden field if (move.state == "posted" and set(vals).intersection(MOVE_FIELDS)): raise UserError( _("According to the French law, you cannot modify a journal entry in order for its posted data to be updated or deleted. Unauthorized field: %s." ) % ', '.join(MOVE_FIELDS)) # restrict the operation in case we are trying to overwrite existing hash if (move.l10n_fr_hash and 'l10n_fr_hash' in vals) or ( move.l10n_fr_secure_sequence_number and 'l10n_fr_secure_sequence_number' in vals): raise UserError( _('You cannot overwrite the values ensuring the inalterability of the accounting.' )) res = super(AccountMove, self).write(vals) # write the hash and the secure_sequence_number when posting an account.move if has_been_posted: for move in self.filtered( lambda m: m.company_id._is_accounting_unalterable() and not (m.l10n_fr_secure_sequence_number or m.l10n_fr_hash)): new_number = move.company_id.l10n_fr_secure_sequence_id.next_by_id( ) vals_hashing = { 'l10n_fr_secure_sequence_number': new_number, 'l10n_fr_hash': move._get_new_hash(new_number) } res |= super(AccountMove, move).write(vals_hashing) return res
def action_validate(self): self._check_security_action_validate() current_employee = self.env['hr.employee'].search( [('user_id', '=', self.env.uid)], limit=1) for holiday in self: if holiday.state not in ['confirm', 'validate1']: raise UserError( _('Leave request must be confirmed in order to approve it.' )) if holiday.state == 'validate1' and not holiday.env.user.has_group( 'hr_holidays.group_hr_holidays_manager'): raise UserError( _('Only an HR Manager can apply the second approval on leave requests.' )) holiday.write({'state': 'validate'}) if holiday.double_validation: holiday.write({'second_approver_id': current_employee.id}) else: holiday.write({'first_approver_id': current_employee.id}) if holiday.holiday_type == 'employee' and holiday.type == 'remove': holiday._validate_leave_request() elif holiday.holiday_type == 'category': leaves = self.env['hr.holidays'] for employee in holiday.category_id.employee_ids: values = holiday._prepare_create_by_category(employee) leaves += self.with_context( mail_notify_force_send=False).create(values) # TODO is it necessary to interleave the calls? leaves.action_approve() if leaves and leaves[0].double_validation: leaves.action_validate() return True
def open_statement(self): self.ensure_one() BankStatement = self.env['account.bank.statement'] journals = self.env['account.journal'].search([('journal_user', '=', True)]) if not journals: raise UserError( _('You have to define which payment method must be available in the point of sale by reusing existing bank and cash through "Accounting / Configuration / Journals / Journals". Select a journal and check the field "PoS Payment Method" from the "Point of Sale" tab. You can also create new payment methods directly from menu "PoS Backend / Configuration / Payment Methods".' )) for journal in journals: if journal.sequence_id: number = journal.sequence_id.next_by_id() else: raise UserError(_("No sequence defined on the journal")) BankStatement += BankStatement.create({ 'journal_id': journal.id, 'user_id': self.env.uid, 'name': number }) tree_id = self.env.ref('account.view_bank_statement_tree').id form_id = self.env.ref('account.view_bank_statement_form').id search_id = self.env.ref('account.view_bank_statement_search').id return { 'type': 'ir.actions.act_window', 'name': _('List of Cash Registers'), 'view_type': 'form', 'view_mode': 'tree,form', 'res_model': 'account.bank.statement', 'domain': str([('id', 'in', BankStatement.ids)]), 'views': [(tree_id, 'tree'), (form_id, 'form')], 'search_view_id': search_id, }
def _satisfy_condition(self, localdict): """ @param contract_id: id of hr.contract to be tested @return: returns True if the given rule match the condition for the given contract. Return False otherwise. """ self.ensure_one() if self.condition_select == 'none': return True elif self.condition_select == 'range': try: result = safe_eval(self.condition_range, localdict) return self.condition_range_min <= result and result <= self.condition_range_max or False except: raise UserError( _('Wrong range condition defined for salary rule %s (%s).') % (self.name, self.code)) else: # python code try: safe_eval(self.condition_python, localdict, mode='exec', nocopy=True) return 'result' in localdict and localdict['result'] or False except: raise UserError( _('Wrong python condition defined for salary rule %s (%s).' ) % (self.name, self.code))
def generate_report(self): if (not self.env.user.company_id.logo): raise UserError(_("You have to set a logo or a layout for your company.")) elif (not self.env.user.company_id.external_report_layout): raise UserError(_("You have to set your reports's header and footer layout.")) data = {'date_start': self.start_date, 'date_stop': self.end_date, 'config_ids': self.pos_config_ids.ids} return self.env.ref('point_of_sale.sale_details_report').report_action([], data=data)
def _inverse_remaining_leaves(self): status_list = self.env['hr.holidays.status'].search([('limit', '=', False)]) # Create leaves (adding remaining leaves) or raise (reducing remaining leaves) actual_remaining = self._get_remaining_leaves() for employee in self.filtered(lambda employee: employee.remaining_leaves): # check the status list. This is done here and not before the loop to avoid raising # exception on employee creation (since we are in a computed field). if len(status_list) != 1: raise UserError(_("The feature behind the field 'Remaining Legal Leaves' can only be used when there is only one " "leave type with the option 'Allow to Override Limit' unchecked. (%s Found). " "Otherwise, the update is ambiguous as we cannot decide on which leave type the update has to be done. " "\n You may prefer to use the classic menus 'Leave Requests' and 'Allocation Requests' located in Leaves Application " "to manage the leave days of the employees if the configuration does not allow to use this field.") % (len(status_list))) status = status_list[0] if status_list else None if not status: continue # if a status is found, then compute remaing leave for current employee difference = employee.remaining_leaves - actual_remaining.get(employee.id, 0) if difference > 0: leave = self.env['hr.holidays'].create({ 'name': _('Allocation for %s') % employee.name, 'employee_id': employee.id, 'holiday_status_id': status.id, 'type': 'add', 'holiday_type': 'employee', 'number_of_days_temp': difference }) leave.action_approve() if leave.double_validation: leave.action_validate() elif difference < 0: raise UserError(_('You cannot reduce validated allocation requests'))
def print_checks(self): """ Check that the recordset is valid, set the payments state to sent and call print_checks() """ # Since this method can be called via a client_action_multi, we need to make sure the received records are what we expect self = self.filtered(lambda r: r.payment_method_id.code == 'check_printing' and r.state != 'reconciled') if len(self) == 0: raise UserError(_("Payments to print as a checks must have 'Check' selected as payment method and " "not have already been reconciled")) if any(payment.journal_id != self[0].journal_id for payment in self): raise UserError(_("In order to print multiple checks at once, they must belong to the same bank journal.")) if not self[0].journal_id.check_manual_sequencing: # The wizard asks for the number printed on the first pre-printed check # so payments are attributed the number of the check the'll be printed on. last_printed_check = self.search([ ('journal_id', '=', self[0].journal_id.id), ('check_number', '!=', 0)], order="check_number desc", limit=1) next_check_number = last_printed_check and last_printed_check.check_number + 1 or 1 return { 'name': _('Print Pre-numbered Checks'), 'type': 'ir.actions.act_window', 'res_model': 'print.prenumbered.checks', 'view_type': 'form', 'view_mode': 'form', 'target': 'new', 'context': { 'payment_ids': self.ids, 'default_next_check_number': next_check_number, } } else: self.filtered(lambda r: r.state == 'draft').post() return self.do_print_checks()
def act_update(self): ''' Function called by the wizard. ''' flag, gengo = self.gengo_authentication() if not flag: raise UserError(gengo) for wizard in self: supported_langs = self.env[ 'ir.translation']._get_all_supported_languages() language = self.env[ 'ir.translation']._get_gengo_corresponding_language( wizard.lang_id.code) if language not in supported_langs: raise UserError( _('This language is not supported by the Gengo translation services.' )) ctx = self.env.context.copy() ctx['gengo_language'] = wizard.lang_id.id if wizard.sync_limit > 200 or wizard.sync_limit < 1: raise UserError( _('The number of terms to sync should be between 1 to 200 to work with Gengo translation services.' )) if wizard.sync_type in ['send', 'both']: self.with_context(ctx)._sync_request(wizard.sync_limit) if wizard.sync_type in ['receive', 'both']: self.with_context(ctx)._sync_response(wizard.sync_limit) return {'type': 'ir.actions.act_window_close'}
def _action_done(self): self.product_price_update_before_done() res = super(StockMove, self)._action_done() for move in res: # Apply restrictions on the stock move to be able to make # consistent accounting entries. if move._is_in() and move._is_out(): raise UserError( _("The move lines are not in a consistent state: some are entering and other are leaving the company. " )) company_src = move.mapped('move_line_ids.location_id.company_id') company_dst = move.mapped( 'move_line_ids.location_dest_id.company_id') try: if company_src: company_src.ensure_one() if company_dst: company_dst.ensure_one() except ValueError: raise UserError( _("The move lines are not in a consistent states: they do not share the same origin or destination company." )) if company_src and company_dst and company_src.id != company_dst.id: raise UserError( _("The move lines are not in a consistent states: they are doing an intercompany in a single step while they should go through the intercompany transit location." )) move._run_valuation() for move in res.filtered( lambda m: m.product_id.valuation == 'real_time' and (m._is_in() or m._is_out() or m._is_dropshipped())): move._account_entry_move() return res
def button_upgrade(self): Dependency = self.env['ir.module.module.dependency'] self.update_list() todo = list(self) i = 0 while i < len(todo): module = todo[i] i += 1 if module.state not in ('installed', 'to upgrade'): raise UserError(_("Can not upgrade module '%s'. It is not installed.") % (module.name,)) self.check_external_dependencies(module.name, 'to upgrade') for dep in Dependency.search([('name', '=', module.name)]): if dep.module_id.state == 'installed' and dep.module_id not in todo: todo.append(dep.module_id) self.browse(module.id for module in todo).write({'state': 'to upgrade'}) to_install = [] for module in todo: for dep in module.dependencies_id: if dep.state == 'unknown': raise UserError(_('You try to upgrade the module %s that depends on the module: %s.\nBut this module is not available in your system.') % (module.name, dep.name,)) if dep.state == 'uninstalled': to_install += self.search([('name', '=', dep.name)]).ids self.browse(to_install).button_install() return dict(ACTION_DICT, name=_('Apply Schedule Upgrade'))
def _state_update(self, newstate, states_to_update, level=100): if level < 1: raise UserError(_('Recursion error in modules dependencies !')) # whether some modules are installed with demo data demo = False for module in self: # determine dependency modules to update/others update_mods, ready_mods = self.browse(), self.browse() for dep in module.dependencies_id: if dep.state == 'unknown': raise UserError(_("You try to install module '%s' that depends on module '%s'.\nBut the latter module is not available in your system.") % (module.name, dep.name,)) if dep.depend_id.state == newstate: ready_mods += dep.depend_id else: update_mods += dep.depend_id # update dependency modules that require it, and determine demo for module update_demo = update_mods._state_update(newstate, states_to_update, level=level-1) module_demo = module.demo or update_demo or any(mod.demo for mod in ready_mods) demo = demo or module_demo # check dependencies and update module itself self.check_external_dependencies(module.name, newstate) if module.state in states_to_update: module.write({'state': newstate, 'demo': module_demo}) return demo
def action_repair_cancel(self): if self.filtered(lambda repair: repair.state == 'done'): raise UserError(_("Cannot cancel completed repairs.")) if any(repair.invoiced for repair in self): raise UserError(_('Repair order is already invoiced.')) self.mapped('operations').write({'state': 'cancel'}) return self.write({'state': 'cancel'})
def create(self, vals): reference = vals.get('reference', False) reference_type = vals.get('reference_type', False) if vals.get('type') == 'out_invoice' and not reference_type: # fallback on default communication type for partner partner = self.env['res.partner'].browse(vals['partner_id']) reference_type = partner.out_inv_comm_type if reference_type == 'bba': reference = self.generate_bbacomm(vals['type'], reference_type, partner.id, '')['value']['reference'] vals.update({ 'reference_type': reference_type or 'none', 'reference': reference, }) if reference_type == 'bba': if not reference: raise UserError(_('Empty BBA Structured Communication!' '\nPlease fill in a unique BBA Structured Communication.')) if self.check_bbacomm(reference): reference = re.sub('\D', '', reference) vals['reference'] = '+++' + reference[0:3] + '/' + reference[3:7] + '/' + reference[7:] + '+++' same_ids = self.search([('type', '=', 'out_invoice'), ('reference_type', '=', 'bba'), ('reference', '=', vals['reference'])]) if same_ids: raise UserError(_('The BBA Structured Communication has already been used!' '\nPlease create manually a unique BBA Structured Communication.')) return super(AccountInvoice, self).create(vals)
def unlink(self): for asset in self: if asset.state in ['open', 'close']: raise UserError(_('You cannot delete a document is in %s state.') % (asset.state,)) for depreciation_line in asset.depreciation_line_ids: if depreciation_line.move_id: raise UserError(_('You cannot delete a document that contains posted entries.')) return super(AccountAssetAsset, self).unlink()
def unlink(self): if any(bool(rec.move_line_ids) for rec in self): raise UserError( _("You can not delete a payment that is already posted")) if any(rec.move_name for rec in self): raise UserError( _('It is not allowed to delete a payment that already created a journal entry since it would create a gap in the numbering. You should create the journal entry again and cancel it thanks to a regular revert.' )) return super(account_payment, self).unlink()
def default_get(self, fields): if len(self.env.context.get('active_ids', list())) > 1: raise UserError("You may only return one picking at a time!") res = super(ReturnPicking, self).default_get(fields) move_dest_exists = False product_return_moves = [] picking = self.env['stock.picking'].browse( self.env.context.get('active_id')) if picking: res.update({'picking_id': picking.id}) if picking.state != 'done': raise UserError(_("You may only return Done pickings")) for move in picking.move_lines: if move.scrapped: continue if move.move_dest_ids: move_dest_exists = True quantity = move.product_qty - sum(move.move_dest_ids.filtered(lambda m: m.state in ['partially_available', 'assigned', 'done']).\ mapped('move_line_ids').mapped('product_qty')) quantity = float_round( quantity, precision_rounding=move.product_uom.rounding) product_return_moves.append((0, 0, { 'product_id': move.product_id.id, 'quantity': quantity, 'move_id': move.id, 'uom_id': move.product_id.uom_id.id })) if not product_return_moves: raise UserError( _("No products to return (only lines in Done state and not fully returned yet can be returned)!" )) if 'product_return_moves' in fields: res.update({'product_return_moves': product_return_moves}) if 'move_dest_exists' in fields: res.update({'move_dest_exists': move_dest_exists}) if 'parent_location_id' in fields and picking.location_id.usage == 'internal': res.update({ 'parent_location_id': picking.picking_type_id.warehouse_id and picking.picking_type_id.warehouse_id.view_location_id.id or picking.location_id.location_id.id }) if 'original_location_id' in fields: res.update({'original_location_id': picking.location_id.id}) if 'location_id' in fields: location_id = picking.location_id.id if picking.picking_type_id.return_picking_type_id.default_location_dest_id.return_location: location_id = picking.picking_type_id.return_picking_type_id.default_location_dest_id.id res['location_id'] = location_id return res
def action_apply(self): self.env['res.partner'].check_access_rights('write') """ From selected partners, add corresponding users to chosen portal group. It either granted existing user, or create new one (and add it to the group). """ error_msg = self.get_error_messages() if error_msg: raise UserError("\n\n".join(error_msg)) for wizard_user in self.sudo().with_context(active_test=False): group_portal = wizard_user.wizard_id.portal_id if not group_portal.is_portal: raise UserError( _('Group %s is not a portal') % group_portal.name) user = wizard_user.partner_id.user_ids[ 0] if wizard_user.partner_id.user_ids else None # update partner email, if a new one was introduced if wizard_user.partner_id.email != wizard_user.email: wizard_user.partner_id.write({'email': wizard_user.email}) # add portal group to relative user of selected partners if wizard_user.in_portal: user_portal = None # create a user if necessary, and make sure it is in the portal group if not user: if wizard_user.partner_id.company_id: company_id = wizard_user.partner_id.company_id.id else: company_id = self.env[ 'res.company']._company_default_get('res.users') user_portal = wizard_user.sudo().with_context( company_id=company_id)._create_user() else: user_portal = user wizard_user.write({'user_id': user_portal.id}) if not wizard_user.user_id.active or group_portal not in wizard_user.user_id.groups_id: wizard_user.user_id.write({ 'active': True, 'groups_id': [(4, group_portal.id)] }) # prepare for the signup process wizard_user.user_id.partner_id.signup_prepare() wizard_user.with_context(active_test=True)._send_email() wizard_user.refresh() else: # remove the user (if it exists) from the portal group if user and group_portal in user.groups_id: # if user belongs to portal only, deactivate it if len(user.groups_id) <= 1: user.write({ 'groups_id': [(3, group_portal.id)], 'active': False }) else: user.write({'groups_id': [(3, group_portal.id)]})
def button_install(self): # domain to select auto-installable (but not yet installed) modules auto_domain = [('state', '=', 'uninstalled'), ('auto_install', '=', True)] # determine whether an auto-install module must be installed: # - all its dependencies are installed or to be installed, # - at least one dependency is 'to install' install_states = frozenset(('installed', 'to install', 'to upgrade')) def must_install(module): states = set(dep.state for dep in module.dependencies_id) return states <= install_states and 'to install' in states modules = self while modules: # Mark the given modules and their dependencies to be installed. modules._state_update('to install', ['uninstalled']) # Determine which auto-installable modules must be installed. modules = self.search(auto_domain).filtered(must_install) # the modules that are installed/to install/to upgrade install_mods = self.search([('state', 'in', list(install_states))]) # check individual exclusions install_names = {module.name for module in install_mods} for module in install_mods: for exclusion in module.exclusion_ids: if exclusion.name in install_names: msg = _('Modules "%s" and "%s" are incompatible.') raise UserError(msg % (module.shortdesc, exclusion.exclusion_id.shortdesc)) # check category exclusions def closure(module): todo = result = module while todo: result |= todo todo = todo.mapped('dependencies_id.depend_id') return result exclusives = self.env['ir.module.category'].search([('exclusive', '=', True)]) for category in exclusives: # retrieve installed modules in category and sub-categories categories = category.search([('id', 'child_of', category.ids)]) modules = install_mods.filtered(lambda mod: mod.category_id in categories) # the installation is valid if all installed modules in categories # belong to the transitive dependencies of one of them if modules and not any(modules <= closure(module) for module in modules): msg = _('You are trying to install incompatible modules in category "%s":') labels = dict(self.fields_get(['state'])['state']['selection']) raise UserError("\n".join([msg % category.name] + [ "- %s (%s)" % (module.shortdesc, labels[module.state]) for module in modules ])) return dict(ACTION_DICT, name=_('Install'))
def get_access_token(self, scope=None): Config = self.env['ir.config_parameter'].sudo() google_drive_refresh_token = Config.get_param( 'google_drive_refresh_token') user_is_admin = self.env['res.users'].browse( self.env.user.id)._is_admin() if not google_drive_refresh_token: if user_is_admin: dummy, action_id = self.env[ 'ir.model.data'].get_object_reference( 'base_setup', 'action_general_configuration') msg = _( "You haven't configured 'Authorization Code' generated from google, Please generate and configure it ." ) raise RedirectWarning(msg, action_id, _('Go to the configuration panel')) else: raise UserError( _("Google Drive is not yet configured. Please contact your administrator." )) google_drive_client_id = Config.get_param('google_drive_client_id') google_drive_client_secret = Config.get_param( 'google_drive_client_secret') #For Getting New Access Token With help of old Refresh Token data = { 'client_id': google_drive_client_id, 'refresh_token': google_drive_refresh_token, 'client_secret': google_drive_client_secret, 'grant_type': "refresh_token", 'scope': scope or 'https://www.googleapis.com/auth/drive' } headers = {"Content-type": "application/x-www-form-urlencoded"} try: req = requests.post(GOOGLE_TOKEN_ENDPOINT, data=data, headers=headers, timeout=TIMEOUT) req.raise_for_status() except requests.HTTPError: if user_is_admin: dummy, action_id = self.env[ 'ir.model.data'].get_object_reference( 'base_setup', 'action_general_configuration') msg = _( "Something went wrong during the token generation. Please request again an authorization code ." ) raise RedirectWarning(msg, action_id, _('Go to the configuration panel')) else: raise UserError( _("Google Drive is not yet configured. Please contact your administrator." )) return req.json().get('access_token')
def _check_parsed_data(self, stmts_vals): """ Basic and structural verifications """ if len(stmts_vals) == 0: raise UserError(_('This file doesn\'t contain any statement.')) no_st_line = True for vals in stmts_vals: if vals['transactions'] and len(vals['transactions']) > 0: no_st_line = False break if no_st_line: raise UserError(_('This file doesn\'t contain any transaction.'))
def do_signup(self, qcontext): """ Shared helper that creates a res.partner out of a token """ values = { key: qcontext.get(key) for key in ('login', 'name', 'password') } if not values: raise UserError(_("The form was not properly filled in.")) if values.get('password') != qcontext.get('confirm_password'): raise UserError(_("Passwords do not match; please retype them.")) supported_langs = [lang['code'] for lang in request.env['res.lang'].sudo().search_read([], ['code'])] if request.lang in supported_langs: values['lang'] = request.lang self._signup_with_values(qcontext.get('token'), values) request.env.cr.commit()
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})
def button_reg_close(self): """ Close Registration """ today = fields.Datetime.now() if self.event_id.date_begin <= today and self.event_id.state == 'confirm': self.write({'state': 'done', 'date_closed': today}) elif self.event_id.state == 'draft': raise UserError( _("You must wait the event confirmation before doing this action." )) else: raise UserError( _("You must wait the event starting day before doing this action." ))
def _run(self, records): for box in self: for record in records: if not record.journal_id: raise UserError( _("Please check that the field 'Journal' is set on the Bank Statement" )) if not record.journal_id.company_id.transfer_account_id: raise UserError( _("Please check that the field 'Transfer Account' is set on the company." )) box._create_bank_statement_line(record) return {}
def _check_twitter_authorization(self): try: self.website_id.fetch_favorite_tweets() except requests.HTTPError as e: _logger.info("%s - %s" % (e.response.status_code, e.response.reason), exc_info=True) raise UserError("%s - %s" % (e.response.status_code, e.response.reason) + ':' + self._get_twitter_exception_message(e.response.status_code)) except IOError: _logger.info(_('We failed to reach a twitter server.'), exc_info=True) raise UserError(_('Internet connection refused') + ' ' + _('We failed to reach a twitter server.')) except Exception: _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!'))
def button_validate(self): if any(cost.state != 'draft' for cost in self): raise UserError(_('Only draft landed costs can be validated')) if any(not cost.valuation_adjustment_lines for cost in self): raise UserError( _('No valuation adjustments lines. You should maybe recompute the landed costs.' )) if not self._check_sum(): raise UserError( _('Cost and adjustments lines do not match. You should maybe recompute the landed costs.' )) for cost in self: move = self.env['account.move'].create({ 'journal_id': cost.account_journal_id.id, 'date': cost.date, 'ref': cost.name }) for line in cost.valuation_adjustment_lines.filtered( lambda line: line.move_id): # Prorate the value at what's still in stock cost_to_add = ( line.move_id.remaining_qty / line.move_id.product_qty) * line.additional_landed_cost new_landed_cost_value = line.move_id.landed_cost_value + line.additional_landed_cost line.move_id.write({ 'landed_cost_value': new_landed_cost_value, 'remaining_value': line.move_id.remaining_value + cost_to_add, 'price_unit': (line.move_id.value + new_landed_cost_value) / line.move_id.product_qty, }) # `remaining_qty` is negative if the move is out and delivered proudcts that were not # in stock. qty_out = 0 if line.move_id._is_in(): qty_out = line.move_id.product_qty - line.move_id.remaining_qty elif line.move_id._is_out(): qty_out = line.move_id.product_qty line._create_accounting_entries(move, qty_out) move.assert_balanced() cost.write({'state': 'done', 'account_move_id': move.id}) move.post() return True
def done(self): pickings = self.mapped('picking_ids').filtered(lambda picking: picking.state not in ('cancel', 'done')) if any(picking.state not in ('assigned') for picking in pickings): raise UserError(_('Some pickings are still waiting for goods. Please check or force their availability before setting this batch to done.')) for picking in pickings: picking.message_post( body="<b>%s:</b> %s <a href=#id=%s&view_type=form&model=stock.picking.batch>%s</a>" % ( _("Transferred by"), _("Batch Picking"), picking.batch_id.id, picking.batch_id.name)) picking_to_backorder = self.env['stock.picking'] picking_without_qty_done = self.env['stock.picking'] for picking in pickings: if all([x.qty_done == 0.0 for x in picking.move_line_ids]): # If no lots when needed, raise error picking_type = picking.picking_type_id if (picking_type.use_create_lots or picking_type.use_existing_lots): for ml in picking.move_line_ids: if ml.product_id.tracking != 'none': raise UserError(_('Some products require lots/serial numbers, so you need to specify those first!')) # Check if we need to set some qty done. picking_without_qty_done |= picking elif picking._check_backorder(): picking_to_backorder |= picking else: picking.action_done() self.write({'state': 'done'}) if picking_without_qty_done: view = self.env.ref('stock.view_immediate_transfer') wiz = self.env['stock.immediate.transfer'].create({ 'pick_ids': [(4, p.id) for p in picking_without_qty_done], 'pick_to_backorder_ids': [(4, p.id) for p in picking_to_backorder], }) return { 'name': _('Immediate Transfer?'), 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'stock.immediate.transfer', 'views': [(view.id, 'form')], 'view_id': view.id, 'target': 'new', 'res_id': wiz.id, 'context': self.env.context, } if picking_to_backorder: return picking_to_backorder.action_generate_backorder_wizard() return True
def default_get(self, fields): rec = super(account_register_payments, self).default_get(fields) active_ids = self._context.get('active_ids') # Check for selected invoices ids if not active_ids: raise UserError( _("Programming error: wizard action executed without active_ids in context." )) invoices = self.env['account.invoice'].browse(active_ids) # Check all invoices are open if any(invoice.state != 'open' for invoice in invoices): raise UserError( _("You can only register payments for open invoices")) # Check all invoices have the same currency if any(inv.currency_id != invoices[0].currency_id for inv in invoices): raise UserError( _("In order to pay multiple invoices at once, they must use the same currency." )) # Look if we are mixin multiple commercial_partner or customer invoices with vendor bills multi = any( inv.commercial_partner_id != invoices[0].commercial_partner_id or MAP_INVOICE_TYPE_PARTNER_TYPE[ inv.type] != MAP_INVOICE_TYPE_PARTNER_TYPE[invoices[0].type] for inv in invoices) total_amount = self._compute_payment_amount(invoices) rec.update({ 'amount': abs(total_amount), 'currency_id': invoices[0].currency_id.id, 'payment_type': total_amount > 0 and 'inbound' or 'outbound', 'partner_id': False if multi else invoices[0].commercial_partner_id.id, 'partner_type': False if multi else MAP_INVOICE_TYPE_PARTNER_TYPE[invoices[0].type], 'communication': ' '.join([ref for ref in invoices.mapped('reference') if ref]), 'invoice_ids': [(6, 0, invoices.ids)], 'multi': multi, }) return rec