Commit 1c4e9b3f by François C.

Sales average computation improvements

parent c7f65956
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from openerp import _, api, models, fields from openerp import _, api, models, fields
import datetime
import numpy
class LaCagetteProducts(models.Model): class LaCagetteProducts(models.Model):
_name = "lacagette.products" _name = "lacagette.products"
...@@ -106,6 +108,80 @@ class LaCagetteProducts(models.Model): ...@@ -106,6 +108,80 @@ class LaCagetteProducts(models.Model):
return res return res
def _compte_consecutive_non_sale_days(self, sale_days, days):
"""
@sale_days : list of sale days
@days: list of full period days (except excluded one, such as sundays)
@return : integer days to remove from days number to compute average
"""
minimum_significative_consecutive_days = 5 # arbitrary set (TODO ? : set it in odoo parameters)
consecutive_found = [] # each serie is added to compute total of them
missing_days = []
for d in days:
if not (d in sale_days):
missing_days.append(d)
current_consecutive_number = 1
for i in range(len(missing_days)):
if i > 0:
current_day = datetime.datetime.strptime(missing_days[i], "%Y-%m-%d")
previous_day = datetime.datetime.strptime(missing_days[i-1], "%Y-%m-%d")
if (current_day - previous_day).days == 1:
current_consecutive_number += 1
else:
if current_consecutive_number >= minimum_significative_consecutive_days:
consecutive_found.append(current_consecutive_number)
current_consecutive_number = 1
return int(numpy.sum(consecutive_found))
def _compute_product_template_sales_average(self, ids, days, result):
res = []
products_qtys = {} # used to compute totals and sigma
products_discounts = {} # used to compute totals
products_sums = {} # used to sum daily sales quantity
found_ids = [] # used to set not found product results to 0
products_sale_days = {} # used to compute consecutive non sale days (to fit average)
for p in result:
pid = p['tpl_id']
found_ids.append(pid)
if not (pid in products_sale_days):
products_sale_days[pid] = [p['day']]
else:
products_sale_days[pid].append(p['day'])
if not (pid in products_qtys):
products_qtys[pid] = [p['qtys']]
else:
products_qtys[pid].append(p['qtys'])
if not (pid in products_discounts):
products_discounts[pid] = [p['discounts']]
else:
products_discounts[pid].append(p['discounts'])
if not (pid in products_sums):
products_sums[pid] = {'total_qty': p['qtys'], 'total_discount': p['discounts']}
else:
products_sums[pid]['total_qty'] += p['qtys']
products_sums[pid]['total_discount'] += p['discounts']
for i in ids:
average_qty = average_discount = sigma = 0
vpc = 1 # Void PerCent (percant of non sales days)
if (i in found_ids):
days_nb_to_remove = self._compte_consecutive_non_sale_days(products_sale_days[i], days)
significative_days = len(days) - days_nb_to_remove
if significative_days > 0:
average_qty = round(numpy.sum(products_qtys[i])/significative_days, 2)
average_discount = round(numpy.sum(products_discounts[i])/significative_days, 2)
# to compute sigma, add 0 for non_sales_days
void = []
for j in range(len(days) - len(products_sale_days[i])):
void.append(0)
sigma = round(numpy.std(products_qtys[i] + void), 2)
vpc = round((float(len(days)) - len(products_sale_days[i]))/len(days), 2)
res.append({'id': i, 'average_qty': average_qty, 'average_discount': average_discount, 'sigma': sigma, 'vpc': vpc})
return res
@api.model @api.model
def get_template_products_sales_average(self, params={}): def get_template_products_sales_average(self, params={}):
"""Retrieve products sales average. """Retrieve products sales average.
...@@ -116,7 +192,6 @@ class LaCagetteProducts(models.Model): ...@@ -116,7 +192,6 @@ class LaCagetteProducts(models.Model):
if 'ids' in params: if 'ids' in params:
ids = list(filter(lambda x: isinstance(x, int), params['ids'])) ids = list(filter(lambda x: isinstance(x, int), params['ids']))
if len(ids) > 0: if len(ids) > 0:
import datetime
today = datetime.date.today() today = datetime.date.today()
excluded_days = [0] excluded_days = [0]
if 'excluded_days' in params: if 'excluded_days' in params:
...@@ -161,21 +236,8 @@ class LaCagetteProducts(models.Model): ...@@ -161,21 +236,8 @@ class LaCagetteProducts(models.Model):
""" """
self.env.cr.execute(sql_dates) self.env.cr.execute(sql_dates)
days = list(filter(lambda x: not (x['dow'] in excluded_days), self.env.cr.dictfetchall())) days = list(filter(lambda x: not (x['dow'] in excluded_days), self.env.cr.dictfetchall()))
days = map(lambda x: x['ddate'], days)
res['list'] = [] res['list'] = self._compute_product_template_sales_average(ids, days, req_res)
products_sums = {}
for p in req_res:
pid = p['tpl_id']
if not (pid in products_sums):
products_sums[pid] = {'total_qty': p['qtys'], 'total_discount': p['discounts']}
else:
products_sums[pid]['total_qty'] += p['qtys']
products_sums[pid]['total_discount'] += p['discounts']
for pid, val in products_sums.items():
res['list'].append({'id': pid,
'average_qty': round(val['total_qty']/len(days),2),
'average_discount': round(val['total_discount']/len(days),2)})
except Exception as e: except Exception as e:
res['error'] = str(e) res['error'] = str(e)
else: else:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment