Skip to content

Commit

Permalink
fix(backend): 我的待办区分处理和协助页面 TencentBlueKing#8750
Browse files Browse the repository at this point in the history
# Reviewed, transaction id: 27452
  • Loading branch information
ygcyao committed Dec 23, 2024
1 parent b553a46 commit 3e32468
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 17 deletions.
8 changes: 8 additions & 0 deletions dbm-ui/backend/configuration/models/dba.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,11 @@ def get_biz_db_type_admins(cls, bk_biz_id: int, db_type: str) -> List[str]:
if db_type == admin["db_type"]:
return admin["users"] or DEFAULT_DB_ADMINISTRATORS
return DEFAULT_DB_ADMINISTRATORS

@classmethod
def get_dba_for_db_type(cls, bk_biz_id: int, db_type: str) -> List[str]:
"""获取主dba、备dba、二线dba人员"""
dba_list = cls.list_biz_admins(bk_biz_id)
dba_content = next((dba for dba in dba_list if dba["db_type"] == db_type), {"users": []})
users = dba_content.get("users", [])
return users[:1], users[1:2], users[2:]
22 changes: 20 additions & 2 deletions dbm-ui/backend/ticket/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from backend import env
from backend.components import ItsmApi
from backend.configuration.constants import PLAT_BIZ_ID, SystemSettingsEnum
from backend.configuration.models import SystemSettings
from backend.configuration.models import DBAdministrator, SystemSettings
from backend.db_meta.models import Cluster
from backend.db_services.ipchooser.handlers.host_handler import HostHandler
from backend.ticket.builders import BuilderFactory
Expand All @@ -40,7 +40,6 @@
from backend.ticket.exceptions import TicketFlowsConfigException
from backend.ticket.flow_manager.manager import TicketFlowManager
from backend.ticket.models import Flow, Ticket, TicketFlowsConfig, Todo
from backend.ticket.serializers import TodoSerializer
from backend.ticket.todos import BaseTodoContext, TodoActorFactory
from backend.ticket.todos.itsm_todo import ItsmTodoContext

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

results = []
for operation in operations:
Expand Down Expand Up @@ -458,3 +458,21 @@ def ticket_status_standardization(cls):
context=ItsmTodoContext(itsm_flow.id, ticket.id).to_dict(),
)
print(f"ticket[{ticket.id}] add a itsm todo")

@classmethod
def get_todo_operators(cls, todo: Todo, bk_biz_id, db_type):
"""
获取待办处理人、协助人列表
"""
operators_dict = {}
operators_dict["operators"] = []
operators_dict["helpers"] = []
dba, second_dba, other_dba = DBAdministrator.get_dba_for_db_type(bk_biz_id, db_type)
if todo.type == TodoType.APPROVE:
operators_dict["operators"] = todo.operators[:1]
operators_dict["helpers"] = todo.operators[1:]
elif todo.type in [TodoType.INNER_APPROVE, TodoType.RESOURCE_REPLENISH, TodoType.INNER_FAILED]:
# 第一个元素固定为提单人 判断第二个元素是否存在且为主dba
operators_dict["operators"] = todo.operators[:2] if todo.operators[1:2] in dba else todo.operators[:1]
operators_dict["helpers"] = todo.operators[2:] if todo.operators[1:2] in dba else todo.operators[1:]
return operators_dict
22 changes: 12 additions & 10 deletions dbm-ui/backend/ticket/models/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,30 +39,32 @@ def exist_unfinished(self):
def get_operators(self, todo_type, ticket, operators):
# 获得提单人,dba,业务协助人. TODO: 后续还会细分主、备、二线DBA,以及明确区分协助人角色
creator = [ticket.creator]
dba = DBAdministrator.get_biz_db_type_admins(ticket.bk_biz_id, ticket.group)
# dba = DBAdministrator.get_biz_db_type_admins(ticket.bk_biz_id, ticket.group)
dba, second_dba, other_dba = DBAdministrator.get_dba_for_db_type(ticket.bk_biz_id, ticket.group)
biz_helpers = BizSettings.get_assistance(ticket.bk_biz_id)

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

def create(self, **kwargs):
operators = self.get_operators(kwargs["type"], kwargs["ticket"], kwargs.get("operators", []))
creator, helpers, operators = self.get_operators(kwargs["type"], kwargs["ticket"], kwargs.get("operators", []))
receiver = operators[0] if kwargs["type"] == TodoType.ITSM else creator + helpers
kwargs["operators"] = operators
todo = super().create(**kwargs)
send_msg_for_flow.apply_async(
Expand All @@ -71,7 +73,7 @@ def create(self, **kwargs):
"flow_msg_type": FlowMsgType.TODO.value,
"flow_status": FlowMsgStatus.UNCONFIRMED.value,
"processor": ",".join(todo.operators),
"receiver": todo.creator,
"receiver": ",".join(receiver),
}
)
return todo
Expand Down
41 changes: 37 additions & 4 deletions dbm-ui/backend/ticket/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
TodoStatus,
)
from backend.ticket.flow_manager.manager import TicketFlowManager
from backend.ticket.handler import TicketHandler
from backend.ticket.models import Flow, Ticket, Todo
from backend.ticket.todos import ActionType
from backend.ticket.yasg_slz import todo_operate_example
Expand Down Expand Up @@ -96,6 +97,7 @@ class TicketSerializer(AuditedSerializer, serializers.ModelSerializer):
details = TicketDetailsSerializer(help_text=_("单据详情"))
# 额外补充展示字段
todo_operators = serializers.SerializerMethodField(help_text=_("处理人列表"))
todo_helpers = serializers.SerializerMethodField(help_text=_("协助人列表"))
status = serializers.SerializerMethodField(help_text=_("状态"), read_only=True)
status_display = serializers.SerializerMethodField(help_text=_("状态名称"))
ticket_type_display = serializers.SerializerMethodField(help_text=_("单据类型名称"))
Expand All @@ -121,9 +123,21 @@ def validate_ticket_type(self, value):
return value

def get_todo_operators(self, obj):
# 任取一个运行中的todo,获取operators即可
obj.running_todos = [todo for todo in obj.todo_of_ticket.all() if todo.status == TodoStatus.TODO]
return obj.running_todos[0].operators if obj.running_todos else []
for todo in obj.todo_of_ticket.all():
if todo.status == TodoStatus.TODO:
running_todos = TicketHandler.get_todo_operators(todo=todo, bk_biz_id=obj.bk_biz_id, db_type=obj.group)
return running_todos.get("operators", [])
return []

# obj.running_todos = [todo for todo in obj.todo_of_ticket.all() if todo.status == TodoStatus.TODO]
# return obj.running_todos["operators"]

def get_todo_helpers(self, obj):
for todo in obj.todo_of_ticket.all():
if todo.status == TodoStatus.TODO:
running_todos = TicketHandler.get_todo_operators(todo=todo, bk_biz_id=obj.bk_biz_id, db_type=obj.group)
return running_todos.get("helpers", [])
return []

def get_status(self, obj):
if obj.status == TicketStatus.RUNNING and obj.running_todos:
Expand All @@ -147,6 +161,18 @@ def get_bk_biz_name(self, obj):
def get_db_app_abbr(self, obj):
return self.context["ticket_ctx"].app_abbr_map.get(obj.bk_biz_id) or ""

def to_representation(self, instance):
request = self.context.get("request")
is_assist = request.query_params.get("is_assist", False)
representation = super().to_representation(instance)
if not int(request.query_params.get("self_manage", 0)):
return representation
# 根据is_assist判断返回待我处理、待我协助页面数据
key = "todo_helpers" if is_assist else "todo_operators"
if request.user.username in representation.get(key, []):
return representation
return


class TicketFlowSerializer(TranslationSerializerMixin, serializers.ModelSerializer):
status = serializers.SerializerMethodField(help_text=_("流程状态"))
Expand Down Expand Up @@ -230,14 +256,21 @@ class TodoSerializer(serializers.ModelSerializer):
单据序列化
"""

operators = serializers.JSONField(help_text=_("待办人列表"))
todo_operators = serializers.SerializerMethodField(help_text=_("处理人列表"))
todo_helpers = serializers.SerializerMethodField(help_text=_("协助人列表"))
cost_time = serializers.SerializerMethodField(help_text=_("耗时"))

def get_cost_time(self, obj):
if obj.status in TODO_RUNNING_STATUS:
return calculate_cost_time(timezone.now(), obj.create_at)
return calculate_cost_time(obj.done_at, obj.create_at)

def get_todo_operators(self, obj):
return TicketHandler.get_todo_operators(obj, obj.ticket.bk_biz_id, obj.ticket.group).get("operators", [])

def get_todo_helpers(self, obj):
return TicketHandler.get_todo_operators(obj, obj.ticket.bk_biz_id, obj.ticket.group).get("helpers", [])

class Meta:
model = Todo
exclude = model.AUDITED_FIELDS
Expand Down
4 changes: 3 additions & 1 deletion dbm-ui/backend/ticket/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ def retrieve(self, request, *args, **kwargs):
def list(self, request, *args, **kwargs):
resp = super().list(request, *args, **kwargs)
# 补充单据关联信息
resp.data["results"] = TicketHandler.add_related_object(resp.data["results"])
resp.data["results"] = TicketHandler.add_related_object(
list(filter(lambda x: x is not None, resp.data["results"]))
)
# 如果是查询自身单据(self_manage),则不进行鉴权
skip_iam = "self_manage" in request.query_params
resp.data["results"] = [{"skip_iam": skip_iam, **t} for t in resp.data["results"]]
Expand Down

0 comments on commit 3e32468

Please sign in to comment.