AgentCustomerController.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. # -*- encoding: utf-8 -*-
  2. """
  3. @File : AgentCustomerController.py
  4. @Time : 2024/3/7 16:56
  5. @Author : stephen
  6. @Email : zhangdongming@asj6.wecom.work
  7. @Software: PyCharm
  8. """
  9. import re
  10. import time
  11. import json
  12. from decimal import Decimal
  13. from django.db.models import Sum
  14. from django.http import QueryDict
  15. from django.views import View
  16. from django.core.paginator import Paginator
  17. from datetime import datetime, timedelta
  18. from AgentModel.models import AgentCustomerInfo, AgentCustomerCard, AgentCustomerPackage, AgentCloudServicePackage, \
  19. AgentDeviceOrder, AgentAccountWithdraw, AgentDevice, AgentAccount, ApplyAgent, AgentDeviceOrderInstallment
  20. from Model.models import UnicomCombo, Store_Meal, Device_User
  21. from Object.ResponseObject import ResponseObject
  22. from Object.TokenObject import TokenObject
  23. class AgentCustomerView(View):
  24. def get(self, request, *args, **kwargs):
  25. request.encoding = 'utf-8'
  26. operation = kwargs.get('operation')
  27. return self.validation(request.GET, request, operation)
  28. def post(self, request, *args, **kwargs):
  29. request.encoding = 'utf-8'
  30. operation = kwargs.get('operation')
  31. return self.validation(request.POST, request, operation)
  32. def delete(self, request, *args, **kwargs):
  33. request.encoding = 'utf-8'
  34. operation = kwargs.get('operation')
  35. delete = QueryDict(request.body)
  36. if not delete:
  37. delete = request.GET
  38. return self.validation(delete, request, operation)
  39. def put(self, request, *args, **kwargs):
  40. request.encoding = 'utf-8'
  41. operation = kwargs.get('operation')
  42. put = QueryDict(request.body)
  43. return self.validation(put, request, operation)
  44. def validation(self, request_dict, request, operation):
  45. AgentCustomerInfo.objects.filter()
  46. language = request_dict.get('language', 'en')
  47. response = ResponseObject(language, 'pc')
  48. if operation == 'getUnicomAndIcloud':
  49. return self.get_unicom_and_icloud(response)
  50. elif operation == 'applyAgent':
  51. return self.apply_agent(request_dict, response)
  52. else:
  53. tko = TokenObject(
  54. request.META.get('HTTP_AUTHORIZATION'),
  55. returntpye='pc')
  56. if tko.code != 0:
  57. return response.json(tko.code)
  58. response.lang = tko.lang
  59. userID = tko.userID
  60. # 代理用户界面(代理顾客个人信息)
  61. if operation == 'getAgentInfo':
  62. return self.get_agent_info(userID, response)
  63. # 代理云存套餐
  64. elif operation == 'getAgentServicePackage':
  65. return self.get_agent_service_package(request_dict, response)
  66. elif operation == 'addAgentServicePackage':
  67. return self.add_agent_service_package(userID, request_dict, response)
  68. elif operation == 'updateAgentServicePackage':
  69. return self.update_agent_service_package(userID, request_dict, response)
  70. elif operation == 'delAgentServicePackage':
  71. return self.del_agent_service_package(request_dict, response)
  72. # 代理客户绑定套餐
  73. elif operation == 'getCustomerList':
  74. return self.get_customer_list(request_dict, response)
  75. elif operation == 'getCustomerPackageList':
  76. return self.get_cumstomer_package_list(request_dict, response)
  77. elif operation == 'batchRebindCustomerPackage':
  78. return self.batch_rebind_customer_packages(userID, request_dict, response)
  79. elif operation == 'getAgentServicePackageList':
  80. return self.get_agent_service_package_list(response)
  81. elif operation == 'getAgentSettleOrders':
  82. return self.get_agent_settle_order(userID, request_dict, response)
  83. elif operation == 'getDataStatistics':
  84. return self.get_data_statistics(userID, response)
  85. # 代理商提现功能
  86. elif operation == 'getAgentAccountWithdraw':
  87. return self.get_agent_account_withdraw(userID, request_dict, response)
  88. elif operation == 'getCheckBalance':
  89. return self.get_check_balance(userID, response)
  90. elif operation == 'agentApplyWithdraw':
  91. return self.agent_apply_withdraw(userID, request_dict, response)
  92. elif operation == 'getWithdrawalReview':
  93. return self.get_withdrawal_review(request_dict, response)
  94. elif operation == 'updateWithdrawalReview':
  95. return self.update_withdrawal_review(userID, request_dict, response)
  96. else:
  97. return response.json(444, 'operation')
  98. def get_unicom_and_icloud(self, response):
  99. """
  100. 查询云存储套餐和物联网卡套餐列表
  101. @param response: 响应对象
  102. @return:
  103. """
  104. try:
  105. # 云存储套餐查询,只包括is_show=0的记录
  106. store_meals = Store_Meal.objects.filter(is_show=0).values('id', 'bucket__bucket').distinct()
  107. # 联通套餐查询,只包括is_show=1且未被删除的记录
  108. unicom_combos = UnicomCombo.objects.filter(is_show=1, is_del=False).values('id', 'combo_name').distinct()
  109. # 将查询结果转换为列表
  110. store_meal_list = [{'id': meal['id'], 'name': meal['bucket__bucket']} for meal in store_meals]
  111. unicom_combo_list = [{'id': combo['id'], 'name': combo['combo_name']} for combo in unicom_combos]
  112. # 合并结果并返回
  113. return response.json(0, {
  114. 'storeMeals': store_meal_list,
  115. 'unicomCombos': unicom_combo_list,
  116. })
  117. except Exception as e:
  118. print(e)
  119. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  120. def get_agent_info(self, userID, response):
  121. """
  122. 查询用户信息
  123. @param userID: userID
  124. @param response: 响应对象
  125. @return:
  126. """
  127. try:
  128. # 使用userID查询AgentCustomerInfo获取基本信息
  129. agent_info = AgentCustomerInfo.objects.filter(user_id=userID, status=1).first()
  130. if not agent_info:
  131. return response.json(444, {'error': '没有找到这个代理用户'})
  132. # userID查询用户电话
  133. device_user_qs = Device_User.objects.filter(userID=userID).first()
  134. # 代理客户ID(ac_id)查询AgentCustomerCard获取银行卡信息。
  135. card_details = AgentCustomerCard.objects.filter(ac_id=agent_info.id, status=1).first()
  136. # ac_id查询AgentCustomerPackage来找到关联的云服务套餐ID(cs_id)
  137. package_ids = AgentCustomerPackage.objects.filter(ac_id=agent_info.id).values_list('cs_id',
  138. flat=True)
  139. # cs_id查询AgentCloudServicePackage获取服务套餐详情。
  140. service_packages = AgentCloudServicePackage.objects.filter(id__in=package_ids, status=1).values()
  141. result = {
  142. 'agent_info': {
  143. 'ac_id': agent_info.id,
  144. 'company_name': agent_info.company_name,
  145. 'phone': device_user_qs.phone,
  146. 'created_time': agent_info.created_time,
  147. 'service_packages': list(service_packages),
  148. }
  149. }
  150. if card_details:
  151. # 获取银行卡号
  152. card_no = card_details.card_no
  153. # 检查银行卡号字符串长度,如果小于等于8,则返回"null"
  154. if len(card_no) <= 8:
  155. masked_card_no = "null"
  156. else:
  157. # 保留前四位和后四位,用"*"代替中间的数字
  158. masked_card_no = card_no[:4] + '*' * (len(card_no) - 8) + card_no[-4:]
  159. result['agent_info'].update({
  160. 'card_name': card_details.name,
  161. 'card_no': masked_card_no,
  162. 'card_address': card_details.card_address,
  163. })
  164. return response.json(0, result)
  165. except Exception as e:
  166. return response.json(500, {'error': str(e)})
  167. def get_agent_service_package(self, request_dict, response):
  168. """
  169. 查询所有代理云服务套餐
  170. @param request_dict: 请求参数
  171. @request_dict page: 页码
  172. @request_dict page_size: 查询分页数
  173. @param response: 响应对象
  174. @return:
  175. """
  176. page = int(request_dict.get('page', 1))
  177. page_size = int(request_dict.get('page_size', 10))
  178. try:
  179. # 查询所有有效的代理云服务套餐
  180. all_packages = AgentCloudServicePackage.objects.filter(status=1).order_by('type', '-created_time')
  181. # 创建分页对象
  182. paginator = Paginator(all_packages, page_size)
  183. # 获取请求页的数据
  184. packages_page = paginator.page(page)
  185. # 准备响应数据,转换查询集为列表形式
  186. agents_list = []
  187. for agent_info in packages_page:
  188. package_name = agent_info.package_id
  189. if agent_info.type == 1:
  190. store_meals = Store_Meal.objects.filter(id=agent_info.package_id).values('bucket__bucket').first()
  191. if store_meals:
  192. package_name = store_meals['bucket__bucket']
  193. else:
  194. unicom_combos = UnicomCombo.objects.filter(id=agent_info.package_id).first()
  195. if unicom_combos:
  196. package_name = unicom_combos.combo_name
  197. agents = {
  198. 'id': agent_info.id,
  199. 'service_name': agent_info.service_name,
  200. 'package_name': package_name,
  201. 'type': agent_info.type,
  202. 'profit_type': agent_info.profit_type,
  203. 'cost': agent_info.cost,
  204. 'profit': agent_info.profit,
  205. 'status': agent_info.status,
  206. 'created_time': agent_info.created_time
  207. }
  208. agents_list.append(agents)
  209. # 返回分页数据
  210. return response.json(0, {
  211. 'page': page,
  212. 'page_size': page_size,
  213. 'total': paginator.count,
  214. 'num_pages': paginator.num_pages,
  215. 'list': agents_list
  216. })
  217. except Exception as e:
  218. # 出错时返回错误信息
  219. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  220. def add_agent_service_package(self, userID, request_dict, response):
  221. """
  222. 添加代理云服务套餐
  223. @param request_dict: 请求参数
  224. @request_dict package_id: 代理服务id
  225. @request_dict service_name: 代理服务名称
  226. @request_dict package_type: 套餐类型 1:云存,2:4G
  227. @response_dict profit_type: 利润分配类型 1:固定值,2:百分比
  228. @response_dict cost: 成本
  229. @response_dict profit: 利润值
  230. @param response: 响应对象
  231. @return:
  232. """
  233. package_id = request_dict.get('package_id', None)
  234. service_name = request_dict.get('service_name', None)
  235. package_type = int(request_dict.get('package_type', 0)) # 默认为0,确保类型安全
  236. profit_type = int(request_dict.get('profit_type', 1)) # 默认值为1
  237. profit = request_dict.get('profit', 0)
  238. cost = request_dict.get('cost', 0)
  239. try:
  240. # 创建AgentCloudServicePackage实例并保存
  241. if not all([package_id, service_name]):
  242. return response.json(444)
  243. if package_type == 1:
  244. query_set = Store_Meal.objects.filter(is_show=0, id=package_id)
  245. elif package_type == 2:
  246. query_set = UnicomCombo.objects.filter(is_show=1, is_del=False, id=package_id)
  247. else:
  248. return response.json(444, 'error package_type')
  249. if not query_set.exists():
  250. return response.json(173)
  251. AgentCloudServicePackage.objects.create(
  252. service_name=service_name,
  253. package_id=package_id,
  254. type=package_type,
  255. profit_type=profit_type,
  256. profit=profit,
  257. status=1,
  258. cost=cost,
  259. created_by=userID,
  260. created_time=int(time.time()),
  261. updated_by=userID,
  262. updated_time=int(time.time())
  263. )
  264. return response.json(0)
  265. except Exception as e:
  266. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  267. def update_agent_service_package(self, userID, request_dict, response):
  268. """
  269. 更新代理云服务套餐
  270. @param request_dict: 请求参数
  271. @request_dict package_id: 代理服务id
  272. @request_dict service_name: 代理服务名称
  273. @response_dict profit_type: 利润分配类型 1:固定值,2:百分比
  274. @response_dict cost: 成本
  275. @response_dict profit: 利润值
  276. @param response: 响应对象
  277. @return:
  278. """
  279. id = request_dict.get('id', None)
  280. service_name = request_dict.get('service_name', None)
  281. profit_type = request_dict.get('profit_type', None)
  282. cost = request_dict.get('cost', None)
  283. profit = request_dict.get('profit', None)
  284. if not all([id, service_name, profit_type, cost, profit]):
  285. return response.json(444)
  286. try:
  287. ac_service_package = AgentCloudServicePackage.objects.get(pk=id)
  288. ac_service_package.service_name = service_name
  289. ac_service_package.profit_type = profit_type
  290. ac_service_package.cost = cost
  291. ac_service_package.profit = profit
  292. ac_service_package.updated_time = int(time.time())
  293. ac_service_package.updated_by = userID
  294. ac_service_package.save()
  295. return response.json(0)
  296. except AgentCloudServicePackage.DoesNotExist:
  297. return response.json(173)
  298. except Exception as e:
  299. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  300. def del_agent_service_package(self, request_dict, response):
  301. """
  302. 删除代理云服务套餐
  303. @param userID: 用户ID(执行删除操作的用户)
  304. @param request_dict: 请求参数
  305. @request_dict package_id: 代理服务id
  306. @param response: 响应对象
  307. @return:
  308. """
  309. id = request_dict.get('id', None)
  310. if not id:
  311. return response.json(444, 'Missing package_id')
  312. try:
  313. ac_service_package = AgentCloudServicePackage.objects.get(pk=id)
  314. # 假删除,否则查利润会出问题
  315. ac_service_package.status = 0
  316. ac_service_package.save()
  317. return response.json(0)
  318. except AgentCloudServicePackage.DoesNotExist:
  319. return response.json(173, 'Package does not exist.')
  320. except Exception as e:
  321. return response.json(500, {'error': str(e)})
  322. def get_customer_list(self, request_dict, response):
  323. """
  324. 查询代理商信息,并进行分页处理
  325. @param request_dict: 请求对象,用于接收分页参数
  326. @param response: 响应对象
  327. @return:
  328. """
  329. # 接收分页参数
  330. page = int(request_dict.get('page', 1))
  331. page_size = int(request_dict.get('page_size', 10))
  332. search_query = request_dict.get('search_query', '')
  333. user_id = request_dict.get('user_id', None)
  334. phone = request_dict.get('phone', None)
  335. userEmail = request_dict.get('userEmail', None)
  336. try:
  337. # 基础查询条件
  338. agent_infos_query = AgentCustomerInfo.objects.filter(status=1)
  339. # 精确查询条件
  340. if user_id:
  341. agent_infos_query = agent_infos_query.filter(user_id=user_id)
  342. # 获取所有符合条件的AgentCustomerInfo记录
  343. agent_infos = agent_infos_query.values('id', 'user_id', 'company_name').order_by('id')
  344. # 对结果进行分页
  345. paginator = Paginator(agent_infos, page_size)
  346. packages_page = paginator.page(page)
  347. # 准备最终的代理商列表
  348. agents_list = []
  349. for agent_info in packages_page:
  350. # 模糊查询
  351. if search_query:
  352. card_info_query = AgentCustomerCard.objects.filter(ac_id=agent_info['id'],
  353. name__icontains=search_query)
  354. if not card_info_query.exists() and search_query not in agent_info['company_name']:
  355. continue
  356. else:
  357. card_info_query = AgentCustomerCard.objects.filter(ac_id=agent_info['id'])
  358. # 获取卡信息
  359. card_info = card_info_query.values('name', 'card_no', 'card_address').first()
  360. # 获取用户信息,根据需要进行精确查询
  361. user_info_query = Device_User.objects.filter(userID=agent_info['user_id'])
  362. if phone:
  363. user_info_query = user_info_query.filter(phone=phone)
  364. if userEmail:
  365. user_info_query = user_info_query.filter(userEmail=userEmail)
  366. user_info = user_info_query.values('phone', 'userEmail').first()
  367. # 组合信息
  368. agent_record = {
  369. 'id': agent_info['id'],
  370. 'company_name': agent_info['company_name'],
  371. 'user_id': agent_info['user_id'],
  372. 'phone': user_info.get('phone') if user_info else None,
  373. 'userEmail': user_info.get('userEmail') if user_info else None,
  374. 'card_name': card_info.get('name') if card_info else None,
  375. 'card_no': card_info.get('card_no') if card_info else None,
  376. 'card_address': card_info.get('card_address') if card_info else None,
  377. }
  378. agents_list.append(agent_record)
  379. # 返回分页后的结果
  380. return response.json(0, {
  381. 'page': page,
  382. 'page_size': page_size,
  383. 'total': paginator.count,
  384. 'num_pages': paginator.num_pages,
  385. 'list': agents_list
  386. })
  387. except Exception as e:
  388. print(e)
  389. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  390. def get_cumstomer_package_list(self, request_dict, response):
  391. """
  392. 查询代理商服务套餐列表
  393. @param response: 响应对象
  394. @return:
  395. """
  396. ac_id = request_dict.get('id', None)
  397. try:
  398. if ac_id is None:
  399. return response.json(444, 'Missing ac_id')
  400. # ac_id查询AgentCustomerPackage来找到关联的云服务套餐ID(cs_id)
  401. package_ids = AgentCustomerPackage.objects.filter(ac_id=ac_id).values_list('cs_id', flat=True)
  402. # cs_id查询AgentCloudServicePackage获取服务套餐详情。
  403. service_packages = AgentCloudServicePackage.objects.filter(id__in=package_ids, status=1).values(
  404. 'id', 'service_name', 'type'
  405. )
  406. service_packages_list = list(service_packages)
  407. return response.json(0, {'service_packages': service_packages_list})
  408. except Exception as e:
  409. print(e)
  410. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  411. def batch_rebind_customer_packages(self, userID, request_dict, response):
  412. """
  413. 清空并重新绑定代理商服务套餐
  414. @param userID: 操作用户的ID
  415. @param request_dict: 请求参数,包含代理商ID和新的服务套餐ID列表
  416. @param response: 响应对象
  417. @return:
  418. """
  419. ac_id = request_dict.get('ac_id', None) # 代理客户ID
  420. new_cs_ids = json.loads(request_dict.get('cs_ids', '[]')) # 新的服务套餐ID列表
  421. if not ac_id:
  422. return response.json(444, 'Missing agent customer ID.')
  423. if not new_cs_ids:
  424. return response.json(444, 'Service package IDs are required.')
  425. try:
  426. # 删除该代理客户的所有现有绑定
  427. AgentCustomerPackage.objects.filter(ac_id=ac_id).delete()
  428. # 过滤出存在且状态为有效的套餐ID
  429. valid_new_cs_ids = AgentCloudServicePackage.objects.filter(id__in=new_cs_ids, status=1).values_list('id',
  430. flat=True)
  431. # 准备批量创建的数据
  432. packages_to_bind = [
  433. AgentCustomerPackage(
  434. ac_id=ac_id,
  435. cs_id=cs_id,
  436. created_by=userID,
  437. updated_by=userID,
  438. created_time=int(time.time()),
  439. updated_time=int(time.time())
  440. )
  441. for cs_id in valid_new_cs_ids
  442. ]
  443. # 批量创建新的绑定关系
  444. AgentCustomerPackage.objects.bulk_create(packages_to_bind)
  445. return response.json(0)
  446. except Exception as e:
  447. print(e)
  448. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  449. def get_agent_service_package_list(self, response):
  450. """
  451. 查询云服务套餐列表 id + service_name
  452. @param response: 响应对象
  453. @return:
  454. """
  455. try:
  456. # 查询所有有效的代理云服务套餐
  457. all_packages = AgentCloudServicePackage.objects.filter(status=1).order_by('-created_time').values('id',
  458. 'service_name')
  459. # 转换查询集为列表形式
  460. packages_list = list(all_packages)
  461. # 返回数据
  462. return response.json(0, {'packages': packages_list})
  463. except Exception as e:
  464. # 出错时返回错误信息
  465. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  466. def get_agent_settle_order(self, userID, request_dict, response):
  467. """
  468. 查询结算明细
  469. @param userID: userID
  470. @param request_dict: 请求参数
  471. @param request_dict status: 结算状态
  472. @param request_dict time: 年-季度 2023-1
  473. @param response: 响应对象
  474. @return:
  475. """
  476. status = request_dict.get('status', None)
  477. time_str = request_dict.get('time', None)
  478. package_type = request_dict.get('package_type', None)
  479. startTime = int(request_dict.get('start_time', 1))
  480. endTime = int(request_dict.get('end_time', 0))
  481. page = int(request_dict.get('page', 1)) # 默认为第一页
  482. page_size = int(request_dict.get('page_size', 10)) # 默认每页10条记录
  483. try:
  484. agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
  485. if agent_customer_info is None:
  486. agent_device_orders_qs = AgentDeviceOrder.objects.filter(is_del=False)
  487. else:
  488. ac_id = agent_customer_info.id
  489. agent_device_orders_qs = AgentDeviceOrder.objects.filter(ac_id=ac_id, is_del=False)
  490. if time_str:
  491. year, quarter = map(int, time_str.split('-'))
  492. start_month = 3 * (quarter - 1) + 1
  493. end_month = start_month + 2
  494. start_date = datetime(year, start_month, 1)
  495. end_date = datetime(year + 1, 1, 1) if end_month == 12 else datetime(year, end_month + 1, 1)
  496. start_time = int(start_date.timestamp())
  497. end_time = int(end_date.timestamp()) - 1
  498. agent_device_orders_qs = agent_device_orders_qs.filter(created_time__gte=start_time,
  499. created_time__lte=end_time)
  500. if startTime < endTime:
  501. agent_device_orders_qs = agent_device_orders_qs.filter(created_time__gte=startTime,
  502. created_time__lte=endTime)
  503. if package_type:
  504. csp_ids = list(
  505. AgentCloudServicePackage.objects.filter(type=int(package_type)).values_list('id', flat=True))
  506. agent_device_orders_qs = agent_device_orders_qs.filter(csp_id__in=csp_ids)
  507. if status is None:
  508. total_profit = agent_device_orders_qs.aggregate(Sum('profit'))['profit__sum'] or 0
  509. else:
  510. # 计算特定状态的device_orders总额
  511. full_profit = agent_device_orders_qs.filter(status=status).aggregate(Sum('profit'))[
  512. 'profit__sum'] or 0
  513. # 初始化total_profit
  514. total_profit = full_profit
  515. # 对于状态1和2,计算部分结算的利润
  516. if status in ["1", "2"]:
  517. partial_settled_profit = AgentDeviceOrderInstallment.objects.filter(
  518. ado_id__in=agent_device_orders_qs.filter(status=1).values_list('id', flat=True),
  519. status=2
  520. ).aggregate(total=Sum('amount'))['total'] or 0
  521. # 根据状态调整total_profit
  522. if status == "1":
  523. total_profit -= partial_settled_profit
  524. else: # 当status为"2"时,添加partial_settled_profit(根据业务逻辑,这可能需要调整)
  525. total_profit += partial_settled_profit
  526. agent_device_orders_qs = agent_device_orders_qs.filter(status=status)
  527. # 应用分页
  528. agent_device_orders_qs = agent_device_orders_qs.order_by('-created_time')
  529. paginator = Paginator(agent_device_orders_qs, page_size)
  530. current_page = paginator.get_page(page)
  531. orders = []
  532. for order in current_page:
  533. csp = AgentCloudServicePackage.objects.filter(id=order.csp_id).first()
  534. service_name = csp.service_name if csp else order.csp_id
  535. agent_customer_info = AgentCustomerInfo.objects.filter(id=order.ac_id).first()
  536. company_name = agent_customer_info.company_name if agent_customer_info else order.ac_id
  537. ado_id = order.id
  538. settled_profit = \
  539. AgentDeviceOrderInstallment.objects.filter(ado_id=ado_id, status=2).aggregate(Sum('amount'))[
  540. 'amount__sum'] or 0
  541. orders.append({
  542. 'id': order.id,
  543. 'company_name': company_name,
  544. 'serial_number': order.serial_number,
  545. 'status': order.status,
  546. 'service_name': service_name,
  547. 'profit_amount': order.profit_amount,
  548. 'profit': order.profit,
  549. 'settled_profit': settled_profit,
  550. 'settlement_time': order.settlement_time,
  551. 'remark': order.remark,
  552. 'created_time': order.created_time
  553. })
  554. response_data = {
  555. 'list': orders,
  556. 'total_profit': total_profit,
  557. 'total': paginator.count,
  558. 'page': current_page.number,
  559. 'page_size': page_size,
  560. 'num_pages': paginator.num_pages,
  561. }
  562. return response.json(0, response_data)
  563. except Exception as e:
  564. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  565. def get_agent_account_withdraw(self, userID, request_dict, response):
  566. """
  567. 查询提现明细
  568. @param userID: userID
  569. @param request_dict: 请求参数
  570. @param response: 响应对象
  571. @return:
  572. """
  573. agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
  574. if not agent_customer_info:
  575. return response.json(104, 'Agent customer not found')
  576. ac_id = agent_customer_info.id
  577. try:
  578. agent_account_withdraw_qs = AgentAccountWithdraw.objects.filter(ac_id=ac_id).order_by('-updated_time')
  579. page = int(request_dict.get('page', 1)) # 默认为第一页
  580. page_size = int(request_dict.get('page_size', 10)) # 默认每页10条记录
  581. # 应用分页
  582. paginator = Paginator(agent_account_withdraw_qs, page_size)
  583. current_page = paginator.get_page(page)
  584. withdraw_list = []
  585. for withdraw in current_page:
  586. agent_customer_card = AgentCustomerCard.objects.filter(ac_id=ac_id).first()
  587. card_no = agent_customer_card.card_no
  588. masked_card_no = card_no[:4] + '*' * (len(card_no) - 8) + card_no[-4:]
  589. withdraw_list.append({
  590. 'id': withdraw.id,
  591. 'amount': withdraw.amount,
  592. 'created_time': withdraw.created_time,
  593. 'card_no': masked_card_no,
  594. 'status': withdraw.status,
  595. 'remark': withdraw.remark,
  596. 'arrival_time': withdraw.arrival_time
  597. })
  598. response_data = {
  599. 'list': withdraw_list,
  600. 'total': paginator.count,
  601. 'page': current_page.number,
  602. 'page_size': page_size,
  603. 'num_pages': paginator.num_pages,
  604. }
  605. return response.json(0, response_data)
  606. except Exception as e:
  607. # 出错时返回错误信息
  608. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  609. def get_check_balance(self, userID, response):
  610. """
  611. 查询余额
  612. @param userID: userID
  613. @param response: 响应对象
  614. @return:
  615. """
  616. agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
  617. if not agent_customer_info:
  618. return response.json(104, 'Agent customer not found')
  619. ac_id = agent_customer_info.id
  620. try:
  621. # 计算冻结金额
  622. frozen_amount_qs = AgentAccountWithdraw.objects.filter(ac_id=ac_id, status__in=[1, 2, 3])
  623. frozen_amount = frozen_amount_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  624. # 计算余额:已结算 - (退款+已打款)
  625. incomes_qs = AgentAccount.objects.filter(ac_id=ac_id, status=1)
  626. expense_qs = AgentAccount.objects.filter(ac_id=ac_id, status__in=[2, 3])
  627. incomes_all = incomes_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  628. expense_all = expense_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  629. total_profit = incomes_all - expense_all
  630. # 可用余额 = 总余额 - 冻结金额
  631. available_balance = total_profit - frozen_amount
  632. # 构造返回数据
  633. balance_data = {
  634. 'frozen_amount': frozen_amount, # 冻结金额
  635. 'total_profit': total_profit, # 总余额
  636. 'available_balance': available_balance # 可用余额
  637. }
  638. return response.json(0, balance_data)
  639. except Exception as e:
  640. # 出错时返回错误信息
  641. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  642. def get_data_statistics(self, userID, response):
  643. """
  644. 首页总览
  645. @param userID: userID
  646. @param response: 响应对象
  647. @return:
  648. """
  649. agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
  650. if agent_customer_info is None:
  651. agent_device_orders_qs = AgentDeviceOrder.objects.filter(is_del=False)
  652. agent_device_qs = AgentDevice.objects.filter()
  653. else:
  654. ac_id = agent_customer_info.id
  655. agent_device_orders_qs = AgentDeviceOrder.objects.filter(ac_id=ac_id, is_del=False)
  656. agent_device_qs = AgentDevice.objects.filter(ac_id=ac_id)
  657. now = datetime.now()
  658. today_start = datetime(now.year, now.month, now.day)
  659. yesterday_start = today_start - timedelta(days=1)
  660. tomorrow_start = today_start + timedelta(days=1)
  661. try:
  662. # 计算AgentDeviceOrderInstallment表 结算金额
  663. partial_settled_profit = AgentDeviceOrderInstallment.objects.filter(
  664. ado_id__in=agent_device_orders_qs.filter(status=1).values_list('id', flat=True),
  665. status=2
  666. ).aggregate(total=Sum('amount'))['total'] or 0
  667. # 总利润
  668. total_profit_all = \
  669. agent_device_orders_qs.filter(status__in=[1, 2], is_del=False).aggregate(
  670. total=Sum('profit'))[
  671. 'total'] or Decimal('0.00')
  672. total_profit_no = \
  673. agent_device_orders_qs.filter(status=1, is_del=False).aggregate(total=Sum('profit'))[
  674. 'total'] or Decimal('0.00')
  675. total_profit_no = total_profit_no - partial_settled_profit
  676. total_profit_yes = \
  677. agent_device_orders_qs.filter(status=2, is_del=False).aggregate(total=Sum('profit'))[
  678. 'total'] or Decimal('0.00')
  679. total_profit_yes = total_profit_yes + partial_settled_profit
  680. # 总营业额
  681. profit_amount_all = agent_device_orders_qs.filter(status__in=[1, 2], is_del=False).aggregate(
  682. total=Sum('profit_amount'))['total'] or Decimal('0.00')
  683. # 今日总营业额
  684. profit_amount_today_all = agent_device_orders_qs.filter(
  685. status__in=[1, 2],
  686. is_del=False,
  687. created_time__gte=int(today_start.timestamp()),
  688. created_time__lt=int(tomorrow_start.timestamp())
  689. ).aggregate(total=Sum('profit_amount'))['total'] or Decimal('0.00')
  690. # 昨日总营业额
  691. profit_amount_yesterday_all = agent_device_orders_qs.filter(
  692. status__in=[1, 2],
  693. is_del=False,
  694. created_time__gte=int(yesterday_start.timestamp()),
  695. created_time__lt=int(today_start.timestamp())
  696. ).aggregate(total=Sum('profit_amount'))['total'] or Decimal('0.00')
  697. # 激活设备数
  698. active_device_count_today = agent_device_qs.filter(
  699. status=1,
  700. created_time__gte=int(today_start.timestamp()),
  701. created_time__lt=int(tomorrow_start.timestamp())
  702. ).count()
  703. active_device_count_yesterday = agent_device_qs.filter(
  704. status=1,
  705. created_time__gte=int(yesterday_start.timestamp()),
  706. created_time__lt=int(today_start.timestamp())
  707. ).count()
  708. # 总设备数
  709. active_device_count = agent_device_qs.filter(status=1).count()
  710. inactive_device_count = agent_device_qs.filter(status=0).count()
  711. return response.json(0, {
  712. 'total_profit_all': total_profit_all,
  713. 'total_profit_no': total_profit_no,
  714. 'total_profit_yes': total_profit_yes,
  715. 'profit_amount_all': profit_amount_all,
  716. 'profit_amount_today_all': profit_amount_today_all,
  717. 'profit_amount_yesterday_all': profit_amount_yesterday_all,
  718. 'active_device_count_today': active_device_count_today,
  719. 'active_device_count_yesterday': active_device_count_yesterday,
  720. 'active_device_count': active_device_count,
  721. 'inactive_device_count': inactive_device_count,
  722. 'all_device_count': active_device_count + inactive_device_count
  723. })
  724. except Exception as e:
  725. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  726. def agent_apply_withdraw(self, userID, request_dict, response):
  727. """
  728. 用户提现申请
  729. @param userID: userID
  730. @param request_dict: 请求参数
  731. @param request_dict amount: 金额
  732. @param response: 响应对象
  733. @return:
  734. """
  735. amount = Decimal(request_dict.get('amount', '0.00'))
  736. if amount == Decimal('0.00'):
  737. return response.json(444)
  738. agent_customer_info = AgentCustomerInfo.objects.filter(user_id=userID).first()
  739. if not agent_customer_info:
  740. return response.json(104, 'Agent customer not found')
  741. ac_id = agent_customer_info.id
  742. try:
  743. # 计算余额:已结算 - (退款+已打款)
  744. incomes_qs = AgentAccount.objects.filter(ac_id=ac_id, status=1)
  745. expense_qs = AgentAccount.objects.filter(ac_id=ac_id, status__in=[2, 3])
  746. incomes_all = incomes_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  747. expense_all = expense_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  748. total_profit = incomes_all - expense_all
  749. # 冻结余额
  750. frozen_amount_qs = AgentAccountWithdraw.objects.filter(ac_id=ac_id, status__in=[1, 2, 3])
  751. frozen_amount = frozen_amount_qs.aggregate(total=Sum('amount'))['total'] or Decimal('0.00')
  752. # 可提现余额 = 总余额 - 冻结金额
  753. available_balance = total_profit - frozen_amount
  754. if amount < Decimal('1000.00'):
  755. return response.json(10, '每次提现最少为1000元')
  756. if amount > available_balance:
  757. return response.json(10, '余额不足,无法提现')
  758. # 提交提现申请
  759. acc = AgentCustomerCard.objects.filter(ac_id=ac_id).first()
  760. AgentAccountWithdraw.objects.create(ac_id=ac_id, status=1, card_id=acc.id, amount=amount,
  761. created_time=int(time.time()), updated_time=int(time.time()))
  762. return response.json(0)
  763. except Exception as e:
  764. print(e)
  765. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  766. def get_withdrawal_review(self, request_dict, response):
  767. """
  768. 后台用户提现申请审核列表
  769. @param request_dict: 请求参数
  770. @param request_dict company_name: 公司名称
  771. @param request_dict status: 审核状态
  772. @param response: 响应对象
  773. @return:
  774. """
  775. company_name = request_dict.get('company_name', None)
  776. status = request_dict.get('status', None)
  777. page = int(request_dict.get('page', 1)) # 默认为第一页
  778. page_size = int(request_dict.get('page_size', 10)) # 默认每页10条记录
  779. try:
  780. agent_account_withdraw_qs = AgentAccountWithdraw.objects.filter().order_by('updated_time')
  781. if company_name:
  782. agent_customer_info = AgentCustomerInfo.objects.filter(company_name=company_name).first()
  783. ac_id = agent_customer_info.id
  784. agent_account_withdraw_qs = agent_account_withdraw_qs.filter(ac_id=ac_id)
  785. if status:
  786. agent_account_withdraw_qs = agent_account_withdraw_qs.filter(status=status)
  787. # 提现id 公司名 审核状态 提现金额 余额
  788. paginator = Paginator(agent_account_withdraw_qs, page_size)
  789. current_page = paginator.get_page(page)
  790. review_list = []
  791. for review in current_page:
  792. ac_id = review.ac_id
  793. agent_customer_info = AgentCustomerInfo.objects.filter(id=ac_id).first()
  794. company_name = agent_customer_info.company_name
  795. review_list.append({
  796. "id": review.id,
  797. "company_name": company_name,
  798. "status": review.status,
  799. "amount": review.amount,
  800. "remark": review.remark,
  801. })
  802. response_data = {
  803. 'list': review_list,
  804. 'total': paginator.count,
  805. 'page': current_page.number,
  806. 'page_size': page_size,
  807. 'num_pages': paginator.num_pages,
  808. }
  809. return response.json(0, response_data)
  810. except Exception as e:
  811. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  812. def update_withdrawal_review(self, userID, request_dict, response):
  813. """
  814. 后台提现审核
  815. @param request_dict: 请求参数
  816. @param request_dict id: 提现单id
  817. @param request_dict status: 提现单状态
  818. @param request_dict remark: 提现单备注
  819. @param response: 响应对象
  820. @return:
  821. """
  822. id = request_dict.get('id', None)
  823. status = request_dict.get('status', None)
  824. remark = request_dict.get('remark', "")
  825. if not all([id, status]):
  826. return response.json(444)
  827. try:
  828. agent_account_withdraw = AgentAccountWithdraw.objects.get(pk=id)
  829. agent_account_withdraw.status = status
  830. agent_account_withdraw.remark = remark
  831. agent_account_withdraw.save()
  832. if int(status) == 4:
  833. AgentAccount.objects.create(ac_id=agent_account_withdraw.ac_id,
  834. amount=agent_account_withdraw.amount,
  835. status=3,
  836. created_time=int(time.time()),
  837. updated_time=int(time.time()),
  838. remark=f"{userID}修改为已提现")
  839. return response.json(0)
  840. except Exception as e:
  841. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  842. def apply_agent(self, request_dict, response):
  843. """
  844. 代理申请
  845. @param request_dict: 请求参数
  846. @param request_dict name: 名字
  847. @param request_dict phone: 电话
  848. @param request_dict regin: 地区
  849. @param request_dict remark: 备注
  850. @param response: 响应对象
  851. @return:
  852. """
  853. name = request_dict.get('name', None)
  854. phone = request_dict.get('phone', None)
  855. regin = request_dict.get('regin', None)
  856. remark = request_dict.get('remark', "")
  857. if not all([name, phone, regin]):
  858. return response.json(444)
  859. # 去除非数字字符
  860. clean_phone = re.sub(r'\D', '', phone)
  861. if ApplyAgent.objects.filter(phone=clean_phone).exists():
  862. return response.json(174, 'Phone number already exists')
  863. ApplyAgent.objects.create(name=name, phone=clean_phone, regin=regin, remark=remark)
  864. return response.json(0, '申请已提交')