@@ -7,6 +7,7 @@ from jsonfield import JSONField  | 
            ||
| 7 | 7 | 
                 | 
            
| 8 | 8 | 
                from kodo.basemodels import LensmanTypeBoolMixin  | 
            
| 9 | 9 | 
                from mch.models import SaleclerkInfo  | 
            
| 10 | 
                +from sales.models import SalesResponsibilityInfo  | 
            |
| 10 | 11 | 
                 | 
            
| 11 | 12 | 
                 | 
            
| 12 | 13 | 
                class LensmanInfo(BaseModelMixin, LensmanTypeBoolMixin):  | 
            
                @@ -383,6 +384,21 @@ class UserInfo(BaseModelMixin, LensmanTypeBoolMixin):  | 
            ||
| 383 | 384 | 
                }  | 
            
| 384 | 385 | 
                ]  | 
            
| 385 | 386 | 
                 | 
            
| 387 | 
                + @property  | 
            |
| 388 | 
                + def srinfo(self):  | 
            |
| 389 | 
                + try:  | 
            |
| 390 | 
                + sr = SalesResponsibilityInfo.objects.get(user_id=self.user_id)  | 
            |
| 391 | 
                + except SalesResponsibilityInfo.DoesNotExist:  | 
            |
| 392 | 
                + sr = None  | 
            |
| 393 | 
                + sr_id = sr.sr_id if sr else ''  | 
            |
| 394 | 
                + is_sr = True if sr else False  | 
            |
| 395 | 
                + is_super_sr = True if sr and sr.is_super else False  | 
            |
| 396 | 
                +        return {
               | 
            |
| 397 | 
                + 'sr_id': sr_id,  | 
            |
| 398 | 
                + 'is_sr': is_sr,  | 
            |
| 399 | 
                + 'is_super_sr': is_super_sr,  | 
            |
| 400 | 
                + }  | 
            |
| 401 | 
                +  | 
            |
| 386 | 402 | 
                def brandata(self, brand_id=None):  | 
            
| 387 | 403 | 
                if self.unionid:  | 
            
| 388 | 404 | 
                try:  | 
            
                @@ -406,6 +422,7 @@ class UserInfo(BaseModelMixin, LensmanTypeBoolMixin):  | 
            ||
| 406 | 422 | 
                'cardList': self.cardList,  | 
            
| 407 | 423 | 
                'saleclerk': bool(saleclerk_info),  | 
            
| 408 | 424 | 
                'saleclerk_info': saleclerk_info,  | 
            
| 425 | 
                + 'sr_info': self.srinfo,  | 
            |
| 409 | 426 | 
                }  | 
            
| 410 | 427 | 
                 | 
            
| 411 | 428 | 
                 | 
            
                @@ -31,6 +31,7 @@ def clerk_add(request):  | 
            ||
| 31 | 31 | 
                 | 
            
| 32 | 32 | 
                SaleclerkInfo.objects.create(  | 
            
| 33 | 33 | 
                brand_id=administrator.brand_id,  | 
            
| 34 | 
                + brand_name=administrator.brand_name,  | 
            |
| 34 | 35 | 
                distributor_id=distributor_id,  | 
            
| 35 | 36 | 
                distributor_name=distributor.distributor_name,  | 
            
| 36 | 37 | 
                clerk_name=clerk_name,  | 
            
                @@ -18,6 +18,8 @@ def distributor_add(request):  | 
            ||
| 18 | 18 | 
                     province_code = request.POST.get('province_code', '')
               | 
            
| 19 | 19 | 
                     province_name = request.POST.get('province_name', '')
               | 
            
| 20 | 20 | 
                 | 
            
| 21 | 
                +    sr_id = request.POST.get('sr_id', '')
               | 
            |
| 22 | 
                +  | 
            |
| 21 | 23 | 
                # 如果省份编码不存在,而省份名称存在  | 
            
| 22 | 24 | 
                if not province_code and province_name:  | 
            
| 23 | 25 | 
                province_code = ProvinceShortModelMixin.PROVINCE_NAME_CODE_DICT.get(province_name, '')  | 
            
                @@ -35,6 +37,7 @@ def distributor_add(request):  | 
            ||
| 35 | 37 | 
                distributor_short_name=distributor_short_name,  | 
            
| 36 | 38 | 
                distributor_province_code=province_code,  | 
            
| 37 | 39 | 
                distributor_province_name=province_name,  | 
            
| 40 | 
                + sr_id=sr_id,  | 
            |
| 38 | 41 | 
                )  | 
            
| 39 | 42 | 
                 | 
            
| 40 | 43 | 
                return response(200, 'Distributor Add Success', u'经销商添加成功')  | 
            
                @@ -72,6 +75,8 @@ def distributor_update(request):  | 
            ||
| 72 | 75 | 
                 | 
            
| 73 | 76 | 
                     admin_id = request.session.get('admin_id')
               | 
            
| 74 | 77 | 
                 | 
            
| 78 | 
                +    sr_id = request.POST.get('sr_id', '')
               | 
            |
| 79 | 
                +  | 
            |
| 75 | 80 | 
                try:  | 
            
| 76 | 81 | 
                administrator = AdministratorInfo.objects.get(admin_id=admin_id, user_status=AdministratorInfo.ACTIVATED, status=True)  | 
            
| 77 | 82 | 
                except AdministratorInfo.DoesNotExist:  | 
            
                @@ -94,6 +99,8 @@ def distributor_update(request):  | 
            ||
| 94 | 99 | 
                if not province_code:  | 
            
| 95 | 100 | 
                distributor.distributor_province_code = ProvinceShortModelMixin.PROVINCE_NAME_CODE_DICT.get(province_name, '')  | 
            
| 96 | 101 | 
                 | 
            
| 102 | 
                + distributor.sr_id = sr_id  | 
            |
| 103 | 
                +  | 
            |
| 97 | 104 | 
                distributor.save()  | 
            
| 98 | 105 | 
                 | 
            
| 99 | 106 | 
                return response(200, 'Distributor Update Success', u'经销商更新成功')  | 
            
                @@ -27,6 +27,8 @@ def model_add(request):  | 
            ||
| 27 | 27 | 
                 | 
            
| 28 | 28 | 
                     admin_id = request.session.get('admin_id')
               | 
            
| 29 | 29 | 
                 | 
            
| 30 | 
                +    is_important = request.POST.get('is_important', 0)
               | 
            |
| 31 | 
                +  | 
            |
| 30 | 32 | 
                try:  | 
            
| 31 | 33 | 
                administrator = AdministratorInfo.objects.get(admin_id=admin_id, user_status=AdministratorInfo.ACTIVATED, status=True)  | 
            
| 32 | 34 | 
                except AdministratorInfo.DoesNotExist:  | 
            
                @@ -45,6 +47,7 @@ def model_add(request):  | 
            ||
| 45 | 47 | 
                factory_yuan=factory_yuan,  | 
            
| 46 | 48 | 
                factory_fee=monetary.Yuan2Fen(factory_yuan),  | 
            
| 47 | 49 | 
                integral=integral,  | 
            
| 50 | 
                + is_important=is_important,  | 
            |
| 48 | 51 | 
                )  | 
            
| 49 | 52 | 
                 | 
            
| 50 | 53 | 
                return response(200, 'Model Add Success', u'型号添加成功')  | 
            
                @@ -89,6 +92,8 @@ def model_update(request):  | 
            ||
| 89 | 92 | 
                 | 
            
| 90 | 93 | 
                     admin_id = request.session.get('admin_id')
               | 
            
| 91 | 94 | 
                 | 
            
| 95 | 
                +    is_important = request.POST.get('is_important', 0)
               | 
            |
| 96 | 
                +  | 
            |
| 92 | 97 | 
                try:  | 
            
| 93 | 98 | 
                administrator = AdministratorInfo.objects.get(admin_id=admin_id, user_status=AdministratorInfo.ACTIVATED, status=True)  | 
            
| 94 | 99 | 
                except AdministratorInfo.DoesNotExist:  | 
            
                @@ -121,6 +126,8 @@ def model_update(request):  | 
            ||
| 121 | 126 | 
                if integral:  | 
            
| 122 | 127 | 
                modelObj.integral = integral  | 
            
| 123 | 128 | 
                 | 
            
| 129 | 
                + modelObj.is_important = is_important  | 
            |
| 130 | 
                +  | 
            |
| 124 | 131 | 
                modelObj.save()  | 
            
| 125 | 132 | 
                 | 
            
| 126 | 133 | 
                return response(200, 'Model Update Success', u'型号更新成功')  | 
            
                @@ -0,0 +1,35 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +from __future__ import division  | 
            |
| 4 | 
                +  | 
            |
| 5 | 
                +from django_logit import logit  | 
            |
| 6 | 
                +from django_response import response  | 
            |
| 7 | 
                +from paginator import pagination  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +from mch.models import AdministratorInfo  | 
            |
| 10 | 
                +from sales.models import SalesResponsibilityInfo  | 
            |
| 11 | 
                +from utils.error.errno_utils import AdministratorStatusCode  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                +@logit  | 
            |
| 15 | 
                +def sr_list(request):  | 
            |
| 16 | 
                +    page = request.POST.get('page', 1)
               | 
            |
| 17 | 
                +    num = request.POST.get('num', 20)
               | 
            |
| 18 | 
                +  | 
            |
| 19 | 
                +    admin_id = request.session.get('admin_id')
               | 
            |
| 20 | 
                +  | 
            |
| 21 | 
                + try:  | 
            |
| 22 | 
                + administrator = AdministratorInfo.objects.get(admin_id=admin_id, user_status=AdministratorInfo.ACTIVATED, status=True)  | 
            |
| 23 | 
                + except AdministratorInfo.DoesNotExist:  | 
            |
| 24 | 
                + return response(AdministratorStatusCode.ADMINISTRATOR_NOT_FOUND)  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                +    srs = SalesResponsibilityInfo.objects.filter(brand_id=administrator.brand_id, status=True).order_by('-pk')
               | 
            |
| 27 | 
                + count = srs.count()  | 
            |
| 28 | 
                + srs, left = pagination(srs, page, num)  | 
            |
| 29 | 
                + srs = [sr.admindata for sr in srs]  | 
            |
| 30 | 
                +  | 
            |
| 31 | 
                +    return response(200, 'Get SR List Success', u'获取销售担当列表成功', {
               | 
            |
| 32 | 
                + 'srs': srs,  | 
            |
| 33 | 
                + 'count': count,  | 
            |
| 34 | 
                + 'left': left,  | 
            |
| 35 | 
                + })  | 
            
                @@ -5,7 +5,7 @@ from django_file_upload import views as file_views  | 
            ||
| 5 | 5 | 
                 | 
            
| 6 | 6 | 
                from account import tourguide_views  | 
            
| 7 | 7 | 
                from account import views as account_views  | 
            
| 8 | 
                -from api import admin_views, clerk_views, distributor_views, encrypt_views, mch_views, model_views, operator_views  | 
            |
| 8 | 
                +from api import admin_views, clerk_views, distributor_views, encrypt_views, mch_views, model_views, operator_views, sr_views  | 
            |
| 9 | 9 | 
                from box import views as box_views  | 
            
| 10 | 10 | 
                from geo import views as geo_views  | 
            
| 11 | 11 | 
                from group import (groupuser_views, lensman_views, tourguidegroup_views, tourguidegroupadmin_views,  | 
            
                @@ -17,6 +17,7 @@ from operation import views as op_views  | 
            ||
| 17 | 17 | 
                from page import oauth_views, sale_views, screen_views  | 
            
| 18 | 18 | 
                from pay import views as pay_views  | 
            
| 19 | 19 | 
                from photo import views as photo_views  | 
            
| 20 | 
                +from sales import views as sales_views  | 
            |
| 20 | 21 | 
                from server import server_views  | 
            
| 21 | 22 | 
                from statistic import views as tj_views  | 
            
| 22 | 23 | 
                 | 
            
                @@ -271,6 +272,10 @@ urlpatterns += [  | 
            ||
| 271 | 272 | 
                ]  | 
            
| 272 | 273 | 
                 | 
            
| 273 | 274 | 
                urlpatterns += [  | 
            
| 275 | 
                + url(r'^sr/list$', sr_views.sr_list, name='sr_list'),  | 
            |
| 276 | 
                +]  | 
            |
| 277 | 
                +  | 
            |
| 278 | 
                +urlpatterns += [  | 
            |
| 274 | 279 | 
                url(r'^screen/admin/loginqr$', screen_views.screen_admin_loginqr, name='screen_admin_loginqr'),  | 
            
| 275 | 280 | 
                url(r'^screen/admin/loginrst$', screen_views.screen_admin_loginrst, name='screen_admin_loginrst'),  | 
            
| 276 | 281 | 
                ]  | 
            
                @@ -280,3 +285,10 @@ urlpatterns += [  | 
            ||
| 280 | 285 | 
                url(r'^admin/queryusedsn$', admin_views.queryusedsn, name='queryusedsn'),  | 
            
| 281 | 286 | 
                url(r'^admin/usecoupon$', admin_views.usecoupon, name='usecoupon'),  | 
            
| 282 | 287 | 
                ]  | 
            
| 288 | 
                +  | 
            |
| 289 | 
                +urlpatterns += [  | 
            |
| 290 | 
                + url(r'^sr/submit', sales_views.sr_submit_api, name='sr_submit_api'),  | 
            |
| 291 | 
                + url(r'^sr/distributor/list$', sales_views.sr_distributor_list, name='sr_distributor_list'),  | 
            |
| 292 | 
                + url(r'^sr/distributor/tj$', sales_views.sr_distributor_tj, name='sr_distributor_tj'),  | 
            |
| 293 | 
                + url(r'^supersr/sr/tj$', sales_views.supersr_sr_tj, name='supersr_sr_tj'),  | 
            |
| 294 | 
                +]  | 
            
                @@ -65,6 +65,7 @@ INSTALLED_APPS = (  | 
            ||
| 65 | 65 | 
                'pay',  | 
            
| 66 | 66 | 
                'photo',  | 
            
| 67 | 67 | 
                'pre',  | 
            
| 68 | 
                + 'sales',  | 
            |
| 68 | 69 | 
                'server',  | 
            
| 69 | 70 | 
                'statistic',  | 
            
| 70 | 71 | 
                'website',  | 
            
                @@ -402,6 +403,8 @@ KODO_CLERK_AUTH_URL = 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2F  | 
            ||
| 402 | 403 | 
                 KODO_SCREEN_AUTH_URL = 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fscreen%2Fadmin%2Foauth%3Fbrand_id%3D{0}'
               | 
            
| 403 | 404 | 
                 KODO_SCREEN_LOGIN_URL = 'http://pai.ai/w/o?s=snsapi_base&r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fscreen%2Fadmin%2Flogin%3Fbrand_id%3D{0}%26token%3D{1}'
               | 
            
| 404 | 405 | 
                 | 
            
| 406 | 
                +KODO_SUPERSR_AUTH_URL = 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fsupersr%2Foauth%3Fbrand_id%3D{0}'
               | 
            |
| 407 | 
                +  | 
            |
| 405 | 408 | 
                # 经纬度  | 
            
| 406 | 409 | 
                 GIS_2_ADMINISTRATIVE_DIVISION = 'http://116.196.105.215:1234/gis?auth_user=freevip&latitude={0}&longitude={1}'
               | 
            
| 407 | 410 | 
                 PHONE_2_ADMINISTRATIVE_DIVISION = 'https://www.baifubao.com/callback?cmd=1059&callback=phone&phone={0}'
               | 
            
                @@ -159,6 +159,8 @@ class ModelInfo(BaseModelMixin):  | 
            ||
| 159 | 159 | 
                 | 
            
| 160 | 160 | 
                display = models.BooleanField(_(u'display'), default=True, help_text=_(u'Display'), db_index=True)  | 
            
| 161 | 161 | 
                 | 
            
| 162 | 
                + is_important = models.BooleanField(_(u'is_important'), default=True, help_text=_(u'是否重要型号'), db_index=True)  | 
            |
| 163 | 
                +  | 
            |
| 162 | 164 | 
                class Meta:  | 
            
| 163 | 165 | 
                verbose_name = _(u'型号信息')  | 
            
| 164 | 166 | 
                verbose_name_plural = _(u'型号信息')  | 
            
                @@ -221,6 +223,7 @@ class ModelInfo(BaseModelMixin):  | 
            ||
| 221 | 223 | 
                'image2_url': self.image2_url,  | 
            
| 222 | 224 | 
                'factory_yuan': self.factory_yuan,  | 
            
| 223 | 225 | 
                'integral': self.integral,  | 
            
| 226 | 
                + 'is_important': self.is_important,  | 
            |
| 224 | 227 | 
                }  | 
            
| 225 | 228 | 
                 | 
            
| 226 | 229 | 
                fulldata = admindata  | 
            
                @@ -266,6 +269,8 @@ class DistributorInfo(BaseModelMixin):  | 
            ||
| 266 | 269 | 
                distributor_province_code = models.CharField(_(u'distributor_province_code'), max_length=6, blank=True, null=True, help_text=u'经销商所在省份编码')  | 
            
| 267 | 270 | 
                distributor_province_name = models.CharField(_(u'distributor_province_name'), max_length=3, choices=ProvinceShortModelMixin.PROVINCE_NAME_TUPLE, default=ProvinceShortModelMixin.PROVINCE_DEFAULT_NAME, blank=True, null=True, help_text=u'经销商所在省份名称')  | 
            
| 268 | 271 | 
                 | 
            
| 272 | 
                + sr_id = models.CharField(_(u'sr_id'), max_length=32, blank=True, null=True, help_text=u'销售担当唯一标识', db_index=True)  | 
            |
| 273 | 
                +  | 
            |
| 269 | 274 | 
                position = models.IntegerField(_(u'position'), default=1, help_text=u'排序')  | 
            
| 270 | 275 | 
                 | 
            
| 271 | 276 | 
                class Meta:  | 
            
                @@ -293,6 +298,7 @@ class DistributorInfo(BaseModelMixin):  | 
            ||
| 293 | 298 | 
                'distributor_descr': self.distributor_descr,  | 
            
| 294 | 299 | 
                'province_code': self.distributor_province_code,  | 
            
| 295 | 300 | 
                'province_name': self.distributor_province_name,  | 
            
| 301 | 
                + 'sr_id': self.sr_id,  | 
            |
| 296 | 302 | 
                }  | 
            
| 297 | 303 | 
                 | 
            
| 298 | 304 | 
                 | 
            
                @@ -0,0 +1,31 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +from django.conf import settings  | 
            |
| 4 | 
                +from django_logit import logit  | 
            |
| 5 | 
                +from json_render import json_render  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +from sales.models import SalesResponsibilityInfo  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +  | 
            |
| 10 | 
                +@logit  | 
            |
| 11 | 
                +def supersr_oauthqr(request):  | 
            |
| 12 | 
                +    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                +    return json_render(request, 'page/supersr_oauth_qrcode.html', unjsondumpsdict={
               | 
            |
| 15 | 
                + 'qr': settings.KODO_SUPERSR_AUTH_URL.format(brand_id)  | 
            |
| 16 | 
                + })  | 
            |
| 17 | 
                +  | 
            |
| 18 | 
                +  | 
            |
| 19 | 
                +@logit  | 
            |
| 20 | 
                +def supersr_oauth(request):  | 
            |
| 21 | 
                +    brand_id = request.GET.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 22 | 
                +    unionid = request.GET.get('unionid', '')
               | 
            |
| 23 | 
                +  | 
            |
| 24 | 
                +    SalesResponsibilityInfo.objects.update_or_create(brand_id=brand_id, unionid=unionid, defaults={
               | 
            |
| 25 | 
                + 'user_status': SalesResponsibilityInfo.ACTIVATED,  | 
            |
| 26 | 
                + 'is_auth': True,  | 
            |
| 27 | 
                + 'is_super': True,  | 
            |
| 28 | 
                + })  | 
            |
| 29 | 
                +  | 
            |
| 30 | 
                +    return json_render(request, 'page/supersr_oauth_success.html', unjsondumpsdict={
               | 
            |
| 31 | 
                + })  | 
            
                @@ -0,0 +1,64 @@  | 
            ||
| 1 | 
                +{% load staticfiles %}
               | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +<!DOCTYPE html>  | 
            |
| 4 | 
                +<html lang="zh-CN">  | 
            |
| 5 | 
                + <head>  | 
            |
| 6 | 
                + <meta charset="utf-8">  | 
            |
| 7 | 
                + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">  | 
            |
| 8 | 
                + <meta name="format-detection" content="telephone=no,email=no,address=no">  | 
            |
| 9 | 
                + <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">  | 
            |
| 10 | 
                + <title>超级销售担当授权二维码</title>  | 
            |
| 11 | 
                +  | 
            |
| 12 | 
                + <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />  | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                + <style>  | 
            |
| 15 | 
                +            input:required:invalid {
               | 
            |
| 16 | 
                + color: #E64340;  | 
            |
| 17 | 
                + }  | 
            |
| 18 | 
                +            input:required:valid {
               | 
            |
| 19 | 
                + color: rgb(0, 0, 0);  | 
            |
| 20 | 
                + }  | 
            |
| 21 | 
                +            .hidden {
               | 
            |
| 22 | 
                + display: none;  | 
            |
| 23 | 
                + }  | 
            |
| 24 | 
                +            .qr {
               | 
            |
| 25 | 
                + position: fixed;  | 
            |
| 26 | 
                + left: 50%;  | 
            |
| 27 | 
                + top: 50%;  | 
            |
| 28 | 
                + margin-left: -100px;  | 
            |
| 29 | 
                + margin-top: -100px;  | 
            |
| 30 | 
                + padding: 5px 5px 0 5px;  | 
            |
| 31 | 
                + border: 1px solid #000;  | 
            |
| 32 | 
                + border-radius: 5px;  | 
            |
| 33 | 
                + }  | 
            |
| 34 | 
                + </style>  | 
            |
| 35 | 
                + </head>  | 
            |
| 36 | 
                + <body>  | 
            |
| 37 | 
                + <div class="container" >  | 
            |
| 38 | 
                +            <img id="qr_logo" class="hidden" src="{% static 'kodo/img/paiai_96_96.png' %}">
               | 
            |
| 39 | 
                + <div id="qr" class="qr"></div>  | 
            |
| 40 | 
                + </div>  | 
            |
| 41 | 
                +  | 
            |
| 42 | 
                + <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>  | 
            |
| 43 | 
                + <script src="//cdnjs.cloudflare.com/ajax/libs/lrsjng.jquery-qrcode/0.14.0/jquery-qrcode.min.js"></script>  | 
            |
| 44 | 
                + <script>  | 
            |
| 45 | 
                +            $("#qr").empty().qrcode({
               | 
            |
| 46 | 
                + render: 'canvas',  | 
            |
| 47 | 
                + mode: 0,  | 
            |
| 48 | 
                +                text: '{{ qr }}'
               | 
            |
| 49 | 
                + });  | 
            |
| 50 | 
                + </script>  | 
            |
| 51 | 
                + <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>  | 
            |
| 52 | 
                +        <script type="text/javascript" src="{% static 'kodo/js/jswe-0.0.4.js' %}"></script>
               | 
            |
| 53 | 
                + <script>  | 
            |
| 54 | 
                +            V.initWxData({
               | 
            |
| 55 | 
                + imgUrl: "http://pai.ai/static/kodo/img/paiai_96_96.png",  | 
            |
| 56 | 
                + link: 'http://pai.ai/w/o?r=http%3A%2F%2Fpai.ai%2Fp%2Floginqr',  | 
            |
| 57 | 
                + desc: "授权登录",  | 
            |
| 58 | 
                + title: "授权登录",  | 
            |
| 59 | 
                + timeLine: ""  | 
            |
| 60 | 
                + }, true);  | 
            |
| 61 | 
                + V.hideOptionMenu();  | 
            |
| 62 | 
                + </script>  | 
            |
| 63 | 
                + </body>  | 
            |
| 64 | 
                +</html>  | 
            
                @@ -0,0 +1,13 @@  | 
            ||
| 1 | 
                +<!DOCTYPE html>  | 
            |
| 2 | 
                +<html lang="en">  | 
            |
| 3 | 
                +<head>  | 
            |
| 4 | 
                + <meta charset="UTF-8">  | 
            |
| 5 | 
                + <meta name="viewport" content="width=device-width, initial-scale=1.0">  | 
            |
| 6 | 
                + <meta http-equiv="X-UA-Compatible" content="ie=edge">  | 
            |
| 7 | 
                + <title>授权成功</title>  | 
            |
| 8 | 
                +</head>  | 
            |
| 9 | 
                +<body>  | 
            |
| 10 | 
                + <div class="" style="text-align:center;margin-top:100px;font-size:25px;">授权成功</div>  | 
            |
| 11 | 
                + <div class="" style="text-align:center;font-size:15px;">您已成为超级销售担当</div>  | 
            |
| 12 | 
                +</body>  | 
            |
| 13 | 
                +</html>  | 
            
                @@ -4,7 +4,7 @@ from django.conf.urls import url  | 
            ||
| 4 | 4 | 
                 | 
            
| 5 | 5 | 
                from account import tourguide_views  | 
            
| 6 | 6 | 
                from group import lensman_views  | 
            
| 7 | 
                -from page import info_views, oauth_views, page_views, preauth_views, sale_views, screen_views  | 
            |
| 7 | 
                +from page import info_views, oauth_views, page_views, preauth_views, sale_views, screen_views, supersr_views  | 
            |
| 8 | 8 | 
                 | 
            
| 9 | 9 | 
                 | 
            
| 10 | 10 | 
                urlpatterns = [  | 
            
                @@ -45,3 +45,9 @@ urlpatterns += [  | 
            ||
| 45 | 45 | 
                url(r'^screen/admin/oauth$', screen_views.screen_admin_oauth, name='screen_admin_oauth'),  | 
            
| 46 | 46 | 
                url(r'^screen/admin/login$', screen_views.screen_admin_login, name='screen_admin_login'),  | 
            
| 47 | 47 | 
                ]  | 
            
| 48 | 
                +  | 
            |
| 49 | 
                +# 超级销售担当  | 
            |
| 50 | 
                +urlpatterns += [  | 
            |
| 51 | 
                + url(r'^supersr$', supersr_views.supersr_oauthqr, name='supersr_oauthqr'), # 授权二维码  | 
            |
| 52 | 
                + url(r'^supersr/oauth$', supersr_views.supersr_oauth, name='supersr_oauth'), # 授权成功  | 
            |
| 53 | 
                +]  | 
            
                @@ -0,0 +1,6 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +from __future__ import unicode_literals  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.contrib import admin  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +# Register your models here.  | 
            
                @@ -0,0 +1,8 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +from __future__ import unicode_literals  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.apps import AppConfig  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +class SalesConfig(AppConfig):  | 
            |
| 8 | 
                + name = 'sales'  | 
            
                @@ -0,0 +1,145 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +from django.db import models  | 
            |
| 4 | 
                +from django.utils.translation import ugettext_lazy as _  | 
            |
| 5 | 
                +from django_models_ext import BaseModelMixin, upload_file_url, upload_path  | 
            |
| 6 | 
                +from shortuuidfield import ShortUUIDField  | 
            |
| 7 | 
                +  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +class SalesResponsibilityInfo(BaseModelMixin):  | 
            |
| 10 | 
                + REFUSED = -1  | 
            |
| 11 | 
                + UNVERIFIED = 0  | 
            |
| 12 | 
                + ACTIVATED = 1  | 
            |
| 13 | 
                + DISABLED = 2  | 
            |
| 14 | 
                + DELETED = 3  | 
            |
| 15 | 
                + ASSIGN = 10  | 
            |
| 16 | 
                +  | 
            |
| 17 | 
                + USER_STATUS_TUPLE = (  | 
            |
| 18 | 
                + (REFUSED, u'已拒绝'),  | 
            |
| 19 | 
                + (UNVERIFIED, u'未验证'),  | 
            |
| 20 | 
                + (ACTIVATED, u'已激活'),  | 
            |
| 21 | 
                + (DISABLED, u'已禁用'),  | 
            |
| 22 | 
                + (DELETED, u'已删除'),  | 
            |
| 23 | 
                + (ASSIGN, u'已分配'),  | 
            |
| 24 | 
                + )  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                + brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)  | 
            |
| 27 | 
                + brand_name = models.CharField(_(u'brand_name'), max_length=255, blank=True, null=True, help_text=u'品牌名称')  | 
            |
| 28 | 
                +  | 
            |
| 29 | 
                + sr_id = ShortUUIDField(_(u'sr_id'), max_length=32, blank=True, null=True, help_text=u'销售担当唯一标识', db_index=True, unique=True)  | 
            |
| 30 | 
                +  | 
            |
| 31 | 
                + user_id = models.CharField(_(u'user_id'), max_length=32, blank=True, null=True, help_text=u'用户唯一标识', db_index=True)  | 
            |
| 32 | 
                + unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 UnionID', db_index=True)  | 
            |
| 33 | 
                + openid = models.CharField(_(u'openid'), max_length=32, blank=True, null=True, help_text=u'微信 OpenID', db_index=True)  | 
            |
| 34 | 
                +  | 
            |
| 35 | 
                + name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'销售担当姓名')  | 
            |
| 36 | 
                + phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'销售担当联系电话')  | 
            |
| 37 | 
                +  | 
            |
| 38 | 
                + user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS_TUPLE, default=UNVERIFIED, help_text=u'用户状态', db_index=True)  | 
            |
| 39 | 
                + refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因')  | 
            |
| 40 | 
                +  | 
            |
| 41 | 
                + is_auth = models.BooleanField(_(u'is_auth'), default=False, help_text=_(u'是否已授权'), db_index=True)  | 
            |
| 42 | 
                +  | 
            |
| 43 | 
                + is_super = models.BooleanField(_(u'is_super'), default=True, help_text=_(u'是否超级销售担当'), db_index=True)  | 
            |
| 44 | 
                +  | 
            |
| 45 | 
                + class Meta:  | 
            |
| 46 | 
                + verbose_name = _(u'销售担当信息')  | 
            |
| 47 | 
                + verbose_name_plural = _(u'销售担当信息')  | 
            |
| 48 | 
                +  | 
            |
| 49 | 
                + unique_together = (  | 
            |
| 50 | 
                +            ('brand_id', 'sr_id'),
               | 
            |
| 51 | 
                + )  | 
            |
| 52 | 
                +  | 
            |
| 53 | 
                + def __unicode__(self):  | 
            |
| 54 | 
                +        return u'{}-{}'.format(self.name, self.phone)
               | 
            |
| 55 | 
                +  | 
            |
| 56 | 
                + @property  | 
            |
| 57 | 
                + def admindata(self):  | 
            |
| 58 | 
                +        return {
               | 
            |
| 59 | 
                + 'brand_id': self.brand_id,  | 
            |
| 60 | 
                + 'brand_name': self.brand_name,  | 
            |
| 61 | 
                + 'sr_id': self.sr_id,  | 
            |
| 62 | 
                + 'name': self.name,  | 
            |
| 63 | 
                + 'phone': self.phone,  | 
            |
| 64 | 
                + 'status': self.user_status,  | 
            |
| 65 | 
                + 'refused_reason': self.refused_reason,  | 
            |
| 66 | 
                + 'is_auth': self.is_auth,  | 
            |
| 67 | 
                + }  | 
            |
| 68 | 
                +  | 
            |
| 69 | 
                + data = admindata  | 
            |
| 70 | 
                +  | 
            |
| 71 | 
                +  | 
            |
| 72 | 
                +class SalesResponsibilityInfoModelsSaleStatisticInfo(BaseModelMixin):  | 
            |
| 73 | 
                + brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)  | 
            |
| 74 | 
                +  | 
            |
| 75 | 
                + # 经销商  | 
            |
| 76 | 
                + distributor_id = models.CharField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True)  | 
            |
| 77 | 
                + distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')  | 
            |
| 78 | 
                +  | 
            |
| 79 | 
                + # 型号  | 
            |
| 80 | 
                + model_id = models.CharField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True)  | 
            |
| 81 | 
                + model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称', db_index=True)  | 
            |
| 82 | 
                + is_important = models.BooleanField(_(u'is_important'), default=True, help_text=_(u'是否重要型号'), db_index=True)  | 
            |
| 83 | 
                +  | 
            |
| 84 | 
                + ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True) # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部  | 
            |
| 85 | 
                +  | 
            |
| 86 | 
                + today_num = models.IntegerField(_(u'today_num'), default=0, help_text=u'支数(今日)')  | 
            |
| 87 | 
                + yesterday_num = models.IntegerField(_(u'yesterday_num'), default=0, help_text=u'支数(昨日)')  | 
            |
| 88 | 
                + current_month = models.IntegerField(_(u'current_month'), default=0, help_text=u'支数(本月)')  | 
            |
| 89 | 
                + last_month = models.IntegerField(_(u'last_month'), default=0, help_text=u'支数(上月)')  | 
            |
| 90 | 
                +  | 
            |
| 91 | 
                + position = models.IntegerField(_(u'position'), default=1, help_text=u'排序')  | 
            |
| 92 | 
                +  | 
            |
| 93 | 
                + class Meta:  | 
            |
| 94 | 
                + verbose_name = _(u'[销售担当]型号销量统计')  | 
            |
| 95 | 
                + verbose_name_plural = _(u'[销售担当]型号销量统计')  | 
            |
| 96 | 
                +  | 
            |
| 97 | 
                + def __unicode__(self):  | 
            |
| 98 | 
                + return unicode(self.pk)  | 
            |
| 99 | 
                +  | 
            |
| 100 | 
                + @property  | 
            |
| 101 | 
                + def data(self):  | 
            |
| 102 | 
                +        return {
               | 
            |
| 103 | 
                + 'model_id': self.model_id,  | 
            |
| 104 | 
                + 'model_name': self.model_name,  | 
            |
| 105 | 
                + 'is_important': self.is_important,  | 
            |
| 106 | 
                + 'today_num': self.today_num,  | 
            |
| 107 | 
                + 'yesterday_num': self.yesterday_num,  | 
            |
| 108 | 
                + 'current_month': self.current_month,  | 
            |
| 109 | 
                + 'last_month': self.last_month,  | 
            |
| 110 | 
                + }  | 
            |
| 111 | 
                +  | 
            |
| 112 | 
                +  | 
            |
| 113 | 
                +class SuperSalesResponsibilityInfoModelsSaleStatisticInfo(BaseModelMixin):  | 
            |
| 114 | 
                + brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)  | 
            |
| 115 | 
                +  | 
            |
| 116 | 
                + # 销售担当  | 
            |
| 117 | 
                + sr_id = models.CharField(_(u'sr_id'), max_length=32, help_text=u'销售担当唯一标识', db_index=True)  | 
            |
| 118 | 
                + sr_name = models.CharField(_(u'sr_name'), max_length=255, blank=True, null=True, help_text=u'销售担当名称')  | 
            |
| 119 | 
                +  | 
            |
| 120 | 
                + ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True) # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部  | 
            |
| 121 | 
                +  | 
            |
| 122 | 
                + today_num = models.IntegerField(_(u'today_num'), default=0, help_text=u'支数(今日)')  | 
            |
| 123 | 
                + yesterday_num = models.IntegerField(_(u'yesterday_num'), default=0, help_text=u'支数(昨日)')  | 
            |
| 124 | 
                + current_month = models.IntegerField(_(u'current_month'), default=0, help_text=u'支数(本月)')  | 
            |
| 125 | 
                + last_month = models.IntegerField(_(u'last_month'), default=0, help_text=u'支数(上月)')  | 
            |
| 126 | 
                +  | 
            |
| 127 | 
                + position = models.IntegerField(_(u'position'), default=1, help_text=u'排序')  | 
            |
| 128 | 
                +  | 
            |
| 129 | 
                + class Meta:  | 
            |
| 130 | 
                + verbose_name = _(u'[超级销售担当]销售担当销量统计')  | 
            |
| 131 | 
                + verbose_name_plural = _(u'[超级销售担当]销售担当销量统计')  | 
            |
| 132 | 
                +  | 
            |
| 133 | 
                + def __unicode__(self):  | 
            |
| 134 | 
                + return unicode(self.pk)  | 
            |
| 135 | 
                +  | 
            |
| 136 | 
                + @property  | 
            |
| 137 | 
                + def data(self):  | 
            |
| 138 | 
                +        return {
               | 
            |
| 139 | 
                + 'sr_id': self.sr_id,  | 
            |
| 140 | 
                + 'sr_name': self.sr_name,  | 
            |
| 141 | 
                + 'today_num': self.today_num,  | 
            |
| 142 | 
                + 'yesterday_num': self.yesterday_num,  | 
            |
| 143 | 
                + 'current_month': self.current_month,  | 
            |
| 144 | 
                + 'last_month': self.last_month,  | 
            |
| 145 | 
                + }  | 
            
                @@ -0,0 +1,6 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +from __future__ import unicode_literals  | 
            |
| 3 | 
                +  | 
            |
| 4 | 
                +from django.test import TestCase  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +# Create your tests here.  | 
            
                @@ -0,0 +1,82 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +from __future__ import division  | 
            |
| 4 | 
                +  | 
            |
| 5 | 
                +from django.conf import settings  | 
            |
| 6 | 
                +from django_logit import logit  | 
            |
| 7 | 
                +from django_response import response  | 
            |
| 8 | 
                +from TimeConvert import TimeConvert as tc  | 
            |
| 9 | 
                +  | 
            |
| 10 | 
                +from mch.models import DistributorInfo  | 
            |
| 11 | 
                +from sales.models import SalesResponsibilityInfo, SalesResponsibilityInfoModelsSaleStatisticInfo, SuperSalesResponsibilityInfoModelsSaleStatisticInfo  | 
            |
| 12 | 
                +from utils.error.errno_utils import SalesResponsibilityStatusCode  | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                +  | 
            |
| 15 | 
                +@logit  | 
            |
| 16 | 
                +def sr_submit_api(request):  | 
            |
| 17 | 
                +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 18 | 
                +    user_id = request.POST.get('user_id', '')
               | 
            |
| 19 | 
                +    unionid = request.POST.get('unionid', '')
               | 
            |
| 20 | 
                +    openid = request.POST.get('openid', '')
               | 
            |
| 21 | 
                +    phone = request.POST.get('phone', '')
               | 
            |
| 22 | 
                +  | 
            |
| 23 | 
                + if SalesResponsibilityInfo.objects.filter(brand_id=brand_id, phone=phone).exclude(user_id=user_id).exists():  | 
            |
| 24 | 
                + return response(SalesResponsibilityStatusCode.SR_PHONE_ALREADY_EXISTS)  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                +    SalesResponsibilityInfo.objects.update_or_create(brand_id=brand_id, user_id=user_id, defaults={
               | 
            |
| 27 | 
                +        'name': request.POST.get('name', ''),
               | 
            |
| 28 | 
                +        'phone': request.POST.get('phone', ''),
               | 
            |
| 29 | 
                + 'unionid': unionid,  | 
            |
| 30 | 
                + 'openid': openid,  | 
            |
| 31 | 
                + 'user_status': SalesResponsibilityInfo.UNVERIFIED,  | 
            |
| 32 | 
                + 'status': True,  | 
            |
| 33 | 
                + })  | 
            |
| 34 | 
                +  | 
            |
| 35 | 
                +    return response(200, 'Submit Success', u'提交成功', {})
               | 
            |
| 36 | 
                +  | 
            |
| 37 | 
                +  | 
            |
| 38 | 
                +@logit  | 
            |
| 39 | 
                +def sr_distributor_list(request):  | 
            |
| 40 | 
                +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 41 | 
                +    user_id = request.POST.get('user_id', '')
               | 
            |
| 42 | 
                +    sr_id = request.POST.get('sr_id', '')
               | 
            |
| 43 | 
                +  | 
            |
| 44 | 
                + # if not sr_id:  | 
            |
| 45 | 
                + # try:  | 
            |
| 46 | 
                + # sr = SalesResponsibilityInfo.objects.get(brand_id=brand_id, user_id=user_id)  | 
            |
| 47 | 
                + # except SalesResponsibilityInfo.DoesNotExist:  | 
            |
| 48 | 
                + # return response(SalesResponsibilityStatusCode.SR_NOT_FOUND)  | 
            |
| 49 | 
                + # sr_id = sr.sr_id  | 
            |
| 50 | 
                +  | 
            |
| 51 | 
                + distributors = DistributorInfo.objects.filter(brand_id=brand_id, sr_id=sr_id, status=True)  | 
            |
| 52 | 
                + distributors = [d.admindata for d in distributors]  | 
            |
| 53 | 
                +  | 
            |
| 54 | 
                +    return response(data={
               | 
            |
| 55 | 
                + 'distributors': distributors,  | 
            |
| 56 | 
                + })  | 
            |
| 57 | 
                +  | 
            |
| 58 | 
                +  | 
            |
| 59 | 
                +@logit  | 
            |
| 60 | 
                +def sr_distributor_tj(request):  | 
            |
| 61 | 
                +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 62 | 
                +    distributor_id = request.POST.get('distributor_id', '')
               | 
            |
| 63 | 
                +  | 
            |
| 64 | 
                +    sales = SalesResponsibilityInfoModelsSaleStatisticInfo.objects.filter(brand_id=brand_id, distributor_id=distributor_id, ymd=tc.local_string(format='%Y%m%d'), status=True).order_by('-is_important')
               | 
            |
| 65 | 
                + sales = [sale.data for sale in sales]  | 
            |
| 66 | 
                +  | 
            |
| 67 | 
                +    return response(data={
               | 
            |
| 68 | 
                + 'sales': sales,  | 
            |
| 69 | 
                + })  | 
            |
| 70 | 
                +  | 
            |
| 71 | 
                +  | 
            |
| 72 | 
                +@logit  | 
            |
| 73 | 
                +def supersr_sr_tj(request):  | 
            |
| 74 | 
                +    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
               | 
            |
| 75 | 
                +    sr_id = request.POST.get('sr_id', '')
               | 
            |
| 76 | 
                +  | 
            |
| 77 | 
                +    sales = SuperSalesResponsibilityInfoModelsSaleStatisticInfo.objects.filter(brand_id=brand_id, sr_id=sr_id, ymd=tc.local_string(format='%Y%m%d'), status=True).order_by('-is_important')
               | 
            |
| 78 | 
                + sales = [sale.data for sale in sales]  | 
            |
| 79 | 
                +  | 
            |
| 80 | 
                +    return response(data={
               | 
            |
| 81 | 
                + 'sales': sales,  | 
            |
| 82 | 
                + })  | 
            
                @@ -16,6 +16,13 @@ class SaleclerkStatusCode(BaseStatusCode):  | 
            ||
| 16 | 16 | 
                DUPLICATE_SUBMIT = StatusCodeField(500199, 'Duplicate Submit', description=u'重复提交')  | 
            
| 17 | 17 | 
                 | 
            
| 18 | 18 | 
                 | 
            
| 19 | 
                +class SalesResponsibilityStatusCode(BaseStatusCode):  | 
            |
| 20 | 
                + """ 销售担当相关错误码 5002xx """  | 
            |
| 21 | 
                + SR_NOT_FOUND = StatusCodeField(500201, 'SR Not Found', description=u'销售担当不存在')  | 
            |
| 22 | 
                + # 手机号  | 
            |
| 23 | 
                + SR_PHONE_ALREADY_EXISTS = StatusCodeField(500205, 'SR Phone Already Exists', description=u'手机号已经存在')  | 
            |
| 24 | 
                +  | 
            |
| 25 | 
                +  | 
            |
| 19 | 26 | 
                class ProductBrandStatusCode(BaseStatusCode):  | 
            
| 20 | 27 | 
                """ 品牌相关错误码 5010xx """  | 
            
| 21 | 28 | 
                BRAND_NOT_FOUND = StatusCodeField(501001, 'Brand Not Found', description=u'品牌不存在')  |