123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import requests
- from celery.utils.log import get_task_logger
- from django.conf import settings
- from mongoengine import DoesNotExist
- from typing import Optional, TYPE_CHECKING
- from apps.web.agent.models import Agent
- from apps.web.common.transaction.pay import PayManager
- from apps.web.common.transaction.refund import RefundManager
- from apps.web.constant import Const
- from apps.web.core.bridge.wechat import WechatClientProxy
- from apps.web.core.helpers import ActionDeviceBuilder
- from apps.web.core.models import WechatUserManagerApp, WechatUserSubscribeManagerApp
- from apps.web.core.payment import PaymentGateway
- from apps.web.dealer.models import Dealer, VirtualCard
- from apps.web.device.models import Group, Device
- from apps.web.helpers import get_wechat_user_manager_mp_proxy, get_wechat_user_sub_manager_mp_proxy, \
- get_wechat_user_messager_app
- from apps.web.promotion.models import InsuranceOrder, Insurance
- from apps.web.user.models import RechargeRecord, UserVirtualCard, RefundMoneyRecord
- from apps.web.user.transaction import post_pay
- from apps.web.user.transaction_deprecated import refund_post_pay
- from apps.web.utils import concat_front_end_url
- if TYPE_CHECKING:
- from apps.web.common.transaction.pay import PayRecordPoller
- from apps.web.user.models import MyUser
- from apps.web.core.payment.type_checking import PaymentGatewayT
- logger = get_task_logger('user.tasks')
- def report_to_user_via_wechat(openId, dealerId, templateName, url = None, **kwargs):
- if not settings.WECHAT_PUSH_ENABLED:
- logger.info('WECHAT_PUSH_ENABLED is false, you are probably in a dev/testing env')
- else:
- dealer = Dealer.objects(id = str(dealerId)).first() # type: Optional[Dealer]
- if not dealer:
- return {'info': 'dealer does not exist, id=%s' % (dealerId,)}
- agent = Agent.objects(id = str(dealer.agentId)).first() # type: Optional[Agent]
- if not agent:
- return {'info': 'agent does not exist, id=%s' % (dealer.agentId,)}
- try:
- wechat_mp_proxy = get_wechat_user_sub_manager_mp_proxy(agent)
- wechat_mp_proxy.publish(openId = openId, templateName = templateName, url = url, **kwargs)
- except Exception as e:
- logger.info('wechat_mp_proxy.publish is error=<{}>'.format(e))
- try:
- wechat_mp_proxy = get_wechat_user_manager_mp_proxy(agent)
- wechat_mp_proxy.notify(openId = openId, templateName = templateName, url = url, **kwargs)
- except Exception as e:
- logger.info('wechat_mp_proxy.notify is error=<{}>'.format(e))
- def send_msg_to_user_via_wechat(productId, openId, templateName, url = None, **kwargs):
- if not settings.WECHAT_PUSH_ENABLED:
- logger.info('WECHAT_PUSH_ENABLED is false, you are probably in a dev/testing env')
- else:
- try:
- product_agent = Agent.objects(id = productId).first()
- if not product_agent:
- logger.warning('user<id={}> has no product agent id.')
- return
- app = get_wechat_user_messager_app(product_agent)
- if templateName not in app.templateIdMap:
- logger.warning('is not support {}'.format(templateName))
- return
- template = app.templateIdMap[templateName]
- payload = kwargs.get(app.__class__.__name__, None)
- if not payload:
- logger.warning('not support subscribe message.')
- return
- if isinstance(app, WechatUserManagerApp):
- WechatClientProxy(app).notify_msg(openId, template, url, **payload)
- elif isinstance(app, WechatUserSubscribeManagerApp):
- WechatClientProxy(app).publish_msg(openId, template, url, **payload)
- else:
- logger.warning('no support app type.')
- except Exception as e:
- logger.exception(e)
- def poll_user_recharge_record(pay_app_type, record_id, interval, total_count):
- # type: (str, str, int, int)->None
- poller_cls = PayManager().get_poller(pay_app_type = pay_app_type)
- poller = poller_cls(
- record_id = record_id,
- interval = interval,
- total_count = total_count,
- record_cls = RechargeRecord,
- post_pay = post_pay) # type: PayRecordPoller
- poller.start()
- def test_sync():
- headers = {'Content-Type': 'application/json'}
- with requests.sessions.Session() as session:
- res = session.request(
- url = 'http://develop.5tao5ai.com/user/test',
- method = 'get',
- headers = headers,
- timeout = 15)
- return 'ok'
- def report_to_user_low_power(devNo, line, power, managerialOpenId, dealerId):
- """
- 低电量用户告警
- :param devNo:
- :param line:
- :param power:
- :param managerialOpenId:
- :param dealerId:
- :return:
- """
- dev = Device.get_dev(devNo)
- box = ActionDeviceBuilder.create_action_device(dev)
- result = box.get_port_info(line)
- group = Group.get_group(dev.get("groupId"))
- if result.get("power", 999) < int(power):
- report_to_user_via_wechat(
- openId = managerialOpenId or "",
- dealerId = dealerId,
- templateName = "device_fault",
- device = u"{}-{}".format(dev.logicalCode, line),
- title = u"充电设备低功率告警",
- level = u"一般",
- address = u"{}".format(group.get("groupName")),
- fault = u"您使用 <{}> 设备 <{}> 号充电端口进行充电,当前充电功率 <{}> 过低,可能会影响正常充电。".format(dev.logicalCode, line, power),
- notifyTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- )
- def notify_virtual_card_expired():
- """
- 虚拟卡卷到期提醒
- 提醒方式是 过期前三天 过期后三天 每天18:00提醒一次
- 霍珀的 虚拟卡 名称叫 电子月票 使用特性 is_huopo 来标识
- :return:
- """
- agentIdList = list()
- huoPoAgentIdList = list()
- # 找到需要通知的经销商
- agents = Agent.objects.only("id", "features")
- for agent in agents:
- if agent.features and "notify_virtual_card_expired" in agent.features:
- if "is_huopo" not in agent.features:
- agentIdList.append(str(agent.id))
- else:
- huoPoAgentIdList.append(str(agent.id))
- dealerIdList = [str(dealer.id) for dealer in Dealer.objects.filter(agentId__in = agentIdList).only("id", "agentId")]
- huoPoDealerIdList = [str(dealer.id) for dealer in
- Dealer.objects.filter(agentId__in = huoPoAgentIdList).only("id", "agentId")]
- # 先找母卡 母卡判断母卡是否停售或者删除
- cardTypes = VirtualCard.objects.filter(
- ownerId__in = dealerIdList + huoPoDealerIdList,
- status = 1
- )
- vCards = list()
- nowTime = datetime.datetime.now()
- for cardType in cardTypes:
- leftTime = nowTime - datetime.timedelta(days = min(cardType.needRenewMax, Const.VCARD_NEED_NOTIFY_TIME))
- rightTime = nowTime + datetime.timedelta(days = min(cardType.needRenewMin, Const.VCARD_NEED_NOTIFY_TIME))
- vCards.extend(
- UserVirtualCard.objects.filter(
- cardTypeId = str(cardType.id),
- expiredTime__gt = leftTime,
- expiredTime__lt = rightTime
- )
- )
- vCardInfoList = []
- for vCard in vCards:
- if vCard.dealerId in dealerIdList:
- cardName = u"优惠卡卷"
- else:
- cardName = u"电子月票"
- # 即将过期的
- if vCard.expiredTime > nowTime:
- title = u"您的{}<{}>即将过期,为避免影响您的正常使用,请及时续费充值".format(cardName, vCard.cardName)
- # 已经过期的
- else:
- title = u"您的{}<{}>已经过期,如需继续使用,请及时续费充值".format(cardName, vCard.cardName)
- expiredTime = vCard.expiredTime.strftime("%Y-%m-%d %H:%M:%S")
- vCardInfo = {
- "openId" : vCard.managerialOpenId,
- "dealerId" : vCard.dealerId,
- "cardNo" : vCard.cardNo,
- "cardName":cardName,
- "title" : title,
- "expiredTime" : expiredTime
- }
- vCardInfoList.append(vCardInfo)
- for vCardInfo in vCardInfoList:
- report_to_user_via_wechat(
- openId=vCardInfo.get("openId"),
- dealerId=vCardInfo.get("dealerId"),
- templateName="service_expired",
- title=vCardInfo.get("title"),
- cardNo=vCardInfo.get("cardNo"),
- expiredTime=vCardInfo.get("expiredTime"),
- remark=u"您可以打开公众号的个人中心,选择{},然后选择您的卡票进行续费".format(vCardInfo.get("cardName"))
- )
- def notify_insurance_order_subscribe(orderId): # type:(InsuranceOrder) -> None
- """
- 通知用户投保成功的通知
- {{first.DATA}}
- 保单名称:{{keyword1.DATA}}
- 保单种类:{{keyword2.DATA}}
- 保单单号:{{keyword3.DATA}}
- 支付保费:{{keyword4.DATA}}
- 保单生效时间:{{keyword5.DATA}}
- {{remark.DATA}}
- :param orderId: 用户保险单的 ID
- :return:
- """
- try:
- order = InsuranceOrder.objects.get(id = orderId)
- except DoesNotExist:
- logger.error("can not find insurance order <id={}> to report user!".format(orderId))
- return
- # 防止任务重入以及任务过于延时 做拦截
- if not order.effective:
- logger.warning(
- "insurance order <id={}> is not effective <effective={}>, need not to report user!".format(orderId,
- order.effective))
- return
- if order.endTime < datetime.datetime.now():
- logger.warning(
- "insurance order <id={}> is expired <endTime={}>, need not to report user!".format(orderId, order.endTime))
- return
- insurance = order.insurance # type: Insurance
- user = order.user # type: MyUser
- title = u"已加入保险保障,本服务由【中国平安】承保"
- url = concat_front_end_url(uri = '/user/index.html#/insurance/compensate')
- report_to_user_via_wechat(
- openId = user.managerialOpenId,
- dealerId = order.ownerId,
- templateName = "insurance_sub",
- title = title,
- name = insurance.name,
- category = insurance.categoryName,
- orderNo = order.orderNo,
- money = order.money,
- validTime = u"{}至{}".format(
- order.startTime.strftime("%Y-%m-%d %H:%M:%S"),
- order.endTime.strftime("%Y-%m-%d %H:%M:%S")
- ),
- remark = u"点击查看理赔条款>>>",
- url = url
- )
- def notify_insurance_order_cancel(orderId):
- """
- 通知用户保单取消的通知
- {{first.DATA}}
- 保单号:{{keyword1.DATA}}
- 产品名称:{{keyword2.DATA}}
- 被保险人:{{keyword3.DATA}}
- 保障期间:{{keyword4.DATA}}
- 退款金额:{{keyword5.DATA}}
- {{remark.DATA}}
- :param orderId: 用户保险单的ID
- :return:
- """
- try:
- order = InsuranceOrder.objects.get(id = orderId)
- except DoesNotExist:
- logger.error("can not find insurance order <id={}> to report user!".format(orderId))
- return
- # 防止被错误调用 判断一次状态
- if order.effective:
- logger.warning(
- "insurance order <id={}> is effective <effective={}>, need not to report user cancel!".format(orderId,
- order.effective))
- return
- insurance = order.insurance # type: Insurance
- user = order.user # type: MyUser
- title = u"退保成功通知"
- report_to_user_via_wechat(
- openId = user.managerialOpenId,
- dealerId = order.ownerId,
- templateName = "insurance_cancel",
- title = title,
- orderNo = order.orderNo,
- name = insurance.name,
- user = u"微信昵称-{}".format(user.nickname),
- cancelTime = u"于 {} 退保".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
- money = order.money,
- remark = u"感谢您的使用"
- )
- def pull_refund_order():
- """
- 拉取 状态不定的 退款订单
- """
- refundOrders = RefundMoneyRecord.objects.filter(
- status__in = [RefundMoneyRecord.Status.PROCESSING],
- datetimeAdded__gt = datetime.datetime.now() - datetime.timedelta(days = 2)
- )
- for refundOrder in refundOrders:
- rechargeOrder = RechargeRecord.objects.get(id = refundOrder.rechargeObjId) # type: RechargeRecord
- payOrder = rechargeOrder.payOrder
- payGateway = PaymentGateway.clone_from_order(payOrder) # type: PaymentGatewayT
- try:
- puller = RefundManager().get_poller(payGateway.pay_app_type)
- puller(refundOrder).pull(payGateway, payOrder, refund_post_pay)
- except Exception as e:
- logger.exception(e)
|