Compare commits
No commits in common. 'master' and 'stepan-k' have entirely different histories.
47 changed files with 81 additions and 1160 deletions
@ -1,7 +0,0 @@ |
|||||||
from __future__ import absolute_import, unicode_literals |
|
||||||
|
|
||||||
# This will make sure the app is always imported when |
|
||||||
# Django starts so that shared_task will use this app. |
|
||||||
from .celery import app as celery_app |
|
||||||
|
|
||||||
__all__ = ['celery_app'] |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
|
|
||||||
from django.conf import settings |
|
||||||
|
|
||||||
|
|
||||||
def dev(request): |
|
||||||
try: |
|
||||||
PROD_MODE = settings.PROD_MODE |
|
||||||
except AttributeError: |
|
||||||
PROD_MODE = True |
|
||||||
|
|
||||||
context = { |
|
||||||
'PROD_MODE': PROD_MODE |
|
||||||
} |
|
||||||
context['request'] = request |
|
||||||
return context |
|
||||||
@ -1,11 +1,7 @@ |
|||||||
from easy_thumbnails.files import get_thumbnailer |
from easy_thumbnails.files import get_thumbnailer |
||||||
from easy_thumbnails.exceptions import InvalidImageFormatError |
|
||||||
|
|
||||||
|
|
||||||
def thumbnail(img, size='420x420'): |
def thumbnail(img, size='420x420'): |
||||||
weight, height = size.split('x') |
weight, height = size.split('x') |
||||||
options = {'size': (int(weight), int(height)), 'background': '#fff'} |
options = {'size': (int(weight), int(height)), 'background': '#fff'} |
||||||
try: |
return get_thumbnailer(img).get_thumbnail(options) |
||||||
return get_thumbnailer(img).get_thumbnail(options) |
|
||||||
except (ValueError, InvalidImageFormatError): |
|
||||||
return {'url': ''} |
|
||||||
|
|||||||
@ -1,29 +0,0 @@ |
|||||||
{% extends 'base.jinja' %} |
|
||||||
|
|
||||||
{% block meta_description %}{% endblock %} |
|
||||||
|
|
||||||
{% block title %} |
|
||||||
Поймай свою цену |
|
||||||
{% endblock %} |
|
||||||
|
|
||||||
{% block stylesheet %}{% endblock stylesheet %} |
|
||||||
|
|
||||||
|
|
||||||
{% block jss %} |
|
||||||
<script src="/static/js/dtys.js"></script> |
|
||||||
{% endblock jss %} |
|
||||||
|
|
||||||
|
|
||||||
{% block content %} |
|
||||||
<div class="index-goods"> |
|
||||||
<div class="row"> |
|
||||||
<h1>Поймай свою цену</h1> |
|
||||||
|
|
||||||
<div class="dtys"> |
|
||||||
{% for object in object_list %} |
|
||||||
{% include "includes/dtys_product_thumb.jinja" with context %} |
|
||||||
{% endfor %} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{% endblock content %} |
|
||||||
@ -1,50 +0,0 @@ |
|||||||
<div class="col-md-4 col-xs-4 col-sm-4 col-lg-4"> |
|
||||||
<div class="thumbnail dtys__product {% if object.is_stopped %}stopped{% endif %}" id="dtys_product_{{ object.id }}"> |
|
||||||
<div class="wait-block"> |
|
||||||
<span class="wait-icon glyphicon glyphicon-refresh glyphicon-refresh-animate"></span> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="sold-block alert-danger"> |
|
||||||
<div class="sold-block__message">Продано!</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
{% set product = object.product.product %} |
|
||||||
{% set im = product.main_image()|thumbnail("420x420") %} |
|
||||||
|
|
||||||
<a> |
|
||||||
<img src="/static/{{ im.url|watermark('medium-photo') }}" |
|
||||||
class="img-responsive" alt="Купить {{ product.title }}" |
|
||||||
title="Купить {{ product.title }}" width="210" height="210"> |
|
||||||
</a> |
|
||||||
|
|
||||||
<div class="caption"> |
|
||||||
<div class="title"> |
|
||||||
<span> |
|
||||||
{{ product.title }} |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="price counter"> |
|
||||||
{% if not object.is_stopped %} |
|
||||||
{{ object.current_price_format() }} |
|
||||||
{% else %} |
|
||||||
{{ object.price_stopped }} |
|
||||||
{% endif %} |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="in-cart"> |
|
||||||
<a class="btn btn-warning btn-block add-to-cart" |
|
||||||
href="/dtys/buy/{{ object.id }}/" |
|
||||||
{% if object.is_stopped %}style="display: none"{% endif %}> |
|
||||||
<span><i class="glyphicon glyphicon-shopping-cart" |
|
||||||
aria-hidden="true"></i> Добавить в корзину</span> |
|
||||||
</a> |
|
||||||
|
|
||||||
<span class="btn btn-warning btn-block fake-add-to-cart" {% if not object.is_stopped %}style="display: none"{% endif %}> |
|
||||||
<span><i class="glyphicon glyphicon-shopping-cart" |
|
||||||
aria-hidden="true"></i> Добавить в корзину</span> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
DTYS |
|
||||||
|
|
||||||
Для возврата незаказанного товара нужно чтобы работал celery |
|
||||||
Его нужно запустить со следующими параметрами: |
|
||||||
|
|
||||||
celery -A dtys.tasks worker --loglevel=info |
|
||||||
|
|
||||||
|
|
||||||
Выбранный (остановленный) товар возвращается на страницу после некоторого |
|
||||||
количества секунд, указанного в settings.RESUME_DTYS_DELAY_SECONDS |
|
||||||
@ -1 +0,0 @@ |
|||||||
default_app_config = 'dtys.apps.DtysConfig' |
|
||||||
@ -1,14 +0,0 @@ |
|||||||
from django.contrib import admin |
|
||||||
|
|
||||||
from .models import DTYSModel |
|
||||||
|
|
||||||
|
|
||||||
@admin.register(DTYSModel) |
|
||||||
class DTYSModelAdmin(admin.ModelAdmin): |
|
||||||
raw_id_fields = ('product',) |
|
||||||
list_display = ( |
|
||||||
'id', |
|
||||||
'product', |
|
||||||
'is_stopped', |
|
||||||
'is_public' |
|
||||||
) |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
from django.apps import AppConfig |
|
||||||
|
|
||||||
|
|
||||||
class DtysConfig(AppConfig): |
|
||||||
"""Drop `Til You Shop""" |
|
||||||
|
|
||||||
name = 'dtys' |
|
||||||
verbose_name = "Поймай свою цену" |
|
||||||
@ -1,34 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-10-26 22:45 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
import django.db.models.deletion |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0061_auto_20170603_0220'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.CreateModel( |
|
||||||
name='DTYSModel', |
|
||||||
fields=[ |
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
||||||
('price_start', models.IntegerField()), |
|
||||||
('price_end', models.IntegerField()), |
|
||||||
('price_stopped', models.IntegerField(blank=True, null=True)), |
|
||||||
('start_date', models.DateField()), |
|
||||||
('start_time', models.TimeField()), |
|
||||||
('end_date', models.DateField()), |
|
||||||
('end_time', models.TimeField()), |
|
||||||
('is_stopped', models.BooleanField(default=False)), |
|
||||||
('is_public', models.BooleanField(default=False)), |
|
||||||
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.ProductVariation')), |
|
||||||
], |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,65 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-11-03 21:58 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('dtys', '0001_initial'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='is_ordered', |
|
||||||
field=models.BooleanField(default=False, verbose_name='Заказан'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='end_date', |
|
||||||
field=models.DateField(verbose_name='Дата окончания'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='end_time', |
|
||||||
field=models.TimeField(verbose_name='Время окончания'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='is_public', |
|
||||||
field=models.BooleanField(default=False, verbose_name='Опубликован'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='is_stopped', |
|
||||||
field=models.BooleanField(default=False, verbose_name='Остановлен'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='price_end', |
|
||||||
field=models.IntegerField(verbose_name='Конечная цена (минимальная)'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='price_start', |
|
||||||
field=models.IntegerField(verbose_name='Начальная цена'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='price_stopped', |
|
||||||
field=models.IntegerField(default=0, verbose_name='Прайс заказа'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='start_date', |
|
||||||
field=models.DateField(verbose_name='Дата начала'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='dtysmodel', |
|
||||||
name='start_time', |
|
||||||
field=models.TimeField(verbose_name='Время начала'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,95 +0,0 @@ |
|||||||
from datetime import datetime |
|
||||||
|
|
||||||
from django.db import models |
|
||||||
from store.models import ProductVariation |
|
||||||
|
|
||||||
|
|
||||||
def get_change(current, previous): |
|
||||||
if current == previous: |
|
||||||
return 100.0 |
|
||||||
try: |
|
||||||
return (abs(current - previous) / previous) * 100.0 |
|
||||||
except ZeroDivisionError: |
|
||||||
return 0 |
|
||||||
|
|
||||||
|
|
||||||
class DTYSModel(models.Model): |
|
||||||
"""Drop `Til You Shop Model""" |
|
||||||
|
|
||||||
product = models.ForeignKey(ProductVariation) |
|
||||||
|
|
||||||
price_start = models.IntegerField(verbose_name="Начальная цена") |
|
||||||
price_end = models.IntegerField(verbose_name="Конечная цена (минимальная)") |
|
||||||
price_stopped = models.IntegerField(verbose_name="Прайс заказа", default=0) |
|
||||||
|
|
||||||
start_date = models.DateField(verbose_name='Дата начала') |
|
||||||
start_time = models.TimeField(verbose_name='Время начала') |
|
||||||
|
|
||||||
end_date = models.DateField(verbose_name='Дата окончания') |
|
||||||
end_time = models.TimeField(verbose_name='Время окончания') |
|
||||||
|
|
||||||
is_stopped = models.BooleanField(verbose_name="Остановлен", default=False) |
|
||||||
is_public = models.BooleanField(verbose_name="Опубликован", default=False) |
|
||||||
is_ordered = models.BooleanField(verbose_name="Заказан", default=False) |
|
||||||
|
|
||||||
class Meta: |
|
||||||
verbose_name = "Счётчик цены" |
|
||||||
verbose_name_plural = "Счётчики цен" |
|
||||||
|
|
||||||
@property |
|
||||||
def end_datetime(self): |
|
||||||
return datetime.combine(self.end_date, self.end_time) |
|
||||||
|
|
||||||
@property |
|
||||||
def start_datetime(self): |
|
||||||
return datetime.combine(self.start_date, self.start_time) |
|
||||||
|
|
||||||
def get_dec_by_sec(self): |
|
||||||
return "%.1f" % (self.get_price_diff() / self.get_date_delta()) |
|
||||||
|
|
||||||
def get_price_diff(self): |
|
||||||
return self.price_start - self.price_end |
|
||||||
|
|
||||||
def _time_percent(self): |
|
||||||
time_percent = get_change( |
|
||||||
self.get_delta_now(), |
|
||||||
self.get_date_delta() |
|
||||||
) |
|
||||||
return time_percent |
|
||||||
|
|
||||||
def get_delta_now(self): |
|
||||||
"""in seconds""" |
|
||||||
from django.utils import timezone as tz |
|
||||||
_now = tz.now() |
|
||||||
return (self.end_datetime - _now).total_seconds() |
|
||||||
|
|
||||||
def get_date_delta(self): |
|
||||||
""" in seconds """ |
|
||||||
return (self.end_datetime - self.start_datetime).total_seconds() |
|
||||||
|
|
||||||
def get_current_price(self): |
|
||||||
dec_from_price = (self.get_price_diff() * (self._time_percent() / 100)) |
|
||||||
price_current = self.price_start - dec_from_price |
|
||||||
|
|
||||||
return price_current |
|
||||||
|
|
||||||
def current_price_format(self): |
|
||||||
return "%.1f" % self.get_current_price() |
|
||||||
|
|
||||||
def stop(self): |
|
||||||
"""Stop this DTYS""" |
|
||||||
self.is_stopped = True |
|
||||||
|
|
||||||
if self.price_stopped == 0: |
|
||||||
self.price_stopped = max(self.price_end, self.get_current_price()) |
|
||||||
|
|
||||||
self.save() |
|
||||||
|
|
||||||
def save(self, *args, **kwargs): |
|
||||||
if not self.id: |
|
||||||
pass |
|
||||||
|
|
||||||
ProductVariation.objects.filter(id=self.product.id)\ |
|
||||||
.update(has_discount=False) |
|
||||||
|
|
||||||
super(DTYSModel, self).save(*args, **kwargs) |
|
||||||
@ -1,2 +0,0 @@ |
|||||||
celery=4.1.0 |
|
||||||
redis |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
from celery import task |
|
||||||
|
|
||||||
# app = Celery('tasks', broker='redis://localhost:6379/0') |
|
||||||
|
|
||||||
|
|
||||||
@task |
|
||||||
def return_dtys(dtys_id): |
|
||||||
from .models import DTYSModel |
|
||||||
|
|
||||||
DTYSModel.objects.filter(id=dtys_id, is_ordered=False)\ |
|
||||||
.update(is_stopped=False, price_stopped=0) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
from django.test import TestCase |
|
||||||
|
|
||||||
# Create your tests here. |
|
||||||
@ -1,12 +0,0 @@ |
|||||||
from django.conf.urls import patterns, url |
|
||||||
|
|
||||||
from .views import DTYSListView, DTYSInfoView, DTYSBuyView, dtys_modified |
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns( |
|
||||||
'', |
|
||||||
url(r'^$', DTYSListView.as_view()), |
|
||||||
url(r'^updates$', dtys_modified), |
|
||||||
url(r'^info/$', DTYSInfoView.as_view()), |
|
||||||
url(r'^buy/(?P<pk>\d+)/$', DTYSBuyView.as_view()) |
|
||||||
) |
|
||||||
@ -1,165 +0,0 @@ |
|||||||
import os |
|
||||||
|
|
||||||
from django.conf import settings |
|
||||||
from django.http import ( |
|
||||||
Http404, |
|
||||||
HttpResponse, |
|
||||||
HttpResponseRedirect, |
|
||||||
JsonResponse, |
|
||||||
) |
|
||||||
from django.core.cache import cache |
|
||||||
from django.utils import timezone |
|
||||||
from django.views.decorators.http import etag |
|
||||||
from django.views.generic import View, ListView, DetailView |
|
||||||
|
|
||||||
from .models import DTYSModel |
|
||||||
|
|
||||||
import logging |
|
||||||
|
|
||||||
log = logging.getLogger(__name__) |
|
||||||
|
|
||||||
|
|
||||||
DTYS_UPDATE_FILE = os.path.join(settings.MEDIA_ROOT, "dtys_update") |
|
||||||
|
|
||||||
|
|
||||||
def update_dtys_etag(): |
|
||||||
fhandle = open(DTYS_UPDATE_FILE, 'a') |
|
||||||
|
|
||||||
try: |
|
||||||
os.utime(DTYS_UPDATE_FILE, None) |
|
||||||
except FileNotFoundError: |
|
||||||
open(DTYS_UPDATE_FILE, 'a').close() |
|
||||||
finally: |
|
||||||
fhandle.close() |
|
||||||
|
|
||||||
|
|
||||||
def latest_entry(request): |
|
||||||
DTYSModel.objects.filter( |
|
||||||
end_date__lte=timezone.now().date(), |
|
||||||
end_time__lte=timezone.now().time() |
|
||||||
).update(is_stopped=True) |
|
||||||
|
|
||||||
d = DTYSModel.objects.filter( |
|
||||||
is_public=True, |
|
||||||
is_stopped=False |
|
||||||
) |
|
||||||
|
|
||||||
if d.count() != cache.get("dtysETAGCount"): |
|
||||||
cache.set("dtysETAGCount", d.count()) |
|
||||||
update_dtys_etag() |
|
||||||
|
|
||||||
if not os.path.exists(DTYS_UPDATE_FILE): |
|
||||||
update_dtys_etag() |
|
||||||
|
|
||||||
modified = str(os.path.getmtime(DTYS_UPDATE_FILE)) |
|
||||||
|
|
||||||
return modified |
|
||||||
|
|
||||||
|
|
||||||
@etag(latest_entry) |
|
||||||
def dtys_modified(request): |
|
||||||
return HttpResponse('') |
|
||||||
|
|
||||||
|
|
||||||
class DTYSListView(ListView): |
|
||||||
model = DTYSModel |
|
||||||
template_name = "dtys/index.jinja" |
|
||||||
|
|
||||||
def get_queryset(self, *args, **kwargs): |
|
||||||
qs = super(DTYSListView, self).get_queryset(*args, **kwargs) |
|
||||||
qs = qs.filter( |
|
||||||
is_public=True, |
|
||||||
start_date__lte=timezone.now().date(), |
|
||||||
end_date__gte=timezone.now().date(), |
|
||||||
start_time__lte=timezone.now().time(), |
|
||||||
end_time__gte=timezone.now().time() |
|
||||||
) |
|
||||||
if qs.count() == 0: |
|
||||||
raise Http404() |
|
||||||
|
|
||||||
return qs |
|
||||||
|
|
||||||
|
|
||||||
class DTYSBuyView(DetailView): |
|
||||||
model = DTYSModel |
|
||||||
|
|
||||||
def get_queryset(self, *args, **kwargs): |
|
||||||
qs = super(DTYSBuyView, self).get_queryset(*args, **kwargs) |
|
||||||
qs = qs.filter( |
|
||||||
is_public=True, |
|
||||||
start_date__lte=timezone.now().date(), |
|
||||||
end_date__gte=timezone.now().date(), |
|
||||||
start_time__lte=timezone.now().time(), |
|
||||||
end_time__gte=timezone.now().time() |
|
||||||
) |
|
||||||
|
|
||||||
if qs.count() == 0: |
|
||||||
raise Http404() |
|
||||||
|
|
||||||
return qs |
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs): |
|
||||||
obj = self.get_object() |
|
||||||
|
|
||||||
log.debug(obj.id) |
|
||||||
|
|
||||||
if obj.is_public and not obj.is_stopped: |
|
||||||
from store.cart import Cart, CartItem |
|
||||||
from store.models import ProductVariation |
|
||||||
from .tasks import return_dtys |
|
||||||
|
|
||||||
update_dtys_etag() |
|
||||||
|
|
||||||
# stop DTYS for this product |
|
||||||
obj.stop() |
|
||||||
|
|
||||||
ProductVariation.objects.filter(id=obj.product.id)\ |
|
||||||
.update(price=obj.price_stopped) |
|
||||||
obj.product.price = int(obj.price_stopped) |
|
||||||
obj.product.save() |
|
||||||
|
|
||||||
# Add to cart |
|
||||||
cart = Cart(self.request) |
|
||||||
|
|
||||||
cart.add_item(CartItem(obj.product, 1)) |
|
||||||
|
|
||||||
return_dtys.apply_async( |
|
||||||
(obj.id, ), countdown=settings.RESUME_DTYS_DELAY_SECONDS) |
|
||||||
|
|
||||||
return HttpResponseRedirect('/store/cart/') |
|
||||||
|
|
||||||
return HttpResponseRedirect('/dtys/') |
|
||||||
|
|
||||||
|
|
||||||
class DTYSInfoView(View): |
|
||||||
"""Ajax info""" |
|
||||||
|
|
||||||
def get(self, request): |
|
||||||
data = { |
|
||||||
"dtys_list": [] |
|
||||||
} |
|
||||||
|
|
||||||
dtys_list = DTYSModel.objects.filter( |
|
||||||
is_public=True, |
|
||||||
start_date__lte=timezone.now(), |
|
||||||
end_date__gte=timezone.now(), |
|
||||||
start_time__lte=timezone.now().time() |
|
||||||
) |
|
||||||
|
|
||||||
for i in dtys_list: |
|
||||||
if i.end_time <= timezone.now().time(): |
|
||||||
i.stop() |
|
||||||
|
|
||||||
dtys_item = { |
|
||||||
'id': i.id, |
|
||||||
'stopped': i.is_stopped, |
|
||||||
'stopped_price': i.price_stopped |
|
||||||
} |
|
||||||
|
|
||||||
if not i.is_stopped: |
|
||||||
dtys_item['current_price'] = i.current_price_format() |
|
||||||
dtys_item['price_dec_in_sec'] = i.get_dec_by_sec() |
|
||||||
|
|
||||||
data['dtys_list'].append(dtys_item) |
|
||||||
|
|
||||||
return JsonResponse(data) |
|
||||||
@ -1,3 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
|
|
||||||
celery -A batiskaf worker --loglevel=info >> celery.log & |
|
||||||
@ -1,162 +0,0 @@ |
|||||||
function getCookie(name) { |
|
||||||
var cookieValue = null; |
|
||||||
if (document.cookie && document.cookie !== '') { |
|
||||||
var cookies = document.cookie.split(';'); |
|
||||||
for (var i = 0; i < cookies.length; i++) { |
|
||||||
var cookie = cookies[i]; |
|
||||||
// Does this cookie string begin with the name we want?
|
|
||||||
if (cookie.substring(0, name.length + 1) === (name + '=')) { |
|
||||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return cookieValue; |
|
||||||
} |
|
||||||
|
|
||||||
function countdownPrice(el, beginValue, decInSecond) { |
|
||||||
var counter = el.find(".counter"); |
|
||||||
|
|
||||||
counter.text(beginValue); |
|
||||||
|
|
||||||
if (el.attr("data-tid") ) { |
|
||||||
var tid = el.attr("data-tid") |
|
||||||
clearInterval(tid); |
|
||||||
} |
|
||||||
|
|
||||||
var delay = 1000; |
|
||||||
var div = 2.0; |
|
||||||
|
|
||||||
var timerId = setInterval(function(){ |
|
||||||
var val = parseFloat(counter.text()); |
|
||||||
var new_val = (val - (decInSecond / div)).toFixed(); |
|
||||||
counter.text(new_val); |
|
||||||
}, delay / div); |
|
||||||
|
|
||||||
el.attr("data-tid", timerId); |
|
||||||
} |
|
||||||
|
|
||||||
function countdownPriceStop(el) { |
|
||||||
clearInterval(el.attr("data-tid")); |
|
||||||
} |
|
||||||
|
|
||||||
function get_price() { |
|
||||||
$.ajax({ |
|
||||||
url: "/dtys/info/", |
|
||||||
method: "GET", |
|
||||||
success: function(data, textStatus, jqXHR) { |
|
||||||
console.log(data); |
|
||||||
|
|
||||||
if (data.dtys_list.length > 0) { |
|
||||||
var active = data.dtys_list; |
|
||||||
|
|
||||||
active.forEach(function(i, idx, list) { |
|
||||||
var product = $("#dtys_product_" + i.id); |
|
||||||
var add_to_cart_btn = product.find(".add-to-cart"); |
|
||||||
var fake_add_to_cart_btn = product.find(".fake-add-to-cart"); |
|
||||||
|
|
||||||
if (i.stopped) { |
|
||||||
product.addClass("stopped"); |
|
||||||
fake_add_to_cart_btn.show(); |
|
||||||
add_to_cart_btn.hide(); |
|
||||||
|
|
||||||
product.find('.price').text(i.stopped_price); |
|
||||||
|
|
||||||
countdownPriceStop(product); |
|
||||||
} else { |
|
||||||
product.removeClass("stopped"); |
|
||||||
product.find(".price").text(i.current_price); |
|
||||||
fake_add_to_cart_btn.hide(); |
|
||||||
add_to_cart_btn.show(); |
|
||||||
|
|
||||||
countdownPrice(product, i.current_price, i.price_dec_in_sec); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
}, |
|
||||||
error: function(jqXHR, textStatus, errorThrow) { |
|
||||||
console.log("что-то пошло не так, сервер не отвечает"); |
|
||||||
} |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
var Updater = function(){ |
|
||||||
this.params = { |
|
||||||
period: 3000, |
|
||||||
url: '', |
|
||||||
onModified: function(data,x,modified){}, |
|
||||||
bgPause: false |
|
||||||
}; |
|
||||||
|
|
||||||
this.interval = null; |
|
||||||
this.ETag = ''; |
|
||||||
this.lastModified = ''; |
|
||||||
|
|
||||||
this.init = function(params){ |
|
||||||
var me = this; |
|
||||||
this.params = $.extend(this.params, params); |
|
||||||
|
|
||||||
if(this.params.bgPause){ |
|
||||||
$(window).blur(function(){ me.pause() }); |
|
||||||
$(window).focus(function(){ me.resume() }); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
this.start = function(){ |
|
||||||
var me = this; |
|
||||||
this.interval = setInterval(function(){ me.doUpdate() }, this.params.period); |
|
||||||
}; |
|
||||||
|
|
||||||
this.doUpdate = function() { |
|
||||||
var me = this; |
|
||||||
$.ajax(this.params.url, { |
|
||||||
success: function(data,status,x){ |
|
||||||
$(".dtys__product").each(function(){ |
|
||||||
$(this).removeClass("wait"); |
|
||||||
}); |
|
||||||
|
|
||||||
if(me.ETag != x.getResponseHeader('ETag')){ |
|
||||||
me.params.onModified(data,x,me.lastModified); |
|
||||||
me.lastModified = x.getResponseHeader('Last-Modified'); |
|
||||||
} |
|
||||||
me.ETag = x.getResponseHeader('ETag'); |
|
||||||
}, |
|
||||||
error: function(jqXHR, textStatus, errorThrown) { |
|
||||||
$(".dtys__product").each(function(){ |
|
||||||
$(this).addClass("wait"); |
|
||||||
countdownPriceStop($(this)); |
|
||||||
}); |
|
||||||
}, |
|
||||||
beforeSend: function(x){ |
|
||||||
if(me.ETag != '') { x.setRequestHeader('If-None-Match', me.ETag); } |
|
||||||
}, |
|
||||||
cache: false |
|
||||||
}); |
|
||||||
}; |
|
||||||
|
|
||||||
this.pause = function(){ |
|
||||||
clearInterval(this.interval); |
|
||||||
this.interval = null; |
|
||||||
}; |
|
||||||
|
|
||||||
this.resume = function(){ |
|
||||||
if(this.interval != null) return; |
|
||||||
this.start(); |
|
||||||
this.doUpdate(); |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
$(function(){ |
|
||||||
var upd = new Updater(); |
|
||||||
|
|
||||||
get_price(); |
|
||||||
|
|
||||||
upd.init({ |
|
||||||
url: "/dtys/updates", |
|
||||||
onModified: function(data, x, modified) { |
|
||||||
get_price(); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
upd.start(); |
|
||||||
}); |
|
||||||
File diff suppressed because one or more lines are too long
@ -1,19 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import models, migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0044_auto_20151223_1612'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterField( |
|
||||||
model_name='orderdata', |
|
||||||
name='deliv_type', |
|
||||||
field=models.CharField(max_length=2, blank=True, verbose_name='Способ Алемтат', choices=[('E', 'Экспресс-отправления по РК'), ('T', 'Не срочные отправления по РК')], null=True, default=''), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import models, migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0045_auto_20160107_1403'), |
|
||||||
('store', '0045_auto_20151223_1646'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import models, migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0046_merge'), |
|
||||||
('store', '0046_auto_20160202_1121'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import models, migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0047_merge'), |
|
||||||
('store', '0047_auto_20160229_1409'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,15 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import models, migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0048_auto_20160302_0839'), |
|
||||||
('store', '0048_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2016-03-07 20:44 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0049_merge'), |
|
||||||
('store', '0049_auto_20160307_2043'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2016-03-12 16:33 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0050_merge'), |
|
||||||
('store', '0050_auto_20160312_1628'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2016-03-14 11:41 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0051_cartmodel'), |
|
||||||
('store', '0051_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2016-04-04 10:33 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0053_productvariation_delivery_date'), |
|
||||||
('store', '0052_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2016-07-15 19:20 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0054_merge'), |
|
||||||
('store', '0054_auto_20160715_1811'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-03-07 15:49 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0057_auto_20170306_1933'), |
|
||||||
('store', '0055_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-05-07 02:57 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0059_auto_20170506_1116'), |
|
||||||
('store', '0058_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,25 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-06-03 02:27 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0060_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterField( |
|
||||||
model_name='orderdata', |
|
||||||
name='city', |
|
||||||
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='Город Алемтат'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='orderdata', |
|
||||||
name='deliv_type', |
|
||||||
field=models.CharField(blank=True, default='', max_length=2, null=True, verbose_name='Способ Алемтат'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-06-03 02:28 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0061_auto_20170603_0220'), |
|
||||||
('store', '0061_auto_20170603_0227'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-11-07 16:56 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0061_auto_20170603_0220'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='productvariation', |
|
||||||
name='has_discount', |
|
||||||
field=models.BooleanField(default=True, help_text='Если не указано, то скидка при расчёте цены не учитывается', verbose_name='Со скидкой'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,16 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.9.3 on 2017-11-07 18:10 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('store', '0062_productvariation_has_discount'), |
|
||||||
('store', '0062_merge'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
] |
|
||||||
Loading…
Reference in new issue