views.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. # coding=utf-8
  2. import requests
  3. from rest_framework.exceptions import NotFound
  4. from django.db import transaction
  5. from rest_framework.views import APIView
  6. from rest_framework import generics
  7. import datetime
  8. from django.db.models import Sum, Count
  9. from rest_framework_jwt.views import ObtainJSONWebToken, VerifyJSONWebToken, RefreshJSONWebToken
  10. from rest_framework.serializers import ValidationError
  11. from utils import response_ok, response_error
  12. from apps.tenant.option.serializers import OptionSerializer, Option
  13. from django.utils import timezone
  14. from apps.tenant.notices.models import Notices
  15. from apps.tenant.notices.serializers import NoticesWXSerializer
  16. from apps.tenant.notices.filters import NoticesFilter
  17. from utils.permission import isLogin, IsTenantUser
  18. from utils.wx.WXBizDataCrypt import WXBizDataCrypt
  19. from apps.tenant.poster.serializer import PosterSerializer, Poster
  20. from apps.tenant.device.models import DeviceModel
  21. from apps.tenant.repair_order.models import RepairOrder, RepairOrderComment
  22. from .serializers import *
  23. class CustomerRefreshTokenView(RefreshJSONWebToken):
  24. def post(self, request, *args, **kwargs):
  25. try:
  26. ser = self.serializer_class(data=request.data)
  27. if ser.is_valid(raise_exception=True):
  28. return response_ok({'token': ser.validated_data['token']})
  29. except ValidationError as e:
  30. return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
  31. class CustomerVerifyTokenView(VerifyJSONWebToken):
  32. def post(self, request, *args, **kwargs):
  33. try:
  34. ser = self.serializer_class(data=request.data)
  35. if ser.is_valid(raise_exception=True):
  36. return response_ok({'token': ser.validated_data['token']})
  37. except ValidationError as e:
  38. return response_error(u'登录状态失效,请重新登录[' + e.detail['error'][0] + ']')
  39. class SetUserInfoView(APIView):
  40. permission_classes = [isLogin, ]
  41. def post(self, request, *args, **kwargs):
  42. appid = request.POST.get('appid')
  43. openid = request.POST.get('openid')
  44. encryptedData = request.POST.get('encryptedData')
  45. iv = request.POST.get('iv')
  46. customer_wechat = CustomerWechat.objects.filter(openid=openid).first()
  47. if not customer_wechat:
  48. raise CustomError(u'未找到相应的微信客户!')
  49. employee = self.request.user.employee
  50. if customer_wechat.customer and customer_wechat.customer.id != employee.id:
  51. raise CustomError(u'该微信已同步其他客户!')
  52. if not customer_wechat.customer:
  53. customer_wechat.customer = employee
  54. customer_wechat.save()
  55. pc = WXBizDataCrypt(appid, customer_wechat.session_key)
  56. result = pc.decrypt(encryptedData, iv)
  57. with transaction.atomic():
  58. if employee.name == employee.tel:
  59. employee.name = result['nickName']
  60. employee.gender = result['gender']
  61. employee.face = result['avatarUrl']
  62. employee.save()
  63. customer_log(employee, BizLog.INSERT, u'客户设置信息,id=%d' % employee.id, result)
  64. return response_ok()
  65. class WxLoginView(APIView):
  66. serializer_class = WechatLoginSerializer
  67. def post(self, request, *args, **kwargs):
  68. ser = self.serializer_class(data=request.data)
  69. if ser.is_valid():
  70. return response_ok(ser.validated_data)
  71. else:
  72. return response_error('参数错误')
  73. class WxBindView(APIView):
  74. serializer_class = WechatBindSerializer
  75. def post(self, request, *args, **kwargs):
  76. ser = self.serializer_class(data=request.data)
  77. if ser.is_valid():
  78. return response_ok(ser.validated_data)
  79. else:
  80. return response_error('参数错误')
  81. class HomeStatisticsView(APIView):
  82. '''小程序首页统计数据'''
  83. def get(self, request):
  84. statistics = {
  85. 'total': 0, # 总报修
  86. 'wait': 0, # 待维修
  87. 'working': 0, # 维修中
  88. 'complete': 0, # 已完工
  89. }
  90. if request.user and request.user.is_authenticated:
  91. tenant = request.user.employee.tenant
  92. rows = RepairOrder.objects.filter(tenant=tenant)
  93. statistics['total'] = rows.filter(status__gte=RepairOrder.CHECKED).count()
  94. statistics['wait'] = rows.filter(status=RepairOrder.CHECKED).count()
  95. statistics['working'] = rows.filter(status=RepairOrder.DISPATCH).count()
  96. statistics['complete'] = rows.filter(status__in=[RepairOrder.FINISH, RepairOrder.APPRAISE, ]).count()
  97. return response_ok(statistics)
  98. else:
  99. return response_ok(statistics)
  100. class StatisticsRepairView(APIView):
  101. '''小程序统计数据'''
  102. permission_classes = [IsTenantUser, ]
  103. def get(self, request):
  104. days = int(request.GET.get('days')) # 7 30 365
  105. data = [] # 报修数据
  106. tenant = request.user.employee.tenant
  107. now = timezone.now()
  108. rows = RepairOrder.objects.filter(tenant=tenant, status__gte=RepairOrder.CHECKED)
  109. if days < 31:
  110. for d in range(days):
  111. date = (now + datetime.timedelta(days=-d)).strftime('%Y-%m-%d')
  112. item = {
  113. 'title': date[5:],
  114. 'data': rows.filter(create_time__gte=date, create_time__lte=date + ' 23:59:59').count(),
  115. }
  116. data.append(item)
  117. data = data[::-1]
  118. else:
  119. # 得到今年的的时间 (年份) 得到的today_year等于2016年
  120. today_year = now.year
  121. # 今年的时间减去1,得到去年的时间。last_year等于2015
  122. last_year = int(now.year) - 1
  123. # 得到今年的每个月的时间。today_year_months等于1 2 3 4 5 6 7 8 9,
  124. today_year_months = range(1, now.month + 1)
  125. # 得到去年的每个月的时间 last_year_months 等于10 11 12
  126. last_year_months = range(now.month + 1, 13)
  127. # 定义列表去年的数据
  128. data_list_lasts = []
  129. # 通过for循环,得到去年的时间夹月份的列表
  130. # 先遍历去年每个月的列表
  131. for last_year_month in last_year_months:
  132. # 定义date_list 去年加上去年的每个月
  133. date_list = '%s-%s' % (last_year, last_year_month)
  134. # 通过函数append,得到去年的列表
  135. data_list_lasts.append(date_list)
  136. data_list_todays = []
  137. # 通过for循环,得到今年的时间夹月份的列表
  138. # 先遍历今年每个月的列表
  139. for today_year_month in today_year_months:
  140. # 定义date_list 去年加上今年的每个月
  141. data_list = '%s-%s' % (today_year, today_year_month)
  142. # 通过函数append,得到今年的列表
  143. data_list_todays.append(data_list)
  144. # 去年的时间数据加上今年的时间数据得到年月时间列表
  145. data_year_month = data_list_lasts + data_list_todays
  146. for year_months in data_year_month:
  147. year_month = year_months.split('-')
  148. year = int(year_month[0])
  149. month = int(year_month[1])
  150. item = {
  151. 'title': year_months,
  152. 'data': rows.filter(create_time__year=year, create_time__month=month).count(),
  153. }
  154. data.append(item)
  155. return response_ok(data)
  156. class StatisticsEvaluateView(APIView):
  157. '''小程序评价统计数据'''
  158. permission_classes = [IsTenantUser, ]
  159. def get(self, request):
  160. days = int(request.GET.get('days')) # 7 30 365
  161. data = [] # 评价数据
  162. tenant = request.user.employee.tenant
  163. now = timezone.now()
  164. date = (now + datetime.timedelta(days=-days)).strftime('%Y-%m-%d')
  165. # 分组统计分析
  166. rows = RepairOrderComment.objects.filter(repair_order__tenant=tenant, create_time__gte=date, ) \
  167. .values('repair_user_id') \
  168. .annotate(starts=Sum('start'), count=Count('id')) \
  169. .values('repair_user__employee__name', 'starts', 'count')
  170. for row in rows:
  171. item = {
  172. 'title': row['repair_user__employee__name'],
  173. 'data': round(float(row['starts']) / float(row['count']), 2),
  174. }
  175. data.append(item)
  176. data.sort(key=lambda d: d['data'], reverse=True)
  177. return response_ok(data)
  178. class PosterView(generics.ListAPIView):
  179. '''小程序首页数据'''
  180. queryset = Poster.objects.filter(enable=True)
  181. serializer_class = PosterSerializer
  182. def filter_queryset(self, queryset):
  183. is_auth = False
  184. if self.request.user and self.request.user.is_authenticated:
  185. is_auth = True
  186. if is_auth:
  187. queryset = queryset.filter(Q(tenant__isnull=True) | Q(tenant=self.request.user.employee.tenant))
  188. else:
  189. queryset = queryset.filter(tenant__isnull=True)
  190. return queryset
  191. def list(self, request, *args, **kwargs):
  192. try:
  193. data = super(PosterView, self).list(request)
  194. except NotFound:
  195. return response_ok([])
  196. return data
  197. class DictView(APIView):
  198. permission_classes = [isLogin, ]
  199. def get(self, request):
  200. tenant = request.user.employee.tenant
  201. ret = {
  202. 'repair_type': OptionSerializer(
  203. Option.objects.filter(delete=False, type=Option.REPAIRS_TYPE, enable=True, tenant=tenant),
  204. many=True).data,
  205. 'fault_cause': OptionSerializer(
  206. Option.objects.filter(delete=False, type=Option.FAULT_CAUSE, enable=True, tenant=tenant),
  207. many=True).data,
  208. }
  209. return response_ok(ret)
  210. class NoticesView(generics.ListAPIView):
  211. queryset = Notices.objects.filter(type=Notices.NOTICE, end_time__gte=timezone.now().date())
  212. serializer_class = NoticesWXSerializer
  213. def filter_queryset(self, queryset):
  214. if self.request.user and self.request.user.is_authenticated:
  215. queryset = queryset.filter(tenant=self.request.user.employee.tenant)
  216. # 查看自己的通知和所有通知
  217. queryset = queryset.filter(Q(range=self.request.user.type) | Q(range=Notices.ALL))
  218. else:
  219. queryset = queryset.filter(tenant=0)
  220. f = NoticesFilter(self.request.GET, queryset=queryset)
  221. return f.qs
  222. class NoticesDetailView(generics.RetrieveAPIView):
  223. permission_classes = [isLogin, ]
  224. queryset = Notices.objects.filter()
  225. serializer_class = NoticesWXSerializer
  226. def get_queryset(self):
  227. queryset = self.queryset.filter(tenant=self.request.user.employee.tenant)
  228. return queryset
  229. def retrieve(self, request, *args, **kwargs):
  230. return response_ok(NoticesWXSerializer(self.get_object()).data)
  231. class MessageView(generics.ListAPIView):
  232. queryset = Notices.objects.filter(type=Notices.MESSAGE, end_time__gte=timezone.now().date())
  233. serializer_class = NoticesWXSerializer
  234. def filter_queryset(self, queryset):
  235. if self.request.user and self.request.user.is_authenticated:
  236. queryset = queryset.filter(notice_user__user=self.request.user)
  237. # 查看自己的通知和所有通知
  238. # queryset = queryset.filter(Q(range=self.request.user.type) | Q(range=Notices.ALL))
  239. else:
  240. queryset = queryset.filter(tenant=0)
  241. f = NoticesFilter(self.request.GET, queryset=queryset)
  242. return f.qs
  243. class MessageListView(generics.ListAPIView):
  244. permission_classes = [IsTenantUser, ]
  245. queryset = Notices.objects.filter(type=Notices.MESSAGE)
  246. serializer_class = NoticesWXSerializer
  247. def filter_queryset(self, queryset):
  248. queryset = queryset.filter(tenant=self.request.user.employee.tenant, notice_user__user=self.request.user)
  249. f = NoticesFilter(self.request.GET, queryset=queryset)
  250. return f.qs
  251. class DeviceView(APIView):
  252. permission_classes = [isLogin, ]
  253. def get(self, request):
  254. param = request.GET.get('param')
  255. device_id = request.GET.get('device_id')
  256. data = []
  257. rows = DeviceModel.objects.filter(tenant=request.user.employee.tenant)
  258. if device_id:
  259. item = rows.filter(id=device_id).first()
  260. if item:
  261. data = {
  262. 'id': item.id,
  263. 'name': item.name,
  264. 'address': '{}{}'.format(item.branch, item.address),
  265. }
  266. return response_ok(data)
  267. else:
  268. return response_error('设备信息错误,请重新查询!')
  269. if param:
  270. rows = rows.filter(Q(name=param) | Q(device_no=param) | Q(device_model=param))
  271. else:
  272. rows = rows[:10]
  273. for item in rows:
  274. build_dict = {
  275. 'id': item.id,
  276. 'name': item.name,
  277. 'device_no': item.device_no,
  278. 'device_model': item.device_model,
  279. 'branch': item.branch,
  280. 'address': item.address,
  281. }
  282. data.append(build_dict)
  283. return response_ok(data)