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())
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'),
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)
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)
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']
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'))
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')
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
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
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}
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
def __init__(self): self.public_trpc = Trpc('public') self.message_trpc = Trpc('message')
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, [], '删除属性失败'
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)
def record_statistics_route_crontab(): public_trpc = Trpc('public') data = public_trpc.requests('get', '/public/route/statistics/crontab') return data
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
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)