Merge tamron branch

Kimi.Huang 5 年之前
父节点
当前提交
3b6b3ca2b3
共有 13 个文件被更改,包括 262 次插入43 次删除
  1. 98 0
      api/admin_views.py
  2. 3 2
      api/encrypt_views.py
  3. 8 2
      api/mch_views.py
  4. 7 1
      api/urls.py
  5. 6 5
      mch/admin.py
  6. 50 0
      mch/migrations/0036_auto_20190719_1508.py
  7. 53 13
      mch/models.py
  8. 7 2
      page/sale_views.py
  9. 7 9
      requirements.txt
  10. 6 6
      requirements_dj.txt
  11. 1 1
      requirements_pywe.txt
  12. 1 1
      statistic/views.py
  13. 15 1
      utils/error/errno_utils.py

+ 98 - 0
api/admin_views.py

@@ -0,0 +1,98 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from __future__ import division
4
+
5
+from django.conf import settings
6
+from django.db import transaction
7
+from django_logit import logit
8
+from django_response import response
9
+from TimeConvert import TimeConvert as tc
10
+
11
+from mch.models import ConsumeInfoSubmitLogInfo, AdministratorInfo
12
+from utils.error.errno_utils import AdministratorStatusCode, ProductBrandStatusCode, ProductCouponStatusCode, ProductMachineStatusCode
13
+
14
+
15
+WECHAT = settings.WECHAT
16
+
17
+
18
+@logit
19
+def querysn(request):
20
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
21
+    admin_id = request.POST.get('admin_id', '')
22
+    model_id = request.POST.get('model_id', '')
23
+    sn = request.POST.get('sn', '')
24
+
25
+    if brand_id != settings.KODO_DEFAULT_BRAND_ID:
26
+        return response(ProductBrandStatusCode.BRAND_NOT_MATCH)
27
+
28
+    if not AdministratorInfo.objects.filter(admin_id=admin_id, admin_type=AdministratorInfo.MAINTENANCE, user_status=AdministratorInfo.ACTIVATED, status=True).exists():
29
+        return response(AdministratorStatusCode.MAINTENANCE_NOT_FOUND)
30
+
31
+    log = ConsumeInfoSubmitLogInfo.objects.filter(brand_id=brand_id, model_id=model_id, serialNo=sn, submit_during_activity=True).order_by('has_used', '-pk').first()
32
+
33
+    if not log:
34
+        log = ConsumeInfoSubmitLogInfo.objects.filter(brand_id=brand_id, model_id=model_id, serialNo=sn).order_by('-submit_during_activity', 'dupload').first()
35
+
36
+    if not log:
37
+        return response(ProductMachineStatusCode.SN_NOT_FOUND)
38
+
39
+    return response(200, 'Query SN Success', u'查询序列号成功', data=log.data)
40
+
41
+
42
+@logit
43
+def queryusedsn(request):
44
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
45
+    admin_id = request.POST.get('admin_id', '')
46
+
47
+    if brand_id != settings.KODO_DEFAULT_BRAND_ID:
48
+        return response(ProductBrandStatusCode.BRAND_NOT_MATCH)
49
+
50
+    if not AdministratorInfo.objects.filter(admin_id=admin_id, admin_type=AdministratorInfo.MAINTENANCE, user_status=AdministratorInfo.ACTIVATED, status=True).exists():
51
+        return response(AdministratorStatusCode.MAINTENANCE_NOT_FOUND)
52
+
53
+    logs = ConsumeInfoSubmitLogInfo.objects.filter(brand_id=brand_id, admin_id=admin_id, has_used=True).order_by('-used_at')
54
+    logs = [log.data for log in logs]
55
+
56
+    return response(200, 'Query Used SN Success', u'查询核销序列号成功', data={
57
+        'logs': logs,
58
+    })
59
+
60
+
61
+@logit
62
+@transaction.atomic
63
+def usecoupon(request):
64
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
65
+    admin_id = request.POST.get('admin_id', '')
66
+    model_id = request.POST.get('model_id', '')
67
+    sn = request.POST.get('sn', '')
68
+
69
+    if brand_id != settings.KODO_DEFAULT_BRAND_ID:
70
+        return response(ProductBrandStatusCode.BRAND_NOT_MATCH)
71
+
72
+    if not AdministratorInfo.objects.filter(
73
+        admin_id=admin_id,
74
+        admin_type=AdministratorInfo.MAINTENANCE,
75
+        user_status=AdministratorInfo.ACTIVATED,
76
+        status=True
77
+    ).exists():
78
+        return response(AdministratorStatusCode.MAINTENANCE_NOT_FOUND)
79
+
80
+    log = ConsumeInfoSubmitLogInfo.objects.filter(
81
+        brand_id=brand_id,
82
+        model_id=model_id,
83
+        serialNo=sn,
84
+        submit_during_activity=True,
85
+        has_used=False
86
+    ).first()
87
+    if not log:
88
+        return response(ProductMachineStatusCode.SN_NOT_FOUND)
89
+
90
+    logdata = log.data
91
+    if logdata.get('final_coupon_info', {}).get('coupon_has_expired', True):
92
+        return response(ProductCouponStatusCode.COUPON_HAS_EXPIRED)
93
+
94
+    log.has_used = True
95
+    log.used_at = tc.utc_datetime()
96
+    log.save()
97
+
98
+    return response(200, 'Use Coupon Success', u'核销优惠券成功')

+ 3 - 2
api/encrypt_views.py

@@ -108,10 +108,11 @@ def decrypt(request):
108 108
         mdli.decrypt_count += 1
109 109
         mdli.save()
110 110
 
111
-    act = ActivityInfo.objects.filter(brand_id=brand.brand_id, status=True).order_by('-pk').first()
111
+    act = ActivityInfo.objects.filter(status=True).order_by('-pk').first()
112 112
     has_unexpired_activity = True if act and act.has_unexpired_activity(model.model_uni_name) else False
113
+
113 114
     coupon_info = {
114
-        'coupon_expire_at': act.final_coupon_expire_at,
115
+        'coupon_expire_at': act.final_coupon_expire_at(created_at=None),
115 116
         'coupon_value': act.coupon_value,
116 117
     } if has_unexpired_activity else {
117 118
         'coupon_expire_at': '',

+ 8 - 2
api/mch_views.py

@@ -69,6 +69,8 @@ def admin_login_api(request):
69 69
     request.session['admin_id'] = administrator.admin_id
70 70
 
71 71
     return response(200, 'Admin Login Success', u'管理员登录成功', data={
72
+        'admin_id': administrator.admin_id,
73
+        'admin_type': administrator.admin_type,
72 74
         'qrurl': settings.KODO_CLERK_AUTH_URL.format(administrator.brand_id),
73 75
     })
74 76
 
@@ -268,8 +270,12 @@ def consumer_info_api(request):
268 270
         test_user=False,
269 271
     ).exists()
270 272
 
271
-    act = ActivityInfo.objects.filter(status=True).order_by('-pk').first()
272
-    during_activity = True if act and act.has_unexpired_activity(model.model_uni_name) else False
273
+    if dupload:
274
+        act = None
275
+        during_activity = False
276
+    else:
277
+        act = ActivityInfo.objects.filter(status=True).order_by('-pk').first()
278
+        during_activity = True if act and act.has_unexpired_activity(model.model_uni_name) else False
273 279
 
274 280
     # 记录用户信息提交记录
275 281
     log = ConsumeInfoSubmitLogInfo.objects.create(

+ 7 - 1
api/urls.py

@@ -5,7 +5,7 @@ from django_file_upload import views as file_views
5 5
 
6 6
 from account import tourguide_views
7 7
 from account import views as account_views
8
-from api import clerk_views, distributor_views, encrypt_views, mch_views, model_views, operator_views
8
+from api import admin_views, clerk_views, distributor_views, encrypt_views, mch_views, model_views, operator_views
9 9
 from box import views as box_views
10 10
 from geo import views as geo_views
11 11
 from group import (groupuser_views, lensman_views, tourguidegroup_views, tourguidegroupadmin_views,
@@ -280,3 +280,9 @@ urlpatterns += [
280 280
     url(r'^screen/admin/loginqr$', screen_views.screen_admin_loginqr, name='screen_admin_loginqr'),
281 281
     url(r'^screen/admin/loginrst$', screen_views.screen_admin_loginrst, name='screen_admin_loginrst'),
282 282
 ]
283
+
284
+urlpatterns += [
285
+    url(r'^admin/querysn$', admin_views.querysn, name='querysn'),
286
+    url(r'^admin/queryusedsn$', admin_views.queryusedsn, name='queryusedsn'),
287
+    url(r'^admin/usecoupon$', admin_views.usecoupon, name='usecoupon'),
288
+]

+ 6 - 5
mch/admin.py

@@ -13,8 +13,8 @@ from mch.models import (ActivityInfo, AdministratorInfo, BrandInfo, ConsumeInfoS
13 13
 
14 14
 
15 15
 class AdministratorInfoAdmin(admin.ModelAdmin):
16
-    list_display = ('admin_id', 'phone', 'name', 'brand_id', 'brand_name', 'user_status', 'status', 'created_at', 'updated_at')
17
-    list_filter = ('brand_name', 'user_status', 'status')
16
+    list_display = ('admin_id', 'admin_type', 'phone', 'password', 'encryption', 'name', 'brand_id', 'brand_name', 'user_status', 'status', 'created_at', 'updated_at')
17
+    list_filter = ('admin_type', 'user_status', 'status', 'brand_name')
18 18
     readonly_fields = ('encryption', 'brand_name')
19 19
 
20 20
     def save_model(self, request, obj, form, change):
@@ -180,13 +180,14 @@ class LatestAppScreenInfoAdmin(admin.ModelAdmin):
180 180
 
181 181
 
182 182
 class ConsumeInfoSubmitLogInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
183
-    list_display = ('user_id', 'phone', 'lat', 'lon', 'serialNo', 'verifyResult', 'dupload', 'test_user', 'status', 'created_at', 'updated_at')
184
-    list_filter = ('brand_id', 'dupload', 'test_user', 'verifyResult', 'status')
183
+    list_display = ('user_id', 'phone', 'lat', 'lon', 'serialNo', 'verifyResult', 'dupload', 'test_user', 'submit_during_activity', 'activity_id', 'coupon_expire_at', 'coupon_value', 'has_used', 'status', 'created_at', 'updated_at')
184
+    list_filter = ('brand_id', 'submit_during_activity', 'activity_id', 'dupload', 'test_user', 'verifyResult', 'has_used', 'status')
185 185
     search_fields = ('user_id', 'phone', 'serialNo')
186 186
 
187 187
 
188 188
 class ActivityInfoAdmin(admin.ModelAdmin):
189
-    list_display = ('activity_name', 'model_uni_names', 'start_at', 'end_at', 'coupon_expire_at', 'coupon_value', 'status', 'created_at', 'updated_at')
189
+    list_display = ('activity_name', 'model_uni_names', 'start_at', 'end_at', 'coupon_expire_type', 'coupon_valid_period', 'coupon_expire_at', 'coupon_value', 'status', 'created_at', 'updated_at')
190
+    list_filter = ('coupon_expire_type', 'status')
190 191
 
191 192
 
192 193
 admin.site.register(AdministratorInfo, AdministratorInfoAdmin)

+ 50 - 0
mch/migrations/0036_auto_20190719_1508.py

@@ -0,0 +1,50 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.20 on 2019-07-19 07:08
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', '0035_auto_20190521_1543'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AddField(
16
+            model_name='activityinfo',
17
+            name='coupon_expire_type',
18
+            field=models.IntegerField(choices=[(0, '\u56fa\u5b9a\u7ed3\u675f\u65f6\u95f4'), (1, '\u53ef\u53d8\u7ed3\u675f\u65f6\u95f4')], default=0, help_text='\u7ef4\u4fee\u5238\u7c7b\u578b', verbose_name='coupon_expire_type'),
19
+        ),
20
+        migrations.AddField(
21
+            model_name='activityinfo',
22
+            name='coupon_valid_period',
23
+            field=models.IntegerField(default=0, help_text='\u7ef4\u4fee\u5238\u6709\u6548\u65f6\u95f4\uff08\u5355\u4f4d\uff1a\u5929\uff09', verbose_name='coupon_valid_period'),
24
+        ),
25
+        migrations.AddField(
26
+            model_name='administratorinfo',
27
+            name='admin_type',
28
+            field=models.IntegerField(choices=[(0, '\u7ba1\u7406\u5458'), (1, '\u7ef4\u4fee\u5458')], db_index=True, default=0, help_text='\u7ba1\u7406\u5458\u7c7b\u578b', verbose_name='admin_type'),
29
+        ),
30
+        migrations.AddField(
31
+            model_name='consumeinfosubmitloginfo',
32
+            name='activity_id',
33
+            field=models.IntegerField(default=0, help_text='\u6d3b\u52a8\u552f\u4e00\u6807\u8bc6', verbose_name='activity_id'),
34
+        ),
35
+        migrations.AddField(
36
+            model_name='consumeinfosubmitloginfo',
37
+            name='admin_id',
38
+            field=models.CharField(blank=True, db_index=True, help_text='\u6838\u9500\u5458\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='admin_id'),
39
+        ),
40
+        migrations.AddField(
41
+            model_name='consumeinfosubmitloginfo',
42
+            name='has_used',
43
+            field=models.BooleanField(db_index=True, default=False, help_text='\u662f\u5426\u5df2\u6838\u9500', verbose_name='has_used'),
44
+        ),
45
+        migrations.AddField(
46
+            model_name='consumeinfosubmitloginfo',
47
+            name='used_at',
48
+            field=models.DateTimeField(blank=True, help_text='\u7ef4\u4fee\u5238\u6838\u9500\u65f6\u95f4', null=True, verbose_name='used_at'),
49
+        ),
50
+    ]

+ 53 - 13
mch/models.py

@@ -11,6 +11,14 @@ from TimeConvert import TimeConvert as tc
11 11
 
12 12
 
13 13
 class AdministratorInfo(BaseModelMixin):
14
+    ADMINISTRATOR = 0
15
+    MAINTENANCE = 1
16
+
17
+    USER_TYPE_TUPLE = (
18
+        (ADMINISTRATOR, u'管理员'),
19
+        (MAINTENANCE, u'维修员'),
20
+    )
21
+
14 22
     ACTIVATED = 1
15 23
     DISABLED = 2
16 24
     DELETED = 3
@@ -23,6 +31,8 @@ class AdministratorInfo(BaseModelMixin):
23 31
 
24 32
     admin_id = ShortUUIDField(_(u'admin_id'), max_length=32, blank=True, null=True, help_text=u'管理员唯一标识', db_index=True, unique=True)
25 33
 
34
+    admin_type = models.IntegerField(_(u'admin_type'), choices=USER_TYPE_TUPLE, default=ADMINISTRATOR, help_text=u'管理员类型', db_index=True)
35
+
26 36
     phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'管理员电话', db_index=True)
27 37
     password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'管理员密码')
28 38
     encryption = models.CharField(_(u'encryption'), max_length=255, blank=True, null=True, help_text=u'管理员密码')
@@ -503,6 +513,10 @@ class ConsumeInfoSubmitLogInfo(BaseModelMixin):
503 513
     coupon_expire_at = models.DateTimeField(_(u'coupon_expire_at'), blank=True, null=True, help_text=_(u'维修券过期时间'))
504 514
     coupon_value = models.IntegerField(_(u'coupon_value'), default=0, help_text=_(u'维修券金额(单位:分)'))
505 515
 
516
+    has_used = models.BooleanField(_(u'has_used'), default=False, help_text=_(u'是否已核销'), db_index=True)
517
+    admin_id = models.CharField(_(u'admin_id'), max_length=32, blank=True, null=True, help_text=u'核销员唯一标识', db_index=True)
518
+    used_at = models.DateTimeField(_(u'used_at'), blank=True, null=True, help_text=_(u'维修券核销时间'))
519
+
506 520
     test_user = models.BooleanField(_(u'test_user'), default=False, help_text=_(u'是否为测试用户'), db_index=True)
507 521
 
508 522
     class Meta:
@@ -532,11 +546,16 @@ class ConsumeInfoSubmitLogInfo(BaseModelMixin):
532 546
     @property
533 547
     def coupon_info(self):
534 548
         return {
535
-            'coupon_expire_at': self.final_coupon_expire_at,
536
-            'coupon_value': self.coupon_value,
549
+            'coupon_expire_at': '',
550
+            'coupon_value': 0,
551
+            'coupon_has_expired': True,
537 552
         }
538 553
 
539 554
     @property
555
+    def coupon_info2(self):
556
+        return self.coupon_info,
557
+
558
+    @property
540 559
     def data(self):
541 560
         if self.submit_during_activity:
542 561
             try:
@@ -556,11 +575,22 @@ class ConsumeInfoSubmitLogInfo(BaseModelMixin):
556 575
             'serialNo': self.serialNo,
557 576
             'verifyResult': self.verifyResult,
558 577
             'submit_during_activity': self.submit_during_activity,
559
-            'coupon_info': act.coupon_info if act else self.coupon_info,
578
+            'coupon_info': act.coupon_info2(created_at=self.created_at) if act else self.coupon_info2,
579
+            'final_coupon_info': act.coupon_info(created_at=self.created_at) if act else self.coupon_info,
580
+            'has_used': self.has_used,
581
+            'used_at': self.used_at,
560 582
         }
561 583
 
562 584
 
563 585
 class ActivityInfo(BaseModelMixin):
586
+    FIXED_EXPIRED_TIME = 0
587
+    CHANGED_EXPIRED_TIME = 1
588
+
589
+    COUPON_EXPIRED_TIME_TUPLE = (
590
+        (FIXED_EXPIRED_TIME, u'固定结束时间'),
591
+        (CHANGED_EXPIRED_TIME, u'可变结束时间'),
592
+    )
593
+
564 594
     brand_id = models.CharField(_(u'brand_id'), max_length=32, blank=True, null=True, help_text=u'品牌唯一标识', db_index=True)
565 595
 
566 596
     activity_name = models.CharField(_(u'activity_name'), max_length=255, blank=True, null=True, help_text=u'活动名称')
@@ -570,6 +600,8 @@ class ActivityInfo(BaseModelMixin):
570 600
     start_at = models.DateTimeField(_(u'start_at'), help_text=_(u'start_at'))
571 601
     end_at = models.DateTimeField(_(u'end_at'), help_text=_(u'end_at'))
572 602
 
603
+    coupon_expire_type = models.IntegerField(_(u'coupon_expire_type'), choices=COUPON_EXPIRED_TIME_TUPLE, default=FIXED_EXPIRED_TIME, help_text=_(u'维修券类型'))
604
+    coupon_valid_period = models.IntegerField(_(u'coupon_valid_period'), default=0, help_text=_(u'维修券有效时间(单位:天)'))
573 605
     coupon_expire_at = models.DateTimeField(_(u'coupon_expire_at'), blank=True, null=True, help_text=_(u'维修券过期时间'))
574 606
     coupon_value = models.IntegerField(_(u'coupon_value'), default=0, help_text=_(u'维修券金额(单位:分)'))
575 607
 
@@ -580,21 +612,29 @@ class ActivityInfo(BaseModelMixin):
580 612
     def __unicode__(self):
581 613
         return unicode(self.pk)
582 614
 
583
-    @property
584
-    def final_coupon_expire_at(self):
585
-        if not self.coupon_expire_at:
615
+    def final_expire_at(self, created_at=None):
616
+        if self.coupon_expire_type == ActivityInfo.FIXED_EXPIRED_TIME:
617
+            return self.coupon_expire_at
618
+        return tc.utc_datetime(dt=created_at, days=self.coupon_valid_period)
619
+
620
+    def final_coupon_expire_at(self, created_at=None):
621
+        final_expire_at = self.final_expire_at(created_at=created_at)
622
+        if not final_expire_at:
586 623
             return ''
587
-        y = tc.local_string(self.coupon_expire_at, format='%Y')
588
-        m = tc.local_string(self.coupon_expire_at, format='%m')
589
-        d = tc.local_string(self.coupon_expire_at, format='%d')
624
+        y = tc.local_string(final_expire_at, format='%Y')
625
+        m = tc.local_string(final_expire_at, format='%m')
626
+        d = tc.local_string(final_expire_at, format='%d')
590 627
         return u'{}年{}月{}日'.format(y, m, d)
591 628
 
592 629
     def has_unexpired_activity(self, model_name):
593 630
         return (self.model_uni_names and model_name in self.model_uni_names) and (self.start_at <= tc.utc_datetime() < self.end_at)
594 631
 
595
-    @property
596
-    def coupon_info(self):
632
+    def coupon_info(self, created_at=None):
597 633
         return {
598
-            'coupon_expire_at': self.final_coupon_expire_at,
634
+            'coupon_expire_at': self.final_coupon_expire_at(created_at=created_at),
599 635
             'coupon_value': self.coupon_value,
600
-        },
636
+            'coupon_has_expired': tc.utc_datetime() >= self.final_expire_at(created_at=created_at),
637
+        }
638
+
639
+    def coupon_info2(self, created_at=None):
640
+        return self.coupon_info(created_at=created_at),

+ 7 - 2
page/sale_views.py

@@ -108,7 +108,12 @@ def clerk_sale_submit_api(request):
108 108
 
109 109
     if settings.CHECK_DUPLOAD_ENABLED:
110 110
         try:
111
-            sci = SaleclerkIntegralIncomeExpensesInfo.objects.get(code=serialNo, status=True)
111
+            sci = SaleclerkIntegralIncomeExpensesInfo.objects.get(
112
+                brand_id=brand.brand_id,
113
+                model_id=model.model_id,
114
+                code=serialNo,
115
+                status=True
116
+            )
112 117
         except SaleclerkIntegralIncomeExpensesInfo.DoesNotExist:
113 118
             sci = None
114 119
     else:
@@ -159,7 +164,7 @@ def clerk_sale_submit_api(request):
159 164
         )
160 165
 
161 166
     # TODO: Make statistic async
162
-    if (not settings.CHECK_DUPLOAD_ENABLED) or (not sci):
167
+    if (not settings.CHECK_DUPLOAD_ENABLED) or (not clerk.test_user and not sci):
163 168
         ymd = tc.local_string(format='%Y%m%d')
164 169
 
165 170
         # 日销量统计

+ 7 - 9
requirements.txt

@@ -1,19 +1,17 @@
1 1
 CodeConvert==2.0.5
2 2
 MySQL-python==1.2.5
3
-Pillow==5.0.0
3
+Pillow==6.1.0
4 4
 StatusCode==1.0.0
5
-TimeConvert==1.4.3
6
-cryptography==1.5.2
5
+TimeConvert==1.4.4
7 6
 furl==2.0.0
8 7
 isoweek==1.3.3
9 8
 jsonfield==2.0.2
10
-mock==2.0.0
11
-monetary==1.0.2
12
-pysnippets==1.0.8
13
-qiniu==7.2.2
14
-requests==2.21.0
9
+monetary==1.0.3
10
+pysnippets==1.0.9
11
+qiniu==7.2.6
12
+requests==2.22.0
15 13
 rlog==0.3
16
-rsa==3.4.2
14
+rsa==4.0
17 15
 shortuuid==0.5.0
18 16
 versions==0.10.0
19 17
 -r requirements_dj.txt

+ 6 - 6
requirements_dj.txt

@@ -1,19 +1,19 @@
1
-Django==1.11.20
1
+Django==1.11.22
2 2
 django-admin==1.3.2
3
-django-cors-headers==2.4.0
3
+django-cors-headers==3.0.2
4 4
 django-curtail-uuid==1.0.4
5
-django-detect==1.0.8
5
+django-detect==1.0.12
6 6
 django-file-md5==1.0.2
7 7
 django-file-upload==1.1.0
8 8
 django-ip==1.0.2
9
-django-json-render==1.0.2
9
+django-json-render==1.0.3
10 10
 django-json-response==1.1.5
11 11
 django-logit==1.1.3
12 12
 django-mobi==0.1.7
13 13
 django-models-ext==1.1.8
14 14
 django-multidomain==1.1.4
15 15
 django-paginator2==1.0.4
16
-django-query==1.0.3
16
+django-query==1.0.5
17 17
 django-redis-connector==1.0.1
18 18
 django-response==1.1.1
19 19
 django-rlog==1.0.7
@@ -21,4 +21,4 @@ django-shortuuidfield==0.1.3
21 21
 django-six==1.0.4
22 22
 django-uniapi==1.0.5
23 23
 django-we==1.4.2
24
-djangorestframework==3.7.7
24
+djangorestframework==3.9.4

+ 1 - 1
requirements_pywe.txt

@@ -5,7 +5,7 @@ pywe-jssdk==1.1.0
5 5
 pywe-membercard==1.0.1
6 6
 pywe-miniapp==1.1.5
7 7
 pywe-oauth==1.0.7
8
-pywe-pay==1.0.12
8
+pywe-pay==1.0.13
9 9
 pywe-pay-notify==1.0.4
10 10
 pywe-response==1.0.1
11 11
 pywe-sign==1.0.8

+ 1 - 1
statistic/views.py

@@ -251,7 +251,7 @@ def ytj(brand_id):
251 251
         '-num'
252 252
     )[:20]
253 253
     clerks = SaleclerkInfo.objects.filter(brand_id=brand_id, status=True)
254
-    clerks = {clerk.clerk_id: {'distributor_id': clerk.distributor_id, 'distributor_name': clerk.distributor_name, 'clerk_name': clerk.clerk_name} for clerk in clerks}
254
+    clerks = {clerk.clerk_id: {'distributor_id': clerk.distributor_id, 'distributor_name': clerk.distributor_name, 'clerk_name': clerk.clerk_name, 'salesman_id': clerk.clerk_id, 'salesman_name': clerk.clerk_name} for clerk in clerks}
255 255
     salesmen = [dict(sm, **clerks.get(sm.get('clerk_id', ''), {})) for sm in salesmen]
256 256
 
257 257
     # [收费者维度] 统计周期内省份销量排行数据,请按顺序返回

+ 15 - 1
utils/error/errno_utils.py

@@ -28,10 +28,22 @@ class ProductModelStatusCode(BaseStatusCode):
28 28
 
29 29
 
30 30
 class ProductDistributorStatusCode(BaseStatusCode):
31
-    """ 经销商相关错误码 5011xx """
31
+    """ 经销商相关错误码 5012xx """
32 32
     DISTRIBUTOR_NOT_FOUND = StatusCodeField(501201, 'Distributor Not Found', description=u'经销商不存在')
33 33
 
34 34
 
35
+class ProductMachineStatusCode(BaseStatusCode):
36
+    """ 机器相关错误码 5013xx """
37
+    SN_NOT_FOUND = StatusCodeField(501301, 'SN Not Found', description=u'序列号不存在')
38
+
39
+
40
+class ProductCouponStatusCode(BaseStatusCode):
41
+    """ 优惠券相关错误码 5014xx """
42
+    COUPON_NOT_FOUND = StatusCodeField(501401, 'Coupon Not Found', description=u'优惠券不存在')
43
+
44
+    COUPON_HAS_EXPIRED = StatusCodeField(501411, 'Coupon Has Expired', description=u'优惠券已过期')
45
+
46
+
35 47
 class ProductStatusCode(BaseStatusCode):
36 48
     """ 产品相关错误码 5020xx """
37 49
     PRODUCT_NOT_FOUND = StatusCodeField(502001, 'Product Not Found', description=u'产品不存在')
@@ -77,6 +89,8 @@ class AdministratorStatusCode(BaseStatusCode):
77 89
     ADMINISTRATOR_NOT_ACTIVATED = StatusCodeField(400215, 'Administrator Not Activated', description=u'管理员未激活')
78 90
     ADMINISTRATOR_HAS_DISABLED = StatusCodeField(400216, 'Administrator Has Disabled', description=u'管理员已禁用')
79 91
     ADMINISTRATOR_HAS_DELETED = StatusCodeField(400217, 'Administrator Has Deleted', description=u'管理员已删除')
92
+    # 管理员
93
+    MAINTENANCE_NOT_FOUND = StatusCodeField(400251, 'Maintenance Not Found', description=u'核销员不存在')
80 94
 
81 95
 
82 96
 class OperatorStatusCode(BaseStatusCode):