def test_get_sorted_events(self): # create a campaign campaign = Campaign.create(self.org, self.user, "Planting Reminders", self.farmers) flow = self.create_flow() event1 = CampaignEvent.create_flow_event(self.org, self.admin, campaign, self.planting_date, offset=1, unit='W', flow=flow, delivery_hour='13') event2 = CampaignEvent.create_flow_event(self.org, self.admin, campaign, self.planting_date, offset=1, unit='W', flow=flow, delivery_hour='9') event3 = CampaignEvent.create_flow_event(self.org, self.admin, campaign, self.planting_date, offset=2, unit='W', flow=flow, delivery_hour='1') self.assertEqual(campaign.get_sorted_events(), [event2, event1, event3]) flow_json = self.get_flow_json('call_me_maybe')['definition'] flow = Flow.create_instance(dict(name='Call Me Maybe', org=self.org, flow_type=Flow.MESSAGE, created_by=self.admin, modified_by=self.admin, saved_by=self.admin, version_number=3)) FlowRevision.create_instance(dict(flow=flow, definition=flow_json, spec_version=3, revision=1, created_by=self.admin, modified_by=self.admin)) event4 = CampaignEvent.create_flow_event(self.org, self.admin, campaign, self.planting_date, offset=2, unit='W', flow=flow, delivery_hour='5') self.assertEqual(flow.version_number, 3) self.assertEqual(campaign.get_sorted_events(), [event2, event1, event3, event4]) flow.refresh_from_db() self.assertNotEqual(flow.version_number, 3) self.assertEqual(flow.version_number, get_current_export_version())
def validate(self, data): steps = data.get("steps") revision = data.get("revision", data.get("version")) if not revision: # pragma: needs cover raise serializers.ValidationError("Missing 'revision' field") # load the specific revision of the flow flow_revision = self.flow_obj.revisions.filter( revision=revision).first() if not flow_revision: raise serializers.ValidationError("Invalid revision: %s" % revision) # make sure we are operating off a current spec definition = flow_revision.definition definition = FlowRevision.migrate_definition( definition, self.flow_obj, get_current_export_version()) # look for a matching node for each step in our path for step in steps: node_obj = None node_set = "rule_sets" if "rule" in step else "action_sets" for node_json in definition[node_set]: if node_json["uuid"] == step["node"]: node_obj = FlowRunWriteSerializer.RevisionNode( self.flow_obj, node_json) break if not node_obj: raise serializers.ValidationError( "No such node with UUID %s in flow '%s'" % (step["node"], self.flow_obj.name)) else: rule = step.get("rule", None) if rule: media = rule.get("media", None) if media: (media_type, media_path) = media.split(":", 1) if media_type != "geo": media_type_parts = media_type.split("/") error = None if len(media_type_parts) != 2: error = (media_type, media) if media_type_parts[0] not in Msg.MEDIA_TYPES: error = (media_type_parts[0], media) if error: raise serializers.ValidationError( "Invalid media type '%s': %s" % error) step["node"] = node_obj return data
def create_flow(self, definition=None, **kwargs): if "org" not in kwargs: kwargs["org"] = self.org if "user" not in kwargs: kwargs["user"] = self.user if "name" not in kwargs: kwargs["name"] = "Color Flow" flow = Flow.create(**kwargs) if not definition: # if definition isn't provided, generate simple single message flow node_uuid = str(uuid4()) definition = { "version": "10", "flow_type": "F", "base_language": "eng", "entry": node_uuid, "action_sets": [{ "uuid": node_uuid, "x": 0, "y": 0, "actions": [{ "msg": { "eng": "Hey everybody!" }, "media": {}, "send_all": False, "type": "reply" }], "destination": None, }], "rule_sets": [], } flow.version_number = definition["version"] flow.save() json_flow = FlowRevision.migrate_definition( definition, flow, to_version=Flow.FINAL_LEGACY_VERSION) flow.update(json_flow) return flow
def create_flow(self, definition=None, **kwargs): if "org" not in kwargs: kwargs["org"] = self.org if "user" not in kwargs: kwargs["user"] = self.user if "name" not in kwargs: kwargs["name"] = "Color Flow" flow = Flow.create(**kwargs) if not definition: # if definition isn't provided, generate simple single message flow node_uuid = str(uuid4()) definition = { "version": 10, "flow_type": "F", "base_language": "eng", "entry": node_uuid, "action_sets": [ { "uuid": node_uuid, "x": 0, "y": 0, "actions": [ {"msg": {"eng": "Hey everybody!"}, "media": {}, "send_all": False, "type": "reply"} ], "destination": None, } ], "rule_sets": [], } flow.version_number = definition["version"] flow.save() json_flow = FlowRevision.migrate_definition(definition, flow) flow.update(json_flow) return flow
def validate(self, data): class VersionNode: def __init__(self, node, is_ruleset): self.node = node self.uuid = node['uuid'] self.ruleset = is_ruleset def is_ruleset(self): return self.ruleset def is_pause(self): from temba.flows.models import RuleSet return self.node['ruleset_type'] in RuleSet.TYPE_WAIT def get_step_type(self): if self.is_ruleset(): return FlowStep.TYPE_RULE_SET else: return FlowStep.TYPE_ACTION_SET steps = data.get('steps') revision = data.get('revision', data.get('version')) if not revision: # pragma: needs cover raise serializers.ValidationError("Missing 'revision' field") flow_revision = self.flow_obj.revisions.filter( revision=revision).first() if not flow_revision: raise serializers.ValidationError("Invalid revision: %s" % revision) definition = json.loads(flow_revision.definition) # make sure we are operating off a current spec definition = FlowRevision.migrate_definition( definition, self.flow_obj, get_current_export_version()) for step in steps: node_obj = None key = 'rule_sets' if 'rule' in step else 'action_sets' for json_node in definition[key]: if json_node['uuid'] == step['node']: node_obj = VersionNode(json_node, 'rule' in step) break if not node_obj: raise serializers.ValidationError( "No such node with UUID %s in flow '%s'" % (step['node'], self.flow_obj.name)) else: rule = step.get('rule', None) if rule: media = rule.get('media', None) if media: (media_type, media_path) = media.split(':', 1) if media_type != 'geo': media_type_parts = media_type.split('/') error = None if len(media_type_parts) != 2: error = (media_type, media) if media_type_parts[0] not in Msg.MEDIA_TYPES: error = (media_type_parts[0], media) if error: raise serializers.ValidationError( "Invalid media type '%s': %s" % error) step['node'] = node_obj return data
def validate(self, data): class VersionNode: def __init__(self, node, is_ruleset): self.node = node self.uuid = node["uuid"] self.ruleset = is_ruleset def is_ruleset(self): return self.ruleset def is_pause(self): return self.node["ruleset_type"] in RuleSet.TYPE_WAIT steps = data.get("steps") revision = data.get("revision", data.get("version")) if not revision: # pragma: needs cover raise serializers.ValidationError("Missing 'revision' field") flow_revision = self.flow_obj.revisions.filter( revision=revision).first() if not flow_revision: raise serializers.ValidationError("Invalid revision: %s" % revision) definition = flow_revision.definition # make sure we are operating off a current spec definition = FlowRevision.migrate_definition( definition, self.flow_obj, get_current_export_version()) for step in steps: node_obj = None key = "rule_sets" if "rule" in step else "action_sets" for json_node in definition[key]: if json_node["uuid"] == step["node"]: node_obj = VersionNode(json_node, "rule" in step) break if not node_obj: raise serializers.ValidationError( "No such node with UUID %s in flow '%s'" % (step["node"], self.flow_obj.name)) else: rule = step.get("rule", None) if rule: media = rule.get("media", None) if media: (media_type, media_path) = media.split(":", 1) if media_type != "geo": media_type_parts = media_type.split("/") error = None if len(media_type_parts) != 2: error = (media_type, media) if media_type_parts[0] not in Msg.MEDIA_TYPES: error = (media_type_parts[0], media) if error: raise serializers.ValidationError( "Invalid media type '%s': %s" % error) step["node"] = node_obj return data