lyh 1 年間 前
コミット
5d15c5cd27

+ 16 - 2
apps/account/models.py

@@ -51,7 +51,7 @@ class UserManager(BaseUserManager):
             BizLog.objects.addnew(user, BizLog.UPDATE, u"修改权限组[%s],id=%d" % (group.name, group.id))
         group.permissions = permissions
 
-    def _create_user(self, username,  password, **extra_fields):
+    def _create_user(self, type, username,  password, **extra_fields):
         """
         Creates and saves a User with the given username, email and password.
         """
@@ -60,6 +60,7 @@ class UserManager(BaseUserManager):
         username = self.model.normalize_username(username)
         user = self.model(username=username, **extra_fields)
         user.set_password(password)
+        user.type = type
         user.save(using=self._db)
         return user
 
@@ -69,15 +70,23 @@ class UserManager(BaseUserManager):
         if extra_fields.get('is_superuser') is not True:
             raise ValueError('Superuser must have is_superuser=True.')
 
-        return self._create_user(username,  password, **extra_fields)
+        return self._create_user(User.ADMINSTRATOR, username,  password, **extra_fields)
+
+    def create_customer(self, username, password=None, **extra_fields):
+        return self._create_user(User.CUSTOMER, username, password, **extra_fields)
 
 class User(AbstractBaseUser, PermissionsMixin):
+    ADMINSTRATOR = 1
+    CUSTOMER = 2
+
     DIMISSION = 0
     INSERVICE = 1
     STATUS_CHOICES = (
         (DIMISSION, u'离职'),
         (INSERVICE, u'在职'),
     )
+
+    type = models.PositiveSmallIntegerField(verbose_name=u"类型", editable=False, default=ADMINSTRATOR)
     name = models.CharField(max_length=20, verbose_name=u"姓名")
     username = models.CharField(max_length=30, verbose_name=u'账号', unique=True, db_index=True,error_messages={'unique': u'已存在'})
     status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, verbose_name=u"是否在职", default=INSERVICE)
@@ -110,6 +119,11 @@ class User(AbstractBaseUser, PermissionsMixin):
     def __unicode__(self):
         return self.username
 
+    def is_customer(self):
+        if self.type & self.CUSTOMER:
+            return True
+        return False
+
     class Meta:
         db_table = "auth_user"
         verbose_name = u"人员管理"

+ 1 - 0
apps/activity/filters.py

@@ -6,6 +6,7 @@ from apps.activity.models import Activity
 
 
 class ActivityFilter(django_filters.FilterSet):
+    id = django_filters.CharFilter(field_name='id')
     title = django_filters.CharFilter(field_name='title', lookup_expr='icontains')
 
     class Meta:

+ 7 - 1
apps/customer/filters.py

@@ -2,7 +2,7 @@
 
 import django_filters
 
-from apps.customer.models import Customer, CustomerVehicle
+from apps.customer.models import Customer, CustomerVehicle, CustomerAddress
 
 
 class CustomerFilter(django_filters.FilterSet):
@@ -20,3 +20,9 @@ class CustomerVehicleFilter(django_filters.FilterSet):
     class Meta:
         model = CustomerVehicle
         fields = '__all__'
+
+class CustomerAddressFilter(django_filters.FilterSet):
+
+    class Meta:
+        model = CustomerAddress
+        fields = '__all__'

+ 25 - 1
apps/customer/models.py

@@ -11,9 +11,11 @@ from utils.wx.wechat import WeChat
 from utils.wx.WXBizDataCrypt import WXBizDataCrypt
 from utils.exceptions import CustomError
 from apps.foundation.models import Config
+from apps.account.models import User
 
 
 class Customer(models.Model):
+    user = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, on_delete=models.PROTECT, verbose_name=u'用户')
     name = models.CharField(max_length=100, verbose_name=u"姓名")
     tel = models.CharField(max_length=50, verbose_name=u'电话')
     gender = models.PositiveSmallIntegerField(choices=settings.GENDER_CHOICES, verbose_name=u'性别', null=True)
@@ -30,6 +32,15 @@ class Customer(models.Model):
         )
         default_permissions = ()
 
+    @staticmethod
+    def getOrRegister(user):
+        customer = Customer.objects.filter(user=user).first()
+        if customer:
+            return customer
+        with transaction.atomic():
+            customer = Customer.objects.create(user=user, tel=user.username, name=user.username)
+        return customer
+
     def setInfo(self, nickName, gender, avatarUrl):
         self.name = nickName
         if gender == 1:
@@ -57,8 +68,9 @@ class CustomerWechat(models.Model):
         default_permissions = ()
 
     @staticmethod
-    def login(code, appid):
+    def login(code):
         secret = Config.getConfigValue(Config.KEY_WECHAT_SESSION_KEY)
+        appid = Config.getConfigValue(Config.KEY_WECHAT_APPID)
         res = WeChat.code2Session(appid, secret, code)
         instance = CustomerWechat.objects.filter(openid=res['openid']).first()
         if not instance:
@@ -91,6 +103,18 @@ class CustomerWechat(models.Model):
         customer = Customer.objects.filter(tel=tel).first()
         if not customer:
             Customer.objects.create(tel=tel, name=tel)
+
+        user = User.objects.filter(username=tel).first()
+        if not user:
+            user = User.objects.create_customer(tel, password='')
+
+        try:
+            with transaction.atomic():
+                customer = Customer.getOrRegister(user=user)
+        except:
+            raise CustomError(u'用户注册失败!')
+
+
         customer_wechat.customer = customer
         customer_wechat.save()
         return customer

+ 1 - 0
apps/product/filters.py

@@ -6,6 +6,7 @@ from .models import Product, ProductImg
 
 
 class ProductFilter(django_filters.FilterSet):
+    id = django_filters.CharFilter(field_name='id')
     name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
 
     class Meta:

+ 1 - 1
apps/usedvehicle/serializers.py

@@ -32,7 +32,7 @@ class UsedVehicleSerializer(serializers.ModelSerializer):
         instance = super(UsedVehicleSerializer, self).create(validated_data)
         factory_date = self.context['request'].data.get('factory_date')
         if factory_date:
-            years = int((timezone.now().date() -  datetime.datetime.strptime(factory_date, '%H:%M:%S')).days / 365)
+            years = int((timezone.now() - datetime.datetime.strptime(factory_date, '%Y-%m-%d')).days / 365)
             instance.years = years
             instance.save()
         return instance

+ 1 - 0
apps/vehicle/filters.py

@@ -19,6 +19,7 @@ class BrandFilter(django_filters.FilterSet):
 
 
 class SeriesFilter(django_filters.FilterSet):
+    id = django_filters.CharFilter(field_name='id')
     name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
     brand_name = django_filters.CharFilter(field_name='brand__name', lookup_expr='icontains')
     brand_id = django_filters.CharFilter(field_name='brand_id')

+ 0 - 0
apps/wechat/activity/__init__.py


+ 33 - 0
apps/wechat/activity/serializers.py

@@ -0,0 +1,33 @@
+# coding=utf-8
+
+from utils.exceptions import CustomError
+from django.utils import timezone
+from django.conf import settings
+from rest_framework import serializers
+from apps.activity.models import Activity
+
+class ActivitySerializer(serializers.ModelSerializer):
+    create_user_text = serializers.CharField(source='create_user.employee.name', read_only=True)
+    playbill_url = serializers.SerializerMethodField()
+    cover = serializers.SerializerMethodField()
+    status = serializers.SerializerMethodField()
+
+    def get_status(self, obj):
+        if obj.end_date >= timezone.now().date():
+            return u'进行中'
+        return u'已结束'
+
+    def get_playbill_url(self, obj):
+        if obj.cover:
+            return '%s%s' % (settings.MEDIA_URL, obj.cover.picture)
+        return ''
+
+    def get_cover(self, obj):
+        if obj.cover:
+            return {'width': obj.cover.width, 'height': obj.cover.height, 'url': obj.cover.get_path()}
+        return ''
+
+
+    class Meta:
+        model = Activity
+        fields = '__all__'

+ 10 - 0
apps/wechat/activity/urls.py

@@ -0,0 +1,10 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'^list/$', ActivityListViewSet.as_view()),
+]

+ 33 - 0
apps/wechat/activity/views.py

@@ -0,0 +1,33 @@
+# coding=utf-8
+
+from django.utils import timezone
+from django.db import transaction
+from django.db.models import F
+from django.conf import settings
+from rest_framework import generics, mixins
+from rest_framework.views import APIView
+from rest_framework.viewsets import GenericViewSet
+from rest_framework.decorators import action
+from rest_framework.exceptions import NotFound
+
+from utils import response_ok
+from utils.permission import IsCustomerUser
+from utils.exceptions import CustomError
+from .serializers import ActivitySerializer
+from apps.activity.models import Activity
+from apps.activity.filters import ActivityFilter
+
+
+class ActivityListViewSet(generics.ListAPIView):
+    queryset = Activity.objects.filter(delete=False)
+    serializer_class = ActivitySerializer
+
+    def filter_queryset(self, queryset):
+        f = ActivityFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+

+ 0 - 0
apps/wechat/product/__init__.py


+ 67 - 0
apps/wechat/product/serializers.py

@@ -0,0 +1,67 @@
+# coding=utf-8
+
+from django.conf import settings
+from rest_framework import serializers
+from apps.product.models import Product, ProductImg
+from apps.base import Formater
+from apps.customer.models import Customer
+from apps.foundation.models import Option, Config
+
+
+class ProductSerializer(serializers.ModelSerializer):
+    cover_url = serializers.SerializerMethodField()
+    price = serializers.SerializerMethodField()
+
+    def get_cover_url(self, obj):
+        if obj.cover:
+            return {'width': obj.cover.width, 'height': obj.cover.height, 'url': obj.cover.get_path()}
+        return ''
+
+    def get_price(self, obj):
+        return Formater.formatPriceShow(obj.price)
+
+    class Meta:
+        model = Product
+        fields = ('id', 'cover_url', 'name', 'notes', 'price')
+
+
+class ProductDetailSerializer(serializers.ModelSerializer):
+    price = serializers.SerializerMethodField()
+    Product_images = serializers.SerializerMethodField()
+    has_cover = serializers.SerializerMethodField()
+    cover = serializers.SerializerMethodField()
+
+    def get_cover(self, obj):
+        if obj.cover:
+            return {'width': obj.cover.width, 'height': obj.cover.height, 'url': obj.cover.get_path()}
+        return ''
+
+    def get_has_cover(self, obj):
+        if obj.cover:
+            return True
+        return False
+
+    def get_Product_images(self, obj):
+        result = []
+        rows = ProductImg.objects.filter(product=obj).values('img__picture', 'img__width', 'img__height')
+        for row in rows:
+            url = {'width': row['img__width'], 'height': row['img__height'], 'url': '%s%s%s' % (settings.SERVER_DOMAIN, settings.MEDIA_URL, row['img__picture'])}
+            result.append(url)
+        return result
+
+    def get_price(self, obj):
+        return Formater.formatAmountShow(obj.discount_price)
+
+    class Meta:
+        model = Product
+        fields = (
+            'id', 'name', 'Product_images', 'describe',
+            'notes', 'has_cover', 'give_count', 'cover'
+        )
+
+
+class ProductTypeSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = Option
+        fields = ('id', 'name')

+ 12 - 0
apps/wechat/product/urls.py

@@ -0,0 +1,12 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'^types/$', ProductTypeListView.as_view()),
+    url(r'^detail/$', ProductDetailView.as_view()),
+    url(r'^list/$', ProductListView.as_view()),
+]

+ 69 - 0
apps/wechat/product/views.py

@@ -0,0 +1,69 @@
+# coding=utf-8
+
+from django.db import transaction
+from django.db.models import F
+from django.conf import settings
+
+from rest_framework import generics, mixins
+from rest_framework.viewsets import GenericViewSet
+from rest_framework.views import APIView
+from rest_framework.decorators import action
+from rest_framework.exceptions import NotFound
+
+from utils import response_ok
+from utils.permission import IsCustomerUser
+from utils.exceptions import CustomError
+
+from apps.product.models import Product
+from apps.product.filters import ProductFilter
+from apps.account import tenant_log
+from apps.foundation.models import BizLog, Option
+from apps.customer.models import Customer
+from apps.foundation.filters import OptionFilter
+
+from .serializers import ProductSerializer, ProductDetailSerializer, ProductTypeSerializer
+
+
+class ProductListView(generics.ListAPIView):
+    queryset = Product.objects.filter(delete=False)
+    serializer_class = ProductSerializer
+
+    def filter_queryset(self, queryset):
+        f = ProductFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        try:
+            data = super(ProductListView, self).list(request)
+        except NotFound:
+            return response_ok([])
+        return data
+
+
+class ProductTypeListView(generics.ListAPIView):
+    queryset = Option.objects.filter(enable=True, delete=False, type=Option.PRODUCT_CATEGORY)
+    serializer_class = ProductTypeSerializer
+
+    def filter_queryset(self, queryset):
+        f = OptionFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        try:
+            data = super(ProductTypeListView, self).list(request)
+        except NotFound:
+            return response_ok([])
+        return data
+
+
+class ProductDetailView(generics.RetrieveAPIView):
+    queryset = Product.objects.filter(enabled=True, delete=False)
+    serializer_class = ProductDetailSerializer
+
+    def retrieve(self, request, *args, **kwargs):
+        id = request.GET.get('id')
+        instance = self.queryset.filter(id=id).first()
+        if not instance:
+            raise CustomError(u'未找到相应的商品!')
+        serializer = self.get_serializer(instance)
+        return response_ok(serializer.data)

+ 161 - 0
apps/wechat/serializers.py

@@ -0,0 +1,161 @@
+#coding=utf-8
+
+from django.contrib.auth import get_user_model
+from django.conf import settings
+from django.db.models import Q
+
+from rest_framework import serializers
+from rest_framework_jwt.settings import api_settings
+
+from apps.customer.models import Customer, CustomerWechat, CustomerAddress
+from apps.foundation.models import BizLog
+from apps.base import Formater
+from utils.exceptions import CustomError
+from apps.account import tenant_log
+
+
+User = get_user_model()
+jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
+jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
+
+
+class CustomerMobileSignSerializer(serializers.Serializer):
+    def validate(self, attrs):
+        mobile = self.initial_data.get('mobile')
+        vcode = self.initial_data.get('vcode')
+        appid = self.initial_data.get('appid')
+
+        if mobile and vcode and appid:
+            # VCode.verify(mobile, vcode, tenant)
+            user = User.objects.filter(username=mobile).first()
+            if not user:
+                user = User.objects.create_customer(username=mobile)
+
+            if not user.is_active:
+                msg = '该账户已被禁用'
+                raise serializers.ValidationError(msg)
+
+            try:
+                customer = Customer.getOrRegister(user=user)
+            except:
+                msg = '客户注册失败!'
+                raise serializers.ValidationError(msg)
+
+            payload = jwt_payload_handler(user)
+            tenant_log(user, BizLog.INSERT,u'客户短信登录,username=%s' % user.username)
+
+            return {
+                'token': jwt_encode_handler(payload),
+                'user_id': user.id,
+                'username': user.username,
+                'name': customer.name or '',
+                'tel': customer.tel or '',
+                'face': customer.face and customer.face.get_path() or '',
+                'gender': customer.gender or 0,
+                'member_id': customer.member_id or '',
+            }
+        else:
+            msg = '参数无效'
+            raise serializers.ValidationError(msg)
+
+
+class WechatLoginSerializer(serializers.Serializer):
+    def validate(self, attrs):
+        code = self.initial_data.get('code')
+
+        if code:
+            customer_wechat = CustomerWechat.login(code)
+            if not customer_wechat.customer:
+                return {
+                    'bind': 0,
+                    'openid': customer_wechat.openid,
+                }
+
+            user = customer_wechat.customer.user
+            if not user.is_active:
+                msg = '用户帐户已禁用.'
+                raise serializers.ValidationError(msg)
+
+            payload = jwt_payload_handler(user)
+            tenant_log(user, BizLog.INSERT, u'用户微信登录,username=%s' % user.username)
+            return {
+                'bind': 1,
+                'token': jwt_encode_handler(payload),
+                'openid': customer_wechat.openid,
+                'name': customer_wechat.customer.name or '',
+                'tel': customer_wechat.customer.tel or '',
+                'face': customer_wechat.customer.face and customer_wechat.customer.face.get_path() or '',
+                'gender': customer_wechat.customer.gender or 0,
+                'member_id': customer_wechat.customer.member_id or '',
+            }
+
+        else:
+            msg = '参数无效'
+            raise serializers.ValidationError(msg)
+
+class WechatBindSerializer(serializers.Serializer):
+    def validate(self, attrs):
+        appid = self.initial_data.get('appid')
+        openid = self.initial_data.get('openid')
+        phoneEncryptedData = self.initial_data.get('encryptedData')
+        phoneIv = self.initial_data.get('iv')
+
+        if openid and phoneEncryptedData and phoneIv:
+            customer = CustomerWechat.bindWechat(appid, openid, phoneEncryptedData, phoneIv)
+            user = customer.user
+            payload = jwt_payload_handler(user)
+            tenant_log(user, BizLog.INSERT, u'用户微信登录,username=%s' % user.username)
+
+            return {
+                'token': jwt_encode_handler(payload),
+                'name': customer.name or '',
+                'tel': customer.tel or '',
+                'face': customer.face and customer.face.get_path() or '',
+                'gender': customer.gender or 0,
+                'member_id': customer.member_id or '',
+            }
+
+        else:
+            msg = '参数无效'
+            raise serializers.ValidationError(msg)
+
+
+class CustomerSerializer(serializers.ModelSerializer):
+    face = serializers.SerializerMethodField()
+
+    def get_face(self, obj):
+        if obj.face:
+            return {'width': obj.face.width, 'height': obj.face.height, 'url': obj.face.get_path()}
+        return ''
+
+    class Meta:
+        model = Customer
+        fields = ('name', 'tel', 'face')
+
+
+class CustomerAddressSerializer(serializers.ModelSerializer):
+    full_addr = serializers.SerializerMethodField()
+
+    def get_full_addr(self, obj):
+        full_addr = obj.area + obj.addr
+        return full_addr
+
+    class Meta:
+        model = CustomerAddress
+        fields = '__all__'
+
+    def create(self, validated_data):
+        customer = self.context['request'].customer
+        validated_data['customer'] = customer
+        if validated_data['default']:
+            CustomerAddress.objects.filter(Q(customer=customer), Q(delete=False)).update(default=False)
+        instance = super(CustomerAddressSerializer, self).create(validated_data)
+        return instance
+
+    def update(self, instance, validated_data):
+        if instance.delete:
+            raise CustomError(u'该收货地址已经被删除,禁止操作')
+        if validated_data['default']:
+            CustomerAddress.objects.filter(Q(customer=instance.customer), Q(delete=False), ~Q(id=instance.id)).update(default=False)
+        instance = super(CustomerAddressSerializer, self).update(instance, validated_data)
+        return instance

+ 0 - 0
apps/wechat/store/__init__.py


+ 32 - 0
apps/wechat/store/serializers.py

@@ -0,0 +1,32 @@
+# coding=utf-8
+
+from django.conf import settings
+
+from rest_framework import serializers
+from apps.store.models import Shop
+
+
+class ShopSerializer(serializers.ModelSerializer):
+    img = serializers.SerializerMethodField()
+
+    def get_img(self, obj):
+        if obj.img:
+            return {'width': obj.img.width, 'height': obj.img.height, 'url': obj.img.get_path()}
+        return ''
+
+    class Meta:
+        model = Shop
+        fields = ('id', 'name', 'addr', 'img', )
+
+
+class ShopDetailSerializer(serializers.ModelSerializer):
+    img = serializers.SerializerMethodField()
+
+    def get_img(self, obj):
+        if obj.img:
+            return {'width': obj.img.width, 'height': obj.img.height, 'url': obj.img.get_path()}
+        return ''
+
+    class Meta:
+        model = Shop
+        fields = '__all__'

+ 12 - 0
apps/wechat/store/urls.py

@@ -0,0 +1,12 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'^list/$', ShopViewSet.as_view()),
+    url(r'^map_list/$', ShopMapListView.as_view()),
+]
+

+ 41 - 0
apps/wechat/store/views.py

@@ -0,0 +1,41 @@
+# coding=utf-8
+
+from rest_framework import generics, mixins
+from rest_framework.viewsets import GenericViewSet
+
+from utils.permission import IsCustomerUser
+from utils.exceptions import CustomError
+from utils import response_ok
+
+from apps.store.models import Shop
+from apps.store.filters import ShopFilter
+
+from .serializers import *
+
+
+class ShopViewSet(generics.ListAPIView):
+    queryset = Shop.objects.filter(delete=False)
+    serializer_class = ShopSerializer
+
+    def filter_queryset(self, queryset):
+        f = ShopFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+
+
+class ShopMapListView(generics.ListAPIView):
+    queryset = Shop.objects.filter(delete=False)
+    serializer_class = ShopDetailSerializer
+
+    def filter_queryset(self, queryset):
+        f = ShopFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)

+ 20 - 0
apps/wechat/urls.py

@@ -0,0 +1,20 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'^token/obtain/$', CustomerLoginView.as_view()),
+    url(r'^token/refresh/', CustomerRefreshTokenView),
+    url(r'^token/verify/', CustomerVerifyTokenView),
+
+    url(r'^code2Session/$', WxLoginView.as_view()),
+    url(r'^wxbind/$', WxBindView.as_view()),
+]
+
+router = SimpleRouter()
+router.register(r'addr', CustomerAddressViewSet)
+urlpatterns += router.urls
+

+ 0 - 0
apps/wechat/vehicle/__init__.py


+ 21 - 0
apps/wechat/vehicle/serializers.py

@@ -0,0 +1,21 @@
+# coding=utf-8
+
+from utils.exceptions import CustomError
+from django.utils import timezone
+from django.conf import settings
+from rest_framework import serializers
+from apps.vehicle.models import Series, Brand, Model
+
+class SeriesSerializer(serializers.ModelSerializer):
+    brand_name = serializers.CharField(source='brand.name', read_only=True)
+    img_url = serializers.SerializerMethodField()
+
+    def get_img_url(self, obj):
+        if obj.thumbnail:
+            return '%s%s' % (settings.MEDIA_URL, obj.thumbnail.picture)
+        return ''
+
+
+    class Meta:
+        model = Series
+        fields = '__all__'

+ 10 - 0
apps/wechat/vehicle/urls.py

@@ -0,0 +1,10 @@
+# coding=utf-8
+
+from django.conf.urls import url, include
+from rest_framework.routers import SimpleRouter
+
+from .views import *
+
+urlpatterns = [
+    url(r'^list/$', SeriesListViewSet.as_view()),
+]

+ 34 - 0
apps/wechat/vehicle/views.py

@@ -0,0 +1,34 @@
+# coding=utf-8
+
+from django.utils import timezone
+from django.db import transaction
+from django.db.models import F
+from django.conf import settings
+from rest_framework import generics, mixins
+from rest_framework.views import APIView
+from rest_framework.viewsets import GenericViewSet
+from rest_framework.decorators import action
+from rest_framework.exceptions import NotFound
+
+from utils import response_ok
+from utils.permission import IsCustomerUser
+from utils.exceptions import CustomError
+from .serializers import SeriesSerializer
+from apps.activity.models import Activity
+from apps.vehicle.filters import SeriesFilter
+from apps.vehicle.models import Series
+
+
+class SeriesListViewSet(generics.ListAPIView):
+    queryset = Series.objects.filter(enabled=True, delete=False, is_hot=True)
+    serializer_class = SeriesSerializer
+
+    def filter_queryset(self, queryset):
+        f = SeriesFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+

+ 174 - 0
apps/wechat/views.py

@@ -0,0 +1,174 @@
+# coding=utf-8
+
+import requests
+from django.db import transaction
+from rest_framework.views import APIView
+from rest_framework import generics
+from rest_framework.decorators import action
+from rest_framework_jwt.views import ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken
+from rest_framework.serializers import ValidationError
+from rest_framework import permissions
+
+from utils import response_ok, response_error
+from utils.exceptions import CustomError
+from utils.custom_modelviewset import CustomModelViewSet
+from utils.wx.WXBizDataCrypt import WXBizDataCrypt
+from utils.permission import IsCustomerUser
+from apps.images.models import Images
+from apps.customer.models import CustomerAddress
+from apps.customer.filters import CustomerAddressFilter
+from apps.foundation.models import Config
+from apps.account import tenant_log
+
+
+from .serializers import *
+
+
+class CustomerLoginView(APIView):
+    serializer_class = CustomerMobileSignSerializer
+
+    def post(self, request, *args, **kwargs):
+        ser = self.serializer_class(data=request.data)
+        if ser.is_valid():
+            return response_ok(ser.validated_data)
+        else:
+            return response_error('参数错误')
+
+
+class CustomerRefreshTokenView(RefreshJSONWebToken):
+    def post(self, request, *args, **kwargs):
+        try:
+            ser = self.serializer_class(data=request.data)
+            if ser.is_valid(raise_exception=True):
+                return response_ok({'token': ser.validated_data['token']})
+        except ValidationError as e:
+            return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
+
+
+class CustomerVerifyTokenView(VerifyJSONWebToken):
+    def post(self, request, *args, **kwargs):
+        try:
+            ser = self.serializer_class(data=request.data)
+            if ser.is_valid(raise_exception=True):
+                return response_ok({'token': ser.validated_data['token']})
+        except ValidationError as e:
+            return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
+
+
+class WxLoginView(APIView):
+    serializer_class = WechatLoginSerializer
+
+    def post(self, request, *args, **kwargs):
+        ser = self.serializer_class(data=request.data)
+        if ser.is_valid():
+            return response_ok(ser.validated_data)
+        else:
+            return response_error('参数错误')
+
+
+class WxBindView(APIView):
+    serializer_class = WechatBindSerializer
+
+    def post(self, request, *args, **kwargs):
+        ser = self.serializer_class(data=request.data)
+        if ser.is_valid():
+            return response_ok(ser.validated_data)
+        else:
+            return response_error('参数错误')
+
+
+class SetUserInfoView(APIView):
+    permission_classes = [IsCustomerUser, ]
+
+    def post(self, request, *args, **kwargs):
+        appid = request.POST.get('appid')
+        openid = request.POST.get('openid')
+        encryptedData = request.POST.get('encryptedData')
+        iv = request.POST.get('iv')
+
+        customer_wechat = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first()
+        if not customer_wechat:
+            raise CustomError(u'未找到相应的微信客户!')
+        customer = request.customer
+        if customer_wechat.customer and customer_wechat.customer.id != customer.id:
+            raise CustomError(u'该微信已同步其他客户!')
+        if not customer_wechat.customer:
+            customer_wechat.customer = customer
+            customer_wechat.save()
+        pc = WXBizDataCrypt(customer_wechat.wechat_app.authorizer_appid, customer_wechat.session_key)
+        result = pc.decrypt(encryptedData, iv)
+        with transaction.atomic():
+            customer.setInfo(result['nickName'], result['gender'], result['avatarUrl'])
+            tenant_log(customer.user, BizLog.INSERT, u'客户设置信息,id=%d' % customer.id, result)
+        return response_ok()
+
+
+
+class CustomerInfoView(generics.RetrieveAPIView):
+    permission_classes = [IsCustomerUser, ]
+    # queryset = Customer.objects.filter()
+    serializer_class = CustomerSerializer
+
+    def get_object(self):
+        # queryset = self.filter_queryset(self.get_queryset())
+        # obj = queryset.filter(id=self.request.customer.id).first()
+        obj = self.request.customer
+        return obj
+
+    def retrieve(self, request, *args, **kwargs):
+        instance = self.get_object()
+        serializer = self.get_serializer(instance)
+        return response_ok(serializer.data)
+
+
+class CustomerAddressViewSet(CustomModelViewSet):
+    permission_classes = [IsCustomerUser, ]
+    queryset = CustomerAddress.objects.filter(delete=False)
+    serializer_class = CustomerAddressSerializer
+
+    def filter_queryset(self, queryset):
+        queryset = queryset.filter(customer=self.request.customer)
+        f = CustomerAddressFilter(self.request.GET, queryset=queryset)
+        return f.qs
+
+    def list(self, request, *args, **kwargs):
+        queryset = self.filter_queryset(self.get_queryset())
+        serializer = self.get_serializer(queryset, many=True)
+        return response_ok(serializer.data)
+
+    def perform_create(self, serializer):
+        super(CustomerAddressViewSet, self).perform_create(serializer)
+        instance = serializer.instance
+        validated_data = serializer.validated_data
+        tenant_log(instance.customer.user, BizLog.INSERT, u'客户添加收货地址,id=%d' % instance.id, validated_data)
+
+    @action(methods=['post'], detail=True)
+    def addr_update(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            serializer = self.get_serializer(instance, data=request.data)
+            serializer.is_valid(raise_exception=True)
+            serializer.save()
+            instance = serializer.instance
+            validated_data = serializer.validated_data
+            tenant_log(instance.customer.user, BizLog.UPDATE, u'客户修改收货地址,id=%d' % instance.id, validated_data)
+        return response_ok()
+
+    @action(methods=['get'], detail=True)
+    def addr_destroy(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            queryset = self.get_queryset().filter(customer=self.request.customer).exclude(id=instance.id)
+            instance.destory(queryset)
+            tenant_log(instance.customer.user, BizLog.INSERT, u'客户删除收货地址,id=%d' % instance.id)
+        return response_ok()
+
+    @action(methods=['get'], detail=True)
+    def set_default(self, request, *args, **kwargs):
+        with transaction.atomic():
+            instance = self.get_object()
+            self.get_queryset().filter(customer=self.request.customer, default=True).update(default=False)
+            instance.default = True
+            instance.save()
+            tenant_log(instance.customer.user, BizLog.INSERT, u'客户设置默认收货地址,id=%d' % instance.id)
+        return response_ok()

+ 1 - 0
shop/settings.py

@@ -55,6 +55,7 @@ INSTALLED_APPS = [
     'apps.product_order',
     'apps.vehicle_order',
     'apps.maint_order',
+    'apps.wechat',
     # 'apps.pay',
     # 'apps.poster',
     # 'apps.activity',

+ 1 - 0
shop/urls.py

@@ -34,6 +34,7 @@ urlpatterns = [
     url(r'^product_order/', include('apps.product_order.urls')),
     url(r'^vehicle_order/', include('apps.vehicle_order.urls')),
     url(r'^maint_order/', include('apps.maint_order.urls')),
+    url(r'^wechat/', include('apps.wechat.urls')),
     # url(r'^api/', include('apps.api.urls')),
 ]
 

+ 4 - 4
uis/views/usedvehicle/edit.html

@@ -97,15 +97,15 @@
                   </div>
                 </div>
                 <div>
-                  <label class="layui-form-label">上牌日期:</label>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>上牌日期:</label>
                   <div class="layui-input-block">
-                    <input id="plate_date" type="text" name="plate_date" placeholder="请输入上牌日期" autocomplete="off" class="layui-input">
+                    <input id="plate_date" type="text"  lay-verify="required" name="plate_date" placeholder="请输入上牌日期" autocomplete="off" class="layui-input">
                   </div>
                 </div>
                 <div>
-                  <label class="layui-form-label">出厂日期:</label>
+                  <label class="layui-form-label"><font color='red' size="4">*</font>出厂日期:</label>
                   <div class="layui-input-block">
-                    <input id="factory_date" type="text" name="factory_date" placeholder="请输入出厂日期" autocomplete="off" class="layui-input" >
+                    <input id="factory_date" type="text" lay-verify="required" name="factory_date" placeholder="请输入出厂日期" autocomplete="off" class="layui-input" >
                   </div>
                 </div>
                 <div>

+ 1 - 0
uis/views/usedvehicle/index.html

@@ -105,6 +105,7 @@
        ,{field:'status_text', title:'状态',width: 100}
        ,{field:'guide_price', title:'指导价',width: 100}
        ,{field:'sale_price', title:'售价',width: 100}
+       ,{field:'years', title:'年限',width: 80}
        ,{field:'gearbox_name', title:'变速箱类型',width: 100}
        ,{field:'color_name', title:'颜色',width: 100}
        ,{field:'displacement_name', title:'排量',width: 100}

+ 15 - 0
utils/permission.py

@@ -3,6 +3,21 @@
 from rest_framework import permissions
 
 from utils.exceptions import CustomError
+from apps.customer.models import Customer
+
+
+class IsCustomerUser(permissions.BasePermission):
+    def has_permission(self, request, view):
+        if not request.user or not request.user.is_authenticated:
+            return False
+        if not request.user.is_customer():
+            return False
+
+        customer = Customer.objects.filter(user_id=request.user.id).first()
+        if not customer:
+            return False
+        request.customer = customer
+        return True
 
 class isLogin(permissions.BasePermission):
     def has_permission(self, request, view):