@@ -0,0 +1,20 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.9 on 2018-03-08 06:40 |
|
| 3 |
+from __future__ import unicode_literals |
|
| 4 |
+ |
|
| 5 |
+from django.db import migrations, models |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ dependencies = [ |
|
| 11 |
+ ('account', '0027_franchiserinfo_saleclerkinfo'),
|
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.AddField( |
|
| 16 |
+ model_name='saleclerkinfo', |
|
| 17 |
+ name='total_integral', |
|
| 18 |
+ field=models.IntegerField(default=0, help_text='\u5168\u90e8\u79ef\u5206', verbose_name='total_integral'), |
|
| 19 |
+ ), |
|
| 20 |
+ ] |
@@ -475,6 +475,7 @@ class SaleclerkInfo(BaseModelMixin, SexModelMixin): |
||
| 475 | 475 |
unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 UnionID', db_index=True, unique=True) |
| 476 | 476 |
|
| 477 | 477 |
integral = models.IntegerField(_(u'integral'), default=0, help_text=u'积分') |
| 478 |
+ total_integral = models.IntegerField(_(u'total_integral'), default=0, help_text=u'全部积分') |
|
| 478 | 479 |
|
| 479 | 480 |
user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'用户状态', db_index=True) |
| 480 | 481 |
refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因') |
@@ -1,15 +1,23 @@ |
||
| 1 | 1 |
# -*- coding: utf-8 -*- |
| 2 | 2 |
|
| 3 |
+from djadmin import ReadOnlyModelAdmin |
|
| 3 | 4 |
from django.contrib import admin |
| 4 | 5 |
|
| 5 |
-from integral.models import SaleclerkIntegralIncomeExpensesInfo |
|
| 6 |
+from integral.models import SaleclerkIntegralIncomeExpensesInfo, SaleclerkSubmitLogInfo |
|
| 6 | 7 |
|
| 7 | 8 |
|
| 8 |
-class SaleclerkIntegralIncomeExpensesInfoAdmin(admin.ModelAdmin): |
|
| 9 |
- readonly_fields = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral')
|
|
| 9 |
+class SaleclerkIntegralIncomeExpensesInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin): |
|
| 10 | 10 |
list_display = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral', 'remark', 'status', 'created_at', 'updated_at')
|
| 11 |
- search_fields = ('code', 'remark')
|
|
| 12 | 11 |
list_filter = ('franchiser_id', 'type', 'status')
|
| 12 |
+ readonly_fields = ('franchiser_id', 'clerk_id', 'type', 'code', 'integral', 'left_integral')
|
|
| 13 |
+ search_fields = ('code', 'remark')
|
|
| 14 |
+ |
|
| 15 |
+ |
|
| 16 |
+class SaleclerkSubmitLogInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin): |
|
| 17 |
+ list_display = ('franchiser_id', 'clerk_id', 'code', 'remark', 'status', 'created_at', 'updated_at')
|
|
| 18 |
+ list_filter = ('franchiser_id', 'status')
|
|
| 19 |
+ search_fields = ('code', 'remark')
|
|
| 13 | 20 |
|
| 14 | 21 |
|
| 15 | 22 |
admin.site.register(SaleclerkIntegralIncomeExpensesInfo, SaleclerkIntegralIncomeExpensesInfoAdmin) |
| 23 |
+admin.site.register(SaleclerkSubmitLogInfo, SaleclerkSubmitLogInfoAdmin) |
@@ -0,0 +1,63 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+# Generated by Django 1.11.9 on 2018-03-08 06:40 |
|
| 3 |
+from __future__ import unicode_literals |
|
| 4 |
+ |
|
| 5 |
+from django.db import migrations, models |
|
| 6 |
+import models_ext.fileext |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+class Migration(migrations.Migration): |
|
| 10 |
+ |
|
| 11 |
+ dependencies = [ |
|
| 12 |
+ ('integral', '0001_initial'),
|
|
| 13 |
+ ] |
|
| 14 |
+ |
|
| 15 |
+ operations = [ |
|
| 16 |
+ migrations.CreateModel( |
|
| 17 |
+ name='SaleclerkSubmitLogInfo', |
|
| 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 |
+ ('code', models.CharField(blank=True, db_index=True, help_text='\u673a\u8eab\u7801', max_length=32, null=True, verbose_name='code')),
|
|
| 26 |
+ ('consumer_name', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u59d3\u540d', max_length=32, null=True, verbose_name='consumer_name')),
|
|
| 27 |
+ ('consumer_phone', models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u624b\u673a\u53f7', max_length=32, null=True, verbose_name='consumer_phone')),
|
|
| 28 |
+ ('lat', models.FloatField(default=1.0, help_text='\u7eac\u5ea6', verbose_name='lat')),
|
|
| 29 |
+ ('lon', models.FloatField(default=1.0, help_text='\u7ecf\u5ea6', verbose_name='lon')),
|
|
| 30 |
+ ('image', models.FileField(blank=True, help_text='\u56fe\u7247', null=True, upload_to=models_ext.fileext.upload_path, verbose_name='image')),
|
|
| 31 |
+ ('remark', models.CharField(blank=True, help_text='\u5907\u6ce8', max_length=255, null=True, verbose_name='remark')),
|
|
| 32 |
+ ], |
|
| 33 |
+ options={
|
|
| 34 |
+ 'verbose_name': 'saleclerksubmitloginfo', |
|
| 35 |
+ 'verbose_name_plural': 'saleclerksubmitloginfo', |
|
| 36 |
+ }, |
|
| 37 |
+ ), |
|
| 38 |
+ migrations.AddField( |
|
| 39 |
+ model_name='saleclerkintegralincomeexpensesinfo', |
|
| 40 |
+ name='consumer_name', |
|
| 41 |
+ field=models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u59d3\u540d', max_length=32, null=True, verbose_name='consumer_name'), |
|
| 42 |
+ ), |
|
| 43 |
+ migrations.AddField( |
|
| 44 |
+ model_name='saleclerkintegralincomeexpensesinfo', |
|
| 45 |
+ name='consumer_phone', |
|
| 46 |
+ field=models.CharField(blank=True, help_text='\u6d88\u8d39\u8005\u624b\u673a\u53f7', max_length=32, null=True, verbose_name='consumer_phone'), |
|
| 47 |
+ ), |
|
| 48 |
+ migrations.AddField( |
|
| 49 |
+ model_name='saleclerkintegralincomeexpensesinfo', |
|
| 50 |
+ name='image', |
|
| 51 |
+ field=models.FileField(blank=True, help_text='\u56fe\u7247', null=True, upload_to=models_ext.fileext.upload_path, verbose_name='image'), |
|
| 52 |
+ ), |
|
| 53 |
+ migrations.AddField( |
|
| 54 |
+ model_name='saleclerkintegralincomeexpensesinfo', |
|
| 55 |
+ name='lat', |
|
| 56 |
+ field=models.FloatField(default=1.0, help_text='\u7eac\u5ea6', verbose_name='lat'), |
|
| 57 |
+ ), |
|
| 58 |
+ migrations.AddField( |
|
| 59 |
+ model_name='saleclerkintegralincomeexpensesinfo', |
|
| 60 |
+ name='lon', |
|
| 61 |
+ field=models.FloatField(default=1.0, help_text='\u7ecf\u5ea6', verbose_name='lon'), |
|
| 62 |
+ ), |
|
| 63 |
+ ] |
@@ -2,7 +2,7 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.db import models |
| 4 | 4 |
from django.utils.translation import ugettext_lazy as _ |
| 5 |
-from models_ext import BaseModelMixin |
|
| 5 |
+from models_ext import BaseModelMixin, upload_path |
|
| 6 | 6 |
|
| 7 | 7 |
|
| 8 | 8 |
class SaleclerkIntegralIncomeExpensesInfo(BaseModelMixin): |
@@ -22,6 +22,15 @@ class SaleclerkIntegralIncomeExpensesInfo(BaseModelMixin): |
||
| 22 | 22 |
type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别', db_index=True) |
| 23 | 23 |
|
| 24 | 24 |
code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码', db_index=True) |
| 25 |
+ |
|
| 26 |
+ consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者姓名') |
|
| 27 |
+ consumer_phone = models.CharField(_(u'consumer_phone'), max_length=32, blank=True, null=True, help_text=u'消费者手机号') |
|
| 28 |
+ |
|
| 29 |
+ lat = models.FloatField(_(u'lat'), default=1.0, help_text=u'纬度') |
|
| 30 |
+ lon = models.FloatField(_(u'lon'), default=1.0, help_text=u'经度') |
|
| 31 |
+ |
|
| 32 |
+ image = models.FileField(_(u'image'), upload_to=upload_path, blank=True, null=True, help_text=u'图片') |
|
| 33 |
+ |
|
| 25 | 34 |
integral = models.IntegerField(_(u'integral'), default=0, help_text=u'增减积分') |
| 26 | 35 |
left_integral = models.IntegerField(_(u'left_integral'), default=0, help_text=u'积分增减后数量(分)') |
| 27 | 36 |
|
@@ -33,3 +42,27 @@ class SaleclerkIntegralIncomeExpensesInfo(BaseModelMixin): |
||
| 33 | 42 |
|
| 34 | 43 |
def __unicode__(self): |
| 35 | 44 |
return unicode(self.pk) |
| 45 |
+ |
|
| 46 |
+ |
|
| 47 |
+class SaleclerkSubmitLogInfo(BaseModelMixin): |
|
| 48 |
+ franchiser_id = models.CharField(_(u'franchiser_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True) |
|
| 49 |
+ clerk_id = models.CharField(_(u'clerk_id'), max_length=32, blank=True, null=True, help_text=u'店员唯一标识', db_index=True) |
|
| 50 |
+ |
|
| 51 |
+ code = models.CharField(_(u'code'), max_length=32, blank=True, null=True, help_text=u'机身码', db_index=True) |
|
| 52 |
+ |
|
| 53 |
+ consumer_name = models.CharField(_(u'consumer_name'), max_length=32, blank=True, null=True, help_text=u'消费者姓名') |
|
| 54 |
+ consumer_phone = models.CharField(_(u'consumer_phone'), max_length=32, blank=True, null=True, help_text=u'消费者手机号') |
|
| 55 |
+ |
|
| 56 |
+ lat = models.FloatField(_(u'lat'), default=1.0, help_text=u'纬度') |
|
| 57 |
+ lon = models.FloatField(_(u'lon'), default=1.0, help_text=u'经度') |
|
| 58 |
+ |
|
| 59 |
+ image = models.FileField(_(u'image'), upload_to=upload_path, blank=True, null=True, help_text=u'图片') |
|
| 60 |
+ |
|
| 61 |
+ remark = models.CharField(_(u'remark'), max_length=255, blank=True, null=True, help_text=u'备注') |
|
| 62 |
+ |
|
| 63 |
+ class Meta: |
|
| 64 |
+ verbose_name = _(u'saleclerksubmitloginfo') |
|
| 65 |
+ verbose_name_plural = _(u'saleclerksubmitloginfo') |
|
| 66 |
+ |
|
| 67 |
+ def __unicode__(self): |
|
| 68 |
+ return unicode(self.pk) |
@@ -9,7 +9,7 @@ from django_response import response |
||
| 9 | 9 |
from logit import logit |
| 10 | 10 |
|
| 11 | 11 |
from account.models import SaleclerkInfo |
| 12 |
-from integral.models import SaleclerkIntegralIncomeExpensesInfo |
|
| 12 |
+from integral.models import SaleclerkIntegralIncomeExpensesInfo, SaleclerkSubmitLogInfo |
|
| 13 | 13 |
from product.models import ProductCodeSubmitLogInfo, ProductInfo, ProductModelInfo |
| 14 | 14 |
from utils.error.errno_utils import ProductModelStatusCode, ProductStatusCode, SaleclerkStatusCode |
| 15 | 15 |
|
@@ -47,9 +47,52 @@ def clerk_sale_submit_api(request): |
||
| 47 | 47 |
|
| 48 | 48 |
file_path = request.POST.get('file_path', '')
|
| 49 | 49 |
|
| 50 |
+ try: |
|
| 51 |
+ clerk = SaleclerkInfo.objects.get(user_id=user_id) |
|
| 52 |
+ except SaleclerkInfo.DoesNotExist: |
|
| 53 |
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND) |
|
| 54 |
+ |
|
| 55 |
+ # 店员提交记录 |
|
| 56 |
+ SaleclerkSubmitLogInfo.objects.create( |
|
| 57 |
+ franchiser_id=clerk.franchiser_id, |
|
| 58 |
+ clerk_id=clerk.clerk_id, |
|
| 59 |
+ code=serialNo, |
|
| 60 |
+ consumer_name=consumer_name, |
|
| 61 |
+ consumer_phone=consumer_phone, |
|
| 62 |
+ lat=lat, |
|
| 63 |
+ lon=lon, |
|
| 64 |
+ image=file_path, |
|
| 65 |
+ ) |
|
| 66 |
+ |
|
| 67 |
+ if SaleclerkIntegralIncomeExpensesInfo.objects.filter(code=serialNo, status=True).exists(): |
|
| 68 |
+ return response(SaleclerkStatusCode.DUPLICATE_SUBMIT) |
|
| 69 |
+ |
|
| 70 |
+ # 店员积分 |
|
| 71 |
+ # TODO: 序列号 vs. 积分 |
|
| 72 |
+ integral = 100 |
|
| 73 |
+ |
|
| 74 |
+ clerk.integral += integral |
|
| 75 |
+ clerk.total_integral += integral |
|
| 76 |
+ clerk.save() |
|
| 77 |
+ |
|
| 78 |
+ # 店员积分记录 |
|
| 79 |
+ SaleclerkIntegralIncomeExpensesInfo.objects.create( |
|
| 80 |
+ franchiser_id=clerk.franchiser_id, |
|
| 81 |
+ clerk_id=clerk.clerk_id, |
|
| 82 |
+ type=SaleclerkIntegralIncomeExpensesInfo.INCOME, |
|
| 83 |
+ code=serialNo, |
|
| 84 |
+ consumer_name=consumer_name, |
|
| 85 |
+ consumer_phone=consumer_phone, |
|
| 86 |
+ lat=lat, |
|
| 87 |
+ lon=lon, |
|
| 88 |
+ image=file_path, |
|
| 89 |
+ integral=integral, |
|
| 90 |
+ left_integral=clerk.total_integral, |
|
| 91 |
+ ) |
|
| 92 |
+ |
|
| 50 | 93 |
return response(200, data={
|
| 51 |
- 'integral': 123, |
|
| 52 |
- 'total_integral': 12345, |
|
| 94 |
+ 'integral': integral, |
|
| 95 |
+ 'total_integral': clerk.integral, |
|
| 53 | 96 |
}) |
| 54 | 97 |
|
| 55 | 98 |
|
@@ -16,6 +16,8 @@ class SaleclerkStatusCode(BaseStatusCode): |
||
| 16 | 16 |
# 状态 |
| 17 | 17 |
CLERK_ALREADY_NOT_UNVERIFIED = StatusCodeField(500110, 'Clerk Already Not Unverified', description=u'店员帐号已激活') |
| 18 | 18 |
CLERK_NOT_ACTIVATED = StatusCodeField(500115, 'Clerk Not Activated', description=u'店员帐号未激活') |
| 19 |
+ # 上传 |
|
| 20 |
+ DUPLICATE_SUBMIT = StatusCodeField(500199, 'Duplicate Submit', description=u'重复提交') |
|
| 19 | 21 |
|
| 20 | 22 |
|
| 21 | 23 |
class ProductModelStatusCode(BaseStatusCode): |