1313from django .utils .translation import gettext_lazy as _
1414from rest_framework import serializers
1515
16+ from application .models import Application
1617from common .db .search import page_search
1718from common .exception .app_exception import AppApiException
19+ from tools .models import Tool
1820from trigger .models import TriggerTypeChoices , Trigger , TriggerTaskTypeChoices , TriggerTask
1921
2022
@@ -33,6 +35,149 @@ class TriggerCreateRequest(serializers.Serializer):
3335 is_active = serializers .BooleanField (required = False , label = _ ('Is active' ))
3436 trigger_task = TriggerTaskCreateRequest (many = True )
3537
38+ def is_valid (self , * , raise_exception = False ):
39+ super ().is_valid (raise_exception = True )
40+ trigger_type = self .data .get ('trigger_type' )
41+ trigger_setting = self .data .get ('trigger_setting' , {})
42+
43+ if trigger_type == TriggerTypeChoices .SCHEDULED :
44+ self ._validate_scheduled_setting (trigger_setting )
45+
46+ elif trigger_type == TriggerTypeChoices .EVENT :
47+ self ._validate_event_setting (trigger_setting )
48+ else :
49+ raise AppApiException (500 , _ ('Error trigger type' ))
50+
51+ return True
52+
53+ @staticmethod
54+ def _validate_required_field (setting , field_name , trigger_type ):
55+ if field_name not in setting :
56+ raise serializers .ValidationError ({
57+ 'trigger_setting' : f'{ trigger_type } type requires { field_name } field'
58+ })
59+
60+ @staticmethod
61+ def _validate_non_empty_array (value , field_name ):
62+ if not isinstance (value , list ):
63+ raise serializers .ValidationError ({
64+ 'trigger_setting' : f'{ field_name } must be an array'
65+ })
66+ if len (value ) == 0 :
67+ raise serializers .ValidationError ({
68+ 'trigger_setting' : f'{ field_name } must not be empty'
69+ })
70+
71+ @staticmethod
72+ def _validate_number_range (values , field_name , min_val , max_val ):
73+ for val in values :
74+ try :
75+ num = int (str (val ))
76+ if num < min_val or num > max_val :
77+ raise ValueError
78+ except (ValueError , TypeError ):
79+ raise serializers .ValidationError ({
80+ 'trigger_setting' : f'{ field_name } values must be between "{ min_val } " and "{ max_val } "'
81+ })
82+
83+ def _validate_time_array (self , time_list ):
84+ self ._validate_non_empty_array (time_list , 'time' )
85+
86+ for time_str in time_list :
87+ self ._validate_time_format (time_str )
88+
89+ @staticmethod
90+ def _validate_time_format (time_str ):
91+ import re
92+
93+ pattern = r'^([01]\d|2[0-3]):([0-5]\d)$'
94+ if not re .match (pattern , str (time_str )):
95+ raise serializers .ValidationError ({
96+ 'trigger_setting' : f'Invalid time format: { time_str } , must be HH:MM (e.g., 09:00)'
97+ })
98+
99+ def _validate_scheduled_setting (self , setting ):
100+ schedule_type = setting .get ('schedule_type' )
101+
102+ valid_types = ['daily' , 'weekly' , 'monthly' , 'interval' ]
103+ if schedule_type not in valid_types :
104+ raise serializers .ValidationError ({'trigger_setting' : f'schedule_type must be one of { valid_types } ' })
105+ if schedule_type == 'daily' :
106+ self ._validate_daily (setting )
107+ elif schedule_type == 'weekly' :
108+ self ._validate_weekly (setting )
109+ elif schedule_type == 'monthly' :
110+ self ._validate_monthly (setting )
111+ elif schedule_type == 'interval' :
112+ self ._validate_interval (setting )
113+
114+ def _validate_daily (self , setting ):
115+ self ._validate_required_field (setting , 'time' , 'daily' )
116+ self ._validate_time_array (setting ['time' ])
117+
118+ def _validate_weekly (self , setting ):
119+ self ._validate_required_field (setting , 'weekdays' , 'weekly' )
120+ self ._validate_required_field (setting , 'time' , 'weekly' )
121+ weekdays = setting ['weekdays' ]
122+ self ._validate_non_empty_array (weekdays , 'weekdays' )
123+ self ._validate_number_range (weekdays , 'weekdays' , 1 , 7 )
124+ self ._validate_time_array (setting ['time' ])
125+
126+ def _validate_monthly (self , setting ):
127+ self ._validate_required_field (setting , 'days' , 'monthly' )
128+ self ._validate_required_field (setting , 'time' , 'monthly' )
129+ days = setting ['days' ]
130+ self ._validate_non_empty_array (days , 'days' )
131+ self ._validate_number_range (days , 'days' , 1 , 31 )
132+ self ._validate_time_array (setting ['time' ])
133+
134+ def _validate_interval (self , setting ):
135+ self ._validate_required_field (setting , 'interval_value' , 'interval' )
136+ self ._validate_required_field (setting , 'interval_unit' , 'interval' )
137+ interval_value = setting ['interval_value' ]
138+ interval_unit = setting ['interval_unit' ]
139+ try :
140+ value_int = int (interval_value )
141+ if value_int < 1 :
142+ raise ValueError
143+ except (ValueError , TypeError ):
144+ raise serializers .ValidationError ({
145+ 'trigger_setting' : 'interval_value must be an integer greater than or equal to 1'
146+ })
147+ valid_units = ['minutes' , 'hours' ]
148+ if interval_unit not in valid_units :
149+ raise serializers .ValidationError ({
150+ 'trigger_setting' : f'interval_unit must be one of { valid_units } '
151+ })
152+
153+ @staticmethod
154+ def _validate_event_setting (setting ):
155+ body = setting .get ('body' )
156+ if body is not None and not isinstance (body , list ):
157+ raise serializers .ValidationError ({
158+ 'trigger_setting' : 'body must be an array'
159+ })
160+
161+ class TriggerModelSerializer (serializers .ModelSerializer ):
162+ class Meta :
163+ model = Trigger
164+ fields = "__all__"
165+
166+ class TriggerTaskModelSerializer (serializers .ModelSerializer ):
167+ class Meta :
168+ model = TriggerTask
169+ fields = "__all__"
170+
171+ class ApplicationTriggerTaskSerializer (serializers .ModelSerializer ):
172+ class Meta :
173+ model = Application
174+ fields = ['id' , 'name' , 'work_flow' , 'icon' , 'type' ]
175+
176+ class ToolTriggerTaskSerializer (serializers .ModelSerializer ):
177+ class Meta :
178+ model = Tool
179+ fields = ['id' , 'name' , 'input_field_list' , 'icon' ]
180+
36181
37182class TriggerResponse (serializers .ModelSerializer ):
38183 class Meta :
@@ -75,7 +220,6 @@ def insert(self, instance, with_valid=True):
75220 else :
76221 raise AppApiException (500 , _ ('Trigger task can not be empty' ))
77222
78-
79223 return TriggerResponse (trigger_model ).data
80224
81225 @staticmethod
@@ -89,7 +233,6 @@ def to_trigger_task_model(trigger_id: str, source_type: str, source_id: str):
89233 )
90234
91235
92-
93236class TriggerOperateSerializer (serializers .Serializer ):
94237 trigger_id = serializers .UUIDField (required = True , label = _ ('trigger id' ))
95238 user_id = serializers .UUIDField (required = True , label = _ ("User ID" ))
@@ -104,6 +247,30 @@ def is_valid(self, *, raise_exception=False):
104247 if not query_set .exists ():
105248 raise AppApiException (500 , _ ('Trigger id does not exist' ))
106249
250+ def edit (self ):
251+ pass
252+
253+ def one (self , with_valid = True ):
254+ if with_valid :
255+ self .is_valid ()
256+ trigger_id = self .data .get ('trigger_id' )
257+ trigger = QuerySet (Trigger ).filter (id = trigger_id ).first ()
258+
259+ trigger_tasks = QuerySet (TriggerTask ).filter (trigger_id = trigger_id )
260+ application_ids = [str (task .source_id ) for task in trigger_tasks if task .source_type == TriggerTaskTypeChoices .APPLICATION ]
261+ tool_ids = [str (task .source_id ) for task in trigger_tasks if task .source_type == TriggerTaskTypeChoices .TOOL ]
262+
263+
264+ application_task_list = [ApplicationTriggerTaskSerializer (application ).data for application in
265+ QuerySet (Application ).filter (id__in = application_ids )]
266+
267+ tool_task_list = [ToolTriggerTaskSerializer (tool ).data for tool in QuerySet (Tool ).filter (id__in = tool_ids )]
268+
269+ return {
270+ ** TriggerModelSerializer (trigger ).data ,
271+ 'application_task_list' :application_task_list ,
272+ 'tool_task_list' :tool_task_list ,
273+ }
107274
108275class TriggerQuerySerializer (serializers .Serializer ):
109276 name = serializers .CharField (required = False , allow_null = True , allow_blank = True , label = _ ('Trigger name' ))
0 commit comments