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 _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 attributes(self, record, field_name, options, values): attrs = super(DateTime, self).attributes(record, field_name, options, values) if options.get('inherit_branding'): value = record[field_name] lg = self.env['res.lang']._lang_get( self.env.user.lang) or get_lang(self.env) locale = babel.Locale.parse(lg.code) babel_format = value_format = posix_to_ldml( '%s %s' % (lg.date_format, lg.time_format), locale=locale) tz = record.env.context.get('tz') or self.env.user.tz if isinstance(value, str): value = fields.Datetime.from_string(value) if value: # convert from UTC (server timezone) to user timezone value = fields.Datetime.context_timestamp( self.with_context(tz=tz), timestamp=value) value_format = pycompat.to_text( babel.dates.format_datetime(value, format=babel_format, locale=locale)) value = fields.Datetime.to_string(value) attrs['data-oe-original'] = value attrs['data-oe-original-with-format'] = value_format attrs['data-oe-original-tz'] = tz return attrs
def attributes(self, record, field_name, options, values): attrs = super(Date, self).attributes(record, field_name, options, values) if options.get('inherit_branding'): attrs['data-oe-original'] = record[field_name] if record._fields[field_name].type == 'datetime': attrs = self.env['ir.qweb.field.datetime'].attributes( record, field_name, options, values) attrs['data-oe-type'] = 'datetime' return attrs lg = self.env['res.lang']._lang_get( self.env.user.lang) or get_lang(self.env) locale = babel.Locale.parse(lg.code) babel_format = value_format = posix_to_ldml(lg.date_format, locale=locale) if record[field_name]: date = fields.Date.from_string(record[field_name]) value_format = pycompat.to_text( babel.dates.format_date(date, format=babel_format, locale=locale)) attrs['data-oe-original-with-format'] = value_format return attrs
def from_html(self, model, field, element): value = element.text_content().strip() if not value: return False # parse from string to datetime lg = self.env['res.lang']._lang_get(self.env.user.lang) or get_lang( self.env) dt = datetime.strptime(value, '%s %s' % (lg.date_format, lg.time_format)) # convert back from user's timezone to UTC tz_name = element.attrib.get( 'data-oe-original-tz') or self.env.context.get( 'tz') or self.env.user.tz if tz_name: try: user_tz = pytz.timezone(tz_name) utc = pytz.utc dt = user_tz.localize(dt).astimezone(utc) except Exception: logger.warn( "Failed to convert the value for a field of the model" " %s back from the user's timezone (%s) to UTC", model, tz_name, exc_info=True) # format back to string return fields.Datetime.to_string(dt)
def get_line_graph_datas(self): """Computes the data used to display the graph for bank and cash journals in the accounting dashboard""" currency = self.currency_id or self.company_id.currency_id 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 = currency.round(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_formated_date(self, event): start_date = fields.Datetime.from_string(event.date_begin).date() end_date = fields.Datetime.from_string(event.date_end).date() month = babel.dates.get_month_names( 'abbreviated', locale=get_lang(event.env).code)[start_date.month] return ('%s %s%s') % (month, start_date.strftime("%e"), (end_date != start_date and ("-" + end_date.strftime("%e")) or ""))
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 from_html(self, model, field, element): value = element.text_content().strip() if not value: return False lg = self.env['res.lang']._lang_get(self.env.user.lang) or get_lang( self.env) date = datetime.strptime(value, lg.date_format) return fields.Date.to_string(date)
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 _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 _product_id_change(self): if not self.product_id: return self.product_uom = self.product_id.uom_po_id or self.product_id.uom_id product_lang = self.product_id.with_context( lang=get_lang(self.env, self.partner_id.lang).code, partner_id=self.partner_id.id, company_id=self.company_id.id, ) self.name = self._get_product_purchase_description(product_lang) self._compute_tax_id()
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 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 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 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 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
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