154 lines
7.1 KiB
Python
154 lines
7.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import babel
|
|
|
|
from datetime import datetime, timedelta, time
|
|
|
|
from flectra import fields, http, _
|
|
from flectra.addons.website.controllers.backend import WebsiteBackend
|
|
from flectra.http import request
|
|
|
|
|
|
class WebsiteSaleBackend(WebsiteBackend):
|
|
|
|
@http.route()
|
|
def fetch_dashboard_data(self, date_from, date_to, website_id=None):
|
|
if not website_id:
|
|
website_id = request.website.id
|
|
results = super(WebsiteSaleBackend, self).fetch_dashboard_data(date_from, date_to, website_id)
|
|
|
|
sales_values = dict(
|
|
graph=[],
|
|
best_sellers=[],
|
|
summary=dict(
|
|
order_count=0, order_carts_count=0, order_unpaid_count=0,
|
|
order_to_invoice_count=0, order_carts_abandoned_count=0,
|
|
payment_to_capture_count=0, total_sold=0,
|
|
order_per_day_ratio=0, order_sold_ratio=0, order_convertion_pctg=0,
|
|
)
|
|
)
|
|
results['dashboards']['sales'] = sales_values
|
|
|
|
results['groups']['sale_salesman'] = request.env['res.users'].has_group('sales_team.group_sale_salesman')
|
|
if not results['groups']['sale_salesman']:
|
|
return results
|
|
|
|
date_date_from = fields.Date.from_string(date_from)
|
|
date_date_to = fields.Date.from_string(date_to)
|
|
date_diff_days = (date_date_to - date_date_from).days
|
|
datetime_from = datetime.combine(date_date_from, time.min)
|
|
datetime_to = datetime.combine(date_date_to, time.max)
|
|
|
|
# Product-based computation
|
|
report_product_lines = request.env['sale.report'].read_group(
|
|
domain=[
|
|
('product_id.website_published', '=', True),
|
|
('team_id.team_type', '=', 'website'),
|
|
('state', 'in', ['sale', 'done']),
|
|
('date', '>=', date_from),
|
|
('website_id.id', '=', website_id),
|
|
('date', '<=', date_to)],
|
|
fields=['product_id', 'product_uom_qty', 'price_subtotal'],
|
|
groupby='product_id', orderby='product_uom_qty desc', limit=5)
|
|
for product_line in report_product_lines:
|
|
product_id = request.env['product.product'].browse(product_line['product_id'][0])
|
|
sales_values['best_sellers'].append({
|
|
'id': product_id.id,
|
|
'name': product_id.name,
|
|
'qty': product_line['product_uom_qty'],
|
|
'sales': product_line['price_subtotal'],
|
|
})
|
|
|
|
# Sale-based results computation
|
|
sale_order_domain = [
|
|
('team_id', 'in', request.env['crm.team'].search([('team_type', '=', 'website')]).ids),
|
|
('date_order', '>=', fields.Datetime.to_string(datetime_from)),
|
|
('date_order', '<=', fields.Datetime.to_string(datetime_to)),
|
|
('website_id', '=', website_id)]
|
|
so_group_data = request.env['sale.order'].read_group(sale_order_domain, fields=['state'], groupby='state')
|
|
for res in so_group_data:
|
|
if res.get('state') == 'sent':
|
|
sales_values['summary']['order_unpaid_count'] += res['state_count']
|
|
elif res.get('state') in ['sale', 'done']:
|
|
sales_values['summary']['order_count'] += res['state_count']
|
|
sales_values['summary']['order_carts_count'] += res['state_count']
|
|
|
|
report_price_lines = request.env['sale.report'].read_group(
|
|
domain=[
|
|
('team_id.team_type', '=', 'website'),
|
|
('state', 'in', ['sale', 'done']),
|
|
('date', '>=', date_from),
|
|
('date', '<=', date_to),
|
|
('website_id.id', '=', website_id)],
|
|
fields=['team_id', 'price_subtotal'],
|
|
groupby=['team_id'],
|
|
)
|
|
sales_values['summary'].update(
|
|
order_to_invoice_count=request.env['sale.order'].search_count(sale_order_domain + [
|
|
('state', 'in', ['sale', 'done']),
|
|
('order_line', '!=', False),
|
|
('partner_id', '!=', request.env.ref('base.public_partner').id),
|
|
('invoice_status', '=', 'to invoice'),
|
|
]),
|
|
order_carts_abandoned_count=request.env['sale.order'].search_count(sale_order_domain + [
|
|
('is_abandoned_cart', '=', True),
|
|
('cart_recovery_email_sent', '=', False)
|
|
]),
|
|
payment_to_capture_count=request.env['payment.transaction'].search_count([
|
|
('state', '=', 'authorized'),
|
|
# that part perform a search on sale.order in order to comply with access rights as tx do not have any
|
|
('sale_order_id.id', 'in', request.env['sale.order'].search(sale_order_domain + [('state', '!=', 'cancel')]).ids),
|
|
]),
|
|
total_sold=sum(price_line['price_subtotal'] for price_line in report_price_lines)
|
|
)
|
|
|
|
# Ratio computation
|
|
sales_values['summary']['order_per_day_ratio'] = round(float(sales_values['summary']['order_count']) / date_diff_days, 2)
|
|
sales_values['summary']['order_sold_ratio'] = round(float(sales_values['summary']['total_sold']) / sales_values['summary']['order_count'], 2) if sales_values['summary']['order_count'] else 0
|
|
sales_values['summary']['order_convertion_pctg'] = 100.0 * sales_values['summary']['order_count'] / sales_values['summary']['order_carts_count'] if sales_values['summary']['order_carts_count'] else 0
|
|
|
|
# Graphes computation
|
|
if date_diff_days == 7:
|
|
previous_sale_label = _('Previous Week')
|
|
elif date_diff_days > 7 and date_diff_days <= 31:
|
|
previous_sale_label = _('Previous Month')
|
|
else:
|
|
previous_sale_label = _('Previous Year')
|
|
|
|
sales_domain = [
|
|
('team_id.team_type', '=', 'website'),
|
|
('state', 'in', ['sale', 'done']),
|
|
('date', '>=', date_from),
|
|
('date', '<=', date_to),
|
|
('website_id.id', '=', website_id)
|
|
]
|
|
sales_values['graph'] += [{
|
|
'values': self._compute_sale_graph(date_date_from, date_date_to, sales_domain),
|
|
'key': 'Untaxed Total',
|
|
}, {
|
|
'values': self._compute_sale_graph(date_date_from - timedelta(days=date_diff_days), date_date_from, sales_domain, previous=True),
|
|
'key': previous_sale_label,
|
|
}]
|
|
|
|
return results
|
|
|
|
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=request.env.context.get('lang') or 'en_US'), 0)
|
|
} for d in date_list]
|
|
|
|
return sales_graph
|