コード例 #1
0
 def unlink(self):
     projects = self.env['project.project'].search([('analytic_account_id',
                                                     'in', self.ids)])
     has_tasks = self.env['project.task'].search_count([('project_id', 'in',
                                                         projects.ids)])
     if has_tasks:
         raise UserError(
             _('Please remove existing tasks in the project linked to the accounts you want to delete.'
               ))
     return super(AccountAnalyticAccount, self).unlink()
コード例 #2
0
    def _check_dates(self):
        '''
        Check interleaving between fiscal years.
        There are 3 cases to consider:

        s1   s2   e1   e2
        (    [----)----]

        s2   s1   e2   e1
        [----(----]    )

        s1   s2   e2   e1
        (    [----]    )
        '''
        for fy in self:
            # Starting date must be prior to the ending date
            date_from = fy.date_from
            date_to = fy.date_to
            if date_to < date_from:
                raise ValidationError(
                    _('The ending date must not be prior to the starting date.'
                      ))

            domain = [
                ('id', '!=', fy.id),
                ('company_id', '=', fy.company_id.id),
                '|',
                '|',
                '&',
                ('date_from', '<=', fy.date_from),
                ('date_to', '>=', fy.date_from),
                '&',
                ('date_from', '<=', fy.date_to),
                ('date_to', '>=', fy.date_to),
                '&',
                ('date_from', '<=', fy.date_from),
                ('date_to', '>=', fy.date_to),
            ]

            if self.search_count(domain) > 0:
                raise ValidationError(
                    _('You can not have an overlap between two fiscal years, please correct the start and/or end dates of your fiscal years.'
                      ))
コード例 #3
0
 def assign_responsible(self):
     self.ensure_one()
     pickings = self.env['stock.picking'].browse(
         self.env.context.get('active_ids'))
     restricted_companies = pickings.company_id - self.user_id.company_ids
     if restricted_companies:
         raise UserError(
             _('%s has a restricted access to %s') %
             (self.user_id.name, restricted_companies.mapped('name')))
     pickings.write({'user_id': self.user_id.id})
コード例 #4
0
 def _check_main_currency_rounding(self):
     if any(precision.name == 'Account'
            and tools.float_compare(self.env.company.currency_id.rounding,
                                    10**-precision.digits,
                                    precision_digits=6) == -1
            for precision in self):
         raise ValidationError(
             _("You cannot define the decimal precision of 'Account' as greater than the rounding factor of the company's main currency"
               ))
     return True
コード例 #5
0
 def blacklist_remove(self, mailing_id, res_id, email, token):
     if not self._valid_unsubscribe_token(mailing_id, res_id, email, token):
         return 'unauthorized'
     if email:
         blacklist_rec = request.env['mail.blacklist'].sudo()._remove(email)
         self._log_blacklist_action(
             blacklist_rec, mailing_id,
             _("""Requested de-blacklisting via unsubscription page."""))
         return True
     return 'error'
コード例 #6
0
ファイル: resource.py プロジェクト: marionumza/saas
 def _check_attendance_ids(self):
     for resource in self:
         if (resource.two_weeks_calendar
                 and resource.attendance_ids.filtered(
                     lambda a: a.display_type == 'line_section')
                 and not resource.attendance_ids.sorted(
                     'sequence')[0].display_type):
             raise ValidationError(
                 _("In a calendar with 2 weeks mode, all periods need to be in the sections."
                   ))
コード例 #7
0
ファイル: stock_quant.py プロジェクト: marionumza/saas
 def check_quantity(self):
     for quant in self:
         if float_compare(
                 quant.quantity,
                 1,
                 precision_rounding=quant.product_uom_id.rounding
         ) > 0 and quant.lot_id and quant.product_id.tracking == 'serial':
             raise ValidationError(
                 _('A serial number should only be linked to a single product.'
                   ))
コード例 #8
0
ファイル: stock_inventory.py プロジェクト: marionumza/saas
 def _check_product_id(self):
     """ As no quants are created for consumable products, it should not be possible do adjust
     their quantity.
     """
     for line in self:
         if line.product_id.type != 'product':
             raise ValidationError(
                 _("You can only adjust storable products.") +
                 '\n\n%s -> %s' %
                 (line.product_id.display_name, line.product_id.type))
コード例 #9
0
ファイル: stock_inventory.py プロジェクト: marionumza/saas
 def action_validate(self):
     if not self.exists():
         return
     self.ensure_one()
     if not self.user_has_groups('stock.group_stock_manager'):
         raise UserError(
             _("Only a stock manager can validate an inventory adjustment.")
         )
     if self.state != 'confirm':
         raise UserError(
             _("You can't validate the inventory '%s', maybe this inventory "
               + "has been already validated or isn't ready.") %
             (self.name))
     inventory_lines = self.line_ids.filtered(
         lambda l: l.product_id.tracking in ['lot', 'serial'] and not l.
         prod_lot_id and l.theoretical_qty != l.product_qty)
     lines = self.line_ids.filtered(lambda l: float_compare(
         l.product_qty, 1, precision_rounding=l.product_uom_id.rounding
     ) > 0 and l.product_id.tracking == 'serial' and l.prod_lot_id)
     if inventory_lines and not lines:
         wiz_lines = [(0, 0, {
             'product_id': product.id,
             'tracking': product.tracking
         }) for product in inventory_lines.mapped('product_id')]
         wiz = self.env['stock.track.confirmation'].create({
             'inventory_id':
             self.id,
             'tracking_line_ids':
             wiz_lines
         })
         return {
             'name': _('Tracked Products in Inventory Adjustment'),
             'type': 'ir.actions.act_window',
             'view_mode': 'form',
             'views': [(False, 'form')],
             'res_model': 'stock.track.confirmation',
             'target': 'new',
             'res_id': wiz.id,
         }
     self._action_done()
     self.line_ids._check_company()
     self._check_company()
     return True
コード例 #10
0
 def poll(self, channels, last, options=None):
     if options is None:
         options = {}
     if not dispatch:
         raise Exception("bus.Bus unavailable")
     if [c for c in channels if not isinstance(c, str)]:
         raise Exception("bus.Bus only string channels are allowed.")
     if request.registry.in_test_mode():
         raise exceptions.UserError(_("bus.Bus not available in test mode"))
     return self._poll(request.db, channels, last, options)
コード例 #11
0
    def _purchase_service_create(self, quantity=False):
        """ On Sales Order confirmation, some lines (services ones) can create a purchase order line and maybe a purchase order.
            If a line should create a RFQ, it will check for existing PO. If no one is find, the SO line will create one, then adds
            a new PO line. The created purchase order line will be linked to the SO line.
            :param quantity: the quantity to force on the PO line, expressed in SO line UoM
        """
        PurchaseOrder = self.env['purchase.order']
        supplier_po_map = {}
        sale_line_purchase_map = {}
        for line in self:
            line = line.with_context(force_company=line.company_id.id)
            # determine vendor of the order (take the first matching company and product)
            suppliers = line.product_id.with_context(
                force_company=line.company_id.id)._select_seller(
                    quantity=line.product_uom_qty, uom_id=line.product_uom)
            if not suppliers:
                raise UserError(
                    _("There is no vendor associated to the product %s. Please define a vendor for this product."
                      ) % (line.product_id.display_name, ))
            supplierinfo = suppliers[0]
            partner_supplier = supplierinfo.name  # yes, this field is not explicit .... it is a res.partner !

            # determine (or create) PO
            purchase_order = supplier_po_map.get(partner_supplier.id)
            if not purchase_order:
                purchase_order = PurchaseOrder.search([
                    ('partner_id', '=', partner_supplier.id),
                    ('state', '=', 'draft'),
                    ('company_id', '=', line.company_id.id),
                ],
                                                      limit=1)
            if not purchase_order:
                values = line._purchase_service_prepare_order_values(
                    supplierinfo)
                purchase_order = PurchaseOrder.create(values)
            else:  # update origin of existing PO
                so_name = line.order_id.name
                origins = []
                if purchase_order.origin:
                    origins = purchase_order.origin.split(', ') + origins
                if so_name not in origins:
                    origins += [so_name]
                    purchase_order.write({'origin': ', '.join(origins)})
            supplier_po_map[partner_supplier.id] = purchase_order

            # add a PO line to the PO
            values = line._purchase_service_prepare_line_values(
                purchase_order, quantity=quantity)
            purchase_line = line.env['purchase.order.line'].create(values)

            # link the generated purchase to the SO line
            sale_line_purchase_map.setdefault(line,
                                              line.env['purchase.order.line'])
            sale_line_purchase_map[line] |= purchase_line
        return sale_line_purchase_map
コード例 #12
0
ファイル: purchase.py プロジェクト: marionumza/saas
    def _create_or_update_picking(self):
        for line in self:
            if line.product_id and line.product_id.type in ('product',
                                                            'consu'):
                # Prevent decreasing below received quantity
                if float_compare(line.product_qty, line.qty_received,
                                 line.product_uom.rounding) < 0:
                    raise UserError(
                        _('You cannot decrease the ordered quantity below the received quantity.\n'
                          'Create a return first.'))

                if float_compare(line.product_qty, line.qty_invoiced,
                                 line.product_uom.rounding) == -1:
                    # If the quantity is now below the invoiced quantity, create an activity on the vendor bill
                    # inviting the user to create a refund.
                    activity = self.env['mail.activity'].sudo().create({
                        'activity_type_id':
                        self.env.ref('mail.mail_activity_data_warning').id,
                        'note':
                        _('The quantities on your purchase order indicate less than billed. You should ask for a refund. '
                          ),
                        'res_id':
                        line.invoice_lines[0].move_id.id,
                        'res_model_id':
                        self.env.ref('account.model_account_move').id,
                    })
                    activity._onchange_activity_type_id()

                # If the user increased quantity of existing line or created a new line
                pickings = line.order_id.picking_ids.filtered(
                    lambda x: x.state not in ('done', 'cancel') and x.
                    location_dest_id.usage in ('internal', 'transit'))
                picking = pickings and pickings[0] or False
                if not picking:
                    res = line.order_id._prepare_picking()
                    picking = self.env['stock.picking'].create(res)
                move_vals = line._prepare_stock_moves(picking)
                for move_val in move_vals:
                    self.env['stock.move']\
                        .create(move_val)\
                        ._action_confirm()\
                        ._action_assign()
コード例 #13
0
    def web_auth_signup(self, *args, **kw):
        qcontext = self.get_auth_signup_qcontext()

        if not qcontext.get('token') and not qcontext.get('signup_enabled'):
            raise werkzeug.exceptions.NotFound()

        if 'error' not in qcontext and request.httprequest.method == 'POST':
            try:
                self.do_signup(qcontext)
                # Send an account creation confirmation email
                if qcontext.get('token'):
                    User = request.env['res.users']
                    user_sudo = User.sudo().search(
                        User._get_login_domain(qcontext.get('login')),
                        order=User._get_login_order(),
                        limit=1)
                    template = request.env.ref(
                        'auth_signup.mail_template_user_signup_account_created',
                        raise_if_not_found=False)
                    if user_sudo and template:
                        template.sudo().with_context(
                            lang=user_sudo.lang,
                            auth_login=werkzeug.url_encode(
                                {'auth_login': user_sudo.email}),
                        ).send_mail(user_sudo.id, force_send=True)
                return self.web_login(*args, **kw)
            except UserError as e:
                qcontext['error'] = e.name or e.value
            except (SignupError, AssertionError) as e:
                if request.env["res.users"].sudo().search([
                    ("login", "=", qcontext.get("login"))
                ]):
                    qcontext["error"] = _(
                        "Another user is already registered using this email address."
                    )
                else:
                    _logger.error("%s", e)
                    qcontext['error'] = _("Could not create a new account.")

        response = request.render('auth_signup.signup', qcontext)
        response.headers['X-Frame-Options'] = 'DENY'
        return response
コード例 #14
0
    def convert_comment_to_answer(self, message_id, default=None):
        """ Tool to convert a comment (mail.message) into an answer (forum.post).
        The original comment is unlinked and a new answer from the comment's author
        is created. Nothing is done if the comment's author already answered the
        question. """
        comment = self.env['mail.message'].sudo().browse(message_id)
        post = self.browse(comment.res_id)
        if not comment.author_id or not comment.author_id.user_ids:  # only comment posted by users can be converted
            return False

        # karma-based action check: must check the message's author to know if own / all
        is_author = comment.author_id.id == self.env.user.partner_id.id
        karma_own = post.forum_id.karma_comment_convert_own
        karma_all = post.forum_id.karma_comment_convert_all
        karma_convert = is_author and karma_own or karma_all
        can_convert = self.env.user.karma >= karma_convert
        if not can_convert:
            if is_author and karma_own < karma_all:
                raise AccessError(_('%d karma required to convert your comment to an answer.') % karma_own)
            else:
                raise AccessError(_('%d karma required to convert a comment to an answer.') % karma_all)

        # check the message's author has not already an answer
        question = post.parent_id if post.parent_id else post
        post_create_uid = comment.author_id.user_ids[0]
        if any(answer.create_uid.id == post_create_uid.id for answer in question.child_ids):
            return False

        # create the new post
        post_values = {
            'forum_id': question.forum_id.id,
            'content': comment.body,
            'parent_id': question.id,
            'name': _('Re: %s') % (question.name or ''),
        }
        # done with the author user to have create_uid correctly set
        new_post = self.with_user(post_create_uid).create(post_values)

        # delete comment
        comment.unlink()

        return new_post
コード例 #15
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,
            }
        }
コード例 #16
0
ファイル: slider.py プロジェクト: marionumza/saas
 def create(self, vals_list):
     """
     If it is product slider then slider_filter_ids is required else raise warning
     :param vals_list:
     :return:
     """
     res = super(Slider, self).create(vals_list)
     if not res.slider_filter_ids:
         raise UserError(_('Sorry! Please set product filters first'))
     else:
         return res
コード例 #17
0
 def write(self, values):
     if values.get('publisher_comment'):
         if not self.env.user.has_group("website.group_website_publisher"):
             raise exceptions.AccessError(
                 _("Only the publisher of the website can change the rating comment"
                   ))
         if not values.get('publisher_datetime'):
             values['publisher_datetime'] = fields.Datetime.now()
         if not values.get('publisher_id'):
             values['publisher_id'] = self.env.user.partner_id.id
     return super(Rating, self).write(values)
コード例 #18
0
ファイル: survey_invite.py プロジェクト: marionumza/saas
 def _onchange_partner_ids(self):
     if self.survey_users_login_required and self.partner_ids:
         if not self.survey_id.users_can_signup:
             invalid_partners = self.env['res.partner'].search([
                 ('user_ids', '=', False),
                 ('id', 'in', self.partner_ids.ids)
             ])
             if invalid_partners:
                 raise UserError(
                     _('The following recipients have no user account: %s. You should create user accounts for them or allow external signup in configuration.' %
                         (','.join(invalid_partners.mapped('name')))))
コード例 #19
0
 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)
     if self.env.context.get('active_id') and self.env.context.get(
             'active_model') == 'stock.picking':
         picking = self.env['stock.picking'].browse(
             self.env.context.get('active_id'))
         if picking.exists():
             res.update({'picking_id': picking.id})
     return res
コード例 #20
0
ファイル: mailing_mailing.py プロジェクト: marionumza/saas
    def action_send_sms(self, res_ids=None):
        for mailing in self:
            if not res_ids:
                res_ids = mailing._get_remaining_recipients()
            if not res_ids:
                raise UserError(_('There are no recipients selected.'))

            composer = self.env['sms.composer'].with_context(active_id=False).create(mailing._send_sms_get_composer_values(res_ids))
            composer._action_send_sms()
            mailing.write({'state': 'done', 'sent_date': fields.Datetime.now()})
        return True
コード例 #21
0
ファイル: digest.py プロジェクト: marionumza/saas
 def _compute_project_task_opened_value(self):
     if not self.env.user.has_group('project.group_project_user'):
         raise AccessError(_("Do not have access, skip this data for user's digest email"))
     for record in self:
         start, end, company = record._get_kpi_compute_parameters()
         record.kpi_project_task_opened_value = self.env['project.task'].search_count([
             ('stage_id.fold', '=', False),
             ('create_date', '>=', start),
             ('create_date', '<', end),
             ('company_id', '=', company.id)
         ])
コード例 #22
0
 def _get_sequence_values(self):
     sequence_values = super(Warehouse, self)._get_sequence_values()
     sequence_values.update({
         'pos_type_id': {
             'name': self.name + ' ' + _('Picking POS'),
             'prefix': self.code + '/POS/',
             'padding': 5,
             'company_id': self.company_id.id,
         }
     })
     return sequence_values
コード例 #23
0
ファイル: mailing.py プロジェクト: marionumza/saas
    def action_send_mail(self, res_ids=None):
        author_id = self.env.user.partner_id.id

        for mailing in self:
            if not res_ids:
                res_ids = mailing._get_remaining_recipients()
            if not res_ids:
                raise UserError(_('There are no recipients selected.'))

            composer_values = {
                'author_id':
                author_id,
                'attachment_ids':
                [(4, attachment.id) for attachment in mailing.attachment_ids],
                'body':
                mailing.body_html,
                'subject':
                mailing.subject,
                'model':
                mailing.mailing_model_real,
                'email_from':
                mailing.email_from,
                'record_name':
                False,
                'composition_mode':
                'mass_mail',
                'mass_mailing_id':
                mailing.id,
                'mailing_list_ids':
                [(4, l.id) for l in mailing.contact_list_ids],
                'no_auto_thread':
                mailing.reply_to_mode != 'thread',
                'template_id':
                None,
                'mail_server_id':
                mailing.mail_server_id.id,
            }
            if mailing.reply_to_mode == 'email':
                composer_values['reply_to'] = mailing.reply_to

            composer = self.env['mail.compose.message'].with_context(
                active_ids=res_ids).create(composer_values)
            extra_context = self._get_mass_mailing_context()
            composer = composer.with_context(active_ids=res_ids,
                                             **extra_context)
            # auto-commit except in testing mode
            auto_commit = not getattr(threading.currentThread(), 'testing',
                                      False)
            composer.send_mail(auto_commit=auto_commit)
            mailing.write({
                'state': 'done',
                'sent_date': fields.Datetime.now()
            })
        return True
コード例 #24
0
ファイル: mailing.py プロジェクト: marionumza/saas
 def action_test(self):
     self.ensure_one()
     ctx = dict(self.env.context, default_mass_mailing_id=self.id)
     return {
         'name': _('Test Mailing'),
         'type': 'ir.actions.act_window',
         'view_mode': 'form',
         'res_model': 'mailing.mailing.test',
         'target': 'new',
         'context': ctx,
     }
コード例 #25
0
ファイル: badge.py プロジェクト: marionumza/saas
    def check_granting(self):
        """Check the user 'uid' can grant the badge 'badge_id' and raise the appropriate exception
        if not

        Do not check for SUPERUSER_ID
        """
        status_code = self._can_grant_badge()
        if status_code == self.CAN_GRANT:
            return True
        elif status_code == self.NOBODY_CAN_GRANT:
            raise exceptions.UserError(_('This badge can not be sent by users.'))
        elif status_code == self.USER_NOT_VIP:
            raise exceptions.UserError(_('You are not in the user allowed list.'))
        elif status_code == self.BADGE_REQUIRED:
            raise exceptions.UserError(_('You do not have the required badges.'))
        elif status_code == self.TOO_MANY:
            raise exceptions.UserError(_('You have already sent this badge too many time this month.'))
        else:
            _logger.error("Unknown badge status code: %s" % status_code)
        return False
コード例 #26
0
 def _compute_kpi_crm_lead_created_value(self):
     if not self.env.user.has_group('sales_team.group_sale_salesman'):
         raise AccessError(
             _("Do not have access, skip this data for user's digest email")
         )
     for record in self:
         start, end, company = record._get_kpi_compute_parameters()
         record.kpi_crm_lead_created_value = self.env[
             'crm.lead'].search_count([('create_date', '>=', start),
                                       ('create_date', '<', end),
                                       ('company_id', '=', company.id)])
コード例 #27
0
 def button_done(self):
     if any([x.state in ('done', 'cancel') for x in self]):
         raise UserError(
             _('A Manufacturing Order is already done or cancelled.'))
     self.end_all()
     end_date = datetime.now()
     return self.write({
         'state': 'done',
         'date_finished': end_date,
         'date_planned_finished': end_date,
     })
コード例 #28
0
    def default_get(self, fields):
        result = super(Opportunity2Quotation, self).default_get(fields)

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

        active_id = self._context.get('active_id')
        if 'lead_id' in fields and active_id:
            result['lead_id'] = active_id
        return result
コード例 #29
0
ファイル: product_attribute.py プロジェクト: marionumza/saas
 def write(self, values):
     if 'ptav_product_variant_ids' in values:
         # Force write on this relation from `product.product` to properly
         # trigger `_compute_combination_indices`.
         raise UserError(_("You cannot update related variants from the values. Please update related values from the variants."))
     pav_in_values = 'product_attribute_value_id' in values
     product_in_values = 'product_tmpl_id' in values
     if pav_in_values or product_in_values:
         for ptav in self:
             if pav_in_values and ptav.product_attribute_value_id.id != values['product_attribute_value_id']:
                 raise UserError(
                     _("You cannot change the value of the value %s set on product %s.") %
                     (ptav.display_name, ptav.product_tmpl_id.display_name)
                 )
             if product_in_values and ptav.product_tmpl_id.id != values['product_tmpl_id']:
                 raise UserError(
                     _("You cannot change the product of the value %s set on product %s.") %
                     (ptav.display_name, ptav.product_tmpl_id.display_name)
                 )
     return super(ProductTemplateAttributeValue, self).write(values)
コード例 #30
0
 def launch_payment(self):
     return {
         'name': _('Payment'),
         'view_mode': 'form',
         'res_model': 'pos.make.payment',
         'view_id': False,
         'target': 'new',
         'views': False,
         'type': 'ir.actions.act_window',
         'context': self.env.context,
     }