views.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. # coding=utf-8
  2. from rest_framework.views import APIView
  3. from django.db.models import Q
  4. import traceback
  5. import datetime
  6. from django.db import transaction
  7. from rest_framework.serializers import ValidationError
  8. from django.utils import timezone
  9. from rest_framework.decorators import action
  10. from utils.permission import isLogin, permission_required, check_permission
  11. from utils.custom_modelviewset import CustomModelViewSet
  12. from utils import response_ok, response_error
  13. from utils.exceptions import CustomError
  14. from apps.log.models import BizLog
  15. from apps.option.models import Option
  16. from apps.option.serializers import OptionComboboxSerializer
  17. from .models import ReportCustomer, NewCustomer, Review, NewCustomerRemind
  18. from .serializers import ReportCustomerSerializer, NewCustomerSerializer, ReviewSerializer
  19. from .filters import ReportCustomerFilter, NewCustomerFilter, ReviewFilter
  20. from django.contrib.auth import get_user_model
  21. from apps.order.models import ProgressDetails
  22. from apps.order.serializers import Order, OrderSerializer
  23. from apps.upload.models import Upload
  24. User = get_user_model()
  25. class ReportCustomerViewSet(CustomModelViewSet):
  26. permission_classes = [isLogin]
  27. queryset = ReportCustomer.objects.filter()
  28. serializer_class = ReportCustomerSerializer
  29. @permission_required('customer.view_report_customer')
  30. def filter_queryset(self, queryset):
  31. queryset = queryset.filter(
  32. Q(store_id__in=self.request.user.get_manager_range()) |
  33. Q(create_user=self.request.user))
  34. f = ReportCustomerFilter(self.request.GET, queryset=queryset)
  35. return f.qs
  36. @permission_required('customer.add_report_customer')
  37. def perform_create(self, serializer):
  38. super(ReportCustomerViewSet, self).perform_create(serializer)
  39. instance = serializer.instance
  40. validated_data = serializer.validated_data
  41. BizLog.objects.addnew(self.request.user, BizLog.INSERT,
  42. u'添加客户报备[%s],id=%d' % (instance.name, instance.id), validated_data)
  43. @permission_required('customer.add_report_customer')
  44. def perform_update(self, serializer):
  45. super(ReportCustomerViewSet, self).perform_update(serializer)
  46. instance = serializer.instance
  47. validated_data = serializer.validated_data
  48. BizLog.objects.addnew(self.request.user, BizLog.UPDATE,
  49. u'修改客户报备[%s],id=%d' % (instance.name, instance.id), validated_data)
  50. @permission_required('customer.delete_report_customer')
  51. def perform_destroy(self, instance):
  52. BizLog.objects.addnew(self.request.user, BizLog.DELETE,
  53. u'删除客户报备[%s],id=%d' % (instance.name, instance.id))
  54. super(ReportCustomerViewSet, self).perform_destroy(instance)
  55. @action(methods=['post'], detail=True)
  56. def dispatch_customer(self, request, pk):
  57. check_permission(request, 'customer.check_report_customer')
  58. # 报备客户审核 分配
  59. user_id = request.POST.get('user')
  60. try:
  61. with transaction.atomic():
  62. instance = ReportCustomer.objects.filter(id=pk).first()
  63. if not instance:
  64. raise CustomError('当前客户报备信息有误,请刷新重试!')
  65. instance.check_user = self.request.user
  66. instance.report_status = ReportCustomer.CHECKED
  67. instance.check_time = timezone.now()
  68. instance.save()
  69. BizLog.objects.addnew(request.user, BizLog.INSERT,
  70. u'分配客户报备[%s],id=%d' % (instance.name, instance.id))
  71. # 创建潜客跟踪表
  72. potential_level = Option.objects.filter(type=Option.POTENTIAL_LEVEL, enable=True).order_by(
  73. 'sort').first()
  74. stage_progress = Option.objects.filter(type=Option.STAGE_PROGRESS, enable=True).order_by('sort').first()
  75. if not potential_level.track_day:
  76. raise CustomError('当前潜客级别,没有可用跟踪天数!')
  77. next_time = (timezone.now() + datetime.timedelta(days=potential_level.track_day)).strftime('%Y-%m-%d')
  78. customer = NewCustomer.objects.create(report_customer=instance, potential_level=potential_level,
  79. track_user_id=user_id, stage_progress=stage_progress,
  80. create_user=instance.create_user, store=instance.store,
  81. name=instance.name, tel=instance.tel, village=instance.village,
  82. address=instance.address, source=instance.source,
  83. notes=instance.notes,
  84. )
  85. projects = instance.project.all()
  86. for project in projects:
  87. customer.project.add(project.id)
  88. NewCustomerRemind.objects.create(customer=customer, next_time=next_time, remind_user_id=user_id,)
  89. # 根据分配人所在店面,创建内部跟踪提醒
  90. remind_users = request.user.get_remind_users()
  91. for remind_user in remind_users:
  92. NewCustomerRemind.objects.create(customer=customer, next_time=next_time, remind_user_id=remind_user,
  93. is_employee=False)
  94. except CustomError as e:
  95. return response_error(e.get_error_msg())
  96. except Exception as e:
  97. return response_error(str(e))
  98. return response_ok()
  99. @action(methods=['post'], detail=True)
  100. def sign_hit(self, request, pk):
  101. check_permission(request, 'customer.check_report_customer')
  102. # 报备客户标记撞单
  103. try:
  104. with transaction.atomic():
  105. instance = ReportCustomer.objects.filter(id=pk).first()
  106. if not instance:
  107. raise CustomError('当前客户报备信息有误,请刷新重试!')
  108. instance.check_user = self.request.user
  109. instance.report_status = ReportCustomer.REPEAT_REPORT
  110. instance.check_time = timezone.now()
  111. instance.save()
  112. BizLog.objects.addnew(request.user, BizLog.INSERT,
  113. u'标记客户[%s]为撞单,id=%d' % (instance.name, instance.id))
  114. except CustomError as e:
  115. return response_error(e.get_error_msg())
  116. except Exception as e:
  117. return response_error(str(e))
  118. return response_ok()
  119. class ReportCustomerDictView(APIView):
  120. permission_classes = [isLogin]
  121. def get(self, request):
  122. source = Option.objects.filter(type=Option.CUSTOMER_SOURCE, enable=True)
  123. project = Option.objects.filter(type=Option.CATEGORY, enable=True)
  124. level = Option.objects.filter(type=Option.POTENTIAL_LEVEL, enable=True)
  125. serializer_source = OptionComboboxSerializer(source, many=True)
  126. serializer_project = OptionComboboxSerializer(project, many=True)
  127. serializer_level = OptionComboboxSerializer(level, many=True)
  128. return response_ok({
  129. 'source': serializer_source.data,
  130. 'project': serializer_project.data,
  131. 'level': serializer_level.data,
  132. })
  133. class UserDictView(APIView):
  134. permission_classes = [isLogin]
  135. def get(self, request):
  136. store = request.user.store
  137. if not store:
  138. return response_error('当前账号未绑定门店,禁止分配客户!')
  139. users = User.objects.filter(store=store).values('id', 'name')
  140. users = [{'value': user['id'], 'lable': user['name']} for user in users]
  141. return response_ok(users)
  142. class NewCustomerViewSet(CustomModelViewSet):
  143. permission_classes = [isLogin, ]
  144. queryset = NewCustomer.objects.filter()
  145. serializer_class = NewCustomerSerializer
  146. @permission_required('customer.view_new_customer')
  147. def filter_queryset(self, queryset):
  148. queryset = queryset.filter(
  149. Q(store_id__in=self.request.user.get_manager_range()) |
  150. Q(create_user=self.request.user) |
  151. Q(track_user=self.request.user)
  152. )
  153. f = NewCustomerFilter(self.request.GET, queryset=queryset)
  154. return f.qs
  155. def paginate_queryset(self, queryset):
  156. if self.paginator is None or self.request.GET.get('export'):
  157. return None
  158. return self.paginator.paginate_queryset(queryset, self.request, view=self)
  159. @action(methods=['post'], detail=True)
  160. def add_review(self, request, pk):
  161. # 添加跟踪报告
  162. check_permission(request, 'customer.add_review')
  163. description = request.POST.get('description')
  164. instruction = request.POST.get('instruction')
  165. is_entry = request.POST.get('is_entry') == '1'
  166. is_giveup = request.POST.get('is_giveup') == '1'
  167. potential_level = request.POST.get('potential_level')
  168. next_time = request.POST.get('next_time')
  169. try:
  170. with transaction.atomic():
  171. instance = NewCustomer.objects.filter(id=pk).first()
  172. if not instance:
  173. raise CustomError('当前客户信息有误,请刷新重试!')
  174. data = {
  175. 'customer': instance.id,
  176. 'store': instance.store.id,
  177. 'create_user': request.user.id,
  178. 'description': description,
  179. 'instruction': instruction or None,
  180. 'is_entry': is_entry,
  181. 'is_giveup': is_giveup,
  182. }
  183. serializer = ReviewSerializer(data=data)
  184. if serializer.is_valid(raise_exception=True):
  185. serializer.save()
  186. sort = 1
  187. track_day = 1
  188. try:
  189. sort = int(instance.stage_progress.sort)
  190. track_day = int(instance.stage_progress.track_day)
  191. except:
  192. pass
  193. # 预定客户,sort排序大于1,提交跟踪报告此字段为空
  194. if sort > 1 or not next_time:
  195. next_time = (timezone.now() + datetime.timedelta(days=track_day)).strftime('%Y-%m-%d')
  196. data = {
  197. 'potential_level':potential_level or None, #预定客户,sort排序大于1,,无客户等级
  198. 'next_time':next_time,
  199. 'end_time':timezone.now(),
  200. 'stage_progress':instance.stage_progress.id,
  201. 'status':NewCustomer.NORMAL,
  202. }
  203. # TODO 如果客户已放弃,再次跟踪后自动改成正常客户,同时工单状态改成正常
  204. if instance.status == NewCustomer.ABANDONED:
  205. data['status'] = NewCustomer.NORMAL
  206. order = Order.objects.filter(customer=instance).first()
  207. if order:
  208. order.status = Order.NORMAL
  209. order.save()
  210. ser = self.serializer_class(instance, data=data, partial=True)
  211. if ser.is_valid(raise_exception=True):
  212. ser.save()
  213. except ValidationError as e:
  214. traceback.print_exc()
  215. return response_error('数据格式有误')
  216. except CustomError as e:
  217. return response_error(e.get_error_msg())
  218. except Exception as e:
  219. return response_error(str(e))
  220. return response_ok()
  221. @action(methods=['post'], detail=True)
  222. def add_order(self, request, pk):
  223. # 更新订单进度
  224. check_permission(request, 'order.update_order_process')
  225. stage_progress = request.POST.get('stage_progress')
  226. notes = request.POST.get('notes')
  227. try:
  228. with transaction.atomic():
  229. instance = NewCustomer.objects.filter(id=pk).first()
  230. if not instance:
  231. raise CustomError('当前客户信息有误,请刷新重试!')
  232. order = Order.objects.filter(customer=instance).first()
  233. if order:
  234. if order.stage_progress.end_stage:
  235. raise CustomError('当前客户订单进度已到最后阶段,请勿重复更新!')
  236. if order.status == Order.WAIT_DISPATCH:
  237. raise CustomError('当前客户订单等待分配中,请勿重复更新!')
  238. data = {
  239. 'status': Order.WAIT_DISPATCH,
  240. 'stage_progress': stage_progress,
  241. }
  242. ser = OrderSerializer(order, data=data, partial=True)
  243. if ser.is_valid(raise_exception=True):
  244. ser.save()
  245. else:
  246. data = {
  247. 'status': Order.WAIT_DISPATCH,
  248. 'stage_progress_id': stage_progress,
  249. 'customer': instance,
  250. 'service_user': instance.track_user,
  251. 'store': instance.store,
  252. }
  253. ser = Order.objects.create(**data)
  254. ser.notes = instance.notes
  255. ser.no = ser.get_no()
  256. ser.save()
  257. projects = instance.project.all()
  258. for project in projects:
  259. ser.project.add(project.id)
  260. # 创建订单流程,保存图片
  261. user = self.request.user
  262. operation = u'更新进度为:{}'.format(order.stage_progress.name)
  263. progress_details = ProgressDetails.objects.create(order=order, user=user, operation=operation,
  264. notes=notes)
  265. for i in range(6):
  266. file = request.data.get('file{}'.format(i))
  267. if file:
  268. upload = Upload.objects._addnew(instance.store, progress_details, user, file)
  269. if not upload:
  270. return response_error('上传失败,请重新上传!')
  271. except ValidationError as e:
  272. traceback.print_exc()
  273. return response_error('数据格式有误')
  274. except CustomError as e:
  275. return response_error(e.get_error_msg())
  276. except Exception as e:
  277. return response_error(str(e))
  278. return response_ok()
  279. class StageCountView(APIView):
  280. permission_classes = [isLogin]
  281. @permission_required('customer.view_new_customer')
  282. def get(self, request):
  283. type = request.query_params.get('type') or 'user'
  284. id = request.query_params.get('id') or request.user.id
  285. data = []
  286. stage_progress = Option.objects.filter(type=Option.STAGE_PROGRESS, enable=True).order_by('sort').values('id','name')
  287. time_now = timezone.now().strftime('%Y-%m-%d')
  288. for stage in stage_progress:
  289. reminds = NewCustomerRemind.objects.filter(customer__stage_progress=stage['id'])
  290. if type == 'store':
  291. reminds = reminds.filter(customer__store_id=id, is_employee=True)
  292. elif type == 'user':
  293. reminds = reminds.filter(remind_user_id=id)
  294. elif type == 'agent':
  295. reminds = reminds.filter(customer__store__agent_id=id, is_employee=True)
  296. elif type == 'general_agent':
  297. reminds = reminds.filter(customer__store__agent__general_agent_id=id, is_employee=True)
  298. # new_customers = NewCustomer.objects.filter(
  299. # Q(track_user=user) |
  300. # Q(track_user__store_id__in=request.user.get_manager_range()),
  301. # stage_progress=stage['id'])
  302. stage_count = {
  303. 'stage_id': stage['id'], # 阶段id
  304. 'stage': stage['name'], # 阶段名称
  305. 'total_count': reminds.count(), # 总人数
  306. 'today_count': reminds.filter(next_time=time_now).count(), # 今日人数
  307. 'overdue_count': reminds.filter(next_time__lt=time_now).count() # 逾期人数
  308. }
  309. data.append(stage_count)
  310. return response_ok(data)
  311. class GetReviewViewSet(CustomModelViewSet):
  312. permission_classes = [isLogin]
  313. queryset = Review.objects.filter()
  314. serializer_class = ReviewSerializer
  315. @permission_required('customer.view_new_customer')
  316. def filter_queryset(self, queryset):
  317. queryset = queryset.filter()
  318. f = ReviewFilter(self.request.GET, queryset=queryset)
  319. return f.qs
  320. class ReviewViewSet(CustomModelViewSet):
  321. permission_classes = [isLogin]
  322. queryset = Review.objects.filter()
  323. serializer_class = ReviewSerializer
  324. @permission_required('customer.check_review')
  325. def filter_queryset(self, queryset):
  326. queryset = queryset.filter(store_id__in=self.request.user.get_manager_range(), instruction__isnull=False)
  327. f = ReviewFilter(self.request.GET, queryset=queryset)
  328. return f.qs
  329. @action(methods=['post'], detail=True)
  330. def track_review(self, request, pk):
  331. check_permission(request, 'customer.check_review')
  332. # 跟踪审核
  333. check_status = request.POST.get('check_status')
  334. check_comment = request.POST.get('check_comment')
  335. next_time = request.POST.get('next_time')
  336. try:
  337. instance = Review.objects.filter(id=pk).first()
  338. if int(check_status) == Review.KEEPUP:
  339. instance.check_user = request.user
  340. instance.check_status = check_status
  341. instance.check_comment = check_comment
  342. instance.check_time = timezone.now()
  343. instance.save()
  344. if int(check_status) == Review.ABANDON:
  345. instance.check_user = request.user
  346. instance.check_status = check_status
  347. instance.check_comment = check_comment
  348. instance.check_time = timezone.now()
  349. instance.save()
  350. instance.customer.status = NewCustomer.ABANDONED
  351. # TODO 如果客户已下单,把工单状态改成放弃
  352. order = Order.objects.filter(customer=instance.customer).first()
  353. if order:
  354. order.status = Order.ABANDONED
  355. order.save
  356. instance.customer.next_time = next_time
  357. instance.customer.save()
  358. except CustomError as e:
  359. return response_error(e.get_error_msg())
  360. except Exception as e:
  361. return response_error(str(e))
  362. return response_ok()