forked from DGNum/gestioCOF
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:
parent
3f4a1adbb9
commit
06572f0bb5
3 changed files with 149 additions and 153 deletions
113
kfet/views.py
113
kfet/views.py
|
@ -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'],
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue