# -*- coding: UTF-8 -*-

import json
import datetime
from django.db.models import Q, Max, Min, Count
from django.utils.html import escape
from django.conf import settings
from api.models import CouponLaunch, CouponInfo, ShowCity
from api.models import FEEDBACK_RELATED_OBJECT_TYPE
from api.models import (
    Reservation, ServiceRegister, Service
)
from talos.models.diary import Diary
from talos.models.topic import (
    ActivityWinlist, ReplyHeadline,
)
from wiki.models import ItemTag, CollectTag
from gm_types.gaia import RESERVATION_STATUS, SECKILL_TYPE
from api.models.order import CashBackOrder
from api.models.types import SLIDE_TYPE
from api.models.others import UserBlackList
from api.models.business_channel import BusinessChannel
from api.models import VERIFY_CODE_TYPE
from api.models.doctor import Doctor
from api.models.hospital import Hospital
from api.tool.verification_code import VerifiedCode
from api.tool.image_utils import get_full_path
from rpc.tool.datatables import DataTable
from rpc.tool.protocol import gm_protocol
from api.models.types import (
    CASH_BACK_STATUS, SERVICE_FLAG, ORDER_STATUS, REPORT_REASON,
    REPORT_ACTIONS, REPORT_TYPE, POINTS_OPERATION, POINTS_TYPE, PAYMENT_TYPE,
    SERVICEREGISTER_STATUS, PROBLEM_REVIEW_STATUS_CHOICES, TAG_TYPE, RECOMMEND_TYPE,
    REFUND_STATUS, SERVICE_MONITOR_STATUS, SERVICE_OPERATION_TYPE, NEW_CASH_BACK_STATUS,
    PRIVATE_MESSAGE_PUSH_STATUS, ORDER_OPERATION_TYPE, ORDER_OPERATION_ROLE
)
from .utils import shorten_text
from gm_types.gaia import TAG_ALERT_TYPE, HERA_OPERATE_LOG_PACKAGE, HERA_OPERATE_LOG_ACTION
from gm_types.gaia import SERVICE_SELL_TYPE
from services.talos_service import diary_num_and_cover_by_id, topic_get_tags_by_id, topic_vote_amount_by_id

LIST_TYPE = (list, tuple, set)
STR_TYPE = (str, unicode)
DEFAULT_DBS = [getattr(settings, 'HERA_READ_DB', ''), 'default']


def get_db_key(dbs):
    for db in dbs:
        if db in settings.DATABASES:
            return db
    return None


class BackendUserDT(DataTable):
    def build_queryset(self, req_data=None, global_fields=None):
        options = self.parse_request_data(req_data)
        srch_opts = options.pop('search', {})
        order_opts = options.pop('order')

        using_dbs = DEFAULT_DBS
        using = get_db_key(using_dbs)

        q = self.init_q if self.init_q is not None else Q()
        global_srch = srch_opts.pop('_global', None)
        q &= self.global_query(global_fields, global_srch)
        q &= self.fields_query(srch_opts)

        if order_opts:
            order_fields = ['-%s' % (o['name']) if o['dir'] == 'desc' else o['name']
                            for o in order_opts]

        objs = self.model.objects.using(using).exclude(groups__name=u'医生')
        objs = objs.filter(q).distinct().order_by(*order_fields)
        return objs


class ArticleDT(DataTable):
    # Deprecated - zhongchengyang 20170817
    def getval_topic_info(self, obj):
        return {'id': obj.topic.id, 'title': obj.topic.ask}


class ServiceDT(DataTable):
    def build_queryset(self, req_data=None, global_fields=None):
        """overwrite this method for **** demand"""
        options = self.parse_request_data(req_data)
        srch_opts = options.pop('search', {})
        order_opts = options.pop('order')

        using_dbs = DEFAULT_DBS
        using = get_db_key(using_dbs)

        q = self.init_q if self.init_q is not None else Q()
        global_srch = srch_opts.pop('_global', None)
        q &= self.global_query(global_fields, global_srch)
        q &= self.fields_query(srch_opts)

        order_diary = False
        if order_opts:
            order_fields = ['-%s' % (o['name']) if o['dir'] == 'desc' else o['name']
                            for o in order_opts]
            order_fields = []
            for o in order_opts:
                if o['name'] == 'diary':
                    order_diary = True
                    of = '-diary_count' if o['dir'] == 'desc' else 'diary_count'
                    order_fields.append(of)
                else:
                    order_fields.append('-%s' % (o['name']) if o['dir'] == 'desc' else o['name'])

        objs = self.model.objects.using(using).filter(q)
        if order_diary:
            objs = objs.annotate(diary_count=Count('diary', distinct=True))

        objs = objs.distinct().order_by(*order_fields)
        return objs

    def getval_servicereg__id(self, obj):
        return obj.servicereg.last().id

    def getval_diary(self, obj):
        return obj.diary_set.distinct().count()

    def getval_order_cashback(self, obj):
        return obj.order_set.filter(cash_back_status=CASH_BACK_STATUS.SUCCESS).count()

    def getval_doctor__name(self, obj):
        return obj.doctor.name if obj.doctor else ''

    def getval_hospital__name(self, obj):
        return obj.hospital.name if hasattr(obj, 'hospital') and obj.hospital else ''

    def getval_dr_or_hosp(self, obj):
        val = ''
        if obj.service_flag == SERVICE_FLAG.HOSPITAL:
            val = obj.hospital.name if obj.hospital else ''
        else:
            val = obj.doctor.name if obj.doctor else ''
        return val

    def getval_discount(self, obj):
        if obj.is_multiattribute:
            return obj.items.aggregate(discount=Min('discount')).get('discount')
        else:
            return obj.discount

    def getval_pre_payment_price(self, obj):
        if obj.is_multiattribute:
            preprice_min = obj.items.aggregate(pre=Min('pre_payment_price')).get('pre')
            preprice_max = obj.items.aggregate(pre=Max('pre_payment_price')).get('pre')
            return '{}~{}'.format(preprice_min, preprice_max)
        else:
            return obj.pre_payment_price

    def getval_gengmei_price(self, obj):
        if obj.is_multiattribute:
            gengmei_min = obj.items.aggregate(gm=Min('gengmei_price')).get('gm')
            gengmei_max = obj.items.aggregate(gm=Max('gengmei_price')).get('gm')
            return '{}~{}'.format(gengmei_min, gengmei_max)
        else:
            return obj.gengmei_price

    def getval_service_type_desc(self, obj):
        return SERVICE_SELL_TYPE.getDesc(obj.service_type)

    def query_start_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_update_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_tags(self, srch_key, srch_val, regex=False):
        return Q(tags__id=srch_val)

    def query_itemwiki(self, srch_key, srch_val, regex=False):
        return Q(serviceitemwiki__itemwiki_id=srch_val)

    def query_high_com_service(self, srch_key, srch_val, regex=False):
        q = Q(service_type=SERVICE_SELL_TYPE.FENGXIANGGOU)
        if not int(srch_val):
            q = ~q
        return q


class CouponDT(DataTable):
    def query_start_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def getval_launched(self, obj):
        return CouponLaunch.objects.filter(coupon=obj).exists()

    def getval_get_num(self, obj):
        return CouponInfo.objects.filter(coupon=obj, user__isnull=False).count()

    def getval_campaign__name(self, obj):
        if getattr(obj, 'campaign', None):
            return obj.campaign.name
        return ''

    def getval_use_range(self, obj):
        condition = obj.get_condition()
        if condition.get('specials', None):
            return u'专场'
        else:
            return u'全场'

    def getval_coupon_type(self, obj):
        condition = obj.get_condition()
        if condition.get('prepay_threshold', 0):
            return u'满减'
        else:
            return u'直减'


class CouponInfoDT(DataTable):
    def getval_coupon(self, obj):
        return obj.coupon.name if obj.coupon else ''

    def getval_channel(self, obj):
        channel = ''
        if obj.channel:
            channel = BusinessChannel.getDesc(obj.channel)
        elif obj.coupon_launch:
            channel = BusinessChannel.getDesc(obj.coupon_launch.channel) if obj.coupon_launch.channel is None else ''
        return channel

    def getval_gift_name(self, obj):
        return obj.coupon_gift.name if obj.coupon_gift else ''


class DoctorDT(DataTable):
    def getval_person_phone(self, obj):
        try:
            phone = obj.user.person.phone
        except:
            phone = ''
        return phone

    def getval_validate_code(self, obj):
        try:
            phone = obj.user.person.phone
        except:
            phone = ''

        return VerifiedCode.generate(phone, VERIFY_CODE_TYPE.LOGIN) if phone else ''

    def getval_hospital__name(self, obj):
        return obj.hospital.name if getattr(obj, 'hospital', None) else ''

    def getval_doctor_conversation(self, obj):
        return obj.id if obj.user else ''  # 未绑定用户

    def getval_reservation(self, obj):
        return Reservation.objects.filter(schedule__doctor=obj, status=RESERVATION_STATUS.RESERVING).count()

    def getval_reservation_expired(self, obj):
        return Reservation.objects.filter(schedule__doctor=obj, status=RESERVATION_STATUS.EXPIRED).count()

    def query_online_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_created_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_share_topic_num(self, srch_key, srch_val, regex=False):
        if srch_val == '0':
            return Q(share_topic_num=srch_val)
        else:
            return Q(share_topic_num__gte=srch_val)

    def query_has_online_services(self, srch_key, srch_val, regex=False):
        if srch_val == '':
            return None
        q = Q(services__isnull=False)
        if srch_val == '1':
            return q
        else:
            return ~q


class PhoneRecordDT(DataTable):
    def getval_user__last_name(self, obj):
        return obj.user.last_name if getattr(obj, 'user', None) else ''

    def getval_doctor__name(self, obj):
        return obj.doctor.name if getattr(obj, 'doctor', None) else ''


class TopicDT(DataTable):
    # Deprecated - zhongchengyang 20170824
    def fields_query(self, srch_opts):
        q = Q()
        for field, fsrch in srch_opts.iteritems():
            val = self._search_value(fsrch)
            fn_qfield = 'query_{}'.format(field)
            if field == 'reply_num':
                if val == '1':
                    field = '{}__gt'.format(field)
                    val = '0'
            q &= getattr(self, fn_qfield, self._default_query)(field, val, fsrch['regex'])
        return q

    def getval_ask_wrap(self, obj):
        return shorten_text(obj.ask)

    def getval_answer_wrap(self, obj):
        return shorten_text(obj.answer)

    def getval_user__last_name(self, obj):
        return obj.user.last_name if getattr(obj, 'user', None) else ''

    def getval_reply_num(self, obj):
        return obj.topicreply_set.count()

    def getval_vote_num(self, obj):
        vote_amount = topic_vote_amount_by_id(id=obj.id).get('vote_amount')
        return vote_amount

    def getval_images(self, obj):
        images = []
        for image in obj.images.all():
            images.append(get_full_path(image.image_url))
        return images

    def getval_activity_is_win(self, obj):
        if obj.activity:
            win_list = ActivityWinlist.objects.filter(activity=obj.activity, person__user=obj.user, topic=obj.id)
            if win_list:
                return True
        return False

    def getval_tags(self, obj):
        # tags = [tag['name'] for tag in obj.get_tags()]
        self_tags = topic_get_tags_by_id(id=obj.id)
        tags = [tag['name'] for tag in self_tags]
        return tags

    def getval_last_reply(self, obj):
        if obj.topicreply_set.all():
            return obj.topicreply_set.all().order_by("-id")[0].content
        else:
            return u'无'

    def query_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_is_win(self, srch_key, srch_val, regex=False):
        if not srch_val:
            return None

        values = srch_val.split('|')
        if len(values) < 2:
            return None

        activity_id = int(values[0])
        key = values[1]
        win_topic_ids = ActivityWinlist.objects.filter(activity_id=activity_id).distinct().values('topic')
        if key == '0':
            return Q(activity=activity_id) & ~Q(id__in=win_topic_ids)
        elif key == '1':
            return Q(activity_id=activity_id) & Q(id__in=win_topic_ids)

        return None


class UserDT(DataTable):
    def getval_topic_num(self, obj):
        return obj.problem_user.count()

    def getval_diary_num(self, obj):
        return obj.diaries.count()

    def getval_order_num(self, obj):
        return obj.order_set.count()

    def getval_cellphone(self, obj):
        return obj.person.phone

    def getval_blacklist(self, obj):
        if obj.userblacklist_set.count() == 0:
            return False
        else:
            return True

    # def getval_membership_level(self, obj):
    #     if obj.userextra.membership_level == '1':
    #         return u'是'
    #     else:
    #         return u'否'

    def getval_bind(self, obj):
        try:
            if obj.person.phone is None or '':  # 判断是否能解绑
                return '绑定'
            else:
                return '解绑'
        except:
            # User has no person
            return ''

    # def query_membership_level(self, srch_key, srch_val, regex=False):
    #     if srch_val == '':
    #         return None
    #     q = Q(userextra__membership_level='1')
    #     if srch_val == '1':
    #         return q
    #     else:
    #         return ~q

    def query_cellphone(self, srch_key, srch_val, regex=False):
        return Q(person__phone__contains=srch_val)


class DeviceDT(DataTable):
    pass


class BlackListDT(DataTable):
    pass


class CampaignDT(DataTable):
    def getval_online_time(self, obj):
        if obj.online_time:
            return obj.online_time.strftime('%Y-%m-%d')
        return ''

    def getval_offline_time(self, obj):
        if obj.offline_time:
            return obj.offline_time.strftime('%Y-%m-%d')
        return ''

    def getval_status(self, obj):
        now_t = datetime.datetime.now()
        if now_t < obj.online_time:
            return u'即将开始'
        elif now_t > obj.offline_time:
            return u'已结束'
        else:
            return u'进行中'

    def query_online_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_offline_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class SpecialDT(DataTable):
    def getval_campaign__name(self, obj):
        if getattr(obj, 'campaign', None):
            return obj.campaign.name
        return ''

    def getval_seckill_status(self, obj):
        now_t = datetime.datetime.now()
        if obj.is_online and (obj.start_time and now_t < obj.start_time):
            return u'上线中,即将开始'
        elif obj.is_online and (obj.start_time and obj.end_time and obj.start_time <= now_t <= obj.end_time):
            return u'上线中,正在秒杀'
        elif obj.is_online and (obj.end_time and now_t > obj.end_time):
            return u'上线中,已结束'
        else:
            return u'已下线'

    def getval_seckill_type(self, obj):
        return SECKILL_TYPE.getDesc(obj.seckill_type)


    def query_seckill_status(self, srch_key, srch_val, regex=False):
        now_t = datetime.datetime.now()
        q = None
        if srch_val == '1':
            q = Q(is_online=True) & Q(start_time__gt=now_t)
        elif srch_val == '2':
            q = Q(is_online=True) & Q(start_time__lte=now_t) & Q(end_time__gte=now_t)
        elif srch_val == '3':
            q = Q(is_online=False) | Q(end_time__lt=now_t)
        return q

    def query_start_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class FeedbackDT(DataTable):
    def getval_feedbackcategory__title(self, obj):
        return obj.feedbackcategory.title if getattr(obj, 'feedbackcategory', None) else ''

    def getval_user__last_name(self, obj):
        return obj.user.last_name if getattr(obj, 'user', None) else ''


class FeedbackCategoryDT(DataTable):
    def getval_related_type(self, obj):
        return FEEDBACK_RELATED_OBJECT_TYPE.getDesc(obj.related_type)


class ReportDT(DataTable):
    # has moved to queries/ by zhongchengyang 2016-7-28
    def getval_user_name(self, obj):
        if obj.user:
            return obj.user.last_name if obj.user.last_name else obj.user.username
        return ''

    def getval_reason_text(self, obj):
        return REPORT_REASON.getDesc(obj.reason)

    def getval_text(self, obj):
        if obj.type == REPORT_TYPE.TOPIC:
            if obj.problem and obj.problem.user:
                if obj.problem.user.id == 22:
                    return obj.problem.ask if obj.problem else ''
            return obj.problem.answer if obj.problem else ''

        if obj.type == REPORT_TYPE.REPLY:
            return obj.topic_reply.content if obj.topic_reply else ''

    def getval_related_user(self, obj):
        if obj.type == REPORT_TYPE.TOPIC:
            return obj.problem.user.id if obj.problem and obj.problem.user else ''
        if obj.type == REPORT_TYPE.REPLY:
            return obj.topic_reply.user.id if obj.topic_reply and obj.topic_reply.user else ''

    def getval_related_user_name(self, obj):
        if obj.type == REPORT_TYPE.TOPIC:
            return obj.problem.user.last_name if obj.problem and obj.problem.user else ''
        if obj.type == REPORT_TYPE.REPLY:
            return obj.topic_reply.user.last_name if obj.topic_reply and obj.topic_reply.user else ''

    def getval_action_text(self, obj):
        return REPORT_ACTIONS.getDesc(obj.action) if obj.action else u'已处理'

    def getval_text_id(self, obj):
        if obj.type == REPORT_TYPE.TOPIC:
            return obj.problem.id if obj.problem else ''
        if obj.type in [REPORT_TYPE.REPLY, REPORT_TYPE.DIARY_REPLY]:
            return obj.topic_reply.id if obj.topic_reply else ''

    def query_related_user(self, srch_key, srch_val, regex=False):
        user_id = srch_val
        q = Q(problem__user__id=user_id) | Q(topic_reply__user__id=user_id)
        return q


class PreBlackListDT(DataTable):
    def getval_report_user_name(self, obj):
        return obj.report_user.last_name

    def getval_reported_user_name(self, obj):
        return obj.reported_user.last_name

    def getval_is_blocked(self, obj):
        try:
            user = UserBlackList.objects.filter(bind_user_id=obj.reported_user.id)
        except:
            return False
        if user:
            return True
        return False


class TopicReplyDT(DataTable):
    # Deprecated - zhongchengyang 20170817
    def getval_user__last_name(self, obj):
        return obj.user.last_name

    def getval_problem_name(self, obj):
        name = obj.problem.title if obj.problem.title else obj.problem.ask
        if name:
            return name
        else:
            return u'查看详情'

    def getval_problem_info(self, obj):
        id = obj.problem.id
        name = obj.problem.title if obj.problem.title else obj.problem.ask or obj.problem.answer[:20]
        return {'id': id, 'text': name}

    def getval_diary_info(self, obj):
        id = obj.diary_id
        text = obj.diary.title
        return {'id': id, 'text': text}

    def getval_content(self, obj):
        return obj.content[:20] + '...' if len(obj.content) > 20 else obj.content

    def getval_doctor_info(self, obj):
        if getattr(obj, 'doctor', None):
            return {'id': obj.doctor.id, 'name': obj.doctor.name}
        else:
            return ''

    def getval_last_reply_time(self, obj):
        return str(obj.problem.topicreply_set.all().order_by("-id")[0].reply_date)

    def getval_is_headline(self, obj):
        return ReplyHeadline.objects.filter(reply=obj).count() != 0

    def getval_vote_num(self, obj):
        return obj.topicreplyvote_set.count() or 0

    def query_problem_name(self, srch_key, srch_val, regex=False):
        return Q(problem__title__contains=srch_val) | Q(problem__ask__contains=srch_val)


# class PushTaskDT(DataTable):
#     def getval_to_device(self, obj):
#         text = u'无'
#         if obj.to_android:
#             text = u'Android'
#         if obj.to_ios:
#             text = u' IOS'
#         if obj.to_android and obj.to_ios:
#             text = u'Android IOS'
#         return text
#
#     def getval_creator_name(self, obj):
#         if obj.creator:
#             if obj.creator.last_name:
#                 return obj.creator.last_name
#             else:
#                 return obj.creator.username
#         else:
#             return ''
#
#     def getval_approver_name(self, obj):
#         if obj.approver:
#             if obj.approver.last_name:
#                 return obj.approver.last_name
#             else:
#                 return obj.approver.username
#         else:
#             return ''
#
#     def getval_jump_type(self, obj):
#         text = u''
#         if obj.topic:
#             text += u'话题'
#         if obj.service:
#             text += u'美购'
#         if obj.special:
#             text += u'专题'
#         if obj.diary:
#             text += u'日记本'
#         if obj.tag:
#             text += u'圈子'
#         if obj.url:
#             text += u'网页'
#         if obj.activity:
#             text += u'免费活动'
#         return text
#
#     def getval_approve_status(self, obj):
#         return u'通过审核' if obj.approver else u'未审核'


class BodyPartDT(DataTable):
    def getval_tag_name(self, obj):
        return unicode(obj.tag)


class DiaryDT(DataTable):
    # Deprecated - zhongchengyang 20170817
    def getval_user__last_name(self, obj):
        return obj.user.last_name if obj.user else ''

    def getval_doctor__name(self, obj):
        try:
            return obj.doctor.name if obj.doctor_id else ''
        except:
            return ''

    def getval_hospital__name(self, obj):
        try:
            return obj.hospital.name if obj.hospital_id else ''
        except:
            return ''

    def getval_service__name(self, obj):
        try:
            return obj.service.name if obj.service else ''
        except:
            return ''

    def getval_is_cash_back(self, obj):
        return True if obj.order and obj.order.cash_back_status == CASH_BACK_STATUS.SUCCESS else False

    def getval_cash_back_time(self, obj):
        try:
            cash_back_order = CashBackOrder.objects.get(order_id=obj.order_id) if obj.order else None
            if cash_back_order:
                return str(cash_back_order.created_at)
        except:
            pass
        return ''

    def getval_cash_back_order_id(self, obj):
        """
        返现号
        """
        try:
            cash_back_order = CashBackOrder.objects.get(order_id=obj.order_id) if obj.order else None
            if cash_back_order:
                return cash_back_order.id
        except:
            pass
        return ''

    def getval_has_service(self, obj):
        return True if obj.service else False

    def getval_has_doctor(self, obj):
        return True if obj.doctor_id else False

    def getval_not_empty(self, obj):
        # return True if obj.diary_amount != 0 else False
        diary_amount = diary_num_and_cover_by_id(id=obj.id).get('diary_amount')
        return True if diary_amount != 0 else False

    def getval_to_check_num(self, obj):
        q = Q(review_status=PROBLEM_REVIEW_STATUS_CHOICES.NOT_REVIEW, is_online=True)
        return obj.topics.filter(q).count()

    def query_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_last_modified(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_operation_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_is_cash_back(self, srch_key, srch_val, regex=False):
        q = ~Q(order__isnull=True) & Q(order__cash_back_status=CASH_BACK_STATUS.SUCCESS)
        if srch_val == u'1':
            return q
        else:
            return ~q

    def query_wait_review(self, srch_key, srch_val, regex=False):
        q = Q(
            service__isnull=False, order__isnull=False,
            order__cash_back_status=CASH_BACK_STATUS.WAIT,
        )
        if srch_val == '1':
            q &= Q(
                topics__review_status=PROBLEM_REVIEW_STATUS_CHOICES.NOT_REVIEW, is_online=True
            )
        return q

    def query_cash_back_status(self, srch_key, srch_val, regex=False):
        if not srch_val:
            return None
        q = None
        if srch_val == '1':
            # 待返现日记本
            q = Q(service__isnull=False) & Q(order__isnull=False) & Q(order__cash_back_status=CASH_BACK_STATUS.WAIT)
        elif srch_val == '2':
            # 已返现日记本
            q = Q(service__isnull=False) & Q(order__isnull=False) & Q(order__cash_back_status=CASH_BACK_STATUS.SUCCESS)
        return q

    def query_has_service(self, srch_key, srch_val, regex=False):
        q = ~Q(service__isnull=True)
        if srch_val == u'1':
            return q
        else:
            return ~q

    def query_has_doctor(self, srch_key, srch_val, regex=False):
        try:
            q = ~Q(doctor__isnull=True)
            if srch_val == u'1':
                return q
            else:
                return ~q
        except:
            return ''

    def query_not_empty(self, srch_key, srch_val, regex=False):
        if srch_val == u'1':
            return Q(topics__is_online=True)
        else:
            return Q()

    def query_service_is_online(self, srch_key, srch_val, regex=False):
        if srch_val == '1':
            return Q(service__is_online=True)
        elif srch_val == '0':
            return Q(service__is_online=False)
        return Q()

    def query_service_order_status(self, srch_key, srch_val, regex=False):
        if srch_val:
            return Q(order__status__in=srch_val)
        return Q()

    def query_reply_num(self, srch_key, srch_val, regex=False):
        if srch_val and srch_val.isdigit():
            return Q(reply_num__gt=srch_val)
        return Q()


class DoctorRegisterInfoDT(DataTable):
    pass


class SlideDT(DataTable):
    def getval_slide_type(self, obj):
        return SLIDE_TYPE.getDesc(obj.slide_type)

    def getval_desc(self, obj):
        return obj.title

    def getval_title(self, obj):
        if obj.slide_type == SLIDE_TYPE.TOPIC:
            return obj.topic.ask if obj.topic else ''
        elif obj.slide_type == SLIDE_TYPE.URL:
            return obj.url
        elif obj.slide_type == SLIDE_TYPE.SERVICE:
            return obj.service.name if obj.service else ''
        elif obj.slide_type == SLIDE_TYPE.DIARY:
            return obj.diary.title if obj.diary else ''
        elif obj.slide_type == SLIDE_TYPE.ZONE_SINGLE:
            return obj.zone_single.name if obj.zone_single else ''
        elif obj.slide_type == SLIDE_TYPE.TAG:
            return obj.tag.name if obj.tag else ''
        elif obj.slide_type == SLIDE_TYPE.SPECIAL:
            return obj.special.title if obj.special else ''
        else:
            return SLIDE_TYPE.getDesc(obj.slide_type)

    def query_effect_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_cities(self, srch_key, srch_val, regex=False):
        if srch_key is not None:
            show_cities = ShowCity.objects.filter(city_id=srch_val)
            slidies = [item.slide_id for item in show_cities]
            return Q(id__in=slidies)


class CityDT(DataTable):
    def getval_province__name(self, obj):
        return obj.province.name if getattr(obj, 'province', None) else ''

    def getval_has_hospital(self, obj):
        return obj.is_hospital_exists()


class SmallimageDT(DataTable):
    def getval_jump_type(self, obj):
        if obj.service:
            return u'美购'
        if obj.special:
            return u'专题'
        if obj.diary:
            return u'日记本'
        if obj.tag:
            return u'指定的圈子'
        if obj.url:
            return u'网页'
        if obj.topic:
            return u'帖子'
        if obj.activity:
            return u'免费活动'
        if obj.new_url == gm_protocol.my_points:
            return u'我的积分'
        if obj.new_url == u'gengmei://common_webview?url=http://backend.igengmei.com/hybrid/invitation/my_invitation':
            return u'邀请好友'


class DoctorRegisterDT(DataTable):
    pass


class PointsDT(DataTable):
    def query_add_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def getval_operation(self, obj):
        return POINTS_OPERATION.getDesc(obj.operation) if obj.operation else ''

    def getval_reason(self, obj):
        return POINTS_TYPE.getDesc(obj.reason) if obj.reason else ''

    def getval_user(self, obj):
        return obj.user.last_name if obj.user else ''


class HospitalDT(DataTable):
    def getval_city(self, obj):
        return obj.city.name if obj.city else ''


class FilterWordDT(DataTable):
    pass


class ItemWikiDT(DataTable):
    def getval_tag(self, obj):
        return str(obj.tag.id) + '.' + obj.tag.name if obj.tag else ''


class ServiceReserveDT(DataTable):
    def getval_type(self, obj):
        return PAYMENT_TYPE.getDesc(obj.service.payment_type)

    def getval_user__last_name(self, obj):
        return obj.user.last_name if obj.user else ''

    def getval_service__name(self, obj):
        return obj.service.name if obj.service else ''


class ServiceRegisterDT(DataTable):
    def getval_doctor__name(self, obj):
        return obj.doctor.name if obj.doctor else ''

    def getval_status(self, obj):
        return SERVICEREGISTER_STATUS.getDesc(obj.status)

    def getval_is_multiattribute(self, obj):
        temp = 1
        for attr in obj.attrs.filter(checked=True):
            count = 0
            for option in attr.options.filter(checked=True):
                count += 1
            temp = temp * count
        if temp > 1:
            return u'是'
        else:
            return u'否'

    def getval_discount(self, obj):
        if obj.items.filter(is_online=True).count() == 0:
            return u'未设置多属性'
        elif obj.items.filter(is_online=True).count() > 1:
            gengmei_min = obj.items.filter(is_online=True).aggregate(gm=Min('discount')).get('gm')
            gengmei_max = obj.items.filter(is_online=True).aggregate(gm=Max('discount')).get('gm')
            return '{}%~{}%'.format(gengmei_min, gengmei_max)
        else:
            return str(obj.items.filter(is_online=True).aggregate(gm=Max('discount')).get('gm')) + u'%'

    def getval_pre_payment_price(self, obj):
        if obj.items.filter(is_online=True).count() == 0:
            return u'未设置多属性'
        elif obj.items.filter(is_online=True).count() > 1:
            preprice_min = obj.items.filter(is_online=True).aggregate(pre=Min('pre_payment_price')).get('pre')
            preprice_max = obj.items.filter(is_online=True).aggregate(pre=Max('pre_payment_price')).get('pre')
            return '{}%~{}%'.format(preprice_min, preprice_max)
        else:
            return str(obj.items.filter(is_online=True).aggregate(gm=Max('pre_payment_price')).get('gm')) + u'%'

    def getval_gengmei_price(self, obj):
        if obj.items.filter(is_online=True).count() == 0:
            return u'未设置多属性'
        elif obj.items.filter(is_online=True).count() > 1:
            gengmei_min = obj.items.filter(is_online=True).aggregate(gm=Min('gengmei_price')).get('gm')
            gengmei_max = obj.items.filter(is_online=True).aggregate(gm=Max('gengmei_price')).get('gm')
            return '{}~{}'.format(gengmei_min, gengmei_max)
        else:
            return obj.items.filter(is_online=True).aggregate(gm=Max('gengmei_price')).get('gm')

    def getval_cash_back_rate(self, obj):
        if obj.items.filter(is_online=True).count() == 0:
            return u'未设置多属性'

        elif obj.items.filter(is_online=True).count() > 1:
            gengmei_min = obj.items.filter(is_online=True).aggregate(gm=Min('cash_back_rate')).get('gm')
            gengmei_max = obj.items.filter(is_online=True).aggregate(gm=Max('cash_back_rate')).get('gm')
            return '{}%~{}%'.format(gengmei_min, gengmei_max)
        else:
            return str(obj.items.filter(is_online=True).aggregate(gm=Max('cash_back_rate')).get('gm')) + u'%'

    def query_audit_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_edit_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_online_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class TagDT(DataTable):
    def getval_tag_type(self, obj):
        return TAG_TYPE.getDesc(obj.tag_type)

    def getval_recommend_type(self, obj):
        return RECOMMEND_TYPE.getDesc(obj.recommend_type)

    def getval_children(self, obj):
        return ', '.join([str(item) for item in obj.children_relations])

    def getval_parents(self, obj):
        return ', '.join([str(item) for item in obj.parents_relations])

    def getval_new_wiki(self, obj):
        item = ItemTag.objects.filter(tag_id=obj.id)
        collect = CollectTag.objects.filter(tag_id=obj.id)
        if item:
            return '{}: {}'.format('百科', item[0].item.name.encode("utf-8"))
        elif collect:
            return '{}: {}'.format('聚合', collect[0].collect.name.encode("utf-8"))
        return ''


class TagAlertDT(DataTable):
    def getval_alert_type(self, obj):
        return TAG_ALERT_TYPE.getDesc(obj.type)

    def getval_service_tag_name(self, obj):
        return obj.service_tag.name


class RecommendAppDT(DataTable):
    pass


class CashBackOrderDT(DataTable):
    def getval_service_name(self, obj):
        return obj.order.service.name

    def getval_service(self, obj):
        return obj.order.service.id

    def getval_user_name(self, obj):
        return obj.order.user.last_name

    def getval_user(self, obj):
        return obj.order.user.id

    def getval_item(self, obj):
        return obj.order.order_multiattribute

    def getval_hospital_name(self, obj):
        try:
            return obj.order.service.doctor.hospital.name
        except:
            return ''

    def getval_status(self, obj):
        return NEW_CASH_BACK_STATUS.getDesc(obj.status)

    def getval_diary_id(self, obj):
        try:
            return obj.order.diary.id
        except:
            return ''

    def getval_diary(self, obj):
        try:
            return obj.order.diary.title
        except Diary.DoesNotExist:
            return ''

    def getval_diary_name(self, obj):
        try:
            return obj.order.diary.name
        except Diary.DoesNotExist:
            return ''

    def getval_doctor_name(self, obj):
        return obj.order.service.doctor.name

    def getval_doctor(self, obj):
        return obj.order.service.doctor.id

    def getval_hospital(self, obj):
        return obj.order.service.doctor.hospital.id

    def getval_num(self, obj):
        q = Q(review_status=PROBLEM_REVIEW_STATUS_CHOICES.OK, is_online=True)
        try:
            return str(obj.order.diary.topics.filter(q).count()) + '/' + str(int(obj.fee / 50) + 1)
        except:
            return ''

    def getval_sell_doctor_name(self, obj):
        id = json.loads(obj.order.service_snapshot).get(u"doctor", None)
        return Doctor.objects.get(id=id).name

    def getval_sell_hospital_name(self, obj):
        id = json.loads(obj.order.service_snapshot).get(u"hospital", None)
        return Hospital.objects.get(id=id).name

    def query_created_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_updated_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_cashback_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_doctor_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__doctor__name__contains=srch_val)

    def query_hospital_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__doctor__hospital__name__contains=srch_val)

    def query_service_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__name__contains=srch_val)

    def query_address(self, srch_key, srch_val, regex=False):
        return Q(order__address__contains=srch_val)

    def query_user_name(self, srch_key, srch_val, regex=False):
        return Q(order__user__last_name__contains=srch_val)

    def query_phone(self, srch_key, srch_val, regex=False):
        return Q(order__phone__contains=srch_val)

    def query_payment_channel(self, srch_key, srch_val, regex=False):
        return Q(order__payment_channel=srch_val)


class RefundOrderDT(DataTable):
    def getval_service_name(self, obj):
        return obj.order.service.name

    def getval_service(self, obj):
        return obj.order.service.id

    def getval_user_name(self, obj):
        return obj.order.user.last_name

    def getval_user(self, obj):
        return obj.order.user.id

    def getval_item(self, obj):
        return obj.order.order_multiattribute

    def getval_doctor_name(self, obj):
        return obj.order.service.doctor.name

    def getval_hospital_name(self, obj):
        return obj.order.service.doctor.hospital.name

    def getval_doctor(self, obj):
        return obj.order.service.doctor.id

    def getval_hospital(self, obj):
        return obj.order.service.doctor.hospital.id

    def getval_status(self, obj):
        return REFUND_STATUS.getDesc(obj.status)

    def getval_sell_doctor_name(self, obj):
        id = json.loads(obj.order.service_snapshot).get(u"doctor", None)
        return Doctor.objects.get(id=id).name

    def getval_sell_hospital_name(self, obj):
        id = json.loads(obj.order.service_snapshot).get(u"hospital", None)
        return Hospital.objects.get(id=id).name

    def query_created_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_updated_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_refunded_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_doctor_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__doctor__name__contains=srch_val)

    def query_hospital_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__doctor__hospital__name__contains=srch_val)

    def query_service_name(self, srch_key, srch_val, regex=False):
        return Q(order__service__name__contains=srch_val)

    def query_address(self, srch_key, srch_val, regex=False):
        return Q(order__address__contains=srch_val)

    def query_user_name(self, srch_key, srch_val, regex=False):
        return Q(order__user__last_name__contains=srch_val)

    def query_phone(self, srch_key, srch_val, regex=False):
        return Q(order__phone__contains=srch_val)

    def query_payment_channel(self, srch_key, srch_val, regex=False):
        return Q(order__payment_channel=srch_val)

    def query_staff_time(self, srch_key, srch_val, regex=False):
        q = Q(order__orderoperation__optype__in=[ORDER_OPERATION_TYPE.ARBIT_APPROVE,
                                                 ORDER_OPERATION_TYPE.ARBIT_APPROVE])
        q &= Q(order__orderoperation__role=ORDER_OPERATION_ROLE.STAFF)
        return q & self._qry_time_range('order__orderoperation__operate_at', srch_val, regex)

    def query_optype(self, srch_key, srch_val, regex=False):
        q = Q()
        if isinstance(srch_val, list):
            for optype in srch_val:
                q |= Q(order__orderoperation__optype=int(optype))
        else:
            q |= Q(order__orderoperation__optype=int(srch_val))
        return q

    def getval_fee(self, obj):
        return obj.fee or obj.estimated_fee

    def query_user_reason(self, srch_key, srch_val, regex=False):
        q = Q()
        if srch_val:
            if isinstance(srch_val, list):
                for reason in srch_val:
                    q |= Q(user_reason__contains=reason)
            else:
                q |= Q(user_reason__contains=srch_val)
        return q

    def query_deal_function(self, srch_key, srch_val, regex=False):
        q = Q()
        if srch_val:
            if isinstance(srch_val, list):
                for deal_function in srch_val:
                    q |= Q(order__operation__optype=deal_function)
            else:
                q = Q(order__operation__optype=srch_val)
        return q


class ServiceMonitorDT(DataTable):
    def getval_service_name(self, obj):
        return obj.service.name

    def getval_service(self, obj):
        return obj.service.id

    def getval_item(self, obj):
        return obj.service.is_multiattribute

    def getval_hospital_name(self, obj):
        return obj.service.doctor.hospital.name

    def getval_hospital(self, obj):
        return obj.service.doctor.hospital.id

    def getval_doctor_name(self, obj):
        return obj.service.doctor.name

    def getval_doctor(self, obj):
        return obj.service.doctor.id

    def getval_handle_at(self, obj):
        if obj.handle_at:
            return str(obj.handle_at)[:19]
        return ''

    def getval_business_name(self, obj):
        return obj.service.doctor.business_partener.username

    def getval_times(self, obj):
        return obj.operations.filter(
            optype__in=[SERVICE_OPERATION_TYPE.ALERT, SERVICE_OPERATION_TYPE.SET_BLACK]).count()

    def getval_user_name(self, obj):
        if obj.operations.order_by('handle_at').last():
            operation = obj.operations.order_by('handle_at').last()
            return operation.operator.user.last_name or operation.operator.user.username
        else:
            return u'未受过处理'

    def getval_user(self, obj):
        return obj.operations.order_by('handle_at').last().operator.user.id if \
            obj.operations.order_by('handle_at').last() else u'未受过处理'

    def getval_status(self, obj):
        return SERVICE_MONITOR_STATUS.getDesc(obj.status)

    def query_service_name(self, srch_key, srch_val, regex=False):
        return Q(service__name__contains=srch_val)

    def query_hospital_name(self, srch_key, srch_val, regex=False):
        return Q(service__doctor__hospital__name__contains=srch_val)

    def query_doctor_name(self, srch_key, srch_val, regex=False):
        return Q(service__doctor__name__contains=srch_val)

    def query_handle_at(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_business_name(self, srch_key, srch_val, regex=False):
        return Q(service__doctor__business_partener__username__contains=srch_val)

    def query_refund_comment(self, srch_key, srch_val, regex=False):
        q = Q()
        if srch_val:
            if isinstance(srch_val, list):
                for reason in srch_val:
                    q |= Q(refund_comment__contains=reason)
            else:
                q |= Q(refund_comment__contains=srch_val)
        return q


class GreetingPopupDT(DataTable):
    def getval_jump_type(self, obj):
        if obj.topic:
            return u'话题'
        elif obj.diary:
            return u'日记本'
        elif obj.special:
            return u'美购专题'
        elif obj.service:
            return u'美购'
        elif obj.tag:
            return u'圈子'
        elif obj.activity:
            return u'免费活动'
        elif obj.url:
            return u'网址'
        elif obj.sec_image or obj.sec_image_ipx:
            return u'播放图片'
        else:
            return ''

    def query_start_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class CampaignImageLinkDT(DataTable):
    def getval_related_name(self, obj):
        if obj.link_type == SLIDE_TYPE.TOPIC:
            return obj.topic.ask if obj.topic else ''
        elif obj.link_type == SLIDE_TYPE.URL:
            return obj.url
        elif obj.link_type == SLIDE_TYPE.SERVICE:
            return obj.service.name if obj.service else ''
        elif obj.link_type == SLIDE_TYPE.DIARY:
            return obj.diary.title if obj.diary else ''
        elif obj.link_type == SLIDE_TYPE.ZONE_SINGLE:
            return obj.zone_single.name if obj.zone_single else ''
        elif obj.link_type == SLIDE_TYPE.TAG:
            return obj.tag.name if obj.tag else ''
        elif obj.link_type == SLIDE_TYPE.SPECIAL:
            return obj.special.title if obj.special else ''
        else:
            return SLIDE_TYPE.getDesc(obj.link_type)


def getval_package(obj):
    return HERA_OPERATE_LOG_PACKAGE.getDesc(obj.package_new)


class SimpleActionLogDT(DataTable):
    def getval_nickname(self, obj):
        user = obj.user
        if not user:
            return u''
        if user.last_name:
            return user.last_name
        else:
            return user.username

    def getval_object(self, obj):
        id = obj.object_id
        try:
            if obj.package == '美购上线申请' or obj.package == '美购注册':
                text = ServiceRegister.objects.get(id=id).name or u'-'
            elif obj.package == u'美购':
                text = Service.objects.get(id=id).name or u'-'
            else:
                text = id
        except:
            text = u''
        return {'id': id, 'text': text}

    def getval_action(self, obj):
        return HERA_OPERATE_LOG_ACTION.getDesc(obj.action_new)

    def getval_message_info(self, obj):
        message = obj.message[:560] + '...' if len(obj.message) > 560 else obj.message
        return {'id': obj.object_id, 'message': escape(message)}

    def query_action_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_nickname(self, srch_key, srch_val, regex=False):
        return Q(user__last_name__contains=srch_val) | Q(user__username__contains=srch_val)


class ConsultWikiDT(DataTable):
    def getval_wiki_name(self, obj):
        return obj.wiki.item_name if obj.wiki else ''


class TopicStickyDT(DataTable):
    # Deprecated - zhongchengyang 20170817
    def getval_topic__created_time(self, obj):
        return str(obj.topic.created_time)


class RecommendDoctorDT(DataTable):
    def getval_diary_info(self, obj):
        return {'id': obj.diary.id, 'title': obj.diary.title}

    def getval_person__user_id(self, obj):
        return obj.person.user.id

    def query_recommend_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class StockAlertDT(DataTable):
    def getval_diary__service__name(self, obj):
        return obj.diary.service.name if obj.diary.service else ""

    def getval_diary__price(self, obj):
        return obj.diary.price

    def getval_business_partener__name(self, obj):
        return obj.business_partener.username if obj.business_partener else ""

    def query_has_phone(self, srch_key, srch_val, regex=False):
        return Q(phone__isnull=False)

    def query_has_service(self, srch_key, srch_val, regex=False):
        return Q(diary__service__isnull=False)


class PrivateMessagePushDT(DataTable):
    def getval_target_name(self, obj):
        if obj.service_id:
            return obj.service.name
        elif obj.doctor_id:
            return obj.doctor.name
        elif obj.hospital_id:
            return obj.hospital.name
        else:
            return ''

    def getval_send_status(self, obj):
        now = datetime.datetime.now()
        send_time = obj.send_time
        if obj.status == PRIVATE_MESSAGE_PUSH_STATUS.OK:
            if send_time <= now:
                return u'已发送'
            else:
                return u'撤回'
        else:
            return u'未发送'

    def getval_send_time(self, obj):
        now = datetime.datetime.now()
        send_time = obj.send_time
        if obj.status == PRIVATE_MESSAGE_PUSH_STATUS.OK and now >= send_time:
            return send_time.strftime('%Y-%m-%d %H:%M:%S')
        else:
            return '--'

    def query_send_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_person__user_id(self, srch_key, srch_val, regex=False):
        return Q(person__user__id__contains=srch_val)


class ReservationDT(DataTable):
    def query_doctor_id(self, srch_key, srch_val, regex=False):
        return Q(schedule__doctor__id=srch_val)

    def getval_user(self, obj):
        return {
            'id': obj.user.id,
            'text': obj.user.last_name or obj.user.username,
        }

    def getval_address(self, obj):
        return obj.schedule.address.desc

    def getval_service(self, obj):
        return {
            'id': obj.order.service.id,
            'text': obj.order.service.name,
        }


class VersionToChannelDT(DataTable):
    pass


class ChannelDT(DataTable):
    def getval_versiontochannel_id(self, obj):
        versiontochannel = obj.versiontochannel_set.filter(is_released=False, packed=True).order_by(
            '-packed_time').last()
        return versiontochannel.id if versiontochannel else ''


class SpecialItemDT(DataTable):
    def getval_service__id(self, obj):
        return obj.service.id

    def getval_service__name(self, obj):
        return obj.service.name

    def getval_service__is_online(self, obj):
        if obj.service.is_online:
            return '是'
        else:
            return '否'

    def getval_pre_payment_price(self, obj):
        service = obj.service
        pre_payment_price = service.pre_payment_price
        if service.is_multiattribute:
            pre_payment_price = service.items.aggregate(c=Min('pre_payment_price')).get('c')
        return pre_payment_price

    def getval_gengmei_price(self, obj):
        service = obj.service
        gengmei_price = service.gengmei_price
        if service.is_multiattribute:
            gengmei_price = service.items.aggregate(c=Min('gengmei_price')).get('c')
        return gengmei_price

    def getval_discount(self, obj):
        service = obj.service
        discount = service.discount
        if service.is_multiattribute:
            discount = service.items.aggregate(c=Min('discount')).get('c')
        return discount

    def getval_is_online(self, obj):
        return obj.service.is_online


class GadgetDT(DataTable):
    pass


class ContentDT(DataTable):
    """
    医生端运营内容
    """

    def query_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class PopupsDT(DataTable):
    """
    医生端轮播图
    """

    def query_begin_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class DoctorSlideDT(DataTable):
    """
    医生端弹窗
    """

    def query_begin_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def query_end_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class BulletinDT(DataTable):
    """
    医生端消息公告
    """

    def query_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)


class ShareDT(DataTable):
    """
    分享文案配置
    """
    pass


class StatementDT(DataTable):
    def getval_doctor__account__city__name(self, obj):
        if obj.doctor.merchant.account is None:
            return ''
        if obj.doctor.merchant.account.city is None:
            return ''
        else:
            return obj.doctor.merchant.account.city.name

    def getval_doctor__account__province__name(self, obj):
        if obj.doctor.merchant.account is None:
            return ''
        if obj.doctor.merchant.account.province is None:
            return ''
        else:
            return obj.doctor.merchant.account.province.name


class StatementOrderDT(DataTable):
    def getval_service__name(self, obj):
        return json.loads(obj.service_snapshot).get('name')

    def getval_total_number(self, obj):
        return json.loads(obj.service_snapshot).get('gengmei_price')

    def getval_pre_payment_price(self, obj):
        return json.loads(obj.service_snapshot).get('pre_payment_price')

    def getval_settle_price(self, obj):
        if obj.orderstatementrelationship.installment:
            # return obj.service_price - obj.discount
            return obj.servicesnapshot.pre_payment_price - obj.discount
        else:
            return obj.servicesnapshot.pre_payment_price - obj.discount
