コード例 #1
0
    def create_membership_invoice(self, product, amount):
        """ Create Customer Invoice of Membership for partners.
        """
        invoice_vals_list = []
        for partner in self:
            addr = partner.address_get(['invoice'])
            if partner.free_member:
                raise UserError(_("Partner is a free Member."))
            if not addr.get('invoice', False):
                raise UserError(
                    _("Partner doesn't have an address to make the invoice."))

            invoice_vals_list.append({
                'type':
                'out_invoice',
                'partner_id':
                partner.id,
                'invoice_line_ids': [(0, None, {
                    'product_id': product.id,
                    'quantity': 1,
                    'price_unit': amount,
                    'tax_ids': [(6, 0, product.taxes_id.ids)]
                })]
            })

        return self.env['account.move'].create(invoice_vals_list)
コード例 #2
0
    def attachment_remove(self, attachment_id, access_token=None):
        """Remove the given `attachment_id`, only if it is in a "pending" state.

        The user must have access right on the attachment or provide a valid
        `access_token`.
        """
        try:
            attachment_sudo = self._document_check_access(
                'ir.attachment', int(attachment_id), access_token=access_token)
        except (AccessError, MissingError) as e:
            raise UserError(
                _("The attachment does not exist or you do not have the rights to access it."
                  ))

        if attachment_sudo.res_model != 'mail.compose.message' or attachment_sudo.res_id != 0:
            raise UserError(
                _("The attachment %s cannot be removed because it is not in a pending state."
                  ) % attachment_sudo.name)

        if attachment_sudo.env['mail.message'].search([('attachment_ids', 'in',
                                                        attachment_sudo.ids)]):
            raise UserError(
                _("The attachment %s cannot be removed because it is linked to a message."
                  ) % attachment_sudo.name)

        return attachment_sudo.unlink()
コード例 #3
0
    def _show_report(self, model, report_type, report_ref, download=False):
        if report_type not in ('html', 'pdf', 'text'):
            raise UserError(_("Invalid report type: %s") % report_type)

        report_sudo = request.env.ref(report_ref).sudo()

        if not isinstance(report_sudo, type(request.env['ir.actions.report'])):
            raise UserError(
                _("%s is not the reference of a report") % report_ref)

        method_name = 'render_qweb_%s' % (report_type)
        report = getattr(report_sudo, method_name)([model.id],
                                                   data={
                                                       'report_type':
                                                       report_type
                                                   })[0]
        reporthttpheaders = [
            ('Content-Type',
             'application/pdf' if report_type == 'pdf' else 'text/html'),
            ('Content-Length', len(report)),
        ]
        if report_type == 'pdf' and download:
            filename = "%s.pdf" % (re.sub('\W+', '-',
                                          model._get_report_base_filename()))
            reporthttpheaders.append(
                ('Content-Disposition', content_disposition(filename)))
        return request.make_response(report, headers=reporthttpheaders)
コード例 #4
0
ファイル: repair.py プロジェクト: marionumza/saas
 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(_('The repair order is already invoiced.'))
     self.mapped('operations').write({'state': 'cancel'})
     return self.write({'state': 'cancel'})
コード例 #5
0
    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'}
コード例 #6
0
 def action_in_progress(self):
     self.ensure_one()
     if not all(obj.line_ids for obj in self):
         raise UserError(
             _("You cannot confirm agreement '%s' because there is no product line."
               ) % self.name)
     if self.type_id.quantity_copy == 'none' and self.vendor_id:
         for requisition_line in self.line_ids:
             if requisition_line.price_unit <= 0.0:
                 raise UserError(
                     _('You cannot confirm the blanket order without price.'
                       ))
             if requisition_line.product_qty <= 0.0:
                 raise UserError(
                     _('You cannot confirm the blanket order without quantity.'
                       ))
             requisition_line.create_supplier_info()
         self.write({'state': 'ongoing'})
     else:
         self.write({'state': 'in_progress'})
     # Set the sequence number regarding the requisition type
     if self.name == 'New':
         if self.is_quantity_copy != 'none':
             self.name = self.env['ir.sequence'].next_by_code(
                 'purchase.requisition.purchase.tender')
         else:
             self.name = self.env['ir.sequence'].next_by_code(
                 'purchase.requisition.blanket.order')
コード例 #7
0
    def action_create_sale_order(self):
        # if project linked to SO line or at least on tasks with SO line, then we consider project as billable.
        if self.project_id.sale_line_id:
            raise UserError(_("The project is already linked to a sales order item."))

        if self.billable_type == 'employee_rate':
            # at least one line
            if not self.line_ids:
                raise UserError(_("At least one line should be filled."))

            # all employee having timesheet should be in the wizard map
            timesheet_employees = self.env['account.analytic.line'].search([('task_id', 'in', self.project_id.tasks.ids)]).mapped('employee_id')
            map_employees = self.line_ids.mapped('employee_id')
            missing_meployees = timesheet_employees - map_employees
            if missing_meployees:
                raise UserError(_('The Sales Order cannot be created because you did not enter some employees that entered timesheets on this project. Please list all the relevant employees before creating the Sales Order.\nMissing employee(s): %s') % (', '.join(missing_meployees.mapped('name'))))

        # check here if timesheet already linked to SO line
        timesheet_with_so_line = self.env['account.analytic.line'].search_count([('task_id', 'in', self.project_id.tasks.ids), ('so_line', '!=', False)])
        if timesheet_with_so_line:
            raise UserError(_('The sales order cannot be created because some timesheets of this project are already linked to another sales order.'))

        # create SO according to the chosen billable type
        sale_order = self._create_sale_order()

        view_form_id = self.env.ref('sale.view_order_form').id
        action = self.env.ref('sale.action_orders').read()[0]
        action.update({
            'views': [(view_form_id, 'form')],
            'view_mode': 'form',
            'name': sale_order.name,
            'res_id': sale_order.id,
        })
        return action
コード例 #8
0
    def _update_move_lines(self):
        """ update a move line to save the workorder line data"""
        self.ensure_one()
        if self.lot_id:
            move_lines = self.move_id.move_line_ids.filtered(
                lambda ml: ml.lot_id == self.lot_id and not ml.lot_produced_ids
            )
        else:
            move_lines = self.move_id.move_line_ids.filtered(
                lambda ml: not ml.lot_id and not ml.lot_produced_ids)

        # Sanity check: if the product is a serial number and `lot` is already present in the other
        # consumed move lines, raise.
        if self.product_id.tracking != 'none' and not self.lot_id:
            raise UserError(
                _('Please enter a lot or serial number for %s !' %
                  self.product_id.display_name))

        if self.lot_id and self.product_id.tracking == 'serial' and self.lot_id in self.move_id.move_line_ids.filtered(
                lambda ml: ml.qty_done).mapped('lot_id'):
            raise UserError(
                _('You cannot consume the same serial number twice. Please correct the serial numbers encoded.'
                  ))

        # Update reservation and quantity done
        for ml in move_lines:
            rounding = ml.product_uom_id.rounding
            if float_compare(self.qty_done, 0,
                             precision_rounding=rounding) <= 0:
                break
            quantity_to_process = min(self.qty_done,
                                      ml.product_uom_qty - ml.qty_done)
            self.qty_done -= quantity_to_process

            new_quantity_done = (ml.qty_done + quantity_to_process)
            # if we produce less than the reserved quantity to produce the finished products
            # in different lots,
            # we create different component_move_lines to record which one was used
            # on which lot of finished product
            if float_compare(new_quantity_done,
                             ml.product_uom_qty,
                             precision_rounding=rounding) >= 0:
                ml.write({
                    'qty_done': new_quantity_done,
                    'lot_produced_ids': self._get_produced_lots(),
                })
            else:
                new_qty_reserved = ml.product_uom_qty - new_quantity_done
                default = {
                    'product_uom_qty': new_quantity_done,
                    'qty_done': new_quantity_done,
                    'lot_produced_ids': self._get_produced_lots(),
                }
                ml.copy(default=default)
                ml.with_context(bypass_reservation_update=True).write({
                    'product_uom_qty':
                    new_qty_reserved,
                    'qty_done':
                    0
                })
コード例 #9
0
ファイル: ir_model.py プロジェクト: marionumza/saas
 def write(self, vals):
     if self and ('is_mail_thread' in vals or 'is_mail_activity' in vals
                  or 'is_mail_blacklist' in vals):
         if not all(rec.state == 'manual' for rec in self):
             raise UserError(_('Only custom models can be modified.'))
         if 'is_mail_thread' in vals and not all(
                 rec.is_mail_thread <= vals['is_mail_thread']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Thread" cannot be changed to "False".'))
         if 'is_mail_activity' in vals and not all(
                 rec.is_mail_activity <= vals['is_mail_activity']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Activity" cannot be changed to "False".'))
         if 'is_mail_blacklist' in vals and not all(
                 rec.is_mail_blacklist <= vals['is_mail_blacklist']
                 for rec in self):
             raise UserError(
                 _('Field "Mail Blacklist" cannot be changed to "False".'))
         res = super(IrModel, self).write(vals)
         self.flush()
         # setup models; this reloads custom models in registry
         self.pool.setup_models(self._cr)
         # update database schema of models
         models = self.pool.descendants(self.mapped('model'), '_inherits')
         self.pool.init_models(
             self._cr, models, dict(self._context,
                                    update_custom_fields=True))
     else:
         res = super(IrModel, self).write(vals)
     return res
コード例 #10
0
    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_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,
        }
コード例 #11
0
ファイル: product_attribute.py プロジェクト: marionumza/saas
    def write(self, values):
        """Override to:
        - Add constraints to prevent doing changes that are not supported such
            as modifying the template or the attribute of existing lines.
        - Clean up related values and related variants when archiving or when
            updating `value_ids`.
        """
        if 'product_tmpl_id' in values:
            for ptal in self:
                if ptal.product_tmpl_id.id != values['product_tmpl_id']:
                    raise UserError(
                        _("You cannot move the attribute %s from the product %s to the product %s.") %
                        (ptal.attribute_id.display_name, ptal.product_tmpl_id.display_name, values['product_tmpl_id'])
                    )

        if 'attribute_id' in values:
            for ptal in self:
                if ptal.attribute_id.id != values['attribute_id']:
                    raise UserError(
                        _("On the product %s you cannot transform the attribute %s into the attribute %s.") %
                        (ptal.product_tmpl_id.display_name, ptal.attribute_id.display_name, values['attribute_id'])
                    )
        # Remove all values while archiving to make sure the line is clean if it
        # is ever activated again.
        if not values.get('active', True):
            values['value_ids'] = [(5, 0, 0)]
        res = super(ProductTemplateAttributeLine, self).write(values)
        if 'active' in values:
            self.flush()
            self.env['product.template'].invalidate_cache(fnames=['attribute_line_ids'])
        # If coming from `create`, no need to update the values and the variants
        # before all lines are created.
        if self.env.context.get('update_product_template_attribute_values', True):
            self._update_product_template_attribute_values()
        return res
コード例 #12
0
ファイル: google_drive.py プロジェクト: marionumza/saas
 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.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 = _("There is no refresh code set for Google Drive. You can set it up from the configuration panel.")
             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')
コード例 #13
0
 def _portal_post_check_attachments(self, attachment_ids, attachment_tokens):
     if len(attachment_tokens) != len(attachment_ids):
         raise UserError(_("An access token must be provided for each attachment."))
     for (attachment_id, access_token) in zip(attachment_ids, attachment_tokens):
         try:
             CustomerPortal._document_check_access(self, 'ir.attachment', attachment_id, access_token)
         except (AccessError, MissingError):
             raise UserError(_("The attachment %s does not exist or you do not have the rights to access it.") % attachment_id)
コード例 #14
0
    def _find_additional_data(self, currency_code, account_number):
        """ Look for a res.currency and account.journal using values extracted from the
            statement and make sure it's consistent.
        """
        company_currency = self.env.company.currency_id
        journal_obj = self.env['account.journal']
        currency = None
        sanitized_account_number = sanitize_account_number(account_number)

        if currency_code:
            currency = self.env['res.currency'].search(
                [('name', '=ilike', currency_code)], limit=1)
            if not currency:
                raise UserError(
                    _("No currency found matching '%s'.") % currency_code)
            if currency == company_currency:
                currency = False

        journal = journal_obj.browse(self.env.context.get('journal_id', []))
        if account_number:
            # No bank account on the journal : create one from the account number of the statement
            if journal and not journal.bank_account_id:
                journal.set_bank_account(account_number)
            # No journal passed to the wizard : try to find one using the account number of the statement
            elif not journal:
                journal = journal_obj.search([
                    ('bank_account_id.sanitized_acc_number', '=',
                     sanitized_account_number)
                ])
            # Already a bank account on the journal : check it's the same as on the statement
            else:
                if not self._check_journal_bank_account(
                        journal, sanitized_account_number):
                    raise UserError(
                        _('The account of this statement (%s) is not the same as the journal (%s).'
                          ) %
                        (account_number, journal.bank_account_id.acc_number))

        # If importing into an existing journal, its currency must be the same as the bank statement
        if journal:
            journal_currency = journal.currency_id
            if currency is None:
                currency = journal_currency
            if currency and currency != journal_currency:
                statement_cur_code = not currency and company_currency.name or currency.name
                journal_cur_code = not journal_currency and company_currency.name or journal_currency.name
                raise UserError(
                    _('The currency of the bank statement (%s) is not the same as the currency of the journal (%s).'
                      ) % (statement_cur_code, journal_cur_code))

        # If we couldn't find / can't create a journal, everything is lost
        if not journal and not account_number:
            raise UserError(
                _('Cannot find in which journal import this statement. Please manually select a journal.'
                  ))

        return currency, journal
コード例 #15
0
    def done(self):
        self._check_company()
        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 transfers 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 Transfer"),
                   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.')
                            )
                # 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()
        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_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()
        # Change the state only if there is no other action (= wizard) waiting.
        self.write({'state': 'done'})
        return True
コード例 #16
0
    def test_smtp_connection(self):
        for server in self:
            smtp = False
            try:
                smtp = self.connect(mail_server_id=server.id)
                # simulate sending an email from current user's address - without sending it!
                email_from, email_to = self.env.user.email, '*****@*****.**'
                if not email_from:
                    raise UserError(
                        _('Please configure an email on the current user to simulate '
                          'sending an email message via this outgoing server'))
                # Testing the MAIL FROM step should detect sender filter problems
                (code, repl) = smtp.mail(email_from)
                if code != 250:
                    raise UserError(
                        _('The server refused the sender address (%(email_from)s) '
                          'with error %(repl)s') % locals())
                # Testing the RCPT TO step should detect most relaying problems
                (code, repl) = smtp.rcpt(email_to)
                if code not in (250, 251):
                    raise UserError(
                        _('The server refused the test recipient (%(email_to)s) '
                          'with error %(repl)s') % locals())
                # Beginning the DATA step should detect some deferred rejections
                # Can't use self.data() as it would actually send the mail!
                smtp.putcmd("data")
                (code, repl) = smtp.getreply()
                if code != 354:
                    raise UserError(
                        _('The server refused the test connection '
                          'with error %(repl)s') % locals())
            except UserError as e:
                # let UserErrors (messages) bubble up
                raise e
            except Exception as e:
                raise UserError(
                    _("Connection Test Failed! Here is what we got instead:\n %s"
                      ) % ustr(e))
            finally:
                try:
                    if smtp:
                        smtp.close()
                except Exception:
                    # ignored, just a consequence of the previous exception
                    pass

        title = _("Connection Test Succeeded!")
        message = _("Everything seems properly set up!")
        return {
            'type': 'ir.actions.client',
            'tag': 'display_notification',
            'params': {
                'title': title,
                'message': message,
                'sticky': False,
            }
        }
コード例 #17
0
    def _check_approval_update(self, state):
        """ Check if target state is achievable. """
        if self.env.is_superuser():
            return
        current_employee = self.env.user.employee_id
        if not current_employee:
            return
        is_officer = self.env.user.has_group(
            'hr_holidays.group_hr_holidays_user')
        is_manager = self.env.user.has_group(
            'hr_holidays.group_hr_holidays_manager')
        for holiday in self:
            val_type = holiday.holiday_status_id.sudo().validation_type
            if state == 'confirm':
                continue

            if state == 'draft':
                if holiday.employee_id != current_employee and not is_manager:
                    raise UserError(
                        _('Only a time off Manager can reset other people allocation.'
                          ))
                continue

            if not is_officer and self.env.user != holiday.employee_id.leave_manager_id:
                raise UserError(
                    _('Only a time off Officer/Responsible or Manager can approve or refuse time off requests.'
                      ))

            if is_officer or self.env.user == holiday.employee_id.leave_manager_id:
                # use ir.rule based first access check: department, members, ... (see security.xml)
                holiday.check_access_rule('write')

            if holiday.employee_id == current_employee and not is_manager:
                raise UserError(
                    _('Only a time off Manager can approve its own requests.'))

            if (state == 'validate1'
                    and val_type == 'both') or (state == 'validate'
                                                and val_type == 'manager'):
                if self.env.user == holiday.employee_id.leave_manager_id and self.env.user != holiday.employee_id.user_id:
                    continue
                manager = holiday.employee_id.parent_id or holiday.employee_id.department_id.manager_id
                if (manager and manager != current_employee
                    ) and not self.env.user.has_group(
                        'hr_holidays.group_hr_holidays_manager'):
                    raise UserError(
                        _('You must be either %s\'s manager or time off manager to approve this time off'
                          ) % (holiday.employee_id.name))

            if state == 'validate' and val_type == 'both':
                if not self.env.user.has_group(
                        'hr_holidays.group_hr_holidays_manager'):
                    raise UserError(
                        _('Only a Time off Manager can apply the second approval on allocation requests.'
                          ))
コード例 #18
0
 def process_coupon(self):
     """
     Apply the entered coupon code if valid, raise an UserError otherwise.
     """
     sales_order = self.env['sale.order'].browse(
         self.env.context.get('active_id'))
     error_status = self.apply_coupon(sales_order, self.coupon_code)
     if error_status.get('error', False):
         raise UserError(error_status.get('error', False))
     if error_status.get('not_found', False):
         raise UserError(error_status.get('not_found', False))
コード例 #19
0
 def _check_general_rights(self, vals={}):
     post = self.post_id
     if vals.get('post_id'):
         post = self.env['forum.post'].browse(vals.get('post_id'))
     if not self.env.is_admin():
         # own post check
         if self._uid == post.create_uid.id:
             raise UserError(_('It is not allowed to vote for its own post.'))
         # own vote check
         if self._uid != self.user_id.id:
             raise UserError(_('It is not allowed to modify someone else\'s vote.'))
コード例 #20
0
 def button_uninstall(self):
     if 'base' in self.mapped('name'):
         raise UserError(_("The `base` module cannot be uninstalled"))
     if not all(state in ('installed', 'to upgrade')
                for state in self.mapped('state')):
         raise UserError(
             _("One or more of the selected modules have already been uninstalled, if you "
               "believe this to be an error, you may try again later or contact support."
               ))
     deps = self.downstream_dependencies()
     (self + deps).write({'state': 'to remove'})
     return dict(ACTION_DICT, name=_('Uninstall'))
コード例 #21
0
 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 {}
コード例 #22
0
ファイル: event.py プロジェクト: marionumza/saas
 def button_reg_close(self):
     """ Close Registration """
     for registration in self:
         today = fields.Datetime.now()
         if registration.event_id.date_begin <= today and registration.event_id.state == 'confirm':
             registration.write({'state': 'done', 'date_closed': today})
         elif registration.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."
                   ))
コード例 #23
0
 def write(self, vals):
     if 'company_id' in vals:
         for lot in self:
             if lot.company_id.id != vals['company_id']:
                 raise UserError(_("Changing the company of this record is forbidden at this point, you should rather archive it and create a new one."))
     if 'product_id' in vals and any([vals['product_id'] != lot.product_id.id for lot in self]):
         move_lines = self.env['stock.move.line'].search([('lot_id', 'in', self.ids), ('product_id', '!=', vals['product_id'])])
         if move_lines:
             raise UserError(_(
                 'You are not allowed to change the product linked to a serial or lot number ' +
                 'if some stock moves have already been created with that number. ' +
                 'This would lead to inconsistencies in your stock.'
             ))
     return super(ProductionLot, self).write(vals)
コード例 #24
0
    def create_invoices(self):
        sale_orders = self.env['sale.order'].browse(
            self._context.get('active_ids', []))

        if self.advance_payment_method == 'delivered':
            sale_orders._create_invoices(final=self.deduct_down_payments)
        else:
            # Create deposit product if necessary
            if not self.product_id:
                vals = self._prepare_deposit_product()
                self.product_id = self.env['product.product'].create(vals)
                self.env['ir.config_parameter'].sudo().set_param(
                    'sale.default_deposit_product_id', self.product_id.id)

            sale_line_obj = self.env['sale.order.line']
            for order in sale_orders:
                amount, name = self._get_advance_details(order)

                if self.product_id.invoice_policy != 'order':
                    raise UserError(
                        _('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'
                          ))
                if self.product_id.type != 'service':
                    raise UserError(
                        _("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."
                          ))
                taxes = self.product_id.taxes_id.filtered(
                    lambda r: not order.company_id or r.company_id == order.
                    company_id)
                if order.fiscal_position_id and taxes:
                    tax_ids = order.fiscal_position_id.map_tax(
                        taxes, self.product_id, order.partner_shipping_id).ids
                else:
                    tax_ids = taxes.ids
                context = {'lang': order.partner_id.lang}
                analytic_tag_ids = []
                for line in order.order_line:
                    analytic_tag_ids = [
                        (4, analytic_tag.id, None)
                        for analytic_tag in line.analytic_tag_ids
                    ]

                so_line_values = self._prepare_so_line(order, analytic_tag_ids,
                                                       tax_ids, amount)
                so_line = sale_line_obj.create(so_line_values)
                del context
                self._create_invoice(order, so_line, amount)
        if self._context.get('open_invoices', False):
            return sale_orders.action_view_invoice()
        return {'type': 'ir.actions.act_window_close'}
コード例 #25
0
    def _svl_empty_stock_am(self, stock_valuation_layers):
        move_vals_list = []
        product_accounts = {
            product.id: product.product_tmpl_id.get_product_accounts()
            for product in stock_valuation_layers.mapped('product_id')
        }
        for out_stock_valuation_layer in stock_valuation_layers:
            product = out_stock_valuation_layer.product_id
            expense_account = product.property_account_expense_id or product.categ_id.property_account_expense_categ_id
            if not expense_account:
                raise UserError(
                    _('Please define an expense account for this product: "%s" (id:%d) - or for its category: "%s".'
                      ) % (product.name, product.id, self.name))
            if not product_accounts[product.id].get('stock_valuation'):
                raise UserError(
                    _('You don\'t have any stock valuation account defined on your product category. You must define one before processing this operation.'
                      ))

            debit_account_id = expense_account.id
            credit_account_id = product_accounts[
                product.id]['stock_valuation'].id
            value = out_stock_valuation_layer.value
            move_vals = {
                'journal_id':
                product_accounts[product.id]['stock_journal'].id,
                'company_id':
                self.env.company.id,
                'ref':
                product.default_code,
                'stock_valuation_layer_ids':
                [(6, None, [out_stock_valuation_layer.id])],
                'line_ids': [(0, 0, {
                    'name': out_stock_valuation_layer.description,
                    'account_id': debit_account_id,
                    'debit': abs(value),
                    'credit': 0,
                    'product_id': product.id,
                }),
                             (0, 0, {
                                 'name': out_stock_valuation_layer.description,
                                 'account_id': credit_account_id,
                                 'debit': 0,
                                 'credit': abs(value),
                                 'product_id': product.id,
                             })],
                'type':
                'entry',
            }
            move_vals_list.append(move_vals)
        return move_vals_list
コード例 #26
0
 def write(self, values):
     if 'production_id' in values:
         raise UserError(
             _('You cannot link this work order to another manufacturing order.'
               ))
     if 'workcenter_id' in values:
         for workorder in self:
             if workorder.workcenter_id.id != values['workcenter_id']:
                 if workorder.state in ('progress', 'done', 'cancel'):
                     raise UserError(
                         _('You cannot change the workcenter of a work order that is in progress or done.'
                           ))
                 workorder.leave_id.resource_id = self.env[
                     'mrp.workcenter'].browse(
                         values['workcenter_id']).resource_id
     if list(values.keys()) != ['time_ids'] and any(
             workorder.state == 'done' for workorder in self):
         raise UserError(_('You can not change the finished work order.'))
     if 'date_planned_start' in values or 'date_planned_finished' in values:
         for workorder in self:
             start_date = fields.Datetime.to_datetime(
                 values.get(
                     'date_planned_start')) or workorder.date_planned_start
             end_date = fields.Datetime.to_datetime(
                 values.get('date_planned_finished')
             ) or workorder.date_planned_finished
             if start_date and end_date and start_date > end_date:
                 raise UserError(
                     _('The planned end date of the work order cannot be prior to the planned start date, please correct this to save the work order.'
                       ))
             # Update MO dates if the start date of the first WO or the
             # finished date of the last WO is update.
             if workorder == workorder.production_id.workorder_ids[
                     0] and 'date_planned_start' in values:
                 workorder.production_id.with_context(
                     force_date=True).write({
                         'date_planned_start':
                         fields.Datetime.to_datetime(
                             values['date_planned_start'])
                     })
             if workorder == workorder.production_id.workorder_ids[
                     -1] and 'date_planned_finished' in values:
                 workorder.production_id.with_context(
                     force_date=True).write({
                         'date_planned_finished':
                         fields.Datetime.to_datetime(
                             values['date_planned_finished'])
                     })
     return super(MrpWorkorder, self).write(values)
コード例 #27
0
    def _svl_replenish_stock_am(self, stock_valuation_layers):
        move_vals_list = []
        product_accounts = {
            product.id: product.product_tmpl_id.get_product_accounts()
            for product in stock_valuation_layers.mapped('product_id')
        }
        for out_stock_valuation_layer in stock_valuation_layers:
            product = out_stock_valuation_layer.product_id
            if not product_accounts[product.id].get('stock_input'):
                raise UserError(
                    _('You don\'t have any input valuation account defined on your product category. You must define one before processing this operation.'
                      ))
            if not product_accounts[product.id].get('stock_valuation'):
                raise UserError(
                    _('You don\'t have any stock valuation account defined on your product category. You must define one before processing this operation.'
                      ))

            debit_account_id = product_accounts[
                product.id]['stock_valuation'].id
            credit_account_id = product_accounts[product.id]['stock_input'].id
            value = out_stock_valuation_layer.value
            move_vals = {
                'journal_id':
                product_accounts[product.id]['stock_journal'].id,
                'company_id':
                self.env.company.id,
                'ref':
                product.default_code,
                'stock_valuation_layer_ids':
                [(6, None, [out_stock_valuation_layer.id])],
                'line_ids': [(0, 0, {
                    'name': out_stock_valuation_layer.description,
                    'account_id': debit_account_id,
                    'debit': abs(value),
                    'credit': 0,
                    'product_id': product.id,
                }),
                             (0, 0, {
                                 'name': out_stock_valuation_layer.description,
                                 'account_id': credit_account_id,
                                 'debit': 0,
                                 'credit': abs(value),
                                 'product_id': product.id,
                             })],
                'type':
                'entry',
            }
            move_vals_list.append(move_vals)
        return move_vals_list
コード例 #28
0
    def default_get(self, fields):
        result = super(ProjectCreateSalesOrder, self).default_get(fields)

        active_model = self._context.get('active_model')
        if active_model != 'project.project':
            raise UserError(_("You can only apply this action from a project."))

        active_id = self._context.get('active_id')
        if 'project_id' in fields and active_id:
            project = self.env['project.project'].browse(active_id)
            if project.billable_type != 'no':
                raise UserError(_("The project is already billable."))
            result['project_id'] = active_id
            result['partner_id'] = project.partner_id.id
        return result
コード例 #29
0
    def button_start(self):
        self.ensure_one()
        # As button_start is automatically called in the new view
        if self.state in ('done', 'cancel'):
            return True

        # Need a loss in case of the real time exceeding the expected
        timeline = self.env['mrp.workcenter.productivity']
        if self.duration < self.duration_expected:
            loss_id = self.env['mrp.workcenter.productivity.loss'].search(
                [('loss_type', '=', 'productive')], limit=1)
            if not len(loss_id):
                raise UserError(
                    _("You need to define at least one productivity loss in the category 'Productivity'. Create one from the Manufacturing app, menu: Configuration / Productivity Losses."
                      ))
        else:
            loss_id = self.env['mrp.workcenter.productivity.loss'].search(
                [('loss_type', '=', 'performance')], limit=1)
            if not len(loss_id):
                raise UserError(
                    _("You need to define at least one productivity loss in the category 'Performance'. Create one from the Manufacturing app, menu: Configuration / Productivity Losses."
                      ))
        if self.production_id.state != 'progress':
            self.production_id.write({
                'date_start': datetime.now(),
            })
        timeline.create({
            'workorder_id': self.id,
            'workcenter_id': self.workcenter_id.id,
            'description': _('Time Tracking: ') + self.env.user.name,
            'loss_id': loss_id[0].id,
            'date_start': datetime.now(),
            'user_id':
            self.env.user.id,  # FIXME sle: can be inconsistent with company_id
            'company_id': self.company_id.id,
        })
        if self.state == 'progress':
            return True
        else:
            start_date = datetime.now()
            vals = {
                'state': 'progress',
                'date_start': start_date,
                'date_planned_start': start_date,
            }
            if self.date_planned_finished < start_date:
                vals['date_planned_finished'] = start_date
            return self.write(vals)
コード例 #30
0
def _check_with_xsd(tree_or_str, stream, env=None):
    """Check an XML against an XSD schema.

    This will raise a UserError if the XML file is not valid according to the
    XSD file.
    :param tree_or_str (etree, str): representation of the tree to be checked
    :param stream (io.IOBase, str): the byte stream used to build the XSD schema.
        If env is given, it can also be the name of an attachment in the filestore
    :param env (harpiya.api.Environment): If it is given, it enables resolving the
        imports of the schema in the filestore with ir.attachments.
    """
    if not isinstance(tree_or_str, etree._Element):
        tree_or_str = etree.fromstring(tree_or_str)
    parser = etree.XMLParser()
    if env:
        parser.resolvers.add(harpiya_resolver(env))
        if isinstance(stream, str) and stream.endswith('.xsd'):
            attachment = env['ir.attachment'].search([('name', '=', stream)])
            if not attachment:
                raise FileNotFoundError()
            stream = BytesIO(base64.b64decode(attachment.datas))
    xsd_schema = etree.XMLSchema(etree.parse(stream, parser=parser))
    try:
        xsd_schema.assertValid(tree_or_str)
    except etree.DocumentInvalid as xml_errors:
        raise UserError('\n'.join(str(e) for e in xml_errors.error_log))