def _compute_sale_graph(self, date_from, date_to, sales_domain, previous=False): days_between = (date_to - date_from).days date_list = [(date_from + timedelta(days=x)) for x in range(0, days_between + 1)] daily_sales = request.env['sale.report'].read_group( domain=sales_domain, fields=['date', 'price_subtotal'], groupby='date:day') daily_sales_dict = { p['date:day']: p['price_subtotal'] for p in daily_sales } sales_graph = [ { '0': fields.Date.to_string(d) if not previous else fields.Date.to_string(d + timedelta(days=days_between)), # Respect read_group format in models.py '1': daily_sales_dict.get( babel.dates.format_date(d, format='dd MMM yyyy', locale=get_lang(request.env).code), 0) } for d in date_list ] return sales_graph
def load(self, name, options): lang = options.get('lang', get_lang(self.env).code) env = self.env if lang != env.context.get('lang'): env = env(context=dict(env.context, lang=lang)) template = env['ir.ui.view'].read_template(name) # QWeb's `read_template` will check if one of the first children of # what we send to it has a "t-name" attribute having `name` as value # to consider it has found it. As it'll never be the case when working # with view ids or children view or children primary views, force it here. def is_child_view(view_name): view_id = self.env['ir.ui.view'].get_view_id(view_name) view = self.env['ir.ui.view'].browse(view_id) return view.inherit_id is not None if isinstance(name, int) or is_child_view(name): view = etree.fromstring(template) for node in view: if node.get('t-name'): node.set('t-name', str(name)) return view else: return template
def _compile_directive_lang(self, el, options): lang = el.attrib.pop('t-lang', get_lang(self.env).code) if el.get('t-call-options'): el.set('t-call-options', el.get('t-call-options')[0:-1] + u', "lang": %s}' % lang) else: el.set('t-call-options', u'{"lang": %s}' % lang) return self._compile_node(el, options)
def user_lang(self): """ user_lang() Fetches the res.lang record corresponding to the language code stored in the user's context. :returns: Model[res.lang] """ return get_lang(self.env)
def submit_rating(self, token, rate, **kwargs): rating = request.env['rating.rating'].sudo().search([('access_token', '=', token)]) if not rating: return request.not_found() record_sudo = request.env[rating.res_model].sudo().browse(rating.res_id) record_sudo.rating_apply(rate, token=token, feedback=kwargs.get('feedback')) lang = rating.partner_id.lang or get_lang(request.env).code return request.env['ir.ui.view'].with_context(lang=lang).render_template('rating.rating_external_page_view', { 'web_base_url': request.env['ir.config_parameter'].sudo().get_param('web.base.url'), 'rating': rating, })
def check_report(self): self.ensure_one() data = {} data['ids'] = self.env.context.get('active_ids', []) data['model'] = self.env.context.get('active_model', 'ir.ui.menu') data['form'] = self.read([ 'date_from', 'date_to', 'journal_ids', 'target_move', 'company_id' ])[0] used_context = self._build_contexts(data) data['form']['used_context'] = dict(used_context, lang=get_lang(self.env).code) return self.with_context(discard_logo_check=True)._print_report(data)
def open_rating(self, token, rate, **kwargs): assert rate in (1, 5, 10), "Incorrect rating" rating = request.env['rating.rating'].sudo().search([('access_token', '=', token)]) if not rating: return request.not_found() rate_names = { 5: _("not satisfied"), 1: _("highly dissatisfied"), 10: _("satisfied") } rating.write({'rating': rate, 'consumed': True}) lang = rating.partner_id.lang or get_lang(request.env).code return request.env['ir.ui.view'].with_context(lang=lang).render_template('rating.rating_external_page_submit', { 'rating': rating, 'token': token, 'rate_name': rate_names[rate], 'rate': rate })
def nav_list(self, blog=None): dom = blog and [('blog_id', '=', blog.id)] or [] if not request.env.user.has_group('website.group_website_designer'): dom += [('post_date', '<=', fields.Datetime.now())] groups = request.env['blog.post']._read_group_raw( dom, ['name', 'post_date'], groupby=["post_date"], orderby="post_date desc") for group in groups: (r, label) = group['post_date'] start, end = r.split('/') group['post_date'] = label group['date_begin'] = start group['date_end'] = end locale = get_lang(request.env).code start = pytz.UTC.localize(fields.Datetime.from_string(start)) tzinfo = pytz.timezone(request.context.get('tz', 'utc') or 'utc') group['month'] = babel.dates.format_datetime(start, format='MMMM', tzinfo=tzinfo, locale=locale) group['year'] = babel.dates.format_datetime(start, format='YYYY', tzinfo=tzinfo, locale=locale) return OrderedDict((year, [m for m in months]) for year, months in itertools.groupby(groups, lambda g: g['year']))
def send_and_print_action(self): self.ensure_one() # Send the mails in the correct language by splitting the ids per lang. # This should ideally be fixed in mail_compose_message, so when a fix is made there this whole commit should be reverted. # basically self.body (which could be manually edited) extracts self.template_id, # which is then not translated for each customer. if self.composition_mode == 'mass_mail' and self.template_id: active_ids = self.env.context.get('active_ids', self.res_id) active_records = self.env[self.model].browse(active_ids) langs = active_records.mapped('partner_id.lang') default_lang = get_lang(self.env) for lang in (set(langs) or [default_lang]): active_ids_lang = active_records.filtered( lambda r: r.partner_id.lang == lang).ids self_lang = self.with_context(active_ids=active_ids_lang, lang=lang) self_lang.onchange_template_id() self_lang._send_email() else: self._send_email() if self.is_print: return self._print_document() return {'type': 'ir.actions.act_window_close'}
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if name and operator == '=' and not args: # search on the name of the pricelist and its currency, opposite of name_get(), # Used by the magic context filter in the product search view. query_args = {'name': name, 'limit': limit, 'lang': get_lang(self.env).code} query = """SELECT p.id FROM (( SELECT pr.id, pr.name FROM product_pricelist pr JOIN res_currency cur ON (pr.currency_id = cur.id) WHERE pr.name || ' (' || cur.name || ')' = %(name)s ) UNION ( SELECT tr.res_id as id, tr.value as name FROM ir_translation tr JOIN product_pricelist pr ON ( pr.id = tr.res_id AND tr.type = 'model' AND tr.name = 'product.pricelist,name' AND tr.lang = %(lang)s ) JOIN res_currency cur ON (pr.currency_id = cur.id) WHERE tr.value || ' (' || cur.name || ')' = %(name)s ) ) p ORDER BY p.name""" if limit: query += " LIMIT %(limit)s" self._cr.execute(query, query_args) ids = [r[0] for r in self._cr.fetchall()] # regular search() to apply ACLs - may limit results below limit in some cases pricelist_ids = self._search([('id', 'in', ids)], limit=limit, access_rights_uid=name_get_uid) if pricelist_ids: return models.lazy_name_get(self.browse(pricelist_ids).with_user(name_get_uid)) return super(Pricelist, self)._name_search(name, args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def view(self, db, token, action, id, view='calendar'): registry = registry_get(db) with registry.cursor() as cr: # Since we are in auth=none, create an env with SUPERUSER_ID env = Environment(cr, SUPERUSER_ID, {}) attendee = env['calendar.attendee'].search([ ('access_token', '=', token), ('event_id', '=', int(id)) ]) if not attendee: return request.not_found() timezone = attendee.partner_id.tz lang = attendee.partner_id.lang or get_lang(request.env).code event = env['calendar.event'].with_context(tz=timezone, lang=lang).browse( int(id)) # If user is internal and logged, redirect to form view of event # otherwise, display the simplifyed web page with event informations if request.session.uid and request.env['res.users'].browse( request.session.uid).user_has_groups('base.group_user'): return werkzeug.utils.redirect( '/web?db=%s#id=%s&view_type=form&model=calendar.event' % (db, id)) # NOTE : we don't use request.render() since: # - we need a template rendering which is not lazy, to render before cursor closing # - we need to display the template in the language of the user (not possible with # request.render()) response_content = env['ir.ui.view'].with_context( lang=lang).render_template( 'calendar.invitation_page_anonymous', { 'event': event, 'attendee': attendee, }) return request.make_response(response_content, headers=[('Content-Type', 'text/html') ])
def get_line_graph_datas(self): """Computes the data used to display the graph for bank and cash journals in the accounting dashboard""" def build_graph_data(date, amount): #display date in locale format name = format_date(date, 'd LLLL Y', locale=locale) short_name = format_date(date, 'd MMM', locale=locale) return {'x': short_name, 'y': amount, 'name': name} self.ensure_one() BankStatement = self.env['account.bank.statement'] data = [] today = datetime.today() last_month = today + timedelta(days=-30) locale = get_lang(self.env).code #starting point of the graph is the last statement last_stmt = BankStatement.search([('journal_id', '=', self.id), ('date', '<=', today.strftime(DF))], order='date desc, id desc', limit=1) last_balance = last_stmt and last_stmt.balance_end_real or 0 data.append(build_graph_data(today, last_balance)) #then we subtract the total amount of bank statement lines per day to get the previous points #(graph is drawn backward) date = today amount = last_balance query = """SELECT l.date, sum(l.amount) as amount FROM account_bank_statement_line l RIGHT JOIN account_bank_statement st ON l.statement_id = st.id WHERE st.journal_id = %s AND l.date > %s AND l.date <= %s GROUP BY l.date ORDER BY l.date desc """ self.env.cr.execute(query, (self.id, last_month, today)) query_result = self.env.cr.dictfetchall() for val in query_result: date = val['date'] if date != today.strftime( DF): # make sure the last point in the graph is today data[:0] = [build_graph_data(date, amount)] amount -= val['amount'] # make sure the graph starts 1 month ago if date.strftime(DF) != last_month.strftime(DF): data[:0] = [build_graph_data(last_month, amount)] [graph_title, graph_key] = self._graph_title_and_key() color = '#875A7B' if 'e' in version else '#7c7bad' is_sample_data = not last_stmt and len(query_result) == 0 if is_sample_data: data = [] for i in range(30, 0, -5): current_date = today + timedelta(days=-i) data.append( build_graph_data(current_date, random.randint(-5, 15))) return [{ 'values': data, 'title': graph_title, 'key': graph_key, 'area': True, 'color': color, 'is_sample_data': is_sample_data }]
def get_bar_graph_datas(self): data = [] today = fields.Datetime.now(self) data.append({'label': _('Due'), 'value': 0.0, 'type': 'past'}) day_of_week = int( format_datetime(today, 'e', locale=get_lang(self.env).code)) first_day_of_week = today + timedelta(days=-day_of_week + 1) for i in range(-1, 4): if i == 0: label = _('This Week') elif i == 3: label = _('Not Due') else: start_week = first_day_of_week + timedelta(days=i * 7) end_week = start_week + timedelta(days=6) if start_week.month == end_week.month: label = str(start_week.day) + '-' + str( end_week.day) + ' ' + format_date( end_week, 'MMM', locale=get_lang(self.env).code) else: label = format_date( start_week, 'd MMM', locale=get_lang(self.env).code) + '-' + format_date( end_week, 'd MMM', locale=get_lang(self.env).code) data.append({ 'label': label, 'value': 0.0, 'type': 'past' if i < 0 else 'future' }) # Build SQL query to find amount aggregated by week (select_sql_clause, query_args) = self._get_bar_graph_select_query() query = '' start_date = (first_day_of_week + timedelta(days=-7)) for i in range(0, 6): if i == 0: query += "(" + select_sql_clause + " and invoice_date_due < '" + start_date.strftime( DF) + "')" elif i == 5: query += " UNION ALL (" + select_sql_clause + " and invoice_date_due >= '" + start_date.strftime( DF) + "')" else: next_date = start_date + timedelta(days=7) query += " UNION ALL (" + select_sql_clause + " and invoice_date_due >= '" + start_date.strftime( DF) + "' and invoice_date_due < '" + next_date.strftime( DF) + "')" start_date = next_date self.env.cr.execute(query, query_args) query_results = self.env.cr.dictfetchall() is_sample_data = True for index in range(0, len(query_results)): if query_results[index].get('aggr_date') != None: is_sample_data = False data[index]['value'] = query_results[index].get('total') [graph_title, graph_key] = self._graph_title_and_key() if is_sample_data: for index in range(0, len(query_results)): data[index]['type'] = 'o_sample_data' # we use unrealistic values for the sample data data[index]['value'] = random.randint(0, 20) graph_key = _('Sample data') return [{ 'values': data, 'title': graph_title, 'key': graph_key, 'is_sample_data': is_sample_data }]
def _to_short_month_name(date): month_index = fields.Date.from_string(date).month return babel.dates.get_month_names('abbreviated', locale=get_lang( self.env).code)[month_index]
def default_get(self, fields): res = super(BaseGengoTranslations, self).default_get(fields) res['authorized_credentials'], gengo = self.gengo_authentication() if 'lang_id' in fields: res['lang_id'] = get_lang(self.env).id return res
def read_progress_bar(self, domain, group_by, progress_bar): """ Gets the data needed for all the kanban column progressbars. These are fetched alongside read_group operation. :param domain - the domain used in the kanban view to filter records :param group_by - the name of the field used to group records into kanban columns :param progress_bar - the <progressbar/> declaration attributes (field, colors, sum) :return a dictionnary mapping group_by values to dictionnaries mapping progress bar field values to the related number of records """ # Workaround to match read_group's infrastructure # TO DO in master: harmonize this function and readgroup to allow factorization group_by_modifier = group_by.partition(':')[2] or 'month' group_by = group_by.partition(':')[0] display_date_formats = { 'day': 'dd MMM yyyy', 'week': "'W'w YYYY", 'month': 'MMMM yyyy', 'quarter': 'QQQ yyyy', 'year': 'yyyy'} records_values = self.search_read(domain or [], [progress_bar['field'], group_by]) data = {} field_type = self._fields[group_by].type if field_type == 'selection': selection_labels = dict(self.fields_get()[group_by]['selection']) for record_values in records_values: group_by_value = record_values[group_by] # Again, imitating what _read_group_format_result and _read_group_prepare_data do if group_by_value and field_type in ['date', 'datetime']: locale = get_lang(self.env).code group_by_value = fields.Datetime.to_datetime(group_by_value) group_by_value = pytz.timezone('UTC').localize(group_by_value) tz_info = None if field_type == 'datetime' and self._context.get('tz') in pytz.all_timezones: tz_info = self._context.get('tz') group_by_value = babel.dates.format_datetime( group_by_value, format=display_date_formats[group_by_modifier], tzinfo=tz_info, locale=locale) else: group_by_value = babel.dates.format_date( group_by_value, format=display_date_formats[group_by_modifier], locale=locale) if field_type == 'selection': group_by_value = selection_labels[group_by_value] \ if group_by_value in selection_labels else False if type(group_by_value) == tuple: group_by_value = group_by_value[1] # FIXME should use technical value (0) if group_by_value not in data: data[group_by_value] = {} for key in progress_bar['colors']: data[group_by_value][key] = 0 field_value = record_values[progress_bar['field']] if field_value in data[group_by_value]: data[group_by_value][field_value] += 1 return data