| @@ -60,6 +60,7 @@ INSTALLED_APPS = ( | ||
| 60 | 60 | 'page', | 
| 61 | 61 | 'pay', | 
| 62 | 62 | 'photo', | 
| 63 | + 'pre', | |
| 63 | 64 | 'product', | 
| 64 | 65 | 'server', | 
| 65 | 66 | 'statistic', | 
| @@ -363,6 +364,9 @@ DISABLE_ACTION = False | ||
| 363 | 364 | # Django-Logit Settings | 
| 364 | 365 | DJANGO_LOGIT_ENABLED = True | 
| 365 | 366 |  | 
| 367 | +# Test Settings | |
| 368 | +DEBUG_DATA_FLAG = False | |
| 369 | + | |
| 366 | 370 | try: | 
| 367 | 371 | from local_settings import * | 
| 368 | 372 | except ImportError: | 
| @@ -150,6 +150,14 @@ def clerk_sale_submit_api(request): | ||
| 150 | 150 | mssi.num += 1 | 
| 151 | 151 | mssi.save() | 
| 152 | 152 |  | 
| 153 | + mssi2, _ = ModelSaleStatisticInfo.objects.select_for_update().get_or_create( | |
| 154 | + model_id=modelID, | |
| 155 | + ymd='0', | |
| 156 | + ) | |
| 157 | + mssi2.model_name = model.model_name | |
| 158 | + mssi2.num += 1 | |
| 159 | + mssi2.save() | |
| 160 | + | |
| 153 | 161 | # 经销商销量统计 | 
| 154 | 162 | dssi, _ = DistributorSaleStatisticInfo.objects.select_for_update().get_or_create( | 
| 155 | 163 | distributor_id=distributorID, | 
| @@ -159,6 +167,14 @@ def clerk_sale_submit_api(request): | ||
| 159 | 167 | dssi.num += 1 | 
| 160 | 168 | dssi.save() | 
| 161 | 169 |  | 
| 170 | + dssi2, _ = DistributorSaleStatisticInfo.objects.select_for_update().get_or_create( | |
| 171 | + distributor_id=distributorID, | |
| 172 | + ymd='0', | |
| 173 | + ) | |
| 174 | + dssi2.distributor_name = distributor.distributor_name | |
| 175 | + dssi2.num += 1 | |
| 176 | + dssi2.save() | |
| 177 | + | |
| 162 | 178 |      return response(200, data={ | 
| 163 | 179 | 'integral': integral, | 
| 164 | 180 | 'total_integral': clerk.integral, | 
| @@ -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. | 
| @@ -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 PreConfig(AppConfig): | |
| 8 | + name = 'pre' | 
| @@ -0,0 +1,7 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +from __future__ import unicode_literals | |
| 3 | + | |
| 4 | +from django.db import models | |
| 5 | + | |
| 6 | + | |
| 7 | +# Create your models here. | 
| @@ -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. | 
| @@ -0,0 +1,67 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | + | |
| 3 | +from __future__ import division | |
| 4 | + | |
| 5 | +from mch.models import DistributorInfo, ModelInfo | |
| 6 | +from statistic.models import DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo | |
| 7 | + | |
| 8 | + | |
| 9 | +PROVINCE_LIST = { | |
| 10 | + "110000": "北京市", | |
| 11 | + "120000": "天津市", | |
| 12 | + "130000": "河北省", | |
| 13 | + "140000": "山西省", | |
| 14 | + "150000": "内蒙古自治区", | |
| 15 | + "210000": "辽宁省", | |
| 16 | + "220000": "吉林省", | |
| 17 | + "230000": "黑龙江省", | |
| 18 | + "310000": "上海市", | |
| 19 | + "320000": "江苏省", | |
| 20 | + "330000": "浙江省", | |
| 21 | + "340000": "安徽省", | |
| 22 | + "350000": "福建省", | |
| 23 | + "360000": "江西省", | |
| 24 | + "370000": "山东省", | |
| 25 | + "410000": "河南省", | |
| 26 | + "420000": "湖北省", | |
| 27 | + "430000": "湖南省", | |
| 28 | + "440000": "广东省", | |
| 29 | + "450000": "广西壮族自治区", | |
| 30 | + "460000": "海南省", | |
| 31 | + "500000": "重庆市", | |
| 32 | + "510000": "四川省", | |
| 33 | + "520000": "贵州省", | |
| 34 | + "530000": "云南省", | |
| 35 | + "540000": "西藏自治区", | |
| 36 | + "610000": "陕西省", | |
| 37 | + "620000": "甘肃省", | |
| 38 | + "630000": "青海省", | |
| 39 | + "640000": "宁夏回族自治区", | |
| 40 | + "650000": "新疆维吾尔自治区", | |
| 41 | + "710000": "台湾省", | |
| 42 | + "810000": "香港特别行政区", | |
| 43 | + "820000": "澳门特别行政区" | |
| 44 | +} | |
| 45 | + | |
| 46 | + | |
| 47 | +def pre_provinces(): | |
| 48 | + for pcode, pname in PROVINCE_LIST.items(): | |
| 49 | + pssi, created = ProvinceSaleStatisticInfo.objects.get_or_create(province_code=pcode, ymd='0') | |
| 50 | + pssi.province_name = pname | |
| 51 | + pssi.save() | |
| 52 | + | |
| 53 | + | |
| 54 | +def pre_models(): | |
| 55 | + models = ModelInfo.objects.filter(status=True) | |
| 56 | + for mdl in models: | |
| 57 | + mssi, created = ModelSaleStatisticInfo.objects.get_or_create(model_id=mdl.model_id, ymd='0') | |
| 58 | + mssi.model_name = mdl.model_name | |
| 59 | + mssi.save() | |
| 60 | + | |
| 61 | + | |
| 62 | +def pre_distributors(): | |
| 63 | + distributors = DistributorInfo.objects.filter(status=True) | |
| 64 | + for dtbt in distributors: | |
| 65 | + dssi, created = DistributorSaleStatisticInfo.objects.get_or_create(distributor_id=dtbt.distributor_id, ymd='0') | |
| 66 | + dssi.distributor_name = dtbt.distributor_name | |
| 67 | + dssi.save() | 
| @@ -9,7 +9,7 @@ django-admin==1.2.4 | ||
| 9 | 9 | django-curtail-uuid==1.0.4 | 
| 10 | 10 | django-detect==1.0.5 | 
| 11 | 11 | django-file-md5==1.0.2 | 
| 12 | -django-file-upload==1.0.2 | |
| 12 | +django-file-upload==1.0.5 | |
| 13 | 13 | django-ip==1.0.2 | 
| 14 | 14 | django-json-render==1.0.0 | 
| 15 | 15 | django-json-response==1.1.5 | 
| @@ -24,7 +24,7 @@ django-rlog==1.0.7 | ||
| 24 | 24 | django-shortuuidfield==0.1.3 | 
| 25 | 25 | django-six==1.0.4 | 
| 26 | 26 | django-uniapi==1.0.1 | 
| 27 | -django-we==1.2.9 | |
| 27 | +django-we==1.3.0 | |
| 28 | 28 | djangorestframework==3.7.7 | 
| 29 | 29 | furl==1.0.1 | 
| 30 | 30 | hiredis==0.2.0 | 
| @@ -40,7 +40,7 @@ pywe-pay==1.0.11 | ||
| 40 | 40 | pywe-pay-notify==1.0.4 | 
| 41 | 41 | pywe-response==1.0.1 | 
| 42 | 42 | pywe-sign==1.0.8 | 
| 43 | -pywe-xml==1.0.3 | |
| 43 | +pywe-xml==1.0.6 | |
| 44 | 44 | qiniu==7.2.0 | 
| 45 | 45 | redis==2.10.6 | 
| 46 | 46 | redis-extensions==1.2.1 | 
| @@ -1,7 +1,42 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- | 
| 2 | -from __future__ import unicode_literals | |
| 3 | 2 |  | 
| 4 | 3 | from django.contrib import admin | 
| 4 | +from django_admin import ReadOnlyModelAdmin | |
| 5 | 5 |  | 
| 6 | +from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo, | |
| 7 | + RegisterStatisticInfo, SaleStatisticInfo) | |
| 6 | 8 |  | 
| 7 | -# Register your models here. | |
| 9 | + | |
| 10 | +class RegisterStatisticInfoAdmin(admin.ModelAdmin): | |
| 11 | +    list_display = ('ymd', 'num', 'status', 'created_at', 'updated_at') | |
| 12 | +    search_fields = ('ymd', ) | |
| 13 | + | |
| 14 | + | |
| 15 | +class SaleStatisticInfoAdmin(admin.ModelAdmin): | |
| 16 | +    list_display = ('ymd', 'num', 'status', 'created_at', 'updated_at') | |
| 17 | +    search_fields = ('ymd', ) | |
| 18 | + | |
| 19 | + | |
| 20 | +class ModelSaleStatisticInfoAdmin(admin.ModelAdmin): | |
| 21 | +    list_display = ('model_id', 'model_name', 'ymd', 'num', 'status', 'created_at', 'updated_at') | |
| 22 | +    list_filter = ('model_name', 'status') | |
| 23 | +    search_fields = ('model_id', 'model_name', 'ymd') | |
| 24 | + | |
| 25 | + | |
| 26 | +class DistributorSaleStatisticInfoAdmin(admin.ModelAdmin): | |
| 27 | +    list_display = ('distributor_id', 'distributor_name', 'ymd', 'num', 'status', 'created_at', 'updated_at') | |
| 28 | +    list_filter = ('distributor_name', 'status') | |
| 29 | +    search_fields = ('distributor_id', 'distributor_name', 'ymd') | |
| 30 | + | |
| 31 | + | |
| 32 | +class ProvinceSaleStatisticInfoAdmin(admin.ModelAdmin): | |
| 33 | +    list_display = ('province_code', 'province_name', 'ymd', 'num', 'status', 'created_at', 'updated_at') | |
| 34 | +    list_filter = ('province_code', 'province_name', 'status') | |
| 35 | +    search_fields = ('province_code', 'province_name', 'ymd') | |
| 36 | + | |
| 37 | + | |
| 38 | +admin.site.register(RegisterStatisticInfo, RegisterStatisticInfoAdmin) | |
| 39 | +admin.site.register(SaleStatisticInfo, SaleStatisticInfoAdmin) | |
| 40 | +admin.site.register(ModelSaleStatisticInfo, ModelSaleStatisticInfoAdmin) | |
| 41 | +admin.site.register(DistributorSaleStatisticInfo, DistributorSaleStatisticInfoAdmin) | |
| 42 | +admin.site.register(ProvinceSaleStatisticInfo, ProvinceSaleStatisticInfoAdmin) | 
| @@ -0,0 +1,32 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | +# Generated by Django 1.11.11 on 2018-04-25 04:59 | |
| 3 | +from __future__ import unicode_literals | |
| 4 | + | |
| 5 | +from django.db import migrations, models | |
| 6 | + | |
| 7 | + | |
| 8 | +class Migration(migrations.Migration): | |
| 9 | + | |
| 10 | + dependencies = [ | |
| 11 | +        ('statistic', '0001_initial'), | |
| 12 | + ] | |
| 13 | + | |
| 14 | + operations = [ | |
| 15 | + migrations.CreateModel( | |
| 16 | + name='ProvinceSaleStatisticInfo', | |
| 17 | + fields=[ | |
| 18 | +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | |
| 19 | +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')), | |
| 20 | +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')), | |
| 21 | +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')), | |
| 22 | +                ('province_code', models.CharField(db_index=True, help_text='\u7701\u4efd\u7f16\u7801', max_length=32, verbose_name='province_code')), | |
| 23 | +                ('province_name', models.CharField(blank=True, help_text='\u7701\u4efd\u540d\u79f0', max_length=32, null=True, verbose_name='province_name')), | |
| 24 | +                ('ymd', models.CharField(blank=True, db_index=True, help_text='\u5e74\u6708\u65e5', max_length=8, null=True, verbose_name='ymd')), | |
| 25 | +                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')), | |
| 26 | + ], | |
| 27 | +            options={ | |
| 28 | + 'verbose_name': '\u7701\u4efd\u9500\u91cf\u7edf\u8ba1', | |
| 29 | + 'verbose_name_plural': '\u7701\u4efd\u9500\u91cf\u7edf\u8ba1', | |
| 30 | + }, | |
| 31 | + ), | |
| 32 | + ] | 
| @@ -1,9 +1,12 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- | 
| 2 | 2 |  | 
| 3 | +from django.conf import settings | |
| 3 | 4 | from django.db import models | 
| 4 | 5 | from django.utils.translation import ugettext_lazy as _ | 
| 5 | 6 | from django_models_ext import BaseModelMixin | 
| 6 | 7 |  | 
| 8 | +from utils.rdm_utils import randnum | |
| 9 | + | |
| 7 | 10 |  | 
| 8 | 11 | class RegisterStatisticInfo(BaseModelMixin): | 
| 9 | 12 | 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') | 
| @@ -20,7 +23,7 @@ class RegisterStatisticInfo(BaseModelMixin): | ||
| 20 | 23 | def data(self): | 
| 21 | 24 |          return { | 
| 22 | 25 | 'ymd': self.ymd, | 
| 23 | - 'num': self.num, | |
| 26 | + 'num': randnum() if settings.DEBUG_DATA_FLAG else self.num, | |
| 24 | 27 | } | 
| 25 | 28 |  | 
| 26 | 29 |  | 
| @@ -39,14 +42,14 @@ class SaleStatisticInfo(BaseModelMixin): | ||
| 39 | 42 | def data(self): | 
| 40 | 43 |          return { | 
| 41 | 44 | 'ymd': self.ymd, | 
| 42 | - 'num': self.num, | |
| 45 | + 'num': randnum() if settings.DEBUG_DATA_FLAG else self.num, | |
| 43 | 46 | } | 
| 44 | 47 |  | 
| 45 | 48 |  | 
| 46 | 49 | class ModelSaleStatisticInfo(BaseModelMixin): | 
| 47 | 50 | model_id = models.CharField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True) | 
| 48 | 51 | 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') | |
| 52 | + 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'), 0 为全部 | |
| 50 | 53 | num = models.IntegerField(_(u'num'), default=0, help_text=u'数量') | 
| 51 | 54 |  | 
| 52 | 55 | class Meta: | 
| @@ -62,14 +65,14 @@ class ModelSaleStatisticInfo(BaseModelMixin): | ||
| 62 | 65 | 'model_id': self.model_id, | 
| 63 | 66 | 'model_name': self.model_name, | 
| 64 | 67 | 'ymd': self.ymd, | 
| 65 | - 'num': self.num, | |
| 68 | + 'num': randnum() if settings.DEBUG_DATA_FLAG else self.num, | |
| 66 | 69 | } | 
| 67 | 70 |  | 
| 68 | 71 |  | 
| 69 | 72 | class DistributorSaleStatisticInfo(BaseModelMixin): | 
| 70 | 73 | distributor_id = models.CharField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True) | 
| 71 | 74 | 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') | |
| 75 | + 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'), 0 为全部 | |
| 73 | 76 | num = models.IntegerField(_(u'num'), default=0, help_text=u'数量') | 
| 74 | 77 |  | 
| 75 | 78 | class Meta: | 
| @@ -85,5 +88,28 @@ class DistributorSaleStatisticInfo(BaseModelMixin): | ||
| 85 | 88 | 'distributor_id': self.distributor_id, | 
| 86 | 89 | 'distributor_name': self.distributor_name, | 
| 87 | 90 | 'ymd': self.ymd, | 
| 88 | - 'num': self.num, | |
| 91 | + 'num': randnum() if settings.DEBUG_DATA_FLAG else self.num, | |
| 92 | + } | |
| 93 | + | |
| 94 | + | |
| 95 | +class ProvinceSaleStatisticInfo(BaseModelMixin): | |
| 96 | + province_code = models.CharField(_(u'province_code'), max_length=32, help_text=u'省份编码', db_index=True) | |
| 97 | + province_name = models.CharField(_(u'province_name'), max_length=32, blank=True, null=True, help_text=u'省份名称') | |
| 98 | + 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'), 0 为全部 | |
| 99 | + num = models.IntegerField(_(u'num'), default=0, help_text=u'数量') | |
| 100 | + | |
| 101 | + class Meta: | |
| 102 | + verbose_name = _(u'省份销量统计') | |
| 103 | + verbose_name_plural = _(u'省份销量统计') | |
| 104 | + | |
| 105 | + def __unicode__(self): | |
| 106 | + return unicode(self.pk) | |
| 107 | + | |
| 108 | + @property | |
| 109 | + def data(self): | |
| 110 | +        return { | |
| 111 | + 'province_code': self.province_code, | |
| 112 | + 'province_name': self.province_name, | |
| 113 | + 'ymd': self.ymd, | |
| 114 | + 'num': randnum() if settings.DEBUG_DATA_FLAG else self.num, | |
| 89 | 115 | } | 
| @@ -1,11 +1,13 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- | 
| 2 | 2 |  | 
| 3 | +from django.conf import settings | |
| 3 | 4 | from django_logit import logit | 
| 4 | 5 | from django_response import response | 
| 5 | 6 | from TimeConvert import TimeConvert as tc | 
| 6 | 7 |  | 
| 7 | -from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, RegisterStatisticInfo, | |
| 8 | - SaleStatisticInfo) | |
| 8 | +from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo, | |
| 9 | + RegisterStatisticInfo, SaleStatisticInfo) | |
| 10 | +from utils.rdm_utils import randnum | |
| 9 | 11 |  | 
| 10 | 12 |  | 
| 11 | 13 | @logit | 
| @@ -25,7 +27,7 @@ def tj_data(request): | ||
| 25 | 27 | # 销量统计 & 今日销量 | 
| 26 | 28 | try: | 
| 27 | 29 | sale_num = SaleStatisticInfo.objects.get(ymd=ymd).num | 
| 28 | - except RegisterStatisticInfo.DoesNotExist: | |
| 30 | + except SaleStatisticInfo.DoesNotExist: | |
| 29 | 31 | sale_num = 0 | 
| 30 | 32 |  | 
| 31 | 33 | # 商品销量趋势 | 
| @@ -33,18 +35,23 @@ def tj_data(request): | ||
| 33 | 35 | sale_trends = [s.data for s in sale_trends] | 
| 34 | 36 |  | 
| 35 | 37 | # 型号销量统计 & 热销商品榜 | 
| 36 | -    model_sales = ModelSaleStatisticInfo.objects.filter(status=True).order_by('-num')[:3] | |
| 38 | +    model_sales = ModelSaleStatisticInfo.objects.filter(ymd='0', status=True).order_by('-num')[:3] | |
| 37 | 39 | model_sales = [m.data for m in model_sales] | 
| 38 | 40 |  | 
| 39 | 41 | # 经销商销量统计 & 经销商榜 | 
| 40 | -    distributor_sales = DistributorSaleStatisticInfo.objects.filter(status=True).order_by('-num')[:3] | |
| 42 | +    distributor_sales = DistributorSaleStatisticInfo.objects.filter(ymd='0', status=True).order_by('-num')[:3] | |
| 41 | 43 | distributor_sales = [d.data for d in distributor_sales] | 
| 42 | 44 |  | 
| 45 | + # 各地区实时销量 | |
| 46 | +    province_sales = ProvinceSaleStatisticInfo.objects.filter(ymd='0', status=True).order_by('-num')[:3] | |
| 47 | + province_sales = [p.data for p in province_sales] | |
| 48 | + | |
| 43 | 49 |      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 | + 'register_num': randnum() if settings.DEBUG_DATA_FLAG else register_num, # 注册用户统计 & 今日注册用户 | |
| 51 | + 'register_trends': register_trends, # 注册用户数趋势 | |
| 52 | + 'sale_num': randnum() if settings.DEBUG_DATA_FLAG else sale_num, # 销量统计 & 今日销量 | |
| 53 | + 'sale_trends': sale_trends, # 商品销量趋势 | |
| 54 | + 'model_sales': model_sales, # 型号销量统计 & 热销商品榜 | |
| 55 | + 'distributor_sales': distributor_sales, # 经销商销量统计 & 经销商榜 | |
| 56 | + 'province_sales': province_sales, # 各地区实时销量 | |
| 50 | 57 | }) | 
| @@ -0,0 +1,7 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | + | |
| 3 | +import random | |
| 4 | + | |
| 5 | + | |
| 6 | +def randnum(sflag=100, eflag=1000): | |
| 7 | + return random.randint(sflag, eflag) |