amron
  • requirements_dj.txt 522B

      Django==1.11.23 django-admin==1.3.2 django-cors-headers==3.0.2 django-curtail-uuid==1.0.4 django-detect==1.0.15 django-file==1.0.3 django-ip==1.0.2 django-json-render==1.0.3 django-json-response==1.1.5 django-logit==1.1.3 django-mobi2==1.0.2 django-models-ext==1.1.9 django-multidomain==1.1.4 django-paginator2==1.0.4 django-query==1.0.5 django-redis-connector==1.0.1 django-response==1.1.1 django-rlog==1.0.7 django-shortuuidfield==0.1.3 django-six==1.0.4 django-uniapi==1.0.5 django-we==1.4.2 djangorestframework==3.9.4
    Update Kodo · 627187a7d7 - Gogs: Go Git Service

    Update Kodo

    Brightcells %!s(int64=8) %!d(string=hace) años
    padre
    commit
    627187a7d7

    + 24 - 6
    account/admin.py

    @@ -5,7 +5,8 @@ from djadmin import ChangeOnlyModelAdmin, ReadOnlyModelAdmin
    5 5
     from django.contrib import admin
    6 6
     from django.db import transaction
    7 7
     
    8
    -from account.models import LensmanIncomeExpensesInfo, LensmanInfo, TourGuideInfo, UserIncomeExpensesInfo, UserInfo
    8
    +from account.models import (FranchiserInfo, LensmanIncomeExpensesInfo, LensmanInfo, SaleclerkInfo, TourGuideInfo,
    9
    +                            UserIncomeExpensesInfo, UserInfo)
    9 10
     
    10 11
     
    11 12
     class LensmanInfoAdmin(ChangeOnlyModelAdmin, admin.ModelAdmin):
    @@ -104,8 +105,25 @@ class UserIncomeExpensesInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):
    104 105
         list_filter = ('type', 'status')
    105 106
     
    106 107
     
    107
    -admin.site.register(LensmanInfo, LensmanInfoAdmin)
    108
    -admin.site.register(LensmanIncomeExpensesInfo, LensmanIncomeExpensesInfoAdmin)
    109
    -admin.site.register(TourGuideInfo, TourGuideInfoAdmin)
    110
    -admin.site.register(UserInfo, UserInfoAdmin)
    111
    -admin.site.register(UserIncomeExpensesInfo, UserIncomeExpensesInfoAdmin)
    108
    +class FranchiserInfoAdmin(admin.ModelAdmin):
    109
    +    readonly_fields = ('franchiser_id', )
    110
    +    list_display = ('franchiser_id', 'franchiser_name', 'franchiser_addr', 'franchiser_phone', 'franchiser_boss_name', 'franchiser_boss_phone', 'status', 'created_at', 'updated_at')
    111
    +    search_fields = ('franchiser_id', 'franchiser_name', 'franchiser_addr', 'franchiser_phone', 'franchiser_boss_name', 'franchiser_boss_phone')
    112
    +    list_filter = ('status', )
    113
    +
    114
    +
    115
    +class SaleclerkInfoAdmin(admin.ModelAdmin):
    116
    +    readonly_fields = ('franchiser_id', )
    117
    +    list_display = ('franchiser_id', 'clerk_id', 'clerk_name', 'clerk_sex', 'clerk_phone', 'user_status', 'status', 'created_at', 'updated_at')
    118
    +    search_fields = ('franchiser_id', 'clerk_id', 'clerk_name', 'clerk_phone')
    119
    +    list_filter = ('user_status', 'status')
    120
    +
    121
    +
    122
    +# admin.site.register(LensmanInfo, LensmanInfoAdmin)
    123
    +# admin.site.register(LensmanIncomeExpensesInfo, LensmanIncomeExpensesInfoAdmin)
    124
    +# admin.site.register(TourGuideInfo, TourGuideInfoAdmin)
    125
    +# admin.site.register(UserInfo, UserInfoAdmin)
    126
    +# admin.site.register(UserIncomeExpensesInfo, UserIncomeExpensesInfoAdmin)
    127
    +
    128
    +admin.site.register(FranchiserInfo, FranchiserInfoAdmin)
    129
    +admin.site.register(SaleclerkInfo, SaleclerkInfoAdmin)

    + 60 - 0
    account/migrations/0027_franchiserinfo_saleclerkinfo.py

    @@ -0,0 +1,60 @@
    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
    +    dependencies = [
    12
    +        ('account', '0026_auto_20180103_0446'),
    13
    +    ]
    14
    +
    15
    +    operations = [
    16
    +        migrations.CreateModel(
    17
    +            name='FranchiserInfo',
    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', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
    24
    +                ('franchiser_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=32, null=True, verbose_name='franchiser_name')),
    25
    +                ('franchiser_addr', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u5730\u5740', max_length=32, null=True, verbose_name='franchiser_addr')),
    26
    +                ('franchiser_phone', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u8054\u7cfb\u7535\u8bdd', max_length=11, null=True, verbose_name='franchiser_phone')),
    27
    +                ('franchiser_boss_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u8001\u677f\u540d\u79f0', max_length=32, null=True, verbose_name='franchiser_boss_name')),
    28
    +                ('franchiser_boss_phone', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u8001\u677f\u8054\u7cfb\u7535\u8bdd', max_length=11, null=True, verbose_name='franchiser_boss_phone')),
    29
    +            ],
    30
    +            options={
    31
    +                'verbose_name': '\u7ecf\u9500\u5546\u4fe1\u606f\u8868',
    32
    +                'verbose_name_plural': '\u7ecf\u9500\u5546\u4fe1\u606f\u8868',
    33
    +            },
    34
    +        ),
    35
    +        migrations.CreateModel(
    36
    +            name='SaleclerkInfo',
    37
    +            fields=[
    38
    +                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    39
    +                ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')),
    40
    +                ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
    41
    +                ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
    42
    +                ('sex', models.BooleanField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='Sex', verbose_name='sex')),
    43
    +                ('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')),
    44
    +                ('franchiser_name', models.CharField(blank=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=32, null=True, verbose_name='franchiser_name')),
    45
    +                ('clerk_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='\u5e97\u5458\u552f\u4e00\u6807\u8bc6', max_length=22, unique=True)),
    46
    +                ('clerk_name', models.CharField(blank=True, help_text='\u5e97\u5458\u540d\u79f0', max_length=32, null=True, verbose_name='clerk_name')),
    47
    +                ('clerk_sex', models.IntegerField(choices=[(1, '\u7537'), (0, '\u5973')], db_index=True, default=1, help_text='\u5e97\u5458\u6027\u522b', verbose_name='clerk_sex')),
    48
    +                ('clerk_phone', models.CharField(blank=True, help_text='\u5e97\u5458\u8054\u7cfb\u7535\u8bdd', max_length=11, null=True, verbose_name='clerk_phone')),
    49
    +                ('openid', models.CharField(blank=True, db_index=True, help_text='\u5fae\u4fe1 OpenID', max_length=32, null=True, unique=True, verbose_name='openid')),
    50
    +                ('unionid', models.CharField(blank=True, db_index=True, help_text='\u5fae\u4fe1 UnionID', max_length=32, null=True, unique=True, verbose_name='unionid')),
    51
    +                ('integral', models.IntegerField(default=0, help_text='\u79ef\u5206', verbose_name='integral')),
    52
    +                ('user_status', models.IntegerField(choices=[(-1, '\u5df2\u62d2\u7edd'), (0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664'), (10, '\u5df2\u5206\u914d')], db_index=True, default=0, help_text='\u7528\u6237\u72b6\u6001', verbose_name='user_status')),
    53
    +                ('refused_reason', models.TextField(blank=True, help_text='\u5ba1\u6838\u62d2\u7edd\u539f\u56e0', null=True, verbose_name='refused_reason')),
    54
    +            ],
    55
    +            options={
    56
    +                'verbose_name': 'saleclerkinfo',
    57
    +                'verbose_name_plural': 'saleclerkinfo',
    58
    +            },
    59
    +        ),
    60
    +    ]

    + 79 - 1
    account/models.py

    @@ -3,7 +3,8 @@
    3 3
     from django.db import models
    4 4
     from django.utils.translation import ugettext_lazy as _
    5 5
     from jsonfield import JSONField
    6
    -from models_ext import BaseModelMixin
    6
    +from models_ext import BaseModelMixin, SexModelMixin
    7
    +from shortuuidfield import ShortUUIDField
    7 8
     
    8 9
     from pai2.basemodels import LensmanTypeBoolMixin, LensmanTypeMixin
    9 10
     
    @@ -420,3 +421,80 @@ class UserIncomeExpensesInfo(BaseModelMixin):
    420 421
     
    421 422
         def __unicode__(self):
    422 423
             return unicode(self.pk)
    424
    +
    425
    +
    426
    +class FranchiserInfo(BaseModelMixin):
    427
    +    franchiser_id = ShortUUIDField(_(u'franchiser_id'), max_length=32, help_text=u'经销商唯一标识', db_index=True, unique=True)
    428
    +    franchiser_name = models.CharField(_(u'franchiser_name'), max_length=32, blank=True, null=True, help_text=u'经销商名称')
    429
    +    franchiser_addr = models.CharField(_(u'franchiser_addr'), max_length=32, blank=True, null=True, help_text=u'经销商地址')
    430
    +    franchiser_phone = models.CharField(_(u'franchiser_phone'), max_length=11, blank=True, null=True, help_text=u'经销商联系电话')
    431
    +    franchiser_boss_name = models.CharField(_(u'franchiser_boss_name'), max_length=32, blank=True, null=True, help_text=u'经销商老板名称')
    432
    +    franchiser_boss_phone = models.CharField(_(u'franchiser_boss_phone'), max_length=11, blank=True, null=True, help_text=u'经销商老板联系电话')
    433
    +
    434
    +    class Meta:
    435
    +        verbose_name = _(u'经销商信息表')
    436
    +        verbose_name_plural = _(u'经销商信息表')
    437
    +
    438
    +    def __unicode__(self):
    439
    +        return unicode(self.pk)
    440
    +
    441
    +    @property
    442
    +    def data(self):
    443
    +        return {
    444
    +            'franchiser_id': self.franchiser_id,
    445
    +            'franchiser_name': self.franchiser_name,
    446
    +        }
    447
    +
    448
    +
    449
    +class SaleclerkInfo(BaseModelMixin, SexModelMixin):
    450
    +    REFUSED = -1
    451
    +    UNVERIFIED = 0
    452
    +    ACTIVATED = 1
    453
    +    DISABLED = 2
    454
    +    DELETED = 3
    455
    +    ASSIGN = 10
    456
    +
    457
    +    USER_STATUS = (
    458
    +        (REFUSED, u'已拒绝'),
    459
    +        (UNVERIFIED, u'未验证'),
    460
    +        (ACTIVATED, u'已激活'),
    461
    +        (DISABLED, u'已禁用'),
    462
    +        (DELETED, u'已删除'),
    463
    +        (ASSIGN, u'已分配'),
    464
    +    )
    465
    +
    466
    +    franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True)
    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'摄影师不存在')

    kodo - Gogs: Go Git Service

    説明なし

    Brightcells: afd07e5389 Add api box_program_version_api 9 年 前
    ..
    __init__.py afd07e5389 Add api box_program_version_api 9 年 前
    rbox_program_version.py afd07e5389 Add api box_program_version_api 9 年 前