td> 467
+    franchiser_name = models.CharField(_(u'franchiser_name'), max_length=32, blank=True, null=True, help_text=u'经销商名称')
468
+    clerk_id = ShortUUIDField(_(u'clerk_id'), max_length=32, help_text=u'店员唯一标识', db_index=True, unique=True)
469
+    clerk_name = models.CharField(_(u'clerk_name'), max_length=32, blank=True, null=True, help_text=u'店员名称')
470
+    clerk_sex = models.IntegerField(_(u'clerk_sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.MALE, help_text=u'店员性别', db_index=True)
471
+    clerk_phone = models.CharField(_(u'clerk_phone'), max_length=11, blank=True, null=True, help_text=u'店员联系电话')
472
+
473
+    openid = models.CharField(_(u'openid'), max_length=32, blank=True, null=True, help_text=u'微信 OpenID', db_index=True, unique=True)
474
+    unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 UnionID', db_index=True, unique=True)
475
+
476
+    integral = models.IntegerField(_(u'integral'), default=0, help_text=u'积分')
477
+
478
+    user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'用户状态', db_index=True)
479
+    refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因')
480
+
481
+    class Meta:
482
+        verbose_name = _(u'saleclerkinfo')
483
+        verbose_name_plural = _(u'saleclerkinfo')
484
+
485
+    def __unicode__(self):
486
+        return unicode(self.pk)
487
+
488
+    @property
489
+    def data(self):
490
+        return {
491
+            'franchiser_id': self.franchiser_id,
492
+            'franchiser_name': self.franchiser_name,
493
+            'clerk_id': self.clerk_id,
494
+            'clerk_name': self.clerk_name,
495
+            'clerk_sex': self.clerk_sex,
496
+            'clerk_phone': self.clerk_phone,
497
+            'integral': self.integral,
498
+            'status': self.user_status,
499
+            'refused_reason': self.refused_reason,
500
+        }

+ 6 - 0
api/urls.py

@@ -13,6 +13,7 @@ from group import (groupuser_views, lensman_views, tourguidegroup_views, tourgui
13 13
 from message import views as message_views
14 14
 from miniapp import views as mini_views
15 15
 from operation import views as op_views
16
+from page import oauth_views, sale_views
16 17
 from pay import views as pay_views
17 18
 from photo import views as photo_views
18 19
 from server import server_views
@@ -207,3 +208,8 @@ urlpatterns += [
207 208
 urlpatterns += [
208 209
     url(r'^api/consumer_info$', mch_views.consumer_info_api, name='consumer_info_api'),
209 210
 ]
211
+
212
+urlpatterns = [
213
+    url(r'^clerk/submit$', oauth_views.clerk_submit_api, name='clerk_submit_api'),  # 店员信息提交
214
+    url(r'^clerk/sale/submit$', sale_views.clerk_sale_submit_api, name='clerk_sale_submit_api'),  # 店员销售信息提交
215
+]

+ 6 - 6
group/admin.py

@@ -36,9 +36,9 @@ class PhotoThumbUpInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
36 36
     list_filter = ('thumbup', 'status')
37 37
 
38 38
 
39
-admin.site.register(GroupInfo, GroupInfoAdmin)
40
-admin.site.register(GroupUserInfo, GroupUserInfoAdmin)
41
-admin.site.register(GroupPhotoInfo, GroupPhotoInfoAdmin)
42
-admin.site.register(GroupPhotoOrderInfo, GroupPhotoOrderInfoAdmin)
43
-admin.site.register(PhotoCommentInfo, PhotoCommentInfoAdmin)
44
-admin.site.register(PhotoThumbUpInfo, PhotoThumbUpInfoAdmin)
39
+# admin.site.register(GroupInfo, GroupInfoAdmin)
40
+# admin.site.register(GroupUserInfo, GroupUserInfoAdmin)
41
+# admin.site.register(GroupPhotoInfo, GroupPhotoInfoAdmin)
42
+# admin.site.register(GroupPhotoOrderInfo, GroupPhotoOrderInfoAdmin)
43
+# admin.site.register(PhotoCommentInfo, PhotoCommentInfoAdmin)
44
+# admin.site.register(PhotoThumbUpInfo, PhotoThumbUpInfoAdmin)

+ 0 - 0
integral/__init__.py


+ 15 - 0
integral/admin.py

@@ -0,0 +1,15 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.contrib import admin
4
+
5
+from integral.models import SaleclerkIntegralIncomeExpensesInfo
6
+
7
+
8
+class SaleclerkIntegralIncomeExpensesInfoAdmin(admin.ModelAdmin):
9
+    readonly_fields = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral')
10
+    list_display = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral', 'remark', 'status', 'created_at', 'updated_at')
11
+    search_fields = ('code', 'remark')
12
+    list_filter = ('franchiser_id', 'type', 'status')
13
+
14
+
15
+admin.site.register(SaleclerkIntegralIncomeExpensesInfo, SaleclerkIntegralIncomeExpensesInfoAdmin)

+ 36 - 0
integral/migrations/0001_initial.py

@@ -0,0 +1,36 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.9 on 2018-02-07 14:16
3
+from __future__ import unicode_literals
4
+
5
+from django.db import migrations, models
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    initial = True
11
+
12
+    dependencies = [
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='SaleclerkIntegralIncomeExpensesInfo',
18
+            fields=[
19
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
21
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
22
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
23
+                ('franchiser_id', models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='franchiser_id')),
24
+                ('clerk_id', models.CharField(blank=True, db_index=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='clerk_id')),
25
+                ('type', models.IntegerField(choices=[(0, '\u6536\u5165'), (1, '\u652f\u51fa'), (2, '\u89e3\u51bb')], db_index=True, default=0, help_text='\u6536\u652f\u7c7b\u522b', verbose_name='type')),
26
+                ('code', models.CharField(blank=True, db_index=True, help_text='\u673a\u8eab\u7801', max_length=32, null=True, verbose_name='code')),
27
+                ('integral', models.IntegerField(default=0, help_text='\u589e\u51cf\u79ef\u5206', verbose_name='integral')),
28
+                ('left_integral', models.IntegerField(default=0, help_text='\u79ef\u5206\u589e\u51cf\u540e\u6570\u91cf(\u5206)', verbose_name='left_integral')),
29
+                ('remark', models.CharField(blank=True, help_text='\u5907\u6ce8', max_length=255, null=True, verbose_name='remark')),
30
+            ],
31
+            options={
32
+                'verbose_name': 'saleclerkintegralincomeexpensesinfo',
33
+                'verbose_name_plural': 'saleclerkintegralincomeexpensesinfo',
34
+            },
35
+        ),
36
+    ]

+ 0 - 0
integral/migrations/__init__.py


+ 35 - 0
integral/models.py

@@ -0,0 +1,35 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.db import models
4
+from django.utils.translation import ugettext_lazy as _
5
+from models_ext import BaseModelMixin
6
+
7
+
8
+class SaleclerkIntegralIncomeExpensesInfo(BaseModelMixin):
9
+    INCOME = 0
10
+    EXPENSE = 1
11
+    UNFREEZE = 2
12
+
13
+    TYPE = (
14
+        (INCOME, u'收入'),
15
+        (EXPENSE, u'支出'),
16
+        (UNFREEZE, u'解冻'),
17
+    )
18
+
19
+    franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
20
+    clerk_id = models.CharField(_(u'clerk_id'), max_length=32, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
21
+
22
+    type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别', db_index=True)
23
+
24
+    code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码', db_index=True)
25
+    integral = models.IntegerField(_(u'integral'), default=0, help_text=u'增减积分')
26
+    left_integral = models.IntegerField(_(u'left_integral'), default=0, help_text=u'积分增减后数量(分)')
27
+
28
+    remark = models.CharField(_(u'remark'), max_length=255, blank=True, null=True, help_text=u'备注')
29
+
30
+    class Meta:
31
+        verbose_name = _(u'saleclerkintegralincomeexpensesinfo')
32
+        verbose_name_plural = _(u'saleclerkintegralincomeexpensesinfo')
33
+
34
+    def __unicode__(self):
35
+        return unicode(self.pk)

+ 4 - 0
integral/tests.py

@@ -0,0 +1,4 @@
1
+from django.test import TestCase
2
+
3
+
4
+# Create your tests here.

+ 4 - 0
integral/views.py

@@ -0,0 +1,4 @@
1
+from django.shortcuts import render
2
+
3
+
4
+# Create your views here.

+ 4 - 4
message/admin.py

@@ -26,7 +26,7 @@ class SystemMessageDeleteInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
26 26
     list_filter = ('status', )
27 27
 
28 28
 
29
-admin.site.register(UserMessageInfo, UserMessageInfoAdmin)
30
-admin.site.register(SystemMessageInfo, SystemMessageInfoAdmin)
31
-admin.site.register(SystemMessageReadInfo, SystemMessageReadInfoAdmin)
32
-admin.site.register(SystemMessageDeleteInfo, SystemMessageDeleteInfoAdmin)
29
+# admin.site.register(UserMessageInfo, UserMessageInfoAdmin)
30
+# admin.site.register(SystemMessageInfo, SystemMessageInfoAdmin)
31
+# admin.site.register(SystemMessageReadInfo, SystemMessageReadInfoAdmin)
32
+# admin.site.register(SystemMessageDeleteInfo, SystemMessageDeleteInfoAdmin)

+ 7 - 7
operation/admin.py

@@ -169,10 +169,10 @@ class BoxProgramVersionInfoAdmin(admin.ModelAdmin):
169 169
         set_box_program_version()
170 170
 
171 171
 
172
-admin.site.register(LatestAppInfo, LatestAppInfoAdmin)
173
-admin.site.register(PatchInfo, PatchInfoAdmin)
174
-admin.site.register(APPSettingsInfo, APPSettingsInfoAdmin)
175
-admin.site.register(SplashInfo, SplashInfoAdmin)
176
-admin.site.register(FeedbackInfo, FeedbackInfoAdmin)
177
-admin.site.register(GuestEntranceControlInfo, GuestEntranceControlInfoAdmin)
178
-admin.site.register(BoxProgramVersionInfo, BoxProgramVersionInfoAdmin)
172
+# admin.site.register(LatestAppInfo, LatestAppInfoAdmin)
173
+# admin.site.register(PatchInfo, PatchInfoAdmin)
174
+# admin.site.register(APPSettingsInfo, APPSettingsInfoAdmin)
175
+# admin.site.register(SplashInfo, SplashInfoAdmin)
176
+# admin.site.register(FeedbackInfo, FeedbackInfoAdmin)
177
+# admin.site.register(GuestEntranceControlInfo, GuestEntranceControlInfoAdmin)
178
+# admin.site.register(BoxProgramVersionInfo, BoxProgramVersionInfoAdmin)

+ 22 - 0
page/info_views.py

@@ -0,0 +1,22 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from __future__ import division
4
+
5
+from django.conf import settings
6
+from django.shortcuts import render
7
+
8
+from account.models import SaleclerkInfo
9
+
10
+
11
+def clerk_info_oauth(request):
12
+    unionid = request.GET.get('unionid', '')
13
+
14
+    try:
15
+        clerk = SaleclerkInfo.objects.get(unionid=unionid)
16
+    except SaleclerkInfo.DoesNotExist:
17
+        clerk = None
18
+
19
+    return render(request, 'page/clerk_info.html', {
20
+        'domain': settings.DOMAIN,
21
+        'clerk_info': clerk and clerk.data,
22
+    })

+ 64 - 1
page/oauth_views.py

@@ -1,9 +1,14 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
+from django.conf import settings
4
+from django.db import transaction
3 5
 from django.shortcuts import render
6
+from django_response import response
4 7
 from json_render import json_render
8
+from logit import logit
5 9
 
6
-from account.models import LensmanInfo, TourGuideInfo
10
+from account.models import FranchiserInfo, LensmanInfo, SaleclerkInfo, TourGuideInfo
11
+from utils.error.errno_utils import FranchiserStatusCode, SaleclerkStatusCode
7 12
 from utils.redis.connect import r
8 13
 
9 14
 
@@ -48,3 +53,61 @@ def login_qrcode(request):
48 53
     }
49 54
 
50 55
     return json_render(request, 'page/login_qrcode.html', data)
56
+
57
+
58
+def clerk_oauth(request):
59
+    unionid = request.GET.get('unionid', '')
60
+
61
+    chisers = FranchiserInfo.objects.filter(status=True)
62
+    chisers = [chiser.data for chiser in chisers]
63
+
64
+    try:
65
+        clerk = SaleclerkInfo.objects.get(unionid=unionid)
66
+    except SaleclerkInfo.DoesNotExist:
67
+        clerk = None
68
+
69
+    return render(request, 'page/clerk_oauth.html', {
70
+        'domain': settings.DOMAIN,
71
+        'chisers': chisers,
72
+        'clerk_info': clerk and clerk.data,
73
+        'modified': bool((not clerk) or (clerk and clerk.user_status in [SaleclerkInfo.UNVERIFIED, SaleclerkInfo.REFUSED])),  # 是否可以更改信息
74
+    })
75
+
76
+
77
+@logit
78
+@transaction.atomic
79
+def clerk_submit_api(request):
80
+    """ 店员授权信息提交 """
81
+    unionid = request.POST.get('unionid', '')
82
+    openid = request.POST.get('openid', '')
83
+    phone = request.POST.get('phone', '')
84
+    chiser = request.POST.get('chiser', '')
85
+
86
+    if SaleclerkInfo.objects.filter(clerk_phone=phone).exclude(unionid=unionid).exists():
87
+        return response(SaleclerkStatusCode.CLERK_PHONE_ALREADY_EXISTS)
88
+
89
+    try:
90
+        franchiser = FranchiserInfo.objects.get(franchiser_id=chiser)
91
+    except FranchiserInfo.DoesNotExist:
92
+        return response(FranchiserStatusCode.CHISER_NOT_FOUND)
93
+
94
+    fields = {
95
+        'franchiser_id': chiser,
96
+        'franchiser_name': franchiser.franchiser_name,
97
+        'clerk_name': request.POST.get('name', ''),
98
+        'clerk_sex': int(request.POST.get('sex', 1)),
99
+        'clerk_phone': phone,
100
+        'openid': openid,
101
+        'user_status': SaleclerkInfo.UNVERIFIED,
102
+    }
103
+
104
+    lensman, created = SaleclerkInfo.objects.select_for_update().get_or_create(unionid=unionid, defaults=fields)
105
+    # 状态为 UNVERIFIED 的允许修改, 其他需要登录摄影师 APP 进行信息的修改
106
+    if lensman.user_status not in [SaleclerkInfo.UNVERIFIED, SaleclerkInfo.REFUSED]:
107
+        return response(SaleclerkInfo.LENSMAN_ALREADY_NOT_UNVERIFIED)
108
+    if not created:
109
+        for key, value in fields.iteritems():
110
+            setattr(lensman, key, value)
111
+        lensman.save()
112
+
113
+    return response(200, 'Submit Success', u'提交成功', {})

+ 121 - 0
page/sale_views.py

@@ -0,0 +1,121 @@
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.shortcuts import render
8
+from django_response import response
9
+from logit import logit
10
+
11
+from account.models import SaleclerkInfo
12
+from integral.models import SaleclerkIntegralIncomeExpensesInfo
13
+from product.models import ProductCodeSubmitLogInfo, ProductInfo, ProductModelInfo
14
+from utils.error.errno_utils import ProductModelStatusCode, ProductStatusCode, SaleclerkStatusCode
15
+
16
+
17
+def clerk_sale_oauth(request):
18
+    unionid = request.GET.get('unionid', '')
19
+
20
+    models = ProductModelInfo.objects.filter(status=True)
21
+    models = [model.data for model in models]
22
+
23
+    try:
24
+        clerk = SaleclerkInfo.objects.get(unionid=unionid)
25
+    except SaleclerkInfo.DoesNotExist:
26
+        clerk = None
27
+
28
+    return render(request, 'page/clerk_sale.html', {
29
+        'domain': settings.DOMAIN,
30
+        'models': models,
31
+        'clerk_info': clerk and clerk.data,
32
+    })
33
+
34
+
35
+@logit
36
+@transaction.atomic
37
+def clerk_sale_submit_api(request):
38
+    """ 店员信息提交 """
39
+    step = int(request.POST.get('step', 1))
40
+
41
+    clerk_id = request.POST.get('clerk_id', '')
42
+    model_id = request.POST.get('model_id', '')
43
+    mount = request.POST.get('mount', 'NO')
44
+    code = request.POST.get('code', '')
45
+    name = request.POST.get('name', '')
46
+    sex = int(request.POST.get('sex', 1))
47
+    age = int(request.POST.get('age', 1))
48
+    phone = request.POST.get('phone', '')
49
+
50
+    # 店员是否存在
51
+    try:
52
+        clerk = SaleclerkInfo.objects.select_for_update().get(clerk_id=clerk_id)
53
+    except SaleclerkInfo.DoesNotExist:
54
+        return response(SaleclerkStatusCode.CLERK_NOT_FOUND)
55
+
56
+    # 店员是否激活
57
+    if clerk.user_status != SaleclerkInfo.ACTIVATED:
58
+        return response(SaleclerkStatusCode.CLERK_NOT_ACTIVATED)
59
+
60
+    # 型号是否存在
61
+    try:
62
+        model = ProductModelInfo.objects.get(model_id=model_id)
63
+    except ProductModelInfo.DoesNotExist:
64
+        return response(ProductModelStatusCode.MODEL_NOT_FOUND)
65
+
66
+    # 记录销售提交记录
67
+    ProductCodeSubmitLogInfo.objects.create(
68
+        model_id=model.model_id,
69
+        model_name=model.model_name,
70
+        mount=mount,
71
+        code=code,
72
+        franchiser_id=clerk.franchiser_id,
73
+        clerk_id=clerk.clerk_id,
74
+        consumer_name=name,
75
+        consumer_sex=sex,
76
+        consumer_age=age,
77
+        consumer_phone=phone,
78
+    )
79
+
80
+    # 产品是否存在
81
+    try:
82
+        product = ProductInfo.objects.select_for_update().get(model_id=model_id, mount=mount, code=code)
83
+    except ProductInfo.DoesNotExist:
84
+        return response(ProductStatusCode.PRODUCT_NOT_FOUND)
85
+
86
+    # 产品是否使用
87
+    if step == 1 and product.code_status:
88
+        return response(ProductStatusCode.PRODUCT_HAS_USED)
89
+    if step == 2 and not product.code_status:
90
+        return response(ProductStatusCode.PRODUCT_NOT_USED)
91
+
92
+    # 产品使用
93
+    product.code_status = True
94
+    product.integral_status = True
95
+    product.franchiser_id = clerk.franchiser_id
96
+    product.clerk_id = clerk.clerk_id
97
+    if 'name' in request.POST:
98
+        product.consumer_name = name
99
+    if 'sex' in request.POST:
100
+        product.consumer_sex = sex
101
+    if 'age' in request.POST:
102
+        product.consumer_age = age
103
+    if 'phone' in request.POST:
104
+        product.consumer_phone = phone
105
+    product.save()
106
+
107
+    # 店员积分
108
+    clerk.integral += product.integral
109
+    clerk.save()
110
+
111
+    # 店员积分记录
112
+    SaleclerkIntegralIncomeExpensesInfo.objects.create(
113
+        franchiser_id=clerk.franchiser_id,
114
+        clerk_id=clerk.clerk_id,
115
+        type=SaleclerkIntegralIncomeExpensesInfo.INCOME,
116
+        code=code,
117
+        integral=product.integral,
118
+        left_integral=clerk.integral,
119
+    )
120
+
121
+    return response(200, 'Submit Success', u'提交成功', {})

+ 67 - 0
page/static/page/css/weui.ext.css

@@ -0,0 +1,67 @@
1
+/* Input valid or invalid */
2
+input:required:invalid {
3
+    color: #E64340;
4
+}
5
+input:required:valid {
6
+    color: rgb(0, 0, 0);
7
+}
8
+/* Input Placeholder */
9
+ input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
10
+    font-size: 13px;
11
+}
12
+input:-moz-placeholder, textarea:-moz-placeholder {
13
+    font-size: 13px;
14
+}
15
+input::-moz-placeholder, textarea::-moz-placeholder {
16
+    font-size: 13px;
17
+}
18
+input:-ms-input-placeholder, textarea:-ms-input-placeholder {
19
+    font-size: 13px;
20
+}
21
+/* Radio Cells */
22
+.radio_cells {
23
+    margin-top: 0;
24
+    margin-left: 15px;
25
+}
26
+.radio_cells label {
27
+    padding: 8px 10px;
28
+    font-size: 15px;
29
+}
30
+/*.radio_cells>div:first-child .quartern:after {*/
31
+    /*border-left: none;*/
32
+/*}*/
33
+.radio_cells>div:last-child .quartern:after {
34
+    border-right: none;
35
+}
36
+/* Quartern */
37
+.quartern {
38
+    width: 25%;
39
+    box-sizing: border-box;
40
+    text-align: center;
41
+    border-radius: 5px;
42
+    float: left;
43
+}
44
+.quartern:after {
45
+    content: " ";
46
+    width: 200%;
47
+    height: 200%;
48
+    position: absolute;
49
+    top: 0;
50
+    left: 0;
51
+    border-right: 1px solid rgba(0, 0, 0, 0.2);
52
+    /*border-width: 0 1px 0 1px;*/
53
+    /*border-color: rgba(0, 0, 0, 0.2);*/
54
+    /*border-style: solid;*/
55
+    -webkit-transform: scale(0.5);
56
+            transform: scale(0.5);
57
+    -webkit-transform-origin: 0 0;
58
+            transform-origin: 0 0;
59
+    box-sizing: border-box;
60
+    border-radius: 10px;
61
+}
62
+/* Radio Checked Relative */
63
+.weui_check:checked + .quartern {
64
+    color: white;
65
+    background: #04BE02;
66
+    border-width: 0;
67
+}

+ 65 - 0
page/templates/page/clerk_info.html

@@ -0,0 +1,65 @@
1
+{% load staticfiles %}
2
+
3
+<!DOCTYPE html>
4
+<html lang="zh-CN">
5
+    <head>
6
+        <meta charset="utf-8">
7
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8
+        <meta name="format-detection" content="telephone=no,email=no,address=no">
9
+        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
10
+        <title>我的积分</title>
11
+
12
+        <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
13
+        <link href="{% static 'page/css/weui.ext.css' %}?v=1" rel="stylesheet" type="text/css" />
14
+    </head>
15
+    <body>
16
+        <div class="container" >
17
+            <div class="weui_cells_title">基本信息</div>
18
+            <div class="weui_cells weui_cells_form">
19
+                <div class="weui_cell">
20
+                    <div class="weui_cell_hd"><label for="" class="weui_label">经销商</label></div>
21
+                    <div class="weui_cell_bd weui_cell_primary">
22
+                        <label for="" class="weui_textarea">{{ clerk_info.franchiser_name }}</label>
23
+                    </div>
24
+                </div>
25
+                <div class="weui_cell">
26
+                    <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
27
+                    <div class="weui_cell_bd weui_cell_primary">
28
+                        <label for="" class="weui_textarea">{{ clerk_info.clerk_name }}</label>
29
+                    </div>
30
+                </div>
31
+                <div class="weui_cell">
32
+                    <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div>
33
+                    <div class="weui_cell_bd weui_cell_primary">
34
+                        <label for="" class="weui_textarea">{% ifequal clerk_info.clerk_sex 1 %}男{% else %}女{% endifequal %}</label>
35
+                    </div>
36
+                </div>
37
+                <div class="weui_cell">
38
+                    <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
39
+                    <div class="weui_cell_bd weui_cell_primary">
40
+                        <label for="" class="weui_textarea">{{ clerk_info.clerk_phone }}</label>
41
+                    </div>
42
+                </div>
43
+                <div class="weui_cell">
44
+                    <div class="weui_cell_hd"><label for="" class="weui_label">积分</label></div>
45
+                    <div class="weui_cell_bd weui_cell_primary">
46
+                        <label for="" class="weui_textarea">{{ clerk_info.integral }}</label>
47
+                    </div>
48
+                </div>
49
+            </div>
50
+        </div>
51
+
52
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
53
+        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.4.js' %}"></script>
54
+        <script>
55
+            V.initWxData({
56
+                imgUrl: 'http://pai.ai/static/pai2/img/paiai_96_96.png',
57
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fclerk%2Finfo',
58
+                desc: '店员授权',
59
+                title: '店员授权',
60
+                timeLine: ''
61
+            }, true);
62
+            V.hideOptionMenu();
63
+        </script>
64
+    </body>
65
+</html>

+ 191 - 0
page/templates/page/clerk_oauth.html

@@ -0,0 +1,191 @@
1
+{% load staticfiles %}
2
+
3
+<!DOCTYPE html>
4
+<html lang="zh-CN">
5
+    <head>
6
+        <meta charset="utf-8">
7
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8
+        <meta name="format-detection" content="telephone=no,email=no,address=no">
9
+        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
10
+        <title>店员授权</title>
11
+
12
+        <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
13
+        <link href="{% static 'page/css/weui.ext.css' %}?v=1" rel="stylesheet" type="text/css" />
14
+    </head>
15
+    <body>
16
+        <div class="container" >
17
+            <div class="weui_cells_title">基本信息</div>
18
+            <div class="weui_cells weui_cells_form">
19
+                <div class="weui_cell weui_cell_select weui_select_after">
20
+                    <div class="weui_cell_hd"><label for="" class="weui_label">经销商</label></div>
21
+                    <div class="weui_cell_bd weui_cell_primary">
22
+                        <select id="chiser" class="weui_select" name="select" {% if not modified %}disabled{% endif %}>
23
+                            {% for chiser in chisers %}
24
+                            <option value="{{ chiser.franchiser_id }}" {% ifequal chiser.franchiser_id clerk_info.franchiser_id %}selected{% endifequal %}>{{ chiser.franchiser_name }}</option>
25
+                            {% endfor %}
26
+                        </select>
27
+                    </div>
28
+                </div>
29
+                <div class="weui_cell">
30
+                    <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
31
+                    <div class="weui_cell_bd weui_cell_primary">
32
+                        <input id="name" class="weui_input" type="text" value="{{ clerk_info.clerk_name }}" placeholder="请输入姓名" {% if not modified %}disabled{% endif %}>
33
+                    </div>
34
+                </div>
35
+                <div class="weui_cell weui_cell_select weui_select_after">
36
+                    <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div>
37
+                    <div class="weui_cell_bd weui_cell_primary">
38
+                        <select id="sex" class="weui_select" name="select" {% if not modified %}disabled{% endif %}>
39
+                            <option value="1" {% ifequal clerk_info.clerk_sex 1 %}selected{% endifequal %}>男</option>
40
+                            <option value="0" {% ifequal clerk_info.clerk_sex 0 %}selected{% endifequal %}>女</option>
41
+                        </select>
42
+                    </div>
43
+                </div>
44
+                <div class="weui_cell">
45
+                    <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
46
+                    <div class="weui_cell_bd weui_cell_primary">
47
+                        <input id="phone" class="weui_input" type="text" required="required" pattern="[0-9]{11}" value="{{ clerk_info.clerk_phone }}" placeholder="请输入手机号" {% if not modified %}disabled{% endif %}>
48
+                    </div>
49
+                </div>
50
+            </div>
51
+
52
+            {% if clerk_info %}
53
+            <div class="weui_cells_title">审核状态</div>
54
+            <div class="weui_cells">
55
+                <div class="weui_cell">
56
+                    <div class="weui_cell_bd weui_cell_primary">
57
+                        <p>状态</p>
58
+                    </div>
59
+                    <div class="weui_cell_ft">
60
+                        {% ifequal clerk_info.status -1 %}已拒绝{% endifequal %}
61
+                        {% ifequal clerk_info.status 0 %}审核中{% endifequal %}
62
+                        {% ifequal clerk_info.status 1 %}已激活{% endifequal %}
63
+                        {% ifequal clerk_info.status 2 %}已禁用{% endifequal %}
64
+                        {% ifequal clerk_info.status 3 %}已删除{% endifequal %}
65
+                    </div>
66
+                </div>
67
+            </div>
68
+            {% endif %}
69
+
70
+
71
+            {% ifequal clerk_info.status -1 %}
72
+            <div class="weui_cells_title">拒绝原因</div>
73
+            <div class="weui_cells">
74
+                <div class="weui_panel_bd">
75
+                    <div class="weui_media_box weui_media_text">
76
+                        <p class="weui_media_desc">{{ clerk_info.refused_reason|safe|linebreaks }}</p>
77
+                    </div>
78
+                </div>
79
+            </div>
80
+            {% endifequal %}
81
+
82
+            <br>
83
+
84
+            {% if modified %}<button id="submit" class="weui_btn weui_btn_warn">确认</button>{% endif %}
85
+
86
+            <div class="weui_dialog_alert" id="dialog" style="display: none">
87
+                <div class="weui_mask"></div>
88
+                <div class="weui_dialog">
89
+                    <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
90
+                    <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
91
+                    <div class="weui_dialog_ft">
92
+                        <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
93
+                    </div>
94
+                </div>
95
+            </div>
96
+
97
+            <div id="toast" style="display: none;">
98
+                <div class="weui_mask_transparent"></div>
99
+                <div class="weui_toast">
100
+                    <i class="weui_icon_toast"></i>
101
+                    <p class="weui_toast_content">已完成</p>
102
+                </div>
103
+            </div>
104
+        </div>
105
+
106
+        <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
107
+        <script>
108
+            {% if modified %}
109
+            $(function() {
110
+                function getURLParameter(name) {
111
+                  return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
112
+                }
113
+
114
+                function show_error_dialog(title, content) {
115
+                    $('#dialog #title').text(title);
116
+                    $('#dialog #content').text(content);
117
+                    $('#dialog').show();
118
+                }
119
+
120
+                function data_check() {
121
+                    var unionid = getURLParameter('unionid');
122
+                    if (!unionid) {
123
+                        show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
124
+                        return false;
125
+                    }
126
+
127
+                    var name = $('#name').val();
128
+                    if (!name) {
129
+                        show_error_dialog('姓名', '姓名错误,请检查重新输入');
130
+                        return false;
131
+                    }
132
+
133
+                    var phone = $('#phone').val();
134
+                    var phone_valid = $('#phone').is(':valid');
135
+                    if (!(phone && phone_valid)) {
136
+                        show_error_dialog('手机号', '手机号错误,请检查重新输入');
137
+                        return false;
138
+                    }
139
+
140
+                    return {
141
+                        unionid: unionid,
142
+                        openid: getURLParameter('openid'),
143
+                        chiser: $('#chiser option:checked').val(),
144
+                        name: name,
145
+                        sex: $('#sex option:checked').val(),
146
+                        phone: phone,
147
+                    }
148
+                }
149
+
150
+                $('#submit').click(function () {
151
+                    var check_result = data_check();
152
+                    if (check_result){
153
+                        $.ajax({
154
+                            type: 'POST',
155
+                            url: '{{ domain }}/api/clerk/submit',
156
+                            data: check_result,
157
+                            success: function(data) {
158
+                                if (data.status == 200) {
159
+                                    $('#toast').show();
160
+                                    setTimeout(function () {
161
+                                        $('#toast').hide();
162
+                                    }, 1000);
163
+                                    window.location.reload();
164
+                                } else {
165
+                                    show_error_dialog('错误', data.description);
166
+                                }
167
+                            }
168
+                        })
169
+                    }
170
+                });
171
+
172
+                $('#dialog .weui_btn_dialog').click(function () {
173
+                    $('#dialog').hide();
174
+                })
175
+            });
176
+            {% endif %}
177
+        </script>
178
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
179
+        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.4.js' %}"></script>
180
+        <script>
181
+            V.initWxData({
182
+                imgUrl: 'http://pai.ai/static/pai2/img/paiai_96_96.png',
183
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fclerk',
184
+                desc: '店员授权',
185
+                title: '店员授权',
186
+                timeLine: ''
187
+            }, true);
188
+            V.hideOptionMenu();
189
+        </script>
190
+    </body>
191
+</html>

+ 366 - 0
page/templates/page/clerk_sale.html

@@ -0,0 +1,366 @@
1
+{% load staticfiles %}
2
+
3
+<!DOCTYPE html>
4
+<html lang="zh-CN">
5
+    <head>
6
+        <meta charset="utf-8">
7
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
8
+        <meta name="format-detection" content="telephone=no,email=no,address=no">
9
+        <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
10
+        <title>店员销售</title>
11
+
12
+        <link href="//res.wx.qq.com/open/libs/weui/0.4.3/weui.min.css" rel="stylesheet" type="text/css" />
13
+        <link href="{% static 'page/css/weui.ext.css' %}?v=1" rel="stylesheet" type="text/css" />
14
+    </head>
15
+    <body>
16
+        <div class="container" >
17
+            <div id="machine_info">
18
+                <div class="weui_cells_title">机器信息</div>
19
+                <div class="weui_cells weui_cells_form">
20
+                    <div class="weui_cell">
21
+                        <div class="weui_cell_hd"><label for="" class="weui_label">型号</label></div>
22
+                        <div class="weui_cell_bd weui_cell_primary">
23
+                            <input id="model" class="weui_input" type="text" value="" placeholder="请选择相机型号" disabled>
24
+                        </div>
25
+                    </div>
26
+                    <div id="model_radio" class="weui_cells weui_cells_radio radio_cells">
27
+                        {% for model in models %}
28
+                        <div>
29
+                            <input type="radio" class="weui_check" name="model" id="{{ model.model_id }}" value="{{ model.model_id }}" {% if forloop.first %}checked="checked"{% endif %}>
30
+                            <label class="weui_cell weui_check_label quartern" for="{{ model.model_id }}">
31
+                                <div class="weui_cell_bd weui_cell_primary">{{ model.model_name }}</div>
32
+                            </label>
33
+                        </div>
34
+                        {% endfor %}
35
+                    </div>
36
+                    <div class="weui_cell">
37
+                        <div class="weui_cell_hd"><label for="" class="weui_label">卡口</label></div>
38
+                        <div class="weui_cell_bd weui_cell_primary">
39
+                            <input id="mount" class="weui_input" type="text" value="" placeholder="请选择相机卡口" disabled>
40
+                        </div>
41
+                    </div>
42
+                    <div id="mount_radio" class="weui_cells weui_cells_radio radio_cells">
43
+                        <div>
44
+                            <input type="radio" class="weui_check" name="mount" id="e" value="E" checked="checked">
45
+                            <label class="weui_cell weui_check_label quartern" for="e">
46
+                                <div class="weui_cell_bd weui_cell_primary">E</div>
47
+                            </label>
48
+                        </div>
49
+                        <div>
50
+                            <input type="radio" class="weui_check" name="mount" id="n" value="N">
51
+                            <label class="weui_cell weui_check_label quartern" for="n">
52
+                                <div class="weui_cell_bd weui_cell_primary">N</div>
53
+                            </label>
54
+                        </div>
55
+                        <div>
56
+                            <input type="radio" class="weui_check" name="mount" id="s" value="S">
57
+                            <label class="weui_cell weui_check_label quartern" for="s">
58
+                                <div class="weui_cell_bd weui_cell_primary">S</div>
59
+                            </label>
60
+                        </div>
61
+                        <div>
62
+                            <input type="radio" class="weui_check" name="mount" id="p" value="P">
63
+                            <label class="weui_cell weui_check_label quartern" for="p">
64
+                                <div class="weui_cell_bd weui_cell_primary">P</div>
65
+                            </label>
66
+                        </div>
67
+                    </div>
68
+                    <div class="weui_cell">
69
+                        <div class="weui_cell_hd"><label for="" class="weui_label">机身码</label></div>
70
+                        <div class="weui_cell_bd weui_cell_primary">
71
+                            <input id="code" class="weui_input" type="text" value="" placeholder="请输入机身码">
72
+                        </div>
73
+                        <div class="weui_cell_ft">
74
+                            <a id="scan" href="javascript:;" class="weui_btn weui_btn_mini weui_btn_default">扫码</a>
75
+                        </div>
76
+                    </div>
77
+                </div>
78
+
79
+                <br>
80
+
81
+                <button id="submit1" class="weui_btn weui_btn_warn">确认</button>
82
+            </div>
83
+
84
+            <div id="customer_info" style="display: none;">
85
+                <div class="weui_cells_title">消费者信息</div>
86
+                <div class="weui_cells weui_cells_form">
87
+                    <div class="weui_cell">
88
+                        <div class="weui_cell_hd"><label for="" class="weui_label">姓名</label></div>
89
+                        <div class="weui_cell_bd weui_cell_primary">
90
+                            <input id="name" class="weui_input" type="text" value="" placeholder="请输入消费者姓名">
91
+                        </div>
92
+                    </div>
93
+                    <div class="weui_cell">
94
+                        <div class="weui_cell_hd"><label for="" class="weui_label">性别</label></div>
95
+                        <div class="weui_cell_bd weui_cell_primary">
96
+                            <input id="sex" class="weui_input" type="text" value="" placeholder="请选择消费者性别" disabled>
97
+                        </div>
98
+                    </div>
99
+                    <div id="sex_radio" class="weui_cells weui_cells_radio radio_cells">
100
+                        <div>
101
+                            <input type="radio" class="weui_check" name="sex" id="male" value="1" checked="checked">
102
+                            <label class="weui_cell weui_check_label quartern" for="male">
103
+                                <div class="weui_cell_bd weui_cell_primary">先生</div>
104
+                            </label>
105
+                        </div>
106
+                        <div>
107
+                            <input type="radio" class="weui_check" name="sex" id="female" value="0">
108
+                            <label class="weui_cell weui_check_label quartern" for="female">
109
+                                <div class="weui_cell_bd weui_cell_primary">女士</div>
110
+                            </label>
111
+                        </div>
112
+                    </div>
113
+                    <div class="weui_cell">
114
+                        <div class="weui_cell_hd"><label for="" class="weui_label">年龄段</label></div>
115
+                        <div class="weui_cell_bd weui_cell_primary">
116
+                            <input id="age" class="weui_input" type="text" value="" placeholder="请选择消费者年龄段" disabled>
117
+                        </div>
118
+                    </div>
119
+                    <div id="age_radio" class="weui_cells weui_cells_radio radio_cells">
120
+                        <div>
121
+                            <input type="radio" class="weui_check" name="age" id="age1" value="1" checked="checked">
122
+                            <label class="weui_cell weui_check_label quartern" for="age1">
123
+                                <div class="weui_cell_bd weui_cell_primary">20岁以下</div>
124
+                            </label>
125
+                        </div>
126
+                        <div>
127
+                            <input type="radio" class="weui_check" name="age" id="age2" value="2">
128
+                            <label class="weui_cell weui_check_label quartern" for="age2">
129
+                                <div class="weui_cell_bd weui_cell_primary">20~30岁</div>
130
+                            </label>
131
+                        </div>
132
+                        <div>
133
+                            <input type="radio" class="weui_check" name="age" id="age3" value="3">
134
+                            <label class="weui_cell weui_check_label quartern" for="age3">
135
+                                <div class="weui_cell_bd weui_cell_primary">30~40岁</div>
136
+                            </label>
137
+                        </div>
138
+                        <div>
139
+                            <input type="radio" class="weui_check" name="age" id="age4" value="4">
140
+                            <label class="weui_cell weui_check_label quartern" for="age4">
141
+                                <div class="weui_cell_bd weui_cell_primary">40~50岁</div>
142
+                            </label>
143
+                        </div>
144
+                        <div>
145
+                            <input type="radio" class="weui_check" name="age" id="age5" value="5">
146
+                            <label class="weui_cell weui_check_label quartern" for="age5">
147
+                                <div class="weui_cell_bd weui_cell_primary">50岁以上</div>
148
+                            </label>
149
+                        </div>
150
+                    </div>
151
+                    <div class="weui_cell">
152
+                        <div class="weui_cell_hd"><label for="" class="weui_label">手机号</label></div>
153
+                        <div class="weui_cell_bd weui_cell_primary">
154
+                            <input id="phone" class="weui_input" type="text" required="required" pattern="1[0-9]{10}" value="" placeholder="请输入消费者手机号">
155
+                        </div>
156
+                    </div>
157
+                </div>
158
+
159
+                <br>
160
+
161
+                <button id="submit2" class="weui_btn weui_btn_warn">确认</button>
162
+            </div>
163
+
164
+            <div class="weui_dialog_alert" id="dialog" style="display: none">
165
+                <div class="weui_mask"></div>
166
+                <div class="weui_dialog">
167
+                    <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
168
+                    <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
169
+                    <div class="weui_dialog_ft">
170
+                        <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
171
+                    </div>
172
+                </div>
173
+            </div>
174
+
175
+            <div class="weui_dialog_alert" id="dialog2" style="display: none">
176
+                <div class="weui_mask"></div>
177
+                <div class="weui_dialog">
178
+                    <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
179
+                    <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
180
+                    <div class="weui_dialog_ft">
181
+                        <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
182
+                    </div>
183
+                </div>
184
+            </div>
185
+
186
+            <div class="weui_dialog_alert" id="dialog3" style="display: none">
187
+                <div class="weui_mask"></div>
188
+                <div class="weui_dialog">
189
+                    <div class="weui_dialog_hd"><strong id="title" class="weui_dialog_title">弹窗标题</strong></div>
190
+                    <div id="content" class="weui_dialog_bd">弹窗内容,告知当前页面信息等</div>
191
+                    <div class="weui_dialog_ft">
192
+                        <a href="javascript:;" class="weui_btn_dialog primary">确定</a>
193
+                    </div>
194
+                </div>
195
+            </div>
196
+
197
+            <div id="toast" style="display: none;">
198
+                <div class="weui_mask_transparent"></div>
199
+                <div class="weui_toast">
200
+                    <i class="weui_icon_toast"></i>
201
+                    <p class="weui_toast_content">已完成</p>
202
+                </div>
203
+            </div>
204
+        </div>
205
+
206
+        <script src="//cdn.bootcss.com/zepto/1.1.6/zepto.min.js"></script>
207
+        <script>
208
+            $(function() {
209
+                function show_error_dialog(title, content) {
210
+                    $('#dialog #title').text(title);
211
+                    $('#dialog #content').text(content);
212
+                    $('#dialog').show();
213
+                }
214
+
215
+                function show_error_dialog2(title, content) {
216
+                    $('#dialog2 #title').text(title);
217
+                    $('#dialog2 #content').text(content);
218
+                    $('#dialog2').show();
219
+                }
220
+
221
+                function show_error_dialog3(title, content) {
222
+                    $('#dialog3 #title').text(title);
223
+                    $('#dialog3 #content').text(content);
224
+                    $('#dialog3').show();
225
+                }
226
+
227
+                function data_check() {
228
+                    var clerk_id = "{{ clerk_info.clerk_id }}";
229
+                    if (!clerk_id) {
230
+                        show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
231
+                        return false;
232
+                    }
233
+
234
+                    var code = $('#code').val();
235
+                    if (!code) {
236
+                        show_error_dialog('机身码', '机身码错误,请检查重新输入');
237
+                        return false;
238
+                    }
239
+
240
+                    return {
241
+                        step: 1,
242
+                        clerk_id: clerk_id,
243
+                        model_id: $("#model_radio input[name='model']:checked").val(),
244
+                        mount: $("#mount_radio input[name='mount']:checked").val(),
245
+                        code: code,
246
+                    }
247
+                }
248
+
249
+                function data_check2() {
250
+                    var clerk_id = "{{ clerk_info.clerk_id }}";
251
+                    if (!clerk_id) {
252
+                        show_error_dialog('微信授权', '微信授权失败,请重新打开页面');
253
+                        return false;
254
+                    }
255
+
256
+                    var code = $('#code').val();
257
+                    if (!code) {
258
+                        show_error_dialog('机身码', '机身码错误,请检查重新输入');
259
+                        return false;
260
+                    }
261
+
262
+                    var name = $('#name').val();
263
+                    if (!name) {
264
+                        show_error_dialog('姓名', '姓名错误,请检查重新输入');
265
+                        return false;
266
+                    }
267
+
268
+                    var phone = $('#phone').val();
269
+                    var phone_valid = $('#phone').is(':valid');
270
+                    if (!(phone && phone_valid)) {
271
+                        show_error_dialog('手机号', '手机号错误,请检查重新输入');
272
+                        return false;
273
+                    }
274
+
275
+                    return {
276
+                        step: 2,
277
+                        clerk_id: clerk_id,
278
+                        model_id: $("#model_radio input[name='model']:checked").val(),
279
+                        mount: $("#mount_radio input[name='mount']:checked").val(),
280
+                        code: code,
281
+                        name: name,
282
+                        sex: $("#sex_radio input[name='sex']:checked").val(),
283
+                        age: $("#age_radio input[name='age']:checked").val(),
284
+                        phone: phone,
285
+                    }
286
+                }
287
+
288
+                $('#submit1').click(function () {
289
+                    var check_result = data_check();
290
+                    if (check_result){
291
+                        $.ajax({
292
+                            type: 'POST',
293
+                            url: '{{ domain }}/api/clerk/sale/submit',
294
+                            data: check_result,
295
+                            success: function(data) {
296
+                                if (data.status == 200) {
297
+{#                                    $('#toast').show();#}
298
+{#                                    setTimeout(function () {#}
299
+{#                                        $('#toast').hide();#}
300
+{#                                    }, 1000);#}
301
+                                    show_error_dialog2('成功', '机器信息提交成功');
302
+                                } else {
303
+                                    show_error_dialog('错误', data.description);
304
+                                }
305
+                            }
306
+                        })
307
+                    }
308
+                });
309
+
310
+                $('#submit2').click(function () {
311
+                    var check_result = data_check2();
312
+                    if (check_result){
313
+                        $.ajax({
314
+                            type: 'POST',
315
+                            url: '{{ domain }}/api/clerk/sale/submit',
316
+                            data: check_result,
317
+                            success: function(data) {
318
+                                if (data.status == 200) {
319
+                                    show_error_dialog3('成功', '消费者信息提交成功');
320
+                                } else {
321
+                                    show_error_dialog('错误', data.description);
322
+                                }
323
+                            }
324
+                        })
325
+                    }
326
+                });
327
+
328
+                $('#dialog .weui_btn_dialog').click(function () {
329
+                    $('#dialog').hide();
330
+                })
331
+
332
+                $('#dialog2 .weui_btn_dialog').click(function () {
333
+                    $('#dialog2').hide();
334
+                    $('#machine_info').hide();
335
+                    $('#customer_info').show();
336
+                })
337
+
338
+                $('#dialog3 .weui_btn_dialog').click(function () {
339
+                    $('#dialog').hide();
340
+                    window.location.reload();
341
+                })
342
+            });
343
+        </script>
344
+        <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
345
+        <script type="text/javascript" src="{% static 'pai2/js/jswe-0.0.4.js' %}"></script>
346
+        <script>
347
+            V.initWxData({
348
+                imgUrl: 'http://pai.ai/static/pai2/img/paiai_96_96.png',
349
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fkodo.xfoto.com.cn%2Fp%2Fclerk%2Fsale',
350
+                desc: '店员授权',
351
+                title: '店员授权',
352
+                timeLine: ''
353
+            }, true);
354
+            V.hideOptionMenu();
355
+
356
+            $('#scan').click(function () {
357
+                V.scanQRCode({
358
+                    needResult: 1
359
+                });
360
+            });
361
+            V.wxScanQRCodeSuccess = function (res) {
362
+                $('#code').val(V.parseScanQRCodeResultStr(res.resultStr));
363
+            }
364
+        </script>
365
+    </body>
366
+</html>

+ 1 - 1
page/templates/page/lensman_oauth.html

@@ -190,7 +190,7 @@
190 190
         <script>
191 191
             V.initWxData({
192 192
                 imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
193
-                link: 'http://pai.ai/we/we_oauth2?redirect_url=http://pai.ai/page/lensman&scope=snsapi_userinfo',
193
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fpai.ai%2Fp%2Flensman',
194 194
                 desc: "摄影师授权",
195 195
                 title: "摄影师授权",
196 196
                 timeLine: ""

+ 1 - 1
page/templates/page/login_qrcode.html

@@ -51,7 +51,7 @@
51 51
         <script>
52 52
             V.initWxData({
53 53
                 imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
54
-                link: 'http://pai.ai/we/we_oauth2?redirect_url=http://pai.ai/page/loginqr&scope=snsapi_userinfo',
54
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fpai.ai%2Fp%2Floginqr',
55 55
                 desc: "授权登录",
56 56
                 title: "授权登录",
57 57
                 timeLine: ""

+ 1 - 1
page/templates/page/tourguide_oauth.html

@@ -252,7 +252,7 @@
252 252
         <script>
253 253
             V.initWxData({
254 254
                 imgUrl: "http://pai.ai/static/pai2/img/paiai_96_96.png",
255
-                link: 'http://pai.ai/we/we_oauth2?redirect_url=http://pai.ai/page/tourguide&scope=snsapi_userinfo',
255
+                link: 'http://pai.ai/w/o?r=http%3A%2F%2Fpai.ai%2Fp%2Ftourguide',
256 256
                 desc: "导游授权",
257 257
                 title: "导游授权",
258 258
                 timeLine: ""

+ 7 - 1
page/urls.py

@@ -4,7 +4,7 @@ from django.conf.urls import url
4 4
 
5 5
 from account import tourguide_views
6 6
 from group import lensman_views
7
-from page import oauth_views, page_views
7
+from page import info_views, oauth_views, page_views, sale_views
8 8
 
9 9
 
10 10
 urlpatterns = [
@@ -28,3 +28,9 @@ urlpatterns += [
28 28
 urlpatterns += [
29 29
     url(r'^t/submit$', tourguide_views.tourguide_submit_api, name='tourguide_submit_api'),  # 导游信息提交
30 30
 ]
31
+
32
+urlpatterns = [
33
+    url(r'^clerk$', oauth_views.clerk_oauth, name='clerk_oauth'),  # 店员授权页面
34
+    url(r'^clerk/sale$', sale_views.clerk_sale_oauth, name='clerk_sale_oauth'),  # 店员销售授权页面
35
+    url(r'^clerk/info$', info_views.clerk_info_oauth, name='clerk_info_oauth'),  # 店员信息授权页面
36
+]

+ 23 - 21
pai2/settings.py

@@ -43,8 +43,8 @@ INSTALLED_APPS = (
43 43
     'django.contrib.sessions',
44 44
     'django.contrib.messages',
45 45
     'django.contrib.staticfiles',
46
-    'rest_framework',
47
-    'django_q',
46
+    # 'rest_framework',
47
+    # 'django_q',
48 48
     'django_rlog',
49 49
     'django_uniapi',
50 50
     'django_we',
@@ -53,6 +53,7 @@ INSTALLED_APPS = (
53 53
     'account',
54 54
     'box',
55 55
     'group',
56
+    'integral',
56 57
     'mch',
57 58
     'message',
58 59
     'miniapp',
@@ -60,6 +61,7 @@ INSTALLED_APPS = (
60 61
     'page',
61 62
     'pay',
62 63
     'photo',
64
+    'product',
63 65
     'server',
64 66
     'website',
65 67
 )
@@ -79,12 +81,12 @@ MIDDLEWARE_CLASSES = (
79 81
     'mobi.middleware.MobileDetectionMiddleware',
80 82
 )
81 83
 
82
-MIDDLEWARE_CLASSES += ('multidomain.middleware.DomainMiddleware', )
83
-
84
-URL_CONFIG = (
85
-    # (r'^(.+\.)?xfoto\.com\.cn', 'pai2.urls_www'),
86
-    (r'^(.+\.)?api\.pai\.ai', 'pai2.urls_api'),
87
-)
84
+# MIDDLEWARE_CLASSES += ('multidomain.middleware.DomainMiddleware', )
85
+#
86
+# URL_CONFIG = (
87
+#     # (r'^(.+\.)?xfoto\.com\.cn', 'pai2.urls_www'),
88
+#     (r'^(.+\.)?api\.pai\.ai', 'pai2.urls_api'),
89
+# )
88 90
 
89 91
 ROOT_URLCONF = 'pai2.urls'
90 92
 
@@ -121,7 +123,7 @@ DATABASES = {
121 123
     # CREATE DATABASE pai2 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
122 124
     'default': {
123 125
         'ENGINE': 'django.db.backends.mysql',
124
-        'NAME': 'pai2',
126
+        'NAME': 'kodo',
125 127
         'USER': 'root',
126 128
         'PASSWORD': '',
127 129
         'CONN_MAX_AGE': 600,
@@ -385,18 +387,18 @@ THUMBUP_MESSAGE_AVATAR = PAI2_LOGO_URL
385 387
 # Redis 连接
386 388
 REDIS_CACHE = connector(REDIS.get('default', {}))
387 389
 
388
-Q_CLUSTER = {
389
-    'name': 'pai2',
390
-    'workers': 8,
391
-    'recycle': 500,
392
-    'timeout': 60,
393
-    'compress': True,
394
-    'cpu_affinity': 1,
395
-    'save_limit': 250,
396
-    'queue_limit': 500,
397
-    'label': 'Django Q',
398
-    'redis_conn': REDIS_CACHE,
399
-}
390
+# Q_CLUSTER = {
391
+#     'name': 'pai2',
392
+#     'workers': 8,
393
+#     'recycle': 500,
394
+#     'timeout': 60,
395
+#     'compress': True,
396
+#     'cpu_affinity': 1,
397
+#     'save_limit': 250,
398
+#     'queue_limit': 500,
399
+#     'label': 'Django Q',
400
+#     'redis_conn': REDIS_CACHE,
401
+# }
400 402
 
401 403
 DJLOGIT = {
402 404
     'level': 'DEBUG',

+ 49 - 43
pai2/urls.py

@@ -29,51 +29,51 @@ from photo import views as photo_views
29 29
 from website import views as website_views
30 30
 
31 31
 
32
-router = routers.DefaultRouter()
33
-# router.register(r'users', account_views.UserViewSet)
34
-# router.register(r'groups', account_views.GroupViewSet)
35
-
36
-router.register(r'lensmans', account_views.LensmanInfoViewSet)
37
-router.register(r'users', account_views.UserInfoViewSet)
38
-
39
-router.register(r'groups', group_views.GroupInfoViewSet)
40
-router.register(r'group_users', group_views.GroupUserInfoViewSet)
41
-router.register(r'group_photos', group_views.GroupPhotoInfoViewSet)
42
-
43
-router.register(r'photos', photo_views.PhotoInfoViewSet)
32
+# router = routers.DefaultRouter()
33
+# # router.register(r'users', account_views.UserViewSet)
34
+# # router.register(r'groups', account_views.GroupViewSet)
35
+#
36
+# router.register(r'lensmans', account_views.LensmanInfoViewSet)
37
+# router.register(r'users', account_views.UserInfoViewSet)
38
+#
39
+# router.register(r'groups', group_views.GroupInfoViewSet)
40
+# router.register(r'group_users', group_views.GroupUserInfoViewSet)
41
+# router.register(r'group_photos', group_views.GroupPhotoInfoViewSet)
42
+#
43
+# router.register(r'photos', photo_views.PhotoInfoViewSet)
44 44
 
45 45
 urlpatterns = [
46 46
     url(r'^pai2admin/', include(admin.site.urls)),
47 47
 ]
48 48
 
49
-urlpatterns += [
50
-    # url(r'^api/', include('api.urls', namespace='api')),
51
-    url(r'^s/(?P<session_id>\w+)$', photo_views.session_detail, name='session_detail'),  # Session 详情
52
-    url(r'^p/(?P<photo_id>\w+)$', photo_views.photo_standard, name='photo_standard'),  # standard thumbnail, available for free
53
-    url(r'^m/(?P<photo_id>\w+)$', photo_views.photo_medium, name='photo_medium'),  # medium/mobile version, without watermark, login or paid by others
54
-    url(r'^l/(?P<photo_id>\w+)$', photo_views.photo_large, name='photo_large'),  # large, might support server side panning later, login required
55
-    url(r'^r/(?P<photo_id>\w+)$', photo_views.photo_raw, name='photo_raw'),  # raw image, only for finishers
56
-]
57
-
58
-urlpatterns += [
59
-    url(r'^g/(?P<group_id>\w+)$', grouppage_views.group_detail, name='group_detail'),  # 群组详情(拍爱用户端下载页)
60
-]
61
-
62
-urlpatterns += [
63
-    url(r'^gp/(?P<photo_id>\w+)$', grouppage_views.group_photo_detail, name='group_photo_detail'),  # 群组照片详情
64
-]
65
-
66
-urlpatterns += [
67
-    url(r'^tg/(?P<admin_id>\w+)$', grouppage_views.tgu_group_detail, name='tgu_group_detail'),  # 旅行团详情(拍爱导游端下载页)
68
-]
69
-
70
-urlpatterns += [
71
-    url(r'^tgu/(?P<admin_id>\w+)$', grouppage_views.tgu_group_user_detail, name='tgu_group_user_detail'),  # 旅行团成员详情(拍爱用户端下载页)
72
-]
73
-
74
-urlpatterns += [
75
-    url(r'^$', website_views.pai2_home, name='pai2_home'),  # 官网首页
76
-]
49
+# urlpatterns += [
50
+#     # url(r'^api/', include('api.urls', namespace='api')),
51
+#     url(r'^s/(?P<session_id>\w+)$', photo_views.session_detail, name='session_detail'),  # Session 详情
52
+#     url(r'^p/(?P<photo_id>\w+)$', photo_views.photo_standard, name='photo_standard'),  # standard thumbnail, available for free
53
+#     url(r'^m/(?P<photo_id>\w+)$', photo_views.photo_medium, name='photo_medium'),  # medium/mobile version, without watermark, login or paid by others
54
+#     url(r'^l/(?P<photo_id>\w+)$', photo_views.photo_large, name='photo_large'),  # large, might support server side panning later, login required
55
+#     url(r'^r/(?P<photo_id>\w+)$', photo_views.photo_raw, name='photo_raw'),  # raw image, only for finishers
56
+# ]
57
+#
58
+# urlpatterns += [
59
+#     url(r'^g/(?P<group_id>\w+)$', grouppage_views.group_detail, name='group_detail'),  # 群组详情(拍爱用户端下载页)
60
+# ]
61
+#
62
+# urlpatterns += [
63
+#     url(r'^gp/(?P<photo_id>\w+)$', grouppage_views.group_photo_detail, name='group_photo_detail'),  # 群组照片详情
64
+# ]
65
+#
66
+# urlpatterns += [
67
+#     url(r'^tg/(?P<admin_id>\w+)$', grouppage_views.tgu_group_detail, name='tgu_group_detail'),  # 旅行团详情(拍爱导游端下载页)
68
+# ]
69
+#
70
+# urlpatterns += [
71
+#     url(r'^tgu/(?P<admin_id>\w+)$', grouppage_views.tgu_group_user_detail, name='tgu_group_user_detail'),  # 旅行团成员详情(拍爱用户端下载页)
72
+# ]
73
+#
74
+# urlpatterns += [
75
+#     url(r'^$', website_views.pai2_home, name='pai2_home'),  # 官网首页
76
+# ]
77 77
 
78 78
 # Mini App
79 79
 urlpatterns += [
@@ -83,14 +83,20 @@ urlpatterns += [
83 83
 # Wire up our API using automatic URL routing.
84 84
 # Additionally, we include login URLs for the browsable API.
85 85
 urlpatterns += [
86
-    url(r'^api/', include(router.urls)),
87
-    url(r'^page/', include('page.urls', namespace='page')),
86
+    # url(r'^restapi/', include(router.urls)),
88 87
     url(r'^uniapi/', include('django_uniapi.urls', namespace='uniapi')),
88
+    url(r'^api/', include('api.urls', namespace='api')),
89
+    url(r'^w/', include('django_we.urls', namespace='shortwechat')),
89 90
     url(r'^we/', include('django_we.urls', namespace='wechat')),
90 91
     url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
91 92
 ]
92 93
 
94
+urlpatterns += [
95
+    url(r'^p/', include('page.urls', namespace='shortpage')),
96
+    url(r'^page/', include('page.urls', namespace='page')),
97
+]
98
+
93 99
 urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
94 100
 urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
95 101
 
96
-admin.site.site_header = u'[拍爱]后台管理系统'
102
+admin.site.site_header = u'[盈多]后台管理系统'

+ 1 - 1
pay/admin.py

@@ -13,4 +13,4 @@ class OrderInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
13 13
     search_fields = ('prepay_id', 'transaction_id', 'group_id', 'session_id', 'photo_id', 'lensman_photo_id', 'from_uid', 'to_uid')
14 14
 
15 15
 
16
-admin.site.register(OrderInfo, OrderInfoAdmin)
16
+# admin.site.register(OrderInfo, OrderInfoAdmin)

+ 3 - 3
photo/admin.py

@@ -20,6 +20,6 @@ class PhotosInfoAdmin(admin.ModelAdmin):
20 20
     list_filter = ('lensman_id', 'status')
21 21
 
22 22
 
23
-admin.site.register(UUIDInfo, UUIDInfoAdmin)
24
-admin.site.register(PhotosInfo, PhotosInfoAdmin)
25
-admin.site.register(PhotoUUIDInfo, PhotoUUIDInfoAdmin)
23
+# admin.site.register(UUIDInfo, UUIDInfoAdmin)
24
+# admin.site.register(PhotosInfo, PhotosInfoAdmin)
25
+# admin.site.register(PhotoUUIDInfo, PhotoUUIDInfoAdmin)

+ 8 - 8
photo/views.py

@@ -3,7 +3,7 @@
3 3
 from curtail_uuid import CurtailUUID
4 4
 from django.db import transaction
5 5
 from django.shortcuts import render
6
-from django_q.tasks import async
6
+# from django_q.tasks import async
7 7
 from django_response import response
8 8
 from ipaddr import client_ip
9 9
 from logit import logit
@@ -46,13 +46,13 @@ def uuid(request):
46 46
     # 从 Redis 中 Pop 中指定数量的 UUID
47 47
     uuids, succeed, left = r.multi_pop(UUID_LIST, num)
48 48
 
49
-    # 异步更新 UUID 数据库中状态
50
-    if uuids:
51
-        async(update_uuids, lensman_id, uuids)
52
-
53
-    # 当可用 UUID 数量少于 500 时, 异步创建
54
-    if left < 500:
55
-        async(generate_uuids)
49
+    # # 异步更新 UUID 数据库中状态
50
+    # if uuids:
51
+    #     async(update_uuids, lensman_id, uuids)
52
+    #
53
+    # # 当可用 UUID 数量少于 500 时, 异步创建
54
+    # if left < 500:
55
+    #     async(generate_uuids)
56 56
 
57 57
     return response(200, 'Get UUID Success', u'获取唯一标识成功', uuids)
58 58
 

+ 0 - 0
product/__init__.py


+ 29 - 0
product/admin.py

@@ -0,0 +1,29 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.contrib import admin
4
+
5
+from product.models import ProductCodeSubmitLogInfo, ProductInfo, ProductModelInfo
6
+
7
+
8
+class ProductModelInfoAdmin(admin.ModelAdmin):
9
+    readonly_fields = ('model_id', )
10
+    list_display = ('model_id', 'model_name', 'integral', 'has_mount', 'status', 'created_at', 'updated_at')
11
+    search_fields = ('model_id', 'model_name')
12
+    list_filter = ('has_mount', 'status')
13
+
14
+
15
+class ProductInfoAdmin(admin.ModelAdmin):
16
+    list_display = ('model_id', 'model_name', 'code', 'code_status', 'integral', 'integral_status', 'franchiser_id', 'clerk_id', 'consumer_name', 'consumer_sex', 'consumer_age', 'consumer_phone', 'status', 'created_at', 'updated_at')
17
+    search_fields = ('model_id', 'model_name', 'code', 'consumer_name', 'consumer_phone')
18
+    list_filter = ('code_status', 'integral_status', 'franchiser_id', 'consumer_sex', 'status')
19
+
20
+
21
+class ProductCodeSubmitLogInfoAdmin(admin.ModelAdmin):
22
+    list_display = ('model_id', 'model_name', 'mount', 'code', 'franchiser_id', 'clerk_id', 'consumer_name', 'consumer_sex', 'consumer_age', 'consumer_phone', 'status', 'created_at', 'updated_at')
23
+    search_fields = ('model_id', 'model_name', 'code', 'consumer_name', 'consumer_phone')
24
+    list_filter = ('step', 'mount', 'franchiser_id', 'consumer_sex', 'status')
25
+
26
+
27
+admin.site.register(ProductModelInfo, ProductModelInfoAdmin)
28
+admin.site.register(ProductInfo, ProductInfoAdmin)
29
+admin.site.register(ProductCodeSubmitLogInfo, ProductCodeSubmitLogInfoAdmin)

+ 86 - 0
product/migrations/0001_initial.py

@@ -0,0 +1,86 @@
1
+# -*- coding: utf-8 -*-
2
+# Generated by Django 1.11.9 on 2018-02-07 14:16
3
+from __future__ import unicode_literals
4
+
5
+from django.db import migrations, models
6
+import shortuuidfield.fields
7
+
8
+
9
+class Migration(migrations.Migration):
10
+
11
+    initial = True
12
+
13
+    dependencies = [
14
+    ]
15
+
16
+    operations = [
17
+        migrations.CreateModel(
18
+            name='ProductCodeSubmitLogInfo',
19
+            fields=[
20
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
22
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
23
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
24
+                ('sex', models.BooleanField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='Sex', verbose_name='sex')),
25
+                ('step', models.IntegerField(db_index=True, default=1, help_text='\u63d0\u4ea4\u6b65\u9aa4', verbose_name='step')),
26
+                ('model_id', models.CharField(blank=True, db_index=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='model_id')),
27
+                ('model_name', models.CharField(blank=True, db_index=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=32, null=True, verbose_name='model_name')),
28
+                ('mount', models.CharField(blank=True, db_index=True, help_text='\u5361\u53e3', max_length=255, null=True, verbose_name='mount')),
29
+                ('code', models.CharField(blank=True, help_text='\u673a\u8eab\u7801', max_length=32, null=True, verbose_name='code')),
30
+                ('franchiser_id', models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='franchiser_id')),
31
+                ('clerk_id', models.CharField(blank=True, db_index=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='clerk_id')),
32
+                ('consumer_name', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u540d\u79f0', max_length=32, null=True, verbose_name='consumer_name')),
33
+                ('consumer_sex', models.IntegerField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='\u6d88\u8d39\u8005\u6027\u522b', verbose_name='consumer_sex')),
34
+                ('consumer_age', models.IntegerField(default=0, help_text='\u6d88\u8d39\u8005\u5e74\u9f84', verbose_name='consumer_age')),
35
+                ('consumer_phone', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u8054\u7cfb\u7535\u8bdd', max_length=11, null=True, verbose_name='consumer_phone')),
36
+            ],
37
+            options={
38
+                'verbose_name': 'productcodesubmitloginfo',
39
+                'verbose_name_plural': 'productcodesubmitloginfo',
40
+            },
41
+        ),
42
+        migrations.CreateModel(
43
+            name='ProductInfo',
44
+            fields=[
45
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
46
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
47
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
48
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
49
+                ('sex', models.BooleanField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='Sex', verbose_name='sex')),
50
+                ('model_id', models.CharField(blank=True, db_index=True, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='model_id')),
51
+                ('model_name', models.CharField(blank=True, db_index=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=32, null=True, verbose_name='model_name')),
52
+                ('mount', models.CharField(blank=True, db_index=True, help_text='\u5361\u53e3', max_length=32, null=True, verbose_name='mount')),
53
+                ('code', models.CharField(blank=True, help_text='\u673a\u8eab\u7801', max_length=32, null=True, verbose_name='code')),
54
+                ('code_status', models.BooleanField(db_index=True, default=False, help_text='\u673a\u8eab\u7801\u72b6\u6001, True\u5df2\u4f7f\u7528\uff0cFalse\u672a\u4f7f\u7528', verbose_name='code_status')),
55
+                ('integral', models.IntegerField(default=0, help_text='\u79ef\u5206', verbose_name='integral')),
56
+                ('integral_status', models.BooleanField(db_index=True, default=False, help_text='\u79ef\u5206\u72b6\u6001, True\u5df2\u79ef\u5206\uff0cFalse\u672a\u79ef\u5206', verbose_name='integral_status')),
57
+                ('franchiser_id', models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='franchiser_id')),
58
+                ('clerk_id', models.CharField(blank=True, db_index=True, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='clerk_id')),
59
+                ('consumer_name', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u540d\u79f0', max_length=32, null=True, verbose_name='consumer_name')),
60
+                ('consumer_sex', models.IntegerField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='\u6d88\u8d39\u8005\u6027\u522b', verbose_name='consumer_sex')),
61
+                ('consumer_age', models.IntegerField(default=0, help_text='\u6d88\u8d39\u8005\u5e74\u9f84', verbose_name='consumer_age')),
62
+                ('consumer_phone', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u8054\u7cfb\u7535\u8bdd', max_length=11, null=True, verbose_name='consumer_phone')),
63
+            ],
64
+            options={
65
+                'verbose_name': 'productinfo',
66
+                'verbose_name_plural': 'productinfo',
67
+            },
68
+        ),
69
+        migrations.CreateModel(
70
+            name='ProductModelInfo',
71
+            fields=[
72
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
73
+                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
74
+                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
75
+                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
76
+                ('model_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u578b\u53f7\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
77
+                ('model_name', models.CharField(blank=True, help_text='\u578b\u53f7\u540d\u79f0', max_length=32, null=True, unique=True, verbose_name='model_name')),
78
+                ('integral', models.IntegerField(default=0, help_text='\u578b\u53f7\u79ef\u5206', verbose_name='integral')),
79
+                ('has_mount', models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u6709\u5361\u53e3', verbose_name='has_mount')),
80
+            ],
81
+            options={
82
+                'verbose_name': '\u4ea7\u54c1\u578b\u53f7\u4fe1\u606f',
83
+                'verbose_name_plural': '\u4ea7\u54c1\u578b\u53f7\u4fe1\u606f',
84
+            },
85
+        ),
86
+    ]

+ 0 - 0
product/migrations/__init__.py


+ 88 - 0
product/models.py

@@ -0,0 +1,88 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.db import models
4
+from django.utils.translation import ugettext_lazy as _
5
+from models_ext import BaseModelMixin, SexModelMixin
6
+from shortuuidfield import ShortUUIDField
7
+
8
+
9
+class ProductModelInfo(BaseModelMixin):
10
+    model_id = ShortUUIDField(_(u'model_id'), max_length=32, help_text=u'型号唯一标识', db_index=True, unique=True)
11
+    model_name = models.CharField(_(u'model_name'), max_length=32, blank=True, null=True, help_text=u'型号名称', unique=True)
12
+    integral = models.IntegerField(_(u'integral'), default=0, help_text=u'型号积分')
13
+    has_mount = models.BooleanField(_(u'has_mount'), default=True, help_text=u'是否有卡口', db_index=True)
14
+
15
+    class Meta:
16
+        verbose_name = _(u'产品型号信息')
17
+        verbose_name_plural = _(u'产品型号信息')
18
+
19
+    def __unicode__(self):
20
+        return unicode(self.pk)
21
+
22
+    @property
23
+    def data(self):
24
+        return {
25
+            'model_id': self.model_id,
26
+            'model_name': self.model_name,
27
+            'integral': self.integral,
28
+            'has_mount': self.has_mount,
29
+        }
30
+
31
+
32
+class ProductInfo(BaseModelMixin, SexModelMixin):
33
+    model_id = models.CharField(_(u'model_id'), max_length=32, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
34
+    model_name = models.CharField(_(u'model_name'), max_length=32, blank=True, null=True, help_text=u'型号名称', db_index=True)
35
+
36
+    mount = models.CharField(_(u'mount'), max_length=32, blank=True, null=True, help_text=u'卡口', db_index=True)
37
+    code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码')
38
+    code_status = models.BooleanField(_(u'code_status'), default=False, help_text=u'机身码状态, True已使用,False未使用', db_index=True)
39
+
40
+    integral = models.IntegerField(_(u'integral'), default=0, help_text=u'积分')
41
+    integral_status = models.BooleanField(_(u'integral_status'), default=False, help_text=u'积分状态, True已积分,False未积分', db_index=True)
42
+
43
+    franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
44
+    clerk_id = models.CharField(_(u'clerk_id'), max_length=32, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
45
+
46
+    consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者名称')
47
+    consumer_sex = models.IntegerField(_(u'consumer_sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.MALE, help_text=u'消费者性别', db_index=True)
48
+    consumer_age = models.IntegerField(_(u'consumer_age'), default=0, help_text=u'消费者年龄')
49
+    consumer_phone = models.CharField(_(u'consumer_phone'), max_length=11, blank=True, null=True, help_text=u'消费者联系电话')
50
+
51
+    class Meta:
52
+        verbose_name = _(u'productinfo')
53
+        verbose_name_plural = _(u'productinfo')
54
+
55
+    def __unicode__(self):
56
+        return unicode(self.pk)
57
+
58
+    @property
59
+    def data(self):
60
+        return {
61
+            'model_id': self.model_id,
62
+            'model_name': self.model_name,
63
+            'code': self.code,
64
+        }
65
+
66
+
67
+class ProductCodeSubmitLogInfo(BaseModelMixin, SexModelMixin):
68
+    step = models.IntegerField(_(u'step'), default=1, help_text=u'提交步骤', db_index=True)
69
+
70
+    model_id = models.CharField(_(u'model_id'), max_length=32, blank=True, null=True, help_text=u'型号唯一标识', db_index=True)
71
+    model_name = models.CharField(_(u'model_name'), max_length=32, blank=True, null=True, help_text=u'型号名称', db_index=True)
72
+    mount = models.CharField(_(u'mount'), max_length=255, blank=True, null=True, help_text=u'卡口', db_index=True)
73
+    code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码')
74
+
75
+    franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
76
+    clerk_id = models.CharField(_(u'clerk_id'), max_length=32, blank=True, null=True, help_text=u'店员唯一标识', db_index=True)
77
+
78
+    consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者名称')
79
+    consumer_sex = models.IntegerField(_(u'consumer_sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.MALE, help_text=u'消费者性别', db_index=True)
80
+    consumer_age = models.IntegerField(_(u'consumer_age'), default=0, help_text=u'消费者年龄')
81
+    consumer_phone = models.CharField(_(u'consumer_phone'), max_length=11, blank=True, null=True, help_text=u'消费者联系电话')
82
+
83
+    class Meta:
84
+        verbose_name = _(u'productcodesubmitloginfo')
85
+        verbose_name_plural = _(u'productcodesubmitloginfo')
86
+
87
+    def __unicode__(self):
88
+        return unicode(self.pk)

+ 4 - 0
product/tests.py

@@ -0,0 +1,4 @@
1
+from django.test import TestCase
2
+
3
+
4
+# Create your tests here.

+ 4 - 0
product/views.py

@@ -0,0 +1,4 @@
1
+from django.shortcuts import render
2
+
3
+
4
+# Create your views here.

+ 28 - 0
utils/error/errno_utils.py

@@ -3,6 +3,34 @@
3 3
 from StatusCode import BaseStatusCode, StatusCodeField
4 4
 
5 5
 
6
+class FranchiserStatusCode(BaseStatusCode):
7
+    """ 经销商相关错误码 5000xx """
8
+    CHISER_NOT_FOUND = StatusCodeField(500001, 'Chiser Not Found', description=u'经销商不存在')
9
+
10
+
11
+class SaleclerkStatusCode(BaseStatusCode):
12
+    """ 店员相关错误码 5001xx """
13
+    CLERK_NOT_FOUND = StatusCodeField(500101, 'Clerk Not Found', description=u'店员不存在')
14
+    # 手机号
15
+    CLERK_PHONE_ALREADY_EXISTS = StatusCodeField(500105, 'Clerk Phone Already Exists', description=u'手机号已经存在')
16
+    # 状态
17
+    CLERK_ALREADY_NOT_UNVERIFIED = StatusCodeField(500110, 'Clerk Already Not Unverified', description=u'店员帐号已激活')
18
+    CLERK_NOT_ACTIVATED = StatusCodeField(500115, 'Clerk Not Activated', description=u'店员帐号未激活')
19
+
20
+
21
+class ProductModelStatusCode(BaseStatusCode):
22
+    """ 型号相关错误码 5010xx """
23
+    MODEL_NOT_FOUND = StatusCodeField(501001, 'Model Not Found', description=u'型号不存在')
24
+
25
+
26
+class ProductStatusCode(BaseStatusCode):
27
+    """ 产品相关错误码 5020xx """
28
+    PRODUCT_NOT_FOUND = StatusCodeField(502001, 'Product Not Found', description=u'产品不存在')
29
+    # 状态
30
+    PRODUCT_HAS_USED = StatusCodeField(502011, 'Product Has Used', description=u'产品已使用')
31
+    PRODUCT_NOT_USED = StatusCodeField(502012, 'Product Not Used', description=u'产品未使用')
32
+
33
+
6 34
 class LensmanStatusCode(BaseStatusCode):
7 35
     """ 摄影师相关错误码 4000xx """
8 36
     LENSMAN_NOT_FOUND = StatusCodeField(400001, 'Lensman Not Found', description=u'摄影师不存在')

pai2 - Gogs: Go Git Service

拍爱

Brightcells: fabef63211 set line_length=200 for isort vor 10 Jahren
..
migrations 102152ca4a add api lensman_photo_bought & modify api wx_order_create_api and adjust return field vor 10 Jahren
templates 4a8b4f8819 add watermark vor 11 Jahren
__init__.py 4defb80fdc gogs first init vor 11 Jahren
admin.py f72ccb1875 isort import vor 10 Jahren
models.py f72ccb1875 isort import vor 10 Jahren
serializers.py f72ccb1875 isort import vor 10 Jahren
tests.py fabef63211 set line_length=200 for isort vor 10 Jahren
urls.py 4defb80fdc gogs first init vor 11 Jahren
views.py fabef63211 set line_length=200 for isort vor 10 Jahren