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 _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 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 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 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_pos_session_close(self): # Close CashBox for session in self: company_id = session.config_id.company_id.id ctx = dict(self.env.context, force_company=company_id, company_id=company_id) for st in session.statement_ids: if abs(st.difference) > st.journal_id.amount_authorized_diff: # The pos manager can close statements with maximums. if not self.user_has_groups( "point_of_sale.group_pos_manager"): raise UserError( _("Your ending balance is too different from the theoretical cash closing (%.2f), the maximum allowed is: %.2f. You can contact your manager to force it." ) % (st.difference, st.journal_id.amount_authorized_diff)) if (st.journal_id.type not in ['bank', 'cash']): raise UserError( _("The type of the journal for your payment method should be bank or cash " )) st.with_context(ctx).sudo().button_confirm_bank() self.with_context(ctx)._confirm_orders() self.write({'state': 'closed'}) return { 'type': 'ir.actions.client', 'name': 'Point of Sale Menu', 'tag': 'reload', 'params': { 'menu_id': self.env.ref('point_of_sale.menu_point_root').id }, }
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 geo_find(addr, apikey=False): if not addr: return None if not apikey: raise UserError(_('''API key for GeoCoding (Places) required.\n Save this key in System Parameters with key: google.api_key_geocode, value: <your api key> Visit https://developers.google.com/maps/documentation/geocoding/get-api-key for more information. ''')) url = "https://maps.googleapis.com/maps/api/geocode/json" try: result = requests.get(url, params={'sensor': 'false', 'address': addr, 'key': apikey}).json() except Exception as e: raise UserError(_('Cannot contact geolocation servers. Please make sure that your Internet connection is up and running (%s).') % e) if result['status'] != 'OK': if result.get('error_message'): _logger.error(result['error_message']) return None try: geo = result['results'][0]['geometry']['location'] return float(geo['lat']), float(geo['lng']) except (KeyError, ValueError): return None
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 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 write(self, vals): has_been_posted = False for order in self: if order.company_id._is_accounting_unalterable(): # write the hash and the secure_sequence_number when posting or invoicing an pos.order if vals.get('state') in ['paid', 'done', 'invoiced']: has_been_posted = True # restrict the operation in case we are trying to write a forbidden field if (order.state in ['paid', 'done', 'invoiced'] and set(vals).intersection(ORDER_FIELDS)): raise UserError( _('According to the French law, you cannot modify a point of sale order. Forbidden fields: %s.' ) % ', '.join(ORDER_FIELDS)) # restrict the operation in case we are trying to overwrite existing hash if (order.l10n_fr_hash and 'l10n_fr_hash' in vals) or ( order.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 point of sale.' )) res = super(pos_order, self).write(vals) # write the hash and the secure_sequence_number when posting or invoicing a pos order if has_been_posted: for order in self.filtered( lambda o: o.company_id._is_accounting_unalterable() and not (o.l10n_fr_secure_sequence_number or o.l10n_fr_hash)): new_number = order.company_id.l10n_fr_pos_cert_sequence_id.next_by_id( ) vals_hashing = { 'l10n_fr_secure_sequence_number': new_number, 'l10n_fr_hash': order._get_new_hash(new_number) } res |= super(pos_order, order).write(vals_hashing) return res
def write(self, vals): if 'uom_id' in vals: new_uom = self.env['product.uom'].browse(vals['uom_id']) updated = self.filtered( lambda template: template.uom_id != new_uom) done_moves = self.env['stock.move'].search( [('product_id', 'in', updated.with_context( active_test=False).mapped('product_variant_ids').ids)], limit=1) if done_moves: raise UserError( _("You can not change the unit of measure of a product that has already been used in a done stock move. If you need to change the unit of measure, you may deactivate this product." )) if 'type' in vals and vals['type'] != 'product' and sum( self.mapped('nbr_reordering_rules')) != 0: raise UserError( _('You still have some active reordering rules on this product. Please archive or delete them first.' )) if any('type' in vals and vals['type'] != prod_tmpl.type for prod_tmpl in self): existing_move_lines = self.env['stock.move.line'].search([ ('product_id', 'in', self.mapped('product_variant_ids').ids), ('state', 'in', ['partially_available', 'assigned']), ]) if existing_move_lines: raise UserError( _("You can not change the type of a product that is currently reserved on a stock move. If you need to change the type, you should first unreserve the stock move." )) return super(ProductTemplate, self).write(vals)
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() or m. _is_dropshipped_returned())): move._account_entry_move() return res
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 _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 _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 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 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 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 _check_hash_integrity(self, company_id): """Checks that all posted or invoiced pos orders have still the same data as when they were posted and raises an error with the result. """ def build_order_info(order): entry_reference = _('(Receipt ref.: %s)') order_reference_string = order.pos_reference and entry_reference % order.pos_reference or '' return [ ctx_tz(order, 'date_order'), order.l10n_fr_secure_sequence_number, order.name, order_reference_string, ctx_tz(order, 'write_date') ] orders = self.search([('state', 'in', ['paid', 'done', 'invoiced']), ('company_id', '=', company_id), ('l10n_fr_secure_sequence_number', '!=', 0)], order="l10n_fr_secure_sequence_number ASC") if not orders: raise UserError( _('There isn\'t any order flagged for data inalterability yet for the company %s. This mechanism only runs for point of sale orders generated after the installation of the module France - Certification CGI 286 I-3 bis. - POS' ) % self.env.user.company_id.name) previous_hash = u'' start_order_info = [] for order in orders: if order.l10n_fr_hash != order._compute_hash( previous_hash=previous_hash): raise UserError( _('Corrupted data on point of sale order with id %s.') % order.id) previous_hash = order.l10n_fr_hash orders_sorted_date = orders.sorted(lambda o: o.date_order) start_order_info = build_order_info(orders_sorted_date[0]) end_order_info = build_order_info(orders_sorted_date[-1]) report_dict = { 'start_order_name': start_order_info[2], 'start_order_ref': start_order_info[3], 'start_order_date': start_order_info[0], 'end_order_name': end_order_info[2], 'end_order_ref': end_order_info[3], 'end_order_date': end_order_info[0] } # Raise on success raise UserError( _('''Successful test ! The point of sale orders are guaranteed to be in their original and inalterable state From: %(start_order_name)s %(start_order_ref)s recorded on %(start_order_date)s To: %(end_order_name)s %(end_order_ref)s recorded on %(end_order_date)s For this report to be legally meaningful, please download your certification from your customer account on Infonoble.com (Only for NobleCRM Enterprise users).''' ) % report_dict)
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').id 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 _check_write(self): """check that the field is created from the menu and not from an database update otherwise the database update can crash:""" if self.env.context.get('manual'): global_state = self._get_global_state() if global_state == 'anonymized': raise UserError(_("The database is currently anonymized, you cannot create, modify or delete fields.")) elif global_state == 'unstable': raise UserError(_("The database anonymization is currently in an unstable state. Some fields are anonymized," " while some fields are not anonymized. You should try to solve this problem before trying to create, write or delete fields.")) 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 phone_parse(number, country_code): try: phone_nbr = phonenumbers.parse(number, region=country_code, keep_raw_input=True) except phonenumbers.phonenumberutil.NumberParseException as e: raise UserError(_('Unable to parse %s:\n%s') % (number, e)) if not phonenumbers.is_possible_number(phone_nbr): raise UserError(_('Impossible number %s: probably invalid number of digits') % number) if not phonenumbers.is_valid_number(phone_nbr): raise UserError(_('Invalid number %s: probably incorrect prefix') % number) return phone_nbr
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 _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 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_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 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