utils.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. # -*- coding: utf-8 -*-
  2. # !/usr/bin/env python
  3. import datetime
  4. import time
  5. from collections import Counter
  6. from typing import TYPE_CHECKING, Dict, Union
  7. from apilib.monetary import RMB, VirtualCoin, Percent
  8. from apilib.utils_datetime import to_datetime
  9. from apps.common.utils import get_start_and_end_by_year
  10. from apps.web.agent.models import Agent
  11. from apps.web.common.proxy import DealerDailyStatsModelProxy
  12. from apps.web.constant import MONTH_DATE_KEY
  13. from apps.web.dealer.models import Dealer
  14. from apps.web.device.models import Device, FeedBack
  15. from apps.web.user.models import ServiceProgress, MyUser, RechargeRecord, ConsumeRecord
  16. if TYPE_CHECKING:
  17. from bson.objectid import ObjectId
  18. from apps.web.report.models import DealerDailyStat
  19. def get_dealerMap_by_managerId(managerId, agentId = None, dealerId = None):
  20. # type:(Union[ObjectId,str], str, str)->Dict[str, dict]
  21. if not dealerId:
  22. if not agentId:
  23. agentMap = {str(_['_id']): str(_['nickname'])
  24. for _ in Agent.get_collection().find({'managerId': str(managerId)})}
  25. else:
  26. agent = Agent.objects(id = agentId).get() # type: Agent
  27. agentMap = {agentId: agent.nickname}
  28. dealerMap = {str(_['_id']): {'nickname': str(_['nickname']), 'agentName': agentMap[_['agentId']]}
  29. for _ in Dealer.get_collection().find({'agentId': {'$in': agentMap.keys()}})}
  30. else:
  31. dealer = Dealer.objects(id = dealerId).get() # type: Dealer
  32. agent = Agent.objects(id = dealer.agentId).get() # type: Agent
  33. dealerMap = {dealerId: {'nickname': dealer.nickname, 'agentName': agent.nickname}}
  34. return dealerMap
  35. def query_device_income(dealerIds):
  36. now_time = datetime.datetime.now()
  37. statsDict = DealerDailyStatsModelProxy.get_stats_as_day(
  38. dealerIds = dealerIds,
  39. startDay = (now_time - datetime.timedelta(days = 30)),
  40. endDay = now_time,
  41. project = ('daily.totalIncome', 'daily.consumption.coin'),
  42. aggregateMap = {'payIncome': {'$sum': '$daily.totalIncome'},
  43. 'lineCoins': {'$sum': '$daily.consumption.coin'}})
  44. dataList = []
  45. for _day, _stat in statsDict.iteritems(): # type: DealerDailyStat
  46. dataList.append({
  47. 'dateStr': _day,
  48. 'payIncome': RMB(_stat.get('payIncome', 0)),
  49. 'lineCoins': VirtualCoin(_stat.get('lineCoins', 0))
  50. })
  51. return dataList
  52. def query_device_consumption(dealerIds):
  53. now = datetime.datetime.now()
  54. endDate = MONTH_DATE_KEY.format(year = now.year, month = now.month)
  55. def get_start_day(date, var):
  56. year = int(date.split('-')[0])
  57. month = int(date.split('-')[-1])
  58. year = year if month > var else year - 1
  59. month = month - var if month > var else month + 12 - var
  60. return '{year:d}-{month:02d}-01'.format(year = year, month = month)
  61. endDay = datetime.datetime.now()
  62. startDay = get_start_day(MONTH_DATE_KEY.format(year = endDay.year, month = endDay.month), 5)
  63. rv = DealerDailyStatsModelProxy.get_consume_as_month(
  64. dealerIds = dealerIds,
  65. startDay = startDay,
  66. endDay = endDay,
  67. sources = ['elec', 'coin'])
  68. dataList = []
  69. for monthStr, value in rv.iteritems():
  70. dataList.append({
  71. 'consumptionList': [
  72. {'name': '电量', 'value': Percent(value.get('elec', 0)), 'unit': '度'},
  73. {'name': '金币', 'value': VirtualCoin(value.get('coin', 0)), 'unit': '个'}
  74. ],
  75. 'dateStr': monthStr
  76. })
  77. return dataList
  78. def get_user_stats(dealerIds):
  79. devGroupIdList = [_['groupId'] for _ in list(Device.get_collection().find(
  80. {'ownerId': {'$in': dealerIds}},
  81. {'devNo': 1, 'groupId': 1, '_id': 0}
  82. ))]
  83. myUserList = list(MyUser.get_collection().find(
  84. {'groupId': {'$in': devGroupIdList}},
  85. {'nickname': 1, 'sex': 1, 'openId': 1, '_id': 0}
  86. ))
  87. myUserNameList = list(set([_.get('nickname', '') for _ in myUserList]))
  88. myUserOpenIdList = list(set([_['openId'] for _ in myUserList]))
  89. femaleCount = 0
  90. maleCount = 0
  91. for _ in myUserList:
  92. if _['sex'] == 2:
  93. femaleCount += 1
  94. else:
  95. maleCount += 1
  96. temp = int(((femaleCount + maleCount) - len(myUserNameList)) / 2)
  97. startDateTime = to_datetime(datetime.datetime.now().strftime('%Y-%m-%d') + ' 00:00:00')
  98. endDateTime = to_datetime(datetime.datetime.now().strftime('%Y-%m-%d') + ' 23:59:59')
  99. # 过滤重复的openId,找到今天的活跃用户
  100. rcdList = list(RechargeRecord.get_collection().find(
  101. {'dateTimeAdded': {'$gte': startDateTime, '$lte': endDateTime}, 'openId': {'$in': myUserOpenIdList}},
  102. {'openId': 1, '_id': 0}
  103. ))
  104. todayActiveUsers = list(set([_['openId'] for _ in rcdList]))
  105. return {
  106. "userCount": len(myUserNameList),
  107. "femaleCount": femaleCount - temp,
  108. "maleCount": maleCount - temp,
  109. "todayActiveUsers": len(todayActiveUsers)
  110. }
  111. def get_feed_back_stats(dealerIds):
  112. now_time = datetime.datetime.now()
  113. start_day = now_time.strftime('%Y-%m-%d %H:%M:%S')
  114. end_day = (now_time - datetime.timedelta(days = 90)).strftime('%Y-%m-%d %H:%M:%S')
  115. feedBacks = list(FeedBack.get_collection().find(
  116. {'ownerId': {'$in': dealerIds}, 'createTime': {'$gte': start_day, '$lte': end_day}},
  117. {'_id': 0, 'feedType': 1, 'status': 1}
  118. ))
  119. fault = [_['status'] for _ in feedBacks if _['feedType'] == 'fault']
  120. faultProcessed = [_ for _ in fault if _ == 1]
  121. offlineFeed = [_['status'] for _ in feedBacks if _['feedType'] in ['upper', 'refund', 'ic', 'putCoin']]
  122. offlineProcessed = [_ for _ in offlineFeed if _ == 1]
  123. netpayFeed = [_['status'] for _ in feedBacks if _['feedType'] == 'netpay']
  124. netpayProcessed = [_ for _ in netpayFeed if _ == 1]
  125. return {
  126. "faultCount": len(fault),
  127. "faultProcessedCount": len(faultProcessed),
  128. "offlineFeedCount": len(offlineFeed),
  129. "offlineFeedProcessedCount": len(offlineProcessed),
  130. "netpayFeedCount": len(netpayFeed),
  131. "netpayFeedProcessedCount": len(netpayProcessed)
  132. }
  133. def query_total_dealer_income_top(dealerDict):
  134. startDay, endDay = get_start_and_end_by_year(datetime.date.today().strftime("%Y"))
  135. total_income_dict = DealerDailyStatsModelProxy.get_total_income_as_dealer(
  136. dealerIds = dealerDict.keys(),
  137. startDay = startDay,
  138. endDay = endDay)
  139. dic = {}
  140. for dealerId, nickname in dealerDict.iteritems():
  141. item = total_income_dict.get(dealerId, {'totalIncome': 0})
  142. dic.update({nickname: RMB(item.get('totalIncome'))})
  143. data = Counter(dic).most_common()[0:5] # 返回一个列表,按照dict的value从大到小排序, 取前5位
  144. return [{'name': _[0], 'payIncomeTotal': _[1]} for _ in data]
  145. def query_user_consume_frequency(dealerIds):
  146. # 查找出所有已注册的设备
  147. devGroupIdList = [_['groupId'] for _ in list(Device.get_collection().find(
  148. {'ownerId': {'$in': dealerIds}},
  149. {'devNo': 1, 'groupId': 1, '_id': 0}
  150. ))]
  151. myUserList = list(MyUser.get_collection().find(
  152. {'groupId': {'$in': devGroupIdList}},
  153. {'nickname': 1, 'sex': 1, 'openId': 1, '_id': 0}
  154. ))
  155. myUserOpenIdList = list(set([_['openId'] for _ in myUserList]))
  156. aMonthAgo = time.mktime((datetime.date.today() - datetime.timedelta(days = 30)).timetuple())
  157. rcdOpenIdList = [_['openId'] for _ in list(ConsumeRecord.get_collection().find(
  158. {'openId': {'$in': myUserOpenIdList}, 'dateTimeAdded': {'$gte': aMonthAgo}},
  159. {'openId': 1, '_id': 0}
  160. ))]
  161. rcdCountDict = dict(Counter(rcdOpenIdList))
  162. rcdCountPctDict = dict(Counter([_ for _ in rcdCountDict.values()]))
  163. totalCount = 0
  164. for _ in rcdCountPctDict.values():
  165. totalCount += _
  166. dataList = [
  167. {
  168. "name": "1次",
  169. "percent": 0
  170. },
  171. {
  172. "name": "2-5次",
  173. "percent": 0
  174. },
  175. {
  176. "name": "5-10次",
  177. "percent": 0
  178. },
  179. {
  180. "name": "10-20次",
  181. "percent": 0
  182. },
  183. {
  184. "name": "20+次",
  185. "percent": 0
  186. }
  187. ]
  188. for k, v in rcdCountPctDict.items():
  189. if k == 1:
  190. dataList[0]['percent'] += v
  191. elif 2 <= k <= 5:
  192. dataList[1]['percent'] += v
  193. elif 6 <= k <= 10:
  194. dataList[2]['percent'] += v
  195. elif 11 <= k <= 20:
  196. dataList[3]['percent'] += v
  197. else:
  198. dataList[4]['percent'] += v
  199. for _ in dataList:
  200. if float(totalCount) == 0:
  201. _['percent'] = 0
  202. continue
  203. _['percent'] = Percent((float(_['percent']) / float(totalCount)) * 100)
  204. return dataList
  205. def get_device_being_used_trend(dealerIds):
  206. devList = list(Device.get_collection().find(
  207. {'ownerId': {'$in': dealerIds}, 'groupId': {'$ne': ''}},
  208. {'devNo': 1, 'groupId': 1, '_id': 0}
  209. ))
  210. devNoList = [_['devNo'] for _ in devList]
  211. # 找前一天的数据
  212. def get_hours_time(hoursStr):
  213. return time.mktime(to_datetime(
  214. (datetime.date.today() - datetime.timedelta(days = 1)).strftime('%Y-%m-%d') + hoursStr).timetuple())
  215. yesterdayBegin = get_hours_time(' 00:00:00')
  216. yesterdayEnd = get_hours_time(' 23:59:59')
  217. serviceProgress = list(ServiceProgress.get_collection().find(
  218. {'device_imei': {'$in': devNoList},
  219. 'start_time': {'$gte': int(yesterdayBegin), '$lte': int(yesterdayEnd)}},
  220. {'_id': 0, 'start_time': 1}
  221. ))
  222. dataList = []
  223. for _ in range(24):
  224. if _ < 9:
  225. timeStr = '0' + str(_ + 1) + '时'
  226. else:
  227. timeStr = str(_ + 1) + '时'
  228. dataList.append({
  229. 'time': timeStr,
  230. 'devBeingUsed': 0
  231. })
  232. for svs in serviceProgress:
  233. for _ in range(24):
  234. if _ < 10:
  235. timeStr = ' ' + '0' + str(_)
  236. else:
  237. timeStr = ' ' + str(_)
  238. begin = timeStr + ':00:00'
  239. end = timeStr + ':59:59'
  240. if get_hours_time(begin) <= svs['start_time'] <= get_hours_time(end):
  241. dataList[_]['devBeingUsed'] += 1
  242. return dataList