tasks.py 7.86 KB
import json
import logging
import traceback
from collections import OrderedDict
from . import app
from apps.doc.models import AFCOCRResult, HILOCRResult, AFCComparisonInfo, HILComparisonInfo
from apps.doc import consts
from apps.doc.ocr.gcap import gcap
from apps.doc.exceptions import GCAPException
from common.tools.comparison import cp

compare_log = logging.getLogger('compare')
log_base = '[CA Compare]'


def get_order_dict(src_dict, order_tuple):
    order_dict = OrderedDict({})
    for field in order_tuple:
        value = src_dict.get(field)
        if value is not None:
            order_dict[field] = value
    return order_dict


def field_compare(info_dict, ocr_res_dict, ocr_field, compare_list, res_set):
    is_find = False
    ocr_res_str = ocr_res_dict.get(ocr_field)
    if ocr_res_str is not None:
        ocr_res_list = json.loads(ocr_res_str)
        res_len = len(ocr_res_list)
        for ocr_res in ocr_res_list:
            if is_find:
                break
            for idx, compare_tuple in enumerate(compare_list):
                compare_res = getattr(cp, compare_tuple[2])(
                    info_dict.get(compare_tuple[0]), ocr_res.get(compare_tuple[1]), **compare_tuple[3])
                if idx == 0 and compare_res == consts.RESULT_N and res_len != 1:
                    break
                is_find = True
                info_dict[compare_tuple[0] + 'Result'] = compare_res
                res_set.add(compare_res)
    if not is_find:
        res_set.add(consts.RESULT_N)
        for compare_tuple in compare_list:
            info_dict[compare_tuple[0] + 'Result'] = consts.RESULT_N


@app.task
def compare(application_id, application_entity, uniq_seq, ocr_res_id):
    # POS: application_id, application_entity, uniq_seq, None
    # OCR: application_id, business_type(application_entity), None, ocr_res_id

    compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
        log_base, application_entity, application_id, uniq_seq, ocr_res_id))

    # 根据application_id查找最新的比对信息,如果没有,结束
    comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo
    last_obj = comparison_class.objects.filter(application_id=application_id).last()
    if last_obj is None:
        compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
            log_base, application_entity, application_id, uniq_seq, ocr_res_id))
        return

    # 根据application_id查找OCR累计结果指定license字段,如果没有,结束
    result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult
    if ocr_res_id is None:
        ocr_res_dict = result_class.objects.filter(application_id=application_id).values(*consts.COMPARE_FIELDS).first()
    else:
        ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first()
    if ocr_res_dict is None:
        compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
            log_base, application_entity, application_id, uniq_seq, ocr_res_id
        ))
        return

    # 比对信息
    try:
        comparison_res = OrderedDict({
            'OCR_Input': {
                'uniqSeq': last_obj.uniq_seq,
                'applicationId': application_id,
                'applicationEntity': application_entity,
                'applicationVersion': last_obj.application_version,
                'vehicleStatus': last_obj.vehicle_status,
                'wholeResult': 'Y',
                'wholeResultMessage': '',
                'applicationLink': '',
            }
        })

        res_set = set()

        is_sep = True if last_obj.customer_type == consts.CUSTOMER_TYPE[5] else False

        individual_cus_info_list = json.loads(last_obj.individual_cus_info)
        order_individual_cus_info_list = []
        for individual_cus_info in individual_cus_info_list:
            order_individual_cus_info = get_order_dict(individual_cus_info, consts.IN_ORDER)
            # sep营业执照
            if is_sep and order_individual_cus_info.get('companyName') is not None:
                field_compare(order_individual_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCSEP, res_set)

            # 个人信息证件
            id_type = order_individual_cus_info.get('idType')
            compare_info_list = consts.ID_TYPE_COMPARE.get(id_type)
            if compare_info_list is None:
                continue
            field_compare(order_individual_cus_info, ocr_res_dict, compare_info_list[0], compare_info_list[1], res_set)

            order_individual_cus_info_list.append(order_individual_cus_info)

        comparison_res['OCR_Input']['individualCusInfo'] = order_individual_cus_info_list

        if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and last_obj.usedcar_info is not None:
            usedcar_info = json.loads(last_obj.usedcar_info)
            order_usedcar_info = get_order_dict(usedcar_info, consts.UC_ORDER)

            field_compare(order_usedcar_info, ocr_res_dict, consts.MVC_OCR_FIELD, consts.PCUSD_MVC, res_set)

            if order_usedcar_info[consts.PCUSD_MVC[0][0] + 'Result'] == consts.RESULT_Y:
                field_compare(order_usedcar_info, ocr_res_dict, consts.DL_OCR_FIELD, consts.PCUSD_DL, res_set)

            comparison_res['OCR_Input']['usedCarInfo'] = order_usedcar_info

        if last_obj.corporate_cus_info is not None:
            corporate_cus_info = json.loads(last_obj.corporate_cus_info)
            order_corporate_cus_info = get_order_dict(corporate_cus_info, consts.CO_ORDER)
            field_compare(order_corporate_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCCOR, res_set)

            comparison_res['OCR_Input']['corporateCusInfo'] = order_corporate_cus_info

        comparison_res['OCR_Input']['wholeResult'] = consts.RESULT_N if consts.RESULT_N in res_set else consts.RESULT_Y

    except Exception as e:
        compare_log.error('{0} [compare error] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                          '[error={5}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id,
                                               traceback.format_exc()))
    else:
        compare_log.info('{0} [compare success] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                         '[compare_res={5}]'.format(log_base, application_entity, application_id, uniq_seq,
                                                    ocr_res_id, comparison_res))

        # 将比对结果发送GCAP
        try:
            data = gcap.dict_to_xml(comparison_res)
        except Exception as e:
            compare_log.error('{0} [dict to xml failed] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                              '[error={5}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id,
                                                   traceback.format_exc()))
        else:
            try:
                for times in range(consts.RETRY_TIMES):
                    try:
                        gcap.send(data)
                    except Exception as e:
                        gcap_exc = str(e)
                    else:
                        break
                else:
                    raise GCAPException(gcap_exc)
            except Exception as e:
                compare_log.error('{0} [gcap failed] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
                                  '[error={5}]'.format(log_base, application_entity, application_id, uniq_seq,
                                                       ocr_res_id, traceback.format_exc()))
            else:
                compare_log.info('{0} [task success] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
                    log_base, application_entity, application_id, uniq_seq, ocr_res_id))