123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- # -*- coding: utf-8 -*-
- # !/usr/bin/env python
- import datetime
- import logging
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_datetime import to_datetime
- from apilib.utils_string import make_title_from_dict
- from apps.web.constant import DEALER_CONSUMPTION_AGG_KIND, Const
- from apps.web.device.models import Group, Device
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.base import FaultEvent, WorkEvent
- from apps.web.user.models import Card, CardRechargeOrder, CardConsumeRecord, MyUser, ServiceProgress, \
- UserVirtualCard, ConsumeRecord
- 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:
- return None
- if event_data.has_key('status') and event_data.get('isFaultClass'):
- return LSHBFaultEvent(self.deviceAdapter, event_data)
- elif event_data.has_key('funCode') and event_data['funCode'] in ['15', '16', '17', '1B']: # 沥森环保的卡消费,需要记录一下
- return LSHBRechargeEvent(self.deviceAdapter, event_data)
- elif event_data.has_key('funCode') and event_data['funCode'] in ['19','20']: # 在线卡流程
- return LSHBonlineCardEvent(self.deviceAdapter, event_data)
-
- else:
- return WorkEvent(self.deviceAdapter, event_data)
- class LSHBRechargeEvent(WorkEvent):
- def support_playback(self):
- return self.event_data.get('funCode') == '1B'
- def do(self, **args):
- if self.event_data.get('funCode') == '15':
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'IC') # type: Card
- if not card:
- return
- if card.frozen:
- logger.debug('{} has been frozen.'.format(repr(card)))
- return
- preBalance = RMB(self.event_data['money'])
- Card.update_balance(card.id, preBalance)
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- self.recharge_ic_card(card = card,
- preBalance = preBalance,
- rechargeType = 'append',
- order = card_recharge_order,
- need_verify = False)
- if self.event_data.get('funCode') == '16':
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if not card:
- return
- group = Group.objects.get(id = self.device['groupId'])
- newRcd = CardConsumeRecord(
- openId = card.openId,
- cardId = str(card.id),
- money = RMB(self.event_data['money']),
- devNo = self.device['devNo'],
- devType = self.device['devType']['name'],
- logicalCode = self.device['logicalCode'],
- groupId = str(group.id),
- address = group.address,
- groupNumber = self.device['groupNumber'],
- groupName = group.groupName
- )
- try:
- newRcd.save()
- Card.update_balance(card.id, card.balance - self.event_data['money'])
- except Exception, e:
- logger.error('save card consume rcd error=%s' % e)
- elif self.event_data.get('funCode') == '17':
- cardNo = self.event_data['cardNo']
- card = self.update_card_dealer_and_type(cardNo, 'IC')
- if not card:
- return
- if self.event_data.has_key('money'): # 如果有余额,先更新余额
- Card.update_balance(card.id, RMB(self.event_data['money']))
-
- elif self.event_data.get('funCode') == '1B': # 在线付款的用完后,需要根据实际消费,退还金币
- devNo = self.device['devNo']
- sequanceNo = self.event_data['sequanceNo']
- devCtrInfo = Device.get_dev_control_cache(devNo)
- if sequanceNo != devCtrInfo.get('sequanceNo'):
- logger.info('do finish event sequanceNo is error')
- return
- LeftMoney = float(self.event_data['money'])
- coins = float(devCtrInfo['coins'])
- backCoins = LeftMoney
- price = float(devCtrInfo['price'])
- refundRMB = RMB(price * (backCoins / coins))
- logger.debug(
- 'refund money is: {}; refund rmb is: {}'.format(str(backCoins), str(refundRMB.mongo_amount)))
- extra = []
- consumeDict = {}
- openId = devCtrInfo.get('openId', None)
- if not openId:
- logger.warning('open is null. devNo = {}, sequanceNo = {}'.format(self.device.devNo, sequanceNo))
- return
- user = MyUser.objects(openId=openId, groupId=self.device['groupId']).first()
- group = Group.get_group(self.device['groupId'])
- if refundRMB == RMB(0) or backCoins > coins or not self.device.is_auto_refund:
- extra.append({u'消费金额': u'{}(元)'.format(price)})
- else:
- try:
- if devCtrInfo.get('rechargeRcdId'):
- self.refund_net_pay(user, devCtrInfo, refundRMB, VirtualCoin(0), consumeDict, True)
- extra.append({u"消费金额": u"{}(元)".format(RMB(price) - refundRMB)})
- extra.append({u"退款金额": u"{}(元)".format(refundRMB)})
- elif devCtrInfo.get('vCardId'):
- vCard = UserVirtualCard.objects.filter(id=devCtrInfo['vCardId']).first()
- extra.append({u'优惠卡券': u'{}--{}'.format(vCard.cardName, vCard.cardNo)})
- extra.append({u"消费金额": u"使用优惠卡券抵扣"})
- else:
- self.refund_net_pay(user, devCtrInfo, RMB(0), VirtualCoin(backCoins), consumeDict, False)
- extra.append({u"消费金币": u"{}(金币)".format(VirtualCoin(coins-backCoins))})
- extra.append({u"退款金币": u"{}(金币)".format(refundRMB)})
- except Exception, e:
- logger.error('feedback coins error=%s' % e)
- return
- ServiceProgress.update_progress_and_consume_rcd(
- self.device['ownerId'],
- {
- 'open_id': openId, 'device_imei': self.device['devNo'],
- 'port': devCtrInfo.get('port', 0), 'isFinished': False
- },
- consumeDict)
- self.notify_user_service_complete(
- service_name='使用设备',
- openid=user.managerialOpenId if user.managerialOpenId else '',
- port='',
- address=group.address,
- reason='当前服务已完成,谢谢您的使用,祝您生活愉快!!',
- finished_time=to_datetime(self.recvTime).strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra)
- Device.invalid_device_control_cache(self.device['devNo'])
- class LSHBFaultEvent(FaultEvent):
-
- def do(self, **args):
- cmd = self.event_data.pop('cmd', None)
-
- if self.event_data['funCode'] != '01' or not cmd:
- return
-
- if cmd == '01' or cmd == '02': # 缺液或者缺货
- Device.update_dev_control_cache(self.device['devNo'], self.event_data)
-
- group = Group.get_group(self.device["groupId"])
-
- faultContent = self.event_data.get("statusInfo")
-
- if self.is_notify_dealer:
- self.notify_dealer(
- templateName="device_fault",
- title=u'注意!您的设备发生告警!',
- device=u'{}-{}'.format(self.device.devTypeName, self.device.logicalCode),
- fault=faultContent,
- location=u'{address}-{groupName}-{groupNumber}号设备({logicalCode})'.format(address=group["address"],
- groupName=group[
- "groupName"],
- groupNumber=self.device[
- "groupNumber"],
- logicalCode=self.device[
- "logicalCode"]),
- notifyTime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- )
-
- self.record(
- faultCode=self.event_data.get("FaultCode"),
- description=faultContent,
- title="注意!您的设备发生告警!",
- )
-
- logger.info('devNo=<{}> Report failure!!'.format(self.device.devNo))
-
-
- elif cmd == '04': # 上报工作中
- Device.update_dev_control_cache(self.device['devNo'], self.event_data)
-
- elif cmd == '00': # 消除故障
- ctrInfo = Device.get_dev_control_cache(self.device['devNo'])
- ctrInfo.update({'status': self.event_data.get('status')})
- ctrInfo.pop('funCode', None)
- ctrInfo.pop('statusInfo', None)
- Device.update_dev_control_cache(self.device['devNo'], ctrInfo)
-
- logger.info('devNo=<{}> Fault removal!!'.format(self.device.devNo))
-
- class LSHBonlineCardEvent(WorkEvent):
-
- def do(self, **args):
- if self.event_data.get('funCode') == '19': # 在线卡请求余额
- cardNo = self.event_data.get('cardNo', None)
- cardNoHex = self.event_data.get('cardNoHex', None)
- occupyData = self.event_data.get('occupyData')
- card = self.update_card_dealer_and_type(cardNo)
- if not card:
- logger.info('no bind card!! cardNo=<{}>'.format(cardNo))
- balance = 0
- else:
- #: 首先检查订单,并进行充值
- #: 用户首先在手机客户端充值,需要这个时刻刷卡上报事件将充值的订单同步上来
- card_recharge_order = CardRechargeOrder.get_last_to_do_one(str(card.id))
- if card_recharge_order:
- result = self.recharge_id_card(card=card,
- rechargeType='append',
- order=card_recharge_order)
- card.reload()
- if card.frozen:
- balance = 0
- else:
- balance = card.balance
- self.deviceAdapter.response_card_money(cardNoHex, balance, occupyData)
- elif self.event_data.get('funCode') == '20': # 在线卡请求更新卡余额
-
- cardNo = self.event_data.get('cardNo', None)
- cardNoHex = self.event_data.get('cardNoHex', None)
-
- occupyData = self.event_data.get('occupyData', None)
-
- card = self.update_card_dealer_and_type(cardNo)
-
- if not card:
- return
- else:
-
- card_left = RMB(card.balance)
- cardBalance = RMB(self.event_data.get('cardBalance', 0))
- if cardBalance >= card_left:
- # 处理充值的情况
- oper_money = cardBalance - card_left
-
- # 建立卡充值订单
- openId = card.cardNo
- cardId = card.id
- money = RMB(0)
- coins = RMB(oper_money)
- group = Group.get_group(self.device["groupId"])
- rechangeOrder = None
-
- cardRechangeOrder = CardRechargeOrder.new_one(openId, cardId, cardNo, money, coins, group,
- rechangeOrder,
- rechargeType="rewrite")
- cardRechangeOrder.update(remarks="经销商线下复写卡金额", status='finished')
-
- # 更新卡余额
- card.update(balance=cardBalance)
- # 充值必然是结算
- if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_WASHCAR_LSHB_NOTIFY:
- extra = []
- cacheInfo = Device.get_dev_control_cache(self.device.devNo)
- orderNo = cacheInfo.get('orderNo')
- order = ConsumeRecord.objects.get(orderNo=orderNo) # type:ConsumeRecord
- oldBalance = RMB(cacheInfo.get('oldBalance'))
- actualRefund = cardBalance - oldBalance
- spendMoney = order.money
- usedMoney = spendMoney - actualRefund
- newCard = self.update_card_dealer_and_type(cardNo)
- extra.append({"实体卡": u"{}--No:{}".format(card.cardName or card.nickName, card.cardNo)})
- extra.append({"使用金额": u"{} 元".format(usedMoney)})
- extra.append({"卡余额": u"{} 元".format(RMB(newCard.balance))})
- self.notify_user_service_complete(
- service_name='',
- openid=card.managerialOpenId,
- port=None,
- address=group['address'],
- reason=None,
- finished_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- extra=extra
- )
-
- # 结束
- logger.info(
- 'devNo=<{}> cardNo=<{}> offline_recharge=<{}> last_balance=<{}> now_balance=<{}>'.format(
- self.device.devNo, cardNo, oper_money, card_left, cardBalance))
-
-
- elif cardBalance < card_left:
- # 处理扣费的情况
- # 如果是扣费,必然是刷卡启动
- if self.device.devTypeCode == Const.DEVICE_TYPE_CODE_WASHCAR_LSHB_NOTIFY:
- self.notify_user(
- managerialOpenId=card.managerialOpenId,
- templateName="service_start",
- title=u'亲,您绑定的卡:%s(名称:%s),正在%s启动服务。\\n' % (card.cardNo,card.cardName,self.device.group.address),
- service=u"卡内余额{}元".format(card_left),
- time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- remark=""
- )
- oper_money = card_left - cardBalance
-
- servicedInfo = {
- DEALER_CONSUMPTION_AGG_KIND.CONSUME_CARD: oper_money.mongo_amount,
- 'cardNo': cardNo,
- 'cardBalance': cardBalance.mongo_amount
- }
-
- # 建立卡消费订单
- orderNo, cardOrderNo = self.record_consume_for_card(card, oper_money, servicedInfo=servicedInfo)
-
- # 更新卡余额
- card.update(balance=cardBalance)
- Device.update_dev_control_cache(self.device.devNo,{'orderNo':orderNo,'oldBalance':cardBalance})
-
- # 结束
- logger.info(
- 'devNo=<{}> cardNo=<{}> consume_balance=<{}> last_balance=<{}> now_balance=<{}>'.format(
- self.device.devNo, cardNo, oper_money, card_left, cardBalance))
-
- pass
- else:
- # 不处理
- logger.info('cardNo=<{}> no change return !!!')
-
- self.deviceAdapter.response_card_change_sucess(cardNoHex, cardBalance, occupyData)
|