Example #1
0
class Notification:
    def __init__(self):
        self.public_trpc = Trpc('public')
        self.message_trpc = Trpc('message')

    def send_notification(self, user_ids, text, creator=None, send_type=None):
        if not isinstance(user_ids, list):
            current_app.logger.warn(f'[接收者格式错误] {text}:{user_ids}')
            return
        user_ids = list(set(user_ids))
        if None in user_ids:
            current_app.logger.warn(f'[没有处理人,不发送通知] {text}:{user_ids}')
            return
        is_wx = 1
        is_message = 1
        if creator is None:
            creator = g.userid
        # 此时发送微信,不发送站内信
        if send_type == 1:
            is_wx = 1
            is_message = 0
        # 此时发送站内信,不发送微信
        elif send_type == 2:
            is_wx = 0
            is_message = 1

        if is_wx:
            result = self.public_trpc.requests('post', '/public/wxmessage', body={'user_ids': user_ids, 'text': text})
            if result == 'success':
                current_app.logger.info('发送企业微信通知成功')
            else:
                current_app.logger.warn('发送企业微信通知失败')
        if is_message:
            if self.message_trpc.requests('post', '/message',
                                          body={'send_id': creator, 'rec_id': user_ids, 'content': text}) is not None:
                current_app.logger.info('发送站内信成功')
            else:
                current_app.logger.warn('发送站内信失败')
Example #2
0
class DashboardBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def team_work_dashboard(cls, begin_date, end_date):
        testers = cls.user_trpc.requests('get', '/user/role/3')
        exc_case_info_list = TaskDashBoardBusiness.task_case_all_tester_dashboard(
            begin_date, end_date, testers=testers)
        create_issue_info_list = IssueDashBoardBusiness.issue_all_tester_dashboard(
            begin_date, end_date, testers=testers)
        create_case_info_list = CaseBusiness.case_all_tester_dashboard(
            begin_date, end_date, testers=testers)
        exc_case_info_list.sort(key=lambda z: z['userid'])
        create_issue_info_list.sort(key=lambda x: x['userid'])
        create_case_info_list.sort(key=lambda y: y['userid'])
        results = []
        for index in range(len(exc_case_info_list)):
            result = dict(
                userid=exc_case_info_list[index].get('userid'),
                nickname=exc_case_info_list[index].get('nickname'),
                picture=exc_case_info_list[index].get('picture'),
                exc_cases=exc_case_info_list[index].get('info'),
                submit_issues=create_issue_info_list[index].get('info'),
                create_cases=create_case_info_list[index].get('info'))
            results.append(result)
        return results

    @classmethod
    def team_case_issue_dashboard(cls, project_id, begin_date, end_date):
        testers = cls.user_trpc.requests('get',
                                         '/user/projectandrole',
                                         query={
                                             'project_id': project_id,
                                             'role_id': 3
                                         })
        data_temp = {}
        for tester in testers:
            userid = int(tester.get('userid'))
            nickname = tester.get('nickname')
            data_temp[userid] = dict(userid=userid,
                                     nickname=nickname,
                                     issue_count=0,
                                     case_count=0)
        data_temp = IssueDashBoardBusiness.issue_all_tester_dashboard_for_project(
            data_temp, project_id, begin_date, end_date)
        data_temp = CaseBusiness.case_all_tester_dashboard_for_project(
            data_temp, project_id, begin_date, end_date)
        return list(data_temp.values())
Example #3
0
from datetime import timedelta

from flask import request, g, current_app
from sqlalchemy import desc, func

from apps.auth.models.users import User
from apps.project.business.credit import CreditBusiness
from apps.project.models.assets import Phone, PhoneRecord, VirtualAsset, PhoneBorrow
from apps.project.models.credit import Credit
from apps.public.models.public import Config
from library.api.db import db
from library.api.transfer import transfer2json
from library.notification import notification
from library.trpc import Trpc

user_trpc = Trpc('auth')


class PhoneBusiness(object):
    public_trpc = Trpc('public')
    user_trpc = Trpc('auth')
    message_trpc = Trpc('message')

    @classmethod
    def _query(cls):
        return Phone.query.add_columns(
            Phone.id.label('id'),
            Phone.name.label('name'),
            Phone.asset_id.label('asset_id'),
            Phone.vendor.label('vendor'),
            Phone.device_number.label('device_number'),
Example #4
0
class ModuleBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def project_permission(cls, pid=None, id=None):
        project_id = cls.user_trpc.requests('get', '/user/userbindproject',
                                            {'userid': g.userid})
        if g.is_admin:
            return 0
        if pid:
            return 0 if pid in project_id else 1
        else:
            ret = Module.query.add_columns(
                Module.project_id.label('projectid')).filter(
                    Module.id == id).first()
            return 0 if ret.projectid in project_id else 1

    @classmethod
    def _query(cls):
        return Module.query.add_columns(
            Module.id.label('id'), Module.name.label('name'),
            Module.project_id.label('projectid'),
            Module.description.label('description'),
            Module.weight.label('weight'), Module.status.label('status'),
            Module.parent_id.label('parentid'))

    @classmethod
    @transfer2json('?id|!name|!projectid|!description|!weight|!status')
    def query_all_json(cls, limit, offset):
        ret = cls._query().filter(Module.status == Module.ACTIVE) \
            .order_by(desc(Module.id)) \
            .limit(limit).offset(offset).all()
        return ret

    @classmethod
    def module_create(cls, name, project_id, description, parent_id=None):
        try:
            ret = Module.query.filter(Module.name == name,
                                      Module.status != Module.DISABLE,
                                      Module.project_id == project_id).first()
            if ret:
                return 103, None
            m = Module(
                name=name,
                project_id=project_id,
                description=description,
                parent_id=parent_id,
            )
            db.session.add(m)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def module_delete(cls, id):
        try:
            m = Module.query.get(id)
            m.status = Module.DISABLE
            db.session.add(m)
            for case in Case.query.filter_by(module_id=id):
                case.status = Case.DISABLE
                db.session.add(case)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            return 105, str(e)
Example #5
0
class DeployBusiness(object):
    public_trpc = Trpc('public')
    extention_trpc = Trpc('extention')

    @classmethod
    def _query(cls):
        return Deploy.query.add_columns(
            Deploy.id.label('id'),
            Deploy.project_id.label('project_id'),
            Deploy.server_list.label('server_list'),
            Deploy.node_list.label('node_list'),
            Deploy.status.label('status'),
            Deploy.branch.label('branch'),
            Deploy.flow_id.label('flow_id'),
            Deploy.user_id.label('user_id'),
        )

    # 获取url
    @classmethod
    def get_url(cls):
        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'deploy', 'module_type': 2})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_url = run_dict['URL']

        return track_url

    # 获取url
    @classmethod
    def get_token(cls):
        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'deploy', 'module_type': 3})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_url = run_dict['api']

        return track_url

    # 获取项目id
    @classmethod
    def get_project_id(cls, project_id):

        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'deploy', 'module_type': 1})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_project_id = None
        operation_dict = run_dict['operation_dict']
        for i in range(0, len(operation_dict)):
            track_dict = operation_dict[i]
            for k, v in track_dict.items():
                if int(k) == int(project_id):
                    track_project_id = int(v)

        return track_project_id

    @classmethod
    def get_server(cls):
        project_id = request.args.get('project_id')

        deploy_project_id = DeployBusiness.get_project_id(project_id)

        if deploy_project_id:
            url = str(DeployBusiness.get_url()) + '/api/v1/service/tcloud/list'
            params = {"project_id": deploy_project_id, "page_size": 100, "page": 1}
            header = {"api": DeployBusiness.get_token()}
            ret = requests.get(url=url, params=params, headers=header)
            ret = json.loads(ret.content)
            if ret and 'result' in ret and 'data' in ret['result']:
                return ret['code'], ret['result']['data'], ret['message']

        return 101, [], 'can not find object'

    @classmethod
    def get_node(cls):
        project_id = request.args.get('project_id')
        if project_id:
            url = str(DeployBusiness.get_url()) + '/api/v1/node/tcloud/list'
            params = {"project_id": project_id, "page_size": 100, "page": 1}
            ret = requests.get(url=url, params=params)
            ret = json.loads(ret.content)
            if ret and 'result' in ret:
                return ret['code'], ret['result'], ret['message']

        return 101, [], 'can not find object'

    @classmethod
    def get_branch(cls):
        service_id = request.args.get('server_id')
        if service_id:
            url = str(DeployBusiness.get_url()) + '/api/v1/service/branches'
            params = {"service_id": service_id}
            header = {"api": DeployBusiness.get_token()}
            ret = requests.get(url=url, params=params, headers=header)
            ret = json.loads(ret.content)
            if ret and 'data' in ret:
                data_list = ret['data']
                branch_list = []
                for i in range(0, len(data_list)):
                    if 'displayId' in data_list[i]:
                        branch_list.append(data_list[i]['displayId'])

                return ret['code'], branch_list, ret['message']

        return 101, [], 'can not find object'

    @classmethod
    def deploy(cls, node_list, service_list, deploy_id, branch, project_id):

        deploy_project_id = DeployBusiness.get_project_id(project_id)

        if deploy_project_id is None:
            return {'code': 101}

        # 一键部署
        service_list_all = []
        for i in range(0, len(service_list)):
            service_dict = {'service_id': service_list[i], 'branch': branch, 'commit': 'tcloud'}
            service_list_all.append(service_dict)

        url = str(DeployBusiness.get_url()) + '/api/v1/deploy/tcloud/one-key'
        data = {
            "node_id_list": node_list, "service_list": service_list_all, "deploy_id": deploy_id,
            "project_id": deploy_project_id
        }
        data = json.dumps(data)
        header = {"Content-Type": "application/json", "api": DeployBusiness.get_token()}
        ret = requests.post(url=url, data=data, headers=header)
        ret = json.loads(ret.content)

        return ret

    @classmethod
    def create(cls, project_id, server_list_all, node_list_all, branch, flow_id):
        try:

            server_name = []
            server_list = []
            node_list = []
            node_name = []

            for i in range(0, len(server_list_all)):
                server_name.append(server_list_all[i]['server_name'])
                server_list.append(server_list_all[i]['server_id'])

            for i in range(0, len(node_list_all)):
                node_name.append(node_list_all[i]['node_name'])
                node_list.append(node_list_all[i]['node_id'])

            if len(server_list) == 0 or len(node_list) == 0:
                return 101, None

            server_list_string = ','.join(str(i) for i in server_list)
            node_list_string = ','.join(str(i) for i in node_list)

            c = Deploy(
                project_id=project_id,
                server_list=server_list_string,
                node_list=node_list_string,
                branch=branch,
                flow_id=flow_id,
                user_id=g.userid,
            )
            db.session.add(c)
            db.session.flush()

            ret = DeployBusiness.deploy(node_list, server_list, c.id, branch, project_id)

            # 判断是否正在执行

            if ret['code'] != 0 and 'result' in ret and 'code' in ret:
                return 101, None

            for i in range(0, len(server_list)):
                for j in range(0, len(node_list)):
                    DeployRecordBusiness.create(c.id, c.project_id, server_list[i], node_list[j], branch, flow_id,
                                                server_name[i], node_name[j], ret['result'])

            db.session.commit()
            return 0, c.id
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)
Example #6
0
class JiraBusiness(object):
    user_trpc = Trpc('auth')
    flow_trpc = Trpc('flow')

    @classmethod
    def _query(cls):
        return Jira.query.add_columns(
            Jira.id.label('id'),
            Jira.params.label('params'),
            Jira.result.label('result'),
            Jira.key_id.label('key_id'),
            Jira.key_type.label('key_type'),
            func.date_format(Jira.creation_time, "%Y-%m-%d %H:%i:%s").label('creation_time'),
            func.date_format(Jira.modified_time, "%Y-%m-%d %H:%i:%s").label('modified_time'),
        )

    @classmethod
    @transfer2json(
        '?id|!params|!creation_time|!modified_time|!result|!key_id|!key_type'
    )
    def query_all_json(cls, page_size, page_index):
        ret = cls._query().limit(page_size).offset((page_index - 1) * page_size).all()
        return ret

    @classmethod
    def query_all_count(cls):
        ret = cls._query().count()
        return ret

    @classmethod
    @transfer2json(
        '?id|!params|!creation_time|!modified_time|!result|!key_id|!key_type'
    )
    def query_json_by_id(cls, id):
        return cls._query().filter(
            Jira.id == id).all()

    @classmethod
    def create(cls, params, result, key_id, key_type):
        try:
            t = Jira(
                params=params,
                result=result,
                key_type=key_type,
                key_id=key_id,
            )
            db.session.add(t)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            raise CreateObjectException(str(e))

    @classmethod
    def get_version_by_title(cls, issue, project_id):
        version_title = issue.fields.fixVersions[0].name if issue.fields.fixVersions else None
        if version_title is None:
            raise CannotFindObjectException(f'issue {issue} does not have fixVersion ! please check the issue !')
        version = Version.query.filter(Version.title == version_title,
                                       Version.project_id == project_id).first()
        if version:
            version_id = version.id
        else:
            VersionBusiness.version_create(title=version_title,
                                           project_id=project_id,
                                           start_time=None,
                                           end_time=None,
                                           description="jira create",
                                           creator=1,)  # 默认的 版本创建人 1
            version_id = cls.get_version_by_title(issue, project_id)
        return version_id

    @classmethod
    def get_priority(cls, issue):
        priority_map = {
            '紧急': 0, '重要': 1, '次要': 2, '微小': 3
        }
        if hasattr(issue.fields.priority, 'name') and issue.fields.priority.name:
            return priority_map.get(issue.fields.priority.name, 3)

    @classmethod
    def get_user(cls, wxemail):
        user = cls.user_trpc.requests('get', '/user/userinfo/wxemail', query={'email': wxemail})
        if user:
            return user[0].get('userid')
        current_app.logger.warning(f'tcloud not found the user with wxemail {wxemail}')
        return None

    @classmethod
    def get_handler(cls, issue):
        handler = issue.fields.assignee
        if handler and hasattr(handler, 'emailAddress') and handler.emailAddress:
            return cls.get_user(handler.emailAddress)
        else:
            current_app.logger.warning(f'issue {issue} not have assignee {handler} or assignee not have emailAddress')
            return None

    @classmethod
    def get_creator(cls, issue):
        creator = issue.fields.creator
        if creator and hasattr(creator, 'emailAddress') and creator.emailAddress:
            return cls.get_user(creator.emailAddress)
        else:
            current_app.logger.warning(f'issue {issue} not have reporter {creator} or reporter not have emailAddress')
            return None

    @classmethod
    def get_modifier(cls, modifier_name):
        return cls.get_user(modifier_name)

    @classmethod
    def get_project(cls, issue):
        project = issue.fields.project
        if project and hasattr(project, 'name') and project.name:
            project_in_tc = Project.query.filter(Project.name == project.name).first()
            if project_in_tc:
                return project_in_tc.id
            else:
                raise CannotFindObjectException(f'project {project} not found in system!')
        else:
            raise CannotFindObjectException(f'project {project} not have name property!')

    @classmethod
    def get_status(cls, issue):
        return 0

    @classmethod
    def get_worth(cls, issue):
        worth_map = {
            "高价值需求": 1, "非高价值需求": 2
        }
        worth = None
        if hasattr(issue.fields, "customfield_10812") and issue.fields.customfield_10812 is not None:
            worth = issue.fields.customfield_10812.value
        else:
            for field in dir(issue.fields):
                issue_field = getattr(issue.fields, field)
                if (field.startswith('customfield_') and hasattr(issue_field, 'value') and
                        issue_field.value in ['高价值需求', '非高价值需求']):
                    worth = issue_field.value
                    break
        if worth:
            return worth_map.get(worth)
        else:
            current_app.logger.warning(f'issue {issue} not have worth infos, so make worth to 非高价值需求')
            return 2

    @classmethod
    def issue_to_requirement_fields(cls, issue: Issue, modifier=None):
        project_id = cls.get_project(issue)
        return dict(
            title=issue.fields.summary,
            project_id=project_id,
            version=cls.get_version_by_title(issue, project_id),
            handler=cls.get_handler(issue),
            priority=cls.get_priority(issue),
            requirement_type=None,
            attach="{\"images\":[],\"files\":[],\"videos\":[]}",
            board_status=cls.get_status(issue),
            description=issue.fields.description,
            comment=None,
            jira_id=issue.key,
            worth=cls.get_worth(issue),
            report_time=None,
            report_expect=None,
            report_real=None,
            worth_sure=None,
            case_ids=None,
            creator=cls.get_creator(issue),
            modifier=cls.get_modifier(modifier)
        )

    @classmethod
    def requirement_create_handler(cls, issue):
        requirement_dict = cls.issue_to_requirement_fields(issue)
        params = []
        for key in ['title', 'project_id', 'version', 'handler', 'priority', 'requirement_type', 'attach',
                    'board_status', 'description', 'comment', 'jira_id', 'worth', 'report_time', 'report_expect',
                    'report_real', 'worth_sure', 'case_ids', 'creator']:
            value = requirement_dict.get(key)
            params.append(value)
        return RequirementBusiness.requirement_create(*params)

    @classmethod
    def requirement_update_handler(cls, requirement, issue, modifier):
        requirement_dict = cls.issue_to_requirement_fields(issue, modifier)
        params = []
        for key in ["title", "project_id", "version", "board_status", "handler", "description", "comment",
                    "priority", "requirement_type", "attach", "parent_id", "jira_id", "worth", "report_time",
                    "report_expect", "report_real", "worth_sure", "case_ids", "modifier"]:
            value = requirement_dict.get(key)
            if value is None:
                params.append(getattr(requirement, key, None))
            else:
                params.append(value)
        return RequirementBusiness.requirement_modify(requirement.id, *params)

    @classmethod
    def requirement_handler(cls, key):
        jira_result = None
        requirement_id = None
        user_id = request.args.get('user_id', '')
        user_key = request.args.get('user_key', '')
        try:
            issues = jira.search_issues(f'key={key}')
            if issues:
                issue = issues[0]
                requirement = Requirement.query.filter(Requirement.jira_id == str(issue)).first()
                if requirement:
                    cls.requirement_update_handler(requirement, issue, user_key)
                    requirement_id = requirement.id
                else:
                    cls.requirement_create_handler(issue)
                    requirement = Requirement.query.filter(Requirement.jira_id == str(issue)).first()
                    requirement_id = requirement.id
            else:
                jira_result = f'{user_id} {user_key} - jira cannot found issue with key : {key}'
                raise CannotFindObjectException(jira_result)

            jira_result = f"{user_id} {user_key} - {key} success"
            return 0
        except Exception as e:
            raise e
        finally:
            cls.create(key, jira_result, requirement_id, Jira.KEY_MAP.get('requirement'))

    @classmethod
    def get_requirement_by_jira_key(cls, jira_key):
        requirement = Requirement.query.filter(Requirement.jira_id == jira_key).first()
        return requirement

    @classmethod
    def get_assemble_type(cls, issue):
        assemble_map = {
            "客户端": 1,
            "H5&服务端": 2,
            "Skiptest": 3,
            "hotfix": 4,
            "hotfix(需QA验证)": 5,
        }
        assemble = None
        if hasattr(issue.fields, "customfield_10826") and issue.fields.customfield_10826 is not None:
            assemble = issue.fields.customfield_10826.value
        else:
            for field in dir(issue.fields):
                issue_field = getattr(issue.fields, field)
                if (field.startswith('customfield_') and hasattr(issue_field, 'value') and
                        issue_field.value in list(assemble_map.keys())):
                    assemble = issue_field.value
                    break
        if assemble:
            return assemble_map.get(assemble, 1)
        else:
            current_app.logger.warning(f'issue {issue} not have assemble infos, so make assemble to H5&服务端')
            return 2

    @classmethod
    def get_platform(cls, issue):
        platform_map = {
            "后端": 1,
            "PHP": 2,
            "APP": 3,
            "H5": 4,
            "微信商城": 5,
            "小程序": 6
        }
        platform = None
        if hasattr(issue.fields, "customfield_10827") and issue.fields.customfield_10827 is not None:
            platform = [platform_map.get(test.value) for test in issue.fields.customfield_10827]
        else:
            for field in dir(issue.fields):
                issue_field = getattr(issue.fields, field)
                if (field.startswith('customfield_') and hasattr(issue_field, 'value') and
                        issue_field.value in list(platform_map.keys())):
                    platform = [platform_map.get(test.value) for test in issue_field.value]
                    break
        if platform:
            return platform
        else:
            current_app.logger.warning(f'issue {issue} not have platform infos, so make platform to [后端]')
            return [1]

    @classmethod
    def get_dependence(cls, issue):
        dependence = None
        if hasattr(issue.fields, "customfield_10829") and issue.fields.customfield_10829 is not None:
            dependence = issue.fields.customfield_10829
        else:
            current_app.logger.warning(f'issue {issue} not have dependence infos, so make platform to ""')
            dependence = ""
        return dependence

    @classmethod
    def make_comment(cls, requirement):
        if requirement is None:
            return ""
        comment = [{
            "id": requirement.id,
            "title": requirement.title,
            "jira_id": requirement.jira_id
        }]
        return json.dumps(comment)

    @classmethod
    def flow_handler(cls, key):
        requirement = cls.get_requirement_by_jira_key(key)
        if not requirement:
            cls.requirement_handler(key)
            requirement = cls.get_requirement_by_jira_key(key)

        jira_result = None
        user_id = request.args.get('user_id', '')
        user_key = request.args.get('user_key', '')
        try:
            issues = jira.search_issues(f'key={key}')
            if issues:
                issue = issues[0]
                handler = cls.get_handler(issue)
                creator = cls.get_creator(issue)
                data = {
                    "name": f'{key} - {issue.fields.summary}',
                    "flow_type": 1,
                    "user_test": [cls.get_user("*****@*****.**")],
                    "requirement_list": str(requirement.id),
                    "flow_assemble_id": cls.get_assemble_type(issue),
                    "project_id": cls.get_project(issue),
                    "user_dev": [handler] if handler else [],
                    "user_owner": [handler] if handler else [],
                    "user_prod": [creator] if creator else [],
                    "platform": cls.get_platform(issue),
                    "dependence": cls.get_dependence(issue),
                    "comment": cls.make_comment(requirement),
                    "jira_id": key,
                    "creator": cls.get_creator(issue)
                }
            else:
                jira_result = f'{user_id} {user_key} - jira cannot found issue with key : {key}'
                raise CannotFindObjectException(jira_result)
            response = cls.flow_trpc.requests('post', '/flow/', body=data)
            if isinstance(response, dict):
                if response.get('code') == 0:
                    jira_result = f"{user_id} {user_key} - {key} success"
                else:
                    jira_result = f"{user_id} {user_key} - {key} {response.get('message', 'nothing in message')}"
            else:
                jira_result = f"{user_id} {user_key} - {key} unknown!"
            return 0
        except Exception as e:
            raise e
        finally:
            cls.create(key, jira_result, requirement.id, Jira.KEY_MAP.get('flow'))
Example #7
0
class WxLoginBusiness(object):
    public_trpc = Trpc('public')

    @classmethod
    def get_access_token(cls):
        # acc = Config.query.filter(Config.module == 'access_token', Config.module_type == 1).first()
        acc = cls.public_trpc.requests('get', '/public/config',
                                       {'module': 'access_token', 'module_type': 1, 'is_all': 1})
        if not acc:
            return 102, [], 'error'
        if '{' in acc['content']:
            content = json.loads(acc['content'])
            token = content['access_token']
        else:
            token = acc['content']
        modified_time = datetime.datetime.strptime(acc['modified_time'], '%Y-%m-%d %H:%M:%S')
        expires_time = datetime.datetime.now() + datetime.timedelta(hours=-2)
        if modified_time > expires_time:
            current_app.logger.info('access_token未过期')
            return token
        else:
            current_app.logger.info('access_token已过期,重新获取!')
            ret = cls.force_get_access_token()
            return ret

    @classmethod
    def force_get_access_token(cls):
        # 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET'
        # corpid 企业ID,corpsecret 应用的凭证密钥
        corp_id = CORP_ID
        # corp_secret = Config.query.filter(Config.module == 'corp_secret', Config.module_type == 1).first()
        corp_secret = cls.public_trpc.requests('get', '/public/config', {'module': 'corp_secret', 'module_type': 1})
        # corp_secret = corp_secret.content
        current_app.logger.info('corp_id:' + corp_id + ',corp_secret:' + corp_secret)
        url = QYWXHost + 'gettoken' + '?corpid={}&corpsecret={}'.format(corp_id, corp_secret)
        current_app.logger.info(url)
        ret = requests.get(url=url)
        current_app.logger.info(ret.text)
        r = json.loads(ret.text)
        if r['errcode'] is 0:
            # acc = Config.query.filter(Config.module == 'access_token', Config.module_type == 1).first()
            access_token_info = cls.public_trpc.requests('get', '/public/config',
                                                         {'module': 'access_token', 'module_type': 1, 'is_all': 1})

            data = cls.public_trpc.requests('post', f"/public/config/{access_token_info['id']}",
                                            body={
                                                'module': 'access_token', 'module_type': 1,
                                                'content': {"access_token": r['access_token']},
                                                'project_id': 0
                                            })
            if data == 'success':
                return r['access_token']
            else:
                return ''
        else:
            return ''

    @classmethod
    def get_user_info(cls, access_token, user_code):
        # 获取访问用户身份 'https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE'
        # access_token 调用接口凭证,
        # code 通过成员授权获取到的code,最大为512字节。每次成员授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
        # "errcode":40029, "errmsg":"invalid code
        # "errcode":40014, "errmsg":"invalid access_token"
        code = user_code
        url = QYWXHost + 'user/getuserinfo' + '?access_token={}&code={}'.format(access_token, code)
        current_app.logger.info(url)
        ret = requests.get(url=url)
        current_app.logger.info(ret.text)
        r = json.loads(ret.text)
        if r['errcode'] is 0:
            if 'UserId' in r.keys():
                return r['errcode'], r['UserId']
            return 102, ''
        else:
            return r['errcode'], ''

    @classmethod
    def get_user(cls, user_code):
        # 读取成员 'https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID'
        # access_token 调用接口凭证,
        # userid 成员UserID。对应管理端的帐号,企业内必须唯一。不区分大小写,长度为1~64个字节

        access_token = cls.get_access_token()
        errcode, user_id = cls.get_user_info(access_token, user_code)
        if errcode == 102:
            return 109, [], '非企业人员'
        if errcode == 40014:
            access_token = cls.force_get_access_token()

        url = QYWXHost + 'user/get' + '?access_token={}&userid={}'.format(access_token, user_id)
        current_app.logger.info(url)
        ret = requests.get(url=url)
        current_app.logger.info(ret.text)
        r = json.loads(ret.text)
        if r['errcode'] is 0:
            uid = r['userid']
            nickname = r['name']
            email = r['email']
            telephone = r['mobile']
            avatar = r['avatar']
            current_app.logger.info("avatar:" + str(avatar))
            res = User.query.filter(User.wx_userid == uid, User.status == User.ACTIVE).first()

            if res:
                code, data = AuthBusiness.no_password_login(res.name)
                pic = User.query.get(res.id)
                pic.picture = avatar
                db.session.add(pic)
                db.session.commit()
                try:
                    TrackUserBusiness.user_track(res)
                except Exception as e:
                    current_app.logger.info(e)
                return code, data, ''
            else:
                UserBusiness.create_new_wxuser(uid, nickname, '', email, telephone, avatar)
                code, data = AuthBusiness.no_password_login(uid)
                return code, data, ''
        else:
            return r['errcode'], [], r['errmsg']
Example #8
0
class ProjectBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def _query(cls):
        return Project.query.outerjoin(
            UserBindProject, UserBindProject.project_id == Project.id).outerjoin(
            User, User.id == UserBindProject.user_id).add_columns(
            Project.id.label('id'),
            Project.name.label('name'),
            Project.description.label('description'),
            Project.weight.label('weight'),
            Project.status.label('status'),
            Project.logo.label('logo'),
            User.id.label('user_id'),
            User.nickname.label('nickname'),
        )

    @classmethod
    @slicejson(['user|id|nickname|user_id|nickname'])
    @transfer2jsonwithoutset('?id|!name|!description|!status|!weight|!logo|@user_id|@nickname')
    def query_all_json(cls):
        userid = request.args.get('userid')
        ret = cls._query().filter(Project.status == Project.ACTIVE)
        if userid:
            ret = ret.filter(UserBindProject.user_id == userid)
        ret = ret.order_by(
            desc(Project.weight)).order_by(Project.id).all()

        return ret

    @classmethod
    @slicejson(['user|id|nickname|user_id|nickname'])
    @transfer2json('?id|!name|!description|!status|!weight|!logo|@user_id|@nickname')
    def query_json_by_id(cls, id):
        return cls._query().filter(Project.id == id,
                                   Project.status == Project.ACTIVE).order_by(
            desc(Project.weight)).all()

    @classmethod
    def create_new_project(cls, name, description, logo):

        try:
            p = Project(
                name=name,
                description=description,
                logo=logo,
            )
            db.session.add(p)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def modify(cls, id, name, description, weight, logo):

        project = Project.query.get(id)
        if project.status == Project.ACTIVE:
            try:
                project.name = name
                project.description = description
                project.weight = weight
                project.logo = logo
                db.session.add(project)
                db.session.commit()
                return 0, None
            except Exception as e:
                db.session.rollback()
                current_app.logger.error(str(e))
                return 102, str(e)
        else:
            return 101, "The Project's Status is DISABLE!"

    @classmethod
    def close_project(cls, id):
        project = Project.query.get(id)
        project.status = Project.DISABLE
        db.session.add(project)
        db.session.commit()
        return 0

    @classmethod
    def bind_users(cls, pid, userids):
        try:
            [db.session.delete(item) for item in UserBindProject.query.filter_by(project_id=pid).all()]
            [db.session.add(UserBindProject(user_id=uid, project_id=pid)) for uid in userids]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def detach_users(cls, pid, userids):
        try:
            [db.session.delete(item) for item in UserBindProject.query.filter_by(project_id=pid, user_id=userids).all()]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def add_users(cls, pid, userids):
        try:
            [db.session.add(UserBindProject(user_id=uid, project_id=pid)) for uid in userids]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def detach_users_all(cls, userids):
        try:
            [db.session.delete(item) for item in UserBindProject.query.filter_by(user_id=userids).all()]
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def index(cls, id):
        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        project_id = id
        tester_data = DashboardBusiness.team_case_issue_dashboard(project_id, start_time, str(end_time))
        # 需求总数随版本的趋势图
        requirement = Requirement.query.outerjoin(
            Version, Version.id == Requirement.version).add_columns(
            Requirement.version.label('version_id'),
            Version.title.label('version_title'),
            func.count('*').label('count')
        ).filter(
            Requirement.project_id == id, Requirement.status != Requirement.DISABLE,
            Version.status != Version.DISABLE, Requirement.parent_id == 0
        )
        # issue总数随版本的趋势图
        issue = Issue.query.outerjoin(
            Version, Version.id == Issue.version).add_columns(
            Issue.version.label('version_id'),
            Version.title.label('version_title'),
            func.count('*').label('count')
        ).filter(
            Issue.project_id == id, Issue.status != Issue.DISABLE, Version.status != Version.DISABLE
        )
        # issue打开数随版本的趋势图
        issue_open = Issue.query.outerjoin(
            Version, Version.id == Issue.version).add_columns(
            Issue.version.label('version_id'),
            func.count('*').label('count')
        ).filter(
            Issue.project_id == id, Issue.status != Issue.DISABLE, Issue.handle_status != 4,
            Version.status != Version.DISABLE
        )
        # task总数随版本的趋势图
        task = Task.query.outerjoin(
            Version, Version.id == Task.version).add_columns(
            Task.version.label('version_id'),
            Version.title.label('version_title'),
            func.count('*').label('count')
        ).filter(
            Task.project_id == id, Task.status != Task.DISABLE, Version.status != Version.DISABLE)
        taskcase = TaskCase.query.outerjoin(
            Version, Version.id == TaskCase.version).add_columns(
            TaskCase.version.label('version_id'),
            Version.title.label('version_title'),
            func.count('*').label('count')
        ).filter(
            TaskCase.project_id == id, TaskCase.status != TaskCase.DISABLE, Version.status != Version.DISABLE
        )
        # issue的状态分布
        issue_status_ret = Issue.query.outerjoin(
            Version, Version.id == Issue.version).add_columns(
            Issue.handle_status.label('handle_status'),
            func.count('*').label('count')
        ).filter(
            Issue.project_id == id, Issue.status != Issue.DISABLE, Version.status != Version.DISABLE
        )

        # issue的rank分布
        issue_rank_ret = Issue.query.outerjoin(
            Version, Version.id == Issue.version).add_columns(
            Issue.rank.label('rank')
        ).filter(
            Issue.project_id == id, Issue.status != Issue.DISABLE, Version.status != Version.DISABLE
        )

        # 根据时间过滤数据
        if start_time and end_time:
            requirement = requirement.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))
            issue = issue.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))
            issue_open = issue_open.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))
            task = task.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))
            taskcase = taskcase.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))
            issue_status_ret = issue_status_ret.filter(Issue.creation_time.between(start_time, end_time + " 23:59:59"))
            issue_rank_ret = issue_rank_ret.filter(Version.start_time.between(start_time, end_time + " 23:59:59"))

        requirement = requirement.group_by(Requirement.version).order_by(desc(Version.id)).all()
        issue = issue.group_by(Issue.version).order_by(desc(Version.id)).all()
        issue_open = issue_open.group_by(Issue.version).order_by(desc(Version.id)).all()
        task = task.group_by(Task.version).order_by(desc(Version.id)).all()
        taskcase = taskcase.group_by(TaskCase.version).all()
        issue_status_ret = issue_status_ret.group_by(Issue.handle_status).all()
        # issue_rank_ret = issue_rank_ret.group_by(Issue.version).order_by(desc(Version.id)).all()
        issue_rank_ret = issue_rank_ret.order_by(desc(Version.id)).all()

        # 计算总数
        requirement_sum = sum(r.count for r in requirement)
        task_sum = sum(r.count for r in task)
        taskcase_sum = sum(r.count for r in taskcase)
        issue_sum = sum(r.count for r in issue)

        # 计算rank的总值
        issue_count = []
        issue_rank = []
        issue_all_rank = []
        temp = 0
        for i in range(0, len(issue)):
            issue_count.append(int(issue[i].count))

        for i in range(0, len(issue_rank_ret)):
            if isinstance(issue_rank_ret[i].rank, int):
                issue_rank.append(int(issue_rank_ret[i].rank))
            else:
                issue_rank.append(0)

        for i in range(0, len(issue_count)):
            sumcount = 0
            for j in range(temp, temp + issue_count[i]):
                if j < len(issue_rank):
                    sumcount = sumcount + issue_rank[j]
                else:
                    sumcount = 0
            temp = j + 1
            issue_all_rank.append(sumcount)

        # 处理汇总数据
        issue_status = [dict(i) for i in map(lambda x: zip(('handle_status', 'count'), x),
                                             zip([i.handle_status for i in issue_status_ret],
                                                 [i.count for i in issue_status_ret]))]
        requirement_info = [dict(i) for i in map(lambda x: zip(('version_id', 'version_title', 'count'), x),
                                                 zip([i.version_id for i in requirement],
                                                     [i.version_title for i in requirement],
                                                     [i.count for i in requirement]))]
        task_info = [dict(i) for i in map(lambda x: zip(('version_id', 'version_title', 'count'), x),
                                          zip([i.version_id for i in task], [i.version_title for i in task],
                                              [i.count for i in task]))]
        issue_info = [dict(i) for i in map(lambda x: zip(('version_id', 'version_title', 'count'), x),
                                           zip([i.version_id for i in issue], [i.version_title for i in issue],
                                               [i.count for i in issue]))]
        issue_open_info = [dict(i) for i in map(lambda x: zip(('version_id', 'open'), x),
                                                zip([i.version_id for i in issue_open], [i.count for i in issue_open]))]

        for i in range(len(issue_info)):
            issue_info[i]['open'] = 0
            for a in range(len(issue_open_info)):
                if int(issue_open_info[a]['version_id']) == int(issue_info[i]['version_id']):
                    issue_info[i]['open'] = issue_open_info[a]['open']
            if len(issue_info) == len(issue_all_rank):
                issue_info[i]['rank'] = issue_all_rank[i]
            else:
                issue_info[i]['rank'] = 0

        detail = [
            dict(
                requirement_sum=requirement_sum,
                issue_sum=issue_sum,
                task_sum=task_sum,
                requirement_info=requirement_info,
                issue_info=issue_info,
                task_info=task_info,
                issue_status=issue_status,
                taskcase_sum=taskcase_sum,
                tester_data=tester_data,
            )
        ]
        return detail
Example #9
0
class JobsBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def credit_check_daily(cls):
        db.app.logger.info('credit-check-daily start')
        job = {
            'id': 'credit-check-daily'
        }
        hold_time = Phone.HOLD_DATE  # 可持有时间
        credit_time = Credit.CREDIT_DATE  # 信用分 计算时间
        result = 'success'  # 默认 job 结果
        log = ''
        try:
            with db.app.app_context():
                phones = Phone.query.filter(Phone.status == Phone.ACTIVE)
                log_template_admin = '持有用户 {}({}) 是 admin,不需要提醒!'
                log_template_creator = '持有用户 {}({}) 是 创建者,不需要提醒!'
                log_template_normal = '持有用户 {}({}) 在使用期限内,不需要提醒!'
                log_template_delay = '持有用户 {}({}) 已经超出使用期限,需要提醒!'
                log_dict = {}  # 以 phone.id 作为 key,记录对应设备状态

                confirm_delay_time = 1  # 24 hours
                confirm_delay_reset_time = confirm_delay_time * 3  # 3 days

                admins = cls.user_trpc.requests('get', '/user/admin')
                for phone in phones:
                    phone_holder = User.query.get(phone.borrow_id)
                    phone_recorder = PhoneRecord.query.filter(PhoneRecord.phone_id == phone.id). \
                        order_by(PhoneRecord.id.desc()).first()

                    # 查询 确认时间 过长发送提醒
                    phone_borrow = PhoneBorrowBusiness.get_borrow_by_phone_id(phone.id)
                    if phone_borrow:
                        if int(phone_borrow.confirm_userid) != 0:
                            phone_new_holder = User.query.get(phone_borrow.confirm_userid)

                            date_now = datetime.now()
                            date_confirm_hold = (date_now - datetime.strptime(phone_borrow.modified_time,
                                                                              '%Y-%m-%d %H:%M:%S')).days  # 计算天
                            if date_confirm_hold > confirm_delay_reset_time:
                                PhoneBusiness.cancel_move_to(phone.id)
                            elif date_confirm_hold > confirm_delay_time:
                                PhoneBusiness.send_need_confirm_msg(phone, phone_holder, phone_new_holder)
                            else:  # 如果没有超时,不发送
                                pass
                        else:  # 如果是0,判断借用人是否为空,如果不是则 发送 被借用人 提醒转出信息
                            users = PhoneBorrowBusiness.get_user_list_by_phone_id(phone.id)
                            user_id_list = [int(user.get('id')) for user in users]
                            if len(user_id_list) >= 1 and phone.borrow_id not in user_id_list:
                                date_now = datetime.now()
                                date_confirm_hold = (date_now - datetime.strptime(phone_borrow.modified_time,
                                                                                  '%Y-%m-%d %H:%M:%S')).days
                                if date_confirm_hold > confirm_delay_time:
                                    PhoneBusiness.send_need_move_msg(phone, phone_holder)
                                else:  # 如果没有超时,不发送
                                    pass
                    else:  # 如果没有借用信息,则不处理
                        pass

                    # 查询过期发送提醒: 如果 当前持有者 是 admin 或者 是创建者 则不提醒, admin 用户之间互借不提醒
                    if phone_holder.id in admins:
                        log_dict[phone.id] = log_template_admin.format(phone_holder.nickname, phone_holder.wx_userid)
                        db.app.logger.info(f'[{phone.id}] here is admin ({phone_holder.id} - {phone.creator_id})')
                        continue
                    elif phone_holder.id == phone.creator_id:
                        log_dict[phone.id] = log_template_creator.format(phone_holder.nickname, phone_holder.wx_userid)
                        db.app.logger.info(f'[{phone.id}] here is creator ({phone_holder.id} - {phone.creator_id})')
                        continue
                    else:
                        date_now = datetime.now()  # 当前时间
                        date_borrow = phone_recorder.creation_time  # 借入时间
                        deadline = PhoneBusiness.deadline(phone)  # 到期时间
                        date_holder_hold = (date_now - date_borrow).days  # 持有者已经持有时间
                        date_hold_over = date_holder_hold - hold_time  # 持有超出时间
                        date_hold_over_credit = date_holder_hold - credit_time  # 持有超出信用分时间
                        db.app.logger.info("持有时间: {}".format(date_holder_hold))
                        if date_hold_over > 0:  # 如果 '已经持有时间' > '可持有时间', 发送提醒
                            PhoneBusiness.send_delay_msg_qywx(phone, phone_holder)
                            log_dict[phone.id] = log_template_delay.format(phone_holder.nickname,
                                                                           phone_holder.wx_userid)
                        else:  # 如果 还在可以持有时间范围内, 则不发信息
                            log_dict[phone.id] = log_template_normal.format(phone_holder.nickname,
                                                                            phone_holder.wx_userid)

                        if date_hold_over_credit > 0:  # 如果 '已持有时间' > '信用分时间', 减分, 目前不发减分提醒
                            reason = '设备 {}({}) 超出归还期限 {} 已有 {} 天'.format(phone.name, phone.asset_id, deadline,
                                                                          date_hold_over_credit)
                            CreditBusiness.add_sub_score(phone_holder.id, -1, reason)
        except Exception as e:
            db.app.logger.error(str(e))
            db.app.logger.error(traceback.format_exc())
            result = 'error: {}'.format(str(e))

        JobsRecordBusiness.create(job['id'], result, log_dict)

        db.app.logger.info('credit-check-daily stop')
Example #10
0
from apps.autotest.business.monkey import (
    MonkeyBusiness,
    MonkeyDeviceStatusBusiness,
    MonkeyErrorLogBusiness,
    MonkeyPackageBusiness,
    MonkeyReportBusiness,
    MonkeyDeviceUsingBusiness,
)
from apps.autotest.extentions import parse_list_args2, parse_list_args, validation, parse_json_form
from library.api.exceptions import FieldMissingException
from library.api.render import json_list_render, json_detail_render
from library.trpc import Trpc

monkey = Blueprint('monkey', __name__)

tool_trpc = Trpc('extention')


@monkey.route('/', methods=['GET'])
def monkey_index_handler():
    limit, offset = parse_list_args()

    monkey_id = request.args.get('monkey_id')

    if monkey_id:
        data = MonkeyBusiness.query_all_json()
        return json_list_render(0, data, limit, offset)

    data = MonkeyBusiness.query_all_json(limit, offset)
    return {"code": 0, "data": data}
Example #11
0
class VersionBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def project_permission(cls, pid=None, id=None):
        project_id = cls.user_trpc.requests('get', '/user/userbindproject', {'userid': g.userid})
        if g.is_admin:
            return 0
        if pid:
            return 0 if pid in project_id else 1
        else:
            ret = Version.query.add_columns(Version.project_id.label('projectid')).filter(Version.id == id).first()
            return 0 if ret.projectid in project_id else 1

    @classmethod
    def _query(cls):
        user_creator = aliased(User)

        return Version.query.outerjoin(
            user_creator, user_creator.id == Version.creator).add_columns(
            Version.id.label('id'),
            Version.title.label('title'),
            Version.project_id.label('project_id'),
            func.date_format(Version.creation_time, "%Y-%m-%d").label('creation_time'),
            func.date_format(Version.start_time, "%Y-%m-%d").label('start_time'),
            func.date_format(Version.end_time, "%Y-%m-%d").label('end_time'),
            func.date_format(Version.publish_time, "%Y-%m-%d").label('publish_time'),
            Version.creator.label('creator'),
            Version.publish_status.label('publish_status'),
            Version.status.label('status'),
            Version.description.label('description'),
            Version.comment.label('comment'),
            Version.weight.label('weight'),
            user_creator.id.label('creator_id'),
            user_creator.nickname.label('creator_name'),

        )

    @classmethod
    @slicejson([
        'creator|id|name|creator_id|creator_name'])
    @transfer2json(
        '?id|!title|!project_id|!creation_time|!start_time|!end_time|!publish_time|!publish_status|!status|'
        '!description|!comment|@creator_id|@creator_name')
    def query_all_json(cls):
        projectid = request.args.get('projectid')
        versionid = request.args.get('versionid')
        publish_status = request.args.get('publishstatus')
        ret = cls._query().filter(Version.status != Version.DISABLE)
        if projectid:
            ret = ret.filter(Version.project_id == projectid)
        if versionid:
            ret = ret.filter(Version.version == versionid)
        if publish_status:
            ret = ret.filter(Version.publish_status == publish_status)
        ret = ret.order_by(desc(Version.id)).all()
        return ret

    @classmethod
    @slicejson(['creator|id|name|creator_id|creator_name'])
    @transfer2json(
        '?id|!title|!project_id|!creation_time|!start_time|!end_time|!publish_time|!publish_status|!status|'
        '!description|!comment|@creator_id|@creator_name')
    def query_by_id(cls, versionid):
        ret = cls._query().filter(Version.status != Version.DISABLE,
                                  Version.id == versionid).all()
        return ret

    @classmethod
    def version_delete(cls, versionid):
        version = Version.query.get(versionid)
        version.status = Version.DISABLE
        db.session.add(version)
        db.session.commit()
        return 0

    @classmethod
    def version_publish(cls, versionid):
        version = Version.query.get(versionid)
        if version is None:
            return 101
        version.publish_status = Version.IS_PUBLISH
        version.publish_time = time.strftime('%Y-%m-%d %H:%M:%S',
                                             time.localtime(time.time()))
        db.session.add(version)
        db.session.commit()
        return 0

    @classmethod
    def version_create(cls, title, project_id, start_time, end_time, description, creator=None):
        try:
            creator = g.userid if creator is None else creator
            current_app.logger.info("creator:" + str(creator))
            c = Version(
                title=title,
                project_id=project_id,
                start_time=start_time,
                end_time=end_time,
                creator=creator,
                description=description,
            )
            db.session.add(c)
            db.session.commit()
            mid = c.id
            c.version_number = 'TC' + str(mid)
            db.session.add(c)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            return 102

    @classmethod
    def version_modify(cls, versionid, title, start_time, end_time, description):
        try:
            c = Version.query.get(versionid)
            c.title = title,
            c.start_time = start_time,
            c.end_time = end_time,
            c.description = description,
            db.session.add(c)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            return 301
Example #12
0
class CaseBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def project_permission(cls, pid=None, mid=None, id=None):
        project_id = cls.user_trpc.requests('get', '/user/userbindproject',
                                            {'userid': g.userid})
        if g.is_admin:
            return 0

        ret = Module.query.add_columns(
            Module.project_id.label('projectid')).filter(
                Module.id == mid).first()
        if ret:
            pid = ret.projectid
        if pid:
            return 0 if pid in project_id else 1
        else:
            ret = Case.query.outerjoin(
                Module, Case.module_id == Module.id).add_columns(
                    Module.project_id.label('projectid')).filter(
                        Case.id == id).first()
            return 0 if ret.projectid in project_id else 1

    @classmethod
    def _query(cls):
        return Case.query.outerjoin(
            Module, Case.module_id == Module.id).outerjoin(
                User, User.id == Case.creator).add_columns(
                    Case.id.label('id'), Case.cnumber.label('cnumber'),
                    Case.ctype.label('ctype'), Case.title.label('title'),
                    Case.precondition.label('precondition'),
                    Case.step_result.label('step_result'),
                    Case.is_auto.label('is_auto'),
                    Case.priority.label('priority'),
                    Case.status.label('status'),
                    func.date_format(
                        Case.creation_time,
                        "%Y-%m-%d %H:%i:%s").label('creation_time'),
                    func.date_format(
                        Case.modified_time,
                        "%Y-%m-%d %H:%i:%s").label('modified_time'),
                    Module.id.label('moduleid'), Module.name.label('module'),
                    User.id.label('userid'), User.nickname.label('username'))

    @classmethod
    def case_total_groupby_module(cls):
        return Case.query.outerjoin(Module,
                                    Module.id == Case.module_id).add_columns(
                                        Module.id.label('id'),
                                        Module.project_id.label('projectid'),
                                        Module.status.label('status'),
                                        func.count('*').label('total'),
                                    )

    @classmethod
    def _query_for_requirement(cls):
        return Case.query.outerjoin(
            Module, Case.module_id ==
            Module.id).outerjoin(User, User.id == Case.creator).outerjoin(
                RequirementBindCase,
                and_(RequirementBindCase.case_id == Case.id,
                     RequirementBindCase.status == RequirementBindCase.ACTIVE)
            ).outerjoin(
                Requirement,
                and_(RequirementBindCase.requirement_id == Requirement.id,
                     Requirement.status == Requirement.ACTIVE)).add_columns(
                         Case.id.label('id'), Case.cnumber.label('cnumber'),
                         Case.ctype.label('ctype'), Case.title.label('title'),
                         Case.precondition.label('precondition'),
                         Case.step_result.label('step_result'),
                         Case.is_auto.label('is_auto'),
                         Case.priority.label('priority'),
                         Case.status.label('status'),
                         func.date_format(
                             Case.creation_time,
                             "%Y-%m-%d %H:%i:%s").label('creation_time'),
                         func.date_format(
                             Case.modified_time,
                             "%Y-%m-%d %H:%i:%s").label('modified_time'),
                         Module.id.label('moduleid'),
                         Module.name.label('module'), User.id.label('userid'),
                         User.nickname.label('username'),
                         Requirement.id.label('requirement_id'),
                         Requirement.title.label('requirement_title'))

    @classmethod
    @transfer2json(
        '?id|!cnumber|!ctype|!title|!precondition|!step_result|!creation_time|!modified_time'
        '|!is_auto|!status|!moduleid|!module|!userid|!username|!priority')
    def query_all_json(cls, limit, offset):
        pid = request.args.get('projectid')
        if pid is not None:
            ret = []
            [
                ret.extend(case) for case in (
                    cls._query().filter(
                        Case.status == Case.ACTIVE, Case.module_id ==
                        moduleid[0]).order_by(desc(Case.id)).all()
                    for moduleid in db.session.query(Module.id).filter(
                        Module.project_id == pid).all())
            ]
            return ret
Example #13
0
 def __init__(self):
     self.public_trpc = Trpc('public')
     self.message_trpc = Trpc('message')
Example #14
0
class TrackBusiness(object):
    public_trpc = Trpc('public')

    @classmethod
    def get_token(cls, user_id, name, nickname):

        url = str(cls.get_url()) + '/v1/user/innerAuth'
        data = {
            "userName": name, "userId": user_id, "userRealName": nickname, "mobile": "", "email": "tcloud",
            "type": 1
        }

        data = json.dumps(data)
        header = {"Content-Type": "application/json"}

        ret = requests.post(url=url, data=data, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0:
            return ret['token']

        return None

    @classmethod
    def get_sdk_list(cls):

        project_id = request.args.get('project_id')
        page = request.args.get('page_index')
        size = request.args.get('page_size')
        url = str(TrackBusiness.get_url()) + '/v1/data'

        track_project_id = cls.get_project_id(project_id)

        if track_project_id is None:
            return 0, [], 0, 'ok'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)

        header = {"Authorization": tarck_token}

        params = {"project_id": track_project_id, "page": page, "size": size}

        ret = requests.get(url=url, params=params, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0:
            return ret['code'], ret['data'], ret['total'], 'ok'

        return 101, [], 0, '获取列表失败'

    # 获取获取设备号类型列表
    @classmethod
    def get_device_type_list(cls):

        url = str(TrackBusiness.get_url()) + '/v1/device/id'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token}
        ret = requests.get(url=url, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0:
            return ret['code'], ret['data'], 'ok'

        return 101, [], '获取设备类型失败'

    # 获取项目id
    @classmethod
    def get_project_id(cls, project_id):

        # project_config = Config.query.add_columns(Config.content.label('content')).filter(
        #     Config.module == 'track',
        #     Config.module_type == 1).first().content
        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'track', 'module_type': 1})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_project_id = None
        operation_dict = run_dict['operation_dict']
        for i in range(0, len(operation_dict)):
            track_dict = operation_dict[i]
            for k, v in track_dict.items():
                if int(k) == int(project_id):
                    track_project_id = int(v)

        return track_project_id

    # 获取url
    @classmethod
    def get_url(cls):
        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'track', 'module_type': 2})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_url = run_dict['URL']

        return track_url

    # 获取websocket_url
    @classmethod
    def get_websocket(cls):
        project_config = cls.public_trpc.requests('get', '/public/config', {'module': 'track', 'module_type': 3})
        if project_config:
            run_dict = json.loads(project_config)
        else:
            return None
        track_url = run_dict['URL']

        return track_url

    # 获取事件列表
    @classmethod
    def get_event_list(cls):

        project_id = request.args.get('project_id')
        page_index = request.args.get('page_index')
        page_size = request.args.get('page_size')
        name = request.args.get('name')
        platform = request.args.get('platform')
        updator = request.args.get('updator')
        creator = request.args.get('creator')

        track_project_id = cls.get_project_id(project_id)

        if track_project_id is None:
            return 0, [], 0, 'ok'

        url = str(TrackBusiness.get_url()) + '/v1/event'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token}

        params = {
            "project_id": track_project_id, "page": page_index, "size": page_size, "name": name,
            "platform": platform, "updator": updator, "creator": creator
        }

        ret = requests.get(url=url, headers=header, params=params)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
            return ret['code'], ret['data'], ret['total'], 'ok'

        return 101, [], 0, '获取事件列表失败'

    # 获取事件列表
    @classmethod
    def create_event(cls, project_id, version, update_comment, platform_list, param_list, name, description):

        track_project_id = cls.get_project_id(project_id)
        if track_project_id is None:
            return 0, [], 'ok'

        url = str(TrackBusiness.get_url()) + '/v1/event'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token, "Content-Type": "application/json"}

        data = {
            "projectId": track_project_id, "version": version, "updateComment": update_comment,
            "platformList": platform_list, "paramList": param_list, "name": name, "description": description
        }
        data = json.dumps(data)

        ret = requests.post(url=url, data=data, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
            return ret['code'], ret['data'], 'ok'

        return 101, [], '创建事件失败'

    # 删除事件
    @classmethod
    def track_delete(cls, event_id, delete_comment):

        url = str(TrackBusiness.get_url()) + '/v1/event/' + str(event_id)

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token, "Content-Type": "application/json"}

        data = {"deleteComment": delete_comment}
        data = json.dumps(data)

        ret = requests.delete(url=url, data=data, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
            return ret['code'], ret['data'], 'ok'

        return 101, [], '删除事件失败'

    # 获取事件列表
    @classmethod
    def track_modify(cls, event_id, create_at, creator, delete_comment, description, id, name, param_list, platform,
                     platform_list, projectId, project_id, status, updateComment, update_at,
                     update_comment, updator, version):

        url = str(TrackBusiness.get_url()) + '/v1/event/' + str(event_id)

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)

        header = {"Authorization": tarck_token, "Content-Type": "application/json"}

        data = {
            "create_at": create_at, "creator": creator, "delete_comment": delete_comment,
            "description": description, "id": id, "name": name, "paramList": param_list,
            "platform": platform, "platformList": platform_list, "projectId": projectId, "project_id": project_id,
            "status": status, "updateComment": updateComment, "update_at": update_at,
            "update_comment": update_comment, "updator": updator, "version": version
        }
        data = json.dumps(data)

        ret = requests.patch(url=url, data=data, headers=header)
        ret = json.loads(ret.content)

        if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
            return ret['code'], ret['data'], 'ok'

        return 101, [], '修改事件失败'

    # 创建属性
    @classmethod
    def track_add_param(cls):

        url = str(TrackBusiness.get_url()) + '/v1/event/createparam'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token, "Content-Type": "application/json"}

        data = request.json

        if data:
            data = json.dumps(data)

            ret = requests.post(url=url, data=data, headers=header)
            ret = json.loads(ret.content)

            if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
                return ret['code'], ret['data'], 'ok'

        return 101, [], '创建属性失败'

    # 删除属性
    @classmethod
    def track_delete_param(cls):

        url = str(TrackBusiness.get_url()) + '/v1/event/deleteparam'

        tarck_token = cls.get_token(g.userid, g.username, g.nickname)
        header = {"Authorization": tarck_token, "Content-Type": "application/json"}

        data = request.json
        if data:
            data = json.dumps(data)
            ret = requests.delete(url=url, data=data, headers=header)
            ret = json.loads(ret.content)

            if ret and 'code' in ret and ret['code'] == 0 and 'data' in ret:
                return ret['code'], ret['data'], 'ok'

        return 101, [], '删除属性失败'
Example #15
0
class PhoneBusiness(object):
    public_trpc = Trpc('public')
    user_trpc = Trpc('auth')
    message_trpc = Trpc('message')

    @classmethod
    def _query(cls):
        return Phone.query.add_columns(
            Phone.id.label('id'),
            Phone.name.label('name'),
            Phone.asset_id.label('asset_id'),
            Phone.vendor.label('vendor'),
            Phone.device_number.label('device_number'),
            Phone.os.label('os'),
            Phone.cpu.label('cpu'),
            Phone.core.label('core'),
            Phone.ram.label('ram'),
            Phone.rom.label('rom'),
            Phone.resolution.label('resolution'),
            Phone.buy_date.label('buy_date'),
            Phone.region.label('region'),
            Phone.status.label('status'),
            Phone.borrow_id.label('borrow_id'),
            Phone.creator_id.label('creator_id'),
            Phone.device_source.label('device_source'),
            Phone.device_belong.label('device_belong'),
        )

    @classmethod
    @transfer2json(
        '?id|!name|!asset_id|!vendor|!device_number|!os|!cpu|!core|!ram|!rom|!resolution|!buy_date|!region|!status|'
        '!borrow_id|!creator_id|!device_source|!device_belong'
    )
    def query_all_json(cls, page_size, page_index):
        ret = cls._query().filter(Phone.status == Phone.ACTIVE). \
            order_by(desc(Phone.id)).limit(int(page_size)).offset(int(page_index - 1) * int(page_size)).all()
        return ret

    @classmethod
    def query_all_count(cls):
        count = cls._query().filter(Phone.status == Phone.ACTIVE).count()
        return count

    @classmethod
    @transfer2json(
        '?id|!name|!asset_id|!vendor|!device_number|!os|!cpu|!core|!ram|!rom|!resolution|!buy_date|!region|!status|'
        '!borrow_id|!creator_id|!device_source|!device_belong'
    )
    def query_json_by_id(cls, id):
        return cls._query().filter(
            Phone.id == id, Phone.status == Phone.ACTIVE).all()

    @classmethod
    def get_phone_by_id(cls, id):
        users = user_trpc.requests(method='get', path='/user')
        phone = cls.query_json_by_id(id)

        if len(phone) <= 0:
            return 101, 'phone not exist!'
        phone = phone[0]
        for user in users:
            if user.get('userid') == phone.get('creator_id'):
                phone['creator_nickname'] = user.get('nickname')
            if user.get('userid') == phone.get('borrow_id'):
                phone['borrow_nickname'] = user.get('nickname')
        return 0, [phone]

    @classmethod
    def send_message(cls, user_list, creator, text):
        if cls.message_trpc.requests('post', '/message',
                                     body={'send_id': creator, 'rec_id': user_list, 'content': text}):
            current_app.logger.info('发送站内信成功')
        else:
            current_app.logger.info('发送站内信失败')

    @classmethod
    def get_phone_all(cls, page_size, page_index):

        # 通过设备名称进行搜索
        name = request.args.get('name') or ''
        # 通过制造商进行搜索
        vendor = request.args.get('vendor') or ''
        # 通过系统进行搜索
        os = request.args.get('os') or ''
        # 通过分辨率进行搜索
        resolution = request.args.get('resolution') or ''
        # 通过借用人进行搜索
        borrower_id = request.args.get('borrower_id')
        # 通过持有人进行搜索
        creator_id = request.args.get('creator_id')
        # 通过 归属
        device_belong = request.args.get('device_belong') or ''
        # 通过 来源
        device_source = request.args.get('device_source') or ''
        # 通过 归属人
        # 获取所有 手机设备列表
        phones, count = cls.search_phone_all(name, vendor, os, resolution, borrower_id, device_belong,
                                             device_source, creator_id, page_size, page_index)
        # 获取所有用户的 基本信息
        users = {int(user.get('userid')): user
                 for user in user_trpc.requests(method='get', path='/user', query={'base_info': True})}
        # 获取所有借用关系列表
        phone_borrows = {phone_borrow.id: phone_borrow for phone_borrow in PhoneBorrow.query.all()}
        data = []
        for phone in phones:
            phone_borrow = phone_borrows.get(phone.get('id'))
            if g.userid == phone.get('borrow_id'):
                phone["move_status"] = 1
            else:
                phone["move_status"] = 0

            if PhoneBusiness.in_confirm_status(phone_borrow):
                phone["move_status"] = 2

            if PhoneBusiness.need_confirm_status(phone_borrow):
                phone["confirm_status"] = 0
            else:
                phone["confirm_status"] = 1

            try:
                borrower = users.get(phone.get('borrow_id')).get("nickname")
                creator = users.get(phone.get('creator_id')).get('nickname')

                phone['borrow_nickname'] = borrower
                phone['creator_nickname'] = creator
                # 有此条借用记录
                if phone_borrow:
                    user_list = [int(id) for id in phone_borrow.user_list.split(',') if id != '']
                    # 有需要确认的用户
                    if phone_borrow.confirm_userid != 0:
                        confirm_user_nickname = users.get(phone_borrow.confirm_userid).get('nickname')
                        phone['borrow_status'] = f'[{confirm_user_nickname}] 待接收'
                    # 用户借用列表
                    elif user_list:
                        user_list_temp = [users.get(userid).get('nickname') for userid in user_list]
                        phone['borrow_status'] = f'[{",".join(user_list_temp)}] 申请借用'
                        phone['move_status'] = 3 if phone["move_status"] == 1 else 0
                    # 无借用、确认、归还
                    else:
                        phone['borrow_status'] = f'[{borrower}] 持有'
                else:
                    phone['borrow_status'] = f'[{borrower}] 持有'
            except Exception as e:
                current_app.logger.error(e)
                current_app.logger.error(traceback.format_exc())
                phone['borrow_status'] = '未知'
                phone['borrow_nickname'] = '未知'

            data.append(phone)
        current_app.logger.info(data)
        return data, count

    @classmethod
    @transfer2json(
        '?id|!name|!asset_id|!vendor|!device_number|!os|!cpu|!core|!ram|!rom|!resolution|!buy_date|!region|!status|'
        '!borrow_id|!creator_id|!device_source|!device_belong'
    )
    def search_phone_json(cls, data):
        return data.all()

    @classmethod
    def search_phone_all(cls, name, vendor, os, resolution, borrower_id, device_belong, device_source, creator_id,
                         page_size, page_index):
        try:

            data_all = cls._query().filter(Phone.status == Phone.ACTIVE)
            if name != '':
                data_all = data_all.filter(Phone.name.like(f'%{name}%'))
            if vendor != '':
                data_all = data_all.filter(Phone.vendor.like(f'%{vendor}%'))
            if os != '':
                data_all = data_all.filter(Phone.os.like(f'%{os}%'))
            if resolution != '':
                data_all = data_all.filter(Phone.resolution.like(f'%{resolution}%'))
            if device_belong != '':
                data_all = data_all.filter(Phone.device_belong.like(f'%{device_belong}%'))
            if device_source != '':
                data_all = data_all.filter(Phone.device_source.like(f'%{device_source}%'))
            if borrower_id:
                data_all = data_all.filter(Phone.borrow_id == borrower_id)
            if creator_id:
                data_all = data_all.filter(Phone.creator_id == creator_id)

            count = data_all.count()
            data = cls.search_phone_json(
                data_all.order_by(desc(Phone.id)).limit(int(page_size)).offset(int(page_index - 1) * int(page_size)))
            return data, count
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())

    @classmethod
    def get_holder_json(cls):
        # 获取所有持有者的信息
        try:
            data_all = []
            temp = []
            phones = Phone.query.add_columns(Phone.borrow_id.label('borrow_id')).filter(
                Phone.status == Phone.ACTIVE).all()
            for phone in phones:
                if phone.borrow_id not in temp:
                    temp.append(phone.borrow_id)
                    user = cls.user_trpc.requests('get', '/user/{}'.format(phone.borrow_id))[0]
                    data = {
                        'nickname': user.get('nickname'),
                        'id': user.get('userid')
                    }
                    data_all.append(data)
            return data_all
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())

    @classmethod
    def can_move_status(cls, phone_id):
        # 判断此设备是否归属于当前用户
        phone = Phone.query.get(phone_id)
        if phone and phone.borrow_id == g.userid:
            return True
        else:
            return False

    @classmethod
    def need_confirm_status(cls, phone_borrow):
        # 判断此手机需要是否当前用户确认
        try:
            if phone_borrow is not None:
                if int(phone_borrow.confirm_userid) == g.userid:
                    return True
                else:
                    return False
            else:
                return False
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 101, str(e)

    @classmethod
    def in_confirm_status(cls, phone_borrow):
        # 判断此设备是否存在于确认流程中
        try:
            if phone_borrow is not None:
                if int(phone_borrow.confirm_userid) != 0:
                    return True
                return False
            else:
                return False
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 101, str(e)

    @classmethod
    def qyweixin_email(cls, user_ids, text):
        if not isinstance(user_ids, list):
            user_ids = [user_ids]
        notification.send_notification(user_ids, text, creator=0)
        return 0, 'success'

    @classmethod
    def send_need_confirm_msg(cls, current_phone, phone_current_holder, phone_new_holder):
        deadline = PhoneBusiness.deadline(current_phone)
        new_holder_msg_text = """[TCloud] {} ({})
您有一台设备需要确认接收:
设备 : {},
资产编号 : {},
原持有人 : {} (微信号: {})
现持有人 : {} (微信号: {})
请及时到系统中确认接收!""".format(phone_new_holder.nickname, phone_new_holder.wx_userid,
                       current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                       phone_current_holder.wx_userid, phone_new_holder.nickname,
                       phone_new_holder.wx_userid)
        # phone_current_holder 原持有人
        # phone_new_holder 确认人

        ret, msg = PhoneBusiness.qyweixin_email(phone_new_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_cancel_move_msg(cls, current_phone, phone_current_holder, phone_new_holder):
        deadline = PhoneBusiness.deadline(current_phone)
        new_holder_msg_text = """[TCloud] {} ({})
您有一台设备由于超过 3 天没有接收,已被系统退回:
设备 : {},
资产编号 : {},
现持有人 : {} (微信号: {})
""".format(phone_new_holder.nickname, phone_new_holder.wx_userid, current_phone.name, current_phone.asset_id,
           phone_new_holder.nickname, phone_new_holder.wx_userid)
        # phone_current_holder 原持有人
        # phone_new_holder 确认人

        ret, msg = PhoneBusiness.qyweixin_email(phone_current_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_need_move_msg(cls, current_phone, phone_current_holder):
        new_holder_msg_text = """[TCloud] {} ({})
您有一条借用请求需要处理:
设备 : {}
资产编号 : {}
请及时到系统中处理!
请通过 TCloud->资产->流转 进行转出。""".format(phone_current_holder.nickname, phone_current_holder.wx_userid,
                                   current_phone.name, current_phone.asset_id,
                                   phone_current_holder.wx_userid)

        # phone_current_holder 当前持有人

        ret, msg = PhoneBusiness.qyweixin_email(phone_current_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_create_msg_qywx(cls, current_phone, phone_holder):
        msg_text = """[TCloud] {} ({})
您拥有了一台新的设备:
设备 : {},
资产编号 : {},
持有人 : {} (微信号: {})""".format(phone_holder.nickname, phone_holder.wx_userid,
                             current_phone.name, current_phone.asset_id, phone_holder.nickname,
                             phone_holder.wx_userid, )

        ret, msg = PhoneBusiness.qyweixin_email(phone_holder.id, msg_text)
        return ret, msg

    @classmethod
    def send_delay_msg_qywx(cls, current_phone, phone_holder):
        deadline = PhoneBusiness.deadline(current_phone)
        msg_text = """[TCloud] {} ({})
您拥有的一台设备需要归还:
设备 : {},
资产编号 : {},
持有人 : {} (微信号: {})
到期时间: {}
续借 : 请到系统中点击 续借 进行续借
归还 : 请到系统中点击 退回 进行归还
过期 2 天后会根据超时时间扣除信用分!请及时归还!""".format(phone_holder.nickname, phone_holder.wx_userid,
                                     current_phone.name, current_phone.asset_id, phone_holder.nickname,
                                     phone_holder.wx_userid, deadline)

        return PhoneBusiness.qyweixin_email(phone_holder.id, msg_text)

    @classmethod
    def send_move_msg_qywx(cls, current_phone, phone_current_holder, phone_new_holder):
        if phone_new_holder.id == phone_current_holder.id:
            current_app.logger.info('[{}](资产编号:{}) 设备状态未发生状态变化'.format(current_phone.name, current_phone.asset_id))
            return
        current_holder_msg_text = """[TCloud] {} ({})
您的一台设备状态将要发生变化:
设备 : {},
资产编号 : {},
变化 : 持有人将 由 {} (微信号: {}) 变为 {} (微信号: {})
状态 : 等待接收人确认""".format(phone_current_holder.nickname, phone_current_holder.wx_userid,
                       current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                       phone_current_holder.wx_userid, phone_new_holder.nickname,
                       phone_new_holder.wx_userid)

        ret, msg = PhoneBusiness.qyweixin_email(phone_current_holder.id, current_holder_msg_text)

        deadline = PhoneBusiness.deadline(current_phone)
        new_holder_msg_text = """[TCloud] {} ({})
您将拥有一台新的设备:
设备 : {},
资产编号 : {},
原持有人 : {} (微信号: {})
现持有人 : {} (微信号: {})
可持有时间: {} 天
到期时间: {}
请及时到系统中确认接收!""".format(phone_new_holder.nickname, phone_new_holder.wx_userid,
                       current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                       phone_current_holder.wx_userid,
                       phone_new_holder.nickname, phone_new_holder.wx_userid, Phone.HOLD_DATE, deadline)
        # phone_current_holder 原持有人
        # phone_new_holder 新持有人

        ret, msg = PhoneBusiness.qyweixin_email(phone_new_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_move_confirm_msg_qywx(cls, current_phone, phone_current_holder, phone_new_holder):
        if phone_new_holder.id == phone_current_holder.id:
            current_app.logger.info('[{}](资产编号:{}) 设备状态未发生状态变化'.format(current_phone.name, current_phone.asset_id))
            return
        current_holder_msg_text = """[TCloud] {} ({})
您的一台设备状态发生了变化:
设备 : {},
资产编号 : {},
变化 : 持有人已 由 {} (微信号: {}) 变为 {} (微信号: {})
状态 : 已接收""".format(phone_current_holder.nickname, phone_current_holder.wx_userid,
                   current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                   phone_current_holder.wx_userid, phone_new_holder.nickname,
                   phone_new_holder.wx_userid)

        ret, msg = PhoneBusiness.qyweixin_email(phone_current_holder.id, current_holder_msg_text)

        deadline = PhoneBusiness.deadline(current_phone)
        new_holder_msg_text = """[TCloud] {} ({})
您拥有了一台新的设备:
设备 : {},
资产编号 : {},
原持有人 : {} (微信号: {})
现持有人 : {} (微信号: {})
可持有时间: {} 天
到期时间: {}
状态: 已接收!""".format(phone_new_holder.nickname, phone_new_holder.wx_userid,
                   current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                   phone_current_holder.wx_userid,
                   phone_new_holder.nickname, phone_new_holder.wx_userid, Phone.HOLD_DATE, deadline)
        # phone_current_holder 原持有人
        # phone_new_holder 新持有人

        ret, msg = PhoneBusiness.qyweixin_email(phone_new_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_return_msg_qywx(cls, current_phone, phone_current_holder, phone_new_holder):
        if phone_new_holder.id == phone_current_holder.id:
            current_app.logger.info('[{}](资产编号:{}) 设备状态未发生状态变化'.format(current_phone.name, current_phone.asset_id))
            return

        current_holder_msg_text = """[TCloud] {} ({})
您归还了一台设备:
设备 : {},
资产编号 : {},
变化 : 持有人将 由 {} (微信号: {}) 变为 {} (微信号: {})
状态 : 等待接收人确认""".format(phone_current_holder.nickname, phone_current_holder.wx_userid,
                       current_phone.name, current_phone.asset_id,
                       phone_current_holder.nickname,
                       phone_current_holder.wx_userid,
                       phone_new_holder.nickname, phone_new_holder.wx_userid)

        PhoneBusiness.qyweixin_email(phone_current_holder.id, current_holder_msg_text)

        new_holder_msg_text = """[TCloud] {} ({})
您收到别人归还的一台设备:
设备 : {},
资产编号 : {},
原持有人 : {} (微信号: {})
持有人 : {} (微信号: {})
状态 : 等待确认
请到系统中及时确认接收!""".format(phone_new_holder.nickname, phone_new_holder.wx_userid, current_phone.name,
                       current_phone.asset_id,
                       phone_current_holder.nickname, phone_current_holder.wx_userid,
                       phone_new_holder.nickname, phone_new_holder.wx_userid)

        ret, msg = PhoneBusiness.qyweixin_email(phone_new_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def send_return_confirm_msg_qywx(cls, current_phone, phone_current_holder, phone_new_holder):
        if phone_new_holder.id == phone_current_holder.id:
            current_app.logger.info('[{}](资产编号:{}) 设备状态未发生状态变化'.format(current_phone.name, current_phone.asset_id))
            return

        current_holder_msg_text = """[TCloud] {} ({})
您成功归还了一台设备:
设备 : {},
资产编号 : {},
变化 : 持有人已 由 {} (微信号: {}) 变为 {} (微信号: {})
状态 : 接收人已接收""".format(phone_current_holder.nickname, phone_current_holder.wx_userid,
                      current_phone.name, current_phone.asset_id, phone_current_holder.nickname,
                      phone_current_holder.wx_userid,
                      phone_new_holder.nickname, phone_new_holder.wx_userid)

        PhoneBusiness.qyweixin_email(phone_current_holder.id, current_holder_msg_text)

        new_holder_msg_text = """[TCloud] {} ({})
您已接收别人归还的一台设备:
设备 : {},
资产编号 : {},
原持有人 : {} (微信号: {})
持有人 : {} (微信号: {})
状态 : 您已接收!""".format(phone_new_holder.nickname, phone_new_holder.wx_userid, current_phone.name, current_phone.asset_id,
                     phone_current_holder.nickname, phone_current_holder.wx_userid,
                     phone_new_holder.nickname, phone_new_holder.wx_userid)

        ret, msg = PhoneBusiness.qyweixin_email(phone_new_holder.id, new_holder_msg_text)
        return ret, msg

    @classmethod
    def deadline(cls, current_phone):
        # 根据 phone 最后一条记录计算到期时间
        phone_recorder = PhoneRecord.query.filter(PhoneRecord.phone_id == current_phone.id).order_by(
            PhoneRecord.id.desc()).first()
        deadline = phone_recorder.creation_time + timedelta(days=Phone.HOLD_DATE)  # 到期时间
        return deadline

    @classmethod
    def create(cls, name, asset_id, vendor, device_number, os, cpu, core, ram, rom, resolution, buy_date, region,
               borrow_id, device_source, device_belong, creator_id):
        try:
            t = Phone(
                name=name,
                asset_id=asset_id,
                vendor=vendor,
                device_number=device_number,
                os=os,
                cpu=cpu,
                core=core,
                ram=ram,
                rom=rom,
                resolution=resolution,
                buy_date=buy_date,
                region=region,
                borrow_id=borrow_id or g.userid,
                creator_id=creator_id or g.userid,
                device_source=device_source,
                device_belong=device_belong,
            )
            db.session.add(t)
            db.session.flush()
            PhoneRecordBusiness.create(t, g.userid)
            db.session.commit()
            phone_holder = User.query.get(t.creator_id)

            # 发送企业微信
            PhoneBusiness.send_create_msg_qywx(t, phone_holder)

            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    # 发起流转
    @classmethod
    def move_to_user(cls, id, borrow_id):
        try:

            t = Phone.query.get(id)
            phone_new_holder = User.query.get(borrow_id)
            phone_current_holder = User.query.get(t.borrow_id)

            # 消除对应设备已有的申请借用用户列表, 将老用户 id 放入,等待接收
            PhoneBorrowBusiness.clear_borrow_user_list(id, phone_current_holder.id)

            # 将设备的借出标志置为 1,等待接受者确认
            PhoneBorrowBusiness.add_user_to_confirm(id, phone_new_holder.id)

            # 发送企业微信
            PhoneBusiness.send_move_msg_qywx(t, phone_current_holder, phone_new_holder)

            return 0, None

        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    # 确认流转
    @classmethod
    def move(cls, id, borrow_id):
        try:
            t = Phone.query.get(id)

            phone_new_holder = User.query.get(borrow_id)

            if not phone_new_holder:
                return 101, '要转移的用户不存在,请检查用户信息'

            t.borrow_id = borrow_id

            db.session.add(t)
            PhoneRecordBusiness.update(t, g.userid)
            db.session.commit()

            return 0, None
        except Exception as e:
            current_app.logger.error(e)
            return 102, str(e)

    # 退回设备
    @classmethod
    def return_to_admin(cls, id):
        try:
            # 此处返还给 创建人
            current_phone = Phone.query.get(id)

            admin_id = current_phone.creator_id

            phone_current_holder = User.query.get(current_phone.borrow_id)
            phone_new_holder = User.query.get(admin_id)

            PhoneRecordBusiness.update(current_phone, g.userid)

            # 发送企业微信
            PhoneBusiness.send_return_msg_qywx(current_phone, phone_current_holder, phone_new_holder)

            # 消除对应设备已有的申请借用用户列表, 将老用户 id 放入,等待接收
            PhoneBorrowBusiness.clear_borrow_user_list(id, phone_current_holder.id)

            # 增加 admin 到 确认名单
            PhoneBorrowBusiness.add_user_to_confirm(id, admin_id)

            return 0, None
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    # 超时 3 天未接收设备,将退回
    @classmethod
    def cancel_move_to(cls, id):
        try:
            # 直接清除 phone borrow 数据
            current_phone = Phone.query.get(id)

            phone_borrow = PhoneBorrowBusiness.get_borrow_by_phone_id(phone_id=id)

            admin_id = current_phone.creator_id

            phone_current_holder = User.query.get(phone_borrow.confirm_userid)

            phone_new_holder = User.query.get(admin_id)

            # 发送企业微信
            cls.send_cancel_move_msg(current_phone, phone_current_holder, phone_new_holder)

            ret, msg = PhoneBorrowBusiness.update(phone_borrow.id, phone_borrow.phone_id, 0, '')

            return ret, msg

        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    @classmethod
    def update(cls, id, name, asset_id, vendor, device_number, os, cpu, core, ram, rom, resolution, buy_date, region,
               borrow_id, device_source, device_belong, creator_id):
        try:
            t = Phone.query.get(id)

            t.name = name
            t.asset_id = asset_id
            t.vendor = vendor
            t.device_number = device_number
            t.os = os
            t.cpu = cpu
            t.core = core
            t.ram = ram
            t.rom = rom
            t.resolution = resolution
            t.buy_date = buy_date
            t.region = region
            t.borrow_id = borrow_id
            t.device_source = device_source
            t.device_belong = device_belong
            t.creator_id = creator_id
            db.session.add(t)
            PhoneRecordBusiness.update(t, g.userid)
            db.session.commit()

            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def delete(cls, id):
        try:
            t = Phone.query.get(id)
            if t is None:
                return 0
            t.status = Phone.DISABLE
            db.session.add(t)
            PhoneRecordBusiness.delete(t, g.userid)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            return 105, str(e)
Example #16
0
def record_statistics_route_crontab():
    public_trpc = Trpc('public')
    data = public_trpc.requests('get', '/public/route/statistics/crontab')
    return data
Example #17
0
class PhoneBorrowBusiness(object):
    user_trpc = Trpc('auth')

    @classmethod
    def _query(cls):
        return PhoneBorrow.query.add_columns(
            PhoneBorrow.id.label('id'),
            PhoneBorrow.phone_id.label('phone_id'),
            PhoneBorrow.user_list.label('user_list'),
            PhoneBorrow.confirm_userid.label('confirm_userid'),
            func.date_format(PhoneBorrow.creation_time, "%Y-%m-%d %H:%i:%s").label('creation_time'),
            func.date_format(PhoneBorrow.modified_time, "%Y-%m-%d %H:%i:%s").label('modified_time'),
        )

    @classmethod
    @transfer2json('?id|!phone_id|!user_list|!confirm_userid|!creation_time|!modified_time')
    def get_borrow_all(cls):
        phone_borrows = cls._query().all()
        return phone_borrows

    @classmethod
    def get_borrow_by_phone_id(cls, phone_id):
        phone_borrow = cls._query().filter(PhoneBorrow.phone_id == phone_id).first()
        return phone_borrow

    @classmethod
    def create(cls, phone_id, confirm_userid=0, user_list=''):
        try:
            phone_borrow = PhoneBorrow(
                phone_id=phone_id,
                user_list=user_list,
                confirm_userid=confirm_userid,
            )
            db.session.add(phone_borrow)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def update(cls, id, phone_id, confirm_userid, user_list):
        try:
            phone_borrow = PhoneBorrow.query.get(id)
            if not phone_borrow:
                cls.create(phone_id, confirm_userid, user_list)

            phone_borrow.user_list = user_list
            phone_borrow.confirm_userid = confirm_userid
            db.session.add(phone_borrow)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(e)
            return 102, str(e)

    @classmethod
    def clear_borrow_user_list(cls, phone_id, old_holder_id):
        # 清除 申请用户列表
        # 只剩 原持有者 ID
        try:
            old_holder_id = str(old_holder_id)
            phone_borrow = cls.get_borrow_by_phone_id(phone_id)
            if not phone_borrow:
                ret, msg = cls.create(phone_id, 0, old_holder_id)
            else:
                ret, msg = cls.update(phone_borrow.id, phone_borrow.phone_id, 0, old_holder_id)
            return ret, msg
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    @classmethod
    def add_user_to_confirm(cls, phone_id, user_id):
        # 添加 用户ID 到 当前设备的 接收确认列表
        try:
            phone_borrow = cls.get_borrow_by_phone_id(phone_id)
            if not phone_borrow:
                ret, msg = cls.create(phone_id, user_id)
            else:
                ret, msg = cls.update(phone_borrow.id, phone_borrow.phone_id, user_id, phone_borrow.user_list)
            return ret, msg
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    @classmethod
    def add_user_to_userlist(cls, phone_id, user_id):
        # 将 申请用户 ID 添加到申请列表
        try:
            phone_borrow = cls.get_borrow_by_phone_id(phone_id)
            if not phone_borrow:
                cls.create(phone_id)

            phone_borrow = cls.get_borrow_by_phone_id(phone_id)
            old_user_list = [id for id in phone_borrow.user_list.split(',')]
            user_id = str(user_id)
            if user_id not in old_user_list:
                old_user_list.append(user_id)
            else:
                return 103, "不能重复借用"
            new_user_list = ','.join(old_user_list)
            cls.update(phone_borrow.id, phone_id, 0, new_user_list)
            return 0, None
        except Exception as e:
            current_app.logger.error(e)
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    @classmethod
    @transfer2json(
        '?id|!nickname'
    )
    def get_user_list_by_phone_id(cls, phone_id):
        try:
            phone_borrow = cls.get_borrow_by_phone_id(phone_id)
            if not phone_borrow:
                return []
            user_list = [id for id in phone_borrow.user_list.split(',')]
            users = []
            for user_id in user_list:
                if len(user_id) > 0:
                    user = User.query.get(int(user_id))
                    if user:
                        users.append(user)
            return users
        except Exception as e:
            current_app.logger.error(str(e))
            current_app.logger.error(traceback.format_exc())
            return 102, str(e)

    @classmethod
    def send_borrow_msg_qywx(cls, current_phone, phone_holder, current_user):

        current_user_nickname = current_user.nickname
        current_user_wx_userid = current_user.wx_userid
        receiver_id = phone_holder.wx_userid
        msg_text = """[TCloud] {}({})
您收到一个设备借用请求:
借用的设备 : {},
资产编号 : {},
借用人 : {} (微信号: {}),
请通过企业微信沟通,如借出,请通过 TCloud->资产->流转 进行转出。""".format(phone_holder.nickname, phone_holder.wx_userid,
                                                 current_phone.name, current_phone.asset_id, current_user_nickname,
                                                 current_user_wx_userid)
        PhoneBusiness.qyweixin_email(phone_holder.id, msg_text)

    @classmethod
    def send_borrow_continue_msg_qywx(cls, current_phone, phone_holder, current_user):
        deadline = PhoneBusiness.deadline(current_phone)
        current_user_nickname = current_user.nickname
        current_user_wx_userid = current_user.wx_userid
        receiver_id = phone_holder.wx_userid
        msg_text = """[TCloud] {} ({})
您续借了一台设备:
借用的设备 : {},
资产编号 : {},
借用人 : {} (微信号: {})
可持有时间: {} 天
到期时间: {}""".format(phone_holder.nickname, phone_holder.wx_userid,
                   current_phone.name, current_phone.asset_id, current_user_nickname, current_user_wx_userid,
                   Phone.HOLD_DATE, deadline)
        PhoneBusiness.qyweixin_email(phone_holder.id, msg_text)

    @classmethod
    def borrow(cls, phone_id):
        # 发起借用
        try:
            ret, msg = 0, None
            current_phone = Phone.query.get(phone_id)
            if current_phone:
                current_user = User.query.get(g.userid)
                phone_holder = User.query.get(current_phone.borrow_id)
                if current_phone.borrow_id == g.userid:
                    ret, msg = PhoneBusiness.move(phone_id, phone_holder.id)
                    PhoneBorrowBusiness.send_borrow_continue_msg_qywx(current_phone, phone_holder, current_user)
                else:
                    ret, msg = PhoneBorrowBusiness.add_user_to_userlist(phone_id, g.userid)
                    if ret == 103:
                        return ret, msg
                    PhoneBorrowBusiness.send_borrow_msg_qywx(current_phone, phone_holder, current_user)
            else:
                return 101, '设备无效'
            return ret, msg
        except Exception as e:
            current_app.logger.error(traceback.format_exc())
            current_app.logger.error(e)
            return 101, e

    @classmethod
    def confirm_borrow(cls, phone_id):
        # 确认借用, admin 确认接收
        try:
            current_phone = Phone.query.get(phone_id)
            phone_borrow = cls.get_borrow_by_phone_id(phone_id)

            if int(phone_borrow.confirm_userid) != g.userid:
                return 403, '只有接收人可以确认'

            phone_current_holder = User.query.get(current_phone.borrow_id)
            phone_new_holder = User.query.get(phone_borrow.confirm_userid)

            ret, msg = PhoneBusiness.move(phone_id, int(phone_borrow.confirm_userid))

            admins = cls.user_trpc.requests('get', '/user/admin')
            current_app.logger.info('{} 确认接收设备'.format(int(phone_borrow.confirm_userid)))
            if (int(phone_borrow.confirm_userid) in admins or
                    int(phone_borrow.confirm_userid) == current_phone.creator_id):
                try:
                    PhoneBusiness.send_return_confirm_msg_qywx(current_phone, phone_current_holder, phone_new_holder)
                    reason = '成功归还了设备 {}({}) '.format(current_phone.name, current_phone.asset_id)
                    current_app.logger.info(reason)
                    user_old_id = int(phone_borrow.user_list)
                    ret, msg = CreditBusiness.add_sub_score(user_old_id, Credit.CREDIT_ADD_ONCE, reason)
                except Exception as e:
                    current_app.logger.error(e)
            else:
                PhoneBusiness.send_move_confirm_msg_qywx(current_phone, phone_current_holder, phone_new_holder)
            ret, msg = cls.update(phone_borrow.id, phone_borrow.phone_id, 0, '')

            return ret, msg
        except Exception as e:
            current_app.logger.error(str(e))
            current_app.logger.error(traceback.format_exc())
            return 102, e
Example #18
0
class CiJobBusiness(object):
    public_trpc = Trpc('public')

    @classmethod
    def _query(cls):
        return CiJob.query.add_columns(
            CiJob.id.label('id'),
            CiJob.number.label('number'),
            CiJob.url.label('url'),
            CiJob.ci_id.label('ci_id'),
            CiJob.start_name.label('start_name'),
            CiJob.status.label('status'),
            CiJob.report.label('report'),
            CiJob.run_date.label('run_date'),
            CiJob.run_time.label('run_time'),
            CiJob.job_count.label('job_count'),
            CiJob.job_accuracy.label('job_accuracy'),
        )

    @classmethod
    @transfer2json(
        '?id|!number|!url|!ci_id|!start_name|!status|!report|!run_date|!run_time|!job_count|!job_accuracy'
    )
    def query_all_json(cls):
        return cls._query().filter(CiJob.status == CiJob.ACTIVE).order_by(
            desc(CiJob.id)).all()

    @classmethod
    @transfer2json(
        '?id|!number|!url|!ci_id|!start_name|!status|!report|!run_date|!run_time|!job_count|!job_accuracy'
    )
    def query_number_all(cls, ciid):
        return cls._query().filter(CiJob.status == CiJob.ACTIVE,
                                   CiJob.ci_id == ciid).all()

    @classmethod
    @transfer2json(
        '?id|!number|!url|!ci_id|!start_name|!status|!report|!run_date|!run_time|!job_count|!job_accuracy'
    )
    def query_number_id(cls, number, ciid):
        return cls._query().filter(CiJob.status == CiJob.ACTIVE,
                                   CiJob.number == number,
                                   CiJob.ci_id == ciid).all()

    @classmethod
    @transfer2json(
        '?id|!number|!url|!ci_id|!start_name|!status|!report|!run_date|!run_time|!job_count|!job_accuracy'
    )
    def query_json_by_id(cls, id, page_size, page_index):

        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        start_name = request.args.get('start_name')
        return cls._query().filter(
            CiJob.ci_id == id, CiJob.status == CiJob.ACTIVE,
            CiJob.run_date.between(start_time, end_time),
            CiJob.start_name.like('%{}%'.format(start_name))).order_by(
                desc(CiJob.id)).limit(int(page_size)).offset(
                    int(page_index - 1) * int(page_size)).all()

    @classmethod
    def query_count(cls, id):
        start_time = request.args.get('start_time')
        end_time = request.args.get('end_time')
        start_name = request.args.get('start_name')
        return CiJob.query.filter(
            CiJob.ci_id == id, CiJob.status == CiJob.ACTIVE,
            CiJob.run_date.between(start_time, end_time),
            CiJob.start_name.like('%{}%'.format(start_name))).count()

    @classmethod
    def create(cls, number, url, ci_id, start_name, report, run_date, run_time,
               job_count, job_accuracy):
        try:
            cijob = CiJob(
                number=number,
                url=url,
                ci_id=ci_id,
                start_name=start_name,
                report=report,
                run_date=run_date,
                run_time=run_time,
                job_count=job_count,
                job_accuracy=job_accuracy,
            )
            db.session.add(cijob)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def update(cls, id, number, url, ci_id, start_name, report, run_date,
               run_time, job_count, job_accuracy):
        try:
            cijob = CiJob.query.get(id)
            cijob.number = number
            cijob.url = url
            cijob.ci_id = ci_id
            cijob.start_name = start_name
            cijob.report = report
            cijob.run_date = run_date
            cijob.run_time = run_time
            cijob.job_count = job_count
            cijob.job_accuracy = job_accuracy

            db.session.add(cijob)
            db.session.commit()
            return 0, None
        except Exception as e:
            current_app.logger.error(str(e))
            return 102, str(e)

    @classmethod
    def delete(cls, id):
        try:
            cijob = CiJob.query.get(id)
            if cijob is None:
                return 0
            cijob.status = CiJob.DISABLE
            db.session.add(cijob)
            db.session.commit()
            return 0
        except Exception as e:
            current_app.logger.error(str(e))
            return 105, str(e)

    @classmethod
    def gain_jenkins_server(cls):

        jenkins_config = cls.public_trpc.requests('get', '/public/config', {
            'module': 'jenkins',
            'module_type': 2
        })
        if not jenkins_config:
            return None
        run_dict = json.loads(jenkins_config)
        jenkins_server_url = run_dict['url']
        user_id = run_dict['user_id']
        api_token = run_dict['api_token']

        server = jenkins.Jenkins(jenkins_server_url,
                                 username=user_id,
                                 password=api_token)

        return server

    @classmethod
    def job_update_data(cls, ciid, ciname, job_data, cijob_number_list,
                        server):
        for i in range(0, len(job_data)):

            run_list = []
            queue_info = server.get_queue_info()
            if len(queue_info) > 0:
                for info_count in range(0, len(queue_info)):
                    if 'task' in queue_info[
                            info_count] and 'name' in queue_info[info_count][
                                'task']:
                        run_list.append(queue_info[info_count]['task']['name'])

            run_build_list = server.get_running_builds()
            for list_count in range(0, len(run_build_list)):
                if 'name' in run_build_list[list_count]:
                    run_list.append(run_build_list[list_count]['name'])

            if ciname in run_list:
                continue

            if job_data[i]['number'] and int(
                    job_data[i]['number']) not in cijob_number_list:
                build_data = server.get_build_info(ciname,
                                                   job_data[i]['number'])

                # 触发时间
                tss1 = build_data['timestamp'] / 1000
                tss1 = time.localtime(tss1)
                run_date = time.strftime("%Y-%m-%d %H:%M:%S", tss1)

                # 运行时长
                run_time = build_data['duration'] / 1000

                # 触发者
                name = 'timer'

                if (build_data and 'actions' in build_data
                        and build_data['actions']
                        and 'causes' in build_data['actions'][0]
                        and build_data['actions'][0]['causes']
                        and len(build_data['actions']) > 0
                        and len(build_data['actions'][0]['causes']) > 0):
                    if 'userName' in build_data['actions'][0]['causes'][0]:
                        name = build_data['actions'][0]['causes'][0][
                            'userName']
                    else:
                        start_name = build_data['actions'][0]['causes'][0][
                            'shortDescription']
                        start_name_list = start_name.split(' ')
                        if len(start_name_list) > 2:
                            name = start_name_list[2]
                report = ''

                job_count = 0
                job_accuracy = 0

                # 获取report
                logo_info = (server.get_build_console_output(
                    ciname, job_data[i]['number']))

                if '/' in logo_info and '$$$$$$' in logo_info:

                    logo_info_list = logo_info.split('/')

                    time_content = logo_info_list[-1][0:10]

                    logo_data = logo_info.split('$$$$$$')

                    if len(logo_data) == 3:
                        logger_info = ((logo_data[1]).strip().encode("utf-8"))
                        logger_info = str(logger_info, 'utf-8')
                        logger_info = logger_info.replace("'", '"')

                        if 'testsRun' in logger_info and 'html' not in logger_info:
                            data_dict = json.loads(logger_info)
                            job_true_count = int(data_dict['successes'])
                            job_count = int(data_dict['testsRun'])
                            if job_true_count != 0 and job_count != 0:
                                job_accuracy = round(
                                    job_true_count / (job_count * 1.0), 4)

                                if time_content.isdigit():
                                    # file = "http://ctsssource.oss-cn-shanghai.aliyuncs.com/api_report/"
                                    file = current_app.config[
                                        'CI_REPORT_FILE_ADRESS']
                                    time_array = time.localtime(
                                        int(time_content))
                                    report = file + time.strftime(
                                        "%Y-%m-%d", time_array
                                    ) + '/' + time_content + '.html'
                job_really_url = ''
                job_url = job_data[i]['url']
                job_url_list = job_url.split('job')
                if len(job_url_list) > 1:
                    ci_job_address = current_app.config['CI_JOB_ADDRESS']
                    # job_really_url = 'http://ci.automancloud.com/job' + job_url_list[1]
                    job_really_url = ci_job_address + job_url_list[1]
                cls.create(job_data[i]['number'], job_really_url, ciid, name,
                           report, run_date, run_time, job_count, job_accuracy)

    @classmethod
    def run(cls, project_id, run_list):

        run_dict, run_name_dict = CiJobBusiness.gain_run_dict(project_id)
        if len(run_dict) == 0 and len(run_dict) < len(run_list):
            return 102, [], 'empty'
        run_name_list = []
        for i in range(0, len(run_list)):
            run_name_list.append(run_dict[str(run_list[i])])
        if len(run_name_list) == 0:
            return 102, [], 'empty'

        server = CiJobBusiness.gain_jenkins_server()
        if not server:
            return 101, [], 'server 错误'
        # job_info = server.get_jobs()
        data = []
        run_build_list = server.get_running_builds()
        isexcute = False
        run_list = []
        for build_count in range(0, len(run_build_list)):
            if 'name' in run_build_list[build_count]:
                run_list.append(run_build_list[build_count]['name'])

        queue_info = server.get_queue_info()

        for info_count in range(0, len(queue_info)):
            if 'task' in queue_info[info_count] and 'name' in queue_info[
                    info_count]['task']:
                run_list.append(queue_info[info_count]['task']['name'])

        for i in range(0, len(run_name_list)):
            if run_name_list[i] in run_list:
                isexcute = True
                # 判断是否正在执行
            data_dict_singel = {}

            if isexcute:
                data_dict_singel['isexcuting'] = True
                data_dict_singel['job'] = run_name_list[i]
                data_id = int(
                    list(run_dict.keys())[list(run_dict.values()).index(
                        run_name_list[i])])
                data_dict_singel['id'] = data_id
                data_dict_singel['name'] = run_name_dict[str(data_id)]

                data.append(data_dict_singel)
                # 若未执行则执行
            else:
                server.build_job(run_name_list[i])
                data_dict_singel['isexcuting'] = False
                data_dict_singel['job'] = run_name_list[i]
                data_id = int(
                    list(run_dict.keys())[list(run_dict.values()).index(
                        run_name_list[i])])
                data_dict_singel['id'] = data_id
                data_dict_singel['name'] = run_name_dict[str(data_id)]
                data.append(data_dict_singel)

        return 0, data, 'ok'

    @classmethod
    def gain_report(cls, project_id, run_list):

        run_dict, run_name_dict = CiJobBusiness.gain_run_dict(project_id)
        if len(run_dict) == 0 and len(run_dict) < len(run_list):
            return 102, [], 'empty'
        run_name_list = []
        for i in range(0, len(run_list)):
            run_name_list.append(run_dict[str(run_list[i])])
        if len(run_name_list) == 0:
            return 102, [], 'empty'

        server = CiJobBusiness.gain_jenkins_server()
        if not server:
            return 101, [], 'server 错误'
        job_info = server.get_jobs()

        run_build_list = []
        run_list = []
        queue_info = server.get_queue_info()
        if len(queue_info) > 0:
            for i in range(0, len(queue_info)):
                if 'task' in queue_info[i] and 'name' in queue_info[i]['task']:
                    run_list.append(queue_info[i]['task']['name'])

        run_build_list = server.get_running_builds()
        for i in range(0, len(run_build_list)):
            if 'name' in run_build_list[i]:
                run_list.append(run_build_list[i]['name'])

        isexcute = False

        run_list = list(set(run_list))

        data = []
        for m in range(0, len(job_info)):
            for i in range(0, len(run_name_list)):

                if run_name_list[i] in run_list:
                    isexcute = True

                if job_info[m]['fullname'] == run_name_list[i]:
                    # 判断是否正在执行
                    data_dict = {}
                    if isexcute:
                        data_dict['isexcuting'] = True
                        data_dict['url'] = ''
                        data_dict['job'] = run_name_list[i]
                        data_id = int(
                            list(run_dict.keys())[list(
                                run_dict.values()).index(run_name_list[i])])
                        data_dict['id'] = data_id
                        data_dict['name'] = run_name_dict[str(data_id)]

                        data.append(data_dict)
                    # 若未执行则执行
                    else:
                        number = server.get_job_info(
                            job_info[m]['fullname'])['lastBuild']['number']
                        logo_info = (server.get_build_console_output(
                            job_info[m]['fullname'], number))
                        if '/' in logo_info and '$$$$$$' in logo_info:
                            logo_info_list = logo_info.split('/')
                            time_content = logo_info_list[-1][0:10]
                            logo_data = logo_info.split('$$$$$$')
                            if time_content.isdigit():
                                file = "http://ctsssource.oss-cn-shanghai.aliyuncs.com/api_report/"
                                time_array = time.localtime(int(time_content))
                                report = file + time.strftime(
                                    "%Y-%m-%d",
                                    time_array) + '/' + time_content + '.html'
                                data_dict['isexcuting'] = False
                                data_dict['url'] = report
                                data_dict['job'] = run_name_list[i]
                                data_id = int(
                                    list(run_dict.keys())[list(
                                        run_dict.values()).index(
                                            run_name_list[i])])
                                data_dict['id'] = data_id
                                data_dict['name'] = run_name_dict[str(data_id)]
                                data.append(data_dict)

                            else:
                                data_dict['isexcuting'] = False
                                data_dict['url'] = ''
                                data_dict['job'] = run_name_list[i]
                                data_id = int(
                                    list(run_dict.keys())[list(
                                        run_dict.values()).index(
                                            run_name_list[i])])
                                data_dict['id'] = data_id
                                data_dict['name'] = run_name_dict[str(data_id)]
                                data.append(data_dict)
                        else:
                            data_dict['isexcuting'] = False
                            data_dict['url'] = ''
                            data_dict['job'] = run_name_list[i]
                            data_id = int(
                                list(run_dict.keys())[list(
                                    run_dict.values()).index(
                                        run_name_list[i])])
                            data_dict['id'] = data_id
                            data_dict['name'] = run_name_dict[str(data_id)]
                            data.append(data_dict)

        return 0, data, 'ok'

    @classmethod
    def gain_run_dict(cls, project_id):

        run_name_list = []
        run_job_dict = {}
        run_name_dict = {}

        jenkins_config = Config.query.add_columns(
            Config.content.label('content')).filter(
                Config.module == 'jenkins', Config.module_type == 1).first()
        run_dict = json.loads(jenkins_config.content)
        if str(project_id) in run_dict.keys():
            project_list = run_dict[str(project_id)]
            for i in range(0, len(project_list)):
                run_name_list.append(project_list[i]['job'])
                project_dict = {
                    str(project_list[i]['id']): project_list[i]['job']
                }
                run_job_dict = run_job_dict.copy()
                run_job_dict.update(project_dict)

                project_name_dict = {
                    str(project_list[i]['id']): project_list[i]['name']
                }
                run_name_dict = run_name_dict.copy()
                run_name_dict.update(project_name_dict)
        return run_job_dict, run_name_dict

    @classmethod
    def jobs_config_data(cls):

        jenkins_config = cls.public_trpc.requests('get', '/public/config', {
            'module': 'jenkins',
            'module_type': 3
        })

        run_dict = json.loads(jenkins_config)

        jobs_list = run_dict['job']

        return jobs_list

    @classmethod
    def update_jenkins_data(cls):

        cidata_list = CiDataBusiness.query_all_json()
        cidata_name_list = []
        for i in range(0, len(cidata_list)):
            cidata_name_list.append("{}".format(cidata_list[i]['name']))

        server = CiJobBusiness.gain_jenkins_server()
        if not server:
            return 101, [], 'server 错误'

        job_info = cls.jobs_config_data()

        # ci数据更新
        for m in range(0, len(job_info)):

            if job_info[m] and server.job_exists(job_info[m]):
                job_name = job_info[m]
                job_true_count = 0
                job_count = 0
                builds = server.get_job_info(job_name,
                                             depth=0,
                                             fetch_all_builds=False)['builds']

                for j in range(0, len(builds)):
                    # 一共有多少个case
                    logo_info = (server.get_build_console_output(
                        job_name, builds[j]['number']))

                    if '$$$$$$' in logo_info:
                        logo_data = logo_info.split('$$$$$$')
                        if len(logo_data) == 3:
                            logger_info = ((
                                logo_data[1]).strip().encode("utf-8"))
                            logger_info = str(logger_info, 'utf-8')
                            logger_info = logger_info.replace("'", '"')
                            if 'testsRun' in logger_info and 'html' not in logger_info:
                                data_dict = json.loads(logger_info)
                                job_true_count = job_true_count + data_dict[
                                    'successes']
                                job_count = job_count + data_dict['testsRun']
                # 增加正确率
                if job_count == 0:
                    accuracy = 0
                else:
                    accuracy = round(job_true_count / (job_count * 1.0), 4)
                # 下一次执行的number
                next_build_number = server.get_job_info(
                    job_name, depth=0,
                    fetch_all_builds=False)['nextBuildNumber']

                # job描述
                job_config = server.get_job_config(job_name)
                root = job_config.split('description')
                description = 'jenkins'
                if len(root) > 1:
                    description = root[1].strip('>').strip('</')

                if job_info[m] not in cidata_name_list:

                    code, ciid, ciname = CiDataBusiness.create(
                        job_name, job_count, next_build_number, accuracy,
                        description)

                    cijob_number_list = []
                    cijob_all_data = CiJobBusiness.query_number_all(int(ciid))

                    for j in range(0, len(cijob_all_data)):
                        cijob_number_list.append(
                            int(cijob_all_data[j]['number']))

                    if code == 0:
                        builds = sorted(builds,
                                        key=lambda e: e.__getitem__('number'))
                        ciname = "{}".format(ciname)
                        CiJobBusiness.job_update_data(ciid, ciname, builds,
                                                      cijob_number_list,
                                                      server)
                if job_info[m] in cidata_name_list:
                    ciid = 1
                    for id_count in range(0, len(cidata_list)):
                        if job_info[m] == "{}".format(
                                cidata_list[id_count]['name']):
                            ciid = cidata_list[id_count]['id']
                    CiDataBusiness.update(ciid, job_name, job_count,
                                          next_build_number, accuracy,
                                          description)

        for mn in range(0, len(cidata_list)):
            ciname = "{}".format(cidata_list[mn]['name'])
            if ciname in job_info and server.job_exists(ciname):

                cijob_number_list_info = []

                cijob_all_data = CiJobBusiness.query_number_all(
                    int(cidata_list[mn]['id']))

                for j in range(0, len(cijob_all_data)):
                    cijob_number_list_info.append(
                        int(cijob_all_data[j]['number']))

                builds_info = server.get_job_info(ciname)['builds']

                builds_info = sorted(builds_info,
                                     key=lambda e: e.__getitem__('number'))

                builds_info_really = []

                for i in range(0, len(builds_info)):
                    if builds_info[i]['number'] not in cijob_number_list_info:
                        builds_info_really.append(builds_info[i])

                if len(builds_info_really) == 0:
                    continue

                CiJobBusiness.job_update_data(int(cidata_list[mn]['id']),
                                              ciname, builds_info_really,
                                              cijob_number_list_info, server)