Skip to content

Commit 224eff7

Browse files
committed
fix(backend): 我的待办区分处理和协助页面 #8750
# Reviewed, transaction id: 28312
1 parent b553a46 commit 224eff7

File tree

5 files changed

+85
-17
lines changed

5 files changed

+85
-17
lines changed

dbm-ui/backend/configuration/models/dba.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,11 @@ def get_biz_db_type_admins(cls, bk_biz_id: int, db_type: str) -> List[str]:
6060
if db_type == admin["db_type"]:
6161
return admin["users"] or DEFAULT_DB_ADMINISTRATORS
6262
return DEFAULT_DB_ADMINISTRATORS
63+
64+
@classmethod
65+
def get_dba_for_db_type(cls, bk_biz_id: int, db_type: str) -> List[str]:
66+
"""获取主dba、备dba、二线dba人员"""
67+
dba_list = cls.list_biz_admins(bk_biz_id)
68+
dba_content = next((dba for dba in dba_list if dba["db_type"] == db_type), {"users": []})
69+
users = dba_content.get("users", [])
70+
return users[:1], users[1:2], users[2:]

dbm-ui/backend/ticket/handler.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from backend import env
2222
from backend.components import ItsmApi
2323
from backend.configuration.constants import PLAT_BIZ_ID, SystemSettingsEnum
24-
from backend.configuration.models import SystemSettings
24+
from backend.configuration.models import DBAdministrator, SystemSettings
2525
from backend.db_meta.models import Cluster
2626
from backend.db_services.ipchooser.handlers.host_handler import HostHandler
2727
from backend.ticket.builders import BuilderFactory
@@ -40,7 +40,6 @@
4040
from backend.ticket.exceptions import TicketFlowsConfigException
4141
from backend.ticket.flow_manager.manager import TicketFlowManager
4242
from backend.ticket.models import Flow, Ticket, TicketFlowsConfig, Todo
43-
from backend.ticket.serializers import TodoSerializer
4443
from backend.ticket.todos import BaseTodoContext, TodoActorFactory
4544
from backend.ticket.todos.itsm_todo import ItsmTodoContext
4645

@@ -287,6 +286,7 @@ def batch_process_todo(cls, user, action, operations):
287286
@param action 动作
288287
@param operations: todo列表,每个item包含todo id和params
289288
"""
289+
from backend.ticket.serializers import TodoSerializer
290290

291291
results = []
292292
for operation in operations:
@@ -458,3 +458,21 @@ def ticket_status_standardization(cls):
458458
context=ItsmTodoContext(itsm_flow.id, ticket.id).to_dict(),
459459
)
460460
print(f"ticket[{ticket.id}] add a itsm todo")
461+
462+
@classmethod
463+
def get_todo_operators(cls, todo: Todo, bk_biz_id, db_type):
464+
"""
465+
获取待办处理人、协助人列表
466+
"""
467+
operators_dict = {}
468+
operators_dict["operators"] = []
469+
operators_dict["helpers"] = []
470+
dba, second_dba, other_dba = DBAdministrator.get_dba_for_db_type(bk_biz_id, db_type)
471+
if todo.type == TodoType.APPROVE:
472+
operators_dict["operators"] = todo.operators[:1]
473+
operators_dict["helpers"] = todo.operators[1:]
474+
elif todo.type in [TodoType.INNER_APPROVE, TodoType.RESOURCE_REPLENISH, TodoType.INNER_FAILED]:
475+
# 第一个元素固定为提单人 判断第二个元素是否存在且为主dba
476+
operators_dict["operators"] = todo.operators[:2] if todo.operators[1:2] in dba else todo.operators[:1]
477+
operators_dict["helpers"] = todo.operators[2:] if todo.operators[1:2] in dba else todo.operators[1:]
478+
return operators_dict

dbm-ui/backend/ticket/models/todo.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,32 @@ def exist_unfinished(self):
3939
def get_operators(self, todo_type, ticket, operators):
4040
# 获得提单人,dba,业务协助人. TODO: 后续还会细分主、备、二线DBA,以及明确区分协助人角色
4141
creator = [ticket.creator]
42-
dba = DBAdministrator.get_biz_db_type_admins(ticket.bk_biz_id, ticket.group)
42+
# dba = DBAdministrator.get_biz_db_type_admins(ticket.bk_biz_id, ticket.group)
43+
dba, second_dba, other_dba = DBAdministrator.get_dba_for_db_type(ticket.bk_biz_id, ticket.group)
4344
biz_helpers = BizSettings.get_assistance(ticket.bk_biz_id)
4445

4546
# 构造单据状态与处理人之间的对应关系
4647
# - 审批中:提单人可撤销,dba可处理,
4748
# 考虑某些单据审批人是特定配置(数据导出 -- 运维审批),所以从ItsmBuilder获得审批人
4849
# - 待执行:提单人 + 单据协助人
49-
# - 待继续:dba + 提单人 + 单据协助人
50-
# - 待补货:dba + 提单人 + 单据协助人
51-
# - 已失败:dba + 提单人 + 单据协助人
50+
# - 待继续:提单人 + dba + 单据协助人 + second_dba + other_dba
51+
# - 待补货:提单人 + dba + 单据协助人 + second_dba + other_dba
52+
# - 已失败:提单人 + dba + 单据协助人 + second_dba + other_dba
5253
itsm_builder = BuilderFactory.get_builder_cls(ticket.ticket_type).itsm_flow_builder(ticket)
5354
todo_operators_map = {
5455
TodoType.ITSM: itsm_builder.get_approvers().split(","),
5556
TodoType.APPROVE: creator + biz_helpers,
56-
TodoType.INNER_APPROVE: dba + creator + biz_helpers,
57-
TodoType.RESOURCE_REPLENISH: dba + creator + biz_helpers,
58-
TodoType.INNER_FAILED: dba + creator + biz_helpers,
57+
TodoType.INNER_APPROVE: creator + dba + biz_helpers + second_dba + other_dba,
58+
TodoType.RESOURCE_REPLENISH: creator + dba + biz_helpers + second_dba + other_dba,
59+
TodoType.INNER_FAILED: creator + dba + biz_helpers + second_dba + other_dba,
5960
}
6061
# 按照顺序去重
6162
operators = list(dict.fromkeys(operators + todo_operators_map.get(todo_type, [])))
62-
return operators
63+
return creator, biz_helpers, operators
6364

6465
def create(self, **kwargs):
65-
operators = self.get_operators(kwargs["type"], kwargs["ticket"], kwargs.get("operators", []))
66+
creator, helpers, operators = self.get_operators(kwargs["type"], kwargs["ticket"], kwargs.get("operators", []))
67+
receiver = operators[0] if kwargs["type"] == TodoType.ITSM else creator + helpers
6668
kwargs["operators"] = operators
6769
todo = super().create(**kwargs)
6870
send_msg_for_flow.apply_async(
@@ -71,7 +73,7 @@ def create(self, **kwargs):
7173
"flow_msg_type": FlowMsgType.TODO.value,
7274
"flow_status": FlowMsgStatus.UNCONFIRMED.value,
7375
"processor": ",".join(todo.operators),
74-
"receiver": todo.creator,
76+
"receiver": ",".join(receiver),
7577
}
7678
)
7779
return todo

dbm-ui/backend/ticket/serializers.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
TodoStatus,
3434
)
3535
from backend.ticket.flow_manager.manager import TicketFlowManager
36+
from backend.ticket.handler import TicketHandler
3637
from backend.ticket.models import Flow, Ticket, Todo
3738
from backend.ticket.todos import ActionType
3839
from backend.ticket.yasg_slz import todo_operate_example
@@ -96,6 +97,7 @@ class TicketSerializer(AuditedSerializer, serializers.ModelSerializer):
9697
details = TicketDetailsSerializer(help_text=_("单据详情"))
9798
# 额外补充展示字段
9899
todo_operators = serializers.SerializerMethodField(help_text=_("处理人列表"))
100+
todo_helpers = serializers.SerializerMethodField(help_text=_("协助人列表"))
99101
status = serializers.SerializerMethodField(help_text=_("状态"), read_only=True)
100102
status_display = serializers.SerializerMethodField(help_text=_("状态名称"))
101103
ticket_type_display = serializers.SerializerMethodField(help_text=_("单据类型名称"))
@@ -121,9 +123,26 @@ def validate_ticket_type(self, value):
121123
return value
122124

123125
def get_todo_operators(self, obj):
124-
# 任取一个运行中的todo,获取operators即可
125-
obj.running_todos = [todo for todo in obj.todo_of_ticket.all() if todo.status == TodoStatus.TODO]
126-
return obj.running_todos[0].operators if obj.running_todos else []
126+
obj.running_todos = next(
127+
(
128+
TicketHandler.get_todo_operators(todo=todo, bk_biz_id=obj.bk_biz_id, db_type=obj.group)
129+
for todo in obj.todo_of_ticket.all()
130+
if todo.status == TodoStatus.TODO
131+
),
132+
None,
133+
)
134+
return obj.running_todos.get("operators", []) if obj.running_todos else []
135+
136+
def get_todo_helpers(self, obj):
137+
obj.running_todos = next(
138+
(
139+
TicketHandler.get_todo_operators(todo=todo, bk_biz_id=obj.bk_biz_id, db_type=obj.group)
140+
for todo in obj.todo_of_ticket.all()
141+
if todo.status == TodoStatus.TODO
142+
),
143+
None,
144+
)
145+
return obj.running_todos.get("helpers", []) if obj.running_todos else []
127146

128147
def get_status(self, obj):
129148
if obj.status == TicketStatus.RUNNING and obj.running_todos:
@@ -147,6 +166,18 @@ def get_bk_biz_name(self, obj):
147166
def get_db_app_abbr(self, obj):
148167
return self.context["ticket_ctx"].app_abbr_map.get(obj.bk_biz_id) or ""
149168

169+
def to_representation(self, instance):
170+
request = self.context.get("request")
171+
is_assist = request.query_params.get("is_assist", False)
172+
representation = super().to_representation(instance)
173+
if not int(request.query_params.get("self_manage", 0)):
174+
return representation
175+
# 根据is_assist判断返回待我处理、待我协助页面数据
176+
key = "todo_helpers" if is_assist else "todo_operators"
177+
if request.user.username in representation.get(key, []):
178+
return representation
179+
return
180+
150181

151182
class TicketFlowSerializer(TranslationSerializerMixin, serializers.ModelSerializer):
152183
status = serializers.SerializerMethodField(help_text=_("流程状态"))
@@ -230,14 +261,21 @@ class TodoSerializer(serializers.ModelSerializer):
230261
单据序列化
231262
"""
232263

233-
operators = serializers.JSONField(help_text=_("待办人列表"))
264+
todo_operators = serializers.SerializerMethodField(help_text=_("处理人列表"))
265+
todo_helpers = serializers.SerializerMethodField(help_text=_("协助人列表"))
234266
cost_time = serializers.SerializerMethodField(help_text=_("耗时"))
235267

236268
def get_cost_time(self, obj):
237269
if obj.status in TODO_RUNNING_STATUS:
238270
return calculate_cost_time(timezone.now(), obj.create_at)
239271
return calculate_cost_time(obj.done_at, obj.create_at)
240272

273+
def get_todo_operators(self, obj):
274+
return TicketHandler.get_todo_operators(obj, obj.ticket.bk_biz_id, obj.ticket.group).get("operators", [])
275+
276+
def get_todo_helpers(self, obj):
277+
return TicketHandler.get_todo_operators(obj, obj.ticket.bk_biz_id, obj.ticket.group).get("helpers", [])
278+
241279
class Meta:
242280
model = Todo
243281
exclude = model.AUDITED_FIELDS

dbm-ui/backend/ticket/views.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,9 @@ def retrieve(self, request, *args, **kwargs):
274274
def list(self, request, *args, **kwargs):
275275
resp = super().list(request, *args, **kwargs)
276276
# 补充单据关联信息
277-
resp.data["results"] = TicketHandler.add_related_object(resp.data["results"])
277+
resp.data["results"] = TicketHandler.add_related_object(
278+
list(filter(lambda x: x is not None, resp.data["results"]))
279+
)
278280
# 如果是查询自身单据(self_manage),则不进行鉴权
279281
skip_iam = "self_manage" in request.query_params
280282
resp.data["results"] = [{"skip_iam": skip_iam, **t} for t in resp.data["results"]]

0 commit comments

Comments
 (0)