# coding: utf-8
import sys
import json
from datetime import datetime
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models import F
from django_bulk_update.helper import bulk_update
from gm_types.error import ERROR
from gm_types.gaia import BDTRANSFER_OBJECT_STATE, SINGLE_TYPE, TRANSFER_SOURCE, USER_GENDER
from gm_types.doctor import BDTRANSFER_APPLY_STATUS, BDTRANSFER_PIC_TYPE
from api.models import BDTransfer, Q, GaiaRPCFaultException, transaction, City, BDTransferClueTag, OPERATION_ACTION, \
    BDTransferCommunicationRecord, BDTransferSingleRecord, BuDan, Tag, BDTransferWillingProject, \
    BDTransferHistoryProject, Doctor, BDTransferWebKefu, BDTransferMonth, BDTransferMonthToBudan, BDTransferApplyRecord, \
    BDTransferApplyPic, BDTransferCommunicationRecordImg, Province
from api.models import BDTransferSingleRecordLog, City, Person, BDTransferOperationRecord
from api.tool.datetime_tool import get_timestamp_epoch
from api.tool.user_tool import get_user_from_context, get_user_by_id
from api.tool.buryiny_point_tool import bdtransfer_record
from hera.models import Config
from hera.queries.bdtransfer import BDTransferSingleRecordDQ
from rpc.cache import req_data_cache
from rpc.decorators import bind, bind_context
from rpc.tool.dict_mixin import to_dict
from rpc.tool.error_code import CODES, gen
from api.tasks.referral_data_task import export_referral_data_excel_task, export_clue_data_excel_task
from rpc.tool.queryset_tool import queryset_dec

reload(sys)
sys.setdefaultencoding("utf8")

uri_pre = 'hera/bdtransfer/'


@bind(uri_pre + 'get')
def get_bdtransfer_info(bdtransfer_id):
    """获取商务转诊完整信息用户渲染

    :param bdtransfer_id: 商务转诊ID
    :rtype: Dict[str, List[Dict]]
    """
    try:
        bdtransfer = BDTransfer.objects.prefetch_related(
            'operation_records', 'communication_records', 'willing_projects', 'history_projects', 'single_records'
        ).get(id=bdtransfer_id)
    except BDTransfer.DoesNotExist:
        gen(CODES.BDTRANSFER_NOT_EXIST)
    bdtransfer_creator = get_user_by_id(bdtransfer.creator)
    bdtransfer_formatted = dict(to_dict(bdtransfer, expands={'current_follow_up_consultant': ['username', 'first_name', 'last_name']}))
    bdtransfer_formatted['creator_info'] = to_dict(bdtransfer_creator, fields=['username', 'first_name', 'last_name'])
    bdtransfer_communicationrecord = [to_dict(_, expands={"user": ["id", 'username']})
                                           for _ in bdtransfer.communication_records.all()]
    for i in bdtransfer_communicationrecord:
        img_urls = BDTransferCommunicationRecordImg.objects.filter(bdtransfercommunicationrecord_id=i['id']).values_list('image_url', flat=True)
        i['img_urls'] = list(img_urls)
    return {
        "bdtransfer": bdtransfer_formatted,
        "bdtransfer_operationrecord": [to_dict(_, expands={"operate_user": ["id", "username"]})
                                       for _ in bdtransfer.operation_records.all()],
        "bdtransfer_communicationrecord": bdtransfer_communicationrecord,
        "bdtransfer_willing_projects": [to_dict(_) for _ in bdtransfer.willing_projects.all()],
        "bdtransfer_history_projects": [to_dict(_) for _ in bdtransfer.history_projects.all()],
        "bdtransfer_single_records": [
            to_dict(_, expands={"user": ["id", 'username'], "doctor": ["id", "name"], "project": ["id", "name"]})
            for _ in bdtransfer.single_records.all()
        ],
    }


@bind_context(uri_pre + 'edit')
def edit_bdtransfer_info(ctx, bdtransfer_info, bdtransfer_id=None, is_from=True):
    """更新和创建商务转诊信息

    :param bdtransfer_info: 商务转诊信息
    :param bdtransfer_id: 商务转诊ID, 如果存在则为更新，否则为创建
    :param is_from: 如果is_from为true, 表示创建信息来自个人池，否则为公池
    :return:
    """
    # TODO 是否创建过后分配的人才能修改改信息
    operate_user = get_user_from_context(ctx)
    willing_projects = bdtransfer_info.pop('willing_projects', [])
    user_city = bdtransfer_info.get('user_city', '')
    user_provice = bdtransfer_info.get('user_provice', '')
    if user_city and not user_provice:
        user_provice = City.objects.get(id=user_city).province_id
    if bdtransfer_id:
        bdtransfer_obj = BDTransfer.get_by_id(id=bdtransfer_id)
    check_contact_bd_query = Q()
    if bdtransfer_info['qq'] != '':
        check_contact_bd_query |= Q(qq=bdtransfer_info['qq'])
    if bdtransfer_info['weibo'] != '':
        check_contact_bd_query |= Q(weibo=bdtransfer_info['weibo'])
    if bdtransfer_info['wechat'] != '':
        check_contact_bd_query |= Q(wechat=bdtransfer_info['wechat'])
    if bdtransfer_info['user_phone'] != '':
        check_contact_bd_query |= Q(user_phone=bdtransfer_info['user_phone'])
    check_contact_bd_obj = BDTransfer.objects.filter(check_contact_bd_query)
    if bdtransfer_id:
        check_contact_bd_obj = check_contact_bd_obj.exclude(id=int(bdtransfer_id))
    check_contact_bd_obj = check_contact_bd_obj.first()
    if check_contact_bd_obj:
        if check_contact_bd_obj.qq != '' and check_contact_bd_obj.qq == bdtransfer_info['qq']:
            bdtransfer_exist_field = u'QQ号'
        elif check_contact_bd_obj.weibo != '' and check_contact_bd_obj.weibo == bdtransfer_info['weibo']:
            bdtransfer_exist_field = u'微博账号'
        elif check_contact_bd_obj.wechat != '' and check_contact_bd_obj.wechat == bdtransfer_info['wechat']:
            bdtransfer_exist_field = u'微信号'
        else:
            bdtransfer_exist_field = u'手机号'
        raise GaiaRPCFaultException(
            error=ERROR.UNKNOWN_ERROR, message=u'已存在相同 {} 的转诊对象, 重复数据信息为:'
                                               u'【姓名】{user};【手机号码】{user_phone};【微信号码】{wechat};'
                                               u'【跟进顾问】{current_follower};【对象状态】{state}'.format(
                bdtransfer_exist_field, user=check_contact_bd_obj.user if check_contact_bd_obj.user else u'无',
                user_phone=check_contact_bd_obj.user_phone if check_contact_bd_obj.user_phone else u'无',
                wechat=check_contact_bd_obj.wechat if check_contact_bd_obj else u'无',
                current_follower=check_contact_bd_obj.current_follow_up_consultant if check_contact_bd_obj.current_follow_up_consultant else u"无",
                state=BDTRANSFER_OBJECT_STATE.getDesc(check_contact_bd_obj.object_state)), data=None
        )
    with transaction.atomic():
        """
            创建或者更新商务转诊信息
            如果转诊信息为新增，则创建操作记录
            创建或者更新意向城市
            创建或者更新线索标签
        """
        update_or_create_bdtransfer_data = {
            "user": bdtransfer_info['user'],
            "user_phone": bdtransfer_info['user_phone'],
            "qq": bdtransfer_info['qq'],
            "wechat": bdtransfer_info['wechat'],
            "weibo": bdtransfer_info['weibo'],
            "consume_potential_min": bdtransfer_info["consume_potential_min"],
            "consume_potential_max": bdtransfer_info["consume_potential_max"],
            "intention": bdtransfer_info["intention"],
            "source": bdtransfer_info["source"],
            "potential_assess": bdtransfer_info["potential_assess"],
            'wechat_nickname': bdtransfer_info["wechat_nickname"],
            "email": bdtransfer_info['email'],
            "gender": bdtransfer_info['gender'],
            "call_phone": bdtransfer_info['call_phone'],
            "user_province": user_provice,
            "user_city": user_city,
            "comments": bdtransfer_info['comments'],
            "pooled_time": datetime.now(),
            "age": bdtransfer_info.get('age')
        }
        if bdtransfer_id:
            for attr, value in update_or_create_bdtransfer_data.items():
                setattr(bdtransfer_obj, attr, value)
            bdtransfer_obj.save(update_fields=update_or_create_bdtransfer_data.keys())

        else:
            import random, string
            client_id = None
            #多次尝试获取不重复的client_id
            for i in range(10):
                client_id = ''.join(random.sample(string.digits + string.ascii_uppercase, 6))
                if not BDTransfer.objects.filter(client_id=client_id):
                    break
            update_or_create_bdtransfer_data.update({
                'creator': bdtransfer_info.get('creator', ''),
                'is_assign': True if bdtransfer_info.get('current_follow_up_consultant', None) else False,
                'object_state': BDTRANSFER_OBJECT_STATE.HAS_PASSED_INFOMATION if is_from else BDTRANSFER_OBJECT_STATE.NOT_THROUGH_INFOMATION,
                'current_follow_up_consultant_id': bdtransfer_info.get('current_follow_up_consultant', None),
                'client_id': client_id
            })

            # if bool(is_from):
            update_or_create_bdtransfer_data.update({'assigner': bdtransfer_info.get('current_follow_up_consultant', None)})

            bdtransfer_obj = BDTransfer.objects.create(**update_or_create_bdtransfer_data)
            bdtransfer_obj.operation_records.create(
                operate_user=operate_user, action=OPERATION_ACTION.CREATE, content=u"转诊信息创建"
            )

        willing_cities_obj = list(City.objects.filter(id__in=bdtransfer_info['willing_cities']))
        # django 1.9 m2m can use set
        bdtransfer_obj.willing_cities.clear()
        bdtransfer_obj.willing_cities.add(*willing_cities_obj)

        clue_tags = list(BDTransferClueTag.objects.filter(id__in=bdtransfer_info['clue_tags']))
        bdtransfer_obj.clue_tags.clear()
        bdtransfer_obj.clue_tags.add(*clue_tags)

        bdtransfer_willing_project_handler.func(ctx, bdtransfer_obj.id, willing_projects)

        return bdtransfer_obj.id


@transaction.atomic
@bind_context(uri_pre + 'communication_record')
def bdtransfer_operation_communication_record_handler(ctx, record_id=None, bdtransfer_id=None, content=None, images=''):
    """商务转诊沟通记录Handler

    :param int record_id: 沟通记录ID
    :param int bdtransfer_id: 商务转诊ID
    :param unicode content: 沟通内容
    :return:
    """
    # TODO 权限控制
    def update_bd_last_follow_time(bdtransfer):
        try:
            bdtransfer.last_follow_time = bdtransfer.communication_records.order_by('-communication_time'). \
                only('communication_time').first().communication_time
        except BaseException:
            bdtransfer.last_follow_time = None
        bdtransfer.save()
    operate_user = get_user_from_context(ctx)
    if bdtransfer_id:
        bdtransfer = BDTransfer.get_by_id(id=bdtransfer_id)
    if record_id:
        communication_record = BDTransferCommunicationRecord.get_by_id(id=record_id)
    if record_id and content:  # 修改
        BDTransferCommunicationRecordImg.objects.filter(bdtransfercommunicationrecord_id=record_id).delete()
        if images:
            for i in json.loads(images):
                image = i.replace("'", '')
                BDTransferCommunicationRecordImg.objects.create(bdtransfercommunicationrecord_id=record_id, image_url=image)
        communication_record.content = content
        communication_record.save()
    elif bdtransfer_id and content:  # 新建
        bdtransfercommunicationrecord_id = bdtransfer.communication_records.create(user=operate_user, content=content).id
        if images:
            for i in json.loads(images):
                BDTransferCommunicationRecordImg.objects.create(bdtransfercommunicationrecord_id=bdtransfercommunicationrecord_id, image_url=i)
        update_bd_last_follow_time(bdtransfer)
    elif record_id:  # 删除
        communication_record.delete()
        BDTransferCommunicationRecordImg.objects.filter(bdtransfercommunicationrecord_id=record_id).delete()
        update_bd_last_follow_time(communication_record.bdtransfer)
    else:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, u'无效的操作', data=None)

@bind(uri_pre + 'get_images')
def get_bdtransfer_info(communicationrecord_id):
    """获取沟通记录的图片

    :param communicationrecord_id: 沟通记录ID
    :rtype:
    """
    try:
        img_urls = BDTransferCommunicationRecordImg.objects.filter(bdtransfercommunicationrecord_id=communicationrecord_id).values_list('image_url', flat=True)
    except BDTransfer.DoesNotExist:
        gen(CODES.BDTRANSFER_NOT_EXIST)

    return list(img_urls)


@bind_context(uri_pre + 'single_record')
def bdtransfer_single_record_handler(ctx, bdtransfer_id=None, doctor_id=None, project_ids=None,
                                     record_id=None, budan_id=None, consultation_time=None, appointment_time=None, is_terminate=False, operation_time=None):
    """商务转诊派单记录Handler

    :param bdtransfer_id: 商务转诊ID
    :param doctor_id: 医生ID
    :param project_ids: 项目对应的二级标签TAGS
    :param record_id: 派单记录ID
    :param budan_id: 补单ID
    :param is_terminate: 是否终止派单记录
    :return:
    """
    operate_user = get_user_from_context(ctx)
    if consultation_time is not None:
        consultation_time = datetime.strptime(consultation_time, '%Y-%m-%d %H:%M:%S')
    if appointment_time is not None:
        appointment_time = datetime.strptime(appointment_time, '%Y-%m-%d %H:%M:%S')
    if operation_time is not None:
        operation_time = datetime.strptime(operation_time, '%Y-%m-%d %H:%M:%S')
    # 修改single status 状态
    status = SINGLE_TYPE.NO_ORDER_FORM
    if appointment_time:
        status = SINGLE_TYPE.HAS_APPOINTMENT
    if consultation_time:
        status = SINGLE_TYPE.HAS_CONSULTATION

    if bdtransfer_id:
        bdtransfer = BDTransfer.get_by_id(bdtransfer_id)
    if record_id:
        bdtransfer_single_record = BDTransferSingleRecord.get_by_id(id=record_id)
    try:
        if doctor_id:
            doctor = Doctor.objects.get(id=doctor_id)
        if budan_id:
            budan = BuDan.objects.get(id=budan_id)
    except Doctor.DoesNotExist:
        gen(CODES.DOCTOR_NOT_FOUND)
    except BuDan.DoesNotExist:
        gen(CODES.BUDAN_NOT_FOUND)
    if project_ids:
        tag_objs = Tag.objects.filter(id__in=project_ids).all()
        assert len(tag_objs) == len(project_ids)
    with transaction.atomic():
        if record_id and doctor_id and project_ids:  # 修改
            bdtransfer_single_record.doctor = doctor
            bdtransfer_single_record.project.clear()
            bdtransfer_single_record.appointment_time = appointment_time
            bdtransfer_single_record.consultation_time = consultation_time
            bdtransfer_single_record.operation_time = operation_time
            bdtransfer_single_record.status = status
            bdtransfer_single_record.add(*tag_objs)
            bdtransfer_single_record.save()
        elif bdtransfer_id and doctor_id and project_ids:  # 新增
            bdtransfer_single_record = bdtransfer.single_records.create(
                user=operate_user, doctor=doctor, consultation_time=consultation_time,
                appointment_time=appointment_time, status=status, operation_time=operation_time
            )
            bdtransfer_single_record.project.add(*tag_objs)
        elif record_id and budan_id:  # 关联补单信息
            bdtransfer_single_record.budan = budan
            bdtransfer_single_record.status = SINGLE_TYPE.HAS_ORDER_FORM
            bdtransfer_single_record.confirm_user = operate_user
            bdtransfer_single_record.save()
        elif record_id and not is_terminate:  # 删除
            bdtransfer_single_record.delete()
        elif record_id and is_terminate:  # 终止派单, 但不删除
            bdtransfer_single_record.status = SINGLE_TYPE.HAS_TERMINATE
            bdtransfer_single_record.save()
        else:
            raise GaiaRPCFaultException(ERROR.UNKNOWN_ERROR, u'无效的操作', data=None)


@bind_context(uri_pre + 'willing_project')
def bdtransfer_willing_project_handler(ctx, bdtransfer_id, data):
    """商务转诊意向项目处理Handler

    :param int bdtransfer_id: 商务转诊ID
    :param List[Dict] data: 项目数据
    :return:
    """
    # TODO 权限控制
    bdtransfer = BDTransfer.get_by_id(bdtransfer_id)
    tag_objs = Tag.objects.filter(id__in=[_['opt'] for _ in data]).all()
    tag_obj_dict = {tag.id: tag for tag in tag_objs}
    create_willing_project = list()
    new_tags = []
    for project_info in data:
        if project_info['opt'] is None:
            continue
        willing_project = BDTransferWillingProject(
            tag=tag_obj_dict[int(project_info['opt'])], bdtransfer=bdtransfer
        )
        if project_info['start_time'] != "":
            willing_project.start_time = project_info['start_time']
        if project_info['end_time'] != "":
            willing_project.end_time = project_info['end_time']
        if project_info['comment'] != "":
            willing_project.comment = project_info['comment']

        new_tags.append(int(project_info['opt']))
        create_willing_project.append(willing_project)
    with transaction.atomic():
        bdtransfer.willing_projects.all().delete()
        BDTransferWillingProject.objects.bulk_create(create_willing_project)

    if bdtransfer.user_phone:
        try:
            p = Person.objects.get(phone=bdtransfer.user_phone)
            user_id = p.user_id
        except Person.DoesNotExist:
            user_id = None
        if new_tags and user_id:
            ctx.logger.app(**bdtransfer_record(user_id=user_id, tags=json.dumps(new_tags)))


@bind_context(uri_pre + 'history_project')
def bdtransfer_history_project_handler(ctx, bdtransfer_id, data):
    """商务转诊历史项目处理Handler

    :param int bdtransfer_id: 商务转诊ID
    :param List[Dict] data: 项目数据
    :return:
    """
    bdtransfer = BDTransfer.get_by_id(bdtransfer_id)
    tag_objs = Tag.objects.filter(id__in=[_['opt'] for _ in data]).all()
    tag_obj_dict = {tag.id: tag for tag in tag_objs}
    create_history_project = list()
    for project_info in data:
        history_project = BDTransferHistoryProject(
            tag=tag_obj_dict[int(project_info['opt'])], bdtransfer=bdtransfer
        )
        if project_info['time'] != "":
            history_project.know_time = project_info['time']
        create_history_project.append(history_project)
    with transaction.atomic():
        bdtransfer.history_projects.all().delete()
        BDTransferHistoryProject.objects.bulk_create(create_history_project)


@bind(uri_pre + 'confirm_infomation')
def bdtransfer_confirm_infomation(bdtransfer_id):
    bdtransfer = BDTransfer.get_by_id(bdtransfer_id)
    bdtransfer.object_state = BDTRANSFER_OBJECT_STATE.HAS_PASSED_INFOMATION
    bdtransfer.save(update_fields=['object_state'])


@bind(uri_pre+'statistics_detail_list')
def bdtransfer_record_detail_list(ids=None, start_time=None, end_time=None, status=None, list_stats=None, source=None):
    q_list = Q()

    if start_time and len(start_time) > 0:
        format_start_time = datetime.strptime('{} {}'.format(start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        q_list.add(Q(create_time__gte=format_start_time), Q.AND)
    if end_time and len(end_time) > 0:
        format_end_time = datetime.strptime('{} {}'.format(end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        q_list.add(Q(create_time__lte=format_end_time), Q.AND)
    if status:
        q_list.add(Q(object_state=status), Q.AND)
    if list_stats and len(list_stats):
        q_list.add(Q(object_state__in=list_stats), Q.AND)
    if ids and len(ids) > 0:
        q_list.add(Q(id__in=ids), Q.AND)
    if source:
        q_list.add(Q(source=source), Q.AND)

    query_filter = BDTransfer.objects \
        .annotate(status=F('object_state'),
                  citys=F('willing_cities__name'),
                  consultant_username=F('current_follow_up_consultant__username'),
                  consultant_last_name=F('current_follow_up_consultant__last_name'))\
        .values('id', 'user', 'citys', 'user_phone', 'wechat', 'status', 'create_time',
                'source', 'last_follow_time','consultant_username', 'consultant_last_name','creator')\
        .filter(q_list)
    data = []
    for each in list(query_filter):
        u = User.objects.get(id=each.get('creator'))
        creator_name = u.username if u.username else u.last_name
        if not creator_name:
            creator_name = ""
        follow_name = each.get('consultant_username') if each.get('consultant_username') else each.get('consultant_last_name')
        if not follow_name:
            follow_name = ''
        data.append({
            'bdtransfer_id': each.get('id'),
            'user': each.get('user'),
            'user_phone': each.get('user_phone'),
            'wechat': each.get('wechat'),
            'status': each.get('status'),
            'city': each.get('citys'),
            'create_time':
                each.get('create_time').strftime("%Y-%m-%d %H:%M:%S") if each.get('create_time') else '',
            'source': each.get('source'),
            'last_follow_time':
                each.get('last_follow_time').strftime("%Y-%m-%d %H:%M:%S") if each.get('last_follow_time') else '',
            'follow_up_consultant': follow_name,
            'creator': creator_name
        })

    return data


@bind(uri_pre+'statistics_record_list')
def get_data_from_record_log(start_time=None, end_time=None, source=None,
                           creator=None, current_consultant_id=None,
                           doctor_id=None, **kwargs):
    q_list = Q()
    data = list()
    if start_time and len(start_time) > 0:
        format_start_time = datetime.strptime('{} {}'.format(start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        q_list.add(Q(created_time__gte=format_start_time), Q.AND)
    if end_time and len(end_time) > 0:
        format_end_time = datetime.strptime('{} {}'.format(end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        q_list.add(Q(created_time__lte=format_end_time), Q.AND)
    if source and len(source) > 0:
        q_list.add(Q(singlerecord__dbtransfer__source=source), Q.AND)
    if creator and len(creator) > 0:
        q_list.add(Q(singlerecord__dbtransfer__creator=creator), Q.AND)
    if current_consultant_id and len(current_consultant_id) > 0:
        q_list.add(Q(singlerecord__dbtransfer__current_follow_up_consultant_id=current_consultant_id), Q.AND)
    if doctor_id and len(doctor_id) > 0:
        q_list.add(Q(singlerecord__doctor__id=doctor_id), Q.AND)

    if len(q_list) > 0:
        query_filter = BDTransferSingleRecordLog.objects \
            .annotate(record_id=F('singlerecord__id'),
                      record_status=F('status'),
                      bdtransfer_id=F('singlerecord__dbtransfer__id'),
                      budan_id=F('singlerecord__budan__id'),
                      budan_status=F('singlerecord__budan__status'),
                      consume_total_money=F('singlerecord__budan__extra_consume'),
                      commission=F('singlerecord__budan__payment'),
                      user_id=F('singlerecord__user_id'),
                      bdtransfer_status=F('singlerecord__dbtransfer__object_state'),
                      ) \
            .values('record_id', 'record_status',
                    'bdtransfer_id', 'budan_id',
                    'budan_status', 'consume_total_money',
                    'commission', 'user_id',
                    'bdtransfer_status') \
            .filter(q_list)
        data = list(query_filter)
    return data


@bind(uri_pre+'user_info')
def get_cache_user_info(role):

    """
    :param role:
           role value contains: creator, consultant
    :return:
    """
    data = list()
    if role == 'creator':
        query_filter = User.objects.\
            annotate(name=F('username'))\
            .filter(id__in=BDTransfer.objects.
                    exclude(Q(creator__isnull=False) & Q(creator='')).
                    values_list('creator', flat=True).distinct()).values('id', 'name')
        data = list(query_filter)
    elif role == 'consultant':
        query_filter = User.objects\
            .annotate(name=F('username'))\
            .filter(id__in=BDTransfer.objects
                    .filter(current_follow_up_consultant__id__isnull=False)
                    .values_list('current_follow_up_consultant__id', flat=True).distinct()
                    ).values('id', 'name')
        data = list(query_filter)
    return data


@bind(uri_pre+'doctor_info')
def get_bdtransfer_record_doctor():
    query_filter = Doctor.objects.filter(
        id__in=BDTransferSingleRecord.objects.
            exclude(Q(doctor__id__isnull=False) & Q(doctor__id='')).
            values_list('doctor__id', flat=True).distinct()).values('id', 'name')
    data = list(query_filter)
    return data


@bind(uri_pre + 'web_kefu/get')
def get_bdtransfer_web_kefu_info(kefu_id):
    kefu_info = BDTransferWebKefu.objects.filter(id=kefu_id).first()
    return to_dict(kefu_info)


@bind_context(uri_pre + 'web_kefu/edit')
def edit_bdtransfer_web_kefu_info(ctx, kefu_info, kefu_id):
    if kefu_id:
        kefu_instance = BDTransferWebKefu.objects.filter(id=kefu_id).first()
        if not kefu_instance:
            raise gen(CODES.UNIVERSAL)
        kefu_instance.nickname = kefu_info['nickname']
        kefu_instance.qr_code = kefu_info['qr_code']
        kefu_instance.is_online = kefu_info['is_online']
        kefu_instance.save()
    else:
        kefu_instance = BDTransferWebKefu.objects.create(nickname=kefu_info['nickname'],
                                                         qr_code=kefu_info['qr_code'],
                                                         is_online=kefu_info['is_online'])
    return to_dict(kefu_instance)


@bind(uri_pre + 'web_kefu_image/get')
def get_bdtransfer_web_kefu_image():
    c = Config.objects.filter(key='bdtransfer_web_kefu_image').first()
    return c.value if c else ""


@bind(uri_pre + 'web_kefu_image/update')
def update_bdtransfer_web_kefu_image(image_url):
    Config.objects.update_or_create(key='bdtransfer_web_kefu_image', defaults={"value": image_url})
    return


@bind(uri_pre + 'commission_edit')
def commission_edit(record_id=None, data=None):
    ret = {}
    budan_data = []
    if record_id is None:
        pass

    else:
        bd = BDTransferApplyRecord.objects.get(id=record_id)

        for _bdtransfermonth in bd.record_budans.all():
            budan_data.append({
                'budan_id': _bdtransfermonth.budan.id,
                'total_amount': _bdtransfermonth.budan.extra_consume,
                'should_pay': _bdtransfermonth.budan.payment
            })

        ret = {
            'record_id': bd.id,
            'date': datetime.strftime(bd.bdtransfermonth.month_at, '%Y-%m') if bd.bdtransfermonth.month_at else '',
            'merchant_name': bd.doctor.name,
            'related_budan': budan_data,
            'pay_money': bd.should_pay,
            'apply_time': datetime.strftime(bd.created_time, '%Y-%m-%d %H:%M:%S') if bd.created_time else '',
            'success_time': datetime.strftime(bd.pass_time, '%Y-%m-%d %H:%M:%S') if bd.pass_time else '',
            'status': bd.status,
            'status_desc': BDTRANSFER_APPLY_STATUS.getDesc(bd.status),
            'pay_images': bd.get_pics(BDTRANSFER_PIC_TYPE.PROOF_OF_PAYMENT),
            'gathering_images': bd.get_pics(BDTRANSFER_PIC_TYPE.COLLECTION_OF_PAYMENTS),
            'authorization_images': bd.get_pics(BDTRANSFER_PIC_TYPE.AUTHORIZATION_VOUCHER),
            'reason': bd.reason,
        }
    return ret


@bind(uri_pre + 'commission_confirm')
def bdtransfer_commission_confirm(record_id, is_pass, reason=None, images=[]):
    if not record_id:
        return False

    bd_apply_imgs = []
    bd = BDTransferApplyRecord.objects.get(id=record_id)

    with transaction.atomic():
        if is_pass:  # 审核通过
            bd.status = BDTRANSFER_APPLY_STATUS.SUCCESS
            bd.bdtransfermonth.already_pay += bd.should_pay
            bd.pass_time = datetime.now()
            bd.bdtransfermonth.save()
            bd.save()

            if bd.bdtransfermonth.already_pay == bd.bdtransfermonth.should_pay:
                bd.bdtransfermonth.is_finished = True
                bd.bdtransfermonth.save()

            for img in images:
                bd_apply_imgs.append(BDTransferApplyPic(
                    bdtransferapplyrecord=bd,
                    content=img,
                    image_type=BDTRANSFER_PIC_TYPE.COLLECTION_OF_PAYMENTS
                ))
            BDTransferApplyPic.objects.bulk_create(bd_apply_imgs)

            BDTransferMonthToBudan.objects.filter(
                budan_id__in=list(bd.record_budans.values_list('budan_id', flat=True)),
                bdtransfermonth=bd.bdtransfermonth
            ).update(has_paid=True)
        else:
            # 审核失败
            bd.status = BDTRANSFER_APPLY_STATUS.REJECT
            bd.reason = reason
            bd.save()

    return True


@bind(uri_pre + 'analyze')
def bdtransfer_data_analyze(source, single_start_time=None, single_end_time=None, single_creator_id=None,
                            single_doctor_id=None, budan_start_time=None, budan_end_time=None,
                            bdtransfer_start_time=None, bdtransfer_end_time=None, confirm_single_user_id=None):
    query_q = ~Q(status=SINGLE_TYPE.HAS_CANCEL)
    if source is not None:
        query_q &= Q(dbtransfer__source=source)
    if single_start_time:
        format_single_start_time = datetime.strptime('{} {}'.format(single_start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(single_time__gte=format_single_start_time)
    if single_end_time:
        format_single_end_time = datetime.strptime('{} {}'.format(single_end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(single_time__lte=format_single_end_time)
    if single_creator_id:
        query_q &= Q(user_id=single_creator_id)
    if single_doctor_id:
        query_q &= Q(doctor_id=single_doctor_id)
    if budan_start_time:
        format_budan_start_time = datetime.strptime('{} {}'.format(budan_start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(budan__happen_time__gte=format_budan_start_time)
    if budan_end_time:
        format_budan_end_time = datetime.strptime('{} {}'.format(budan_end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(budan__happen_time__lte=format_budan_end_time)
    if bdtransfer_start_time:
        format_bdtransfer_start_time = datetime.strptime('{} {}'.format(bdtransfer_start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(dbtransfer__create_time__gte=format_bdtransfer_start_time)
    if bdtransfer_end_time:
        format_bdtransfer_end_time = datetime.strptime('{} {}'.format(bdtransfer_end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(dbtransfer__create_time__lte=format_bdtransfer_end_time)
    if confirm_single_user_id:
        query_q &= Q(confirm_user_id=confirm_single_user_id)
    res = BDTransferSingleRecord.objects.using(settings.SLAVE_DB_NAME).filter(query_q).prefetch_related(
        'dbtransfer', 'budan', 'user', 'doctor', 'budan__doctor', 'confirm_user'
    )
    return [format_bdtransfer_analyze(_) for _ in res]


def format_bdtransfer_analyze(bdtransfer_singlerecord):
    return {
        "single_id": bdtransfer_singlerecord.id,
        "single_time": get_timestamp_epoch(bdtransfer_singlerecord.single_time),
        "single_creator_id": bdtransfer_singlerecord.user_id,
        "single_creator_name": bdtransfer_singlerecord.user.username,
        "single_doctor_id": bdtransfer_singlerecord.doctor_id,
        "single_doctor_name": bdtransfer_singlerecord.doctor.name,
        "status": bdtransfer_singlerecord.status,  # 派单状态
        "status_desc": SINGLE_TYPE.getDesc(bdtransfer_singlerecord.status),
        "budan_id": bdtransfer_singlerecord.budan_id,
        "bdtransfer_id": bdtransfer_singlerecord.dbtransfer_id,
        "appointment_time":
            get_timestamp_epoch(bdtransfer_singlerecord.appointment_time) if bdtransfer_singlerecord.appointment_time else '',
        "consultation_time":
            get_timestamp_epoch(bdtransfer_singlerecord.consultation_time) if bdtransfer_singlerecord.consultation_time else '',
        "single_confirm_user_id": bdtransfer_singlerecord.confirm_user_id,
        "single_confirm_user_name": bdtransfer_singlerecord.confirm_user.username if bdtransfer_singlerecord.confirm_user else '',
        "budan_payment": bdtransfer_singlerecord.budan.payment if bdtransfer_singlerecord.budan else 0,
        "budan_projects_payment": bdtransfer_singlerecord.budan.total_project_amount() if bdtransfer_singlerecord.budan else 0,
        "bdtransfer_user": bdtransfer_singlerecord.dbtransfer.user,
        "bdtransfer_userphone": bdtransfer_singlerecord.dbtransfer.user_phone,
        "bdtransfer_wechat": bdtransfer_singlerecord.dbtransfer.wechat,  # 微信
        "bdtransfer_source": bdtransfer_singlerecord.dbtransfer.source,
        "bdtransfer_source_desc": TRANSFER_SOURCE.getDesc(bdtransfer_singlerecord.dbtransfer.source),
        "budan_happen_time": get_timestamp_epoch(bdtransfer_singlerecord.budan.happen_time) if bdtransfer_singlerecord.budan else '' ,
        "budan_doctor_id": bdtransfer_singlerecord.budan.doctor_id if bdtransfer_singlerecord.budan else '',
        "budan_doctor_name": bdtransfer_singlerecord.budan.doctor.name if bdtransfer_singlerecord.budan else '',
    }


@bind_context(uri_pre + 'bdtransfer_excel_export')
def bdtransfer_excel_export(ctx, single_and_hostipal_data=None, budan_data=None, source_data=None):
    data1=bdtransfer_data_analyze.func(**single_and_hostipal_data)
    data2=bdtransfer_data_analyze.func(**budan_data)
    data3=bdtransfer_data_analyze.func(**source_data)
    send_list, order_list, hospital_list, channel_list = [], [], [], []

    single_creator_name_list, single_hostipal_list, single_order_list, single_channel_list = [], [], [], []
    for s in data1:
        if s['single_creator_name'] not in single_creator_name_list:
            single_creator_name_list.append(s['single_creator_name'])

        if s['single_doctor_name'] not in single_hostipal_list:
            single_hostipal_list.append(s['single_doctor_name'])
    for s in data2:
        if s['single_creator_name'] not in single_order_list:
            single_order_list.append(s['single_creator_name'])

    for s in data3:
        if s['bdtransfer_source'] not in single_channel_list:
            single_channel_list.append(s['bdtransfer_source'])

    for c in single_creator_name_list:
        send_data = filter(lambda x: x['single_creator_name']== c, data1)

        send_list.append({
            "single_creator_name": c,
            "send_num": len(send_data),
            "send_person": len(set(map(lambda x:x['bdtransfer_userphone'], send_data))),
            "send_hospital":len(set(map(lambda x:x['single_doctor_id'], send_data)))
        })

    for h in single_hostipal_list:
        hospital_data = filter(lambda x: x['single_doctor_name']== h, data1)
        order_num = len(filter(lambda x: x['status_desc']== u'已成单', hospital_data))
        budan_payment = sum(map(lambda x:x['budan_payment'], hospital_data))
        send_achievement = budan_payment / (len(hospital_data) - order_num) if len(hospital_data) - order_num else 0

        hospital_list.append({
            "single_doctor_name": h,
            "send_num": len(hospital_data),
            "order_num": order_num,
            "budan_projects_payment": round(sum(map(lambda x:x['budan_projects_payment'], hospital_data)),2),
            'budan_payment': round(budan_payment,2),
            'send_achievement': round(send_achievement,2),
            'order_achievement': round(budan_payment / order_num,2)
        })

    for c in single_order_list:
        order_data = filter(lambda x: x['single_creator_name']== c, data2)

        order_list.append({
            "single_creator_name": c,
            'budan_projects_payment': round(sum(map(lambda x:x['budan_projects_payment'], order_data)),2),
            'budan_payment': round(sum(map(lambda x:x['budan_payment'], order_data)),2),
            "send_num": len(order_data),
            "order_num": len(set(map(lambda x:x['bdtransfer_userphone'], order_data)))
        })

    for c in single_channel_list:
        channel_data = filter(lambda x: x['bdtransfer_source']== c, data3)

        channel_list.append({
            "channel": TRANSFER_SOURCE.getDesc(c),
            'clue_num': len(set(map(lambda x:x['bdtransfer_id'], channel_data))),
            "send_num": len(channel_data),
            "order_num": len(filter(lambda x: x['status_desc']== u'已成单', channel_data)),
            'budan_projects_payment': round(sum(map(lambda x:x['budan_projects_payment'], channel_data)),2),
            'budan_payment': round(sum(map(lambda x:x['budan_payment'], channel_data)),2),

        })

    user = ctx.session.user
    export_referral_data_excel_task.delay(user.email, send_list, order_list, hospital_list, channel_list)

@bind(uri_pre + 'analyze_clue')
def bdtransfer_data_analyze_clue(single_start_time=None, single_end_time=None, single_creator_id=None):
    query_q = Q()
    if single_start_time:
        format_single_start_time = datetime.strptime('{} {}'.format(single_start_time, '00:00:00'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(create_time__gte=format_single_start_time)
    if single_end_time:
        format_single_end_time = datetime.strptime('{} {}'.format(single_end_time, '23:59:59'), "%Y-%m-%d %H:%M:%S")
        query_q &= Q(create_time__lte=format_single_end_time)
    if single_creator_id:
        query_q &= Q(creator=single_creator_id)
    res = BDTransfer.objects.using(settings.SLAVE_DB_NAME).filter(query_q)
    return [format_bdtransfer_analyze_clue(_) for _ in res]

def format_bdtransfer_analyze_clue(bdtransfer):
    try:
        bdtransfersinglerecord=BDTransferSingleRecord.objects.get(dbtransfer_id=bdtransfer.id)
    except:
        bdtransfersinglerecord = ''
    return {
        "bdtransfer_id": bdtransfer.id,
        "bdtransfer_user": bdtransfer.user,
        "bdtransfer_userphone": bdtransfer.user_phone,
        "bdtransfer_wechat": bdtransfer.wechat,  # 微信
        "bdtransfer_creator_id": bdtransfer.creator,  # 创建人
        "bdtransfer_creator_name": User.objects.get(id=bdtransfer.creator).username,
        'bdtransfer_object_state': bdtransfer.object_state,
        "single_creator_name": bdtransfersinglerecord.user.username if bdtransfersinglerecord and bdtransfersinglerecord.user else '',
        "single_confirm_user_name": bdtransfersinglerecord.confirm_user.username if bdtransfersinglerecord and bdtransfersinglerecord.confirm_user else '',
        "single_doctor_name": bdtransfersinglerecord.doctor.name if bdtransfersinglerecord and bdtransfersinglerecord.doctor else '',
        "budan_doctor_name": bdtransfersinglerecord.budan.doctor.name if bdtransfersinglerecord and bdtransfersinglerecord.budan else '',
        "budan_projects_payment": bdtransfersinglerecord.budan.total_project_amount() if bdtransfersinglerecord and bdtransfersinglerecord.budan else 0,
        "budan_payment": bdtransfersinglerecord.budan.payment if bdtransfersinglerecord and bdtransfersinglerecord.budan else 0,
        "bdtransfer_source_desc": TRANSFER_SOURCE.getDesc(bdtransfersinglerecord.dbtransfer.source) if bdtransfersinglerecord and bdtransfersinglerecord.dbtransfer else '',
        "status_desc": SINGLE_TYPE.getDesc(bdtransfersinglerecord.status) if bdtransfersinglerecord and bdtransfersinglerecord.status else '',
        "appointment_time":
            get_timestamp_epoch(bdtransfersinglerecord.appointment_time) if bdtransfersinglerecord and bdtransfersinglerecord.appointment_time else '',
        "consultation_time":
            get_timestamp_epoch(bdtransfersinglerecord.consultation_time) if bdtransfersinglerecord and bdtransfersinglerecord.consultation_time else '',
        "budan_happen_time": get_timestamp_epoch(bdtransfersinglerecord.budan.happen_time) if bdtransfersinglerecord and bdtransfersinglerecord.budan else '',
        #个人线索新增字段
        "created_time": get_timestamp_epoch(bdtransfer.create_time),
        "current_follow_up_consultant": bdtransfer.current_follow_up_consultant.username if bdtransfer.current_follow_up_consultant else '',
        "status": BDTRANSFER_OBJECT_STATE.getDesc(bdtransfer.object_state),
        "source": TRANSFER_SOURCE.getDesc(bdtransfer.source)
    }

@bind_context(uri_pre + 'bdtransfer_clue_excel_export')
def bdtransfer_clue_excel_export(ctx, single_start_time=None, single_end_time=None, single_creator_id=None):
    data=bdtransfer_data_analyze_clue.func(single_start_time=single_start_time, single_end_time=single_end_time, single_creator_id=single_creator_id)
    send_list, single_creator_name_list = [], []
    for s in data:
        if s['bdtransfer_creator_name'] not in single_creator_name_list:
            single_creator_name_list.append(s['bdtransfer_creator_name'])

    for c in single_creator_name_list:
        send_data = filter(lambda x: x['bdtransfer_creator_name']== c, data)
        notadopted = len(filter(lambda x: x['bdtransfer_object_state']== 1, send_data))
        send_list.append({
            "bdtransfer_creator_name": c,
            "clue_num": len(send_data),
            "adopted": len(send_data)-notadopted,
            "notadopted": notadopted,
        })

    user = ctx.session.user
    export_clue_data_excel_task.delay(user.email, send_list)

@bind_context(uri_pre + 'redistribution')
def bdtransfer_redistribution(ctx, id=None, updates=None):
    opuser_id = updates['operate_user_id']
    operation_type = int(updates['type'])

    assigner_id = updates.get('assigner_id')
    assigner = get_user_by_id(assigner_id)
    opuser = get_user_by_id(opuser_id)
    if opuser is None:
        raise GaiaRPCFaultException(ERROR.USER_NOT_FOUND, u"对象商务人员不存在", data=None)

    bdtransfer = BDTransfer.objects.filter(id=id).first()
    if not bdtransfer:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, u"转诊对象未找到", data=None)
    if operation_type == OPERATION_ACTION.ASSIGN:
        content = u"分配给 {}".format(assigner.username)
    else:
        raise GaiaRPCFaultException(ERROR.UNIVERSAL, u"操作类型错误", data=None)
    bdtransfer.is_assign = True
    bdtransfer.assigner = assigner_id
    bdtransfer.assigned_time = datetime.now()
    bdtransfer.current_follow_up_consultant_id = assigner
    bdtransfer.save()
    bdtransfer_operation_record = BDTransferOperationRecord.objects.filter(bdtransfer_id = id).first()
    if bdtransfer_operation_record:
        bdtransfer_operation_record.action = operation_type
        bdtransfer_operation_record.content = content
        bdtransfer_operation_record.operate_user = opuser
        bdtransfer_operation_record.save()
    return id

@bind(uri_pre+'province_info')
def get_bdtransfer_record_province():
    query_filter = Province.objects.filter(
        id__in=BDTransferMonth.objects.
            exclude(Q(doctor__hospital__city__province__id__isnull=False) & Q(doctor__hospital__city__province__id='')).
            values_list('doctor__hospital__city__province__id', flat=True).distinct()).values('id', 'name')
    data = list(query_filter)
    return data

@bind(uri_pre+'city_info')
def get_bdtransfer_record_city():
    query_filter = City.objects.filter(
        id__in=BDTransferMonth.objects.
            exclude(Q(doctor__hospital__city__id__isnull=False) & Q(doctor__hospital__city__id='')).
            values_list('doctor__hospital__city__id', flat=True).distinct()).values('id', 'name')
    data = list(query_filter)
    return data

@bind(uri_pre+'business_partener_info')
def get_bdtransfer_record_business_partener():
    query_filter = User.objects \
        .annotate(name=F('username')) \
        .filter(id__in=BDTransferMonth.objects
                .filter(doctor__business_partener__id__isnull=False)
                .values_list('doctor__business_partener__id', flat=True).distinct()
                ).values('id', 'name')
    data = list(query_filter)
    return data

@bind(uri_pre + 'analyze_schedule')
def bdtransfer_data_analyze_schedule(search_data=None):
    province_id = search_data.get('province_id','')
    city_id = search_data.get('city_id','')
    business_partener_id = search_data.get('business_partener_id','')

    query_q = Q()
    if province_id:
        query_q &= Q(doctor__hospital__city__province__id=province_id)
    if city_id:
        query_q &= Q(doctor__hospital__city__id=city_id)
    if business_partener_id:
        query_q &= Q(doctor__business_partener__id=business_partener_id)

    res = BDTransferMonth.objects.using(settings.SLAVE_DB_NAME).filter(query_q).prefetch_related(
        'doctor', 'doctor__business_partener', 'doctor__hospital', 'doctor__hospital__city', 'doctor__hospital__city__province'
    )
    return [format_bdtransfer_analyze_schedule(_) for _ in res]

def format_bdtransfer_analyze_schedule(bdtransfermonth):

    return {
        "bdtransfermonth_id": bdtransfermonth.id,
        "doctor__d_merchant__id": bdtransfermonth.doctor.id,
        "doctor__name": bdtransfermonth.doctor.name,
        "business_partener_name": bdtransfermonth.doctor.business_partener.username if bdtransfermonth.doctor.business_partener else '' ,
        "doctor__hospital__city__province": bdtransfermonth.doctor.hospital.city.province.name if bdtransfermonth.doctor.hospital else '',
        "doctor__hospital__city": bdtransfermonth.doctor.hospital.city.name if bdtransfermonth.doctor.hospital else '',
        'month_at': '.'.join(str(bdtransfermonth.month_at).split('-')[:2]), #将日期从2019-09-01转化成2019.09
        "is_finished": u'是' if bdtransfermonth.is_finished else u'否',
        "budan_amount": bdtransfermonth.month_budans.count(),
        "total_amount": bdtransfermonth.total_amount,
        "should_pay": bdtransfermonth.should_pay,
        "already_pay": bdtransfermonth.already_pay,
    }


@bind(uri_pre + 'dispatch_query')
def dispatch_query(user_id, options):
    req_data_cache.set(str(user_id) + 'dispatch', json.dumps(options))
    dqobj = BDTransferSingleRecordDQ()
    return dqobj.process(**options)


@bind(uri_pre + 'dispatch_export_excel')
def dispatch_export_excel(user_id):
    """
    拍单记录导出
    :param user_id:
    :return:
    """
    dqobj = BDTransferSingleRecordDQ()
    options = json.loads(req_data_cache.get(str(user_id) + 'dispatch'))
    options.pop('paging')
    options.pop('columns')
    datas = dqobj.build_queryset(**options)
    user = User.objects.get(id=user_id)
    from api.tasks.export_excel_task import export_bdtransfer_dispatch_excel
    export_bdtransfer_dispatch_excel.delay(queryset_dec(datas, need_instant_data=True), user)


@bind(uri_pre + 'dispatch_detail')
def dispatch_detail(dispatch_id, doctor_id=None, refer='hera'):
    """
    :param dispatch_id:
    :param doctor_id:
    :param refer: hera:请求从hera来，ascle:请求从ascle来
    :return:
    """
    data = {}
    obj = BDTransferSingleRecord.objects.get(id=dispatch_id)
    if refer == 'ascle':
        obj = BDTransferSingleRecord.objects.get(id=dispatch_id, doctor_id=doctor_id)
    #基本信息构建
    user_name = obj.dbtransfer.user
    gender = USER_GENDER.getDesc(obj.dbtransfer.gender)
    gender = gender if gender else '未知'
    age = obj.dbtransfer.age
    if not isinstance(age, long):
        age = '年龄未知'
    #用户城市省份id与name转换
    user_province = Province.objects.get(id=obj.dbtransfer.user_province).name if obj.dbtransfer.user_province else ''
    user_city = City.objects.get(id=obj.dbtransfer.user_city).name if obj.dbtransfer.user_city else ''
    #基本信息
    base_info = {
        'dbtransfer_client_id': obj.dbtransfer.client_id,
        'dbtransfer_user_name': '{}({}/{})'.format(user_name, gender, age),
        'dbtransfer_address': '{} {}'.format(user_province, user_city),
        'dbtransfer_wechat': obj.dbtransfer.wechat,
        'dbtransfer_user_phone': obj.dbtransfer.user_phone,
        'single_time': obj.single_time.strftime('%Y-%m-%d %H:%M:%S') if obj.single_time else '',
        'project_name': '; '.join(obj.project.all().values_list('name', flat=True)),
        'dbtransfer_consume_potential': '{}-{}'.format(obj.dbtransfer.consume_potential_min, obj.dbtransfer.consume_potential_max),
        'operation_time': obj.operation_time.strftime('%Y-%m-%d %H:%M:%S') if obj.operation_time else '',
        'dbtransfer_comments': obj.dbtransfer.comments,
        'dbtransfer_current_follow_up_consultant': obj.dbtransfer.current_follow_up_consultant.id if obj.dbtransfer.current_follow_up_consultant else None,
        'dbtransfer_id': obj.dbtransfer.id
    }
    #消费信息
    consume_info = {
        'consume_image': obj.consume_image,
        'consume_projects': obj.consume_projects if obj.consume_projects else [],
        'appointment_time': obj.appointment_time.strftime('%Y-%m-%d %H:%M:%S') if obj.appointment_time else '',
        'consultation_time': obj.consultation_time.strftime('%Y-%m-%d %H:%M:%S') if obj.consultation_time else '',
        'comment': obj.comment
    }
    #状态信息
    budan_id = None
    confirm_dispatch = None
    #已预约，已接单，已面诊,已派单
    if obj.status in {SINGLE_TYPE.HAS_APPOINTMENT, SINGLE_TYPE.HAS_CONSULTATION, SINGLE_TYPE.HAS_ACCEPT, SINGLE_TYPE.NO_ORDER_FORM}:
        confirm_dispatch = '0'
    #已成单
    elif obj.status == SINGLE_TYPE.HAS_ORDER_FORM:
        confirm_dispatch = '1'
        budan_id = obj.budan.id
    #已重单
    elif obj.status == SINGLE_TYPE.DUPICATE_DISPATCH:
        confirm_dispatch = '2'
    #已撤销
    elif obj.status ==SINGLE_TYPE.HAS_CANCEL:
        confirm_dispatch = '3'
        budan_id = obj.budan.id
    status_info = {
        'confirm_dispatch': confirm_dispatch,
        'budan_id': budan_id,
    }
    #重单信息
    duplicate_info = {
        'duplicate_comment': obj.duplicate_comment,
        'duplicate_image': obj.duplicate_image
    }
    if refer == 'ascle':
        base_info.pop('dbtransfer_current_follow_up_consultant')
        base_info.pop('dbtransfer_id')
        data.update(base_info=base_info, consume_info=consume_info, status=obj.status, budan_id=obj.budan_id)
        return data
    data.update(base_info=base_info, consume_info=consume_info, status_info=status_info, duplicate_info=duplicate_info)
    return data


@bind(uri_pre + 'dispatch_edit')
def dispatch_edit(consume_data=None, duplicate_data=None, status=None, id=None):
    obj = BDTransferSingleRecord.objects.get(id=id)
    if duplicate_data:
        obj.duplicate_comment = duplicate_data.get('duplicate_comment')
        obj.duplicate_image = duplicate_data.get('duplicate_image')
        obj.status = SINGLE_TYPE.DUPICATE_DISPATCH
    #重单接单状态流转:接单、重单、终止派单
    elif status:
        if int(status) in {SINGLE_TYPE.DUPICATE_DISPATCH, SINGLE_TYPE.HAS_TERMINATE}:
            obj.status = int(status)
        elif int(status) == SINGLE_TYPE.HAS_ACCEPT:
            if obj.consultation_time:
                obj.status = SINGLE_TYPE.HAS_CONSULTATION
            elif obj.appointment_time:
                obj.status = SINGLE_TYPE.HAS_APPOINTMENT
            else:
                obj.status = SINGLE_TYPE.HAS_ACCEPT
    elif consume_data:
        obj.comment = consume_data.get('comment')
        obj.consume_projects = consume_data.get('consume_projects')
        obj.consume_image = consume_data.get('consume_image')
        if consume_data.get('appointment_time'):
            obj.appointment_time = consume_data.get('appointment_time')
            obj.status = SINGLE_TYPE.HAS_APPOINTMENT
        if consume_data.get('consultation_time'):
            obj.consultation_time = consume_data.get('consultation_time')
            obj.status = SINGLE_TYPE.HAS_CONSULTATION
        if obj.consume_projects:
            obj.is_consume = True
        else:
            obj.is_consume = False
    obj.save()
    return {'message': 'ok'}

@bind(uri_pre + 'dispatch_filter')
def dispatch_query(page, options, size=10):
    data = []
    if options.get('dbtransfer__user_name__contains'):
        user = options.pop('dbtransfer__user_name__contains')
        dbtransfer_ids = BDTransfer.objects.filter(user__contains=user).values_list('id', flat=True)
        options.update(dbtransfer_id__in=list(dbtransfer_ids))
    objs = BDTransferSingleRecord.objects.filter(**options).exclude(status=SINGLE_TYPE.HAS_TERMINATE).order_by('-single_time')
    for obj in objs[size*(page - 1): size*page]:
        projects_name = '; '.join(obj.project.all().values_list('name', flat=True))
        user_name = obj.dbtransfer.user
        gender = USER_GENDER.getDesc(obj.dbtransfer.gender)
        gender = gender if gender else '未知'
        age = obj.dbtransfer.age
        if not isinstance(age, long):
            age = '年龄未知'
        #用户城市省份id与name转换
        user_province = Province.objects.get(id=obj.dbtransfer.user_province).name if obj.dbtransfer.user_province else ''
        user_city = City.objects.get(id=obj.dbtransfer.user_city).name if obj.dbtransfer.user_city else ''
        result = {
            'id': obj.id,
            'dbtransfer_client_id': obj.dbtransfer.client_id,
            'dbtransfer_user_name': '{}({}/{})'.format(user_name, gender, age) if obj.status != SINGLE_TYPE.NO_ORDER_FORM and obj.status != SINGLE_TYPE.DUPICATE_DISPATCH else '***',
            'project_name': projects_name if all([projects_name, obj.status != SINGLE_TYPE.NO_ORDER_FORM, obj.status != SINGLE_TYPE.DUPICATE_DISPATCH]) else '***',
            'dbtransfer_address': '{} {}'.format(user_province, user_city) if obj.status != SINGLE_TYPE.NO_ORDER_FORM and obj.status != SINGLE_TYPE.DUPICATE_DISPATCH else '***',
            'single_time': obj.single_time.strftime('%Y-%m-%d %H:%M:%S') if obj.single_time else '',
            'status': obj.status,
            'is_consume': obj.is_consume,
            'dbtransfer_user_phone': obj.dbtransfer.user_phone
        }
        data.append(result)
    return {"dispatch_info": data, 'total': objs.count()}