This is an automated email from the ASF dual-hosted git repository.

beto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 674f234  feat: add logic to creation_method for reports schedule 
(#15685)
674f234 is described below

commit 674f234de6f31f998943b083f37144e3685823be
Author: AAfghahi <[email protected]>
AuthorDate: Thu Jul 15 21:27:54 2021 -0400

    feat: add logic to creation_method for reports schedule (#15685)
    
    * migration
    
    * added logic for creation_method
    
    * revisions
    
    * added index
    
    * Update 
superset/migrations/versions/3317e9248280_add_creation_method_to_reports_model.py
    
    * filters
    
    * Update superset/models/reports.py
    
    Co-authored-by: Beto Dealmeida <[email protected]>
    
    * Update superset/reports/schemas.py
    
    Co-authored-by: Beto Dealmeida <[email protected]>
    
    * Update tests/integration_tests/reports/api_tests.py
    
    Co-authored-by: Beto Dealmeida <[email protected]>
    
    * revisions
    
    Co-authored-by: Beto Dealmeida <[email protected]>
---
 superset/models/reports.py                   |  9 +++
 superset/reports/api.py                      | 11 +++-
 superset/reports/schemas.py                  | 18 ++++++
 tests/integration_tests/reports/api_tests.py | 92 ++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/superset/models/reports.py b/superset/models/reports.py
index 73c74eb..f0bbcac 100644
--- a/superset/models/reports.py
+++ b/superset/models/reports.py
@@ -74,6 +74,12 @@ class ReportDataFormat(str, enum.Enum):
     DATA = "CSV"
 
 
+class ReportCreationMethodType(str, enum.Enum):
+    CHARTS = "charts"
+    DASHBOARDS = "dashboards"
+    ALERTS_REPORTS = "alerts_reports"
+
+
 report_schedule_user = Table(
     "report_schedule_user",
     metadata,
@@ -102,6 +108,9 @@ class ReportSchedule(Model, AuditMixinNullable):
     context_markdown = Column(Text)
     active = Column(Boolean, default=True, index=True)
     crontab = Column(String(1000), nullable=False)
+    creation_method = Column(
+        String(255), server_default=ReportCreationMethodType.ALERTS_REPORTS
+    )
     report_format = Column(String(50), default=ReportDataFormat.VISUALIZATION)
     sql = Column(Text())
     # (Alerts/Reports) M-O to chart
diff --git a/superset/reports/api.py b/superset/reports/api.py
index c9efae1..ccbda74 100644
--- a/superset/reports/api.py
+++ b/superset/reports/api.py
@@ -84,6 +84,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
         "chart.id",
         "chart.slice_name",
         "context_markdown",
+        "creation_method",
         "crontab",
         "dashboard.dashboard_title",
         "dashboard.id",
@@ -123,6 +124,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
         "created_by.first_name",
         "created_by.last_name",
         "created_on",
+        "creation_method",
         "crontab",
         "crontab_humanized",
         "id",
@@ -140,6 +142,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
         "active",
         "chart",
         "context_markdown",
+        "creation_method",
         "crontab",
         "dashboard",
         "database",
@@ -173,7 +176,13 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
         "type",
         "crontab_humanized",
     ]
-    search_columns = ["name", "active", "created_by", "type", "last_state"]
+    search_columns = [
+        "name",
+        "active",
+        "created_by",
+        "type",
+        "last_state",
+    ]
     search_filters = {"name": [ReportScheduleAllTextFilter]}
     allowed_rel_fields = {"owners", "chart", "dashboard", "database", 
"created_by"}
     filter_rel_fields = {
diff --git a/superset/reports/schemas.py b/superset/reports/schemas.py
index 1ea711f..acbb658 100644
--- a/superset/reports/schemas.py
+++ b/superset/reports/schemas.py
@@ -20,8 +20,10 @@ from croniter import croniter
 from flask_babel import gettext as _
 from marshmallow import fields, Schema, validate, validates_schema
 from marshmallow.validate import Length, Range, ValidationError
+from marshmallow_enum import EnumField
 
 from superset.models.reports import (
+    ReportCreationMethodType,
     ReportDataFormat,
     ReportRecipientType,
     ReportScheduleType,
@@ -83,6 +85,10 @@ working_timeout_description = (
     "If an alert is staled at a working state, how long until it's state is 
reseted to"
     " error"
 )
+creation_method_description = (
+    "Creation method is used to inform the frontend whether the report/alert 
was "
+    "created in the dashboard, chart, or alerts and reports UI."
+)
 
 
 def validate_crontab(value: Union[bytes, bytearray, str]) -> None:
@@ -150,6 +156,12 @@ class ReportSchedulePostSchema(Schema):
         description=sql_description, example="SELECT value FROM 
time_series_table"
     )
     chart = fields.Integer(required=False, allow_none=True)
+    creation_method = EnumField(
+        ReportCreationMethodType,
+        by_value=True,
+        required=True,
+        description=creation_method_description,
+    )
     dashboard = fields.Integer(required=False, allow_none=True)
     database = fields.Integer(required=False)
     owners = fields.List(fields.Integer(description=owners_description))
@@ -226,6 +238,12 @@ class ReportSchedulePutSchema(Schema):
         allow_none=True,
     )
     chart = fields.Integer(required=False, allow_none=True)
+    creation_method = EnumField(
+        ReportCreationMethodType,
+        by_value=True,
+        allow_none=True,
+        description=creation_method_description,
+    )
     dashboard = fields.Integer(required=False, allow_none=True)
     database = fields.Integer(required=False)
     owners = fields.List(fields.Integer(description=owners_description), 
required=False)
diff --git a/tests/integration_tests/reports/api_tests.py 
b/tests/integration_tests/reports/api_tests.py
index 995aa22..1fe7106 100644
--- a/tests/integration_tests/reports/api_tests.py
+++ b/tests/integration_tests/reports/api_tests.py
@@ -29,6 +29,7 @@ from superset.models.slice import Slice
 from superset.models.dashboard import Dashboard
 from superset.models.reports import (
     ReportSchedule,
+    ReportCreationMethodType,
     ReportRecipients,
     ReportExecutionLog,
     ReportScheduleType,
@@ -269,6 +270,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "changed_on_delta_humanized",
             "created_by",
             "created_on",
+            "creation_method",
             "crontab",
             "crontab_humanized",
             "id",
@@ -442,6 +444,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "name": "new3",
             "description": "description",
             "crontab": "0 9 * * *",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "recipients": [
                 {
                     "type": ReportRecipientType.EMAIL,
@@ -470,6 +473,7 @@ class TestReportSchedulesApi(SupersetTestCase):
         assert created_model.crontab == report_schedule_data["crontab"]
         assert created_model.chart.id == report_schedule_data["chart"]
         assert created_model.database.id == report_schedule_data["database"]
+        assert created_model.creation_method == 
report_schedule_data["creation_method"]
         # Rollback changes
         db.session.delete(created_model)
         db.session.commit()
@@ -487,6 +491,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "name3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "chart": chart.id,
             "database": example_db.id,
@@ -503,6 +508,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "name": "name3",
             "description": "description",
             "crontab": "0 9 * * *",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "chart": chart.id,
         }
         uri = "api/v1/report/"
@@ -532,6 +538,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.REPORT,
             "name": "name3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "chart": chart.id,
             "database": example_db.id,
@@ -545,6 +552,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "recipients": [
                 {
@@ -569,6 +577,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "recipients": [
                 {
@@ -592,6 +601,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "recipients": [
                 {
@@ -617,6 +627,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new4",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "recipients": [
                 {
@@ -642,6 +653,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new5",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "recipients": [
                 {
@@ -678,6 +690,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "name": "new3",
             "description": "description",
             "crontab": "0 9 * * *",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "chart": chart.id,
             "dashboard": dashboard.id,
             "database": example_db.id,
@@ -701,6 +714,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "chart": chart.id,
         }
@@ -726,6 +740,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "type": ReportScheduleType.ALERT,
             "name": "new3",
             "description": "description",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "crontab": "0 9 * * *",
             "chart": chart_max_id + 1,
             "database": database_max_id + 1,
@@ -748,6 +763,7 @@ class TestReportSchedulesApi(SupersetTestCase):
             "name": "new3",
             "description": "description",
             "crontab": "0 9 * * *",
+            "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
             "dashboard": dashboard_max_id + 1,
             "database": examples_db.id,
         }
@@ -757,6 +773,82 @@ class TestReportSchedulesApi(SupersetTestCase):
         data = json.loads(rv.data.decode("utf-8"))
         assert data == {"message": {"dashboard": "Dashboard does not exist"}}
 
+    @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
+    # TODO (AAfghahi): I am going to enable this when the report schedule 
feature is fully finished
+    # def test_create_report_schedule_no_creation_method(self):
+    #     """
+    #     ReportSchedule Api: Test create report schedule
+    #     """
+    #     self.login(username="admin")
+
+    #     chart = db.session.query(Slice).first()
+    #     example_db = get_example_database()
+    #     report_schedule_data = {
+    #         "type": ReportScheduleType.ALERT,
+    #         "name": "new3",
+    #         "description": "description",
+    #         "crontab": "0 9 * * *",
+    #         "recipients": [
+    #             {
+    #                 "type": ReportRecipientType.EMAIL,
+    #                 "recipient_config_json": {"target": 
"[email protected]"},
+    #             },
+    #             {
+    #                 "type": ReportRecipientType.SLACK,
+    #                 "recipient_config_json": {"target": "channel"},
+    #             },
+    #         ],
+    #         "grace_period": 14400,
+    #         "working_timeout": 3600,
+    #         "chart": chart.id,
+    #         "database": example_db.id,
+    #     }
+    #     uri = "api/v1/report/"
+    #     rv = self.client.post(uri, json=report_schedule_data)
+    #     response = json.loads(rv.data.decode("utf-8"))
+    #     assert response == {
+    #         "message": {"creation_method": ["Missing data for required 
field."]}
+    #     }
+    #     assert rv.status_code == 400
+
+    @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
+    def test_create_report_schedule_invalid_creation_method(self):
+        """
+        ReportSchedule API: Test create report schedule
+        """
+        self.login(username="admin")
+
+        chart = db.session.query(Slice).first()
+        example_db = get_example_database()
+        report_schedule_data = {
+            "type": ReportScheduleType.ALERT,
+            "name": "new3",
+            "description": "description",
+            "creation_method": "BAD_CREATION_METHOD",
+            "crontab": "0 9 * * *",
+            "recipients": [
+                {
+                    "type": ReportRecipientType.EMAIL,
+                    "recipient_config_json": {"target": "[email protected]"},
+                },
+                {
+                    "type": ReportRecipientType.SLACK,
+                    "recipient_config_json": {"target": "channel"},
+                },
+            ],
+            "grace_period": 14400,
+            "working_timeout": 3600,
+            "chart": chart.id,
+            "database": example_db.id,
+        }
+        uri = "api/v1/report/"
+        rv = self.client.post(uri, json=report_schedule_data)
+        response = json.loads(rv.data.decode("utf-8"))
+        assert response == {
+            "message": {"creation_method": ["Invalid enum value 
BAD_CREATION_METHOD"]}
+        }
+        assert rv.status_code == 400
+
     @pytest.mark.usefixtures("create_report_schedules")
     def test_update_report_schedule(self):
         """

Reply via email to