Statistic

Brightcells 7 anni fa
parent
commit
44a6cdf337

+ 1 - 0
api/encrypt_views.py

@@ -86,6 +86,7 @@ def decrypt(request):
86 86
             'Brand': brand.brand_name if brand else '',
87 87
             'ModelID': model_pk,
88 88
             'Model': (model.model_full_name or model.model_name) if model else '',
89
+            'DistributorID': distributor_pk,
89 90
             'SerialNo': sn,
90 91
         }
91 92
     })

+ 5 - 0
api/urls.py

@@ -18,6 +18,7 @@ from page import oauth_views, sale_views
18 18
 from pay import views as pay_views
19 19
 from photo import views as photo_views
20 20
 from server import server_views
21
+from statistic import views as tj_views
21 22
 
22 23
 
23 24
 # 帐户相关
@@ -224,3 +225,7 @@ urlpatterns += [
224 225
 urlpatterns += [
225 226
     url(r'^membercard_extradata$', mini_views.membercard_extradata, name='membercard_extradata'),  #
226 227
 ]
228
+
229
+urlpatterns += [
230
+    url(r'^tj$', tj_views.tj_data, name='tj_data'),  # 统计数据
231
+]

+ 1 - 0
kodo/settings.py

@@ -62,6 +62,7 @@ INSTALLED_APPS = (
62 62
     'photo',
63 63
     'product',
64 64
     'server',
65
+    'statistic',
65 66
     'website',
66 67
 )
67 68
 

+ 7 - 0
miniapp/views.py

@@ -12,6 +12,7 @@ from pywe_storage import RedisStorage
12 12
 from TimeConvert import TimeConvert as tc
13 13
 
14 14
 from account.models import UserInfo
15
+from statistic.models import RegisterStatisticInfo
15 16
 from utils.redis.connect import r
16 17
 from utils.redis.rprofile import set_profile_info
17 18
 
@@ -49,6 +50,12 @@ def get_userinfo_api(request):
49 50
     # Set User_id
50 51
     if created:
51 52
         user.user_id = CurtailUUID.uuid(UserInfo, 'user_id')
53
+        # 注册用户统计
54
+        rsi, _ = RegisterStatisticInfo.objects.select_for_update().get_or_create(
55
+            ymd=tc.local_string(format='%Y%m%d'),
56
+        )
57
+        rsi.num += 1
58
+        rsi.save()
52 59
 
53 60
     # Set User Key's Value
54 61
     user.user_from = UserInfo.MINIAPP_USER

+ 40 - 2
page/sale_views.py

@@ -3,16 +3,19 @@
3 3
 from __future__ import division
4 4
 
5 5
 from django.conf import settings
6
+from django.db import transaction
6 7
 from django.shortcuts import render
7 8
 from django_logit import logit
8 9
 from django_response import response
9 10
 from paginator import pagination
11
+from TimeConvert import TimeConvert as tc
10 12
 
11 13
 from account.models import SaleclerkInfo, UserInfo
12 14
 from integral.models import SaleclerkIntegralIncomeExpensesInfo, SaleclerkSubmitLogInfo
13
-from mch.models import ModelInfo
15
+from mch.models import DistributorInfo, ModelInfo
14 16
 from product.models import ProductModelInfo
15
-from utils.error.errno_utils import ProductModelStatusCode, SaleclerkStatusCode
17
+from statistic.models import DistributorSaleStatisticInfo, ModelSaleStatisticInfo, SaleStatisticInfo
18
+from utils.error.errno_utils import ProductDistributorStatusCode, ProductModelStatusCode, SaleclerkStatusCode
16 19
 
17 20
 
18 21
 def clerk_sale_oauth(request):
@@ -34,6 +37,7 @@ def clerk_sale_oauth(request):
34 37
 
35 38
 
36 39
 @logit
40
+@transaction.atomic
37 41
 def clerk_sale_submit_api(request):
38 42
     user_id = request.POST.get('user_id', '')
39 43
     iv = request.POST.get('iv', '')
@@ -41,6 +45,7 @@ def clerk_sale_submit_api(request):
41 45
     lat = float(request.POST.get('lat', 0))
42 46
     lon = float(request.POST.get('lon', 0))
43 47
     modelID = request.POST.get('ModelID', '')
48
+    distributorID = request.POST.get('DistributorID', '')
44 49
     serialNo = request.POST.get('SerialNo', '')
45 50
     verifyResult = request.POST.get('verifyResult', '')
46 51
 
@@ -97,6 +102,11 @@ def clerk_sale_submit_api(request):
97 102
     except ModelInfo.DoesNotExist:
98 103
         return response(ProductModelStatusCode.MODEL_NOT_FOUND)
99 104
 
105
+    try:
106
+        distributor = DistributorInfo.objects.get(pk=distributorID)
107
+    except DistributorInfo.DoesNotExist:
108
+        return response(ProductDistributorStatusCode.DISTRIBUTOR_NOT_FOUND)
109
+
100 110
     integral = model.integral
101 111
 
102 112
     clerk.integral += integral
@@ -121,6 +131,34 @@ def clerk_sale_submit_api(request):
121 131
         test_user=clerk.test_user,
122 132
     )
123 133
 
134
+    if not sci:
135
+        ymd = tc.local_string(format='%Y%m%d')
136
+
137
+        # 销量统计
138
+        ssi, _ = SaleStatisticInfo.objects.select_for_update().get_or_create(
139
+            ymd=ymd,
140
+        )
141
+        ssi.num += 1
142
+        ssi.save()
143
+
144
+        # 型号销量统计
145
+        mssi, _ = ModelSaleStatisticInfo.objects.select_for_update().get_or_create(
146
+            model_id=modelID,
147
+            ymd=ymd,
148
+        )
149
+        mssi.model_name = model.model_name
150
+        mssi.num += 1
151
+        mssi.save()
152
+
153
+        # 经销商销量统计
154
+        dssi, _ = DistributorSaleStatisticInfo.objects.select_for_update().get_or_create(
155
+            distributor_id=distributorID,
156
+            ymd=ymd,
157
+        )
158
+        dssi.distributor_name = distributor.distributor_name
159
+        dssi.num += 1
160
+        dssi.save()
161
+
124 162
     return response(200, data={
125 163
         'integral': integral,
126 164
         'total_integral': clerk.integral,

+ 0 - 0
statistic/__init__.py


+ 7 - 0
statistic/admin.py

@@ -0,0 +1,7 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.contrib import admin
5
+
6
+
7
+# Register your models here.

+ 8 - 0
statistic/apps.py

@@ -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 StatisticConfig(AppConfig):
8
+    name = 'statistic'

+ 80 - 0
statistic/migrations/0001_initial.py

@@ -0,0 +1,80 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.11 on 2018-04-22 17:45
3
+from __future__ import unicode_literals
4
+
5
+from django.db import migrations, models
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    initial = True
11
+
12
+    dependencies = [
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='DistributorSaleStatisticInfo',
18
+            fields=[
19
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
21
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
22
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
23
+                ('distributor_id', models.CharField(db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, verbose_name='distributor_id')),
24
+                ('distributor_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='distributor_name')),
25
+                ('ymd', models.CharField(blank=True, db_index=True, help_text='\u5e74\u6708\u65e5', max_length=8, null=True, verbose_name='ymd')),
26
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
27
+            ],
28
+            options={
29
+                'verbose_name': '\u7ecf\u9500\u5546\u9500\u91cf\u7edf\u8ba1',
30
+                'verbose_name_plural': '\u7ecf\u9500\u5546\u9500\u91cf\u7edf\u8ba1',
31
+            },
32
+        ),
33
+        migrations.CreateModel(
34
+            name='ModelSaleStatisticInfo',
35
+            fields=[
36
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
37
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
38
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
39
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
40
+                ('model_id', models.CharField(db_index=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=32, verbose_name='model_id')),
41
+                ('model_name', models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name')),
42
+                ('ymd', models.CharField(blank=True, db_index=True, help_text='\u5e74\u6708\u65e5', max_length=8, null=True, verbose_name='ymd')),
43
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
44
+            ],
45
+            options={
46
+                'verbose_name': '\u578b\u53f7\u9500\u91cf\u7edf\u8ba1',
47
+                'verbose_name_plural': '\u578b\u53f7\u9500\u91cf\u7edf\u8ba1',
48
+            },
49
+        ),
50
+        migrations.CreateModel(
51
+            name='RegisterStatisticInfo',
52
+            fields=[
53
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
54
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
55
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
56
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
57
+                ('ymd', models.CharField(blank=True, db_index=True, help_text='\u5e74\u6708\u65e5', max_length=8, null=True, verbose_name='ymd')),
58
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
59
+            ],
60
+            options={
61
+                'verbose_name': '\u6ce8\u518c\u7528\u6237\u7edf\u8ba1',
62
+                'verbose_name_plural': '\u6ce8\u518c\u7528\u6237\u7edf\u8ba1',
63
+            },
64
+        ),
65
+        migrations.CreateModel(
66
+            name='SaleStatisticInfo',
67
+            fields=[
68
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
69
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
70
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
71
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
72
+                ('ymd', models.CharField(blank=True, db_index=True, help_text='\u5e74\u6708\u65e5', max_length=8, null=True, verbose_name='ymd')),
73
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
74
+            ],
75
+            options={
76
+                'verbose_name': '\u9500\u91cf\u7edf\u8ba1',
77
+                'verbose_name_plural': '\u9500\u91cf\u7edf\u8ba1',
78
+            },
79
+        ),
80
+    ]

+ 0 - 0
statistic/migrations/__init__.py


+ 89 - 0
statistic/models.py

@@ -0,0 +1,89 @@
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
6
+
7
+
8
+class RegisterStatisticInfo(BaseModelMixin):
9
+    ymd = models.CharField(_(u'ymd'), max_length=8, blank=True, null=True, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
10
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
11
+
12
+    class Meta:
13
+        verbose_name = _(u'注册用户统计')
14
+        verbose_name_plural = _(u'注册用户统计')
15
+
16
+    def __unicode__(self):
17
+        return unicode(self.pk)
18
+
19
+    @property
20
+    def data(self):
21
+        return {
22
+            'ymd': self.ymd,
23
+            'num': self.num,
24
+        }
25
+
26
+
27
+class SaleStatisticInfo(BaseModelMixin):
28
+    ymd = models.CharField(_(u'ymd'), max_length=8, blank=True, null=True, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
29
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
30
+
31
+    class Meta:
32
+        verbose_name = _(u'销量统计')
33
+        verbose_name_plural = _(u'销量统计')
34
+
35
+    def __unicode__(self):
36
+        return unicode(self.pk)
37
+
38
+    @property
39
+    def data(self):
40
+        return {
41
+            'ymd': self.ymd,
42
+            'num': self.num,
43
+        }
44
+
45
+
46
+class ModelSaleStatisticInfo(BaseModelMixin):
47
+    model_id = models.CharField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True)
48
+    model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
49
+    ymd = models.CharField(_(u'ymd'), max_length=8, blank=True, null=True, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
50
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
51
+
52
+    class Meta:
53
+        verbose_name = _(u'型号销量统计')
54
+        verbose_name_plural = _(u'型号销量统计')
55
+
56
+    def __unicode__(self):
57
+        return unicode(self.pk)
58
+
59
+    @property
60
+    def data(self):
61
+        return {
62
+            'model_id': self.model_id,
63
+            'model_name': self.model_name,
64
+            'ymd': self.ymd,
65
+            'num': self.num,
66
+        }
67
+
68
+
69
+class DistributorSaleStatisticInfo(BaseModelMixin):
70
+    distributor_id = models.CharField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True)
71
+    distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
72
+    ymd = models.CharField(_(u'ymd'), max_length=8, blank=True, null=True, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
73
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
74
+
75
+    class Meta:
76
+        verbose_name = _(u'经销商销量统计')
77
+        verbose_name_plural = _(u'经销商销量统计')
78
+
79
+    def __unicode__(self):
80
+        return unicode(self.pk)
81
+
82
+    @property
83
+    def data(self):
84
+        return {
85
+            'distributor_id': self.distributor_id,
86
+            'distributor_name': self.distributor_name,
87
+            'ymd': self.ymd,
88
+            'num': self.num,
89
+        }

+ 7 - 0
statistic/tests.py

@@ -0,0 +1,7 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.test import TestCase
5
+
6
+
7
+# Create your tests here.

+ 50 - 0
statistic/views.py

@@ -0,0 +1,50 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django_logit import logit
4
+from django_response import response
5
+from TimeConvert import TimeConvert as tc
6
+
7
+from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, RegisterStatisticInfo,
8
+                              SaleStatisticInfo)
9
+
10
+
11
+@logit
12
+def tj_data(request):
13
+    ymd = tc.local_string(format='%Y%m%d')
14
+
15
+    # 注册用户统计 & 今日注册用户
16
+    try:
17
+        register_num = RegisterStatisticInfo.objects.get(ymd=ymd).num
18
+    except RegisterStatisticInfo.DoesNotExist:
19
+        register_num = 0
20
+
21
+    # 注册用户数趋势
22
+    register_trends = RegisterStatisticInfo.objects.filter(status=True).order_by('-pk')[:30]
23
+    register_trends = [r.data for r in register_trends]
24
+
25
+    # 销量统计 & 今日销量
26
+    try:
27
+        sale_num = SaleStatisticInfo.objects.get(ymd=ymd).num
28
+    except RegisterStatisticInfo.DoesNotExist:
29
+        sale_num = 0
30
+
31
+    # 商品销量趋势
32
+    sale_trends = SaleStatisticInfo.objects.filter(status=True).order_by('-pk')[:30]
33
+    sale_trends = [s.data for s in sale_trends]
34
+
35
+    # 型号销量统计 & 热销商品榜
36
+    model_sales = ModelSaleStatisticInfo.objects.filter(status=True).order_by('-num')[:3]
37
+    model_sales = [m.data for m in model_sales]
38
+
39
+    # 经销商销量统计 & 经销商榜
40
+    distributor_sales = DistributorSaleStatisticInfo.objects.filter(status=True).order_by('-num')[:3]
41
+    distributor_sales = [d.data for d in distributor_sales]
42
+
43
+    return response(200, 'Get TJ Data Success', u'获取统计数据成功', {
44
+        'register_num': register_num,
45
+        'register_trends': register_trends,
46
+        'sale_num': sale_num,
47
+        'sale_trends': sale_trends,
48
+        'model_sales': model_sales,
49
+        'distributor_sales': distributor_sales,
50
+    })

+ 5 - 0
utils/error/errno_utils.py

@@ -25,6 +25,11 @@ class ProductModelStatusCode(BaseStatusCode):
25 25
     MODEL_NOT_FOUND = StatusCodeField(501001, 'Model Not Found', description=u'型号不存在')
26 26
 
27 27
 
28
+class ProductDistributorStatusCode(BaseStatusCode):
29
+    """ 经销商相关错误码 5011xx """
30
+    DISTRIBUTOR_NOT_FOUND = StatusCodeField(501101, 'Distributor Not Found', description=u'经销商不存在')
31
+
32
+
28 33
 class ProductStatusCode(BaseStatusCode):
29 34
     """ 产品相关错误码 5020xx """
30 35
     PRODUCT_NOT_FOUND = StatusCodeField(502001, 'Product Not Found', description=u'产品不存在')