Example #1
0
    def create_action(self):
        ActWindow = self.env['ir.actions.act_window']
        view = self.env.ref('mail.email_compose_message_wizard_form')

        for template in self:
            button_name = _('Send Mail (%s)') % template.name
            action = ActWindow.create({
                'name': button_name,
                'type': 'ir.actions.act_window',
                'res_model': 'mail.compose.message',
                'src_model': template.model_id.model,
                'view_type': 'form',
                'context': "{'default_composition_mode': 'mass_mail', 'default_template_id' : %d, 'default_use_template': True}" % (template.id),
                'view_mode': 'form,tree',
                'view_id': view.id,
                'target': 'new',
                'binding_model_id': template.model_id.id,
            })
            template.write({'ref_ir_act_window': action.id})

        return True
Example #2
0
    def value_to_html(self, value, options):
        display_currency = options['display_currency']

        if not isinstance(value, (int, float)):
            raise ValueError(
                _("The value send to monetary field is not a number."))

        # lang.format mandates a sprintf-style format. These formats are non-
        # minimal (they have a default fixed precision instead), and
        # lang.format will not set one by default. currency.round will not
        # provide one either. So we need to generate a precision value
        # (integer > 0) from the currency's rounding (a float generally < 1.0).
        fmt = "%.{0}f".format(display_currency.decimal_places)

        if options.get('from_currency'):
            date = options.get('date') or fields.Date.today()
            company_id = options.get('company_id')
            if company_id:
                company = self.env['res.company'].browse(company_id)
            else:
                company = self.env.user.company_id
            value = options['from_currency']._convert(value, display_currency,
                                                      company, date)

        lang = self.user_lang()
        formatted_amount = lang.format(
            fmt, display_currency.round(value), grouping=True,
            monetary=True).replace(r' ', u'\N{NO-BREAK SPACE}').replace(
                r'-', u'-\N{ZERO WIDTH NO-BREAK SPACE}')

        pre = post = u''
        if display_currency.position == 'before':
            pre = u'{symbol}\N{NO-BREAK SPACE}'.format(
                symbol=display_currency.symbol or '')
        else:
            post = u'\N{NO-BREAK SPACE}{symbol}'.format(
                symbol=display_currency.symbol or '')

        return u'{pre}<span class="oe_currency_value">{0}</span>{post}'.format(
            formatted_amount, pre=pre, post=post)
Example #3
0
 def _get_error_message(self, error):
     if error == 'CREDIT_ERROR':
         link = self.env['iap.account'].get_credits_url(service_name='snailmail')
         return _('You don\'t have enough credits to perform this operation.<br>Please go to your <a href=%s target="new">iap account</a>.') % link
     if error == 'TRIAL_ERROR':
         link = self.env['iap.account'].get_credits_url(service_name='snailmail', trial=True)
         return _('You don\'t have an IAP account registered for this service.<br>Please go to <a href=%s target="new">iap.swerp.it</a> to claim your free credits.') % link
     if error == 'NO_PRICE_AVAILABLE':
         return _('The country of the partner is not covered by Snailmail.')
     if error == 'MISSING_REQUIRED_FIELDS':
         return _('One or more required fields are empty.')
     if error == 'FORMAT_ERROR':
         return _('The attachment of the letter could not be sent. Please check its content and contact the support if the problem persists.')
     else:
         return _('An unknown error happened. Please contact the support.')
     return error
Example #4
0
 def action_validate(self):
     self.ensure_one()
     precision = self.env['decimal.precision'].precision_get(
         'Product Unit of Measure')
     available_qty_owner = self.env['stock.quant']._get_available_quantity(
         self.product_id,
         self.location_id,
         self.lot_id,
         owner_id=self.partner_id,
         strict=True)
     available_qty_noown = self.env['stock.quant']._get_available_quantity(
         self.product_id, self.location_id, self.lot_id, strict=True)
     for available_qty in [available_qty_owner, available_qty_noown]:
         if float_compare(available_qty,
                          self.product_qty,
                          precision_digits=precision) >= 0:
             return self.action_repair_confirm()
     else:
         return {
             'name':
             _('Insufficient Quantity'),
             'view_type':
             'form',
             'view_mode':
             'form',
             'res_model':
             'stock.warn.insufficient.qty.repair',
             'view_id':
             self.env.ref(
                 'repair.stock_warn_insufficient_qty_repair_form_view').id,
             'type':
             'ir.actions.act_window',
             'context': {
                 'default_product_id': self.product_id.id,
                 'default_location_id': self.location_id.id,
                 'default_repair_id': self.id
             },
             'target':
             'new'
         }
Example #5
0
class MrpRouting(models.Model):
    """ Specifies routings of work centers """
    _name = 'mrp.routing'
    _description = 'Routings'

    name = fields.Char('Routing', required=True)
    active = fields.Boolean(
        'Active',
        default=True,
        help=
        "If the active field is set to False, it will allow you to hide the routing without removing it."
    )
    code = fields.Char('Reference',
                       copy=False,
                       default=lambda self: _('New'),
                       readonly=True)
    note = fields.Text('Description')
    operation_ids = fields.One2many('mrp.routing.workcenter',
                                    'routing_id',
                                    'Operations',
                                    copy=True,
                                    oldname='workcenter_lines')
    location_id = fields.Many2one(
        'stock.location',
        'Raw Materials Location',
        help=
        "Keep empty if you produce at the location where you find the raw materials. "
        "Set a location if you produce at a fixed location. This can be a partner location "
        "if you subcontract the manufacturing operations.")
    company_id = fields.Many2one('res.company',
                                 'Company',
                                 default=lambda self: self.env['res.company'].
                                 _company_default_get('mrp.routing'))

    @api.model
    def create(self, vals):
        if 'code' not in vals or vals['code'] == _('New'):
            vals['code'] = self.env['ir.sequence'].next_by_code(
                'mrp.routing') or _('New')
        return super(MrpRouting, self).create(vals)
Example #6
0
 def _timesheet_preprocess(self, vals):
     """ Deduce other field values from the one given.
         Overrride this to compute on the fly some field that can not be computed fields.
         :param values: dict values for `create`or `write`.
     """
     # project implies analytic account
     if vals.get('project_id') and not vals.get('account_id'):
         project = self.env['project.project'].browse(
             vals.get('project_id'))
         vals['account_id'] = project.analytic_account_id.id
         vals['company_id'] = project.analytic_account_id.company_id.id
         if not project.analytic_account_id.active:
             raise UserError(
                 _('The project you are timesheeting on is not linked to an active analytic account. Set one on the project configuration.'
                   ))
     # employee implies user
     if vals.get('employee_id') and not vals.get('user_id'):
         employee = self.env['hr.employee'].browse(vals['employee_id'])
         vals['user_id'] = employee.user_id.id
     # force customer partner, from the task or the project
     if (vals.get('project_id')
             or vals.get('task_id')) and not vals.get('partner_id'):
         partner_id = False
         if vals.get('task_id'):
             partner_id = self.env['project.task'].browse(
                 vals['task_id']).partner_id.id
         else:
             partner_id = self.env['project.project'].browse(
                 vals['project_id']).partner_id.id
         if partner_id:
             vals['partner_id'] = partner_id
     # set timesheet UoM from the AA company (AA implies uom)
     if 'product_uom_id' not in vals and all([
             v in vals for v in ['account_id', 'project_id']
     ]):  # project_id required to check this is timesheet flow
         analytic_account = self.env['account.analytic.account'].sudo(
         ).browse(vals['account_id'])
         vals[
             'product_uom_id'] = analytic_account.company_id.project_time_mode_id.id
     return vals
Example #7
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
     raise UserError(
         _("Connection Test Succeeded! Everything seems properly set up!"))
Example #8
0
    def _parse_youtube_document(self, document_id, only_preview_fields):
        key = self.env['website'].get_current_website(
        ).website_slide_google_app_key
        fetch_res = self._fetch_data(
            'https://www.googleapis.com/youtube/v3/videos', {
                'id': document_id,
                'key': key,
                'part': 'snippet',
                'fields': 'items(id,snippet)'
            }, 'json')
        if fetch_res.get('error'):
            return fetch_res

        values = {'slide_type': 'video', 'document_id': document_id}
        items = fetch_res['values'].get('items')
        if not items:
            return {'error': _('Please enter valid Youtube or Google Doc URL')}
        youtube_values = items[0]
        if youtube_values.get('snippet'):
            snippet = youtube_values['snippet']
            if only_preview_fields:
                values.update({
                    'url_src': snippet['thumbnails']['high']['url'],
                    'title': snippet['title'],
                    'description': snippet['description']
                })
                return values
            values.update({
                'name':
                snippet['title'],
                'image':
                self._fetch_data(snippet['thumbnails']['high']['url'], {},
                                 'image')['values'],
                'description':
                snippet['description'],
                'mime_type':
                False,
            })
        return {'values': values}
Example #9
0
 def _authorize_form_get_tx_from_data(self, data):
     """ Given a data dict coming from authorize, verify it and find the related
     transaction record. """
     reference, trans_id, fingerprint = data.get('x_invoice_num'), data.get(
         'x_trans_id'), data.get('x_SHA2_Hash') or data.get('x_MD5_Hash')
     if not reference or not trans_id or not fingerprint:
         error_msg = _(
             'Authorize: received data with missing reference (%s) or trans_id (%s) or fingerprint (%s)'
         ) % (reference, trans_id, fingerprint)
         _logger.info(error_msg)
         raise ValidationError(error_msg)
     tx = self.search([('reference', '=', reference)])
     if not tx or len(tx) > 1:
         error_msg = 'Authorize: received data for reference %s' % (
             reference)
         if not tx:
             error_msg += '; no order found'
         else:
             error_msg += '; multiple order found'
         _logger.info(error_msg)
         raise ValidationError(error_msg)
     return tx[0]
Example #10
0
 def payment_transaction(self, *args, **kwargs):
     """ Payment transaction override to double check cart quantities before
     placing the order
     """
     order = request.website.sale_get_order()
     values = []
     for line in order.order_line:
         if line.product_id.type == 'product' and line.product_id.inventory_availability in [
                 'always', 'threshold'
         ]:
             cart_qty = sum(
                 order.order_line.filtered(lambda p: p.product_id.id == line
                                           .product_id.id).mapped(
                                               'product_uom_qty'))
             avl_qty = line.product_id.virtual_available
             if cart_qty > avl_qty:
                 values.append(
                     _('You ask for %s products but only %s is available') %
                     (cart_qty, avl_qty if avl_qty > 0 else 0))
     if values:
         raise UserError('. '.join(values) + '.')
     return super(WebsiteSale, self).payment_transaction(*args, **kwargs)
Example #11
0
    def _split_street_with_params(self, street_raw, street_format):
        street_fields = self.get_street_fields()
        vals = {}
        previous_pos = 0
        field_name = None
        # iter on fields in street_format, detected as '%(<field_name>)s'
        for re_match in re.finditer(r'%\(\w+\)s', street_format):
            field_pos = re_match.start()
            if not field_name:
                #first iteration: remove the heading chars
                street_raw = street_raw[field_pos:]

            # get the substring between 2 fields, to be used as separator
            separator = street_format[previous_pos:field_pos]
            field_value = None
            if separator and field_name:
                #maxsplit set to 1 to unpack only the first element and let the rest untouched
                tmp = street_raw.split(separator, 1)
                if len(tmp) == 2:
                    field_value, street_raw = tmp
                    vals[field_name] = field_value
            if field_value or not field_name:
                # select next field to find (first pass OR field found)
                # [2:-2] is used to remove the extra chars '%(' and ')s'
                field_name = re_match.group()[2:-2]
            else:
                # value not found: keep looking for the same field
                pass
            if field_name not in street_fields:
                raise UserError(_("Unrecognized field %s in street format.") % field_name)
            previous_pos = re_match.end()

        # last field value is what remains in street_raw minus trailing chars in street_format
        trailing_chars = street_format[previous_pos:]
        if trailing_chars and street_raw.endswith(trailing_chars):
            vals[field_name] = street_raw[:-len(trailing_chars)]
        else:
            vals[field_name] = street_raw
        return vals
 def _process(self, cancel_backorder=False):
     if cancel_backorder:
         for pick_id in self.pick_ids:
             moves_to_log = {}
             for move in pick_id.move_lines:
                 if float_compare(
                         move.product_uom_qty,
                         move.quantity_done,
                         precision_rounding=move.product_uom.rounding) > 0:
                     moves_to_log[move] = (move.quantity_done,
                                           move.product_uom_qty)
             pick_id._log_less_quantities_than_expected(moves_to_log)
     self.pick_ids.action_done()
     if cancel_backorder:
         for pick_id in self.pick_ids:
             backorder_pick = self.env['stock.picking'].search([
                 ('backorder_id', '=', pick_id.id)
             ])
             backorder_pick.action_cancel()
             pick_id.message_post(
                 body=_("Back order <em>%s</em> <b>cancelled</b>.") %
                 (",".join([b.name or '' for b in backorder_pick])))
Example #13
0
    def get_valuation_lines(self):
        lines = []

        for move in self.mapped('picking_ids').mapped('move_lines'):
            # it doesn't make sense to make a landed cost for a product that isn't set as being valuated in real time at real cost
            if move.product_id.valuation != 'real_time' or move.product_id.cost_method != 'fifo':
                continue
            vals = {
                'product_id': move.product_id.id,
                'move_id': move.id,
                'quantity': move.product_qty,
                'former_cost': move.value,
                'weight': move.product_id.weight * move.product_qty,
                'volume': move.product_id.volume * move.product_qty
            }
            lines.append(vals)

        if not lines and self.mapped('picking_ids'):
            raise UserError(
                _("You cannot apply landed costs on the chosen transfer(s). Landed costs can only be applied for products with automated inventory valuation and FIFO costing method."
                  ))
        return lines
Example #14
0
    def onchange_employee(self):

        if (not self.employee_id) or (not self.date_from) or (not self.date_to):
            return

        employee = self.employee_id
        date_from = self.date_from
        date_to = self.date_to
        contract_ids = []

        ttyme = datetime.combine(fields.Date.from_string(date_from), time.min)
        locale = self.env.context.get('lang') or 'en_US'
        self.name = _('Salary Slip of %s for %s') % (employee.name, tools.ustr(babel.dates.format_date(date=ttyme, format='MMMM-y', locale=locale)))
        self.company_id = employee.company_id

        if not self.env.context.get('contract') or not self.contract_id:
            contract_ids = self.get_contract(employee, date_from, date_to)
            if not contract_ids:
                return
            self.contract_id = self.env['hr.contract'].browse(contract_ids[0])

        if not self.contract_id.struct_id:
            return
        self.struct_id = self.contract_id.struct_id

        #computation of the salary input
        contracts = self.env['hr.contract'].browse(contract_ids)
        worked_days_line_ids = self.get_worked_day_lines(contracts, date_from, date_to)
        worked_days_lines = self.worked_days_line_ids.browse([])
        for r in worked_days_line_ids:
            worked_days_lines += worked_days_lines.new(r)
        self.worked_days_line_ids = worked_days_lines

        input_line_ids = self.get_inputs(contracts, date_from, date_to)
        input_lines = self.input_line_ids.browse([])
        for r in input_line_ids:
            input_lines += input_lines.new(r)
        self.input_line_ids = input_lines
        return
Example #15
0
    def _graph_data(self, start_date, end_date):
        """ return format should be an iterable of dicts that contain {'x_value': ..., 'y_value': ...}
            x_values should either be dates, weeks, months or user_ids depending on the self.dashboard_graph_group value.
            y_values are floats.
        """
        query = """SELECT %(x_query)s as x_value, %(y_query)s as y_value
                     FROM %(table)s
                    WHERE team_id = %(team_id)s
                      AND DATE(%(date_column)s) >= %(start_date)s
                      AND DATE(%(date_column)s) <= %(end_date)s
                      %(extra_conditions)s
                    GROUP BY x_value;"""

        # apply rules
        if not self.dashboard_graph_model:
            raise UserError(
                _('Undefined graph model for Sales Team: %s') % self.name)
        GraphModel = self.env[self.dashboard_graph_model]
        graph_table = GraphModel._table
        extra_conditions = self._extra_sql_conditions()
        where_query = GraphModel._where_calc([])
        GraphModel._apply_ir_rules(where_query, 'read')
        from_clause, where_clause, where_clause_params = where_query.get_sql()
        if where_clause:
            extra_conditions += " AND " + where_clause

        query = query % {
            'x_query': self._graph_x_query(),
            'y_query': self._graph_y_query(),
            'table': graph_table,
            'team_id': "%s",
            'date_column': self._graph_date_column(),
            'start_date': "%s",
            'end_date': "%s",
            'extra_conditions': extra_conditions
        }
        self._cr.execute(query,
                         [self.id, start_date, end_date] + where_clause_params)
        return self.env.cr.dictfetchall()
Example #16
0
 def post_inventory(self):
     for order in self:
         moves_not_to_do = order.move_raw_ids.filtered(
             lambda x: x.state == 'done')
         moves_to_do = order.move_raw_ids.filtered(lambda x: x.state not in
                                                   ('done', 'cancel'))
         for move in moves_to_do.filtered(
                 lambda m: m.product_qty == 0.0 and m.quantity_done > 0):
             move.product_uom_qty = move.quantity_done
         moves_to_do._action_done()
         moves_to_do = order.move_raw_ids.filtered(
             lambda x: x.state == 'done') - moves_not_to_do
         order._cal_price(moves_to_do)
         moves_to_finish = order.move_finished_ids.filtered(
             lambda x: x.state not in ('done', 'cancel'))
         moves_to_finish._action_done()
         order.action_assign()
         consume_move_lines = moves_to_do.mapped('active_move_line_ids')
         for moveline in moves_to_finish.mapped('active_move_line_ids'):
             if moveline.product_id == order.product_id and moveline.move_id.has_tracking != 'none':
                 if any(
                     [not ml.lot_produced_id for ml in consume_move_lines]):
                     raise UserError(
                         _('You can not consume without telling for which lot you consumed it'
                           ))
                 # Link all movelines in the consumed with same lot_produced_id false or the correct lot_produced_id
                 filtered_lines = consume_move_lines.filtered(
                     lambda x: x.lot_produced_id == moveline.lot_id)
                 moveline.write({
                     'consume_line_ids':
                     [(6, 0, [x for x in filtered_lines.ids])]
                 })
             else:
                 # Link with everything
                 moveline.write({
                     'consume_line_ids':
                     [(6, 0, [x for x in consume_move_lines.ids])]
                 })
     return True
Example #17
0
    def _get_report_values(self, docids, data=None):
        PosOrder = self.env['pos.order']
        ids_to_print = []
        invoiced_posorders_ids = []
        selected_orders = PosOrder.browse(docids)
        for order in selected_orders.filtered(lambda o: o.invoice_id):
            ids_to_print.append(order.invoice_id.id)
            invoiced_posorders_ids.append(order.id)
        not_invoiced_orders_ids = list(
            set(docids) - set(invoiced_posorders_ids))
        if not_invoiced_orders_ids:
            not_invoiced_posorders = PosOrder.browse(not_invoiced_orders_ids)
            not_invoiced_orders_names = [
                a.name for a in not_invoiced_posorders
            ]
            raise UserError(
                _('No link to an invoice for %s.') %
                ', '.join(not_invoiced_orders_names))

        return {
            'docs': self.env['account.invoice'].sudo().browse(ids_to_print)
        }
Example #18
0
 def phone_format(number, country_code, country_phone_code, always_international=True, raise_exception=True):
     """ Format the given phone number according to the localisation and international options.
         :param number: number to convert
         :param country_code: the ISO country code in two chars
         :type country_code: str
         :param country_phone_code: country dial in codes, defined by the ITU-T (Ex: 32 for Belgium)
         :type country_phone_code: int
         :rtype: str
     """
     try:
         phone_nbr = phone_parse(number, country_code)
     except (phonenumbers.phonenumberutil.NumberParseException, UserError) as e:
         if raise_exception:
             raise
         else:
             _logger.warning(_('Unable to format %s:\n%s'), number, e)
             return number
     if always_international or phone_nbr.country_code != country_phone_code:
         phone_fmt = phonenumbers.PhoneNumberFormat.INTERNATIONAL
     else:
         phone_fmt = phonenumbers.PhoneNumberFormat.NATIONAL
     return phonenumbers.format_number(phone_nbr, phone_fmt)
Example #19
0
    def get_action(self):
        """Get the ir.action related to update the goal

        In case of a manual goal, should return a wizard to update the value
        :return: action description in a dictionary
        """
        if self.definition_id.action_id:
            # open a the action linked to the goal
            action = self.definition_id.action_id.read()[0]

            if self.definition_id.res_id_field:
                current_user = self.env.user.sudo(self.env.user)
                action['res_id'] = safe_eval(self.definition_id.res_id_field,
                                             {'user': current_user})

                # if one element to display, should see it in form mode if possible
                action['views'] = [(view_id, mode)
                                   for (view_id, mode) in action['views']
                                   if mode == 'form'] or action['views']
            return action

        if self.computation_mode == 'manually':
            # open a wizard window to update the value manually
            action = {
                'name': _("Update %s") % self.definition_id.name,
                'id': self.id,
                'type': 'ir.actions.act_window',
                'views': [[False, 'form']],
                'target': 'new',
                'context': {
                    'default_goal_id': self.id,
                    'default_current': self.current
                },
                'res_model': 'gamification.goal.wizard'
            }
            return action

        return False
Example #20
0
    def open_table(self):
        self.ensure_one()

        if self.compute_at_date:
            tree_view_id = self.env.ref('stock.view_stock_product_tree').id
            form_view_id = self.env.ref(
                'stock.product_form_view_procurement_button').id
            # We pass `to_date` in the context so that `qty_available` will be computed across
            # moves until date.
            action = {
                'type': 'ir.actions.act_window',
                'views': [(tree_view_id, 'tree'), (form_view_id, 'form')],
                'view_mode': 'tree,form',
                'name': _('Products'),
                'res_model': 'product.product',
                'domain': "[('type', '=', 'product')]",
                'context': dict(self.env.context, to_date=self.date),
            }
            return action
        else:
            self.env['stock.quant']._merge_quants()
            self.env['stock.quant']._unlink_zero_quants()
            return self.env.ref('stock.quantsact').read()[0]
Example #21
0
    def _notify_get_groups(self, message, groups):
        access_token = self._portal_ensure_token()

        if access_token and 'partner_id' in self._fields and self['partner_id']:
            customer = self['partner_id']
            additional_params = {
                'access_token': self.access_token,
            }
            additional_params.update(customer.signup_get_auth_param()[customer.id])
            access_link = self._notify_get_action_link('view', **additional_params)

            new_group = [
                ('portal_customer', lambda pdata: pdata['id'] == customer.id, {
                    'has_button_access': False,
                    'button_access': {
                        'url': access_link,
                        'title': _('View %s') % self.env['ir.model']._get(message.model).display_name,
                    },
                })
            ]
        else:
            new_group = []
        return super(PortalMixin, self)._notify_get_groups(message, new_group + groups)
Example #22
0
    def _get_google_token_json(self, authorize_code, service):
        """ Call Google API to exchange authorization code against token, with POST request, to
            not be redirected.
        """
        get_param = self.env['ir.config_parameter'].sudo().get_param
        base_url = get_param('web.base.url', default='http://www.swerp.it?NoBaseUrl')
        client_id = get_param('google_%s_client_id' % (service,), default=False)
        client_secret = get_param('google_%s_client_secret' % (service,), default=False)

        headers = {"content-type": "application/x-www-form-urlencoded"}
        data = {
            'code': authorize_code,
            'client_id': client_id,
            'client_secret': client_secret,
            'grant_type': 'authorization_code',
            'redirect_uri': base_url + '/google_account/authentication'
        }
        try:
            dummy, response, dummy = self._do_request(GOOGLE_TOKEN_ENDPOINT, params=data, headers=headers, type='POST', preuri='')
            return response
        except requests.HTTPError:
            error_msg = _("Something went wrong during your token generation. Maybe your Authorization Code is invalid")
            raise self.env['res.config.settings'].get_config_warning(error_msg)
Example #23
0
 def button_confirm_login(self):
     for server in self:
         try:
             connection = server.connect()
             server.write({'state': 'done'})
         except Exception as err:
             _logger.info("Failed to connect to %s server %s.",
                          server.type,
                          server.name,
                          exc_info=True)
             raise UserError(
                 _("Connection test failed: %s") % tools.ustr(err))
         finally:
             try:
                 if connection:
                     if server.type == 'imap':
                         connection.close()
                     elif server.type == 'pop':
                         connection.quit()
             except Exception:
                 # ignored, just a consequence of the previous exception
                 pass
     return True
Example #24
0
    def write(self, vals):
        """Override to make sure attribute type can't be changed if it's used on
        a product template.

        This is important to prevent because changing the type would make
        existing combinations invalid without recomputing them, and recomputing
        them might take too long and we don't want to change products without
        the user knowing about it."""
        if 'create_variant' in vals:
            products = self._get_related_product_templates()
            if products:
                message = ', '.join(products.mapped('name'))
                raise UserError(
                    _('You are trying to change the type of an attribute value still referenced on at least one product template: %s'
                      ) % message)
        invalidate_cache = 'sequence' in vals and any(
            record.sequence != vals['sequence'] for record in self)
        res = super(ProductAttribute, self).write(vals)
        if invalidate_cache:
            # prefetched o2m have to be resequenced
            # (eg. product.template: attribute_line_ids)
            self.invalidate_cache()
        return res
Example #25
0
    def action_your_pipeline(self):
        action = self.env.ref('crm.crm_lead_opportunities_tree_view').read()[0]
        user_team_id = self.env.user.sale_team_id.id
        if user_team_id:
            # To ensure that the team is readable in multi company
            user_team_id = self.search([('id', '=', user_team_id)], limit=1).id
        else:
            user_team_id = self.search([], limit=1).id
            action['help'] = _(
                """<p class='o_view_nocontent_smiling_face'>Add new opportunities</p><p>
    Looks like you are not a member of a Sales Team. You should add yourself
    as a member of one of the Sales Team.
</p>""")
            if user_team_id:
                action[
                    'help'] += "<p>As you don't belong to any Sales Team, Swerp opens the first one by default.</p>"

        action_context = safe_eval(action['context'], {'uid': self.env.uid})
        if user_team_id:
            action_context['default_team_id'] = user_team_id

        action['context'] = action_context
        return action
Example #26
0
    def _get_report_values(self, docids, data=None):
        if not data.get('form') or not self.env.context.get(
                'active_model') or not self.env.context.get('active_id'):
            raise UserError(
                _("Form content is missing, this report cannot be printed."))

        model = self.env.context.get('active_model')
        docs = self.env[model].browse(self.env.context.get('active_id'))
        get_periods, months, total_mnths = self.get_periods(data['form'])
        get_employee = self.get_employee(data['form'], months, total_mnths)
        get_months_tol = self.get_months_tol()
        get_total = self.get_total(get_months_tol)
        return {
            'doc_ids': docids,
            'doc_model': model,
            'data': data,
            'docs': docs,
            'get_periods': get_periods,
            'get_employee': get_employee,
            'get_months_tol': get_months_tol,
            'get_total': get_total,
            'month_len': len(total_mnths) + 1
        }
Example #27
0
    def _create_accounting_entries(self, move, qty_out):
        # TDE CLEANME: product chosen for computation ?
        cost_product = self.cost_line_id.product_id
        if not cost_product:
            return False
        accounts = self.product_id.product_tmpl_id.get_product_accounts()
        debit_account_id = accounts.get(
            'stock_valuation') and accounts['stock_valuation'].id or False
        # If the stock move is dropshipped move we need to get the cost account instead the stock valuation account
        if self.move_id._is_dropshipped():
            debit_account_id = accounts.get(
                'expense') and accounts['expense'].id or False
        already_out_account_id = accounts['stock_output'].id
        credit_account_id = self.cost_line_id.account_id.id or cost_product.property_account_expense_id.id or cost_product.categ_id.property_account_expense_categ_id.id

        if not credit_account_id:
            raise UserError(
                _('Please configure Stock Expense Account for product: %s.') %
                (cost_product.name))

        return self._create_account_move_line(move, credit_account_id,
                                              debit_account_id, qty_out,
                                              already_out_account_id)
Example #28
0
    def button_mark_done(self):
        self.ensure_one()
        for wo in self.workorder_ids:
            if wo.time_ids.filtered(lambda x: (not x.date_end) and (
                    x.loss_type in ('productive', 'performance'))):
                raise UserError(_('Work order %s is still running') % wo.name)
        self._check_lots()

        self.post_inventory()
        # Moves without quantity done are not posted => set them as done instead of canceling. In
        # case the user edits the MO later on and sets some consumed quantity on those, we do not
        # want the move lines to be canceled.
        (self.move_raw_ids | self.move_finished_ids
         ).filtered(lambda x: x.state not in ('done', 'cancel')).write({
             'state':
             'done',
             'product_uom_qty':
             0.0,
         })
        return self.write({
            'state': 'done',
            'date_finished': fields.Datetime.now()
        })
Example #29
0
    def create(self, values):
        # First of all, extract values to ensure emails are really unique (and don't modify values in place)
        new_values = []
        all_emails = []
        for value in values:
            email = self._sanitize_email(value.get('email'))
            if not email:
                raise UserError(_('Invalid email address %r') % value['email'])
            if email in all_emails:
                continue
            all_emails.append(email)
            new_value = dict(value, email=email)
            new_values.append(new_value)
        """ To avoid crash during import due to unique email, return the existing records if any """
        sql = '''SELECT email, id FROM mail_blacklist WHERE email = ANY(%s)'''
        emails = [v['email'] for v in new_values]
        self._cr.execute(sql, (emails, ))
        bl_entries = dict(self._cr.fetchall())
        to_create = [v for v in new_values if v['email'] not in bl_entries]

        # TODO DBE Fixme : reorder ids according to incoming ids.
        results = super(MailBlackList, self).create(to_create)
        return self.env['mail.blacklist'].browse(bl_entries.values()) | results
Example #30
0
 def create_returns(self):
     for wizard in self:
         new_picking_id, pick_type_id = wizard._create_returns()
     # Override the context to disable all the potential filters that could have been set previously
     ctx = dict(self.env.context)
     ctx.update({
         'search_default_picking_type_id': pick_type_id,
         'search_default_draft': False,
         'search_default_assigned': False,
         'search_default_confirmed': False,
         'search_default_ready': False,
         'search_default_late': False,
         'search_default_available': False,
     })
     return {
         'name': _('Returned Picking'),
         'view_type': 'form',
         'view_mode': 'form,tree,calendar',
         'res_model': 'stock.picking',
         'res_id': new_picking_id,
         'type': 'ir.actions.act_window',
         'context': ctx,
     }