大表功能完成

This commit is contained in:
2025-05-10 19:21:24 +08:00
parent 9a716bb730
commit 67c2cfad10
15 changed files with 2916 additions and 42 deletions

View File

@@ -7,11 +7,14 @@ from ninja.errors import HttpError
from utils.chen_pagination import MyPagination from utils.chen_pagination import MyPagination
from django.db import transaction from django.db import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.db.models.functions import Replace
from django.db.models import Q, F, Value
from typing import List from typing import List
from utils.chen_response import ChenResponse from utils.chen_response import ChenResponse
from utils.chen_crud import multi_delete_case from utils.chen_crud import multi_delete_case
from apps.project.models import Design, Dut, Round, TestDemand, Case, CaseStep, Project, Problem from apps.project.models import Design, Dut, Round, TestDemand, Case, CaseStep, Project, Problem
from apps.project.schemas.case import DeleteSchema, CaseModelOutSchema, CaseFilterSchema, CaseTreeReturnSchema, \ from apps.project.schemas.case import DeleteSchema, CaseModelOutSchema, CaseFilterSchema, \
CaseTreeReturnSchema, ReplaceCaseSchema, PersonReplaceSchema, ExetimeReplaceSchema, \
CaseTreeInputSchema, CaseCreateOutSchema, CaseCreateInputSchema, DemandNodeSchema CaseTreeInputSchema, CaseCreateOutSchema, CaseCreateInputSchema, DemandNodeSchema
from utils.util import get_testType from utils.util import get_testType
from utils.codes import HTTP_INDEX_ERROR, HTTP_EXISTS_CASES from utils.codes import HTTP_INDEX_ERROR, HTTP_EXISTS_CASES
@@ -35,15 +38,23 @@ class CaseController(ControllerBase):
qs = Case.objects.filter(id=case_id) # type:ignore qs = Case.objects.filter(id=case_id) # type:ignore
else: else:
conditionNoneToBlank(data) conditionNoneToBlank(data)
query_params = {
'project__id': data.project_id,
'ident__icontains': data.ident,
'name__icontains': data.name,
'designPerson__icontains': data.designPerson,
'testPerson__icontains': data.testPerson,
'monitorPerson__icontains': data.monitorPerson,
'summarize__icontains': data.summarize
}
# 如果没有多个key则是“那个汇总界面”
if data.dut_id and data.design_id and data.test_id:
test_key = "".join([data.round_id, '-', data.dut_id, '-', data.design_id, '-', data.test_id]) test_key = "".join([data.round_id, '-', data.dut_id, '-', data.design_id, '-', data.test_id])
qs = Case.objects.filter(project__id=data.project_id, test__key=test_key, # type:ignore query_params['test__key'] = test_key
ident__icontains=data.ident, else:
name__icontains=data.name, # 汇总界面只查round
designPerson__icontains=data.designPerson, query_params['round__key'] = data.round_id
testPerson__icontains=data.testPerson, qs = Case.objects.filter(**query_params).order_by("key")
monitorPerson__icontains=data.monitorPerson,
summarize__icontains=data.summarize,
).order_by("key")
# 由于有嵌套query_set存在把每个用例的schema加上一个字段 # 由于有嵌套query_set存在把每个用例的schema加上一个字段
query_list = [] query_list = []
for query_single in qs: for query_single in qs:
@@ -54,6 +65,14 @@ class CaseController(ControllerBase):
related_problem: Problem = query_single.caseField.first() related_problem: Problem = query_single.caseField.first()
if query_single.caseField.all(): if query_single.caseField.all():
setattr(query_single, 'problem', related_problem) setattr(query_single, 'problem', related_problem)
# 2025年5月10日在test字段加上testContent
test_obj = query_single.test
sub_list = []
for step_obj in test_obj.testQField.all():
setattr(step_obj, "subStep", step_obj.testStepField.all().values())
sub_list.append(step_obj)
setattr(test_obj, "testContent", sub_list)
setattr(query_single, 'test', test_obj)
query_list.append(query_single) query_list.append(query_single)
return query_list return query_list
@@ -69,6 +88,17 @@ class CaseController(ControllerBase):
return case return case
raise HttpError(500, "您获取的数据不存在") raise HttpError(500, "您获取的数据不存在")
@route.get("/getCaseOneById", response=CaseModelOutSchemaWithoutProblem, url_name='case-one-by-id')
@transaction.atomic
def get_case_by_id(self, id: int):
"""用于在用例树状页面获取promblem信息这里根据key获取信息"""
case = Case.objects.filter(id=id).first()
if case:
setattr(case, "testStep", case.step.all().values())
setattr(case, 'testType', get_testType(case.test.testType, dict_code='testType'))
return case
raise HttpError(500, "您获取的数据不存在")
# 处理树状数据 # 处理树状数据
@route.get("/getCaseInfo", response=List[CaseTreeReturnSchema], url_name="case-info") @route.get("/getCaseInfo", response=List[CaseTreeReturnSchema], url_name="case-info")
@transaction.atomic @transaction.atomic
@@ -108,7 +138,8 @@ class CaseController(ControllerBase):
# 直接把测试项的标识给前端处理显示 # 直接把测试项的标识给前端处理显示
asert_dict['ident'] = test_instance.ident asert_dict['ident'] = test_instance.ident
# ~~~~~~~~~end~~~~~~~~~ # ~~~~~~~~~end~~~~~~~~~
asert_dict.update({'key': key_string, 'round': round_instance, 'dut': dut_instance, 'design': design_instance, asert_dict.update(
{'key': key_string, 'round': round_instance, 'dut': dut_instance, 'design': design_instance,
"test": test_instance, 'title': payload.name}) "test": test_instance, 'title': payload.name})
asert_dict.pop("round_key") asert_dict.pop("round_key")
asert_dict.pop("dut_key") asert_dict.pop("dut_key")
@@ -144,7 +175,8 @@ class CaseController(ControllerBase):
content_single.delete() content_single.delete()
data_list = [] data_list = []
for item in value: for item in value:
if item['operation'] or item['expect'] or item['result'] or item['passed'] or item['status']: if item['operation'] or item['expect'] or item['result'] or item['passed'] or item[
'status']:
item["case"] = case_qs item["case"] = case_qs
data_list.append(CaseStep(**item)) data_list.append(CaseStep(**item))
CaseStep.objects.bulk_create(data_list) # type:ignore CaseStep.objects.bulk_create(data_list) # type:ignore
@@ -186,7 +218,8 @@ class CaseController(ControllerBase):
# 先查询当前测试项下面有无case # 先查询当前测试项下面有无case
case_exists = demand.tcField.exists() case_exists = demand.tcField.exists()
if case_exists: if case_exists:
return ChenResponse(status=500, code=HTTP_EXISTS_CASES, message='测试项下面有用例,请删除后生成') return ChenResponse(status=500, code=HTTP_EXISTS_CASES,
message='测试项下面有用例,请删除后生成')
# 查询所有测试子项 # 查询所有测试子项
sub_items = demand.testQField.all() sub_items = demand.testQField.all()
# 每一个子项都创建一个用例先声明一个列表后面可以bulk_create # 每一个子项都创建一个用例先声明一个列表后面可以bulk_create
@@ -224,7 +257,8 @@ class CaseController(ControllerBase):
CaseStep.objects.create(**case_step_dict) # type:ignore CaseStep.objects.create(**case_step_dict) # type:ignore
index += 1 index += 1
# 这里返回一个demand的key用于前端刷新树状图 # 这里返回一个demand的key用于前端刷新树状图
return ChenResponse(data={'key': demand_node.key}, status=200, code=200, message='测试项自动生成用例成功') return ChenResponse(data={'key': demand_node.key}, status=200, code=200,
message='测试项自动生成用例成功')
# 测试用例复制/移动到测试项上 # 测试用例复制/移动到测试项上
@route.get("/case/copy_or_move_to_demand", url_name='case-copy-move-demand') @route.get("/case/copy_or_move_to_demand", url_name='case-copy-move-demand')
@@ -240,6 +274,56 @@ class CaseController(ControllerBase):
# 测试用例复制/移动到用例 # 测试用例复制/移动到用例
@route.get("/case/copy_or_move_by_case", url_name='case-copy-move-case') @route.get("/case/copy_or_move_by_case", url_name='case-copy-move-case')
@transaction.atomic @transaction.atomic
def copy_move_case_by_case(self, project_id: int, drag_key: str, drop_key: str, move: bool, position: int): def copy_move_case_by_case(self, project_id: int, drag_key: str, drop_key: str, move: bool,
position: int):
case_to_case_copy_or_move(project_id, drag_key, drop_key, move, position) case_to_case_copy_or_move(project_id, drag_key, drop_key, move, position)
return ChenResponse(data={'old': {'key': drag_key}, 'new': {'key': drop_key}}) return ChenResponse(data={'old': {'key': drag_key}, 'new': {'key': drop_key}})
# 用例-替换接口
@route.post("/case/replace/", url_name='case-replace')
@transaction.atomic
def replace_case_step_content(self, payload: ReplaceCaseSchema):
# 1.首先查询项目
project_obj: Project = get_object_or_404(Project, id=payload.project_id)
# 2.查询[所有轮次]的selectRows的id
case_qs = project_obj.pcField.filter(id__in=payload.selectRows, round__key=payload.round_key)
# 3.批量替换里面文本(解构不影响老数组)
selectColumn = [x for x in payload.selectColumn if x != 'testStep']
replace_kwargs = {
field_name: Replace(F(field_name), Value(payload.originText), Value(payload.replaceText))
for field_name in selectColumn
}
# 4.单独处理testContentStep的操作、预期-查询所有
# 4.1.获取所有关联的TestDemandContentStep
step_count = 0
if 'testStep' in payload.selectColumn:
caseStep_qs = CaseStep.objects.filter(case__in=case_qs)
# 批量更新 operation 和 expect
step_count = caseStep_qs.update(
operation=Replace(F('operation'), Value(payload.originText), Value(payload.replaceText)),
expect=Replace(F('expect'), Value(payload.originText), Value(payload.replaceText))
)
# 5.提交更新
replace_count = case_qs.update(**replace_kwargs)
return {'count': replace_count + step_count}
# 批量替换设计人员、执行人员、审核人员
@route.post("/case/personReplace/", url_name='case-person-replace')
@transaction.atomic
def bulk_replace_person(self, payload: PersonReplaceSchema):
# 替换设计人员
case_qs = Case.objects.filter(id__in=payload.selectRows)
if payload.designPerson != '不替换' and payload.designPerson != '':
case_qs.update(designPerson=payload.designPerson)
if payload.testPerson != '不替换' and payload.testPerson != '':
case_qs.update(testPerson=payload.testPerson)
if payload.monitorPerson != '不替换' and payload.monitorPerson != '':
case_qs.update(monitorPerson=payload.monitorPerson)
# 批量替换事件
@route.post("/case/timeReplace/", url_name='case-time-replace')
@transaction.atomic
def bulk_replace_time(self, payload: ExetimeReplaceSchema):
# 替换设计人员
case_qs = Case.objects.filter(id__in=payload.selectRows)
case_qs.update(exe_time=payload.exetime)

View File

@@ -6,30 +6,44 @@ from ninja.pagination import paginate
from ninja.errors import HttpError from ninja.errors import HttpError
from utils.chen_pagination import MyPagination from utils.chen_pagination import MyPagination
from django.db import transaction from django.db import transaction
from django.db.models import F, Value
from django.db.models.functions import Replace
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from typing import List from typing import List
from utils.chen_response import ChenResponse from utils.chen_response import ChenResponse
from utils.chen_crud import multi_delete_design from utils.chen_crud import multi_delete_design
from utils.codes import HTTP_INDEX_ERROR from utils.codes import HTTP_INDEX_ERROR
from apps.project.models import Design, Dut, Round, Project from apps.project.models import Design, Dut, Round, Project
from apps.project.schemas.design import DeleteSchema, DesignFilterSchema, DesignModelOutSchema, DesignTreeReturnSchema, \ from apps.project.schemas.design import DeleteSchema, DesignFilterSchema, DesignModelOutSchema, \
DesignTreeInputSchema, DesignCreateOutSchema, DesignCreateInputSchema, MultiDesignCreateInputSchema DesignTreeReturnSchema, \
DesignTreeInputSchema, DesignCreateOutSchema, DesignCreateInputSchema, MultiDesignCreateInputSchema, \
ReplaceDesignContentSchema
from apps.project.tools.delete_change_key import design_delete_sub_node_key from apps.project.tools.delete_change_key import design_delete_sub_node_key
from utils.smallTools.interfaceTools import conditionNoneToBlank from utils.smallTools.interfaceTools import conditionNoneToBlank
@api_controller("/project", auth=JWTAuth(), permissions=[IsAuthenticated], tags=['设计需求数据']) @api_controller("/project", auth=JWTAuth(), permissions=[IsAuthenticated], tags=['设计需求数据'])
class DesignController(ControllerBase): class DesignController(ControllerBase):
@route.get("/getDesignDemandList", response=List[DesignModelOutSchema], exclude_none=True, url_name="design-list") @route.get("/getDesignDemandList", response=List[DesignModelOutSchema], exclude_none=True,
url_name="design-list")
@transaction.atomic @transaction.atomic
@paginate(MyPagination) @paginate(MyPagination)
def get_design_list(self, datafilter: DesignFilterSchema = Query(...)): def get_design_list(self, datafilter: DesignFilterSchema = Query(...)):
conditionNoneToBlank(datafilter) conditionNoneToBlank(datafilter)
dut_key = "".join([datafilter.round_id, '-', datafilter.dut_id]) query_params = {
qs = Design.objects.filter(project__id=datafilter.project_id, dut__key=dut_key, 'project__id': datafilter.project_id,
ident__icontains=datafilter.ident, 'ident__icontains': datafilter.ident,
name__icontains=datafilter.name, 'name__icontains': datafilter.name,
demandType__contains=datafilter.demandType, 'demandType__contains': datafilter.demandType,
chapter__icontains=datafilter.chapter).order_by('id') 'chapter__icontains': datafilter.chapter
}
# 判断是否传递dut_id如果没传递则查询轮次全部
if datafilter.dut_id:
dut_key = f"{datafilter.round_id}-{datafilter.dut_id}"
query_params['dut__key'] = dut_key
else:
# 如果没有dut__key则要查询round__key
query_params['round__key'] = datafilter.round_id
qs = Design.objects.filter(**query_params).order_by('id')
return qs return qs
@route.get("/getDesignOne", response=DesignModelOutSchema, url_name='design-one') @route.get("/getDesignOne", response=DesignModelOutSchema, url_name='design-one')
@@ -39,6 +53,13 @@ class DesignController(ControllerBase):
return design_qs return design_qs
raise HttpError(500, "未找到相应的数据") raise HttpError(500, "未找到相应的数据")
@route.get("/getDesignOneById", response=DesignModelOutSchema, url_name='design-one-by-id')
def get_one_by_id(self, id: int):
design_qs = Design.objects.filter(id=id).first()
if design_qs:
return design_qs
raise HttpError(500, "未找到相应的数据")
# 处理树状数据 # 处理树状数据
@route.get("/getDesignDemandInfo", response=List[DesignTreeReturnSchema], url_name="design-info") @route.get("/getDesignDemandInfo", response=List[DesignTreeReturnSchema], url_name="design-info")
def get_design_tree(self, payload: DesignTreeInputSchema = Query(...)): def get_design_tree(self, payload: DesignTreeInputSchema = Query(...)):
@@ -55,7 +76,8 @@ class DesignController(ControllerBase):
# 构造dut_key # 构造dut_key
dut_key = "".join([payload.round_key, "-", payload.dut_key]) dut_key = "".join([payload.round_key, "-", payload.dut_key])
# 判重标识-不需要再查询round以后的 # 判重标识-不需要再查询round以后的
if Design.objects.filter(project__id=payload.project_id, round__key=payload.round_key, dut__key=dut_key, if Design.objects.filter(project__id=payload.project_id, round__key=payload.round_key,
dut__key=dut_key,
ident=payload.ident).exists() and asert_dict['ident'] != "": ident=payload.ident).exists() and asert_dict['ident'] != "":
return ChenResponse(code=400, status=400, message='研制需求的标识重复,请检查') return ChenResponse(code=400, status=400, message='研制需求的标识重复,请检查')
# 查询当前key应该为多少 # 查询当前key应该为多少
@@ -64,7 +86,8 @@ class DesignController(ControllerBase):
# 查询当前的round_id # 查询当前的round_id
round_instance = Round.objects.get(project__id=payload.project_id, key=payload.round_key) round_instance = Round.objects.get(project__id=payload.project_id, key=payload.round_key)
dut_instance = Dut.objects.get(project__id=payload.project_id, key=dut_key) dut_instance = Dut.objects.get(project__id=payload.project_id, key=dut_key)
asert_dict.update({'key': key_string, 'round': round_instance, 'dut': dut_instance, 'title': payload.name}) asert_dict.update(
{'key': key_string, 'round': round_instance, 'dut': dut_instance, 'title': payload.name})
asert_dict.pop("round_key") asert_dict.pop("round_key")
asert_dict.pop("dut_key") asert_dict.pop("dut_key")
qs = Design.objects.create(**asert_dict) qs = Design.objects.create(**asert_dict)
@@ -156,3 +179,20 @@ class DesignController(ControllerBase):
round_dict['children'].append(dut_dict) round_dict['children'].append(dut_dict)
data_list.append(round_dict) data_list.append(round_dict)
return ChenResponse(message='获取成功', data=data_list) return ChenResponse(message='获取成功', data=data_list)
# 设计需求-替换接口
@route.post("/designDemand/replace/", url_name='design-replace')
@transaction.atomic
def replace_content(self, payload: ReplaceDesignContentSchema):
# 1.首先查询项目
project_obj: Project = get_object_or_404(Project, id=payload.project_id)
# 2.查询[所有轮次]的selectRows的id
design_qs = project_obj.psField.filter(id__in=payload.selectRows, round__key=payload.round_key)
# 3.批量替换里面文本
replace_kwargs = {
field_name: Replace(F(field_name), Value(payload.originText), Value(payload.replaceText))
for field_name in payload.selectColumn
}
# 4.提交更新
replace_count = design_qs.update(**replace_kwargs)
return {'count': replace_count}

View File

@@ -42,7 +42,7 @@ class DutController(ControllerBase):
qs = Dut.objects.filter(project__id=payload.project_id, round__key=payload.key) qs = Dut.objects.filter(project__id=payload.project_id, round__key=payload.key)
return qs return qs
# 获取单个dut # 获取单个dut-根据项目id和dut.key
@route.get("/getDutOne", response=DutModelOutSchema, url_name="dut-one") @route.get("/getDutOne", response=DutModelOutSchema, url_name="dut-one")
@transaction.atomic @transaction.atomic
def get_dut(self, project_id: int, key: str): def get_dut(self, project_id: int, key: str):
@@ -51,6 +51,13 @@ class DutController(ControllerBase):
return dut_qs return dut_qs
raise HttpError(500, "未找到相应的数据") raise HttpError(500, "未找到相应的数据")
@route.get("/getDutOneById", response=DutModelOutSchema, url_name='dut-one-by-id')
def get_one_by_id(self, id: int):
dut_qs = Dut.objects.filter(id=id).first()
if dut_qs:
return dut_qs
raise HttpError(500, "未找到相应的数据")
# 添加被测件 # 添加被测件
@route.post("/dut/save", url_name="dut-create", response=DutCreateOutSchema) @route.post("/dut/save", url_name="dut-create", response=DutCreateOutSchema)
@transaction.atomic @transaction.atomic

View File

@@ -6,6 +6,8 @@ from ninja.pagination import paginate
from ninja.errors import HttpError from ninja.errors import HttpError
from utils.chen_pagination import MyPagination from utils.chen_pagination import MyPagination
from django.db import transaction from django.db import transaction
from django.db.models.functions import Replace
from django.db.models import Q, F, Value
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from typing import List from typing import List
from utils.chen_response import ChenResponse from utils.chen_response import ChenResponse
@@ -13,7 +15,8 @@ from utils.chen_crud import multi_delete_testDemand
from utils.codes import HTTP_INDEX_ERROR from utils.codes import HTTP_INDEX_ERROR
from apps.project.models import Design, Dut, Round, TestDemand, TestDemandContent, TestDemandContentStep from apps.project.models import Design, Dut, Round, TestDemand, TestDemandContent, TestDemandContentStep
from apps.project.schemas.testDemand import DeleteSchema, TestDemandModelOutSchema, TestDemandFilterSchema, \ from apps.project.schemas.testDemand import DeleteSchema, TestDemandModelOutSchema, TestDemandFilterSchema, \
TestDemandTreeReturnSchema, TestDemandTreeInputSchema, TestDemandCreateOutSchema, TestDemandCreateInputSchema, \ TestDemandTreeReturnSchema, TestDemandTreeInputSchema, TestDemandCreateOutSchema, \
TestDemandCreateInputSchema, ReplaceDemandContentSchema, \
TestDemandRelatedSchema, TestDemandExistRelatedSchema, DemandCopyToDesignSchema TestDemandRelatedSchema, TestDemandExistRelatedSchema, DemandCopyToDesignSchema
# 导入ORM # 导入ORM
from apps.project.models import Project from apps.project.models import Project
@@ -30,12 +33,29 @@ class TestDemandController(ControllerBase):
@paginate(MyPagination) @paginate(MyPagination)
def get_test_demand_list(self, datafilter: TestDemandFilterSchema = Query(...)): def get_test_demand_list(self, datafilter: TestDemandFilterSchema = Query(...)):
conditionNoneToBlank(datafilter) conditionNoneToBlank(datafilter)
query_params = {
'project__id': datafilter.project_id,
'ident__icontains': datafilter.ident,
'name__icontains': datafilter.name,
'testType__contains': datafilter.testType,
'priority__icontains': datafilter.priority
}
# 如果没有传递多个key则认为是“那个轮次汇总界面”
if datafilter.dut_id and datafilter.design_id:
design_key = "".join([datafilter.round_id, '-', datafilter.dut_id, '-', datafilter.design_id]) design_key = "".join([datafilter.round_id, '-', datafilter.dut_id, '-', datafilter.design_id])
qs = TestDemand.objects.filter(project__id=datafilter.project_id, design__key=design_key, query_params['design__key'] = design_key
ident__icontains=datafilter.ident, else:
name__icontains=datafilter.name, # 轮次汇总界面要查round__key
testType__contains=datafilter.testType, query_params['round__key'] = datafilter.round_id
priority__icontains=datafilter.priority).order_by("key") # 判断是否存在testDesciption有则表示是大表查询
if datafilter.testDesciption:
query_params['testDesciption__icontains'] = datafilter.testDesciption
qs = TestDemand.objects.filter(**query_params).order_by("key")
# 判断是否存在testContent有则表示是大表查询这里需要查询子字段
if datafilter.testContent:
qs = qs.filter(Q(testQField__subName__icontains=datafilter.testContent) |
Q(testQField__testStepField__operation__icontains=datafilter.testContent) |
Q(testQField__testStepField__expect__icontains=datafilter.testContent))
# 由于有嵌套query_set存在把每个测试需求的schema加上一个字段 # 由于有嵌套query_set存在把每个测试需求的schema加上一个字段
query_list = [] query_list = []
for query_single in qs: for query_single in qs:
@@ -61,6 +81,20 @@ class TestDemandController(ControllerBase):
return demand_qs return demand_qs
raise HttpError(500, "未找到相应的数据") raise HttpError(500, "未找到相应的数据")
# 根据id直接查询
@route.get("/getTestDemandOneById", response=TestDemandModelOutSchema, url_name='testDemand-one-by-id')
@transaction.atomic
def get_demand_by_id(self, id: int):
demand_qs = TestDemand.objects.filter(id=id).first()
if demand_qs:
sub_list = []
for step_obj in demand_qs.testQField.all():
setattr(step_obj, "subStep", step_obj.testStepField.all().values())
sub_list.append(step_obj)
setattr(demand_qs, "testContent", sub_list)
return demand_qs
raise HttpError(500, "未找到相应的数据")
# 处理树状数据 # 处理树状数据
@route.get("/getTestdemandInfo", response=List[TestDemandTreeReturnSchema], url_name="testDemand-info") @route.get("/getTestdemandInfo", response=List[TestDemandTreeReturnSchema], url_name="testDemand-info")
@transaction.atomic @transaction.atomic
@@ -78,11 +112,13 @@ class TestDemandController(ControllerBase):
if payload.ident and project_qs: if payload.ident and project_qs:
exists = project_qs.ptField.filter(ident=payload.ident).exists() exists = project_qs.ptField.filter(ident=payload.ident).exists()
if exists: if exists:
return ChenResponse(code=500, status=500, message='测试项标识和其他测试项重复,请更换测试项标识!!!') return ChenResponse(code=500, status=500,
message='测试项标识和其他测试项重复,请更换测试项标识!!!')
# 构造design_key # 构造design_key
design_key = "".join([payload.round_key, "-", payload.dut_key, '-', payload.design_key]) design_key = "".join([payload.round_key, "-", payload.dut_key, '-', payload.design_key])
# 查询当前key应该为多少 # 查询当前key应该为多少
test_demand_count = TestDemand.objects.filter(project__id=payload.project_id, design__key=design_key).count() test_demand_count = TestDemand.objects.filter(project__id=payload.project_id,
design__key=design_key).count()
key_string = ''.join([design_key, "-", str(test_demand_count)]) key_string = ''.join([design_key, "-", str(test_demand_count)])
# 查询当前各个前面节点的instance # 查询当前各个前面节点的instance
round_instance = Round.objects.get(project__id=payload.project_id, key=payload.round_key) round_instance = Round.objects.get(project__id=payload.project_id, key=payload.round_key)
@@ -90,7 +126,8 @@ class TestDemandController(ControllerBase):
key="".join([payload.round_key, "-", payload.dut_key])) key="".join([payload.round_key, "-", payload.dut_key]))
design_instance = Design.objects.get(project__id=payload.project_id, key="".join( design_instance = Design.objects.get(project__id=payload.project_id, key="".join(
[payload.round_key, "-", payload.dut_key, '-', payload.design_key])) [payload.round_key, "-", payload.dut_key, '-', payload.design_key]))
asert_dict.update({'key': key_string, 'round': round_instance, 'dut': dut_instance, 'design': design_instance, asert_dict.update(
{'key': key_string, 'round': round_instance, 'dut': dut_instance, 'design': design_instance,
'title': payload.name}) 'title': payload.name})
asert_dict.pop("round_key") asert_dict.pop("round_key")
asert_dict.pop("dut_key") asert_dict.pop("dut_key")
@@ -153,11 +190,13 @@ class TestDemandController(ControllerBase):
) )
for step in item["subStep"] for step in item["subStep"]
]) ])
setattr(testDemand_qs, attr, value)
# ~~~2024年5月9日测试项更新标识后还要更新下面用例的标识~~~ # ~~~2024年5月9日测试项更新标识后还要更新下面用例的标识~~~
if testDemand_qs.ident != old_ident: if testDemand_qs.ident != old_ident:
for case in testDemand_qs.tcField.all(): for case in testDemand_qs.tcField.all():
case.ident = testDemand_qs.ident case.ident = testDemand_qs.ident
case.save() case.save()
testDemand_qs.save()
return testDemand_qs return testDemand_qs
# 删除测试项 # 删除测试项
@@ -215,7 +254,8 @@ class TestDemandController(ControllerBase):
if ti.pk == test_id: if ti.pk == test_id:
non_exist_ids.remove(test_id) non_exist_ids.remove(test_id)
if len(non_exist_ids) <= 0 < len(test_item_ids): if len(non_exist_ids) <= 0 < len(test_item_ids):
return ChenResponse(status=400, code=200, message='选择的测试项全部存在于当前设计需求中,请重新选择...') return ChenResponse(status=400, code=200,
message='选择的测试项全部存在于当前设计需求中,请重新选择...')
# 先查询现在有的关联测试项 # 先查询现在有的关联测试项
for item in design_item.odField.values('id'): for item in design_item.odField.values('id'):
item_id = item.get('id', None) item_id = item.get('id', None)
@@ -251,3 +291,32 @@ class TestDemandController(ControllerBase):
"""前端测试项右键复制到某个设计需求下面""" """前端测试项右键复制到某个设计需求下面"""
new_demand_key = demand_copy_to_design(data.project_id, data.demand_key, data.design_id, data.depth) new_demand_key = demand_copy_to_design(data.project_id, data.demand_key, data.design_id, data.depth)
return ChenResponse(data={'key': new_demand_key}) return ChenResponse(data={'key': new_demand_key})
# 测试项-替换接口
@route.post("/testDemand/replace/", url_name='testDemand-replace')
@transaction.atomic
def replace_demand_content(self, payload: ReplaceDemandContentSchema):
# 1.首先查询项目
project_obj: Project = get_object_or_404(Project, id=payload.project_id)
# 2.查询[所有轮次]的selectRows的id
demand_qs = project_obj.ptField.filter(id__in=payload.selectRows, round__key=payload.round_key)
# 3.批量替换里面文本(解构不影响老数组)
selectColumn = [x for x in payload.selectColumn if x != 'testContent']
replace_kwargs = {
field_name: Replace(F(field_name), Value(payload.originText), Value(payload.replaceText))
for field_name in selectColumn
}
# 4.单独处理testContentStep的操作、预期-查询所有
# 4.1.获取所有关联的TestDemandContentStep
step_count = 0
if 'testContent' in payload.selectColumn:
test_demand_contents = TestDemandContent.objects.filter(testDemand__in=demand_qs)
test_steps = TestDemandContentStep.objects.filter(testDemandContent__in=test_demand_contents)
# 批量更新 operation 和 expect
step_count = test_steps.update(
operation=Replace(F('operation'), Value(payload.originText), Value(payload.replaceText)),
expect=Replace(F('expect'), Value(payload.originText), Value(payload.replaceText))
)
# 5.提交更新
replace_count = demand_qs.update(**replace_kwargs)
return {'count': replace_count + step_count}

View File

@@ -5,6 +5,7 @@ from typing import List, Union, Optional
from datetime import date from datetime import date
# 关联问题单 # 关联问题单
from apps.project.schemas.problem import ProblemModelOutSchema from apps.project.schemas.problem import ProblemModelOutSchema
from apps.project.schemas.testDemand import TestDemandModelOutSchemaOrigin
# 删除schema # 删除schema
class DeleteSchema(Schema): class DeleteSchema(Schema):
@@ -31,12 +32,25 @@ class CaseModelOutSchemaWithoutProblem(ModelSchema):
model = Case model = Case
model_exclude = ['project', 'round', 'dut', 'design', 'test', 'remark', 'sort'] model_exclude = ['project', 'round', 'dut', 'design', 'test', 'remark', 'sort']
# 输出case关联问题单
class CaseModelOutSchemaOrigin(ModelSchema):
testStep: List[CaseStepSchema]
testType: str # 用例额外字段用于测试类型FT的标识给前端
# 新增:关联的问题单
problem: Optional[ProblemModelOutSchema] = None
class Config:
model = Case
model_exclude = ['project', 'round', 'dut', 'design', 'test', 'remark', 'sort']
# 输出case关联问题单 # 输出case关联问题单
class CaseModelOutSchema(ModelSchema): class CaseModelOutSchema(ModelSchema):
testStep: List[CaseStepSchema] testStep: List[CaseStepSchema]
testType: str # 用例额外字段用于测试类型FT的标识给前端 testType: str # 用例额外字段用于测试类型FT的标识给前端
# 新增:关联的问题单 # 新增:关联的问题单
problem: Optional[ProblemModelOutSchema] = None problem: Optional[ProblemModelOutSchema] = None
# 2025年5月10日新增上级字段
test: Optional[TestDemandModelOutSchemaOrigin] = None
class Config: class Config:
model = Case model = Case
@@ -119,3 +133,24 @@ class DemandNodeSchema(Schema):
isLeaf: bool = False isLeaf: bool = False
key: str = Field(None, alias='nodekey') key: str = Field(None, alias='nodekey')
title: str = Field(None) title: str = Field(None)
# 替换文本输入Schema
class ReplaceCaseSchema(Schema):
project_id: int
round_key: str
originText: str
replaceText: str
selectRows: List[int]
selectColumn: List[str]
# 人员替换Schema
class PersonReplaceSchema(Schema):
selectRows: List[int] = None
designPerson: str
testPerson: str
monitorPerson: str
# 事件替换Schema
class ExetimeReplaceSchema(Schema):
selectRows: List[int] = None
exetime: str

View File

@@ -1,7 +1,10 @@
from typing import Optional
from apps.project.models import Design from apps.project.models import Design
from ninja import Field, Schema, ModelSchema from ninja import Field, Schema, ModelSchema
from typing import List, Union from typing import List, Union
from pydantic import AliasChoices from pydantic import AliasChoices
# 上级dut-schema
from apps.project.schemas.dut import DutModelOutSchema
# 删除schema # 删除schema
class DeleteSchema(Schema): class DeleteSchema(Schema):
@@ -18,7 +21,16 @@ class DesignFilterSchema(Schema):
# 新增字段 - chapter # 新增字段 - chapter
chapter: str = Field(None, alias='chapter') chapter: str = Field(None, alias='chapter')
# 2025年改为2个输出因为下级需要上级原始不再嵌套上级
class DesignModelOutSchemaOrigin(ModelSchema):
class Config:
model = Design
model_exclude = ['project', 'round', 'dut', 'remark', 'sort']
class DesignModelOutSchema(ModelSchema): class DesignModelOutSchema(ModelSchema):
# 新增字段 - 上级的dut对象
dut: Optional[DutModelOutSchema] = None
class Config: class Config:
model = Design model = Design
model_exclude = ['project', 'round', 'dut', 'remark', 'sort'] model_exclude = ['project', 'round', 'dut', 'remark', 'sort']
@@ -72,3 +84,12 @@ class MultiDesignCreateInputSchema(Schema):
project_id: int = Field(..., alias="projectId") project_id: int = Field(..., alias="projectId")
dut_key: str = Field(..., alias="key") dut_key: str = Field(..., alias="key")
data: List[SingleDesignSchema] data: List[SingleDesignSchema]
# 批量替换design的接口Schema
class ReplaceDesignContentSchema(Schema):
project_id: int
round_key: str
originText: str
replaceText: str
selectRows: List[int]
selectColumn: List[str]

View File

@@ -1,4 +1,5 @@
from apps.project.models import TestDemand, TestDemandContent, TestDemandContentStep from apps.project.models import TestDemand, TestDemandContent, TestDemandContentStep
from apps.project.schemas.design import DesignModelOutSchemaOrigin # 注意导入的是不含上级的Schema
from ninja import Field, Schema, ModelSchema from ninja import Field, Schema, ModelSchema
from typing import List, Union, Optional from typing import List, Union, Optional
from pydantic import AliasChoices from pydantic import AliasChoices
@@ -20,8 +21,18 @@ class TestContentSchema(ModelSchema):
model = TestDemandContent model = TestDemandContent
fields = ["subName"] fields = ["subName"]
# 2025年修改为两个一个含上级一个不含
class TestDemandModelOutSchemaOrigin(ModelSchema):
testContent: List[TestContentSchema] # 下级对象
class Meta:
model = TestDemand
exclude = ['project', 'round', 'dut', 'design', 'remark', 'sort']
class TestDemandModelOutSchema(ModelSchema): class TestDemandModelOutSchema(ModelSchema):
testContent: List[TestContentSchema] testContent: List[TestContentSchema] # 下级对象
# 2025年5月9日新增上级字段design
design: Optional[DesignModelOutSchemaOrigin] = None
class Meta: class Meta:
model = TestDemand model = TestDemand
@@ -38,6 +49,9 @@ class TestDemandFilterSchema(Schema):
testType: str = Field(None, alias='testType') testType: str = Field(None, alias='testType')
name: str = Field(None, alias='name') name: str = Field(None, alias='name')
priority: str = Field(None, alias="priority") priority: str = Field(None, alias="priority")
# 新增查询字段,给大表的查询
testDesciption: str = Field(None, alias="testDesciption")
testContent: str = Field(None, alias="testContent")
# 处理树状结构的schema # 处理树状结构的schema
class TestDemandTreeReturnSchema(Schema): class TestDemandTreeReturnSchema(Schema):
@@ -102,3 +116,12 @@ class DemandCopyToDesignSchema(Schema):
design_id: int design_id: int
demand_key: str demand_key: str
depth: bool = False depth: bool = False
# 替换文本输入Schema
class ReplaceDemandContentSchema(Schema):
project_id: int
round_key: str
originText: str
replaceText: str
selectRows: List[int]
selectColumn: List[str]

File diff suppressed because it is too large Load Diff