def add_case_suite(project_id):
    request_data = request.get_json()
    request_data["status"] = True
    request_data["projectId"] = ObjectId(project_id)
    request_data["lastUpdateTime"] = datetime.datetime.utcnow()
    request_data["createAt"] = datetime.datetime.utcnow()

    try:
        filtered_data = CaseSuite.filter_field(request.get_json(),
                                               use_set_default=True)
        CaseSuite.insert(filtered_data)
        return jsonify({'status': 'ok', 'data': '添加成功'})
    except BaseException as e:
        return jsonify({'status': 'failed', 'data': '添加失败 %s' % e})
def import_test_cases():
    file = request.files.get('file')
    request_data = request.form
    case_suite_id = request_data.get('caseSuiteId') if request_data else None
    project_id = request_data.get('projectId') if request_data else None
    current_user_name = request_data.get('userName') if request_data else None

    if file is None or project_id is None or current_user_name is None:
        return jsonify({'status': 'failed', 'data': '参数不合法!值为: None'})

    if case_suite_id == 'undefined' or project_id == 'undefined' or current_user_name == 'undefined':
        return jsonify({'status': 'failed', 'data': '参数不合法!值为: undefined'})

    try:
        file_content = file.read()
        workbook = xlrd.open_workbook(file_contents=file_content)
    except BaseException as e:
        return jsonify({'status': 'failed', 'data': '「Excel」读取失败! %s' % e})

    if '测试用例' not in workbook.sheet_names():
        return jsonify({'status': 'failed', 'data': '「Excel」缺失「测试用例」Sheet'})

    test_case_table = workbook.sheet_by_name('测试用例')
    rows_num = test_case_table.nrows  # 获取该sheet中的有效行数

    if rows_num < 2:
        return jsonify({
            'status': 'failed',
            'data': '「测试用例」Sheet 有效行数小于两行: %s 行' % rows_num
        })

    test_case_attributes = test_case_table.row_values(0)

    non_intersection = list(
        set(test_case_map.values()) ^ set(test_case_attributes))
    if non_intersection:
        missing_attributes = [
            nip for nip in non_intersection if nip in test_case_map.values()
        ]
        return jsonify({'status': 'failed', 'data': '「测试用例」Sheet 表头缺失字段: %s' % missing_attributes}) \
            if missing_attributes else jsonify({'status': 'failed', 'data': '「测试用例」Sheet 表头存在多余字段: %s' %
                                               [nip for nip in non_intersection if nip not in test_case_map.values()]})

    attributes_indexes = [
        test_case_attributes.index(v) for v in test_case_map.values()
    ]

    def get_pre_import_case_info(case_info, test_case_mapping,
                                 table_row_index):
        _is_case_exist, _case_info, _is_case_suite_exist = \
            common.validate_and_pre_process_import_test_case(CaseSuite, TestingCase, case_info,
                                                             test_case_mapping, table_row_index)
        return _is_case_exist, _case_info, _is_case_suite_exist

    results = []
    import_count = 0
    update_count = 0
    test_case_info = copy.deepcopy(test_case_map)
    for i in range(rows_num - 1):
        for j, v in enumerate(test_case_info.keys()):
            test_case_info[v] = test_case_table.row_values(i + 1)[
                attributes_indexes[j]]
        try:
            is_case_exist, pre_import_case_info, is_case_suite_exist\
                = get_pre_import_case_info(test_case_info, test_case_mapping=test_case_map, table_row_index=(i+2))
        except BaseException as b_e:
            return jsonify({'status': 'failed', 'data': '导入数据异常: %s' % b_e})

        try:
            # 在接口用例列表中导入
            if case_suite_id:
                if is_case_exist and str(
                        pre_import_case_info.get('caseSuiteId')) == str(
                            case_suite_id):
                    pre_import_case_info = TestingCase.filter_field(
                        pre_import_case_info, use_set_default=False)
                    result = str(TestingCase.update({"_id": ObjectId(pre_import_case_info.get('_id'))},
                                                    {'$set': pre_import_case_info})) + \
                                                     ' _id: {}'.format(pre_import_case_info.get('_id'))
                    update_count += 1
                else:
                    try:
                        pre_import_case_info.pop('_id')
                    except BaseException:
                        pass
                    pre_import_case_info['status'] = True
                    pre_import_case_info['caseSuiteId'] = ObjectId(
                        case_suite_id)
                    pre_import_case_info['projectId'] = ObjectId(project_id)
                    pre_import_case_info['creatorNickName'] = current_user_name
                    pre_import_case_info[
                        'lastUpdatorNickName'] = current_user_name
                    pre_import_case_info = TestingCase.filter_field(
                        pre_import_case_info, use_set_default=True)
                    result = TestingCase.insert(pre_import_case_info)
                    import_count += 1
            # 在用例列表内导入
            else:
                inserted_case_suite_id = None
                case_suite_name = pre_import_case_info.get('caseSuiteName')\
                    if pre_import_case_info.get('caseSuiteName') else ''
                if is_case_suite_exist:
                    if not case_suite_name == CaseSuite.find_one({
                            "_id":
                            ObjectId(pre_import_case_info.get('caseSuiteId'))
                    })['name']:
                        CaseSuite.update(
                            {
                                "_id":
                                ObjectId(
                                    pre_import_case_info.get('caseSuiteId'))
                            }, {'$set': {
                                'name': case_suite_name
                            }})
                    else:
                        pass
                else:
                    insert_data = dict()
                    insert_data["name"] = case_suite_name
                    insert_data["status"] = True
                    insert_data["projectId"] = ObjectId(project_id)
                    insert_data["lastUpdateTime"] = datetime.datetime.utcnow()
                    insert_data["createAt"] = datetime.datetime.utcnow()
                    insert_data["creatorNickName"] = current_user_name
                    insert_data["lastUpdatorNickName"] = current_user_name
                    inserted_case_suite_id = CaseSuite.insert(insert_data)

                if inserted_case_suite_id:
                    pre_import_case_info.pop('_id') if is_case_exist else None
                    pre_import_case_info["projectId"] = ObjectId(project_id)
                    pre_import_case_info['caseSuiteId'] = ObjectId(
                        inserted_case_suite_id)
                    pre_import_case_info = TestingCase.filter_field(
                        pre_import_case_info, use_set_default=True)
                    result = TestingCase.insert(pre_import_case_info)
                    import_count += 1

                else:
                    if is_case_exist:
                        pre_import_case_info = TestingCase.filter_field(
                            pre_import_case_info, use_set_default=False)
                        result = str(TestingCase.update({"_id": ObjectId(pre_import_case_info.get('_id'))},
                                                        {'$set': pre_import_case_info})) + ' _id: {}'\
                            .format(pre_import_case_info.get('_id'))

                        update_count += 1
                    else:
                        pre_import_case_info["projectId"] = ObjectId(
                            project_id)
                        pre_import_case_info['caseSuiteId'] = ObjectId(
                            pre_import_case_info.get('caseSuiteId'))
                        pre_import_case_info = TestingCase.filter_field(
                            pre_import_case_info, use_set_default=True)
                        result = TestingCase.insert(pre_import_case_info)
                        import_count += 1

            results.append(result)
        except BaseException as e:
            return jsonify({'status': 'failed', 'data': '数据导入异常: %s' % e})

    def get_returned_data(_results, _import_count, _update_count):
        _returned_data = dict()
        _returned_data['status'] = 'ok'
        if import_count > 0 and update_count == 0:
            _returned_data['data'] = '操作成功, 共成功导入 %s 条用例' % _import_count
            # _returned_data['log'] = '导入数据_id: %s' % _results
        elif update_count > 0 and import_count == 0:
            _returned_data['data'] = '操作成功, 共成功覆盖 %s 条用例' % _update_count
            # _returned_data['log'] = '导入数据_id: %s' % _results
        elif import_count > 0 and update_count > 0:
            _returned_data['data'] = '操作成功, 共成功导入 %s 条用例、覆盖 %s 条用例' % (
                import_count, update_count)
            # _returned_data['log'] = '导入数据_id: %s' % _results
        else:
            _returned_data['data'] = '操作成功,但啥都没导入 / 覆盖'
            # _returned_data['log'] = None
        return jsonify(_returned_data)

    returned_data = get_returned_data(results, import_count, update_count)
    return returned_data
def copy_case_suite(project_id, case_suite_id):
    try:
        test_case_suite = list(CaseSuite.find({'_id':
                                               ObjectId(case_suite_id)}))[0]
        test_case_suite['originCaseSuiteIds'] = [] if 'originCaseSuiteIds' not in test_case_suite \
            else test_case_suite['originCaseSuiteIds']
        origin_case_suite_id_info = dict()
        origin_case_suite_id_info['_id'] = test_case_suite.pop(
            '_id') if test_case_suite.get('_id') else None
        origin_case_suite_id_info['copiedAt'] = datetime.datetime.utcnow()
        test_case_suite['originCaseSuiteIds'].append(origin_case_suite_id_info)

        def get_new_create_at(create_at):
            time_quantity = 1
            while True:
                new_create_at = create_at - datetime.timedelta(
                    milliseconds=time_quantity)
                find_result = list(CaseSuite.find({'createAt': new_create_at}))
                has_identical_create_at_case_suite = True if len(
                    find_result) > 0 else False
                if not has_identical_create_at_case_suite:
                    return new_create_at
                else:
                    time_quantity += 1

        case_suite_create_at = test_case_suite.get('createAt')
        new_case_suite_create_at = get_new_create_at(
            case_suite_create_at)  # 超前插入,精髓
        new_case_suite_suffix = '(复制版)'
        case_suite_name = test_case_suite.pop('name') + new_case_suite_suffix \
            if 'name' in test_case_suite else '未知用例组' + new_case_suite_suffix
        test_case_suite['createAt'] = new_case_suite_create_at
        test_case_suite['name'] = case_suite_name
        new_case_suite_id = CaseSuite.insert(test_case_suite)

        query = {
            'caseSuiteId': ObjectId(case_suite_id),
            'isDeleted': {
                '$ne': True
            }
        }
        test_cases = list(TestingCase.find(query))

        def substitute_info(testing_case):
            testing_case['originTestingCaseIds'] = [] if 'originTestingCaseIds' not in testing_case \
                else testing_case['originTestingCaseIds']
            origin_testing_case_id_info = dict()
            origin_testing_case_id_info['_id'] = testing_case.pop(
                '_id') if testing_case.get('_id') else None
            origin_testing_case_id_info['copiedAt'] = datetime.datetime.utcnow(
            )
            testing_case['originTestingCaseIds'].append(
                origin_testing_case_id_info)
            testing_case['caseSuiteId'] = new_case_suite_id
            return testing_case

        substituted_test_cases = list(map(substitute_info, test_cases))
        for substituted_test_case in substituted_test_cases:
            TestingCase.insert(substituted_test_case)
        return jsonify({'status': 'ok', 'data': '复制成功'})
    except BaseException as e:
        return jsonify({'status': 'failed', 'data': '复制失败 %s' % e})