Files
effekt-interface/app/api/dao/caseDao.py
2026-05-11 14:29:16 +08:00

248 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# encoding: UTF-8
from sqlalchemy import func
from ..model.caseModel import CaseReview, CaseSnapshot, Module, TestCase
from logger import logger
class CaseDao(object):
"""用例域通用 DAO复用模块、用例、快照、评审的基础操作。"""
@staticmethod
def create(session, model_cls, add_info):
"""创建记录并提交事务。"""
obj = model_cls(**add_info)
session.add(obj)
err = session.done(close=False)
if err:
logger.warning(f'{model_cls.__name__}新增失败!{err}')
return 0, f'新增失败!{err}'
return obj.id, ''
@staticmethod
def update_by_id(session, model_cls, obj_id, update_info, soft_delete=True):
filters = [model_cls.id == int(obj_id)]
if soft_delete and hasattr(model_cls, 'is_delete'):
filters.append(model_cls.is_delete == 0)
update_res = session.query(model_cls).filter(*filters).update(update_info)
err = session.done(close=False)
if err:
logger.error(f'{model_cls.__name__}更新失败id: {obj_id}, err: {err}')
return 0, f'更新失败!{err}'
if not update_res:
return 0, '未查询到对应记录!'
return int(obj_id), ''
@staticmethod
def get_by_id(session, model_cls, obj_id, soft_delete=True):
filters = [model_cls.id == int(obj_id)]
if soft_delete and hasattr(model_cls, 'is_delete'):
filters.append(model_cls.is_delete == 0)
return session.query(model_cls).filter(*filters).first()
@staticmethod
def list_by_filters(session, model_cls, filter_list, page=1, limit=20, order_column=None):
query = session.query(model_cls).filter(*filter_list)
if hasattr(model_cls, 'is_delete'):
query = query.filter(model_cls.is_delete == 0)
total = query.count()
if order_column is not None:
query = query.order_by(order_column.desc())
rets = query.offset((int(page) - 1) * int(limit)).limit(int(limit)).all()
return rets, total
@staticmethod
def delete_by_id(session, model_cls, obj_id):
return CaseDao.update_by_id(session, model_cls, obj_id, {'is_delete': 1})
@staticmethod
def next_case_key(session, project_id, module_id=None, product_id=None):
from ..model.productModel import Product
from ..model.projectModel import Project
from ..model.caseModel import Module
product_abbr = ''
if product_id:
product = session.query(Product).filter(Product.id == int(product_id), Product.is_delete == 0).first()
if product and product.name:
product_abbr = CaseDao._generate_abbreviation(product.name)
project_abbr = ''
project = session.query(Project).filter(Project.id == int(project_id), Project.is_delete == 0).first()
if project and project.name:
project_abbr = CaseDao._generate_abbreviation(project.name)
module_abbr = ''
if module_id:
module = session.query(Module).filter(Module.id == int(module_id), Module.is_delete == 0).first()
if module and module.name:
module_abbr = CaseDao._generate_abbreviation(module.name)
parts = ['TC']
if product_abbr:
parts.append(product_abbr)
if project_abbr:
parts.append(project_abbr)
if module_abbr:
parts.append(module_abbr)
prefix = '-'.join(parts)
count_num = session.query(func.count(TestCase.id)).filter(
TestCase.project_id == int(project_id),
TestCase.is_delete == 0,
TestCase.case_key.like(f'{prefix}-%')
).scalar() or 0
return '{}-{:03d}'.format(prefix, count_num + 1)
@staticmethod
def _generate_abbreviation(name):
import re
chinese_pattern = re.compile(r'[\u4e00-\u9fff]+')
english_pattern = re.compile(r'[a-zA-Z]+')
chinese_chars = chinese_pattern.findall(name)
if chinese_chars:
full_chinese = ''.join(chinese_chars)
abbr = ''.join([CaseDao._get_pinyin_first_char(c) for c in full_chinese[:4]])
abbr = abbr.lower()
if len(abbr) < 2:
abbr = abbr.ljust(2, 'n')
return abbr
english_words = english_pattern.findall(name)
if english_words:
abbr = english_words[0].lower()[:4]
if len(abbr) < 2:
abbr = abbr.ljust(2, 'x')
return abbr
abbr = name.lower()[:4]
if len(abbr) < 2:
abbr = abbr.ljust(2, 'x')
return abbr
@staticmethod
def _get_pinyin_first_char(char):
pinyin_map = {
'': 'Z', '': 'H', '': 'Y', '': 'Y',
'': 'B', '': 'G', '': 'G', '': 'Z', '': 'T',
'': 'C', '': 'S', '': 'Y', '': 'L',
'': 'C', '': 'P', '': 'X', '': 'M',
'': 'M', '': 'K', '': 'G', '': 'L',
'': 'X', '': 'T', '': 'G', '': 'N',
'': 'Y', '': 'M', '': 'C', '': 'X',
'': 'T', '': 'J', '': 'B', '': 'J',
'': 'S', '': 'C', '': 'D', '': 'R',
'': 'D', '': 'C', '': 'P', '': 'L',
'': 'S', '': 'Z', '': 'P', '': 'Z',
'': 'Q', '': 'X', '': 'J', '': 'S',
'': 'Y', '': 'H', '': 'Z', '': 'Z',
'': 'J', '': 'H', '': 'Z', '': 'X',
'': 'B', '': 'G', '': 'T', '': 'J',
'': 'S', '': 'Y', '': 'Y', '': 'B',
'': 'Y', '': 'M', '': 'H', '': 'G',
'': 'J', '': 'C', '': 'J', '': 'K',
'': 'A', '': 'Q', '': 'R', '': 'Z',
'': 'J', '': 'K', '': 'Y', '': 'H',
'': 'X', '': 'N', '': 'S', '': 'W',
'': 'K', '': 'F', '': 'C', '': 'Y',
'': 'W', '': 'S', '': 'J', '': 'Y',
'': 'F', '': 'B', '': 'Z', '': 'G',
'': 'R', '': 'G', '': 'S', '': 'Y',
'': 'X', '': 'Z', '': 'R', '': 'G',
'': 'F', '': 'J', '': 'T', '': 'K',
'': 'J', '': 'W', '': 'L', '': 'X',
'': 'X', '': 'R', '': 'J', '': 'X',
'': 'T', '': 'J', '': 'J', '': 'F',
'': 'A', '': 'F', '': 'W', '': 'Z',
'': 'C', '': 'P', '': 'X', '': 'Z',
'': 'X', '': 'X', '': 'S', '': 'S',
'': 'C', '': 'Y', '': 'Y', '': 'G',
'': 'L', '': 'C', '': 'W', '': 'R',
'': 'L', '': 'Z', '': 'Y', '': 'X',
'': 'Z', '': 'F', '': 'L', '': 'H',
'': 'G', '': 'Z', '': 'L', '': 'A',
'': 'Q', '': 'H', '': 'J', '': 'Z',
'': 'N', '': 'M', '': 'K', '': 'Y',
'': 'M', '': 'C', '': 'K', '': 'B',
'': 'D', '': 'A', '': 'N', '': 'L',
'': 'J', '': 'T', '': 'B', '': 'C',
'': 'D', '': 'D', '': 'H', '': 'S',
'': 'S', '': 'G', '': 'L', '': 'P',
'': 'X', '': 'F', '': 'Y', '': 'D',
'': 'R', '': 'D', '': 'C', '': 'D',
'': 'Y', '': 'D', '': 'C', '': 'S',
'': 'C', '': 'F', '': 'Z', '': 'N',
'': 'T', '': 'J', '': 'Q', '': 'B',
'': 'C', '': 'Q', '': 'X', '': 'Q',
'': 'R', '': 'T', '': 'J', '': 'S',
'': 'H', '': 'P', '': 'Z', '': 'J',
'': 'J', '': 'F', '': 'H', '': 'X',
'': 'G', '': 'C', '': 'K', '': 'X',
'': 'Q', '': 'L', '': 'B', '': 'T',
'': 'J', '': 'T', '': 'B', '': 'B',
'': 'G', '': 'R', '': 'Z', '': 'B',
'': 'Z', '': 'M', '': 'S', '': 'M',
'': 'C', '': 'B', '': 'H', '': 'L',
'': 'X', '': 'Z', '': 'T', '': 'Y',
'': 'X', '': 'J', '': 'B', '': 'Q',
'': 'G', '': 'J', '': 'C', '': 'M',
'': 'S', '': 'F', '': 'J', '': 'L',
'': 'J', '': 'S', '': 'J', '': 'R',
'': 'Q', '': 'S', '': 'L', '': 'J',
'': 'E', '': 'J', '': 'G', '': 'S',
'': 'J', '': 'K', '': 'F', '': 'W',
'': 'Q', '线': 'X', '': 'C', '': 'J',
'': 'D', '': 'S', '': 'D', '': 'X',
'': 'L', '': 'X', '': 'N', '': 'W',
'': 'D', '': 'K', '': 'K', '': 'A',
'': 'Q', '': 'J', '': 'R', '': 'K',
'': 'Z', '': 'S', '': 'J', '': 'G',
'': 'X', '': 'X', '': 'B', '': 'X',
'': 'F', '': 'Y', '': 'H', '': 'Z',
'': 'G', '': 'G', '': 'Z', '': 'Y',
'': 'Z', '': 'J', '': 'C', '': 'J',
'': 'K', '': 'T', '': 'S', '': 'C',
'': 'S', '': 'Y', '': 'Z', '': 'Q',
'': 'R', '': 'H', '': 'G', '': 'Y',
'': 'S', '': 'P', '': 'X', '': 'Z',
'': 'D', '': 'Z', '': 'C', '': 'B',
'': 'Z', '': 'F', '': 'K', '': 'T',
'': 'S', '': 'J', '': 'Y', '': 'P',
'': 'D', '': 'L', '': 'Z', '': 'C',
'': 'G', '': 'G', '': 'Y', '': 'S',
'': 'J', '': 'M', '': 'Y', '': 'D'
}
return pinyin_map.get(char, 'N')
@staticmethod
def next_snapshot_version(session, case_id):
"""生成用例快照版本号。"""
max_version = session.query(func.max(CaseSnapshot.version)).filter(CaseSnapshot.case_id == int(case_id)).scalar() or 0
return int(max_version) + 1
@staticmethod
def module_model():
return Module
@staticmethod
def case_model():
return TestCase
@staticmethod
def snapshot_model():
return CaseSnapshot
@staticmethod
def review_model():
return CaseReview
@staticmethod
def get_module_name_map(session, module_ids):
if not module_ids:
return {}
module_items = session.query(Module).filter(Module.id.in_(module_ids), Module.is_delete == 0).all()
return {module.id: module.name for module in module_items}