123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- import datetime
- import logging
- import time
- from mongoengine import DoesNotExist
- from apilib.monetary import RMB, VirtualCoin
- from apilib.utils_string import make_title_from_dict
- from apilib.utils_sys import memcache_lock
- from apps.web.constant import Const
- from apps.web.core.accounting import Accounting
- from apps.web.dealer.models import Dealer
- from apps.web.device.models import WeifuleDeviceOrder, Group, Device
- from apps.web.eventer import EventBuilder
- from apps.web.eventer.base import WorkEvent
- from apps.web.user.models import ServiceProgress, UserVirtualCard, VCardConsumeRecord, \
- ConsumeRecord, Card, CardConsumeRecord, CardRechargeOrder, MyUser
- from apps.web.user.transaction_deprecated import refund_money
- logger = logging.getLogger(__name__)
- created_order_32 = 32
- executing_order_33 = 33
- finished_order_34 = 34
- id_card_request_35 = 35
- card_is_normal = 1
- card_not_in_db = 2
- card_is_forzen = 3
- card_has_not_order = 4 #IC卡适用
- card_less_balance = 5 #ID卡适用
- card_type_is_ic = 6#IC卡不允许当做ID卡使用
- 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['fun_code'] in [created_order_32,executing_order_33,finished_order_34,id_card_request_35]:
- return BlowerWEIFULEWorkEvent(self.deviceAdapter, event_data)
-
-
- class BlowerWEIFULEWorkEvent(WorkEvent):
- #微付乐的板子:根据设备上报上来的订单,创建正在服务的信息
- def create_progress_for_weifule_order(self,dev,consumeRcd,order):
- try:
- progress = ServiceProgress.objects.filter(weifuleOrderNo = order['id']).first()
- if progress:
- return
-
- attachParas = consumeRcd.attachParas
-
- consumeOrder = {
- 'orderNo': consumeRcd.orderNo,
- 'coin': consumeRcd.coin.mongo_amount,
- 'money': consumeRcd.money.mongo_amount,
- 'consumeType':'mobile_vcard' if u'虚拟卡' in consumeRcd.remarks else 'mobile'
- }
-
- new_service_progress = ServiceProgress(
- open_id=consumeRcd.openId,
- device_imei=consumeRcd.devNo,
- devTypeCode=dev['devType']['code'],
- port=-2,
- attachParas=attachParas if attachParas else {},
- start_time=int(order['createTime']),
- finished_time=24*60*60,
- consumeOrder = consumeOrder
- )
-
- new_service_progress.save()
- except Exception as e:
- logger.exception(e)
-
- def consume_money_for_ID_card(self,agentId,cardNo,balance,money):
- card = Card.objects.get(agentId=agentId,cardNo = cardNo)
- if card.balance < money:
- card.balance = RMB(0)
- else:
- card.balance = (card.balance - money)
- try:
- card.save()
- except Exception as e:
- logger.exception(e)
-
- return card
-
- def is_order_accepted(self,orderNo,funCode):
- return True if WeifuleDeviceOrder.objects.filter(orderNo = orderNo,funCode = funCode).count() > 0 else False
-
- def record_order_event(self,order,funCode):
- newObj = WeifuleDeviceOrder(orderNo = order['id'],funCode = funCode,order = order)
- try:
- newObj.save()
- except Exception,e:
- logger.exception('save order event error=%s' % e)
- pass
-
- def record_consume_for_card(self, card, money, orderNo):
- group = Group.get_group(self.device['groupId'])
- address = group['address']
- group_number = self.device['groupNumber']
- now = datetime.datetime.now()
- new_record = {
- 'orderNo': orderNo,
- 'time': now.strftime("%Y-%m-%d %H:%M:%S"),
- 'dateTimeAdded': now,
- 'openId': card.openId,
- 'ownerId': self.device['ownerId'],
- 'coin': money.mongo_amount,
- 'money': money.mongo_amount,
- 'devNo': self.device['devNo'],
- 'logicalCode': self.device['logicalCode'],
- 'groupId': self.device['groupId'],
- 'address': address,
- 'groupNumber': group_number,
- 'groupName': group['groupName'],
- 'devTypeCode': self.device.devTypeCode,
- 'devTypeName': self.device.devTypeName,
- 'isNormal': True,
- 'remarks': u'刷卡消费',
- 'errorDesc': '',
- 'sequanceNo': '',
- 'desc': '',
- 'attachParas': {},
- 'servicedInfo': {}
- }
- ConsumeRecord.get_collection().insert_one(new_record)
- # 刷卡消费也记录一条数据
- new_card_record = {
- 'orderNo': orderNo,
- 'openId': card.openId,
- 'cardId': str(card.id),
- 'money': money.mongo_amount,
- 'balance': card.balance.mongo_amount,
- 'devNo': self.device['devNo'],
- 'devType': self.device['devType']['name'],
- 'logicalCode': self.device['logicalCode'],
- 'groupId': self.device['groupId'],
- 'address': address,
- 'groupNumber': group_number,
- 'groupName': group['groupName'],
- 'result': 'success',
- 'remarks': u'刷卡消费',
- 'sequanceNo': '',
- 'dateTimeAdded': datetime.datetime.now(),
- 'desc': '',
- 'servicedInfo': {},
- 'linkedConsumeRcdOrderNo':str(new_record['orderNo'])
- }
- CardConsumeRecord.get_collection().insert(new_card_record)
- return new_record['orderNo'], new_card_record['orderNo']
- # {u'fee': 100, u'fun_code': 35, u'card_no': u'389924938'}
- def response_id_card(self,msgDict):
- data = msgDict
- cardNo = str(int(data['card_no']))
-
- Card.record_dev_card_no(self.device['devNo'],cardNo)
-
- card = self.find_card_by_card_no(cardNo)
-
- # 如果没有卡,直接返回
- if card is None:
- return self.deviceAdapter.response_card_balance(cardNo=data['card_no'], balance=0, result=card_not_in_db)
- elif card.frozen:
- return self.deviceAdapter.response_card_balance(cardNo=data['card_no'], balance=0, result=card_is_forzen)
-
- if card.cardType == 'IC':#如果以前是离线卡,只能用于离线卡,需要提醒用户
- return self.deviceAdapter.response_card_balance(cardNo=data['card_no'], balance=0, result=card_type_is_ic)
-
- card = self.update_card_dealer_and_type(cardNo, 'ID')
-
- #: 首先检查订单,并进行充值
- #: 用户首先在手机客户端充值,需要这个时刻刷卡上报事件将充值的订单同步上来
- 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()
-
- fee = RMB(data['fee']/100.0)
- if card.showBalance >= fee:
- result = card_is_normal
- # balance = card.showBalance * 100
- else:
- result = card_less_balance
- # balance = card.showBalance * 100
-
- if result == card_is_normal:
- card.showBalance -= fee
-
- self.deviceAdapter.response_card_balance(data['card_no'], card.showBalance, result)#返回的cardNo为16进制
-
- #确定发送成功了,然后再保存到数据库中
- card.save()
-
- def do(self, **args):
- devNo = self.device['devNo']
- funCode = self.event_data['fun_code']
- if funCode == id_card_request_35:
- self.response_id_card(self.event_data)
- else:#处理任务事件
- order = self.event_data['order']
-
- logger.info('weifule charging event detected, devNo=%s' % (devNo,))
- with memcache_lock(key = '%s-%s-%s-finished' % (devNo, order['id'], funCode), value = 1,
- expire = 120) as acquired:
- if acquired:
- self.deal_order(devNo, funCode, order, self.event_data)
- def deal_order(self,devNo,funCode,order,msgDict):
- dealer = Dealer.get_dealer(self.device['ownerId'])
- #开始洗衣最重要的功能核对订单,以及记录订单。
- #扫码情况下,需要检查订单,如果订单成功了,就不需要核查,如果订单失败的,需要核查,然后把没有扣的钱扣掉
- #刷卡情况下,正式把刷卡的钱扣掉,并产生消费的订单。
- #投币情况下,把投币扣费的记录记录下来即可
-
- #首先,统一回复确认报文
- if funCode in [created_order_32,executing_order_33,finished_order_34,id_card_request_35]:
- try:
- self.deviceAdapter.ack_event(order['id'], funCode)
- except Exception,e:
- logger.info('ack event devNo=%s err=%s' % (devNo,e))
- pass
-
- if funCode == created_order_32:#订单创建成功,开始收单,并检查账单
- #首先把端口状态给刷新掉(虽然是任务在设备上排队的通知,端口肯定是要忙起来的,先搞成忙)
- Device.update_dev_control_cache(self.device['devNo'],{'status':Const.DEV_WORK_STATUS_WORKING})
-
- if order['order_type'] == 'coin_start':#投币,直接记账即可
-
- Accounting.recordOfflineCoin(self.device,
- int(time.time()),
- int(order['amount']))
- elif order['order_type'] == 'card_start':#刷卡
-
- cardNo = str(int(order['card_no'],16))
-
- # 目前只支持在线卡哦
- card = self.update_card_dealer_and_type(cardNo, 'ID')
- balance = card.balance - RMB(order['amount']/100.0)
- self.update_card_balance(card, balance)
- #卡的显示余额同步下
- card.showBalance = card.balance
- card.save()
-
- fee = RMB(order['amount']/100.0)
-
- # 记录卡消费记录以及消费记录
- orderNo, cardOrderNo = self.record_consume_for_card(card, fee,order['id'])
- # 记录当前服务的progress,便于手机界面查询进度
-
- consumeDict = {'orderNo': orderNo,'money': order['amount']/100.0,'coin': order['amount']/100.0,'cardOrderNo': cardOrderNo}
- ServiceProgress.register_card_service_for_weifule(self.device, -2, card, consumeDict)
- # 通知用户,已经扣费
- self.notify_balance_has_consume_for_card(card, fee)
-
- elif order['order_type'] == 'apps_start':#扫码
- #检查订单是否失败,如果是失败的,需要纠正为成功,并把用户的余额扣除掉
- consumeRcd = ConsumeRecord.objects.filter(orderNo = order['id']).first()
-
- if consumeRcd is None or consumeRcd.isNormal:
- return
-
- consumeRcd.isNormal = True
- consumeRcd.save()
-
- if u'虚拟卡' in consumeRcd.remarks:
- pass#虚拟卡,不管成功与否都已经先扣掉了配额(有些不合理),这里什么都不处理
- else:
- user = MyUser.objects.get(openId = consumeRcd.openId,groupId = consumeRcd.groupId)
- user.pay(VirtualCoin(order['amount']/100.0))
-
- self.create_progress_for_weifule_order(self.device,consumeRcd,order)
-
-
- #如果是启动了订单,需要更新端口状态,需要刷新服务状态
- elif funCode == executing_order_33 :
-
- progress = ServiceProgress.objects.filter(weifuleOrderNo = order['id']).first()
- if not progress:
- return
-
- Device.update_dev_control_cache(self.device['devNo'],{
- 'status':Const.DEV_WORK_STATUS_WORKING,
- 'openId':progress.open_id,
- 'startTime':datetime.datetime.now().strftime(Const.DATETIME_FMT)
-
- }
- )
- progress.status = 'running'
- progress.runningTime = datetime.datetime.now()
- progress.save()
-
- #订单结束,需要把进行账单核对、记录更新、通知、退费等;
- elif funCode == finished_order_34 :
-
- Device.update_dev_control_cache(self.device['devNo'],{'status':Const.DEV_WORK_STATUS_IDLE})
-
- order['reason'] = order['reason']
-
- progress = ServiceProgress.objects.filter(weifuleOrderNo = order['id']).first()
- if progress is None:
- return
-
- progress.status = 'finished'
- progress.isFinished = True
- progress.save()
-
- consumeRcd = ConsumeRecord.objects.filter(orderNo = order['id']).first()
- if not consumeRcd:#投币的不会生成订单
- return
-
- try:
- group = Group.get_group(self.device['groupId'])
-
- consumeDict = {
- 'reason': order['reason'],
- }
-
- service = u'服务结束'
- if order['status'] == 'failed':
- service = u'订单异常结束。结束原因:%s' % order['reason']
- elif order['status'] == 'finished':
- service = u'订单正常结束'
-
- notifyDict = {
- 'service': service,
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
- 'remark': u'谢谢您的支持'
- }
-
- refundDict = {
- 'finishTime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- }
-
- coins = RMB(order['amount']/100.0)
-
- titleDictList = [
- {u'设备编号':self.device['logicalCode']},
- {u'地址':group['address']},
- {u'结束原因':order['reason']},
- ]
-
- notifyDict.update(
- {
- 'title': make_title_from_dict(titleDictList)
- }
- )
-
- backCoins = RMB(order['left_time']/order['total_time']*order['amount']/100.0)
-
- titleDictList = [
- {u'设备编号':self.device['logicalCode']},
- {u'付款':u'%s元' % coins},
- ]
- refundDict.update(
- {
- 'title':make_title_from_dict(titleDictList),
- 'backCount': u'金币:%s' % backCoins
- }
- )
-
-
- if u'虚拟卡' in consumeRcd.remarks:
- #退额度
- try:
- vRcd = VCardConsumeRecord.objects.get(orderNo = order['id'])
- vCard = UserVirtualCard.objects.get(id = vRcd.cardId)
- except DoesNotExist,e:
- logger.info('can not find the vCard id = %s' % vRcd.cardId)
- return
- #通知服务结束
- notifyOpenId = self.get_managerialOpenId_by_openId(vRcd.openId) if vCard else ''
- self.notify_user(notifyOpenId, 'service_complete',**notifyDict)
-
- #不需要退款,直接返回,不通知
- if self.device.is_auto_refund:
- vCard.refund_quota(vRcd,0,0.0,backCoins.mongo_amount)
- #刷卡的方式
- elif order['order_type'] == 'card_start' and order['card_no']:
- dealer = Dealer.get_dealer(ownerId = self.device['ownerId'])
- card = Card.objects.filter(agentId = dealer['agentId'],cardNo = str(int(order['card_no'],16))).first()
- if card is None:#离线卡没有绑定或者在线卡被解绑了
- return
-
- #先通知
- notifyOpenId = card.managerialOpenId if card else ''
- self.notify_user(notifyOpenId, 'service_complete',**notifyDict)
-
- #不需要退款,直接返回.在线卡需要退费,离线卡只登记使用记录就OK
- if self.device.is_auto_refund and card.cardType == 'ID':
- card = self.refund_money_for_card(RMB(backCoins), card.id)
- card.showBalance = card.balance
- card.save()
- consumeDict.update({'refundedMoney': str(backCoins)})
- self.notify_user(notifyOpenId, 'refund_coins', **refundDict)
-
- else:#扫码的
- user = MyUser.objects(openId = consumeRcd.openId, groupId = self.device['groupId']).first()
- if not user:
- return
-
- #通知服务结束
- notifyOpenId = user.managerialOpenId if user else ''
- self.notify_user(notifyOpenId, 'service_complete',**notifyDict)
-
- #如果需要退款,计算退款数据.
- if self.device.is_auto_refund: # 仅仅订单失败,才退款
- consumeDict.update({'refundedMoney': str(backCoins)})
- refund_money(self.device, backCoins, consumeRcd.openId)
- self.notify_user(notifyOpenId, 'refund_coins', **refundDict)
-
- ServiceProgress.update_progress_and_consume_rcd(self.device['ownerId'],{'weifuleOrderNo':order['id']}, consumeDict)
-
- except Exception,e:
- logger.exception('some exception happed,devNo=%s,e=%s' % (devNo,e))
- finally:
- pass
- else:
- pass
|