Order create use Scale.

Order create view use WeekScale. No query improvements, only shorter
code.

Scale/ScaleMixin:
- Two methods directly relative to the Scale class move to... the Scale
  class.

- Fix order create on Chrome.
This commit is contained in:
Aurélien Delobelle 2017-04-13 14:11:44 +02:00
parent 3f4a1adbb9
commit 06572f0bb5
3 changed files with 149 additions and 153 deletions

View file

@ -50,7 +50,7 @@ from decimal import Decimal
import django_cas_ng
import heapq
import statistics
from kfet.statistic import ScaleMixin, last_stats_manifest, tot_ventes
from kfet.statistic import ScaleMixin, last_stats_manifest, tot_ventes, WeekScale
class Home(TemplateView):
@ -1798,68 +1798,60 @@ class OrderList(ListView):
context['suppliers'] = Supplier.objects.order_by('name')
return context
@teamkfet_required
def order_create(request, pk):
supplier = get_object_or_404(Supplier, pk=pk)
articles = (Article.objects
.filter(suppliers=supplier.pk)
.distinct()
.select_related('category')
.order_by('category__name', 'name'))
articles = (
Article.objects
.filter(suppliers=supplier.pk)
.distinct()
.select_related('category')
.order_by('category__name', 'name')
)
initial = []
today = timezone.now().date()
sales_q = (Operation.objects
# Force hit to cache
articles = list(articles)
sales_q = (
Operation.objects
.select_related('group')
.filter(article__in=articles, canceled_at=None)
.values('article'))
sales_s1 = (sales_q
.filter(
group__at__gte = today-timedelta(weeks=5),
group__at__lt = today-timedelta(weeks=4))
.values('article')
.annotate(nb=Sum('article_nb'))
)
sales_s1 = { d['article']:d['nb'] for d in sales_s1 }
sales_s2 = (sales_q
.filter(
group__at__gte = today-timedelta(weeks=4),
group__at__lt = today-timedelta(weeks=3))
.annotate(nb=Sum('article_nb'))
)
sales_s2 = { d['article']:d['nb'] for d in sales_s2 }
sales_s3 = (sales_q
.filter(
group__at__gte = today-timedelta(weeks=3),
group__at__lt = today-timedelta(weeks=2))
.annotate(nb=Sum('article_nb'))
)
sales_s3 = { d['article']:d['nb'] for d in sales_s3 }
sales_s4 = (sales_q
.filter(
group__at__gte = today-timedelta(weeks=2),
group__at__lt = today-timedelta(weeks=1))
.annotate(nb=Sum('article_nb'))
)
sales_s4 = { d['article']:d['nb'] for d in sales_s4 }
sales_s5 = (sales_q
.filter(group__at__gte = today-timedelta(weeks=1))
.annotate(nb=Sum('article_nb'))
)
sales_s5 = { d['article']:d['nb'] for d in sales_s5 }
scale = WeekScale(last=True, n_steps=5, std_chunk=False)
chunks = scale.chunkify_qs(sales_q, field='group__at')
sales = []
for chunk in chunks:
sales.append(
{d['article']: d['nb'] for d in chunk}
)
initial = []
for article in articles:
v_s1 = sales_s1.get(article.pk, 0)
v_s2 = sales_s2.get(article.pk, 0)
v_s3 = sales_s3.get(article.pk, 0)
v_s4 = sales_s4.get(article.pk, 0)
v_s5 = sales_s5.get(article.pk, 0)
# Get sales for each 5 last weeks
v_s1 = sales[0].get(article.pk, 0)
v_s2 = sales[1].get(article.pk, 0)
v_s3 = sales[2].get(article.pk, 0)
v_s4 = sales[3].get(article.pk, 0)
v_s5 = sales[4].get(article.pk, 0)
v_all = [v_s1, v_s2, v_s3, v_s4, v_s5]
# Take the 3 greatest (eg to avoid 2 weeks of vacations)
v_3max = heapq.nlargest(3, v_all)
# Get average and standard deviation
v_moy = statistics.mean(v_3max)
v_et = statistics.pstdev(v_3max, v_moy)
# Expected sales for next week
v_prev = v_moy + v_et
# We want to have 1.5 * the expected sales in stock
# (because sometimes some articles are not delivered)
c_rec_tot = max(v_prev * 1.5 - article.stock, 0)
# If ordered quantity is close enough to a level which can led to free
# boxes, we increase it to this level.
if article.box_capacity:
c_rec_temp = c_rec_tot / article.box_capacity
if c_rec_temp >= 10:
@ -1889,8 +1881,9 @@ def order_create(request, pk):
})
cls_formset = formset_factory(
form = OrderArticleForm,
extra = 0)
form=OrderArticleForm,
extra=0,
)
if request.POST:
formset = cls_formset(request.POST, initial=initial)
@ -1907,14 +1900,15 @@ def order_create(request, pk):
order.save()
saved = True
article = articles.get(pk=form.cleaned_data['article'].pk)
article = form.cleaned_data['article']
q_ordered = form.cleaned_data['quantity_ordered']
if article.box_capacity:
q_ordered *= article.box_capacity
OrderArticle.objects.create(
order = order,
article = article,
quantity_ordered = q_ordered)
order=order,
article=article,
quantity_ordered=q_ordered,
)
if saved:
messages.success(request, 'Commande créée')
return redirect('kfet.order.read', order.pk)
@ -1926,9 +1920,10 @@ def order_create(request, pk):
return render(request, 'kfet/order_create.html', {
'supplier': supplier,
'formset' : formset,
'formset': formset,
})
class OrderRead(DetailView):
model = Order
template_name = 'kfet/order_read.html'
@ -2378,8 +2373,8 @@ class AccountStatOperation(ScaleMixin, PkUrlMixin, JSONDetailView):
)
if types is not None:
all_operations = all_operations.filter(type__in=types)
chunks = self.get_by_chunks(
all_operations, scale, field_db='group__at',
chunks = scale.get_by_chunks(
all_operations, field_db='group__at',
field_callback=(lambda d: d['group__at']),
)
return chunks
@ -2462,12 +2457,12 @@ class ArticleStatSales(ScaleMixin, JSONDetailView):
liq_only = all_purchases.filter(group__on_acc__trigramme='LIQ')
liq_exclude = all_purchases.exclude(group__on_acc__trigramme='LIQ')
chunks_liq = self.get_by_chunks(
liq_only, scale, field_db='group__at',
chunks_liq = scale.get_by_chunks(
liq_only, field_db='group__at',
field_callback=lambda d: d['group__at'],
)
chunks_no_liq = self.get_by_chunks(
liq_exclude, scale, field_db='group__at',
chunks_no_liq = scale.get_by_chunks(
liq_exclude, field_db='group__at',
field_callback=lambda d: d['group__at'],
)