@@ -309,3 +309,70 @@ class ReportSpecifier:
309309class ReportRequest :
310310 report_request_id : str
311311 report_specifier : ReportSpecifier
312+
313+
314+ @dataclass
315+ class VavailabilityComponent :
316+ dtstart : datetime
317+ duration : timedelta
318+
319+
320+ @dataclass
321+ class Vavailability :
322+ components : List [VavailabilityComponent ]
323+
324+
325+ @dataclass
326+ class Opt :
327+ opt_type : str
328+ opt_reason : str
329+ opt_id : str = None
330+ created_date_time : datetime = None
331+
332+ event_id : str = None
333+ modification_number : int = None
334+ vavailability : Vavailability = None
335+ targets : List [Target ] = None
336+ targets_by_type : Dict = None
337+ market_context : str = None
338+ signal_target_mrid : str = None
339+
340+ def __post_init__ (self ):
341+ if self .opt_type not in enums .OPT .values :
342+ raise ValueError (f"""The opt_type must be one of '{ "', '" .join (enums .OPT .values )} ', """
343+ f"""you specified: '{ self .opt_type } '.""" )
344+ if self .opt_reason not in enums .OPT_REASON .values :
345+ raise ValueError (f"""The opt_reason must be one of '{ "', '" .join (enums .OPT_REASON .values )} ', """
346+ f"""you specified: '{ self .opt_type } '.""" )
347+ if self .signal_target_mrid is not None and self .signal_target_mrid not in enums .SIGNAL_TARGET_MRID .values and not self .signal_target_mrid .startswith ('x-' ):
348+ raise ValueError (f"""The signal_target_mrid must be one of '{ "', '" .join (enums .SIGNAL_TARGET_MRID .values )} ', """
349+ f"""you specified: '{ self .signal_target_mrid } '.""" )
350+ if self .event_id is None and self .vavailability is None :
351+ raise ValueError (
352+ "You must supply either 'event_id' or 'vavailability'." )
353+ if self .event_id is not None and self .vavailability is not None :
354+ raise ValueError (
355+ "You supplied both 'event_id' and 'vavailability."
356+ "Please supply either, but not both." )
357+ if self .created_date_time is None :
358+ self .created_date_time = datetime .now (timezone .utc )
359+ if self .modification_number is None :
360+ self .modification_number = 0
361+ if self .targets is None and self .targets_by_type is None :
362+ raise ValueError (
363+ "You must supply either 'targets' or 'targets_by_type'." )
364+ if self .targets_by_type is None :
365+ list_of_targets = [asdict (target ) if is_dataclass (
366+ target ) else target for target in self .targets ]
367+ self .targets_by_type = utils .group_targets_by_type (list_of_targets )
368+ elif self .targets is None :
369+ self .targets = [Target (
370+ ** target ) for target in utils .ungroup_targets_by_type (self .targets_by_type )]
371+ elif self .targets is not None and self .targets_by_type is not None :
372+ list_of_targets = [asdict (target ) if is_dataclass (
373+ target ) else target for target in self .targets ]
374+ if utils .group_targets_by_type (list_of_targets ) != self .targets_by_type :
375+ raise ValueError ("You assigned both 'targets' and 'targets_by_type' in your event, "
376+ "but the two were not consistent with each other. "
377+ f"You supplied 'targets' = { self .targets } and "
378+ f"'targets_by_type' = { self .targets_by_type } " )
0 commit comments