remotes/origin/artem
Gena 11 years ago
parent 66b134174a
commit 1927e0047b
  1. 68
      accounts/admin.py
  2. 4
      accounts/forms.py
  3. 33
      accounts/migrations/0001_initial.py
  4. 24
      accounts/migrations/0002_auto_20150611_2306.py
  5. 67
      accounts/models.py
  6. 10
      accounts/urls.py
  7. 6
      accounts/views.py
  8. 2
      api/views.py
  9. 9
      batiskaf/jinja2.py
  10. 31
      batiskaf/settings.py
  11. 4
      batiskaf/templates/jinja2/accounts/login.jinja
  12. 82
      batiskaf/templates/jinja2/bootstrapform/field.jinja
  13. 16
      batiskaf/templates/jinja2/bootstrapform/form.jinja
  14. 13
      batiskaf/templates/jinja2/bootstrapform/formset.jinja
  15. 53
      batiskaf/templates/jinja2/cart_detail.jinja
  16. 12
      batiskaf/templates/jinja2/order_ok.jinja
  17. 36
      batiskaf/templates/jinja2/order_print.jinja
  18. 1
      batiskaf/templates/jinja2/product.jinja
  19. 8
      batiskaf/urls.py
  20. 193
      static/js/_.js
  21. 6
      static/less/_.css
  22. 7
      static/less/_.less
  23. 69
      store/alemtat.py
  24. 7
      store/cart.py
  25. 9
      store/forms.py
  26. 31
      store/migrations/0013_auto_20150611_2306.py
  27. 24
      store/migrations/0014_auto_20150612_0050.py
  28. 19
      store/migrations/0015_orderdata_items.py
  29. 22
      store/models.py
  30. 1
      store/urls.py
  31. 43
      store/views.py

@ -1,3 +1,69 @@
from django.contrib import admin
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from .models import Profile
class ProfileCreationForm(forms.ModelForm):
password1 = forms.CharField(label='Пароль', widget=forms.PasswordInput)
password2 = forms.CharField(label='Подтверждение', widget=forms.PasswordInput)
class Meta:
model = Profile
fields = ('phone', 'email')
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Пароли не совпадают")
return password2
def save(self, commit=True):
user = super(ProfileCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class ProfileChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = Profile
fields = ('phone', 'email', 'password', 'is_active', 'is_superuser')
def clean_password(self):
return self.initial["password"]
class ProfileAdmin(UserAdmin):
form = ProfileChangeForm
add_form = ProfileCreationForm
list_display = ('phone', 'first_name', 'last_name', 'email', 'is_superuser', 'date_joined')
list_filter = ('is_superuser',)
fieldsets = (
(None, {'fields': (
'phone', 'email', 'password', 'first_name', 'last_name'
)}),
('Инфо', {'fields': ('date_joined',)}),
('Доступ', {'fields': ('is_superuser', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('phone', 'email', 'first_name', 'last_name', 'password1', 'password2')}
),
)
search_fields = ('phone', 'email',)
ordering = ('phone', 'email',)
filter_horizontal = ()
# Register your models here.
admin.site.register(Profile, ProfileAdmin)
admin.site.unregister(Group)

@ -0,0 +1,4 @@
from django import forms
class LoginForm(forms.Form):
phone = forms.CharField(label='Телефон', max_length=15)

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import datetime
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='Profile',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
('password', models.CharField(verbose_name='password', max_length=128)),
('last_login', models.DateTimeField(verbose_name='last login', blank=True, null=True)),
('phone', models.CharField(verbose_name='Телефон', db_index=True, max_length=15, unique=True)),
('email', models.EmailField(verbose_name='Email', db_index=True, default=None, max_length=254, unique=True)),
('first_name', models.CharField(verbose_name='first name', blank=True, max_length=30)),
('last_name', models.CharField(verbose_name='last name', blank=True, max_length=30)),
('date_joined', models.DateTimeField(verbose_name='Регистрация', default=datetime.datetime.now)),
('is_superuser', models.BooleanField(verbose_name='Админ', default=False)),
('is_active', models.BooleanField(verbose_name='Активный', db_index=True, default=True)),
],
options={
'verbose_name': 'пользователь',
'verbose_name_plural': 'пользователи',
},
),
]

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='first_name',
field=models.CharField(max_length=30, blank=True, verbose_name='Имя'),
),
migrations.AlterField(
model_name='profile',
name='last_name',
field=models.CharField(max_length=30, blank=True, verbose_name='Фамилия'),
),
]

@ -1,3 +1,68 @@
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, AbstractUser, User
from django.core.mail import send_mail
from django.db import models
from datetime import datetime
# Create your models here.
class ProfileManager(BaseUserManager):
def _create_user(self, phone, email, password,
is_superuser, **extra_fields):
now = datetime.now()
if not phone:
raise ValueError('Телефон не может быть пустым')
email = self.normalize_email(email)
user = self.model(phone=phone, email=email,
is_active=True,
is_superuser=is_superuser, last_login=now,
date_joined=now, **extra_fields)
user.set_password(password)
user.save()
return user
def create_user(self, phone, email=None, password=None, **extra_fields):
return self._create_user(phone, email, password, False,
**extra_fields)
def create_superuser(self, phone, email, password, **extra_fields):
return self._create_user(phone, email, password, True,
**extra_fields)
class Profile(AbstractBaseUser):
phone = models.CharField('Телефон', max_length=15, unique=True, db_index=True)
email = models.EmailField('Email', blank=False, null=False, default=None, unique=True, db_index=True)
first_name = models.CharField('Имя', max_length=30, blank=True)
last_name = models.CharField('Фамилия', max_length=30, blank=True)
date_joined = models.DateTimeField('Регистрация', default=datetime.now)
is_superuser = models.BooleanField('Админ', default=False)
is_active = models.BooleanField('Активный', default=True, db_index=True)
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = ['email']
objects = ProfileManager()
class Meta:
verbose_name = 'пользователь'
verbose_name_plural = 'пользователи'
def __str__(self):
return self.phone
def get_full_name(self):
return '{} {}'.format(self.first_name, self.last_name)
def get_short_name(self):
return self.first_name
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
@property
def is_staff(self):
return self.is_superuser
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)

@ -0,0 +1,10 @@
from django.conf.urls import patterns, url
from django.views.generic import RedirectView
from .views import *
urlpatterns = patterns('',
url(r'^$', RedirectView.as_view(
url='/', permanent=True), name='store_index'),
url(r'^login/$', LoginView.as_view(),
name='store_cart_detail'),
)

@ -1,3 +1,7 @@
from django.shortcuts import render
from django.views.generic import FormView
from .forms import *
# Create your views here.
class LoginView(FormView):
form_class = LoginForm
template_name = 'accounts/login.jinja'

@ -8,3 +8,5 @@ class CartSerializer(serializers.Serializer):
class CartViewSet(viewsets.ViewSet):
serializer_class = CartSerializer

@ -1,3 +1,4 @@
from bootstrapform_jinja.templatetags.bootstrap import *
from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.urlresolvers import reverse
from batiskaf.jinja2_ext.thumbnails import thumbnail
@ -17,4 +18,12 @@ def environment(**options):
env.filters['linebreaks'] = linebreaks
env.filters['thumbnail'] = thumbnail
env.filters['cart'] = cart
env.filters['bootstrap'] = bootstrap
env.filters['bootstrap_inline'] = bootstrap_inline
env.filters['bootstrap_horizontal'] = bootstrap_horizontal
env.filters['bootstrap_classes'] = bootstrap_classes
env.filters['is_checkbox'] = is_checkbox
env.filters['is_multiple_checkbox'] = is_multiple_checkbox
env.filters['is_radio'] = is_radio
env.filters['is_file'] = is_file
return env

@ -40,7 +40,11 @@ MESSAGE_TAGS = {
messages.SUCCESS: 'success',
}
# Application definition
AUTH_USER_MODEL = 'accounts.Profile'
LOGIN_URL = '/account/login/'
LOGOUT_URL = '/account/logout/'
INSTALLED_APPS = (
'django.contrib.admin',
@ -53,9 +57,10 @@ INSTALLED_APPS = (
'django_extensions',
'rest_framework',
'easy_thumbnails',
'bootstrap3',
'bootstrapform_jinja',
'batiskaf',
'main',
'accounts',
'store',
)
@ -116,13 +121,13 @@ SERVER_EMAIL = "admin@batiskaf.kz"
LANGUAGE_CODE = 'ru'
TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Almaty'
USE_I18N = True
USE_L10N = True
USE_TZ = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
@ -143,6 +148,16 @@ STATICFILES_DIRS = [
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
os.path.join(BASE_DIR, "batiskaf/templates/jinja2"),
#os.path.join(BASE_DIR, "batiskaf/templates/jinja2/bootstrapform"),
],
'OPTIONS': {
'environment': 'batiskaf.jinja2.environment',
}
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "batiskaf/templates"), ],
@ -160,13 +175,7 @@ TEMPLATES = [
)
},
},
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [os.path.join(BASE_DIR, "batiskaf/templates/jinja2"), ],
'OPTIONS': {
'environment': 'batiskaf.jinja2.environment',
}
},
]
BOOTSTRAP3 = {

@ -0,0 +1,4 @@
{% extends 'base.jinja' %}
{% block content %}
{{ form }}
{% endblock %}

@ -0,0 +1,82 @@
{% macro render_field_checkbox(form, field, classes) -%}
<div class="{{ classes.single_value }}">
<div class="checkbox">
{% if field.auto_id %}
<label {% if field.field.required and form.required_css_class %}class="{{ form.required_css_class }}"{% endif %}>
{{ field|safe }} <span>{{ field.label }}</span>
</label>
{% endif %}
{% for error in field.errors %}
<span class="help-block {{ form.error_css_class }}">{{ error }}</span>
{% endfor %}
{% if field.help_text %}
<p class="help-block">
{{ field.help_text|safe }}
</p>
{% endif %}
</div>
</div>
{%- endmacro %}
{% macro render_field_radio(form, field, classes) -%}
{% if field.auto_id %}
<label class="control-label {{ classes.label }} {% if field.field.required %}{{ form.required_css_class }}{% endif %}">{{ field.label }}</label>
{% endif %}
<div class="{{ classes.value }}">
{% for choice in field %}
<div class="radio">
<label>
{{ choice.tag()|safe }}
{{ choice.choice_label }}
</label>
</div>
{% endfor %}
{% for error in field.errors %}
<span class="help-block {{ form.error_css_class }}">{{ error }}</span>
{% endfor %}
{% if field.help_text %}
<p class="help-block">
{{ field.help_text|safe }}
</p>
{% endif %}
</div>
{%- endmacro %}
{% macro render_field_standard(form, field, classes) -%}
{% if field.auto_id %}
<label class="control-label {{ classes.label }} {% if field.field.required %}{{ form.required_css_class }}{% endif %}" for="{{ field.auto_id }}">{{ field.label }}</label>
{% endif %}
<div class="{{ classes.value }} {% if field|is_multiple_checkbox %}multiple-checkbox{% endif %}">
{{ field|safe }}
{% for error in field.errors %}
<span class="help-block {{ form.error_css_class }}">{{ error }}</span>
{% endfor %}
{% if field.help_text %}
<p class="help-block">
{{ field.help_text|safe }}
</p>
{% endif %}
</div>
{%- endmacro %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
{% if field|is_checkbox %}
{{ render_field_checkbox(form, field, classes) }}
{% elif field|is_radio %}
{{ render_field_radio(form, field, classes) }}
{% else %}
{{ render_field_standard(form, field, classes) }}
{% endif %}
</div>

@ -0,0 +1,16 @@
{% if form.non_field_errors() %}
<div class="alert alert-danger">
<a class="close" data-dismiss="alert">&times;</a>
{% for non_field_error in form.non_field_errors() %}
{{ non_field_error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.hidden_fields() %}
{{ field|safe }}
{% endfor %}
{% for field in form.visible_fields() %}
{% include 'bootstrapform/field.jinja' %}
{% endfor %}

@ -0,0 +1,13 @@
{{ formset.management_form }}
{% for form in formset %}
{% if classes.label == 'sr-only' %}
<div class="form-inline">
{% endif %}
{% include 'bootstrapform/form.jinja' %}
{% if classes.label == 'sr-only' %}
</div>
{% endif %}
{% endfor %}

@ -57,16 +57,67 @@
<tr>
<th colspan="2" class="text-left"><a href="javascript:history.back()" class="">
&larr; Продолжить покупки</a></th>
<th colspan="3" class="text-right table-cart-itogo">Итого: {{ cart.total }} ₸</th>
<th colspan="3" class="text-right table-cart-itogo">Итого: <span id="cart-itogo">{{ cart.total }}</span> ₸</th>
<th class="text-center">
<button type="submit" class="btn btn-primary"><span
class="glyphicon glyphicon-repeat"></span> Пересчитать
</button>
</th>
</tr>
</tfoot>
</table>
</form>
</div><br/>
<hr class="dashed"/><br/>
<h4>Оформление заказа</h4>
<div class="order-data">
<div class="row">
<div class="col-xs-6 col-xs-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Данные доставки</h3>
</div>
<div class="panel-body">
<form action="" class="" method="post"><input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{{ form|bootstrap }}
<br/>
<div class="order-itogo text-right">
Итого: <span id="order-itogo-amount">{{ cart.total }}</span> ₸
</div>
<br/>
<div class="form-group text-center">
<button type="submit" name="order_next" class="btn btn-success">Продолжить</button>
</div>
</form>
</div>
</div>
</div>
{# <div class="col-xs-6">#}
{# <div class="panel panel-default">#}
{# <div class="panel-heading">#}
{# <h3 class="panel-title">Доставка</h3>#}
{# </div>#}
{# <div class="panel-body">#}
{# #}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
{# <div class="row">#}
{# <div class="col-xs-12">#}
{# <div class="panel panel-default">#}
{# <div class="panel-heading">#}
{# <h3 class="panel-title">Способ оплаты</h3>#}
{# </div>#}
{# <div class="panel-body">#}
{# Банковский платеж#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
{% else %}

@ -0,0 +1,12 @@
{% extends 'base.jinja' %}
{% block content %}
<div class="alert alert-success alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4>Спасибо!</h4>
<p>Ваш заказ успешно принят и поступит в обработку сразу после оплаты.</p>
<p><a class="btn btn-success" href="/order/{{ order.pk }}/print/">Распечатать квитанцию для оплаты</a></p>
</div>
{% endblock %}

@ -0,0 +1,36 @@
<table>
<tr>
<td colspan="2" style="border-bottom: 1px black solid">{{ date.strftime('%d.%m.%Y') }}</td>
<td colspan="2" style="border-bottom: 1px black solid"> </td>
<td></td>
<td></td>
<td></td>
<td style="border: 1px black solid">{{ order.pk }}</td>
</tr>
<tr>
<td>Поступ. в банк плат.</td>
<td>Списано со сч. плат.</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="3">ПЛАТЕЖНОЕ ПОРУЧЕНИЕ №2015</td>
<td colspan="2" style="border-bottom: 1px black solid"></td>
<td colspan="2" style="border-bottom: 1px black solid"></td>
<td style="border: 1px black solid">08</td>
</tr>
<tr>
<td style="border-right: 1px black solid; border-bottom: 1px black solid; ">Сумма <br/>прописью</td>
<td colspan="3" style="border-bottom: 1px black solid">Двести тысяч рублей 00 копеек</td>
<td colspan="4" style="border-bottom: 1px black solid"></td>
</tr>
<tr>
<td colspan="2" style="border-right: 1px black solid; border-bottom: 1px black solid; ">ИИН 7708654321</td>
<td colspan="2" style="border-right: 1px black solid; border-bottom: 1px black solid; ">КПП 770801001</td>
<td colspan="4" style="border-bottom: 1px black solid"></td>
</tr>
</table>

@ -73,7 +73,6 @@
<a href="/store/cart/add/?pk={{ variant.pk }}&count=1&next={{ product.get_absolute_url() }}"
class="btn btn-warning btn-block" id="product-add-to-cart-link"><span
class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span> Добавить в корзину</a>
</div>
</div>
</div>

@ -1,5 +1,6 @@
from django.conf.urls import patterns, include, url
from django.contrib import admin
from store.views import order_view, order_print
admin.site.site_header = 'Админка Batiskaf.kz'
admin.site.site_title = 'Админка Batiskaf.kz'
@ -9,6 +10,13 @@ urlpatterns = patterns(
'',
url(r'^$', 'main.views.index',
name='index'),
url(r'^get_order_amount/$', 'store.views.get_order_amount'),
url(r'^order/(?P<order>.+)/print/$', order_print,
name='store_order_print'),
url(r'^order/(?P<order>.+)/$', order_view,
name='store_order_view'),
url(r'^store/', include('store.urls')),
url(r'^account/', include('accounts.urls')),
url(r'^admin2517_garpun/', include(admin.site.urls)),
)

@ -66,110 +66,143 @@ $(document).ready(function () {
});
$('.product-min-thumbnails a').each(function(){
var link = $(this);
link.on('click', function(){
$('.product-big-thumbnail img').prop('src', link.prop('href'));
$('#product-big-img').attr('data-zoom-image', link.attr("data-big-url"));
$('.zoomContainer').remove();
$('#product-big-img').removeData('elevateZoom');
$('#product-big-img').removeData('zoomImage');
$('#product-big-img').elevateZoom({
zoomType: "inner",
cursor: "crosshair",
lensFadeIn: 500,
lensFadeOut: 500,
easing : true
});
$('.product-min-thumbnails a').each(function () {
var link = $(this);
link.on('click', function () {
$('.product-big-thumbnail img').prop('src', link.prop('href'));
$('#product-big-img').attr('data-zoom-image', link.attr("data-big-url"));
$('.zoomContainer').remove();
$('#product-big-img').removeData('elevateZoom');
$('#product-big-img').removeData('zoomImage');
$('#product-big-img').elevateZoom({
zoomType: "inner",
cursor: "crosshair",
lensFadeIn: 500,
lensFadeOut: 500,
easing: true
});
// $('.product-big-thumbnail-container').trigger('zoom.destroy');
// $('.product-big-thumbnail-container').zoom({url: link.attr("data-big-url")});
// $('.product-big-thumbnail-container').trigger('zoom.destroy');
// $('.product-big-thumbnail-container').zoom({url: link.attr("data-big-url")});
//$('a#product-big-image-url').prop('href', link.attr('data-big-url'))
return false;
})
});
$('#product-big-img').elevateZoom({
zoomType: "inner",
cursor: "crosshair",
lensFadeIn: 500,
lensFadeOut: 500,
easing : true
});
});
$('#product-big-img').elevateZoom({
zoomType: "inner",
cursor: "crosshair",
lensFadeIn: 500,
lensFadeOut: 500,
easing: true
});
//$('.product-big-thumbnail-container').zoom({url: $('#product-big-image-url').prop("href")});
function create_cart_add_link(product_pk, count){
return $.param.querystring('/store/cart/add/', 'pk=' + product_pk + '&count=' + count + '&next=' + window.location.pathname);
}
function selectVariation(value, index){
var price = $('.product-variations-selecter option[value=' + value + ']').attr('data-price');
var in_stock = $('.product-variations-selecter option[value=' + value + ']').attr('data-count');
$('.product-detail-price-span').html(price);
if (in_stock > 0){
$(".product-count-selecter").selecter('destroy');
$('.product-in-stock').show();
$('.product-not-in-stock').hide();
$('.product-count-selecter').html('');
for (i=0; i<in_stock; i++){
var option = $('<option/>');
option.attr({ 'value': i+1 }).text((i+1) + ' шт.');
$('.product-count-selecter').append(option);
function create_cart_add_link(product_pk, count) {
return $.param.querystring('/store/cart/add/', 'pk=' + product_pk + '&count=' + count + '&next=' + window.location.pathname);
}
function selectVariation(value, index) {
var price = $('.product-variations-selecter option[value=' + value + ']').attr('data-price');
var in_stock = $('.product-variations-selecter option[value=' + value + ']').attr('data-count');
$('.product-detail-price-span').html(price);
if (in_stock > 0) {
$(".product-count-selecter").selecter('destroy');
$('.product-in-stock').show();
$('.product-not-in-stock').hide();
$('.product-count-selecter').html('');
for (i = 0; i < in_stock; i++) {
var option = $('<option/>');
option.attr({'value': i + 1}).text((i + 1) + ' шт.');
$('.product-count-selecter').append(option);
}
$(".product-count-selecter").selecter({
callback: selectCount
});
selectCount(1, index);
$('#product-add-to-cart-link').prop('href',
create_cart_add_link($('.product-variations-selecter').val(),
$('.product-count-selecter').val()));
} else {
$('.product-count-selecter').selecter('destroy');
$('.product-in-stock').hide();
$('.product-not-in-stock').show();
}
$(".product-count-selecter").selecter({
callback: selectCount
});
selectCount(1, index);
}
$(".product-variations-selecter").selecter({
callback: selectVariation
});
function selectCount(value, index) {
var price = parseInt($('.product-detail-price-span').html());
$('.itogo-span').html(price * value);
$('#product-add-to-cart-link').prop('href',
create_cart_add_link($('.product-variations-selecter').val(),
$('.product-count-selecter').val()));
}else{
$('.product-count-selecter').selecter('destroy');
$('.product-in-stock').hide();
$('.product-not-in-stock').show();
}
}
$(".product-count-selecter").selecter({
callback: selectCount
});
$(".product-variations-selecter").selecter({
callback: selectVariation
});
function selectCount(value, index){
var price = parseInt($('.product-detail-price-span').html());
$('.itogo-span').html(price*value);
$('#product-add-to-cart-link').prop('href',
create_cart_add_link($('.product-variations-selecter').val(),
$('.product-count-selecter').val()));
}
if ($('.product-count-selecter option').size() < 1) {
$('.product-in-stock').hide();
$('.product-not-in-stock').show();
$(".product-count-selecter").selecter({
callback: selectCount
});
} else {
$(".product-count-selecter").selecter();
}
$('ul.messages li').each(function () {
var li = $(this);
var messageType = li.attr('data-type');
swal({
html: true,
type: messageType,
title: "OK!",
text: li.html()
});
});
if ($('.product-count-selecter option').size() < 1){
$('.product-in-stock').hide();
$('.product-not-in-stock').show();
function selectCity(value, index) {
var city = $('#id_city').val();
var deliv = $('#id_deliv_type').val();
var cart_itogo = $('#cart-itogo').html();
var order_itogo = $('#order-itogo-amount');
}else{
$(".product-count-selecter").selecter();
}
if (city && deliv) {
$.ajax({
method: "GET",
url: "/get_order_amount/",
data: {
city: city,
deliv: deliv,
$('ul.messages li').each(function(){
var li = $(this);
var messageType = li.attr('data-type');
swal({
html: true,
type: messageType,
title: "OK!",
text: li.html()
}
})
.done(function (msg) {
order_itogo.html(
parseFloat(msg.AmountPlusFSAmount) + parseFloat(cart_itogo)
);
});
} else {
order_itogo.html(cart_itogo);
}
}
});
});
$('#id_city').selecter({
callback: selectCity
});
$('#id_deliv_type').selecter({
callback: selectCity
});
});

@ -949,3 +949,9 @@ ul.messages {
padding-top: 20px;
border-top: 1px #ddd solid;
}
.order-data .radio {
margin-left: 15px;
}
#order-itogo-amount {
font-size: 20px;
}

@ -790,4 +790,11 @@ ul.messages {
margin-top: 40px;
padding-top: 20px;
border-top: 1px #ddd solid;
}
.order-data .radio{
margin-left: 15px;
}
#order-itogo-amount{
font-size: 20px;
}

@ -0,0 +1,69 @@
import requests
class AlemTat(object):
COUNTRY_CODE = '0001'
CITY_CODE = '000003'
API_KEY = '677a8773-c647-4b8f-8968-32a67d55e0d3'
CONTRACT = '05828/ИМ'
def _build_url(self, url):
# url = url.replace('\{ext\}', API_KEY)
retval = url
if '?' in url:
retval = url + '&ApiKey={}'.format(self.API_KEY)
else:
retval = url + '?ApiKey={}'.format(self.API_KEY)
return retval
def get_cities(self):
url = self._build_url(
'http://api.alemtat.kz/web/{ext}/Catalog/getCitiesByCountry?CountryLocalCode={}'.format(self.COUNTRY_CODE, ext=self.API_KEY))
r = requests.get(url)
return r.json()
def get_cities_tuple(self):
retval = map(lambda cities: (cities['LocalCode'], '{} - {}'.format(cities['LocalityName'].title(), cities[
'Region'].capitalize())), self.get_cities())
return tuple(retval)
def get_services(self):
url = self._build_url(
'http://api.alemtat.kz/web/{ext}/Catalog/getServices'.format(ext=self.API_KEY))
r = requests.get(url)
return r.json()
def get_services_tuple(self):
retval = map(lambda services: (services['LocalCode'], services['Name'],), self.get_services())
return tuple(retval)
# def get_services_tuple(self):
# retval = map(lambda cities: (cities['LocalCode'], '{} - {}'.format(cities['LocalityName'].title(), cities[
# 'Region'].capitalize())), self.get_cities())
# return tuple(retval)
def get_amount(self, to, places, weight, service):
url = self._build_url(
'http://api.alemtat.kz/web/{ext}/Calc/getAmount'.format(ext=self.API_KEY))
post_data = dict(
FromCountryCode=self.COUNTRY_CODE,
FromLocalCode=self.CITY_CODE,
ToCountryCode=self.COUNTRY_CODE,
ToLocalCode=to,
ServiceLocalCode=service,
Places=places,
Weight=weight,
Contract=self.CONTRACT,
)
r = requests.post(url, data=post_data)
return r.json()
def alemtat_get_cities_tuple():
a = AlemTat()
return a.get_cities_tuple()
def alemtat_get_services_tuple():
a = AlemTat()
return a.get_services_tuple()

@ -21,6 +21,7 @@ class Cart(object):
items = []
json_items = []
total = 0
weight = 0.1
items_format = {'items': [], 'total': 0}
def __init__(self, request):
@ -37,11 +38,13 @@ class Cart(object):
def deserialize_items(self):
for j in self.json_items['items']:
variation = ProductVariation.objects.get(
pk=j['product'])
item = CartItem(
ProductVariation.objects.get(
pk=j['product']), j['count'], j['id'])
variation, j['count'], j['id'])
self.items.append(item)
self.total += int(item.subtotal)
self.weight += variation.weight
return self
def serialize_items(self):

@ -0,0 +1,9 @@
from django import forms
from store.alemtat import alemtat_get_services_tuple
from store.models import OrderData
class OrderForm(forms.ModelForm):
class Meta:
model = OrderData
fields = ['first_name', 'last_name', 'phone', 'email', 'city', 'address', 'deliv_type']

File diff suppressed because one or more lines are too long

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('store', '0013_auto_20150611_2306'),
]
operations = [
migrations.AddField(
model_name='orderdata',
name='deliv_type',
field=models.CharField(verbose_name='Способ доставки', choices=[('E', 'Экспресс-отправления по РК'), ('T', 'Не срочные отправления по РК'), ('A', 'Автоконсолидация по РК'), ('C', 'Доставка по городу')], max_length=2, default=''),
),
migrations.AlterField(
model_name='orderdata',
name='address',
field=models.CharField(verbose_name='Адрес', max_length=100),
),
]

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('store', '0014_auto_20150612_0050'),
]
operations = [
migrations.AddField(
model_name='orderdata',
name='items',
field=models.CharField(default='', verbose_name='Товары', max_length=256),
),
]

@ -2,6 +2,7 @@ from django.db import models
from django.contrib.postgres.fields import ArrayField
from decimal import *
from django.db.models import Count, Min
from store.alemtat import alemtat_get_cities_tuple, alemtat_get_services_tuple
FIELD_TYPE_CHAR = 'char'
FIELD_TYPE_INT = 'int'
@ -202,6 +203,8 @@ class ProductVariation(models.Model):
'В наличии (шт.)', default=1, null=False, blank=False)
article = models.CharField(
'Артикул', max_length=32, null=True, blank=True, default='')
weight = models.FloatField('Вес (кг)', default=0.1, null=False, blank=False)
#weight = models.FloatField('Вес (кг)', default=0.1, null=False, blank=False)
class Meta:
verbose_name = 'разновидность товара'
@ -244,3 +247,22 @@ class ImageInProduct(models.Model):
class Meta:
verbose_name = 'фото товара'
verbose_name_plural = 'фото товаров'
class OrderData(models.Model):
first_name = models.CharField(
'Имя', max_length=64, blank=False, null=False)
last_name = models.CharField(
'Фамилия', max_length=64, blank=False, null=False)
phone = models.CharField(
'Телефон', max_length=15, blank=False, null=False)
email = models.EmailField(
'Email', blank=False, null=False)
city = models.CharField(
'Город', max_length=20, blank=False, null=False, choices=alemtat_get_cities_tuple())
address = models.CharField(
'Адрес', max_length=100, blank=False, null=False)
deliv_type = models.CharField(
'Способ доставки', max_length=2, blank=False, null=False, default='', choices=alemtat_get_services_tuple())
items = models.CharField(
'Товары', max_length=256, blank=False, null=False, default='')

@ -7,6 +7,7 @@ urlpatterns = patterns('',
url='/', permanent=True), name='store_index'),
url(r'^cart/$', CartDetailView.as_view(),
name='store_cart_detail'),
url(r'^cart/add/$', CartAddView.as_view(
permanent=False), name='store_cart_add'),
url(r'^cart/remove/$', CartRemoveView.as_view(

@ -1,11 +1,14 @@
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, render
from django.views.generic import *
from batiskaf.jinja2_ext.html_filters import escape
from .models import *
from store.alemtat import AlemTat
from store.cart import Cart, CartItem
from django.contrib import messages
from store.forms import OrderForm
from django.http import JsonResponse
from datetime import datetime
class CategoryBaseView(object):
category = None
@ -165,9 +168,45 @@ class CartDetailView(TemplateView):
def get_context_data(self, **kwargs):
retval = super(CartDetailView, self).get_context_data()
retval['cart'] = Cart(self.request)
retval['form'] = OrderForm(self.request.POST or None)
#retval['form_delivs'] = DelivsForm()
return retval
def post(self, request, *args, **kwargs):
cart = Cart(self.request)
cart.update_items()
if 'order_next' in self.request.POST:
form = OrderForm(self.request.POST)
if form.is_valid():
order = form.save()
json_items = map(lambda items: {items.item.pk: items.count}, cart.items)
order.items = str(list(json_items))
order.save()
else:
return self.render_to_response(self.get_context_data())
return redirect(self.request.path)
def get_order_amount(request):
retval = None
a = AlemTat()
cart = Cart(request)
retval = dict(a.get_amount(
request.GET['city'],
len(cart.items),
cart.weight,
request.GET['deliv'],
))
return JsonResponse(retval)
def order_view(request, order):
order = get_object_or_404(OrderData, pk=order)
c = dict(order=order)
return render(request, 'order_ok.jinja', c)
def order_print(request, order):
order = get_object_or_404(OrderData, pk=order)
c = dict(order=order, date=datetime.now())
return render(request, 'order_print.jinja', c)
Loading…
Cancel
Save