123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- import time
- from apilib.monetary import VirtualCoin, RMB
- from apilib.utils_datetime import to_datetime
- from apps.web.constant import Const
- from apps.web.device.models import Device, Group
- from apps.web.eventer.base import FaultEvent, WorkEvent
- from apps.web.eventer import EventBuilder
- from apps.web.south_intf.platform import notify_event_to_north
- from apps.web.user.models import ServiceProgress, MyUser
- from apps.web.user.transaction_deprecated import refund_money
- logger = logging.getLogger(__name__)
- class builder(EventBuilder):
- def __getEvent__(self, device_event):
- event_data = self.deviceAdapter.analyze_event_data(device_event['data'])
- if event_data is None or 'cmdCode' not in event_data:
- return None
- if 'duration' in device_event:
- event_data.update({'duration': device_event['duration']})
- if event_data['cmdCode'] in ("16", "10"):
- return ChargingHongZhuoWorkEvent(self.deviceAdapter, event_data)
- if event_data['cmdCode'] == '0A':
- return FaultEvent(self.deviceAdapter, event_data)
- return None
- class ChargingHongZhuoWorkEvent(WorkEvent):
- SUCCESS = "01"
- FAIL = "00"
- def support_playback(self):
- return self.event_data['cmdCode'] == '16'
- def do(self, **args):
- devNo = self.device['devNo']
- logger.info('hongzhuo charging event detected, devNo=%s,curInfo=%s' % (devNo, self.event_data))
- if self.event_data['cmdCode'] == '16':
- lineInfo = Device.clear_port_control_cache(devNo, str(self.event_data['port']))
- recvTime = to_datetime(self.recvTime)
- cardNo = lineInfo.get("cardNo")
- # 构建 发向山东省平台的数据
- coins = float(lineInfo.get('coins', 0))
- if not coins:
- logger.info("Cache is missing or Offline card , pass!! ") # 缓存丢失 或者使用离线卡
- return
- northerDict = {
- "elec": self.event_data.get("elec"),
- "startTime": lineInfo.get("startTime"),
- "spendMoney": round(coins - self.event_data.get("leftMoney", 0),2) if coins > self.event_data.get("leftMoney", 0) else 0
- }
- # 刷卡启动的结束事件
- if cardNo:
- try:
- card = self.update_card_dealer_and_type(cardNo)
- user = MyUser.objects.filter(openId=card.openId, groupId=self.device["groupId"]).first()
- consumeDict = {
- "chargeIndex": self.event_data.get("portStr"),
- "reason": self.event_data.get("reason"),
- 'actualNeedTime': lineInfo.get("needTime"),
- "duration": self.event_data.get("duration"),
- "elec": self.event_data.get("elec")
- }
- # 设备支持余额回收并且 有余额可以回收
- refundMoney = self.event_data.get("leftMoney")
- if refundMoney and refundMoney > 0 and self.device.is_auto_refund:
- refundMoney = VirtualCoin(refundMoney)
- self.refund_money_for_card(refundMoney, str(card.id))
- consumeDict.update({
- "refundMoney": str(refundMoney)
- })
- desc = u'您使用的%s号端口充电,卡付款:%s元,给您退款:%s元' % (
- self.event_data['port'], lineInfo.get("coins"), refundMoney)
- self.notify_user(
- user.managerialOpenId if user else '',
- 'refund_coins',
- **{
- 'title': desc,
- 'backCount': u'金币:%s' % refundMoney,
- 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S')
- }
- )
- # 通知用户充电结束
- group = Group.get_group(self.device["groupId"])
- self.notify_user(
- managerialOpenId=user.managerialOpenId if user else "",
- templateName="service_complete",
- title=u"\\n\\n结束原因:\\t\\t{reason}\\n\\n设备编号:\\t\\t{logicalCode}-{port}\\n\\n服务地址:\\t\\t{group}".format(
- reason=self.event_data["reason"],
- logicalCode=self.device["logicalCode"],
- port=self.event_data["port"],
- group=group["address"],
- ),
- service=u"充电桩充电服务",
- finishTime=datetime.datetime.strftime(recvTime, "%Y-%m-%d %H:%M:%S"),
- remark=u'谢谢您的支持'
- )
- # 结束充电服务进程,并且累计相关信息
- ServiceProgress.update_progress_and_consume_rcd(
- self.device["ownerId"],
- {
- "open_id": card.openId,
- "device_imei": self.device["devNo"],
- "port": int(self.event_data.get("port")),
- "isFinished": False
- },
- consumeDict
- )
- except Exception as e:
- logger.exception('deal with hongzhuo devNo=%s event e=%s' % (devNo, e))
- finally:
- logger.info('hongzhuo_notify_to_sd_norther:{}'.format(northerDict))
- self.notify_to_sd_norther(portStr=str(self.event_data.get("port")), consumeDict=northerDict)
- Device.clear_port_control_cache(devNo, str(self.event_data['port']))
- else:
- dataDict = dict()
- try:
- if not lineInfo.has_key('coins'):
- return
- if 'duration' in self.event_data and self.event_data['duration'] > 0:
- usedTime = self.event_data['duration']
- else:
- if (not lineInfo) or (not lineInfo.has_key('startTime')):
- return
- startTime = to_datetime(lineInfo['startTime'])
- if startTime > recvTime:#如果web服务器时间和事件监控服务器时间不一致,导致开始时间比事件时间还大
- usedTime = 0
- else:
- usedTime = int(round(((recvTime - startTime).total_seconds() / 60.0)))
- money = float(lineInfo['coins'])
- leftMoney = float(self.event_data['leftMoney'])
- if leftMoney > money:
- leftMoney = money
- workMode = self.event_data['mode']
- openId = lineInfo['openId']
- user = MyUser.objects(openId=openId, groupId=self.device['groupId']).first()
- if workMode == 2:
- # 计算退币金额
- backCoins = VirtualCoin(leftMoney)
- consumeDict = {'chargeIndex': self.event_data['port'],
- 'reason': self.event_data['reason'],
- 'duration': usedTime}
- if not self.device.is_auto_refund:
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': self.event_data['port'], 'isFinished': False}, consumeDict
- )
- else:
- refund_money(self.device, backCoins, lineInfo['openId'])
- consumeDict.update({'refundedMoney': str(backCoins)})
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': self.event_data['port'], 'isFinished': False}, consumeDict)
- desc = u'您使用的%s号端口充电,共付款:%s元,给您退款:%s元' % (
- self.event_data['port'], money, backCoins)
- self.notify_user(user.managerialOpenId if user else '', 'refund_coins', **{
- 'title': desc,
- 'backCount': u'金币:%s' % backCoins,
- 'finishTime': recvTime.strftime('%Y-%m-%d %H:%M:%S')
- })
- dataDict.update({'backCoins': float(backCoins)})
- except Exception, e:
- logger.exception('deal with hongzhuo devNo=%s event e=%s' % (devNo, e))
- finally:
- logger.info('hongzhuo_notify_to_sd_norther:{}'.format(northerDict))
- self.notify_to_sd_norther(portStr=str(self.event_data.get("port")), consumeDict=northerDict)
- if lineInfo.has_key('orderNo'):
- dataDict.update({'orderNo': lineInfo['orderNo']})
- notify_event_to_north(self.dealer, self.device, level = Const.EVENT_NORMAL,
- desc = self.event_data['reason'], dataDict = dataDict)
- # 刷卡启动事件
- elif self.event_data['cmdCode'] == "10":
- cardNo = self.event_data.get("cardNo")
- preFee = self.event_data.get("preFee")
- portStr = self.event_data.get("portStr")
- portCache = Device.get_dev_control_cache(self.device["devNo"]).get(portStr, {})
- if portCache.get("status", Const.DEV_WORK_STATUS_IDLE) == Const.DEV_WORK_STATUS_WORKING:
- logger.info("port is working!")
- card = self.update_card_dealer_and_type(cardNo)
- # 无效的卡
- if not card or not card.openId:
- logger.info("bad card, cardNo is {}".format(cardNo))
- self.deviceAdapter.response_use_card(self.FAIL, portStr, 0)
- return
- # 卡冻结
- if card.frozen:
- logger.info("card is frozen, cardNo is {}".format(cardNo))
- balance = float(card.balance) * 10
- self.deviceAdapter.response_use_card(self.FAIL, portStr, balance)
- return
- # 余额不足
- payMoney = RMB(preFee / 10.0)
- if float(card.balance) < float(payMoney):
- logger.info("card balance is not enough, cardNo is {}".format(card.balance))
- balance = float(card.balance) * 10
- self.deviceAdapter.response_use_card(self.FAIL, portStr, balance)
- return
- # 正常扣费流程, 先创建订单,再注册服务
- orderNo, cardOrderNo = self.record_consume_for_card(card, payMoney)
- ServiceProgress.register_card_service(
- self.device,
- int(portStr),
- card,
- {
- "cardOrderNo": cardOrderNo,
- "orderNo": orderNo,
- "money": payMoney.mongo_amount,
- "coin": payMoney.mongo_amount,
- "needTime": 0,
- }
- )
- leftBalance = float(card.balance - payMoney) * 10
- # 卡扣钱
- self.consume_money_for_card(card, payMoney)
- # 回复主板
- self.deviceAdapter.response_use_card(self.SUCCESS, portStr, leftBalance)
- # 通知已经扣费
- self.notify_balance_has_consume_for_card(card, payMoney)
- portDict = {
- 'startTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'status': Const.DEV_WORK_STATUS_WORKING,
- 'finishedTime': int(time.time()) + 12 * 60 * 60,
- 'coins': float(payMoney),
- 'isStart': True,
- 'price': str(float(payMoney)),
- 'openId': card.openId,
- 'refunded': False,
- "cardNo": cardNo
- }
- Device.update_dev_control_cache(self.device["devNo"], {portStr: portDict})
- # 设备上报的本地付费打开信息,需更新有用的端口信息
- elif self.event_data['cmdCode'] == "20":
- portStr = self.event_data.get("portStr")
- devCache = Device.get_dev_control_cache(self.device["devNo"])
- portCache = devCache.get(portStr)
- # 不干扰宝东的扫码支付
- if not portCache or not portCache.get("cardNo") or self.event_data.get("typeCode") != "01":
- logger.info("no port card start cache, so this info is useless!")
- return
- portCache.update({
- "coins": self.event_data.get("money"),
- })
|