@@ -304,6 +304,7 @@ def consumer_info_api(request): |
||
304 | 304 |
coupon_image=coupon.coupon_image, |
305 | 305 |
active_at=tc.utc_datetime(), |
306 | 306 |
expire_at=coupon.final_expire_at, |
307 |
+ is_coupon_admin_writeoff=coupon.is_coupon_admin_writeoff, |
|
307 | 308 |
coupon_valid_period=coupon.coupon_valid_period, |
308 | 309 |
coupon_limit_model_ids=coupon.coupon_limit_model_ids, |
309 | 310 |
coupon_from='PROMOTION', |
@@ -230,6 +230,8 @@ urlpatterns += [ |
||
230 | 230 |
url(r'^clerk/integral/list$', sale_views.clerk_integral_list_api, name='clerk_integral_list_api'), # 店员销售积分列表 |
231 | 231 |
url(r'^clerk/model/list$', sale_views.clerk_model_list_api, name='clerk_model_list_api'), |
232 | 232 |
url(r'^clerk/checkout/serialNo$', sale_views.clerk_checkout_serialNo_api, name='clerk_checkout_serialNo_api'), # 校验序列号 |
233 |
+ url(r'^clerk/query/coupon$', sale_views.clerk_query_coupon, name='clerk_query_coupon'), |
|
234 |
+ url(r'^clerk/writeoff/coupon$', sale_views.clerk_writeoff_coupon, name='clerk_writeoff_coupon'), |
|
233 | 235 |
] |
234 | 236 |
|
235 | 237 |
urlpatterns += [ |
@@ -61,6 +61,7 @@ class Command(CompatibilityBaseCommand): |
||
61 | 61 |
expire_at=tc.utc_datetime(days=365), |
62 | 62 |
coupon_valid_period=coupon.coupon_valid_period, |
63 | 63 |
coupon_limit_model_ids=coupon.coupon_limit_model_ids, |
64 |
+ is_coupon_admin_writeoff=coupon.is_coupon_admin_writeoff, |
|
64 | 65 |
) |
65 | 66 |
|
66 | 67 |
else: |
@@ -0,0 +1,45 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Generated by Django 1.11.26 on 2020-04-13 07:43 |
|
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 |
+ ('coupon', '0011_auto_20200411_2316'), |
|
12 |
+ ] |
|
13 |
+ |
|
14 |
+ operations = [ |
|
15 |
+ migrations.AddField( |
|
16 |
+ model_name='couponinfo', |
|
17 |
+ name='is_coupon_admin_writeoff', |
|
18 |
+ field=models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u662f\u7ba1\u7406\u5458\u6838\u9500', verbose_name='is_coupon_admin_writeoff'), |
|
19 |
+ ), |
|
20 |
+ migrations.AddField( |
|
21 |
+ model_name='usercouponinfo', |
|
22 |
+ name='clerk_id', |
|
23 |
+ field=models.CharField(blank=True, db_index=True, help_text='\u9500\u552e\u5458\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='admin_id'), |
|
24 |
+ ), |
|
25 |
+ migrations.AddField( |
|
26 |
+ model_name='usercouponinfo', |
|
27 |
+ name='clerk_name', |
|
28 |
+ field=models.CharField(blank=True, db_index=True, help_text='\u9500\u552e\u5458\u540d\u79f0', max_length=32, null=True, verbose_name='clerk_name'), |
|
29 |
+ ), |
|
30 |
+ migrations.AddField( |
|
31 |
+ model_name='usercouponinfo', |
|
32 |
+ name='distributor_id', |
|
33 |
+ field=models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u552f\u4e00\u6807\u8bc6', max_length=32, null=True, verbose_name='distributor_id'), |
|
34 |
+ ), |
|
35 |
+ migrations.AddField( |
|
36 |
+ model_name='usercouponinfo', |
|
37 |
+ name='distributor_name', |
|
38 |
+ field=models.CharField(blank=True, db_index=True, help_text='\u7ecf\u9500\u5546\u540d\u79f0', max_length=32, null=True, verbose_name='distributor_name'), |
|
39 |
+ ), |
|
40 |
+ migrations.AddField( |
|
41 |
+ model_name='usercouponinfo', |
|
42 |
+ name='is_coupon_admin_writeoff', |
|
43 |
+ field=models.BooleanField(db_index=True, default=True, help_text='\u662f\u5426\u662f\u7ba1\u7406\u5458\u6838\u9500', verbose_name='is_coupon_admin_writeoff'), |
|
44 |
+ ), |
|
45 |
+ ] |
@@ -33,6 +33,7 @@ class CouponInfo(BaseModelMixin): |
||
33 | 33 |
coupon_valid_period = models.IntegerField(_(u'coupon_valid_period'), default=0, help_text=_(u'维修券有效时间(单位:天)')) |
34 | 34 |
coupon_expire_at = models.DateTimeField(_(u'coupon_expire_at'), blank=True, null=True, help_text=_(u'维修券过期时间')) |
35 | 35 |
|
36 |
+ is_coupon_admin_writeoff = models.BooleanField(_(u'is_coupon_admin_writeoff'), default=True, help_text=_(u'是否是管理员核销'), db_index=True) |
|
36 | 37 |
coupon_limit_model_ids = JSONField(_(u'coupon_limit_model_ids'), blank=True, null=True, help_text=u'券限制使用 model_ids') |
37 | 38 |
|
38 | 39 |
class Meta: |
@@ -80,6 +81,12 @@ class UserCouponInfo(BaseModelMixin): |
||
80 | 81 |
has_used = models.BooleanField(_(u'has_used'), default=False, help_text=u'是否已核销', db_index=True) |
81 | 82 |
admin_id = models.CharField(_(u'admin_id'), max_length=32, blank=True, null=True, help_text=u'核销员唯一标识', db_index=True) |
82 | 83 |
used_at = models.DateTimeField(_(u'used_at'), blank=True, null=True, help_text=u'维修券核销时间') |
84 |
+ is_coupon_admin_writeoff = models.BooleanField(_(u'is_coupon_admin_writeoff'), default=True, help_text=_(u'是否是管理员核销'), db_index=True) |
|
85 |
+ |
|
86 |
+ clerk_id = models.CharField(_(u'admin_id'), max_length=32, blank=True, null=True, help_text=u'销售员唯一标识', db_index=True) |
|
87 |
+ clerk_name = models.CharField(_(u'clerk_name'), max_length=32, blank=True, null=True, help_text=u'销售员名称', db_index=True) |
|
88 |
+ distributor_id = models.CharField(_(u'distributor_id'), max_length=32, blank=True, null=True, help_text=u'经销商唯一标识', db_index=True) |
|
89 |
+ distributor_name = models.CharField(_(u'distributor_name'), max_length=32, blank=True, null=True, help_text=u'经销商名称', db_index=True) |
|
83 | 90 |
|
84 | 91 |
coupon_from = models.CharField(_(u'coupon_from'), default='MEMBER_BENEFITS', max_length=32, blank=True, null=True, help_text=u'劵来源', db_index=True) |
85 | 92 |
activity_id = models.CharField(_(u'activity_id'), max_length=32, blank=True, null=True, help_text=u'活动唯一标识', db_index=True) |
@@ -12,11 +12,12 @@ from TimeConvert import TimeConvert as tc |
||
12 | 12 |
from account.models import UserInfo |
13 | 13 |
from integral.models import SaleclerkIntegralIncomeExpensesInfo, SaleclerkSubmitLogInfo |
14 | 14 |
from logs.models import MchInfoEncryptLogInfo |
15 |
+from coupon.models import UserCouponInfo |
|
15 | 16 |
from mch.models import BrandInfo, ConsumeInfoSubmitLogInfo, DistributorInfo, ModelInfo, SaleclerkInfo |
16 | 17 |
from statistic.models import (DistributorSaleStatisticInfo, ModelSaleStatisticInfo, ProvinceSaleStatisticInfo, |
17 | 18 |
SaleclerkSaleStatisticInfo, SaleStatisticInfo) |
18 | 19 |
from utils.error.errno_utils import (ProductBrandStatusCode, ProductDistributorStatusCode, ProductMachineStatusCode, |
19 |
- ProductModelStatusCode, SaleclerkStatusCode) |
|
20 |
+ ProductModelStatusCode, SaleclerkStatusCode, CouponStatusCode) |
|
20 | 21 |
import os,sys,string |
21 | 22 |
|
22 | 23 |
|
@@ -420,6 +421,94 @@ def clerk_model_list_api(request): |
||
420 | 421 |
|
421 | 422 |
|
422 | 423 |
@logit |
424 |
+def clerk_query_coupon(request): |
|
425 |
+ brandID = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_PK) |
|
426 |
+ user_id = request.POST.get('user_id', '') |
|
427 |
+ user_coupon_id = request.POST.get('user_coupon_id', '') |
|
428 |
+ |
|
429 |
+ try: |
|
430 |
+ user = UserInfo.objects.get(user_id=user_id, status=True) |
|
431 |
+ except UserInfo.DoesNotExist: |
|
432 |
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND) |
|
433 |
+ |
|
434 |
+ try: |
|
435 |
+ brand = BrandInfo.objects.get(pk=brandID) |
|
436 |
+ except BrandInfo.DoesNotExist: |
|
437 |
+ brand = None |
|
438 |
+ except ValueError: |
|
439 |
+ brand = None |
|
440 |
+ |
|
441 |
+ if not brand: |
|
442 |
+ try: |
|
443 |
+ brand = BrandInfo.objects.get(brand_id=brandID) |
|
444 |
+ except BrandInfo.DoesNotExist: |
|
445 |
+ return response(ProductBrandStatusCode.BRAND_NOT_FOUND) |
|
446 |
+ |
|
447 |
+ try: |
|
448 |
+ clerk = SaleclerkInfo.objects.get(brand_id=brand.brand_id, unionid=user.unionid, status=True) |
|
449 |
+ except SaleclerkInfo.DoesNotExist: |
|
450 |
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND) |
|
451 |
+ |
|
452 |
+ try: |
|
453 |
+ user_coupon = UserCouponInfo.objects.get(user_coupon_id=user_coupon_id) |
|
454 |
+ except UserCouponInfo.DoesNotExist: |
|
455 |
+ return response(CouponStatusCode.COUPON_NOT_FOUND) |
|
456 |
+ |
|
457 |
+ return response(200, data={ |
|
458 |
+ 'user_coupon': user_coupon.data |
|
459 |
+ }) |
|
460 |
+ |
|
461 |
+@logit |
|
462 |
+def clerk_writeoff_coupon(request): |
|
463 |
+ brandID = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_PK) |
|
464 |
+ user_id = request.POST.get('user_id', '') |
|
465 |
+ user_coupon_id = request.POST.get('user_coupon_id', '') |
|
466 |
+ |
|
467 |
+ try: |
|
468 |
+ user = UserInfo.objects.get(user_id=user_id, status=True) |
|
469 |
+ except UserInfo.DoesNotExist: |
|
470 |
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND) |
|
471 |
+ |
|
472 |
+ try: |
|
473 |
+ brand = BrandInfo.objects.get(pk=brandID) |
|
474 |
+ except BrandInfo.DoesNotExist: |
|
475 |
+ brand = None |
|
476 |
+ except ValueError: |
|
477 |
+ brand = None |
|
478 |
+ |
|
479 |
+ if not brand: |
|
480 |
+ try: |
|
481 |
+ brand = BrandInfo.objects.get(brand_id=brandID) |
|
482 |
+ except BrandInfo.DoesNotExist: |
|
483 |
+ return response(ProductBrandStatusCode.BRAND_NOT_FOUND) |
|
484 |
+ |
|
485 |
+ try: |
|
486 |
+ clerk = SaleclerkInfo.objects.get(brand_id=brand.brand_id, unionid=user.unionid, status=True) |
|
487 |
+ except SaleclerkInfo.DoesNotExist: |
|
488 |
+ return response(SaleclerkStatusCode.CLERK_NOT_FOUND) |
|
489 |
+ |
|
490 |
+ try: |
|
491 |
+ user_coupon = UserCouponInfo.objects.get(user_coupon_id=user_coupon_id) |
|
492 |
+ if user_coupon.has_used: |
|
493 |
+ return response(CouponStatusCode.COUPON_HAS_USED) |
|
494 |
+ elif user_coupon.is_coupon_admin_writeoff: |
|
495 |
+ return response(CouponStatusCode.COUPON_PERMISSION_DENIED) |
|
496 |
+ elif not user_coupon.has_expired: |
|
497 |
+ user_coupon.clerk_id = clerk.clerk_id |
|
498 |
+ user_coupon.clerk_name = clerk.clerk_name |
|
499 |
+ user_coupon.distributor_id = clerk.distributor_id |
|
500 |
+ user_coupon.distributor_name = clerk.distributor_name |
|
501 |
+ user_coupon.has_used = True |
|
502 |
+ user_coupon.used_at = tc.utc_datetime() |
|
503 |
+ user_coupon.save() |
|
504 |
+ else: |
|
505 |
+ return response(CouponStatusCode.COUPON_EXPIRED) |
|
506 |
+ except UserCouponInfo.DoesNotExist: |
|
507 |
+ return response(CouponStatusCode.COUPON_NOT_FOUND) |
|
508 |
+ |
|
509 |
+ return response(200, 'Write Off Coupon Success', u'劵核销成功') |
|
510 |
+ |
|
511 |
+@logit |
|
423 | 512 |
def clerk_checkout_serialNo_api(request): |
424 | 513 |
brandID = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_PK) |
425 | 514 |
user_id = request.POST.get('user_id', '') |
@@ -255,3 +255,10 @@ class TokenStatusCode(BaseStatusCode): |
||
255 | 255 |
class PermissionStatusCode(BaseStatusCode): |
256 | 256 |
""" 4099xx 权限相关错误码 """ |
257 | 257 |
PERMISSION_DENIED = StatusCodeField(409900, 'Permission Denied', description=u'权限不足') |
258 |
+ |
|
259 |
+class CouponStatusCode(BaseStatusCode): |
|
260 |
+ """ 4050xx 优惠劵相关错误码 """ |
|
261 |
+ COUPON_NOT_FOUND = StatusCodeField(405001, 'Coupon Not Found', description=u'劵不存在') |
|
262 |
+ COUPON_EXPIRED = StatusCodeField(405002, 'Coupon Expired', description=u'劵已过期') |
|
263 |
+ COUPON_PERMISSION_DENIED = StatusCodeField(405003, 'Permission Denied', description=u'核销劵权限不足') |
|
264 |
+ COUPON_HAS_USED = StatusCodeField(405004, 'Coupon Has Used', description=u'劵已核销') |