Coverage for backend/django/flowsheetInternals/unitops/serializers/SimulationObjectSerializer.py: 93%

67 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2026-07-22 05:22 +0000

1from core.serializer_base import StateOwnedModelSerializer 

2from core.validation import get_current_flowsheet 

3from core.auxiliary.models.Flowsheet import Flowsheet 

4from rest_framework import serializers 

5from flowsheetInternals.unitops.models.property_package_propogation import ( 

6 propogate_property_package, 

7) 

8from flowsheetInternals.unitops.models import SimulationObject, SimulationObjectFactory 

9from flowsheetInternals.propertyPackages.models.StreamFactory import StreamFactory 

10from core.auxiliary.serializers.PropertyInfoSerializer import PropertySetSerializer 

11 

12 

13class SimulationObjectSerializer(StateOwnedModelSerializer): 

14 componentName = serializers.CharField(required=False, allow_blank=True, default="") 

15 # The x and y coordinates of the unit operation. 

16 x = serializers.DecimalField( 

17 max_digits=10, decimal_places=5, write_only=True, default=0.0 

18 ) 

19 y = serializers.DecimalField( 

20 max_digits=10, decimal_places=5, write_only=True, default=0.0 

21 ) 

22 parentGroup = serializers.IntegerField( 

23 write_only=True, default=0 

24 ) # initial group to add the simulation object to 

25 propertySetId = serializers.PrimaryKeyRelatedField( 

26 source="properties.pk", read_only=True 

27 ) 

28 groupId = serializers.PrimaryKeyRelatedField( 

29 source="grouping.pk", read_only=True 

30 ) # This group id is only present on Group unit operations. see groupingModel.py 

31 unspecifiedProperties = serializers.SerializerMethodField() 

32 

33 class Meta: 

34 model = SimulationObject 

35 extra_kwargs = { 

36 "componentName": {"required": False}, # auto-generated 

37 } 

38 fields = "__all__" 

39 

40 def create(self, validated_data): 

41 context = get_current_flowsheet() or {} 

42 flowsheet_id = context.get("flowsheet") 

43 flowsheet_state_id = context.get("flowsheet_state") 

44 if flowsheet_id is None or flowsheet_state_id is None: 44 ↛ 45line 44 didn't jump to line 45 because the condition on line 44 was never true

45 raise serializers.ValidationError( 

46 "An active flowsheet context is required to create a simulation object." 

47 ) 

48 

49 # The public ``flowsheet`` field validates stable identity but is not a 

50 # model field, so it is deliberately absent from ``validated_data``. 

51 # Rehydrate the captured stable/state pair for the factory so naming, 

52 # root-group placement, and all related rows use this request's state. 

53 try: 

54 flowsheet = Flowsheet.objects.select_related("current_state").get( 

55 pk=flowsheet_id, 

56 current_state_id=flowsheet_state_id, 

57 ) 

58 except Flowsheet.DoesNotExist as exc: 

59 raise serializers.ValidationError( 

60 "The active flowsheet state is no longer current." 

61 ) from exc 

62 

63 x = float(validated_data.pop("x")) 

64 y = float(validated_data.pop("y")) 

65 coordinates = {"x": x, "y": y} 

66 result = SimulationObjectFactory.create_simulation_object( 

67 coordinates, 

68 flowsheet=flowsheet, 

69 **validated_data, 

70 ) 

71 result.flowsheet_state.flowsheet.record_content_change() 

72 return result 

73 

74 def to_representation(self, instance): 

75 """Include the canvas context needed to faithfully replay creation.""" 

76 

77 representation = super().to_representation(instance) 

78 graphic = instance.graphicObject.first() 

79 if graphic is not None: 79 ↛ 83line 79 didn't jump to line 83 because the condition on line 79 was always true

80 representation["x"] = f"{graphic.x + graphic.width / 2:.5f}" 

81 representation["y"] = f"{graphic.y + graphic.height / 2:.5f}" 

82 representation["parentGroup"] = graphic.group_id 

83 return representation 

84 

85 def save(self, **kwargs): 

86 # Update property package 

87 validated_data = self.validated_data 

88 result = super().save(**kwargs) 

89 # Then propagate it to all connected streams 

90 if ( 

91 validated_data.get("propertyPackageType") is not None 

92 or validated_data.get("customPackage") is not None 

93 ): 

94 if ( 

95 self.instance.objectType == "stream" 

96 or self.instance.objectType == "humid_air_stream" 

97 ): 

98 factory = StreamFactory(self.instance) 

99 factory.check_and_update_stream() 

100 propogate_property_package(self.instance) 

101 self.instance.flowsheet_state.flowsheet.record_content_change() 

102 

103 return result 

104 

105 def get_unspecifiedProperties(self, instance: SimulationObject) -> list: 

106 return instance.get_unspecified_properties() 

107 

108 

109class SimulationObjectRetrieveSerializer(StateOwnedModelSerializer): 

110 properties = PropertySetSerializer(read_only=True) 

111 propertySetId = serializers.PrimaryKeyRelatedField( 

112 source="properties.pk", 

113 read_only=True, 

114 ) 

115 # This group id is only present on Group unit operations. see groupingModel.py 

116 groupId = serializers.PrimaryKeyRelatedField( 

117 source="grouping.pk", 

118 read_only=True, 

119 ) 

120 unspecifiedProperties = serializers.SerializerMethodField() 

121 

122 class Meta: 

123 model = SimulationObject 

124 fields = "__all__" 

125 extra_kwargs = { 

126 "componentName": {"required": False}, # auto-generated 

127 } 

128 

129 def get_unspecifiedProperties(self, instance: SimulationObject) -> list: 

130 return instance.get_unspecified_properties()