# -*- coding: utf-8 -*- # !/usr/bin/env python import datetime from mongoengine import StringField, DateTimeField, IntField, ObjectIdField, Q, DoesNotExist, BooleanField, ListField from apps.web.constant import INSURANCE_CATEGORY from apps.web.core.db import Searchable, MonetaryField from apps.web.dealer.models import Dealer from apps.web.device.models import Group from apps.web.user.models import MyUser, RechargeRecord class InsuranceOrder(Searchable): """ 用户的上保订单 """ # 保险种类的ID insuranceId = StringField(verbose_name = u"母单") name = StringField(verbose_name=u"保险名称") # 用户的投保单号 orderNo = StringField(verbose_name = u"投保单号") # 用户的信息 openId = StringField(verbose_name = u"用户") ownerId = StringField(verbose_name = u"经销商") devNo = StringField(verbose_name = u"设备IMEI") logicalCode = StringField(verbose_name = u"设备编号") groupId = StringField(verbose_name = "投保地址") # 实际支付的保单的价格 money = MonetaryField(verbose_name = u"支付") # 可以报险的时间段 36小时 startTime = DateTimeField(verbose_name = u"起始时间") endTime = DateTimeField(verbose_name = u"结束时间") # 有效情况 退款后保单失效 effective = IntField(verbose_name = u"有效", choices = (0, 1), default = 1) # 关联的支付订单 rechargeRcdId = ObjectIdField(verbose_name = u"支付订单") # 报险 applyTime = DateTimeField(verbose_name = u"报险时间") phoneNumber = StringField(verbose_name = u"联系电话") # 保单的创建时间 dateTimeAdded = DateTimeField(verbose_name = u"创建时间", default = datetime.datetime.now) # meta = { # 'collection': 'InsuranceOrder' # } @staticmethod def get_insurance_order_no(insurance): """ 用户的投保单号 目前使用大保单号进行显示 :param insurance: :return: """ return insurance.insuranceNo @classmethod def create_by_recharge(cls, rechargeOrder, insurance): # type:(RechargeRecord, Insurance) -> InsuranceOrder """ 创建用户的保单 :param rechargeOrder: :param insurance: :return: """ order = cls( insuranceId = str(insurance.id), name = insurance.name, openId = rechargeOrder.openId, ownerId = rechargeOrder.ownerId, devNo = rechargeOrder.devNo, logicalCode = rechargeOrder.logicalCode, groupId = rechargeOrder.groupId, money = rechargeOrder.money, startTime = rechargeOrder.dateTimeAdded, endTime = rechargeOrder.dateTimeAdded + datetime.timedelta(hours = insurance.validTime), rechargeRcdId = rechargeOrder.id ) order.orderNo = cls.get_insurance_order_no(insurance) return order.save() @classmethod def get_user_effective_orders(cls, openId): # type:(str) -> QuerySet """ 获取用户 未进行退款的 保险订单 :param openId: :return: """ return cls.objects.filter(openId = openId, effective = 1) @classmethod def get_user_not_effective_orders(cls, openId): """ 获取用户已经完全失效的保险订单(退款的) """ return cls.objects.filter(openId = openId, effective = 0) @classmethod def get_user_legal_order(cls, openId): """ 获取用户可以报险的保险单 """ nowTime = datetime.datetime.now() return cls.get_user_effective_orders(openId).filter( endTime__gte=nowTime, startTime__lte=nowTime ) @classmethod def get_user_expired_order(cls, openId): """ 获取用户 已经失去报险资格的保险单 """ nowTime = datetime.datetime.now() return cls.get_user_effective_orders(openId).filter( Q(endTime__lt=nowTime) | Q(startTime__gt=nowTime) ) @classmethod def get_user_effective_by_recharge_order(cls, rechargeOrder): """ 通过充值订单 查询相应的保险单 有效的 """ return cls.get_user_legal_order(rechargeOrder.openId).filter(rechargeRcdId = rechargeOrder.id).first() @classmethod def apply(cls, orderId, phoneNumber, openId): """ 报险 :param orderId: :param phoneNumber: :param openId: :return: """ result = cls.objects.filter( id = orderId, openId = openId ).filter( effective = 1, applyTime = None, phoneNumber = None ).update( applyTime = datetime.datetime.now(), phoneNumber = phoneNumber ) return result @property def dealer(self): return Dealer.get_dealer(self.ownerId) @property def group(self): return Group.get_group(self.groupId) @property def user(self): return MyUser.objects.get(groupId = self.groupId, openId = self.openId) @property def rechargeOrder(self): return RechargeRecord.objects.get(id = self.rechargeRcdId) @property def insurance(self): try: insurance = Insurance.objects.get(id = self.insuranceId) except DoesNotExist: return None return insurance def cancel(self): """ 一般是退款后调用 将订单置为失效状态 :return: """ self.effective = 0 self.save() def to_dict(self): return { "id": str(self.id), "name": self.name, "openId": self.openId, "ownerId": self.ownerId, "devNo": self.devNo, "logicalCode": self.logicalCode, "groupId": self.groupId, "money": self.money, "startTime": self.startTime.strftime("%Y-%m-%d %H:%M:%S"), "endTime": self.endTime.strftime("%Y-%m-%d %H:%M:%S"), "dateTimeAdded": self.dateTimeAdded.strftime("%Y-%m-%d %H:%M:%S"), "applyTime": self.applyTime.strftime("%Y-%m-%d %H:%M:%S") if self.applyTime else "", "phoneNumber": self.phoneNumber or "" } from mongoengine.signals import post_save # 检测订单是否变为失效或者变为生效 def save_success_message(sender, document, created): # type:(InsuranceOrder.__class__, InsuranceOrder, bool) -> None from taskmanager.mediator import task_caller # 保单刚刚生效 发送通知给用户 保单生效 if created: task_caller("notify_insurance_order_subscribe", orderId = str(document.id)) return # 保单被取消的时候 发送 保单失效给用户 if not created and not document.effective: task_caller("notify_insurance_order_cancel", orderId = str(document.id)) return # 信号注册 post_save.connect(receiver = save_success_message, sender = InsuranceOrder) class Insurance(Searchable): """ 用户充电险 目前 """ # 大保单的保单号 insuranceNo = StringField(verbose_name = u"保单号", required = True) # 对外显示的名称 name = StringField(verbose_name = u"保险的名称") # 单次购买定价 price = MonetaryField(verbose_name = u"价格", required = True) # 报险的过期时间 validTime = IntField(verbose_name = u"有效期", default = 12) # 是否在售 onSale = BooleanField(verbose_name = u"销售状态", default = False) # 保险的种类 (目前只有充电险、后续可能会有骑行险或者是偷盗险一类的) category = StringField(verbose_name = u"种类", choices = INSURANCE_CATEGORY.choices()) # 支持的主设备类型 某些不支持的直接排除 supportMajorDeviceType = ListField(verbose_name = u"支持的主设备类型", default = [u"充电桩"]) @classmethod def get_on_sale_by_id(cls, _id): try: obj = cls.objects.get(id = _id, onSale = True) except DoesNotExist: return None return obj @classmethod def get_on_sale_by_category(cls, category): return cls.objects.filter(onSale=True, category=category).first() @property def categoryName(self): if self.category == INSURANCE_CATEGORY.CHARGE: return u"充电险" if self.category == INSURANCE_CATEGORY.STOLEN: return u"偷盗险" if self.category == INSURANCE_CATEGORY.CYCLE: return u"骑行险" return def to_dict(self): return { "id": str(self.id), "price": self.price, "validTime": self.validTime }