-1 ol-1"> 207 208
                     fail: function (res) {
208 209
                         if (JSWE.wxShowMenuItemsFail) {JSWE.wxShowMenuItemsFail(res)}
209 210
                     }
210
-                });
211
+                })
211 212
             }
212 213
             // 8.5 隐藏所有非基本菜单项
213 214
             // 8.6 显示所有被隐藏的非基本菜单项
@@ -216,9 +217,24 @@
216 217
             }
217 218
             // 8.7 关闭当前窗口
218 219
             if (wxConfig.close) {wx.closeWindow()}
220
+        }, wxVoiceApi = function() {
221
+            // 4.3 监听录音自动停止
222
+            wx.onVoiceRecordEnd({
223
+                complete: function (res) {
224
+                    voice.localId = res.localId
225
+                    if (JSWE.wxVoiceRecordEnd) {JSWE.wxVoiceRecordEnd(res)}
226
+                }
227
+            })
228
+            // 4.7 监听录音播放停止
229
+            wx.onVoicePlayEnd({
230
+                complete: function (res) {
231
+                    if (JSWE.wxVoicePlayEnd) {JSWE.wxVoicePlayEnd(res)}
232
+                }
233
+            })
219 234
         }, wxApi = function () {
220 235
             wxShareApi()
221 236
             wxMenuApi()
237
+            wxVoiceApi()
222 238
         }
223 239
 
224 240
         wx.ready(wxApi)
@@ -254,13 +270,119 @@
254 270
         if ('undefined' !== typeof wxApiFun) wxApiFun()
255 271
     }
256 272
 
273
+    // 3 智能接口
274
+    var voice = {
275
+        localId: '',
276
+        serverId: ''
277
+    }
278
+    // 3.1 识别音频并返回识别结果
279
+    function translateVoice() {
280
+        if (voice.localId == '') {
281
+            if (JSWE.wxTranslateVoiceEmpty) {JSWE.wxTranslateVoiceEmpty()}
282
+            return
283
+        }
284
+        wx.translateVoice({
285
+            localId: voice.localId,
286
+            complete: function (res) {
287
+                if (JSWE.wxTranslateVoiceComplete) {JSWE.wxTranslateVoiceComplete(res)}
288
+            }
289
+        })
290
+    }
291
+
292
+    // 4 音频接口
293
+    // 4.1 开始录音
294
+    function startRecord() {
295
+        wx.startRecord({
296
+            cancel: function () {
297
+                if (JSWE.wxStartRecordCancel) {JSWE.wxStartRecordCancel(res)}
298
+            }
299
+        })
300
+    }
301
+
302
+    // 4.2 停止录音
303
+    function stopRecord() {
304
+        wx.stopRecord({
305
+          success: function (res) {
306
+              voice.localId = res.localId
307
+              if (JSWE.wxStopRecordSuccess) {JSWE.wxStopRecordSuccess(res)}
308
+          },
309
+          fail: function (res) {
310
+              if (JSWE.wxStopRecordFail) {JSWE.wxStopRecordFail(res)}
311
+          }
312
+        })
313
+    }
314
+
315
+    // 4.4 播放音频
316
+    function playVoice() {
317
+        if (voice.localId == '') {
318
+            if (JSWE.wxPlayVoiceEmpty) {JSWE.wxPlayVoiceEmpty()}
319
+            return
320
+        }
321
+        wx.playVoice({
322
+            localId: voice.localId
323
+        })
324
+    }
325
+
326
+    // 4.5 暂停播放音频
327
+    function pauseVoice() {
328
+        if (voice.localId == '') {
329
+            if (JSWE.wxPauseVoiceEmpty) {JSWE.wxPauseVoiceEmpty()}
330
+            return
331
+        }
332
+        wx.pauseVoice({
333
+            localId: voice.localId
334
+        })
335
+    }
336
+
337
+    // 4.6 停止播放音频
338
+    function stopVoice() {
339
+        if (voice.localId == '') {
340
+            if (JSWE.wxStopVoiceEmpty) {JSWE.wxStopVoiceEmpty()}
341
+            return
342
+        }
343
+        wx.stopVoice({
344
+            localId: voice.localId
345
+        })
346
+    }
347
+
348
+    // 4.8 上传语音
349
+    function uploadVoice() {
350
+        var localId = voice.localId
351
+        if (localId == '') {
352
+            if (JSWE.wxUploadVoiceEmpty) {JSWE.wxUploadVoiceEmpty()}
353
+            return
354
+        }
355
+        wx.uploadVoice({
356
+            localId: localId,
357
+            success: function (res) {
358
+                voice.serverId = res.serverId
359
+                if (JSWE.wxUploadVoiceSuccess) {JSWE.wxUploadVoiceSuccess(res, localId)}
360
+            }
361
+        })
362
+    }
363
+
364
+    // 4.9 下载语音
365
+    function downloadVoice() {
366
+        var serverId = voice.serverId
367
+        if (serverId == '') {
368
+            if (JSWE.wxDownloadVoiceEmpty) {JSWE.wxDownloadVoiceEmpty()}
369
+            return
370
+        }
371
+        wx.downloadVoice({
372
+            serverId: serverId,
373
+            success: function (res) {
374
+                voice.localId = res.localId
375
+                if (JSWE.wxDownloadVoiceSuccess) {JSWE.wxDownloadVoiceSuccess(res, serverId)}
376
+            }
377
+        })
378
+    }
379
+
257 380
     // 5 图片接口
258
-    // 5.1 拍照、本地选图
259 381
     var images = {
260 382
         localIds: [],
261 383
         serverIds: []
262
-    };
263
-    // function chooseImage(count, directUpload, isShowProgressTips) {
384
+    }
385
+    // 5.1 拍照、本地选图
264 386
     function chooseImage(choose_params) {
265 387
         if ('undefined' === typeof choose_params) choose_params = {}
266 388
         wx.chooseImage({
@@ -268,13 +390,13 @@
268 390
             sizeType: choose_params.sizeType || ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
269 391
             sourceType: choose_params.sourceType || ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
270 392
             success: function (res) {
271
-                images.localIds = res.localIds; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
393
+                images.localIds = res.localIds // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
272 394
                 // 判断是否直接上传
273 395
                 if (choose_params.directUpload) {setTimeout(uploadImages({localIds: images.localIds, isShowProgressTips: choose_params.isShowProgressTips || 1}), 100)}
274 396
                 // 拍照、本地选图成功后的回调函数
275
-                if (JSWE.wxChooseImageSuccess) {JSWE.wxChooseImageSuccess(res)}
397
+                if (JSWE.wxChooseImageSuccess) {JSWE.wxChooseImageSuccess(res, choose_params.extras || {})}
276 398
             }
277
-        });
399
+        })
278 400
     }
279 401
 
280 402
     // 5.2 图片预览
@@ -282,31 +404,59 @@
282 404
         wx.previewImage({
283 405
             current: preview_params.current, // 当前显示图片的链接,不填则默认为 urls 的第一张
284 406
             urls: preview_params.urls // 需要预览的图片链接列表
285
-        });
407
+        })
286 408
     }
287 409
 
288 410
     // 5.3 上传图片
289
-    // function uploadImage(localId, isShowProgressTips) {
290 411
     function uploadImage(upload_params) {
291 412
         // 上传图片为异步处理,重复上传同一图片,返回的serverId也是不同的
413
+        var localId = upload_params.localId
292 414
         wx.uploadImage({
293
-            localId: upload_params.localId, // 需要上传的图片的本地ID,由chooseImage接口获得
415
+            localId: localId, // 需要上传的图片的本地ID,由chooseImage接口获得
294 416
             isShowProgressTips: upload_params.isShowProgressTips || 1, // 默认为1,显示进度提示
295 417
             success: function (res) {
296
-                images.serverIds.push(res.serverId); // 返回图片的服务器端ID
418
+                images.serverIds.push(res.serverId) // 返回图片的服务器端ID
297 419
                 // 上传图片成功后的回调函数
298
-                if (JSWE.wxUploadImageSuccess) {JSWE.wxUploadImageSuccess(res)}
420
+                if (JSWE.wxUploadImageSuccess) {JSWE.wxUploadImageSuccess(res, localId)}
299 421
             }
300
-        });
422
+        })
301 423
     }
302 424
 
303
-    // function uploadImages(localIds, isShowProgressTips) {
304 425
     function uploadImages(upload_params) {
305 426
         var localIds = upload_params.localIds, isShowProgressTips = upload_params.isShowProgressTips || 1
306
-        images.serverIds = [];
427
+        images.serverIds = []
307 428
         for (var idx in localIds) {uploadImage({localId: localIds[idx], isShowProgressTips: isShowProgressTips})}
308 429
     }
309 430
 
431
+    // 5.4 下载图片
432
+    function downloadImage(download_params) {
433
+        var serverId = download_params.serverId
434
+        wx.downloadImage({
435
+            serverId: serverId, // 需要下载的图片的服务器端ID,由uploadImage接口获得
436
+            isShowProgressTips: download_params.isShowProgressTips || 1, // 默认为1,显示进度提示
437
+            success: function (res) {
438
+                images.localId.push(res.localId)
439
+                if (JSWE.wxDownloadImageSuccess) {JSWE.wxDownloadImageSuccess(res, serverId)}
440
+            }
441
+        })
442
+    }
443
+
444
+    function downloadImages(download_params) {
445
+        var serverIds = download_params.serverIds, isShowProgressTips = download_params.isShowProgressTips || 1
446
+        images.localIds = []
447
+        for (var idx in serverIds) {downloadImage({serverId: serverIds[idx], isShowProgressTips: isShowProgressTips})}
448
+    }
449
+
450
+    function getLocalImgData(localId) {
451
+        wx.getLocalImgData({
452
+            localId: localId, // 图片的localID
453
+            success: function (res) {
454
+                // var localData = res.localData; // localData是图片的base64数据,可以用img标签显示
455
+                if (JSWE.wxGetLocalImgDataSuccess) {JSWE.wxGetLocalImgDataSuccess(res)}
456
+            }
457
+        })
458
+    }
459
+
310 460
     // 9 微信原生接口
311 461
     // 9.1.1 扫描二维码并返回结果
312 462
     // 9.1.2 扫描二维码并返回结果
@@ -318,7 +468,7 @@
318 468
             success: function (res) {  // 当 needResult 为 1 时,扫码返回的结果
319 469
                 if (JSWE.wxScanQRCodeSuccess) {JSWE.wxScanQRCodeSuccess(res)}
320 470
             }
321
-        });
471
+        })
322 472
     }
323 473
 
324 474
     // QRCode & BarCode is different
@@ -389,12 +539,26 @@
389 539
         changeWxData: changeWxData,
390 540
         fixedWxData: fixedWxData,
391 541
 
542
+        // Voice Function
543
+        voice: voice,
544
+        translateVoice: translateVoice,
545
+        startRecord: startRecord,
546
+        stopRecord: stopRecord,
547
+        playVoice: playVoice,
548
+        pauseVoice: pauseVoice,
549
+        stopVoice: stopVoice,
550
+        uploadVoice: uploadVoice,
551
+        downloadVoice: downloadVoice,
552
+
392 553
         // Image Function
393 554
         images: images,
394 555
         chooseImage: chooseImage,
395 556
         previewImage: previewImage,
396 557
         uploadImage: uploadImage,
397 558
         uploadImages: uploadImages,
559
+        downloadImage: downloadImage,
560
+        downloadImages: downloadImages,
561
+        getLocalImgData: getLocalImgData,
398 562
 
399 563
         // Scan Function
400 564
         scanQRCode: scanQRCode,

+ 1 - 1
photo/templates/photo/photo_detail.html

@@ -47,7 +47,7 @@
47 47
 
48 48
         <script type="text/javascript" src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
49 49
         <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
50
-        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.3.js' %}"></script>
50
+        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.4.js' %}"></script>
51 51
         <script>
52 52
             V.initWxData({
53 53
                 imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",

+ 1 - 1
photo/templates/photo/session_detail.html

@@ -49,7 +49,7 @@
49 49
 
50 50
         <script type="text/javascript" src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
51 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 'pai2/js/jswe-0.0.3.js' %}"></script>
52
+        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.4.js' %}"></script>
53 53
         <script>
54 54
             V.initWxData({
55 55
                 imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",

Statistic · 537c495621 - Gogs: Go Git Service

Statistic

Brightcells преди 8 години
родител
ревизия
537c495621

+ 1 - 0
api/encrypt_views.py

@@ -83,6 +83,7 @@ def decrypt(request):
83 83
         'logo_url': brand.brand_logo_url if brand else '',
84 84
         'model_imgs': model.images if model else [],
85 85
         'goodsInfo': {
86
+            'BrandID': brand_pk,
86 87
             'Brand': brand.brand_name if brand else '',
87 88
             'ModelID': model_pk,
88 89
             'Model': (model.model_full_name or model.model_name) if model else '',

+ 112 - 1
api/mch_views.py

@@ -8,10 +8,14 @@ from django_logit import logit
8 8
 from django_response import response
9 9
 from pywe_miniapp import get_phone_number
10 10
 from pywe_storage import RedisStorage
11
+from TimeConvert import TimeConvert as tc
11 12
 
12 13
 from account.models import UserInfo
13 14
 from mch.models import BrandInfo, ConsumeInfoSubmitLogInfo, DistributorInfo, LatestAppInfo, ModelInfo, OperatorInfo
14
-from utils.error.errno_utils import OperatorStatusCode, UserStatusCode
15
+from statistic.models import (ConsumeDistributorSaleStatisticInfo, ConsumeModelSaleStatisticInfo,
16
+                              ConsumeProvinceSaleStatisticInfo, ConsumeSaleStatisticInfo)
17
+from utils.error.errno_utils import (OperatorStatusCode, ProductBrandStatusCode, ProductDistributorStatusCode,
18
+                                     ProductModelStatusCode, SaleclerkStatusCode, UserStatusCode)
15 19
 from utils.redis.connect import r
16 20
 
17 21
 
@@ -153,6 +157,9 @@ def consumer_info_api(request):
153 157
     encryptedData = request.POST.get('encryptedData', '')
154 158
     lat = request.POST.get('lat', '')
155 159
     lon = request.POST.get('lon', '')
160
+    brandID = request.POST.get('BrandID', '')
161
+    modelID = request.POST.get('ModelID', '')
162
+    distributorID = request.POST.get('DistributorID', '')
156 163
     serialNo = request.POST.get('SerialNo', '')
157 164
     verifyResult = request.POST.get('verifyResult', '')
158 165
     purePhoneNumber = request.POST.get('purePhoneNumber', '')
@@ -169,6 +176,27 @@ def consumer_info_api(request):
169 176
     user.phone = purePhoneNumber
170 177
     user.save()
171 178
 
179
+    try:
180
+        brand = BrandInfo.objects.get(pk=brandID)
181
+    except BrandInfo.DoesNotExist:
182
+        return response(ProductBrandStatusCode.BRAND_NOT_FOUND)
183
+    except ValueError:
184
+        return response(ProductBrandStatusCode.BRAND_NOT_FOUND)
185
+
186
+    try:
187
+        model = ModelInfo.objects.get(pk=modelID)
188
+    except ModelInfo.DoesNotExist:
189
+        return response(ProductModelStatusCode.MODEL_NOT_FOUND)
190
+    except ValueError:
191
+        return response(ProductModelStatusCode.MODEL_NOT_FOUND)
192
+
193
+    try:
194
+        distributor = DistributorInfo.objects.get(pk=distributorID)
195
+    except DistributorInfo.DoesNotExist:
196
+        return response(ProductDistributorStatusCode.DISTRIBUTOR_NOT_FOUND)
197
+    except ValueError:
198
+        return response(ProductDistributorStatusCode.DISTRIBUTOR_NOT_FOUND)
199
+
172 200
     # 记录用户信息提交记录
173 201
     ConsumeInfoSubmitLogInfo.objects.create(
174 202
         user_id=user_id,
@@ -177,9 +205,92 @@ def consumer_info_api(request):
177 205
         encryptedData=encryptedData,
178 206
         lat=lat,
179 207
         lon=lon,
208
+        brand_id=brand.brand_id,
209
+        brand_name=brand.brand_name,
210
+        model_id=model.model_id,
211
+        model_name=model.model_name,
212
+        distributor_id=distributor.distributor_id,
213
+        distributor_name=distributor.distributor_name,
180 214
         serialNo=serialNo,
181 215
         verifyResult=verifyResult,
182 216
         test_user=user.test_user,
183 217
     )
184 218
 
219
+    if not user.test_user:
220
+        # TODO: Make statistic async
221
+        if ConsumeInfoSubmitLogInfo.objects.filter(
222
+            brand_id=brand.brand_id,
223
+            model_id=model.model_id,
224
+            distributor_id=distributor.distributor_id,
225
+            serialNo=serialNo,
226
+            verifyResult=1,
227
+            test_user=False,
228
+        ).count() == 1:
229
+            ymd = int(tc.local_string(format='%Y%m%d'))
230
+
231
+            # 销量统计
232
+            ssi, _ = ConsumeSaleStatisticInfo.objects.select_for_update().get_or_create(
233
+                brand_id=brand.brand_id,
234
+                ymd=ymd,
235
+            )
236
+            ssi.num += 1
237
+            ssi.save()
238
+
239
+            # 型号销量统计
240
+            mssi, _ = ConsumeModelSaleStatisticInfo.objects.select_for_update().get_or_create(
241
+                brand_id=brand.brand_id,
242
+                model_id=model.model_id,
243
+                ymd=ymd,
244
+            )
245
+            mssi.model_name = model.model_name
246
+            mssi.num += 1
247
+            mssi.save()
248
+
249
+            mssi2, _ = ConsumeModelSaleStatisticInfo.objects.select_for_update().get_or_create(
250
+                brand_id=brand.brand_id,
251
+                model_id=model.model_id,
252
+                ymd=0,
253
+            )
254
+            mssi2.model_name = model.model_name
255
+            mssi2.num += 1
256
+            mssi2.save()
257
+
258
+            # 经销商销量统计
259
+            dssi, _ = ConsumeDistributorSaleStatisticInfo.objects.select_for_update().get_or_create(
260
+                brand_id=brand.brand_id,
261
+                distributor_id=distributor.distributor_id,
262
+                ymd=ymd,
263
+            )
264
+            dssi.distributor_name = distributor.distributor_name
265
+            dssi.num += 1
266
+            dssi.save()
267
+
268
+            dssi2, _ = ConsumeDistributorSaleStatisticInfo.objects.select_for_update().get_or_create(
269
+                brand_id=brand.brand_id,
270
+                distributor_id=distributor.distributor_id,
271
+                ymd=0,
272
+            )
273
+            dssi2.distributor_name = distributor.distributor_name
274
+            dssi2.num += 1
275
+            dssi2.save()
276
+
277
+            # 省份销量统计
278
+            pssi, _ = ConsumeProvinceSaleStatisticInfo.objects.select_for_update().get_or_create(
279
+                brand_id=brand.brand_id,
280
+                province_code=distributor.distributor_province_code,
281
+                ymd=ymd,
282
+            )
283
+            pssi.province_name = distributor.distributor_province_name
284
+            pssi.num += 1
285
+            pssi.save()
286
+
287
+            pssi2, _ = ConsumeProvinceSaleStatisticInfo.objects.select_for_update().get_or_create(
288
+                brand_id=brand.brand_id,
289
+                province_code=distributor.distributor_province_code,
290
+                ymd=0,
291
+            )
292
+            pssi2.province_name = distributor.distributor_province_name
293
+            pssi2.num += 1
294
+            pssi2.save()
295
+
185 296
     return response(200, 'Submit Consumer Info Success', u'提交消费者信息成功')

+ 3 - 1
api/urls.py

@@ -227,6 +227,8 @@ urlpatterns += [
227 227
 ]
228 228
 
229 229
 urlpatterns += [
230
-    url(r'^tj$', tj_views.tj_data, name='tj_data'),  # 统计数据
230
+    url(r'^tj$', tj_views.tj_distributor, name='tj_distributor_old'),  # 统计数据(经销商维度)
231
+    url(r'^tj/distributor$', tj_views.tj_distributor, name='tj_distributor'),  # 统计数据(经销商维度)
232
+    url(r'^tj/consumer$', tj_views.tj_consumer, name='tj_consumer'),  # 统计数据(消费者维度)
231 233
     url(r'^tj/generate$', tj_views.tj_generate, name='tj_generate'),  # 统计数据生成
232 234
 ]

+ 50 - 0
integral/migrations/0006_auto_20180508_1830.py

@@ -0,0 +1,50 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.11 on 2018-05-08 10:30
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
+        ('integral', '0005_saleclerksubmitloginfo_dupload'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AddField(
16
+            model_name='saleclerkintegralincomeexpensesinfo',
17
+            name='brand_id',
18
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
19
+        ),
20
+        migrations.AddField(
21
+            model_name='saleclerkintegralincomeexpensesinfo',
22
+            name='brand_name',
23
+            field=models.CharField(blank=True, help_text='\u54c1\u724c\u540d\u79f0', max_length=255, null=True, verbose_name='brand_name'),
24
+        ),
25
+        migrations.AddField(
26
+            model_name='saleclerkintegralincomeexpensesinfo',
27
+            name='distributor_id',
28
+            field=models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='distributor_id'),
29
+        ),
30
+        migrations.AddField(
31
+            model_name='saleclerkintegralincomeexpensesinfo',
32
+            name='distributor_name',
33
+            field=models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='distributor_name'),
34
+        ),
35
+        migrations.AddField(
36
+            model_name='saleclerksubmitloginfo',
37
+            name='brand_pk',
38
+            field=models.IntegerField(db_index=True, default=0, help_text='\u54c1\u724cPK', verbose_name='brand_pk'),
39
+        ),
40
+        migrations.AddField(
41
+            model_name='saleclerksubmitloginfo',
42
+            name='distributor_pk',
43
+            field=models.IntegerField(db_index=True, default=0, help_text='\u7ecf\u9500\u5546PK', verbose_name='distributor_pk'),
44
+        ),
45
+        migrations.AddField(
46
+            model_name='saleclerksubmitloginfo',
47
+            name='model_pk',
48
+            field=models.IntegerField(db_index=True, default=0, help_text='\u578b\u53f7PK', verbose_name='model_pk'),
49
+        ),
50
+    ]

+ 10 - 0
integral/models.py

@@ -21,9 +21,15 @@ class SaleclerkIntegralIncomeExpensesInfo(BaseModelMixin):
21 21
 
22 22
     type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别', db_index=True)
23 23
 
24
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
25
+    brand_name = models.CharField(_(u'brand_name'), max_length=255, blank=True, null=True, help_text=u'品牌名称')
26
+
24 27
     model_id = models.CharField(_(u'model_id'), max_length=32, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
25 28
     model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
26 29
 
30
+    distributor_id = models.CharField(_(u'distributor_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
31
+    distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
32
+
27 33
     code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码', db_index=True)
28 34
 
29 35
     consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者姓名')
@@ -63,6 +69,10 @@ class SaleclerkSubmitLogInfo(BaseModelMixin):
63 69
     franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
64 70
     clerk_id = models.CharField(_(u'clerk_id'), max_length=32, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
65 71
 
72
+    brand_pk = models.IntegerField(_(u'brand_pk'), default=0, help_text=u'品牌PK', db_index=True)
73
+    model_pk = models.IntegerField(_(u'model_pk'), default=0, help_text=u'型号PK', db_index=True)
74
+    distributor_pk = models.IntegerField(_(u'distributor_pk'), default=0, help_text=u'经销商PK', db_index=True)
75
+
66 76
     code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码', db_index=True)
67 77
 
68 78
     consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者姓名')

+ 1 - 1
mch/admin.py

@@ -165,6 +165,6 @@ admin.site.register(BrandInfo, BrandInfoAdmin)
165 165
 admin.site.register(ModelInfo, ModelInfoAdmin)
166 166
 # admin.site.register(ModelImageInfo, ModelImageInfoAdmin)
167 167
 admin.site.register(DistributorInfo, DistributorInfoAdmin)
168
-admin.site.register(BrandModelDistributorPriceInfo, BrandModelDistributorPriceInfoAdmin)
168
+# admin.site.register(BrandModelDistributorPriceInfo, BrandModelDistributorPriceInfoAdmin)
169 169
 admin.site.register(LatestAppInfo, LatestAppInfoAdmin)
170 170
 admin.site.register(ConsumeInfoSubmitLogInfo, ConsumeInfoSubmitLogInfoAdmin)

+ 49 - 0
mch/migrations/0017_auto_20180508_1830.py

@@ -0,0 +1,49 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.11 on 2018-05-08 10:30
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
+        ('mch', '0016_auto_20180508_1507'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AlterModelOptions(
16
+            name='brandmodeldistributorpriceinfo',
17
+            options={'verbose_name': '\u54c1\u724c/\u578b\u53f7/\u4ee3\u7406\u5546\u4ef7\u683c\u4fe1\u606f', 'verbose_name_plural': '\u54c1\u724c/\u578b\u53f7/\u4ee3\u7406\u5546\u4ef7\u683c\u4fe1\u606f'},
18
+        ),
19
+        migrations.AddField(
20
+            model_name='consumeinfosubmitloginfo',
21
+            name='brand_id',
22
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
23
+        ),
24
+        migrations.AddField(
25
+            model_name='consumeinfosubmitloginfo',
26
+            name='brand_name',
27
+            field=models.CharField(blank=True, help_text='\u54c1\u724c\u540d\u79f0', max_length=255, null=True, verbose_name='brand_name'),
28
+        ),
29
+        migrations.AddField(
30
+            model_name='consumeinfosubmitloginfo',
31
+            name='distributor_id',
32
+            field=models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='distributor_id'),
33
+        ),
34
+        migrations.AddField(
35
+            model_name='consumeinfosubmitloginfo',
36
+            name='distributor_name',
37
+            field=models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=255, null=True, verbose_name='distributor_name'),
38
+        ),
39
+        migrations.AddField(
40
+            model_name='consumeinfosubmitloginfo',
41
+            name='model_id',
42
+            field=models.CharField(blank=True, db_index=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='model_id'),
43
+        ),
44
+        migrations.AddField(
45
+            model_name='consumeinfosubmitloginfo',
46
+            name='model_name',
47
+            field=models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name'),
48
+        ),
49
+    ]

+ 9 - 0
mch/models.py

@@ -281,6 +281,15 @@ class ConsumeInfoSubmitLogInfo(BaseModelMixin):
281 281
     lat = models.FloatField(_(u'lat'), default=1.0, help_text=u'纬度')
282 282
     lon = models.FloatField(_(u'lon'), default=1.0, help_text=u'经度')
283 283
 
284
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
285
+    brand_name = models.CharField(_(u'brand_name'), max_length=255, blank=True, null=True, help_text=u'品牌名称')
286
+
287
+    model_id = models.CharField(_(u'model_id'), max_length=32, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
288
+    model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
289
+
290
+    distributor_id = models.CharField(_(u'distributor_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
291
+    distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
292
+
284 293
     serialNo = models.CharField(_(u'serialNo'), max_length=16, blank=True, null=True, help_text=u'序列号', db_index=True)
285 294
 
286 295
     verifyResult = models.IntegerField(_(u'verifyResult'), default=0, help_text=u'验证结果')

+ 25 - 2
page/sale_views.py

@@ -12,11 +12,12 @@ from TimeConvert import TimeConvert as tc
12 12
 
13 13
 from account.models import SaleclerkInfo, UserInfo
14 14
 from integral.models import SaleclerkIntegralIncomeExpensesInfo, SaleclerkSubmitLogInfo
15
-from mch.models import DistributorInfo, ModelInfo
15
+from mch.models import BrandInfo, DistributorInfo, ModelInfo
16 16
 from product.models import ProductModelInfo
17 17
 from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo,
18 18
                               SaleStatisticInfo)
19
-from utils.error.errno_utils import ProductDistributorStatusCode, ProductModelStatusCode, SaleclerkStatusCode
19
+from utils.error.errno_utils import (ProductBrandStatusCode, ProductDistributorStatusCode, ProductModelStatusCode,
20
+                                     SaleclerkStatusCode)
20 21
 
21 22
 
22 23
 def clerk_sale_oauth(request):
@@ -45,6 +46,7 @@ def clerk_sale_submit_api(request):
45 46
     encryptedData = request.POST.get('encryptedData', '')
46 47
     lat = float(request.POST.get('lat', 0))
47 48
     lon = float(request.POST.get('lon', 0))
49
+    brandID = request.POST.get('BrandID', '')
48 50
     modelID = request.POST.get('ModelID', '')
49 51
     distributorID = request.POST.get('DistributorID', '')
50 52
     serialNo = request.POST.get('SerialNo', '')
@@ -69,6 +71,9 @@ def clerk_sale_submit_api(request):
69 71
     ssli = SaleclerkSubmitLogInfo.objects.create(
70 72
         franchiser_id=clerk.franchiser_id,
71 73
         clerk_id=clerk.clerk_id,
74
+        brand_pk=brandID,
75
+        model_pk=modelID,
76
+        distributor_pk=distributorID,
72 77
         code=serialNo,
73 78
         consumer_name=consumer_name,
74 79
         consumer_phone=consumer_phone,
@@ -99,6 +104,13 @@ def clerk_sale_submit_api(request):
99 104
 
100 105
     # 店员积分
101 106
     try:
107
+        brand = BrandInfo.objects.get(pk=brandID)
108
+    except BrandInfo.DoesNotExist:
109
+        return response(ProductBrandStatusCode.BRAND_NOT_FOUND)
110
+    except ValueError:
111
+        return response(ProductBrandStatusCode.BRAND_NOT_FOUND)
112
+
113
+    try:
102 114
         model = ModelInfo.objects.get(pk=modelID)
103 115
     except ModelInfo.DoesNotExist:
104 116
         return response(ProductModelStatusCode.MODEL_NOT_FOUND)
@@ -123,8 +135,12 @@ def clerk_sale_submit_api(request):
123 135
         franchiser_id=clerk.franchiser_id,
124 136
         clerk_id=clerk.clerk_id,
125 137
         type=SaleclerkIntegralIncomeExpensesInfo.INCOME,
138
+        brand_id=brand.brand_id,
139
+        brand_name=brand.brand_name,
126 140
         model_id=model.model_id,
127 141
         model_name=model.model_name,
142
+        distributor_id=distributor.distributor_id,
143
+        distributor_name=distributor.distributor_name,
128 144
         code=serialNo,
129 145
         consumer_name=consumer_name,
130 146
         consumer_phone=consumer_phone,
@@ -142,6 +158,7 @@ def clerk_sale_submit_api(request):
142 158
 
143 159
         # 销量统计
144 160
         ssi, _ = SaleStatisticInfo.objects.select_for_update().get_or_create(
161
+            brand_id=brand.brand_id,
145 162
             ymd=ymd,
146 163
         )
147 164
         ssi.num += 1
@@ -149,6 +166,7 @@ def clerk_sale_submit_api(request):
149 166
 
150 167
         # 型号销量统计
151 168
         mssi, _ = ModelSaleStatisticInfo.objects.select_for_update().get_or_create(
169
+            brand_id=brand.brand_id,
152 170
             model_id=model.model_id,
153 171
             ymd=ymd,
154 172
         )
@@ -157,6 +175,7 @@ def clerk_sale_submit_api(request):
157 175
         mssi.save()
158 176
 
159 177
         mssi2, _ = ModelSaleStatisticInfo.objects.select_for_update().get_or_create(
178
+            brand_id=brand.brand_id,
160 179
             model_id=model.model_id,
161 180
             ymd=0,
162 181
         )
@@ -166,6 +185,7 @@ def clerk_sale_submit_api(request):
166 185
 
167 186
         # 经销商销量统计
168 187
         dssi, _ = DistributorSaleStatisticInfo.objects.select_for_update().get_or_create(
188
+            brand_id=brand.brand_id,
169 189
             distributor_id=distributor.distributor_id,
170 190
             ymd=ymd,
171 191
         )
@@ -174,6 +194,7 @@ def clerk_sale_submit_api(request):
174 194
         dssi.save()
175 195
 
176 196
         dssi2, _ = DistributorSaleStatisticInfo.objects.select_for_update().get_or_create(
197
+            brand_id=brand.brand_id,
177 198
             distributor_id=distributor.distributor_id,
178 199
             ymd=0,
179 200
         )
@@ -183,6 +204,7 @@ def clerk_sale_submit_api(request):
183 204
 
184 205
         # 省份销量统计
185 206
         pssi, _ = ProvinceSaleStatisticInfo.objects.select_for_update().get_or_create(
207
+            brand_id=brand.brand_id,
186 208
             province_code=distributor.distributor_province_code,
187 209
             ymd=ymd,
188 210
         )
@@ -191,6 +213,7 @@ def clerk_sale_submit_api(request):
191 213
         pssi.save()
192 214
 
193 215
         pssi2, _ = ProvinceSaleStatisticInfo.objects.select_for_update().get_or_create(
216
+            brand_id=brand.brand_id,
194 217
             province_code=distributor.distributor_province_code,
195 218
             ymd=0,
196 219
         )

+ 49 - 15
statistic/admin.py

@@ -3,40 +3,74 @@
3 3
 from django.contrib import admin
4 4
 from django_admin import ReadOnlyModelAdmin
5 5
 
6
-from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo,
7
-                              RegisterStatisticInfo, SaleStatisticInfo)
6
+from statistic.models import (ConsumeDistributorSaleStatisticInfo, ConsumeModelSaleStatisticInfo,
7
+                              ConsumeProvinceSaleStatisticInfo, ConsumeSaleStatisticInfo, DistributorSaleStatisticInfo,
8
+                              ModelSaleStatisticInfo, ProvinceSaleStatisticInfo, RegisterStatisticInfo,
9
+                              SaleStatisticInfo)
8 10
 
9 11
 
10 12
 class RegisterStatisticInfoAdmin(admin.ModelAdmin):
11
-    list_display = ('ymd', 'num', 'status', 'created_at', 'updated_at')
12
-    search_fields = ('ymd', )
13
+    list_display = ('brand_id', 'ymd', 'num', 'status', 'created_at', 'updated_at')
14
+    list_filter = ('brand_id', 'status')
15
+    search_fields = ('brand_id', 'ymd')
13 16
 
14 17
 
15 18
 class SaleStatisticInfoAdmin(admin.ModelAdmin):
16
-    list_display = ('ymd', 'num', 'status', 'created_at', 'updated_at')
17
-    search_fields = ('ymd', )
19
+    list_display = ('brand_id', 'ymd', 'num', 'status', 'created_at', 'updated_at')
20
+    list_filter = ('brand_id', 'status')
21
+    search_fields = ('brand_id', 'ymd')
18 22
 
19 23
 
20 24
 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')
25
+    list_display = ('brand_id', 'model_id', 'model_name', 'ymd', 'num', 'status', 'created_at', 'updated_at')
26
+    list_filter = ('brand_id', 'model_name', 'status')
27
+    search_fields = ('brand_id', 'model_id', 'model_name', 'ymd')
24 28
 
25 29
 
26 30
 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')
31
+    list_display = ('brand_id', 'distributor_id', 'distributor_name', 'ymd', 'num', 'status', 'created_at', 'updated_at')
32
+    list_filter = ('brand_id', 'distributor_name', 'status')
33
+    search_fields = ('brand_id', 'distributor_id', 'distributor_name', 'ymd')
30 34
 
31 35
 
32 36
 class ProvinceSaleStatisticInfoAdmin(admin.ModelAdmin):
33
-    list_display = ('province_code', 'province_name', 'ymd', 'num', 'position', 'status', 'created_at', 'updated_at')
34
-    list_filter = ('province_code', 'province_name', 'status')
35
-    search_fields = ('province_code', 'province_name', 'ymd')
37
+    list_display = ('brand_id', 'province_code', 'province_name', 'ymd', 'num', 'position', 'status', 'created_at', 'updated_at')
38
+    list_filter = ('brand_id', 'province_code', 'province_name', 'status')
39
+    search_fields = ('brand_id', 'province_code', 'province_name', 'ymd')
40
+
41
+
42
+class ConsumeSaleStatisticInfoAdmin(admin.ModelAdmin):
43
+    list_display = ('brand_id', 'ymd', 'num', 'status', 'created_at', 'updated_at')
44
+    list_filter = ('brand_id', 'status')
45
+    search_fields = ('brand_id', 'ymd')
46
+
47
+
48
+class ConsumeModelSaleStatisticInfoAdmin(admin.ModelAdmin):
49
+    list_display = ('brand_id', 'model_id', 'model_name', 'ymd', 'num', 'status', 'created_at', 'updated_at')
50
+    list_filter = ('brand_id', 'model_name', 'status')
51
+    search_fields = ('brand_id', 'model_id', 'model_name', 'ymd')
52
+
53
+
54
+class ConsumeDistributorSaleStatisticInfoAdmin(admin.ModelAdmin):
55
+    list_display = ('brand_id', 'distributor_id', 'distributor_name', 'ymd', 'num', 'status', 'created_at', 'updated_at')
56
+    list_filter = ('brand_id', 'distributor_name', 'status')
57
+    search_fields = ('brand_id', 'distributor_id', 'distributor_name', 'ymd')
58
+
59
+
60
+class ConsumeProvinceSaleStatisticInfoAdmin(admin.ModelAdmin):
61
+    list_display = ('brand_id', 'province_code', 'province_name', 'ymd', 'num', 'position', 'status', 'created_at', 'updated_at')
62
+    list_filter = ('brand_id', 'province_code', 'province_name', 'status')
63
+    search_fields = ('brand_id', 'province_code', 'province_name', 'ymd')
36 64
 
37 65
 
38 66
 admin.site.register(RegisterStatisticInfo, RegisterStatisticInfoAdmin)
67
+
39 68
 admin.site.register(SaleStatisticInfo, SaleStatisticInfoAdmin)
40 69
 admin.site.register(ModelSaleStatisticInfo, ModelSaleStatisticInfoAdmin)
41 70
 admin.site.register(DistributorSaleStatisticInfo, DistributorSaleStatisticInfoAdmin)
42 71
 admin.site.register(ProvinceSaleStatisticInfo, ProvinceSaleStatisticInfoAdmin)
72
+
73
+admin.site.register(ConsumeSaleStatisticInfo, ConsumeSaleStatisticInfoAdmin)
74
+admin.site.register(ConsumeModelSaleStatisticInfo, ConsumeModelSaleStatisticInfoAdmin)
75
+admin.site.register(ConsumeDistributorSaleStatisticInfo, ConsumeDistributorSaleStatisticInfoAdmin)
76
+admin.site.register(ConsumeProvinceSaleStatisticInfo, ConsumeProvinceSaleStatisticInfoAdmin)

+ 111 - 0
statistic/migrations/0006_auto_20180508_1830.py

@@ -0,0 +1,111 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.11 on 2018-05-08 10:30
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', '0005_auto_20180508_1057'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.CreateModel(
16
+            name='ConsumeDistributorSaleStatisticInfo',
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
+                ('brand_id', models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id')),
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.IntegerField(db_index=True, default=0, help_text='\u5e74\u6708\u65e5', 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='ConsumeModelSaleStatisticInfo',
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
+                ('brand_id', models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id')),
41
+                ('model_id', models.CharField(db_index=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=32, verbose_name='model_id')),
42
+                ('model_name', models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=255, null=True, verbose_name='model_name')),
43
+                ('ymd', models.IntegerField(db_index=True, default=0, help_text='\u5e74\u6708\u65e5', verbose_name='ymd')),
44
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
45
+            ],
46
+            options={
47
+                'verbose_name': '\u578b\u53f7\u9500\u91cf\u7edf\u8ba1',
48
+                'verbose_name_plural': '\u578b\u53f7\u9500\u91cf\u7edf\u8ba1',
49
+            },
50
+        ),
51
+        migrations.CreateModel(
52
+            name='ConsumeProvinceSaleStatisticInfo',
53
+            fields=[
54
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
55
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
56
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
57
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
58
+                ('brand_id', models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id')),
59
+                ('province_code', models.CharField(db_index=True, help_text='\u7701\u4efd\u7f16\u7801', max_length=6, verbose_name='province_code')),
60
+                ('province_name', models.CharField(blank=True, help_text='\u7701\u4efd\u540d\u79f0', max_length=3, null=True, verbose_name='province_name')),
61
+                ('ymd', models.IntegerField(db_index=True, default=0, help_text='\u5e74\u6708\u65e5', verbose_name='ymd')),
62
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
63
+                ('position', models.IntegerField(default=1, help_text='\u6392\u5e8f', verbose_name='position')),
64
+            ],
65
+            options={
66
+                'verbose_name': '\u7701\u4efd\u9500\u91cf\u7edf\u8ba1',
67
+                'verbose_name_plural': '\u7701\u4efd\u9500\u91cf\u7edf\u8ba1',
68
+            },
69
+        ),
70
+        migrations.CreateModel(
71
+            name='ConsumeSaleStatisticInfo',
72
+            fields=[
73
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
74
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
75
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
76
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
77
+                ('brand_id', models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id')),
78
+                ('ymd', models.IntegerField(db_index=True, default=0, help_text='\u5e74\u6708\u65e5', verbose_name='ymd')),
79
+                ('num', models.IntegerField(default=0, help_text='\u6570\u91cf', verbose_name='num')),
80
+            ],
81
+            options={
82
+                'verbose_name': '\u9500\u91cf\u7edf\u8ba1',
83
+                'verbose_name_plural': '\u9500\u91cf\u7edf\u8ba1',
84
+            },
85
+        ),
86
+        migrations.AddField(
87
+            model_name='distributorsalestatisticinfo',
88
+            name='brand_id',
89
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
90
+        ),
91
+        migrations.AddField(
92
+            model_name='modelsalestatisticinfo',
93
+            name='brand_id',
94
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
95
+        ),
96
+        migrations.AddField(
97
+            model_name='provincesalestatisticinfo',
98
+            name='brand_id',
99
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
100
+        ),
101
+        migrations.AddField(
102
+            model_name='registerstatisticinfo',
103
+            name='brand_id',
104
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
105
+        ),
106
+        migrations.AddField(
107
+            model_name='salestatisticinfo',
108
+            name='brand_id',
109
+            field=models.CharField(blank=True, db_index=True, help_text='\u54c1\u724c\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='brand_id'),
110
+        ),
111
+    ]

+ 105 - 0
statistic/models.py

@@ -9,6 +9,7 @@ from utils.rdm_utils import randnum
9 9
 
10 10
 
11 11
 class RegisterStatisticInfo(BaseModelMixin):
12
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
12 13
     ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
13 14
     num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
14 15
 
@@ -27,7 +28,11 @@ class RegisterStatisticInfo(BaseModelMixin):
27 28
         }
28 29
 
29 30
 
31
+# 经销商维度
32
+
33
+
30 34
 class SaleStatisticInfo(BaseModelMixin):
35
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
31 36
     ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
32 37
     num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
33 38
 
@@ -47,6 +52,7 @@ class SaleStatisticInfo(BaseModelMixin):
47 52
 
48 53
 
49 54
 class ModelSaleStatisticInfo(BaseModelMixin):
55
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
50 56
     model_id = models.CharField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True)
51 57
     model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
52 58
     ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部
@@ -70,6 +76,7 @@ class ModelSaleStatisticInfo(BaseModelMixin):
70 76
 
71 77
 
72 78
 class DistributorSaleStatisticInfo(BaseModelMixin):
79
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
73 80
     distributor_id = models.CharField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True)
74 81
     distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
75 82
     ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部
@@ -93,6 +100,104 @@ class DistributorSaleStatisticInfo(BaseModelMixin):
93 100
 
94 101
 
95 102
 class ProvinceSaleStatisticInfo(BaseModelMixin):
103
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
104
+    province_code = models.CharField(_(u'province_code'), max_length=6, help_text=u'省份编码', db_index=True)
105
+    province_name = models.CharField(_(u'province_name'), max_length=3, blank=True, null=True, help_text=u'省份名称')
106
+    ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部
107
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
108
+
109
+    position = models.IntegerField(_(u'position'), default=1, help_text=u'排序')
110
+
111
+    class Meta:
112
+        verbose_name = _(u'省份销量统计')
113
+        verbose_name_plural = _(u'省份销量统计')
114
+
115
+    def __unicode__(self):
116
+        return unicode(self.pk)
117
+
118
+    @property
119
+    def data(self):
120
+        return {
121
+            'province_code': self.province_code,
122
+            'province_name': self.province_name,
123
+            'ymd': self.ymd,
124
+            'num': randnum() if settings.DEBUG_DATA_FLAG else self.num,
125
+        }
126
+
127
+
128
+# 消费者维度
129
+
130
+
131
+class ConsumeSaleStatisticInfo(BaseModelMixin):
132
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
133
+    ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d')
134
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
135
+
136
+    class Meta:
137
+        verbose_name = _(u'销量统计')
138
+        verbose_name_plural = _(u'销量统计')
139
+
140
+    def __unicode__(self):
141
+        return unicode(self.pk)
142
+
143
+    @property
144
+    def data(self):
145
+        return {
146
+            'ymd': self.ymd,
147
+            'num': randnum() if settings.DEBUG_DATA_FLAG else self.num,
148
+        }
149
+
150
+
151
+class ConsumeModelSaleStatisticInfo(BaseModelMixin):
152
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
153
+    model_id = models.CharField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True)
154
+    model_name = models.CharField(_(u'model_name'), max_length=255, blank=True, null=True, help_text=u'型号名称')
155
+    ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部
156
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
157
+
158
+    class Meta:
159
+        verbose_name = _(u'型号销量统计')
160
+        verbose_name_plural = _(u'型号销量统计')
161
+
162
+    def __unicode__(self):
163
+        return unicode(self.pk)
164
+
165
+    @property
166
+    def data(self):
167
+        return {
168
+            'model_id': self.model_id,
169
+            'model_name': self.model_name,
170
+            'ymd': self.ymd,
171
+            'num': randnum() if settings.DEBUG_DATA_FLAG else self.num,
172
+        }
173
+
174
+
175
+class ConsumeDistributorSaleStatisticInfo(BaseModelMixin):
176
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
177
+    distributor_id = models.CharField(_(u'distributor_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True)
178
+    distributor_name = models.CharField(_(u'distributor_name'), max_length=255, blank=True, null=True, help_text=u'经销商名称')
179
+    ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部
180
+    num = models.IntegerField(_(u'num'), default=0, help_text=u'数量')
181
+
182
+    class Meta:
183
+        verbose_name = _(u'经销商销量统计')
184
+        verbose_name_plural = _(u'经销商销量统计')
185
+
186
+    def __unicode__(self):
187
+        return unicode(self.pk)
188
+
189
+    @property
190
+    def data(self):
191
+        return {
192
+            'distributor_id': self.distributor_id,
193
+            'distributor_name': self.distributor_name,
194
+            'ymd': self.ymd,
195
+            'num': randnum() if settings.DEBUG_DATA_FLAG else self.num,
196
+        }
197
+
198
+
199
+class ConsumeProvinceSaleStatisticInfo(BaseModelMixin):
200
+    brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
96 201
     province_code = models.CharField(_(u'province_code'), max_length=6, help_text=u'省份编码', db_index=True)
97 202
     province_name = models.CharField(_(u'province_name'), max_length=3, blank=True, null=True, help_text=u'省份名称')
98 203
     ymd = models.IntegerField(_(u'ymd'), default=0, help_text=u'年月日', db_index=True)  # 例:20171208, tc.local_string(format='%Y%m%d'), 0 为全部

+ 50 - 1
statistic/views.py

@@ -12,7 +12,56 @@ from utils.rdm_utils import randnum
12 12
 
13 13
 
14 14
 @logit
15
-def tj_data(request):
15
+def tj_distributor(request):
16
+    ymd = int(tc.local_string(format='%Y%m%d'))
17
+
18
+    # 注册用户统计 & 今日注册用户
19
+    try:
20
+        register_num = RegisterStatisticInfo.objects.get(ymd=ymd).num
21
+    except RegisterStatisticInfo.DoesNotExist:
22
+        register_num = 0
23
+
24
+    # # 注册用户数趋势
25
+    # register_trends = RegisterStatisticInfo.objects.filter(status=True).order_by('-ymd')
26
+    # register_trends = [r.data for r in register_trends]
27
+
28
+    # 销量统计 & 今日销量
29
+    try:
30
+        sale_num = SaleStatisticInfo.objects.get(ymd=ymd).num
31
+    except SaleStatisticInfo.DoesNotExist:
32
+        sale_num = 0
33
+
34
+    # # 商品销量趋势
35
+    # sale_trends = SaleStatisticInfo.objects.filter(status=True).order_by('-ymd')
36
+    # sale_trends = [s.data for s in sale_trends]
37
+
38
+    # 型号销量统计 & 热销商品榜
39
+    model_sales = ModelSaleStatisticInfo.objects.filter(ymd=0, status=True).order_by('-num')
40
+    model_sales = [m.data for m in model_sales]
41
+
42
+    # 经销商销量统计 & 经销商榜
43
+    distributor_sales = DistributorSaleStatisticInfo.objects.filter(ymd=0, status=True).order_by('-num')
44
+    distributor_sales = [d.data for d in distributor_sales]
45
+
46
+    # 各地区实时销量
47
+    province_sales = ProvinceSaleStatisticInfo.objects.filter(ymd=0, status=True).order_by('position')
48
+    province_sales = [p.data for p in province_sales]
49
+
50
+    # TOADD: ROI
51
+
52
+    return response(200, 'Get TJ Data Success', u'获取统计数据成功', {
53
+        'register_num': randnum() if settings.DEBUG_DATA_FLAG else register_num,  # 注册用户统计 & 今日注册用户
54
+        # 'register_trends': register_trends,  # 注册用户数趋势
55
+        'sale_num': randnum() if settings.DEBUG_DATA_FLAG else sale_num,  # 销量统计 & 今日销量
56
+        # 'sale_trends': sale_trends,  # 商品销量趋势
57
+        'model_sales': model_sales,  # 型号销量统计 & 热销商品榜
58
+        'distributor_sales': distributor_sales,  # 经销商销量统计 & 经销商榜
59
+        'province_sales': province_sales,  # 各地区实时销量
60
+    })
61
+
62
+
63
+@logit
64
+def tj_consumer(request):
16 65
     ymd = int(tc.local_string(format='%Y%m%d'))
17 66
 
18 67
     # 注册用户统计 & 今日注册用户

+ 8 - 3
utils/error/errno_utils.py

@@ -20,14 +20,19 @@ class SaleclerkStatusCode(BaseStatusCode):
20 20
     DUPLICATE_SUBMIT = StatusCodeField(500199, 'Duplicate Submit', description=u'重复提交')
21 21
 
22 22
 
23
+class ProductBrandStatusCode(BaseStatusCode):
24
+    """ 品牌相关错误码 5010xx """
25
+    BRAND_NOT_FOUND = StatusCodeField(501001, 'Brand Not Found', description=u'品牌不存在')
26
+
27
+
23 28
 class ProductModelStatusCode(BaseStatusCode):
24
-    """ 型号相关错误码 5010xx """
25
-    MODEL_NOT_FOUND = StatusCodeField(501001, 'Model Not Found', description=u'型号不存在')
29
+    """ 型号相关错误码 5011xx """
30
+    MODEL_NOT_FOUND = StatusCodeField(501101, 'Model Not Found', description=u'型号不存在')
26 31
 
27 32
 
28 33
 class ProductDistributorStatusCode(BaseStatusCode):
29 34
     """ 经销商相关错误码 5011xx """
30
-    DISTRIBUTOR_NOT_FOUND = StatusCodeField(501101, 'Distributor Not Found', description=u'经销商不存在')
35
+    DISTRIBUTOR_NOT_FOUND = StatusCodeField(501201, 'Distributor Not Found', description=u'经销商不存在')
31 36
 
32 37
 
33 38
 class ProductStatusCode(BaseStatusCode):