From 54643151ab8ae758579a8792f9f42843a2d79357 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Thu, 15 Jun 2023 12:33:36 +0200 Subject: [PATCH 001/106] =?UTF-8?q?=E2=9C=85=20updated=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/tasks/test_outlook.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/integration/tasks/test_outlook.py b/tests/integration/tasks/test_outlook.py index e957a5620..c34dfc997 100644 --- a/tests/integration/tasks/test_outlook.py +++ b/tests/integration/tasks/test_outlook.py @@ -22,14 +22,13 @@ def to_df(): @pytest.mark.init def test_outlook_to_df(): - outlook = Outlook( mailbox_name=outlook_env_vars["mail_example"], credentials=outlook_env_vars, start_date="2022-04-28", end_date="2022-04-29", ) - df = outlook.to_df() + df = outlook.get_all_mails_to_df() assert isinstance(df, pd.DataFrame) @@ -48,7 +47,7 @@ def test_outlook_credentials(): @mock.patch("O365.Account", return_value=None) @mock.patch("O365.Account.authenticate", return_value="trial1") @mock.patch("O365.Account.mailbox", return_value="trial2") -@mock.patch("viadot.sources.Outlook.to_df", return_calue=to_df) +@mock.patch("viadot.sources.Outlook.get_all_mails_to_df", return_calue=to_df) @pytest.mark.task def test_outlook_task(mock_account, mock_auth, mock_mail, mock_to_df): outlook_to_df = OutlookToDF(credentials=outlook_env_vars) From 3122c5f379ee63a74bee98662a49560d505f604e Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Thu, 15 Jun 2023 17:03:07 +0200 Subject: [PATCH 002/106] =?UTF-8?q?=F0=9F=9A=80=20Bumped=20version=20after?= =?UTF-8?q?=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_viadot.py | 2 +- viadot/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_viadot.py b/tests/test_viadot.py index 31b71febf..5bcee77ba 100644 --- a/tests/test_viadot.py +++ b/tests/test_viadot.py @@ -2,4 +2,4 @@ def test_version(): - assert __version__ == "0.4.17" + assert __version__ == "0.4.18" diff --git a/viadot/__init__.py b/viadot/__init__.py index ac1552129..2dd553604 100644 --- a/viadot/__init__.py +++ b/viadot/__init__.py @@ -1 +1 @@ -__version__ = "0.4.17" +__version__ = "0.4.18" From 18652ae7501af2fc13ade466caf8c80b54dad698 Mon Sep 17 00:00:00 2001 From: gwieloch Date: Tue, 20 Jun 2023 12:42:35 +0200 Subject: [PATCH 003/106] added new connector flows for SAPBW --- CHANGELOG.md | 3 + .../integration/flows/test_sap_bw_to_adls.py | 52 ++++++ tests/integration/tasks/test_sap_bw.py | 175 ++++++++++++++++++ tests/integration/test_sap_bw.py | 39 ++++ viadot/flows/__init__.py | 5 + viadot/flows/sap_bw_to_adls.py | 157 ++++++++++++++++ viadot/sources/__init__.py | 5 + viadot/sources/sap_bw.py | 79 ++++++++ viadot/tasks/__init__.py | 5 + viadot/tasks/sap_bw.py | 138 ++++++++++++++ 10 files changed, 658 insertions(+) create mode 100644 tests/integration/flows/test_sap_bw_to_adls.py create mode 100644 tests/integration/tasks/test_sap_bw.py create mode 100644 tests/integration/test_sap_bw.py create mode 100644 viadot/flows/sap_bw_to_adls.py create mode 100644 viadot/sources/sap_bw.py create mode 100644 viadot/tasks/sap_bw.py diff --git a/CHANGELOG.md b/CHANGELOG.md index a47b74c30..d645df786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added +- Added `SAPBW` source class +- Added `SAPBWToDF` task class +- Added `SAPBWToADLS` flow class ### Fixed diff --git a/tests/integration/flows/test_sap_bw_to_adls.py b/tests/integration/flows/test_sap_bw_to_adls.py new file mode 100644 index 000000000..d63d04e5e --- /dev/null +++ b/tests/integration/flows/test_sap_bw_to_adls.py @@ -0,0 +1,52 @@ +import os +import pandas as pd +import pytest + +from unittest import mock +from viadot.flows import SAPBWToADLS + +DATA = { + "[0CALMONTH].[LEVEL01].[DESCRIPTION]": ["January 2023"], + "date": ["2023-06-19 11:12:43+00:00"], +} + +ADLS_FILE_NAME = "test_sap_bw_to_adls.parquet" +ADLS_DIR_PATH = "raw/tests/" + + +@mock.patch( + "viadot.tasks.SAPBWToDF.run", + return_value=pd.DataFrame(data=DATA), +) +@pytest.mark.run +def test_sap_bw_to_adls_flow_run(mocked_class): + flow = SAPBWToADLS( + "test_sap_bw_to_adls_flow_run", + sapbw_credentials_key="SAP", + env="BW", + mdx_query=""" + SELECT + { + } + ON COLUMNS, + NON EMPTY + { + { [0CALMONTH].[202301] } + } + DIMENSION PROPERTIES + DESCRIPTION, + MEMBER_NAME + ON ROWS + + FROM ZCSALORD1/ZBW4_ZCSALORD1_006_BOA + + """, + mapping_dict={"[0CALMONTH].[LEVEL01].[DESCRIPTION]": "Calendar Year/Month"}, + overwrite_adls=True, + adls_dir_path=ADLS_DIR_PATH, + adls_file_name=ADLS_FILE_NAME, + ) + result = flow.run() + assert result.is_successful() + os.remove("test_sap_bw_to_adls_flow_run.parquet") + os.remove("test_sap_bw_to_adls_flow_run.json") diff --git a/tests/integration/tasks/test_sap_bw.py b/tests/integration/tasks/test_sap_bw.py new file mode 100644 index 000000000..22101a872 --- /dev/null +++ b/tests/integration/tasks/test_sap_bw.py @@ -0,0 +1,175 @@ +import pytest +import pandas as pd +from viadot.tasks import SAPBWToDF +from viadot.task_utils import credentials_loader + +CREDENTIALS = credentials_loader.run(credentials_secret="SAP") +sapbw_task = SAPBWToDF(sapbw_credentials=CREDENTIALS.get("BW")) + + +@pytest.fixture(scope="session") +def output_variable(): + output = ( + { + "RETURN": { + "TYPE": "", + "ID": "", + "NUMBER": "000", + "MESSAGE": "", + "LOG_NO": "", + "LOG_MSG_NO": "000000", + "MESSAGE_V1": "", + "MESSAGE_V2": "", + "MESSAGE_V3": "", + "MESSAGE_V4": "", + "PARAMETER": "", + "ROW": 0, + "FIELD": "", + "SYSTEM": "", + }, + "STATISTIC": {"STEP": "003YPR44RQTVS3BSMZTKDYBMD"}, + "DATA": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "January 2023", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", + }, + { + "COLUMN": 1, + "ROW": 0, + "DATA": "202301", + "VALUE_DATA_TYPE": "NUMC", + "CELL_STATUS": "", + }, + ], + "HEADER": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "[0CALMONTH].[LEVEL01].[DESCRIPTION]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", + }, + { + "COLUMN": 1, + "ROW": 0, + "DATA": "[0CALMONTH].[LEVEL01].[MEMBER_NAME]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", + }, + ], + }, + { + "RETURN": { + "TYPE": "", + "ID": "", + "NUMBER": "000", + "MESSAGE": "", + "LOG_NO": "", + "LOG_MSG_NO": "000000", + "MESSAGE_V1": "", + "MESSAGE_V2": "", + "MESSAGE_V3": "", + "MESSAGE_V4": "", + "PARAMETER": "", + "ROW": 0, + "FIELD": "", + "SYSTEM": "", + }, + "ROWS": 1, + "STATISTIC": {"STEP": "003YPR44RQTVS3BSMZTKE0FH1"}, + "DATA_INFO": [ + { + "COLUMN_ORDINAL": 1, + "FIELD_NAME": "DIM1", + "DATA_TYPE": "CHAR", + "LENGTH": "000060", + "DECIMALS": 0, + }, + { + "COLUMN_ORDINAL": 2, + "FIELD_NAME": "DIM2", + "DATA_TYPE": "NUMC", + "LENGTH": "000006", + "DECIMALS": 0, + }, + ], + "HEADER": [ + { + "COLUMN_ORDINAL": 1, + "ROW_ORDINAL": 1, + "DATA": "[0CALMONTH].[LEVEL01].[DESCRIPTION]", + }, + { + "COLUMN_ORDINAL": 2, + "ROW_ORDINAL": 1, + "DATA": "[0CALMONTH].[LEVEL01].[MEMBER_NAME]", + }, + ], + }, + ) + yield output + + +@pytest.fixture(scope="session") +def user_mapping(): + mapping = { + "[0CALMONTH].[LEVEL01].[DESCRIPTION]": "Calendar Year/Month", + "[0CALMONTH].[LEVEL01].[MEMBER_NAME]": "Calendar Year/Month key", + } + yield mapping + + +@pytest.fixture(scope="session") +def mdx_query_variable(): + mdx_query = """ + SELECT + { + } + ON COLUMNS, + NON EMPTY + { + { [0CALMONTH].[202301] } + } + DIMENSION PROPERTIES + DESCRIPTION, + MEMBER_NAME + ON ROWS + + FROM ZCSALORD1/ZBW4_ZCSALORD1_006_BOA + + """ + yield mdx_query + + +df_to_test = pd.DataFrame( + data={ + "[0CALMONTH].[LEVEL01].[DESCRIPTION]": ["January 2023"], + "[0CALMONTH].[LEVEL01].[MEMBER_NAME]": ["202301"], + "date": ["2023-06-19 11:12:43+00:00"], + }, +) + + +def test_get_columns(output_variable): + df_cols = sapbw_task.get_columns(output_variable) + assert isinstance(df_cols, list) + + +def test_apply_user_mapping(user_mapping): + apply_mapping = sapbw_task.apply_user_mapping(df_to_test, user_mapping) + print(user_mapping.values()) + assert list(apply_mapping.columns) == list(user_mapping.values()) + assert isinstance(apply_mapping, pd.DataFrame) + + +def test_to_df(output_variable): + df = sapbw_task.to_df(output_variable) + assert isinstance(df, pd.DataFrame) + + +def test_run(mdx_query_variable, user_mapping): + df = sapbw_task.run(mdx_query_variable, user_mapping) + assert isinstance(df, pd.DataFrame) diff --git a/tests/integration/test_sap_bw.py b/tests/integration/test_sap_bw.py new file mode 100644 index 000000000..da7c89ebd --- /dev/null +++ b/tests/integration/test_sap_bw.py @@ -0,0 +1,39 @@ +import pytest +from viadot.sources import SAPBW +from viadot.task_utils import credentials_loader + + +CREDENTIALS = credentials_loader.run(credentials_secret="SAP") +SAPBW = SAPBW(credentials=CREDENTIALS.get("BW")) + + +@pytest.fixture(scope="session") +def mdx_query_variable(): + mdx_query = """ + SELECT + { + } + ON COLUMNS, + NON EMPTY + { + { [0CALMONTH].[202301] } + } + DIMENSION PROPERTIES + DESCRIPTION, + MEMBER_NAME + ON ROWS + + FROM ZCSALORD1/ZBW4_ZCSALORD1_006_BOA + + """ + yield mdx_query + + +def test_get_all_available_columns(mdx_query_variable): + all_available_columns = SAPBW.get_all_available_columns(mdx_query_variable) + assert isinstance(all_available_columns, list) + + +def test_get_output_data(mdx_query_variable): + columns = SAPBW.get_output_data(mdx_query_variable) + assert isinstance(columns, list) diff --git a/viadot/flows/__init__.py b/viadot/flows/__init__.py index f91cd087c..f485053bd 100644 --- a/viadot/flows/__init__.py +++ b/viadot/flows/__init__.py @@ -30,6 +30,11 @@ except ImportError: pass +try: + from .sap_bw_to_adls import SAPBWToADLS +except ImportError: + pass + from .customer_gauge_to_adls import CustomerGaugeToADLS from .epicor_to_duckdb import EpicorOrdersToDuckDB from .eurostat_to_adls import EurostatToADLS diff --git a/viadot/flows/sap_bw_to_adls.py b/viadot/flows/sap_bw_to_adls.py new file mode 100644 index 000000000..8425e170b --- /dev/null +++ b/viadot/flows/sap_bw_to_adls.py @@ -0,0 +1,157 @@ +import os +import pendulum +from pathlib import Path +from typing import Any, Dict, List, Literal +from prefect import Flow +from prefect.backend import set_key_value + +from viadot.task_utils import ( + df_to_parquet, + add_ingestion_metadata_task, + df_get_data_types_task, + df_map_mixed_dtypes_for_parquet, + update_dtypes_dict, + dtypes_to_json_task, +) +from viadot.tasks import AzureDataLakeUpload, SAPBWToDF + + +class SAPBWToADLS(Flow): + def __init__( + self, + name: str, + mdx_query: str = None, + mapping_dict: dict = None, + sapbw_credentials: dict = None, + sapbw_credentials_key: str = "SAP", + env: str = "BW", + output_file_extension: str = ".parquet", + local_file_path: str = None, + adls_file_name: str = None, + adls_dir_path: str = None, + if_exists: Literal["replace", "append", "delete"] = "replace", + overwrite_adls: bool = True, + vault_name: str = None, + sp_credentials_secret: str = None, + *args: List[any], + **kwargs: Dict[str, Any], + ): + """ + Flow for downloading data from SAP BW to file, then uploading it to ADLS. + + Args: + name (str): Name of the flow. + mdx_query (str, optional): MDX query to be passed to SAP BW server. Defaults to None. + mapping_dict (dict, optional): Dictionary with original column names and the mapping for them. If not None then flows is generating mapping automatically with mapping applied by user, if not - it generates automaticaly the json file with columns. + sapbw_credentials (dict, optional): Credentials to SAP in dictionary format. Defaults to None. + sapbw_credentials_key (str, optional): Azure KV secret. Defaults to "SAP". + env (str, optional): SAP environment. Defaults to "BW". + output_file_extension (str, optional): Output file extension - to allow selection of .csv for data which is not easy to handle with parquet. Defaults to ".parquet". + local_file_path (str, optional): Local destination path. Defaults to None. + adls_file_name (str, optional): Azure Data Lake file name. Defaults to None. + adls_dir_path(str, optional): Azure Data Lake destination file path. Defaults to None. + if_exists (Literal["append", "replace", "skip"], optional): What to do if the table exists. Defaults to "replace". + overwrite_adls (bool, optional): Whether to overwrite the file in ADLS. Defaults to True. + vault_name (str, optional): The name of the vault from which to obtain the secrets.. Defaults to None. + sp_credentials_secret (str, optional): The name of the Azure Key Vault secret containing a dictionary with ACCOUNT_NAME and Service Principal credentials (TENANT_ID, CLIENT_ID, CLIENT_SECRET). Defaults to None. + """ + self.sapbw_credentials = sapbw_credentials + self.sapbw_credentials_key = sapbw_credentials_key + self.env = env + self.mdx_query = mdx_query + self.mapping_dict = mapping_dict + self.output_file_extension = output_file_extension + + self.local_file_path = ( + local_file_path or self.slugify(name) + self.output_file_extension + ) + self.local_json_path = self.slugify(name) + ".json" + self.now = str(pendulum.now("utc")) + self.adls_dir_path = adls_dir_path + + if adls_file_name is not None: + self.adls_file_path = os.path.join(adls_dir_path, adls_file_name) + self.adls_schema_file_dir_file = os.path.join( + adls_dir_path, "schema", Path(adls_file_name).stem + ".json" + ) + + else: + self.adls_file_path = os.path.join( + adls_dir_path, self.now + self.output_file_extension + ) + self.adls_schema_file_dir_file = os.path.join( + adls_dir_path, "schema", self.now + ".json" + ) + + self.if_exists = if_exists + self.overwrite_adls = overwrite_adls + self.vault_name = vault_name + self.sp_credentials_secret = sp_credentials_secret + + super().__init__(*args, name=name, **kwargs) + self.gen_flow() + + @staticmethod + def slugify(name): + return name.replace(" ", "_").lower() + + def gen_flow(self) -> Flow: + sapbw_to_df_task = SAPBWToDF( + sapbw_credentials=self.sapbw_credentials, + sapbw_credentials_key=self.sapbw_credentials_key, + env=self.env, + ) + + df = sapbw_to_df_task.bind( + mdx_query=self.mdx_query, + mapping_dict=self.mapping_dict, + flow=self, + ) + + df_viadot_downloaded = add_ingestion_metadata_task.bind(df=df, flow=self) + dtypes_dict = df_get_data_types_task.bind(df_viadot_downloaded, flow=self) + + df_to_be_loaded = df_map_mixed_dtypes_for_parquet( + df_viadot_downloaded, dtypes_dict, flow=self + ) + + df_to_parquet_task = df_to_parquet.bind( + df=df_to_be_loaded, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + + file_to_adls_task = AzureDataLakeUpload() + adls_upload = file_to_adls_task.bind( + from_path=self.local_file_path, + to_path=self.adls_file_path, + overwrite=self.overwrite_adls, + sp_credentials_secret=self.sp_credentials_secret, + flow=self, + ) + + dtypes_updated = update_dtypes_dict(dtypes_dict, flow=self) + dtypes_to_json_task.bind( + dtypes_dict=dtypes_updated, local_json_path=self.local_json_path, flow=self + ) + + json_to_adls_task = AzureDataLakeUpload() + json_to_adls_task.bind( + from_path=self.local_json_path, + to_path=self.adls_schema_file_dir_file, + overwrite=self.overwrite_adls, + sp_credentials_secret=self.sp_credentials_secret, + vault_name=self.vault_name, + flow=self, + ) + + df_viadot_downloaded.set_upstream(df, flow=self) + dtypes_dict.set_upstream(df_viadot_downloaded, flow=self) + df_to_be_loaded.set_upstream(dtypes_dict, flow=self) + adls_upload.set_upstream(df_to_parquet_task, flow=self) + + dtypes_to_json_task.set_upstream(dtypes_updated, flow=self) + json_to_adls_task.set_upstream(dtypes_to_json_task, flow=self) + + set_key_value(key=self.adls_dir_path, value=self.adls_file_path) diff --git a/viadot/sources/__init__.py b/viadot/sources/__init__.py index 267fcbb35..094cec14e 100644 --- a/viadot/sources/__init__.py +++ b/viadot/sources/__init__.py @@ -16,6 +16,11 @@ except ImportError: pass +try: + from .sap_bw import SAPBW +except ImportError: + pass + from .business_core import BusinessCore from .customer_gauge import CustomerGauge from .duckdb import DuckDB diff --git a/viadot/sources/sap_bw.py b/viadot/sources/sap_bw.py new file mode 100644 index 000000000..b77f299d2 --- /dev/null +++ b/viadot/sources/sap_bw.py @@ -0,0 +1,79 @@ +from typing import List +from viadot.sources.base import Source +from viadot.exceptions import CredentialError +from pyrfc import Connection +import textwrap + + +class SAPBW(Source): + """ + A class for quering the SAP BW (SAP Business Warehouse) source using pyrfc library. + Documentation to pyrfc can be found under: https://sap.github.io/PyRFC/pyrfc.html + Documentation for SAP connection modules under: https://www.se80.co.uk/sap-function-modules/list/?index=rsr_mdx + + """ + + def __init__(self, credentials: dict, *args, **kwargs): + self.credentials = credentials + if credentials is None: + raise CredentialError("Missing credentials.") + + super().__init__(*args, credentials=self.credentials, **kwargs) + + def get_connection(self) -> Connection: + """ + Function to create the connection with SAP BW. + + Returns: + Connection: Connection to SAP. + """ + return Connection( + ashost=self.credentials.get("ashost"), + sysnr=self.credentials.get("sysnr"), + user=self.credentials.get("user"), + passwd=self.credentials.get("passwd"), + client=self.credentials.get("client"), + ) + + def get_all_available_columns(self, mdx_query: str = None) -> List: + """ + Function to generate list of all available columns in the SAP table based on passed MDX query. + + Args: + mdx_query (str, optional): The MDX query to be passed to connection. Defaults to []. + + Returns: + List: List of all available columns in the source table. + """ + conn = self.get_connection() + query = textwrap.wrap(mdx_query, 75) + properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) + datasetid = properties["DATASETID"] + + get_axis_info = conn.call( + "RSR_MDX_GET_AXIS_INFO", DATASETID=datasetid + ) # listing all of available columns and metrics + cols = get_axis_info["AXIS_DIMENSIONS"] + + all_available_columns = [x["DIM_UNAM"] for x in cols] + return all_available_columns + + def get_output_data(self, mdx_query: str = None) -> List: + """ + Function to generate the SAP output dataset from MDX query. + + Args: + mdx_query (str, optional): The MDX query to be passed to connection. Defaults to []. + + Returns: + List: (query_output, columns): Set of query output in dictionary format and list of output columns to be passed to final dataframe. + """ + conn = self.get_connection() + query = textwrap.wrap(mdx_query, 75) + properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) + datasetid = properties["DATASETID"] + + query_output = conn.call("RSR_MDX_GET_FLAT_DATA", DATASETID=datasetid) + + columns = conn.call("RSR_MDX_BXML_GET_INFO", DATASETID=datasetid) + return [query_output, columns] diff --git a/viadot/tasks/__init__.py b/viadot/tasks/__init__.py index ad9cefa5d..4aded8cbe 100644 --- a/viadot/tasks/__init__.py +++ b/viadot/tasks/__init__.py @@ -40,6 +40,11 @@ except ImportError: pass +try: + from .sap_bw import SAPBWToDF +except ImportError: + pass + from .business_core import BusinessCoreToParquet from .customer_gauge import CustomerGaugeToDF from .duckdb import DuckDBCreateTableFromParquet, DuckDBQuery, DuckDBToDF diff --git a/viadot/tasks/sap_bw.py b/viadot/tasks/sap_bw.py new file mode 100644 index 000000000..583862cfd --- /dev/null +++ b/viadot/tasks/sap_bw.py @@ -0,0 +1,138 @@ +import pandas as pd + + +from typing import List, Dict, Any, Literal +from prefect import Task +from prefect.tasks.secrets import PrefectSecret +from prefect.utilities import logging +from viadot.exceptions import ValidationError +from viadot.sources import SAPBW +from viadot.task_utils import * + +logger = logging.get_logger() + + +class SAPBWToDF(Task): + def __init__( + self, + sapbw_credentials: dict = None, + sapbw_credentials_key: str = "SAP", + env: str = "BW", + *args, + **kwargs, + ): + """ + A task for quering the SAP BW (SAP Business Warehouse) source using pyrfc library. + + Args: + sapbw_credentials (dict, optional): Credentials to SAP BW server. Defaults to None. + sapbw_credentials_key (str, optional): Azure KV secret. Defaults to "SAP". + env (str, optional): SAP environment. Defaults to "BW". + """ + if sapbw_credentials is None: + self.sapbw_credentials = credentials_loader.run( + credentials_secret=sapbw_credentials_key + ) + self.sapbw_credentials = self.sapbw_credentials[env] + + else: + self.sapbw_credentials = sapbw_credentials + + super().__init__( + name="sapbw_to_df", + *args, + **kwargs, + ) + + def __call__(self): + """Download SAP BW data to a DF""" + super().__call__(self) + + def get_columns(self, json_data: List = []) -> List: + """ + Function to generate the column list to be passed as DataFrame headers. + + Args: + json_data (List, optional): Input DataFrame and column list as list. Defaults to []. + + Returns: + List: Columns list. + """ + columns = json_data[1] + df_cols = [x["DATA"] for x in columns["HEADER"]] + return df_cols + + def apply_user_mapping( + self, df: pd.DataFrame, mapping_dict: dict = {} + ) -> pd.DataFrame: + """ + Function to apply the column mapping defined by user for the output dataframe. + DataFrame will be cut to selected columns - if any other columns need to be included in the output file, + please add them to the mapping dictionary with original names. + + Args: + df (pd.DataFrame): Input dataframe for the column mapping task. + mapping_dict (dict, optional): Dictionary with original and new column names. Defaults to {}. + + Returns: + pd.DataFrame: Output DataFrame with mapped columns. + """ + self.logger.info("Applying user defined mapping for columns. Starting task...") + df = df[mapping_dict.keys()] + df.columns = mapping_dict.values() + + self.logger.info(f"Successfully applied user mapping.") + + return df + + def to_df(self, json_data: dict = {}) -> pd.DataFrame: + """ + Function to convert the SAP output into a dataframe. + + Args: + json_data (dict, optional): Output from teh SAP in json format. Defaults to {}. + + Returns: + pd.DataFrame: Output dataframe. + """ + rows = {} + if "DATA" in json_data[0]: + if len(json_data[0]["DATA"]) > 0: + results = json_data[0]["DATA"] + for cell in results: + if cell["ROW"] not in rows: + rows[cell["ROW"]] = {} + if "].[" not in cell["DATA"]: + rows[cell["ROW"]][cell["COLUMN"]] = cell["DATA"] + + else: + issue_value = str(json_data[0]["RETURN"]["MESSAGE"]) + self.logger.warning(f"---------- {issue_value} --------") + else: + self.logger.warning("No data produced by the query.") + + rows = [rows[row] for row in rows] + df = pd.DataFrame(rows) + df.columns = self.get_columns(json_data) + return df + + def run(self, mdx_query: str = None, mapping_dict: dict = {}) -> pd.DataFrame: + """ + Task run method. + + Args: + mdx_query (str, optional): MDX query to be passed to SAP BW. Defaults to None. + mapping_dict (dict, optional): Mapping dictionary from user in json format. Defaults to {}. + + Returns: + pd.DataFrame: Output DataFrame with applied column mapping. + """ + sap = SAPBW(credentials=self.sapbw_credentials) + + data = sap.get_output_data(mdx_query) + df = self.to_df(data) + + if mapping_dict: + df = self.apply_user_mapping(df, mapping_dict) + + return df From d009a5a5cba3f3f7d41271ae55d8af05b1e884e2 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Wed, 21 Jun 2023 13:41:24 +0200 Subject: [PATCH 004/106] =?UTF-8?q?=F0=9F=90=9B=20fixed=20the=20extra=20se?= =?UTF-8?q?parator=20and=20long=20strings=20in=20rows.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/sources/outlook.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/viadot/sources/outlook.py b/viadot/sources/outlook.py index 86caff298..dd760fe39 100644 --- a/viadot/sources/outlook.py +++ b/viadot/sources/outlook.py @@ -182,10 +182,13 @@ def _get_messages_from_mailbox( recivers_list = fetched.get("toRecipients") recivers = " " if recivers_list is not None: - recivers = ", ".join( - reciver["emailAddress"]["address"] - for reciver in recivers_list - ) + for reciver in recivers_list: + add_string = f", {reciver['emailAddress']['address']}" + if sum(list(map(len, [recivers, add_string]))) >= 8000: + break + else: + recivers += add_string + categories = " " if message.categories is not None: categories = ", ".join( @@ -194,14 +197,18 @@ def _get_messages_from_mailbox( conversation_index = " " if message.conversation_index is not None: conversation_index = message.conversation_index + if isinstance(message.subject, str): + subject = message.subject.replace("\t", " ") + else: + subject = message.subject row = { "(sub)folder": value.name, "conversation ID": fetched.get("conversationId"), "conversation index": conversation_index, "categories": categories, "sender": sender_mail, - "subject": message.subject, - "recivers": recivers, + "subject": subject, + "recivers": recivers.strip(", "), "received_time": fetched.get("receivedDateTime"), "mail_adress": self.mailbox_name.split("@")[0] .replace(".", "_") From d9c8af2dd682a9e6147eb8d1e496db2c89e89c37 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Wed, 21 Jun 2023 13:53:39 +0200 Subject: [PATCH 005/106] =?UTF-8?q?=F0=9F=93=9D=20updated=20CHANGELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a47b74c30..e2024ff52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### Fixed +- Fixed a bug in `subject` (extra separator) and in `receivers` (long strings) parameters in Outlook connector. ### Changed From a9314f1a2198ad6a14f98e354e5f85f11b6b9a66 Mon Sep 17 00:00:00 2001 From: gwieloch Date: Tue, 27 Jun 2023 16:28:27 +0200 Subject: [PATCH 006/106] added changed after review --- viadot/flows/sap_bw_to_adls.py | 31 ++++++++++++------- viadot/sources/sap_bw.py | 56 ++++++++++++++++++++++++++-------- viadot/tasks/sap_bw.py | 52 +++++++++++-------------------- 3 files changed, 82 insertions(+), 57 deletions(-) diff --git a/viadot/flows/sap_bw_to_adls.py b/viadot/flows/sap_bw_to_adls.py index 8425e170b..d0f0c9acb 100644 --- a/viadot/flows/sap_bw_to_adls.py +++ b/viadot/flows/sap_bw_to_adls.py @@ -7,6 +7,7 @@ from viadot.task_utils import ( df_to_parquet, + df_to_csv, add_ingestion_metadata_task, df_get_data_types_task, df_map_mixed_dtypes_for_parquet, @@ -42,11 +43,11 @@ def __init__( Args: name (str): Name of the flow. mdx_query (str, optional): MDX query to be passed to SAP BW server. Defaults to None. - mapping_dict (dict, optional): Dictionary with original column names and the mapping for them. If not None then flows is generating mapping automatically with mapping applied by user, if not - it generates automaticaly the json file with columns. + mapping_dict (dict, optional): Dictionary with original column names and the mapping for them. If not None then flows is generating mapping automatically with mapping applied by user, if not - it generates automatically the json file with columns. sapbw_credentials (dict, optional): Credentials to SAP in dictionary format. Defaults to None. sapbw_credentials_key (str, optional): Azure KV secret. Defaults to "SAP". env (str, optional): SAP environment. Defaults to "BW". - output_file_extension (str, optional): Output file extension - to allow selection of .csv for data which is not easy to handle with parquet. Defaults to ".parquet". + output_file_extension (str, optional): Output file extension - to allow selection between .csv and .parquet. Defaults to ".parquet". local_file_path (str, optional): Local destination path. Defaults to None. adls_file_name (str, optional): Azure Data Lake file name. Defaults to None. adls_dir_path(str, optional): Azure Data Lake destination file path. Defaults to None. @@ -111,16 +112,24 @@ def gen_flow(self) -> Flow: df_viadot_downloaded = add_ingestion_metadata_task.bind(df=df, flow=self) dtypes_dict = df_get_data_types_task.bind(df_viadot_downloaded, flow=self) - df_to_be_loaded = df_map_mixed_dtypes_for_parquet( + df_to_be_loaded = df_map_mixed_dtypes_for_parquet.bind( df_viadot_downloaded, dtypes_dict, flow=self ) - df_to_parquet_task = df_to_parquet.bind( - df=df_to_be_loaded, - path=self.local_file_path, - if_exists=self.if_exists, - flow=self, - ) + if self.output_file_extension == ".parquet": + df_to_file = df_to_parquet.bind( + df=df_to_be_loaded, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + else: + df_to_file = df_to_csv.bind( + df=df_to_be_loaded, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) file_to_adls_task = AzureDataLakeUpload() adls_upload = file_to_adls_task.bind( @@ -149,9 +158,9 @@ def gen_flow(self) -> Flow: df_viadot_downloaded.set_upstream(df, flow=self) dtypes_dict.set_upstream(df_viadot_downloaded, flow=self) df_to_be_loaded.set_upstream(dtypes_dict, flow=self) - adls_upload.set_upstream(df_to_parquet_task, flow=self) + adls_upload.set_upstream(df_to_file, flow=self) - dtypes_to_json_task.set_upstream(dtypes_updated, flow=self) + df_to_file.set_upstream(dtypes_updated, flow=self) json_to_adls_task.set_upstream(dtypes_to_json_task, flow=self) set_key_value(key=self.adls_dir_path, value=self.adls_file_path) diff --git a/viadot/sources/sap_bw.py b/viadot/sources/sap_bw.py index b77f299d2..a3706c270 100644 --- a/viadot/sources/sap_bw.py +++ b/viadot/sources/sap_bw.py @@ -14,11 +14,10 @@ class SAPBW(Source): """ def __init__(self, credentials: dict, *args, **kwargs): - self.credentials = credentials if credentials is None: raise CredentialError("Missing credentials.") - super().__init__(*args, credentials=self.credentials, **kwargs) + super().__init__(*args, credentials=credentials, **kwargs) def get_connection(self) -> Connection: """ @@ -40,13 +39,16 @@ def get_all_available_columns(self, mdx_query: str = None) -> List: Function to generate list of all available columns in the SAP table based on passed MDX query. Args: - mdx_query (str, optional): The MDX query to be passed to connection. Defaults to []. + mdx_query (str, optional): The MDX query to be passed to connection. Defaults to None. Returns: - List: List of all available columns in the source table. + all_available_columns: List of all available columns in the source table. """ conn = self.get_connection() - query = textwrap.wrap(mdx_query, 75) + query = textwrap.wrap( + mdx_query, width=75 + ) # width = 75, to properly split mdx query into substrings passed to SAP object creation function + properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) datasetid = properties["DATASETID"] @@ -58,22 +60,52 @@ def get_all_available_columns(self, mdx_query: str = None) -> List: all_available_columns = [x["DIM_UNAM"] for x in cols] return all_available_columns - def get_output_data(self, mdx_query: str = None) -> List: + def get_output_data(self, mdx_query: str = None) -> dict: """ Function to generate the SAP output dataset from MDX query. Args: - mdx_query (str, optional): The MDX query to be passed to connection. Defaults to []. + mdx_query (str, optional): The MDX query to be passed to connection. Defaults to None. Returns: - List: (query_output, columns): Set of query output in dictionary format and list of output columns to be passed to final dataframe. + query_output: SAP output dictionary in JSON format that contains data rows and column headers. + + Example output: + + { + "RETURN": { + "TYPE": "", + "ID": "", + "NUMBER": "000", + "MESSAGE": "",... + },... + "DATA": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "VELUX Deutschland GmbH", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "" + },... + ], + "HEADER": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "[0COMP_CODE].[LEVEL01].[DESCRIPTION]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "" + },... + ] + } + """ conn = self.get_connection() - query = textwrap.wrap(mdx_query, 75) + query = textwrap.wrap( + mdx_query, 75 + ) # width = 75, to properly split mdx query into substrings passed to SAP object creation function properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) datasetid = properties["DATASETID"] - query_output = conn.call("RSR_MDX_GET_FLAT_DATA", DATASETID=datasetid) - columns = conn.call("RSR_MDX_BXML_GET_INFO", DATASETID=datasetid) - return [query_output, columns] + return query_output diff --git a/viadot/tasks/sap_bw.py b/viadot/tasks/sap_bw.py index 583862cfd..a8f3e0e04 100644 --- a/viadot/tasks/sap_bw.py +++ b/viadot/tasks/sap_bw.py @@ -48,20 +48,6 @@ def __call__(self): """Download SAP BW data to a DF""" super().__call__(self) - def get_columns(self, json_data: List = []) -> List: - """ - Function to generate the column list to be passed as DataFrame headers. - - Args: - json_data (List, optional): Input DataFrame and column list as list. Defaults to []. - - Returns: - List: Columns list. - """ - columns = json_data[1] - df_cols = [x["DATA"] for x in columns["HEADER"]] - return df_cols - def apply_user_mapping( self, df: pd.DataFrame, mapping_dict: dict = {} ) -> pd.DataFrame: @@ -77,7 +63,7 @@ def apply_user_mapping( Returns: pd.DataFrame: Output DataFrame with mapped columns. """ - self.logger.info("Applying user defined mapping for columns. Starting task...") + self.logger.info("Applying user defined mapping for columns...") df = df[mapping_dict.keys()] df.columns = mapping_dict.values() @@ -85,35 +71,33 @@ def apply_user_mapping( return df - def to_df(self, json_data: dict = {}) -> pd.DataFrame: + def to_df(self, query_output: dict = {}) -> pd.DataFrame: """ - Function to convert the SAP output into a dataframe. + Function to convert the SAP output in JSON format into a dataframe. Args: - json_data (dict, optional): Output from teh SAP in json format. Defaults to {}. + query_output: SAP output dictionary in JSON format that contains data rows and column headers. Defaults to {}. Returns: pd.DataFrame: Output dataframe. """ rows = {} - if "DATA" in json_data[0]: - if len(json_data[0]["DATA"]) > 0: - results = json_data[0]["DATA"] - for cell in results: - if cell["ROW"] not in rows: - rows[cell["ROW"]] = {} - if "].[" not in cell["DATA"]: - rows[cell["ROW"]][cell["COLUMN"]] = cell["DATA"] - - else: - issue_value = str(json_data[0]["RETURN"]["MESSAGE"]) - self.logger.warning(f"---------- {issue_value} --------") + + if query_output["RETURN"]["MESSAGE"] == "": + results = query_output["DATA"] + for cell in results: + if cell["ROW"] not in rows: + rows[cell["ROW"]] = {} + if "].[" not in cell["DATA"]: + rows[cell["ROW"]][cell["COLUMN"]] = cell["DATA"] + df_rows = [rows[row] for row in rows] + df_cols = [x["DATA"] for x in query_output["HEADER"]] + df = pd.DataFrame(data=df_rows) + df.columns = df_cols else: - self.logger.warning("No data produced by the query.") + df = pd.DataFrame() + raise ValidationError(query_output["RETURN"]["MESSAGE"]) - rows = [rows[row] for row in rows] - df = pd.DataFrame(rows) - df.columns = self.get_columns(json_data) return df def run(self, mdx_query: str = None, mapping_dict: dict = {}) -> pd.DataFrame: From f4aed464aeb10278928da7e15e017850e1125db8 Mon Sep 17 00:00:00 2001 From: gwieloch Date: Tue, 27 Jun 2023 16:36:45 +0200 Subject: [PATCH 007/106] updated tests for sap_bw --- tests/integration/tasks/test_sap_bw.py | 149 ++++++++----------------- tests/integration/test_sap_bw.py | 4 +- 2 files changed, 49 insertions(+), 104 deletions(-) diff --git a/tests/integration/tasks/test_sap_bw.py b/tests/integration/tasks/test_sap_bw.py index 22101a872..dd1dfdeb1 100644 --- a/tests/integration/tasks/test_sap_bw.py +++ b/tests/integration/tasks/test_sap_bw.py @@ -9,107 +9,57 @@ @pytest.fixture(scope="session") def output_variable(): - output = ( - { - "RETURN": { - "TYPE": "", - "ID": "", - "NUMBER": "000", - "MESSAGE": "", - "LOG_NO": "", - "LOG_MSG_NO": "000000", - "MESSAGE_V1": "", - "MESSAGE_V2": "", - "MESSAGE_V3": "", - "MESSAGE_V4": "", - "PARAMETER": "", + output = { + "RETURN": { + "TYPE": "", + "ID": "", + "NUMBER": "000", + "MESSAGE": "", + "LOG_NO": "", + "LOG_MSG_NO": "000000", + "MESSAGE_V1": "", + "MESSAGE_V2": "", + "MESSAGE_V3": "", + "MESSAGE_V4": "", + "PARAMETER": "", + "ROW": 0, + "FIELD": "", + "SYSTEM": "", + }, + "STATISTIC": {"STEP": "003YPR44RQTVS3BSMZTKDYBMD"}, + "DATA": [ + { + "COLUMN": 0, "ROW": 0, - "FIELD": "", - "SYSTEM": "", + "DATA": "January 2023", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", }, - "STATISTIC": {"STEP": "003YPR44RQTVS3BSMZTKDYBMD"}, - "DATA": [ - { - "COLUMN": 0, - "ROW": 0, - "DATA": "January 2023", - "VALUE_DATA_TYPE": "CHAR", - "CELL_STATUS": "", - }, - { - "COLUMN": 1, - "ROW": 0, - "DATA": "202301", - "VALUE_DATA_TYPE": "NUMC", - "CELL_STATUS": "", - }, - ], - "HEADER": [ - { - "COLUMN": 0, - "ROW": 0, - "DATA": "[0CALMONTH].[LEVEL01].[DESCRIPTION]", - "VALUE_DATA_TYPE": "CHAR", - "CELL_STATUS": "", - }, - { - "COLUMN": 1, - "ROW": 0, - "DATA": "[0CALMONTH].[LEVEL01].[MEMBER_NAME]", - "VALUE_DATA_TYPE": "CHAR", - "CELL_STATUS": "", - }, - ], - }, - { - "RETURN": { - "TYPE": "", - "ID": "", - "NUMBER": "000", - "MESSAGE": "", - "LOG_NO": "", - "LOG_MSG_NO": "000000", - "MESSAGE_V1": "", - "MESSAGE_V2": "", - "MESSAGE_V3": "", - "MESSAGE_V4": "", - "PARAMETER": "", + { + "COLUMN": 1, "ROW": 0, - "FIELD": "", - "SYSTEM": "", + "DATA": "202301", + "VALUE_DATA_TYPE": "NUMC", + "CELL_STATUS": "", }, - "ROWS": 1, - "STATISTIC": {"STEP": "003YPR44RQTVS3BSMZTKE0FH1"}, - "DATA_INFO": [ - { - "COLUMN_ORDINAL": 1, - "FIELD_NAME": "DIM1", - "DATA_TYPE": "CHAR", - "LENGTH": "000060", - "DECIMALS": 0, - }, - { - "COLUMN_ORDINAL": 2, - "FIELD_NAME": "DIM2", - "DATA_TYPE": "NUMC", - "LENGTH": "000006", - "DECIMALS": 0, - }, - ], - "HEADER": [ - { - "COLUMN_ORDINAL": 1, - "ROW_ORDINAL": 1, - "DATA": "[0CALMONTH].[LEVEL01].[DESCRIPTION]", - }, - { - "COLUMN_ORDINAL": 2, - "ROW_ORDINAL": 1, - "DATA": "[0CALMONTH].[LEVEL01].[MEMBER_NAME]", - }, - ], - }, - ) + ], + "HEADER": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "[0CALMONTH].[LEVEL01].[DESCRIPTION]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", + }, + { + "COLUMN": 1, + "ROW": 0, + "DATA": "[0CALMONTH].[LEVEL01].[MEMBER_NAME]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "", + }, + ], + } yield output @@ -153,11 +103,6 @@ def mdx_query_variable(): ) -def test_get_columns(output_variable): - df_cols = sapbw_task.get_columns(output_variable) - assert isinstance(df_cols, list) - - def test_apply_user_mapping(user_mapping): apply_mapping = sapbw_task.apply_user_mapping(df_to_test, user_mapping) print(user_mapping.values()) diff --git a/tests/integration/test_sap_bw.py b/tests/integration/test_sap_bw.py index da7c89ebd..f087603cc 100644 --- a/tests/integration/test_sap_bw.py +++ b/tests/integration/test_sap_bw.py @@ -35,5 +35,5 @@ def test_get_all_available_columns(mdx_query_variable): def test_get_output_data(mdx_query_variable): - columns = SAPBW.get_output_data(mdx_query_variable) - assert isinstance(columns, list) + query_output = SAPBW.get_output_data(mdx_query_variable) + assert isinstance(query_output, dict) From 902d00e1781a54f7025a210efe70299068ead549 Mon Sep 17 00:00:00 2001 From: gwieloch Date: Wed, 28 Jun 2023 11:51:08 +0200 Subject: [PATCH 008/106] updated sap_bw source file --- viadot/sources/sap_bw.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/viadot/sources/sap_bw.py b/viadot/sources/sap_bw.py index a3706c270..d3765ff39 100644 --- a/viadot/sources/sap_bw.py +++ b/viadot/sources/sap_bw.py @@ -1,6 +1,6 @@ from typing import List from viadot.sources.base import Source -from viadot.exceptions import CredentialError +from viadot.exceptions import CredentialError, ValidationError from pyrfc import Connection import textwrap @@ -49,15 +49,20 @@ def get_all_available_columns(self, mdx_query: str = None) -> List: mdx_query, width=75 ) # width = 75, to properly split mdx query into substrings passed to SAP object creation function - properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) + properties = conn.call("RSR_MDX_CREATE_STORED_OBJECT", COMMAND_TEXT=query) datasetid = properties["DATASETID"] - get_axis_info = conn.call( - "RSR_MDX_GET_AXIS_INFO", DATASETID=datasetid - ) # listing all of available columns and metrics - cols = get_axis_info["AXIS_DIMENSIONS"] + if properties["RETURN"]["MESSAGE"] == "": + get_axis_info = conn.call( + "RSR_MDX_GET_AXIS_INFO", DATASETID=datasetid + ) # listing all of available columns and metrics + cols = get_axis_info["AXIS_DIMENSIONS"] + + all_available_columns = [x["DIM_UNAM"] for x in cols] + else: + all_available_columns = [] + self.logger.error(properties["RETURN"]["MESSAGE"]) - all_available_columns = [x["DIM_UNAM"] for x in cols] return all_available_columns def get_output_data(self, mdx_query: str = None) -> dict: @@ -105,7 +110,11 @@ def get_output_data(self, mdx_query: str = None) -> dict: mdx_query, 75 ) # width = 75, to properly split mdx query into substrings passed to SAP object creation function properties = conn.call("RSR_MDX_CREATE_OBJECT", COMMAND_TEXT=query) + datasetid = properties["DATASETID"] query_output = conn.call("RSR_MDX_GET_FLAT_DATA", DATASETID=datasetid) + # if properties["RETURN"]["MESSAGE"] != "": + # self.logger.error(properties["RETURN"]["MESSAGE"]) + return query_output From 94e4043fe72966f8b9d7ec3492479773f77381a4 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 30 Jun 2023 08:30:08 +0200 Subject: [PATCH 009/106] =?UTF-8?q?=F0=9F=93=9D=20updated=20CHANGELOG.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a47b74c30..a8c0b1853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added +- Added a new `end_point` parameter in `genesys_api_connection` to make it more generic. ### Fixed ### Changed +- Genesys API call method and the name changed from `genesys_generate_exports` to `genesys_api_connection`. +- Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, `to_df` +and `delete_scheduled_report_job`. +- Added `GET` connection inside the method `genesys_api_connection`. ## [0.4.17] - 2023-06-15 ### Fixed From bfbca863eefba296c4fd11be4313da86e1320c77 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 30 Jun 2023 08:41:38 +0200 Subject: [PATCH 010/106] =?UTF-8?q?=F0=9F=8E=A8=20updated=20genesys=20flow?= =?UTF-8?q?=20with=20the=20new=20endpoint.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/flows/genesys_to_adls.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/viadot/flows/genesys_to_adls.py b/viadot/flows/genesys_to_adls.py index fbcb6df23..bdb133be2 100644 --- a/viadot/flows/genesys_to_adls.py +++ b/viadot/flows/genesys_to_adls.py @@ -5,8 +5,11 @@ import pandas as pd from prefect import Flow, task -from viadot.task_utils import add_ingestion_metadata_task, adls_bulk_upload from viadot.tasks.genesys import GenesysToCSV +from viadot.task_utils import ( + add_ingestion_metadata_task, + adls_bulk_upload, +) @task(timeout=3600) @@ -80,13 +83,12 @@ def __init__( view_type: str = None, view_type_time_sleep: int = 80, post_data_list: List[str] = None, - end_point: str = "reporting/exports", + end_point: str = "analytics/reporting/exports", list_of_userids: list = None, start_date: str = None, end_date: str = None, sep: str = "\t", environment: str = None, - schedule_id: str = None, report_url: str = None, report_columns: List[str] = None, local_file_path: str = "", @@ -125,14 +127,13 @@ def __init__( >>> "hasCustomParticipantAttributes": True, >>> }]''' If you need to add more POSTs in the same call, just add them to the list separated by a comma. - endpoint (str, optional): Final end point for Genesys connection. Defaults to "reporting/exports". + end_point (str, optional): Final end point for Genesys connection. Defaults to "analytics/reporting/exports". list_of_userids (list, optional): List of all user IDs to select in the data frame. Defaults to None. start_date (str, optional): Start date of the report. Defaults to None. end_date (str, optional): End date of the report. Defaults to None. sep (str, optional): Separator in csv file. Defaults to "\t". environment (str, optional): Adress of host server. Defaults to None than will be used enviroment from credentials. - schedule_id (str, optional): The ID of report. Defaults to None. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". @@ -150,13 +151,12 @@ def __init__( self.view_type_time_sleep = view_type_time_sleep self.post_data_list = post_data_list self.end_point = end_point - if self.end_point == "conversations/details/query": + if self.end_point == "analytics/conversations/details/query": self.apply_method = True else: self.apply_method = False self.list_of_userids = list_of_userids self.environment = environment - self.schedule_id = schedule_id self.report_url = report_url self.report_columns = report_columns self.start_date = start_date @@ -176,7 +176,6 @@ def __init__( self.gen_flow() def gen_flow(self) -> Flow: - to_csv = GenesysToCSV( timeout=self.timeout, local_file_path=self.local_file_path, From 14fffd1ffa59fd3c379c9ba3b6d450095ed4f77e Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 30 Jun 2023 08:58:23 +0200 Subject: [PATCH 011/106] =?UTF-8?q?=F0=9F=8E=A8=20added=20GET=20method=20i?= =?UTF-8?q?n=20Genesys=20source.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +- viadot/sources/genesys.py | 220 ++++++-------------------------------- 2 files changed, 35 insertions(+), 189 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8c0b1853..c96429c21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Genesys API call method and the name changed from `genesys_generate_exports` to `genesys_api_connection`. -- Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, `to_df` -and `delete_scheduled_report_job`. +- Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, +`to_df`, `delete_scheduled_report_job` and `generate_reporting_export`. - Added `GET` connection inside the method `genesys_api_connection`. ## [0.4.17] - 2023-06-15 diff --git a/viadot/sources/genesys.py b/viadot/sources/genesys.py index 15b466e64..27e767a96 100644 --- a/viadot/sources/genesys.py +++ b/viadot/sources/genesys.py @@ -8,7 +8,6 @@ import aiohttp import pandas as pd -from datetime import datetime, timedelta from aiolimiter import AsyncLimiter import prefect from prefect.engine import signals @@ -33,7 +32,6 @@ def __init__( credentials_genesys: Dict[str, Any] = None, environment: str = None, report_url: str = None, - schedule_id: str = None, report_columns: List[str] = None, *args: List[Any], **kwargs: Dict[str, Any], @@ -77,7 +75,6 @@ def __init__( super().__init__(*args, credentials=self.credentials_genesys, **kwargs) self.view_type = view_type - self.schedule_id = schedule_id self.report_name = report_name self.environment = environment self.report_url = report_url @@ -89,22 +86,9 @@ def __init__( self.ids_mapping = ids_mapping self.count = iter(range(99999)) - if self.schedule_id is None: - self.schedule_id = self.credentials.get("SCHEDULE_ID", None) - if self.environment is None: self.environment = self.credentials.get("ENVIRONMENT", None) - if self.ids_mapping is None: - self.ids_mapping = self.credentials.get("IDS_MAPPING", None) - - if type(self.ids_mapping) is dict and self.ids_mapping is not None: - self.logger.info("IDS_MAPPING loaded from local credential.") - else: - self.logger.warning( - "IDS_MAPPING is not provided in you credentials or is not a dictionary." - ) - self.report_data = [] @property @@ -151,14 +135,20 @@ def authorization_token(self, verbose: bool = False): return request_headers - def genesys_generate_exports( - self, post_data_list: List[str], end_point: str = "reporting/exports" + def genesys_api_connection( + self, + post_data_list: List[str], + end_point: str = "analytics/reporting/exports", + params: Dict[str, Any] = None, + method: Literal["POST", "GET"] = "POST", ) -> Optional[dict]: - """Function that make POST request method to generate export reports. + """Function that make POST request method to Genesys API given and endpoint. Args: post_data_list (List[str], optional): List of string templates to generate json body. Defaults to None. - end_point (str, optional): Final end point for Genesys connection. Defaults to "reporting/exports". + end_point (str, optional): Final end point for Genesys connection. Defaults to "analytics/reporting/exports". + params (Dict[str, Any], optional): Parameters to be passed into the POST call. Defaults to None. + method (Literal["POST", "GET"], optional): Type of connection to the API. Defaults to "POST". Returns: Optional[dict]: Dict when the "conversations" endpoint is called, otherwise returns None. @@ -166,18 +156,17 @@ def genesys_generate_exports( limiter = AsyncLimiter(2, 15) semaphore = asyncio.Semaphore(value=1) + url = f"https://api.{self.environment}/api/v2/{end_point}" async def generate_post(): - cnt = 0 - for data_to_post in post_data_list: - if cnt < 10: - payload = json.dumps(data_to_post) - async with aiohttp.ClientSession() as session: - await semaphore.acquire() - async with limiter: + payload = json.dumps(data_to_post) + async with aiohttp.ClientSession() as session: + await semaphore.acquire() + async with limiter: + if method == "POST": async with session.post( - f"https://api.{self.environment}/api/v2/analytics/{end_point}", + url, headers=self.authorization_token, data=payload, ) as resp: @@ -187,17 +176,21 @@ async def generate_post(): f"Generated report export --- \n {payload}." ) semaphore.release() - cnt += 1 - else: - await asyncio.sleep(3) - cnt = 0 + elif method == "GET": + async with session.get( + url, + headers=self.authorization_token, + params=params, + ) as resp: + new_report = await resp.read() + semaphore.release() + await asyncio.sleep(0.5) loop = asyncio.get_event_loop() coroutine = generate_post() loop.run_until_complete(coroutine) - if end_point == "conversations/details/query": - return json.loads(new_report.decode("utf-8")) + return json.loads(new_report.decode("utf-8")) def load_reporting_exports(self, page_size: int = 100, verbose: bool = False): """ @@ -322,21 +315,17 @@ def download_all_reporting_exports( ) continue - if single_report[4].lower() == "queue_performance_detail_view": - file_name = ( - temp_ids_mapping.get(single_report[2]) + "_" + single_report[3] - ).upper() + date = self.start_date.replace("-", "") + if single_report[4].lower() in [ + "queue_performance_detail_view", + "agent_status_detail_view", + ]: + file_name = f"{self.view_type.upper()}_{next(self.count)}_{date}" elif single_report[4].lower() in [ "agent_performance_summary_view", "agent_status_summary_view", ]: - date = self.start_date.replace("-", "") file_name = self.view_type.upper() + "_" + f"{date}" - elif single_report[4].lower() in [ - "agent_status_detail_view", - ]: - date = self.start_date.replace("-", "") - file_name = self.view_type.upper() + f"_{next(self.count)}_" + f"{date}" else: raise signals.SKIP( message=f"View type {self.view_type} not defined in viadot, yet..." @@ -357,36 +346,6 @@ def download_all_reporting_exports( self.logger.info("Successfully genetared file names list.") return file_name_list - def generate_reporting_export( - self, data_to_post: Dict[str, Any], verbose: bool = False - ) -> int: - """ - POST method for reporting export. - - Args: - data_to_post (Dict[str, Any]): json format of POST body. - verbose (bool, optional): Decide if enable logging. - - Returns: - new_report.status_code: status code - """ - payload = json.dumps(data_to_post) - new_report = handle_api_response( - url=f"https://api.{self.environment}/api/v2/analytics/reporting/exports", - headers=self.authorization_token, - method="POST", - body=payload, - ) - if verbose: - if new_report.status_code == 200: - self.logger.info("Succesfully generated new export.") - else: - self.logger.error( - f"Failed to generated new export. - {new_report.content}" - ) - raise APIError("Failed to generated new export.") - return new_report.status_code - def delete_reporting_exports(self, report_id) -> int: """DELETE method for deleting particular reporting exports. @@ -421,116 +380,3 @@ def delete_all_reporting_exports(self) -> None: assert status_code < 300 self.logger.info("Successfully removed all reports.") - - def get_analitics_url_report(self) -> str: - """ - Fetching analytics report url from json response. - - Returns: - string: url for analytics report - """ - response = handle_api_response( - url=f"https://api.{self.environment}/api/v2/analytics/reporting/schedules/{self.schedule_id}", - headers=self.authorization_token, - ) - try: - response_json = response.json() - report_url = response_json.get("lastRun", None).get("reportUrl", None) - self.logger.info("Successfully downloaded report from genesys api") - return report_url - except AttributeError as e: - self.logger.error( - "Output data error: " + str(type(e).__name__) + ": " + str(e) - ) - - def get_all_schedules_job(self) -> json: - """ - Fetching analytics report url from json response. - - Returns: - string: json body with all schedules jobs. - """ - response = handle_api_response( - url=f"https://api.{self.environment}/api/v2/analytics/reporting/schedules", - headers=self.authorization_token, - ) - try: - response_json = response.json() - self.logger.info("Successfully downloaded schedules jobs.") - return response_json - except AttributeError as e: - self.logger.error( - "Output data error: " + str(type(e).__name__) + ": " + str(e) - ) - - def schedule_report(self, data_to_post: Dict[str, Any]) -> json: - """ - POST method for report scheduling. - - Args: - data_to_post (Dict[str, Any]): json format of POST body. - - Returns: - new_report.status_code: status code - """ - payload = json.dumps(data_to_post) - new_report = handle_api_response( - url=f"https://api.{self.environment}/api/v2/analytics/reporting/schedules", - headers=self.authorization_token, - method="POST", - body=payload, - ) - if new_report.status_code == 200: - self.logger.info("Succesfully scheduled new report.") - else: - self.logger.error(f"Failed to scheduled new report. - {new_report.content}") - raise APIError("Failed to scheduled new report.") - return new_report.status_code - - def to_df(self, report_url: str = None): - """Download genesys data into a pandas DataFrame. - - Args: - report_url (str): Report url from api response. - - Returns: - pd.DataFrame: the DataFrame with time range - """ - if report_url is None: - report_url = self.get_analitics_url_report - response_file = handle_api_response( - url=f"{report_url}", headers=self.authorization_token - ) - if self.report_columns is None: - df = pd.read_excel(response_file.content, header=6) - else: - df = pd.read_excel( - response_file.content, names=self.report_columns, skiprows=6 - ) - - return df - - def delete_scheduled_report_job(self, report_id: str): - """DELETE method for deleting particular report job. - - Args: - report_id (str): defined at the end of report url. - - Returns: - delete_method.status_code: status code - """ - delete_method = handle_api_response( - url=f"https://api.{self.environment}/api/v2/analytics/reporting/schedules/{report_id}", - headers=self.authorization_token, - method="DELETE", - ) - if delete_method.status_code == 200: - self.logger.info("Successfully deleted report from Genesys API.") - - else: - self.logger.error( - f"Failed to deleted report from Genesys API. - {delete_method.content}" - ) - raise APIError("Failed to deleted report from Genesys API.") - - return delete_method.status_code From dfcf0afc4e1e2c2c7a8a94f02fa4049ab3b2a20a Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 30 Jun 2023 09:11:56 +0200 Subject: [PATCH 012/106] =?UTF-8?q?=F0=9F=94=A5=20removed=20schedule=5Fid?= =?UTF-8?q?=20parameter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/tasks/genesys.py | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/viadot/tasks/genesys.py b/viadot/tasks/genesys.py index 7b26deb15..0b5ca1043 100644 --- a/viadot/tasks/genesys.py +++ b/viadot/tasks/genesys.py @@ -27,7 +27,6 @@ def __init__( start_date: str = None, end_date: str = None, environment: str = None, - schedule_id: str = None, report_url: str = None, report_columns: List[str] = None, local_file_path: str = "", @@ -48,7 +47,6 @@ def __init__( end_date (str, optional): End date of the report. Defaults to None. environment (str, optional): Adress of host server. Defaults to None than will be used enviroment from credentials. - schedule_id (str, optional): The ID of report. Defaults to None. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". @@ -58,7 +56,6 @@ def __init__( """ self.logger = prefect.context.get("logger") - self.schedule_id = schedule_id self.report_name = report_name self.view_type = view_type self.environment = environment @@ -283,7 +280,6 @@ def merge_conversations_dfs(self, data_to_merge: list) -> DataFrame: "report_name", "view_type", "environment", - "schedule_id", "report_url", "post_data_list", "start_date", @@ -297,10 +293,9 @@ def run( view_type: str = None, view_type_time_sleep: int = 80, environment: str = None, - schedule_id: str = None, report_url: str = None, post_data_list: List[str] = None, - end_point: str = "reporting/exports", + end_point: str = "analytics/reporting/exports", start_date: str = None, end_date: str = None, report_columns: List[str] = None, @@ -314,13 +309,11 @@ def run( view_type (str, optional): The type of view export job to be created. Defaults to None. view_type_time_sleep (int, optional): Waiting time to retrieve data from Genesys API. Defaults to 80. post_data_list (List[str], optional): List of string templates to generate json body. Defaults to None. - end_point (str, optional): Final end point for Genesys connection. Defaults to "reporting/exports". + end_point (str, optional): Final end point for Genesys connection. Defaults to "analytics/reporting/exports". credentials_genesys (Dict[str, Any], optional): Credentials to connect with Genesys API containing CLIENT_ID. Defaults to None. start_date (str, optional): Start date of the report. Defaults to None. end_date (str, optional): End date of the report. Defaults to None. - environment (str, optional): Adress of host server. Defaults to None than will be used enviroment - from credentials. - schedule_id (str, optional): The ID of report. Defaults to None. + environment (str, optional): Adress of host server. Defaults to None than will be used enviroment from credentials. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. @@ -335,13 +328,12 @@ def run( start_date=start_date, end_date=end_date, environment=environment, - schedule_id=schedule_id, report_url=report_url, report_columns=report_columns, ) if view_type == "queue_performance_detail_view": - genesys.genesys_generate_exports( + genesys.genesys_api_connection( post_data_list=post_data_list, end_point=end_point ) @@ -356,7 +348,6 @@ def run( timeout = timeout_start + 60 # while loop with timeout while time.time() < timeout: - try: genesys.get_reporting_exports_data() urls = [col for col in np.array(genesys.report_data).T][1] @@ -375,7 +366,7 @@ def run( "agent_status_summary_view", "agent_status_detail_view", ]: - genesys.genesys_generate_exports( + genesys.genesys_api_connection( post_data_list=post_data_list, end_point=end_point ) logger.info( @@ -385,7 +376,7 @@ def run( genesys.get_reporting_exports_data() - if view_type is not None and end_point == "reporting/exports": + if view_type is not None and end_point == "analytics/reporting/exports": failed = [col for col in np.array(genesys.report_data).T][-1] if "FAILED" in failed and "COMPLETED" in failed: @@ -412,7 +403,7 @@ def run( return file_names - elif view_type is None and end_point == "conversations/details/query": + elif view_type is None and end_point == "analytics/conversations/details/query": if len(post_data_list) > 1: logger.error("Not available more than one body for this end-point.") raise signals.FAIL(message="Stopping the flow.") @@ -421,7 +412,7 @@ def run( page_counter = post_data_list[0]["paging"]["pageNumber"] merged_data = {} while not stop_loop: - report = genesys.genesys_generate_exports( + report = genesys.genesys_api_connection( post_data_list=post_data_list, end_point=end_point ) merged_data_frame = self.merge_conversations_dfs( From 07b95550afea726494232fd121c3d2fea465835c Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 30 Jun 2023 09:12:41 +0200 Subject: [PATCH 013/106] =?UTF-8?q?=E2=9C=85=20modified=20Genesys=20test?= =?UTF-8?q?=20file=20for=20the=20new=20structure.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_genesys.py | 32 +++++-------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/tests/integration/test_genesys.py b/tests/integration/test_genesys.py index d18503d49..817e590b5 100644 --- a/tests/integration/test_genesys.py +++ b/tests/integration/test_genesys.py @@ -144,12 +144,6 @@ def test_environment_param(): assert g.environment != None and type(g.environment) == str -@pytest.mark.init -def test_schedule_id_param(): - g = Genesys() - assert g.schedule_id != None and type(g.schedule_id) == str - - @pytest.mark.parametrize("input_name", ["test_name", "12345", ".##@@"]) @pytest.mark.init def test_other_inicial_params(input_name): @@ -167,31 +161,16 @@ def test_connection_with_genesys_api(): ) -@mock.patch.object(Genesys, "genesys_generate_exports") +@mock.patch.object(Genesys, "genesys_api_connection") @pytest.mark.connection -def test_generate_exports(mock_api_response, var_dictionary): +def test_generate_api_connection(mock_api_response, var_dictionary): g = Genesys() - assert g.genesys_generate_exports() + assert g.genesys_api_connection() mock_api_response.assert_called() -@mock.patch.object(Genesys, "load_reporting_exports") -@pytest.mark.dependency(["test_generate_exports"]) -@pytest.mark.generate -def test_generate_reports_list(mock_load_reports, var_dictionary): - mock_load_reports.return_value = var_dictionary["entities"] - g = Genesys() - g.get_reporting_exports_data() - mock_load_reports.assert_called_once() - - @mock.patch.object(Genesys, "download_report") -@pytest.mark.dependency( - depends=[ - "test_generate_exports", - "test_generate_reports_list", - ] -) +@pytest.mark.dependency(depends=["test_generate_api_connection"]) @pytest.mark.download def test_download_reports(mock_download_files, var_dictionary): g = Genesys() @@ -207,8 +186,7 @@ def test_download_reports(mock_download_files, var_dictionary): @mock.patch("viadot.sources.genesys.handle_api_response", return_value=MockClass) @pytest.mark.dependency( depends=[ - "test_generate_exports", - "test_generate_reports_list", + "test_generate_api_connection", "test_download_reports", ] ) From a59e0e6ecc3f89fa8dbb3dd5048e1c51acc0cd0c Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Mon, 3 Jul 2023 13:56:52 +0200 Subject: [PATCH 014/106] =?UTF-8?q?=E2=9C=85=20Impoved=20coverage=20to=201?= =?UTF-8?q?00%=20-=20BigQuery?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_bigquery.py | 84 ++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index 2efecce52..d03e2c637 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -1,48 +1,86 @@ +from typing import List import pandas as pd +import pandas_gbq +import pytest +from numpy import ndarray +from viadot.exceptions import CredentialError, DBDataAccessError from viadot.sources import BigQuery -BIGQ = BigQuery(credentials_key="BIGQUERY_TESTS") +@pytest.fixture(scope="function") +def BIGQ(): + BQ = BigQuery(credentials_key="BIGQUERY_TESTS") + yield BQ -def test_list_project(): + +@pytest.fixture(scope="session") +def inset_into_tables(): + table_id1 = "manigeo.manigeo_tab" + table_id2 = "manigeo.space" + df = pd.DataFrame({"my_value": ["val1", "val2", "val3"]}) + pandas_gbq.to_gbq(df, table_id1, if_exists="replace") + pandas_gbq.to_gbq(df, table_id2, if_exists="replace") + + +QUERY = """ + SELECT name, SUM(number) AS total + FROM `bigquery-public-data.usa_names.usa_1910_2013` + GROUP BY name, gender + ORDER BY total DESC + LIMIT 4 + """ + + +def test_credentials(): + with pytest.raises(CredentialError, match=r"Credentials not found."): + _ = BigQuery(credentials_key="BIGQUERY_TESTS_FAKE") + + +def test_list_project(BIGQ): project = BIGQ.get_project_id() + assert project == "manifest-geode-341308" -def test_list_datasets(): +def test_list_datasets(BIGQ): datasets = list(BIGQ.list_datasets()) + assert datasets == ["manigeo", "official_empty"] -def test_list_tables(): +def test_list_tables(BIGQ): datasets = BIGQ.list_datasets() tables = list(BIGQ.list_tables(datasets[0])) - assert tables == ["space", "test_data", "manigeo_tab"] + assert "space" and "manigeo_tab" in tables -def test_query_is_df(): - query = """ - SELECT name, SUM(number) AS total - FROM `bigquery-public-data.usa_names.usa_1910_2013` - GROUP BY name, gender - ORDER BY total DESC - LIMIT 4 - """ - df = BIGQ.query_to_df(query) +def test_list_columns(BIGQ): + columns = BIGQ.list_columns(dataset_name="manigeo", table_name="space") + + assert "my_value" in columns + assert isinstance(columns, ndarray) + + +def test_query_is_df(BIGQ): + df = BIGQ.query_to_df(QUERY) assert isinstance(df, pd.DataFrame) -def test_query(): - query = """ - SELECT name, SUM(number) AS total - FROM `bigquery-public-data.usa_names.usa_1910_2013` - GROUP BY name, gender - ORDER BY total DESC - LIMIT 4 - """ - df = BIGQ.query_to_df(query) +def test_query(BIGQ): + df = BIGQ.query_to_df(QUERY) total_received = df["total"].values assert total_received == [4924235, 4818746, 4703680, 4280040] + + +def test_wrong_query(BIGQ): + fake_query = """ + SELECT fake_name + FROM `bigquery-public-data.usa_names.fake_table` + ORDER BY fake_name DESC + LIMIT 4 + """ + with pytest.raises(DBDataAccessError): + _ = BIGQ.query_to_df(fake_query) From fec20560c6a38580f11b702fd685a73102a4607a Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Mon, 3 Jul 2023 16:05:25 +0200 Subject: [PATCH 015/106] =?UTF-8?q?=E2=9C=85=20Impoved=20Sharepoint=20sour?= =?UTF-8?q?ce=20class=20coverage=20to=2096%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_sharepoint.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_sharepoint.py b/tests/integration/test_sharepoint.py index 8beffd210..f3013ba66 100644 --- a/tests/integration/test_sharepoint.py +++ b/tests/integration/test_sharepoint.py @@ -29,7 +29,13 @@ def FILE_NAME(sharepoint): os.remove(path) -def test_credentials(): +def test_credentials_not_found(): + none_credentials = None + with pytest.raises(CredentialError, match=r"Credentials not found."): + Sharepoint(credentials=none_credentials) + + +def test_get_connection_credentials(): credentials = {"site": "tenant.sharepoint.com", "username": "User"} s = Sharepoint(credentials=credentials) with pytest.raises(CredentialError, match="Missing credentials."): @@ -57,6 +63,11 @@ def test_sharepoint_to_df_task(): os.remove("Questionnaires.xlsx") +def test_download_file(sharepoint): + with pytest.raises(ValueError, match=r"Missing required parameter"): + sharepoint.download_file(download_to_path=None, download_from_path=None) + + def test_file_download(FILE_NAME): files = [] for file in os.listdir(): From 6cb237c6e2bbb4dc71ba54bd11d052808534e7f7 Mon Sep 17 00:00:00 2001 From: gwieloch Date: Tue, 4 Jul 2023 13:53:39 +0200 Subject: [PATCH 016/106] updated sap_bw tests and flows --- tests/integration/test_sap_bw.py | 36 ++++++++++++++++ viadot/flows/sap_bw_to_adls.py | 4 +- viadot/sources/sap_bw.py | 71 ++++++++++++++++++-------------- viadot/tasks/sap_bw.py | 33 +++++++-------- 4 files changed, 93 insertions(+), 51 deletions(-) diff --git a/tests/integration/test_sap_bw.py b/tests/integration/test_sap_bw.py index f087603cc..44f579578 100644 --- a/tests/integration/test_sap_bw.py +++ b/tests/integration/test_sap_bw.py @@ -1,6 +1,7 @@ import pytest from viadot.sources import SAPBW from viadot.task_utils import credentials_loader +from pyrfc import Connection CREDENTIALS = credentials_loader.run(credentials_secret="SAP") @@ -29,6 +30,33 @@ def mdx_query_variable(): yield mdx_query +@pytest.fixture(scope="session") +def wrong_mdx_query_variable(): + wrong_mdx_query = """ + SELECT + { + } + ON COLUMNS, + NON EMPTY + { + { [0CALMONTH].[202301] * + } + DIMENSION PROPERTIES + DESCRIPTION, + MEMBER_NAME + ON ROWS + + FROM ZCSALORD1/ZBW4_ZCSALORD1_006_BOA + + """ + yield wrong_mdx_query + + +def test_get_connection(): + conn = SAPBW.get_connection() + assert isinstance(conn, Connection) + + def test_get_all_available_columns(mdx_query_variable): all_available_columns = SAPBW.get_all_available_columns(mdx_query_variable) assert isinstance(all_available_columns, list) @@ -37,3 +65,11 @@ def test_get_all_available_columns(mdx_query_variable): def test_get_output_data(mdx_query_variable): query_output = SAPBW.get_output_data(mdx_query_variable) assert isinstance(query_output, dict) + + +def test_wrong_mdx_query_for_get_output_data(wrong_mdx_query_variable): + query_output = SAPBW.get_output_data(wrong_mdx_query_variable) + assert ( + query_output.get("RETURN").get("MESSAGE") + == "Syntax error: Syntax Error : ... { [0CALMONTH].[2023, row 226, item: 226" + ) diff --git a/viadot/flows/sap_bw_to_adls.py b/viadot/flows/sap_bw_to_adls.py index d0f0c9acb..bd8e0c474 100644 --- a/viadot/flows/sap_bw_to_adls.py +++ b/viadot/flows/sap_bw_to_adls.py @@ -21,7 +21,7 @@ class SAPBWToADLS(Flow): def __init__( self, name: str, - mdx_query: str = None, + mdx_query: str, mapping_dict: dict = None, sapbw_credentials: dict = None, sapbw_credentials_key: str = "SAP", @@ -42,7 +42,7 @@ def __init__( Args: name (str): Name of the flow. - mdx_query (str, optional): MDX query to be passed to SAP BW server. Defaults to None. + mdx_query (str): MDX query to be passed to SAP BW server. mapping_dict (dict, optional): Dictionary with original column names and the mapping for them. If not None then flows is generating mapping automatically with mapping applied by user, if not - it generates automatically the json file with columns. sapbw_credentials (dict, optional): Credentials to SAP in dictionary format. Defaults to None. sapbw_credentials_key (str, optional): Azure KV secret. Defaults to "SAP". diff --git a/viadot/sources/sap_bw.py b/viadot/sources/sap_bw.py index d3765ff39..2cb8b8749 100644 --- a/viadot/sources/sap_bw.py +++ b/viadot/sources/sap_bw.py @@ -14,6 +14,15 @@ class SAPBW(Source): """ def __init__(self, credentials: dict, *args, **kwargs): + """ + Create an instance of the SAPBW class. + + Args: + credentials (dict): Credentials to connect with SAP BW containing ashost, sysnr, user, passwd, client. + + Raises: + CredentialError: If provided credentials are incorrect. + """ if credentials is None: raise CredentialError("Missing credentials.") @@ -34,16 +43,17 @@ def get_connection(self) -> Connection: client=self.credentials.get("client"), ) - def get_all_available_columns(self, mdx_query: str = None) -> List: + def get_all_available_columns(self, mdx_query: str) -> List: """ Function to generate list of all available columns in the SAP table based on passed MDX query. Args: - mdx_query (str, optional): The MDX query to be passed to connection. Defaults to None. + mdx_query (str): The MDX query to be passed to connection. Returns: all_available_columns: List of all available columns in the source table. """ + conn = self.get_connection() query = textwrap.wrap( mdx_query, width=75 @@ -65,44 +75,44 @@ def get_all_available_columns(self, mdx_query: str = None) -> List: return all_available_columns - def get_output_data(self, mdx_query: str = None) -> dict: + def get_output_data(self, mdx_query: str) -> dict: """ Function to generate the SAP output dataset from MDX query. Args: - mdx_query (str, optional): The MDX query to be passed to connection. Defaults to None. + mdx_query (str): The MDX query to be passed to connection. Returns: query_output: SAP output dictionary in JSON format that contains data rows and column headers. - Example output: + Example output: + { + "RETURN": { + "TYPE": "", + "ID": "", + "NUMBER": "000", + "MESSAGE": "",... + },... + "DATA": [ + { + "COLUMN": 0, + "ROW": 0, + "DATA": "VELUX Deutschland GmbH", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "" + },... + ], + "HEADER": [ { - "RETURN": { - "TYPE": "", - "ID": "", - "NUMBER": "000", - "MESSAGE": "",... + "COLUMN": 0, + "ROW": 0, + "DATA": "[0COMP_CODE].[LEVEL01].[DESCRIPTION]", + "VALUE_DATA_TYPE": "CHAR", + "CELL_STATUS": "" },... - "DATA": [ - { - "COLUMN": 0, - "ROW": 0, - "DATA": "VELUX Deutschland GmbH", - "VALUE_DATA_TYPE": "CHAR", - "CELL_STATUS": "" - },... - ], - "HEADER": [ - { - "COLUMN": 0, - "ROW": 0, - "DATA": "[0COMP_CODE].[LEVEL01].[DESCRIPTION]", - "VALUE_DATA_TYPE": "CHAR", - "CELL_STATUS": "" - },... - ] - } + ] + } """ conn = self.get_connection() @@ -114,7 +124,4 @@ def get_output_data(self, mdx_query: str = None) -> dict: datasetid = properties["DATASETID"] query_output = conn.call("RSR_MDX_GET_FLAT_DATA", DATASETID=datasetid) - # if properties["RETURN"]["MESSAGE"] != "": - # self.logger.error(properties["RETURN"]["MESSAGE"]) - return query_output diff --git a/viadot/tasks/sap_bw.py b/viadot/tasks/sap_bw.py index a8f3e0e04..e2d8bab43 100644 --- a/viadot/tasks/sap_bw.py +++ b/viadot/tasks/sap_bw.py @@ -1,7 +1,4 @@ import pandas as pd - - -from typing import List, Dict, Any, Literal from prefect import Task from prefect.tasks.secrets import PrefectSecret from prefect.utilities import logging @@ -32,8 +29,7 @@ def __init__( if sapbw_credentials is None: self.sapbw_credentials = credentials_loader.run( credentials_secret=sapbw_credentials_key - ) - self.sapbw_credentials = self.sapbw_credentials[env] + ).get(env) else: self.sapbw_credentials = sapbw_credentials @@ -71,41 +67,44 @@ def apply_user_mapping( return df - def to_df(self, query_output: dict = {}) -> pd.DataFrame: + def to_df(self, query_output: dict) -> pd.DataFrame: """ Function to convert the SAP output in JSON format into a dataframe. Args: - query_output: SAP output dictionary in JSON format that contains data rows and column headers. Defaults to {}. + query_output (dict): SAP output dictionary in JSON format that contains data rows and column headers. + + Raises: + ValidationError: Prints the original SAP error message in case of issues with MDX execution. Returns: pd.DataFrame: Output dataframe. """ - rows = {} + raw_data = {} if query_output["RETURN"]["MESSAGE"] == "": results = query_output["DATA"] for cell in results: - if cell["ROW"] not in rows: - rows[cell["ROW"]] = {} + if cell["ROW"] not in raw_data: + raw_data[cell["ROW"]] = {} if "].[" not in cell["DATA"]: - rows[cell["ROW"]][cell["COLUMN"]] = cell["DATA"] - df_rows = [rows[row] for row in rows] - df_cols = [x["DATA"] for x in query_output["HEADER"]] - df = pd.DataFrame(data=df_rows) - df.columns = df_cols + raw_data[cell["ROW"]][cell["COLUMN"]] = cell["DATA"] + rows = [raw_data[row] for row in raw_data] + cols = [x["DATA"] for x in query_output["HEADER"]] + df = pd.DataFrame(data=rows) + df.columns = cols else: df = pd.DataFrame() raise ValidationError(query_output["RETURN"]["MESSAGE"]) return df - def run(self, mdx_query: str = None, mapping_dict: dict = {}) -> pd.DataFrame: + def run(self, mdx_query: str, mapping_dict: dict = {}) -> pd.DataFrame: """ Task run method. Args: - mdx_query (str, optional): MDX query to be passed to SAP BW. Defaults to None. + mdx_query (str): MDX query to be passed to SAP BW. mapping_dict (dict, optional): Mapping dictionary from user in json format. Defaults to {}. Returns: From 342986932d1e37f63937767908c25a6fca07c2ee Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 4 Jul 2023 17:01:53 +0200 Subject: [PATCH 017/106] modyfing passing credentials as a parameter --- viadot/sources/vid_club.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 207691fe1..df61835ad 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -26,17 +26,18 @@ def __init__(self, *args, credentials: Dict[str, Any] = None, **kwargs): Create an instance of VidClub. Args: - credentials (dict, optional): Credentials to Vid Club APIs. + credentials (Dict[str, Any], optional): Credentials to Vid Club APIs containing token. Defaults to dictionary. Raises: CredentialError: If credentials are not provided in local_config or directly as a parameter. """ - - DEFAULT_CREDENTIALS = local_config.get("VIDCLUB") - credentials = kwargs.pop("credentials", DEFAULT_CREDENTIALS) - if credentials is None: - raise CredentialError("Missing credentials.") + if credentials is not None: + self.credentials = credentials + else: + self.credentials = local_config.get("VIDCLUB") + if self.credentials is None: + raise CredentialError("Credentials not provided.") self.headers = { "Authorization": "Bearer " + credentials["token"], From 3a53c7914d5287a0757e83fb6e048cc29d38f995 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 5 Jul 2023 13:36:44 +0200 Subject: [PATCH 018/106] change credentials parameter settings --- viadot/sources/vid_club.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index df61835ad..5d931969a 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -35,9 +35,7 @@ def __init__(self, *args, credentials: Dict[str, Any] = None, **kwargs): if credentials is not None: self.credentials = credentials else: - self.credentials = local_config.get("VIDCLUB") - if self.credentials is None: - raise CredentialError("Credentials not provided.") + raise CredentialError("Credentials not provided.") self.headers = { "Authorization": "Bearer " + credentials["token"], From da6262476a4529eb5b59a63a88a8d8430fcfe5f5 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 5 Jul 2023 13:56:28 +0200 Subject: [PATCH 019/106] update tests --- tests/integration/test_vid_club.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index 4a75c911e..30e3f87b7 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -4,9 +4,12 @@ import pytest from viadot.exceptions import ValidationError +from viadot.task_utils import credentials_loader from viadot.sources import VidClub +CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") + @pytest.fixture def var_dictionary(): variables = {} @@ -21,25 +24,22 @@ def json(): df = pd.DataFrame() return df - -@pytest.mark.init -def test_create_club_class(): - vc = VidClub() - assert vc - - @pytest.mark.init def test_default_credential_param(): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) assert vc.credentials != None and type(vc.credentials) == dict +@pytest.mark.init +def test_create_club_class(): + vc = VidClub(credentials = CREDENTIALS) + assert vc @pytest.mark.proper def test_build_query_wrong_source(): with pytest.raises( ValidationError, match=r"Pick one these sources: jobs, product, company, survey" ): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) query = vc.build_query( source="test", from_date="2023-03-24", @@ -54,7 +54,7 @@ def test_get_response_wrong_source(): with pytest.raises( ValidationError, match=r"The source has to be: jobs, product, company or survey" ): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source="test") @@ -64,7 +64,7 @@ def test_get_response_wrong_source(): @pytest.mark.parametrize("source", ["jobs", "company", "product", "survey"]) @pytest.mark.proper def test_get_response_sources(mock_api_response, source): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source=source, to_date="2023-03-24", from_date="2023-03-24") assert isinstance(query, pd.DataFrame) @@ -75,7 +75,7 @@ def test_get_response_wrong_date(): with pytest.raises( ValidationError, match=r"from_date cannot be earlier than 2023-03-22!!" ): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source="jobs", from_date="2021-05-09") @@ -84,7 +84,7 @@ def test_get_response_wrong_date_range(): with pytest.raises( ValidationError, match=r"to_date cannot be earlier than from_date!" ): - vc = VidClub() + vc = VidClub(credentials = CREDENTIALS) query = vc.get_response( source="jobs", to_date="2022-05-04", from_date="2022-05-05" ) From 5b519fd8fae19650ef245039404c5d240d2f1c1d Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 5 Jul 2023 14:07:28 +0200 Subject: [PATCH 020/106] update docstrings --- viadot/sources/vid_club.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 5d931969a..5d29d26f7 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -18,10 +18,13 @@ class VidClub(Source): Documentation for this API is located at: https://evps01.envoo.net/vipapi/ There are 4 endpoints where to get the data. - """ - def __init__(self, *args, credentials: Dict[str, Any] = None, **kwargs): + def __init__( + self, + *args, + credentials: Dict[str, Any] = None, + **kwargs): """ Create an instance of VidClub. @@ -103,11 +106,10 @@ def get_response( Raises: ValidationError: If any source different than the ones in the list are used. - ValidationError: If the initial date of the query is before the oldest date in the data (2023-03-22). + ValidationError: If the initial date of the query is before the oldest date in the data (2022-03-22). ValidationError: If the final date of the query is before the start date. """ - # Dealing with bad arguments if source not in ["jobs", "product", "company", "survey"]: raise ValidationError( "The source has to be: jobs, product, company or survey" @@ -120,15 +122,14 @@ def get_response( delta = from_date_obj - oldest_date_obj if delta.days < 0: - raise ValidationError("from_date cannot be earlier than 2023-03-22!!") + raise ValidationError("from_date cannot be earlier than 2022-03-22.") to_date_obj = datetime.strptime(to_date, "%Y-%m-%d") delta = to_date_obj - from_date_obj if delta.days < 0: - raise ValidationError("to_date cannot be earlier than from_date!") + raise ValidationError("to_date cannot be earlier than from_date.") - # Preparing the Query first_url = self.build_query( source, from_date, @@ -138,10 +139,8 @@ def get_response( ) headers = self.headers - # Getting first page response = handle_api_response(url=first_url, headers=headers, method="GET") - # Next Pages response = response.json() if isinstance(response, dict): @@ -152,7 +151,6 @@ def get_response( keys_list = [] if "data" in keys_list: - # first page content df = pd.DataFrame(response["data"]) length = df.shape[0] page = 2 From 1a245ff04b46550822813c3ca781aaa792995d0a Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 5 Jul 2023 14:11:13 +0200 Subject: [PATCH 021/106] remove unused import --- viadot/sources/vid_club.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 5d29d26f7..de5c14fda 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -6,7 +6,6 @@ import pandas as pd -from ..config import local_config from ..exceptions import CredentialError, ValidationError from ..utils import handle_api_response from .base import Source @@ -33,7 +32,7 @@ def __init__( Defaults to dictionary. Raises: - CredentialError: If credentials are not provided in local_config or directly as a parameter. + CredentialError: If credentials are not provided as a parameter. """ if credentials is not None: self.credentials = credentials From b68e69924dd0bfb793da10b9e917b4fd82fe7c7d Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 5 Jul 2023 14:27:49 +0200 Subject: [PATCH 022/106] update credentials passing --- viadot/tasks/vid_club.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 448df8e41..f522fb4a2 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -10,6 +10,8 @@ from prefect.tasks.secrets import PrefectSecret from prefect.utilities import logging +from viadot.task_utils import credentials_loader + from ..sources import VidClub logger = logging.get_logger() @@ -20,6 +22,8 @@ def __init__( self, source: Literal["jobs", "product", "company", "survey"], credentials: Dict[str, Any] = None, + credentials_secret: str = "VIDCLUB", + vault_name: str = None, from_date: str = "2022-03-22", to_date: str = "", if_empty: str = "warn", @@ -36,6 +40,8 @@ def __init__( source (str): The endpoint source to be accessed, has to be among these: ['jobs', 'product', 'company', 'survey']. credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. + credentials_secret (str, optional): The name of the Azure Key Vault or Prefect or local_config secret containing a dictionary with ['client_id', 'client_secret']. Defaults to "VIDCLUB". + vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str): End date for the query, if empty, datetime.today() will be used. if_empty (str, optional): What to do if query returns no data. Defaults to "warn". @@ -48,12 +54,20 @@ def __init__( """ self.logger = prefect.context.get("logger") self.source = source - self.credentials = credentials self.from_date = from_date self.to_date = to_date self.if_empty = if_empty self.retry_delay = retry_delay self.report_name = report_name + self.credentials_secret = credentials_secret + self.vault_name = vault_name + + if credentials is None: + self.credentials = credentials_loader.run( + credentials_secret = credentials_secret, vault_name = vault_name + ) + else: + self.credentials = credentials super().__init__( name=self.report_name, @@ -74,7 +88,7 @@ def run(self) -> pd.DataFrame: pd.DataFrame: The query result as a pandas DataFrame. """ - vc_obj = VidClub() + vc_obj = VidClub(credentials = self.credentials) vc_dataframe = vc_obj.get_response( source=self.source, from_date=self.from_date, to_date=self.to_date From 3a9e0ff33c692685927126c7e12e56959ba0247b Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 6 Jul 2023 16:14:30 +0200 Subject: [PATCH 023/106] remove unused args --- viadot/tasks/vid_club.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index f522fb4a2..4b7a52555 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -26,8 +26,6 @@ def __init__( vault_name: str = None, from_date: str = "2022-03-22", to_date: str = "", - if_empty: str = "warn", - retry_delay: timedelta = timedelta(seconds=10), timeout: int = 3600, report_name: str = "vid_club_to_df", *args: List[Any], @@ -44,8 +42,6 @@ def __init__( vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str): End date for the query, if empty, datetime.today() will be used. - if_empty (str, optional): What to do if query returns no data. Defaults to "warn". - retry_delay (timedelta, optional): The delay between task retries. Defaults to 10 seconds. timeout (int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. report_name (str, optional): Stores the report name. Defaults to "vid_club_to_df". @@ -56,8 +52,6 @@ def __init__( self.source = source self.from_date = from_date self.to_date = to_date - self.if_empty = if_empty - self.retry_delay = retry_delay self.report_name = report_name self.credentials_secret = credentials_secret self.vault_name = vault_name From b37cbac8de0996b344e6340fb895d9743bbc83e6 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 6 Jul 2023 16:56:16 +0200 Subject: [PATCH 024/106] update default value for source --- viadot/sources/vid_club.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index de5c14fda..2ba3ebf24 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -48,22 +48,21 @@ def __init__( def build_query( self, - source: Literal["jobs", "product", "company", "survey"], from_date: str, to_date: str, api_url: str, items_per_page: int, + source: Literal["jobs", "product", "company", "survey"] = None, ) -> str: """ Builds the query from the inputs. Args: - source (str): The endpoint source to be accessed, has to be among these: - ['jobs', 'product', 'company', 'survey']. from_date (str): Start date for the query. to_date (str): End date for the query, if empty, datetime.today() will be used. api_url (str): Generic part of the URL. items_per_page (int): number of entries per page. + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. Returns: str: Final query with all filters added. @@ -83,7 +82,7 @@ def build_query( def get_response( self, - source: Literal["jobs", "product", "company", "survey"], + source: Literal["jobs", "product", "company", "survey"] = None, from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, @@ -93,8 +92,7 @@ def get_response( Gets the response from the API queried and transforms it into DataFrame. Args: - source (str): The endpoint source to be accessed, has to be among these: - ['jobs', 'product', 'company', 'survey']. + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. From 8a58d4804b74ca3553d5f2e6d9e8656401a882aa Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 6 Jul 2023 16:56:47 +0200 Subject: [PATCH 025/106] add args to run --- viadot/tasks/vid_club.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 4b7a52555..211f7719a 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -9,6 +9,7 @@ from prefect import Task from prefect.tasks.secrets import PrefectSecret from prefect.utilities import logging +from prefect.utilities.tasks import defaults_from_attrs from viadot.task_utils import credentials_loader @@ -20,7 +21,7 @@ class VidClubToDF(Task): def __init__( self, - source: Literal["jobs", "product", "company", "survey"], + source: Literal["jobs", "product", "company", "survey"] = None, credentials: Dict[str, Any] = None, credentials_secret: str = "VIDCLUB", vault_name: str = None, @@ -35,10 +36,9 @@ def __init__( Task to downloading data from Vid Club APIs to Pandas DataFrame. Args: - source (str): The endpoint source to be accessed, has to be among these: - ['jobs', 'product', 'company', 'survey']. + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. - credentials_secret (str, optional): The name of the Azure Key Vault or Prefect or local_config secret containing a dictionary with ['client_id', 'client_secret']. Defaults to "VIDCLUB". + credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str): End date for the query, if empty, datetime.today() will be used. @@ -74,18 +74,35 @@ def __call__(self, *args, **kwargs): """Download Vid Club data to Pandas DataFrame""" return super().__call__(*args, **kwargs) - def run(self) -> pd.DataFrame: + @defaults_from_attrs("source", "credentials", "credentials_secret", "vault_name", "from_date", "to_date") + def run( + self, + source: Literal["jobs", "product", "company", "survey"] = None, + credentials: Dict[str, Any] = None, + credentials_secret: str = "VIDCLUB", + vault_name: str = None, + from_date: str = "2022-03-22", + to_date: str = "", + ) -> pd.DataFrame: """ Task run method. + Args: + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. + credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. + credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". + vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. + from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. + to_date (str, optional): End date for the query, if empty, datetime.today() will be used. + Returns: pd.DataFrame: The query result as a pandas DataFrame. """ - vc_obj = VidClub(credentials = self.credentials) + vc_obj = VidClub(credentials = credentials) vc_dataframe = vc_obj.get_response( - source=self.source, from_date=self.from_date, to_date=self.to_date + source=source, from_date=from_date, to_date=to_date ) return vc_dataframe From 04e26276a54f65415887a45e90e9bf1001ed6f0e Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 6 Jul 2023 17:18:57 +0200 Subject: [PATCH 026/106] remove ovverwritting logger --- viadot/tasks/vid_club.py | 1 - 1 file changed, 1 deletion(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 211f7719a..d0a7dc9b6 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -48,7 +48,6 @@ def __init__( Returns: Pandas DataFrame """ - self.logger = prefect.context.get("logger") self.source = source self.from_date = from_date self.to_date = to_date From 2e7b63ea48d2a6569b13d16a6eae17e64f30ddf6 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 7 Jul 2023 11:47:40 +0200 Subject: [PATCH 027/106] fix arg passing --- viadot/sources/vid_club.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 2ba3ebf24..67dab0198 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -128,10 +128,10 @@ def get_response( raise ValidationError("to_date cannot be earlier than from_date.") first_url = self.build_query( - source, - from_date, - to_date, - self.credentials["url"], + source = source, + from_date = from_date, + to_date = to_date, + api_url = self.credentials["url"], items_per_page=items_per_page, ) headers = self.headers From 61b8de503b403540c3cc245c577f66d1aaf981c5 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 7 Jul 2023 13:09:41 +0200 Subject: [PATCH 028/106] update errors in tests --- tests/integration/test_vid_club.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index 30e3f87b7..49ffb5228 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -73,7 +73,7 @@ def test_get_response_sources(mock_api_response, source): @pytest.mark.proper def test_get_response_wrong_date(): with pytest.raises( - ValidationError, match=r"from_date cannot be earlier than 2023-03-22!!" + ValidationError, match=r"from_date cannot be earlier than 2022-03-22" ): vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source="jobs", from_date="2021-05-09") @@ -82,7 +82,7 @@ def test_get_response_wrong_date(): @pytest.mark.proper def test_get_response_wrong_date_range(): with pytest.raises( - ValidationError, match=r"to_date cannot be earlier than from_date!" + ValidationError, match=r"to_date cannot be earlier than from_date" ): vc = VidClub(credentials = CREDENTIALS) query = vc.get_response( From e18bd7510d9661e326fa3fa6c8ae3f31bb218b59 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 7 Jul 2023 13:09:56 +0200 Subject: [PATCH 029/106] change import for fixing issue in tests --- viadot/tasks/vid_club.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index d0a7dc9b6..438f19a48 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -11,7 +11,7 @@ from prefect.utilities import logging from prefect.utilities.tasks import defaults_from_attrs -from viadot.task_utils import credentials_loader +from viadot.task_utils import * from ..sources import VidClub From 371f68ee1f4e4d4b153469ecd7027f7b60ff74fd Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 10 Jul 2023 13:40:39 +0200 Subject: [PATCH 030/106] =?UTF-8?q?=F0=9F=8E=A8=20added=20mailbox=20parame?= =?UTF-8?q?ter=20in=20source.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/sources/outlook.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/viadot/sources/outlook.py b/viadot/sources/outlook.py index dd760fe39..d693ed1db 100644 --- a/viadot/sources/outlook.py +++ b/viadot/sources/outlook.py @@ -149,6 +149,7 @@ def _get_messages_from_mailbox( self, dict_folder: dict, limit: int = 10000, + address_limit: int = 8000, outbox_list: List[str] = ["Sent Items"], ) -> list: """To retrieve all messages from all the mailboxes passed in the dictionary. @@ -157,6 +158,8 @@ def _get_messages_from_mailbox( dict_folder (dict): Mailboxes dictionary holder, with the following structure: "parent (sub)folder|(sub)folder": Mailbox. limit (int, optional): Number of fetched top messages. Defaults to 10000. + address_limit (int, optional): The maximum number of accepted characters in the sum + of all email names. Defaults to 8000. outbox_list (List[str], optional): List of outbox folders to differenciate between Inboxes and Outboxes. Defaults to ["Sent Items"]. @@ -168,6 +171,7 @@ def _get_messages_from_mailbox( count = 0 for message in value.get_messages(limit=limit): received_time = message.received + print("*" * 20) date_obj = datetime.fromisoformat(str(received_time)) if ( self.date_range_start_time.replace(tzinfo=self.utc) @@ -184,7 +188,10 @@ def _get_messages_from_mailbox( if recivers_list is not None: for reciver in recivers_list: add_string = f", {reciver['emailAddress']['address']}" - if sum(list(map(len, [recivers, add_string]))) >= 8000: + if ( + sum(list(map(len, [recivers, add_string]))) + >= address_limit + ): break else: recivers += add_string From 339f4e4ec89e6756d2f4ee31430483287ed65b72 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 10 Jul 2023 13:40:57 +0200 Subject: [PATCH 031/106] =?UTF-8?q?=E2=9C=85=20updated=20source=20test=20f?= =?UTF-8?q?ile.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/test_outlook.py | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/unit/test_outlook.py b/tests/unit/test_outlook.py index 38b98c141..29d291157 100644 --- a/tests/unit/test_outlook.py +++ b/tests/unit/test_outlook.py @@ -21,6 +21,7 @@ def var_dictionary(): "client_secret": "abcdefghijklmnopqrstuvwxyz", "tenant_id": "abcdefghijklmnopqrstuvwxyz", }, + "final_dict_folders": {"Mailbox": MockValue}, } return variables @@ -36,6 +37,42 @@ def mailbox(): return None +class MockValue: + name = "mailbox" + + def get_messages(limit=1): + return [MockMessage] + + +class MockMessage: + subject = "subject" + received = "2023-04-12T06:09:59+00:00" + categories = ["categories"] + conversation_index = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa" + + def to_api_data(): + data = { + "toRecipients": [ + { + "emailAddress": { + "address": "random@random.com", + "name": "random", + } + }, + { + "emailAddress": { + "address": "random@random2.com", + "name": "random", + } + }, + ], + "from": {"emailAddress": {"address": "random@random.ee", "name": "name"}}, + "receivedDateTime": "2022-04-01T06:09:59+00:00", + "conversationId": "bbbb", + } + return data + + @pytest.mark.basics def test_outlook_credentials(var_dictionary): o = Outlook( @@ -53,6 +90,36 @@ def test_outlook_credentials(var_dictionary): ) +@pytest.mark.basics +@mock.patch("viadot.sources.outlook.Account", return_value=MockClass) +def test_outlook_mailbox_limit(mock_api_Account, var_dictionary): + o = Outlook( + mailbox_name=var_dictionary["mailbox_name"], + credentials=var_dictionary["credentials"], + start_date=var_dictionary["start_date"], + end_date=var_dictionary["end_date"], + ) + data = o._get_messages_from_mailbox( + var_dictionary["final_dict_folders"], address_limit=20 + ) + assert len(data[0]["recivers"]) <= 20 + + +@pytest.mark.basics +@mock.patch("viadot.sources.outlook.Account", return_value=MockClass) +def test_outlook_mailbox_space(mock_api_Account, var_dictionary): + o = Outlook( + mailbox_name=var_dictionary["mailbox_name"], + credentials=var_dictionary["credentials"], + start_date=var_dictionary["start_date"], + end_date=var_dictionary["end_date"], + ) + data = o._get_messages_from_mailbox( + var_dictionary["final_dict_folders"], address_limit=5 + ) + assert len(data[0]["recivers"]) == 0 + + @pytest.mark.exceptions def test_outlook_credential_exception(var_dictionary): with pytest.raises(CredentialError): From f9db638ea3abce910266bc70fe011ca800ab9484 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 10 Jul 2023 13:43:38 +0200 Subject: [PATCH 032/106] =?UTF-8?q?=F0=9F=8E=A8=20removed=20print=20statem?= =?UTF-8?q?ent.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/sources/outlook.py | 1 - 1 file changed, 1 deletion(-) diff --git a/viadot/sources/outlook.py b/viadot/sources/outlook.py index d693ed1db..508f95cfc 100644 --- a/viadot/sources/outlook.py +++ b/viadot/sources/outlook.py @@ -171,7 +171,6 @@ def _get_messages_from_mailbox( count = 0 for message in value.get_messages(limit=limit): received_time = message.received - print("*" * 20) date_obj = datetime.fromisoformat(str(received_time)) if ( self.date_range_start_time.replace(tzinfo=self.utc) From 9681fd513bdd861749a5cbe5ee030a453488dde6 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 10 Jul 2023 14:19:47 +0200 Subject: [PATCH 033/106] =?UTF-8?q?=F0=9F=8E=A8=20added=20sleep=20time=20p?= =?UTF-8?q?arameter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/sources/genesys.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/viadot/sources/genesys.py b/viadot/sources/genesys.py index 27e767a96..e2fb31090 100644 --- a/viadot/sources/genesys.py +++ b/viadot/sources/genesys.py @@ -141,6 +141,7 @@ def genesys_api_connection( end_point: str = "analytics/reporting/exports", params: Dict[str, Any] = None, method: Literal["POST", "GET"] = "POST", + sleep_time: int = 0.5, ) -> Optional[dict]: """Function that make POST request method to Genesys API given and endpoint. @@ -149,6 +150,7 @@ def genesys_api_connection( end_point (str, optional): Final end point for Genesys connection. Defaults to "analytics/reporting/exports". params (Dict[str, Any], optional): Parameters to be passed into the POST call. Defaults to None. method (Literal["POST", "GET"], optional): Type of connection to the API. Defaults to "POST". + sleep_time (int, optional): The time, in seconds, to sleep the script between calls to the API. Defaults to 0.5 Returns: Optional[dict]: Dict when the "conversations" endpoint is called, otherwise returns None. @@ -184,7 +186,7 @@ async def generate_post(): ) as resp: new_report = await resp.read() semaphore.release() - await asyncio.sleep(0.5) + await asyncio.sleep(sleep_time) loop = asyncio.get_event_loop() coroutine = generate_post() From 0eb19dba1bb8730e9274ef95b8991b8b27aff5b4 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 10 Jul 2023 16:22:36 +0200 Subject: [PATCH 034/106] logic with time intervals --- viadot/sources/vid_club.py | 63 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 67dab0198..2456e9c6f 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -1,15 +1,17 @@ import json import os import urllib -from datetime import datetime +from datetime import datetime, date, timedelta from typing import Any, Dict, List, Literal - import pandas as pd +from prefect.utilities import logging + from ..exceptions import CredentialError, ValidationError from ..utils import handle_api_response from .base import Source +logger = logging.get_logger() class VidClub(Source): """ @@ -129,6 +131,7 @@ def get_response( first_url = self.build_query( source = source, + from_date = from_date, to_date = to_date, api_url = self.credentials["url"], @@ -167,3 +170,59 @@ def get_response( df = pd.DataFrame(response) return df + + def total_load( + self, + source: Literal["jobs", "product", "company", "survey"] = None, + from_date: str = "2022-03-22", + to_date: str = None, + items_per_page: int = 100, + region: str = "null", + days_interval: int = 30 + ) -> pd.DataFrame: + + + if to_date == None: + end_date = datetime.today().date() + else: + end_date = datetime.strptime(to_date, "%Y-%m-%d").date() + start_date = datetime.strptime(from_date, "%Y-%m-%d").date() + interval = timedelta(days=days_interval) + starts = [] + ends = [] + period_start = start_date + while period_start < end_date: + period_end = min(period_start + interval, end_date) + starts.append(period_start.strftime("%Y-%m-%d")) + ends.append(period_end.strftime("%Y-%m-%d")) + period_start = period_end + + dfs_list = [] + if len(starts) > 0 and len(ends) > 0: + for start, end in zip(starts, ends): + df = self.get_response( + source = source, + from_date = start, + to_date = end, + items_per_page = items_per_page, + region = region, + ) + dfs_list.append(df) + if len(dfs_list) > 1: + df = pd.concat(dfs_list, axis=0, ignore_index=True) + else: + df = pd.DataFrame(dfs_list[0]) + else: + df = self.get_response( + source = source, + from_date = from_date, + to_date = to_date, + items_per_page = items_per_page, + region = region, + ) + df.drop_duplicates(inplace = True) + + if df.empty: + logger.error("No data for this date range") + + return df \ No newline at end of file From 8aaa887b53d8ec1abfe4c4226ef35f67896d629d Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 12 Jul 2023 15:08:22 +0200 Subject: [PATCH 035/106] added docstrings --- viadot/sources/vid_club.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 2456e9c6f..e6ea59979 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -114,7 +114,7 @@ def get_response( "The source has to be: jobs, product, company or survey" ) if to_date == None: - datetime.today().strftime("%Y-%m-%d") + to_date = datetime.today().strftime("%Y-%m-%d") from_date_obj = datetime.strptime(from_date, "%Y-%m-%d") oldest_date_obj = datetime.strptime("2022-03-22", "%Y-%m-%d") @@ -180,6 +180,19 @@ def total_load( region: str = "null", days_interval: int = 30 ) -> pd.DataFrame: + """_summary_ + + Args: + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. + from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. + to_date (str, optional): End date for the query. By default, datetime.today() will be used. + items_per_page (int, optional): Number of entries per page. 100 entries by default. + region (str, optinal): Region filter for the query. By default, it is empty. + days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. + + Returns: + pd.DataFrame: Dataframe of the concatanated data carried in the responses. + """ if to_date == None: From d991c91f8ff4fe16858feef5a46c1071c6bb5a90 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 10:42:05 +0200 Subject: [PATCH 036/106] add loggers --- viadot/sources/vid_club.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index e6ea59979..ed42ceab7 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -213,6 +213,7 @@ def total_load( dfs_list = [] if len(starts) > 0 and len(ends) > 0: for start, end in zip(starts, ends): + logger.info(f"ingesting data for dates {start}-{end}...") df = self.get_response( source = source, from_date = start, @@ -222,6 +223,7 @@ def total_load( ) dfs_list.append(df) if len(dfs_list) > 1: + logger.info("Concatanating tables into one dataframe...") df = pd.concat(dfs_list, axis=0, ignore_index=True) else: df = pd.DataFrame(dfs_list[0]) From ec5a57a839fa9fc28f62b1627d97a0179c4c310c Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 13:59:40 +0200 Subject: [PATCH 037/106] move creating intervals to separate function --- viadot/sources/vid_club.py | 60 +++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index ed42ceab7..acabfee31 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -2,7 +2,7 @@ import os import urllib from datetime import datetime, date, timedelta -from typing import Any, Dict, List, Literal +from typing import Any, Dict, List, Literal, Tuple import pandas as pd from prefect.utilities import logging @@ -55,6 +55,7 @@ def build_query( api_url: str, items_per_page: int, source: Literal["jobs", "product", "company", "survey"] = None, + page_param: bool = True ) -> str: """ Builds the query from the inputs. @@ -65,6 +66,7 @@ def build_query( api_url (str): Generic part of the URL. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. + page_param (bool, optional): Returns: str: Final query with all filters added. @@ -82,6 +84,40 @@ def build_query( ) return url + def intervals( + self, + from_date: str, + to_date: str, + days_interval: int + ) -> Tuple[List[str], List[str]]: + """Breaks dates range into smaller by provided days interval. + + Args: + from_date (str): Start date for the query. + to_date (str): End date for the query. By default, datetime.today() will be used. + days_interval (int): Days specified in date range per api call (test showed that 30-40 is optimal for performance). + + Returns: + List[str], List[str]: Starts abd Ends lists that contains information about date ranges for specific period and time interval. + """ + + if to_date == None: + end_date = datetime.today().date() + else: + end_date = datetime.strptime(to_date, "%Y-%m-%d").date() + start_date = datetime.strptime(from_date, "%Y-%m-%d").date() + interval = timedelta(days=days_interval) + starts = [] + ends = [] + period_start = start_date + while period_start < end_date: + period_end = min(period_start + interval, end_date) + starts.append(period_start.strftime("%Y-%m-%d")) + ends.append(period_end.strftime("%Y-%m-%d")) + period_start = period_end + + return starts, ends + def get_response( self, source: Literal["jobs", "product", "company", "survey"] = None, @@ -180,7 +216,7 @@ def total_load( region: str = "null", days_interval: int = 30 ) -> pd.DataFrame: - """_summary_ + """Creating date ranges for provided time interval by which get_response is looped and stores dataframes in a list. Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. @@ -194,22 +230,12 @@ def total_load( pd.DataFrame: Dataframe of the concatanated data carried in the responses. """ + starts, ends = self.intervals( + from_date = from_date, + to_date = to_date, + days_interval = days_interval + ) - if to_date == None: - end_date = datetime.today().date() - else: - end_date = datetime.strptime(to_date, "%Y-%m-%d").date() - start_date = datetime.strptime(from_date, "%Y-%m-%d").date() - interval = timedelta(days=days_interval) - starts = [] - ends = [] - period_start = start_date - while period_start < end_date: - period_end = min(period_start + interval, end_date) - starts.append(period_start.strftime("%Y-%m-%d")) - ends.append(period_end.strftime("%Y-%m-%d")) - period_start = period_end - dfs_list = [] if len(starts) > 0 and len(ends) > 0: for start, end in zip(starts, ends): From 3d11bea084c884f7247711c46d428d9b02aacb7c Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 14:04:01 +0200 Subject: [PATCH 038/106] update docstrings --- viadot/sources/vid_club.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index acabfee31..c2dc0404d 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -90,7 +90,8 @@ def intervals( to_date: str, days_interval: int ) -> Tuple[List[str], List[str]]: - """Breaks dates range into smaller by provided days interval. + """ + Breaks dates range into smaller by provided days interval. Args: from_date (str): Start date for the query. @@ -216,7 +217,9 @@ def total_load( region: str = "null", days_interval: int = 30 ) -> pd.DataFrame: - """Creating date ranges for provided time interval by which get_response is looped and stores dataframes in a list. + """ + Looping get_response and iterating by date ranges defined in intervals. Stores outputs as DataFrames in a list. + At the end, daframes are concatenated in one and dropped duplicates that would appear when quering. Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. From e807f03200e2d8d89f83b71de5d61e0b945c557f Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 14:16:29 +0200 Subject: [PATCH 039/106] fix loggers --- viadot/sources/vid_club.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index c2dc0404d..c5fd6e821 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -242,7 +242,7 @@ def total_load( dfs_list = [] if len(starts) > 0 and len(ends) > 0: for start, end in zip(starts, ends): - logger.info(f"ingesting data for dates {start}-{end}...") + logger.info(f"ingesting data for dates [{start}]-[{end}]...") df = self.get_response( source = source, from_date = start, @@ -252,7 +252,7 @@ def total_load( ) dfs_list.append(df) if len(dfs_list) > 1: - logger.info("Concatanating tables into one dataframe...") + logger.info("Concatenating tables into one dataframe...") df = pd.concat(dfs_list, axis=0, ignore_index=True) else: df = pd.DataFrame(dfs_list[0]) From d0f88ee965c458abd97e1193d2b20c507fb79ca8 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 14:16:51 +0200 Subject: [PATCH 040/106] replace function in run --- viadot/tasks/vid_club.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 438f19a48..8000da5d0 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -82,6 +82,9 @@ def run( vault_name: str = None, from_date: str = "2022-03-22", to_date: str = "", + items_per_page: int = 100, + region: str = "null", + days_interval: int = 30 ) -> pd.DataFrame: """ Task run method. @@ -100,8 +103,13 @@ def run( vc_obj = VidClub(credentials = credentials) - vc_dataframe = vc_obj.get_response( - source=source, from_date=from_date, to_date=to_date + vc_dataframe = vc_obj.total_load( + source=source, + from_date=from_date, + to_date=to_date, + items_per_page=items_per_page, + region=region, + days_interval=days_interval ) return vc_dataframe From be0fc16a610ca608ec864cce3941eaa5fe5ea1cd Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 16:23:45 +0200 Subject: [PATCH 041/106] add tests --- tests/integration/test_vid_club.py | 60 ++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index 49ffb5228..f31cf6c54 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -2,6 +2,7 @@ import pandas as pd import pytest +from datetime import datetime, timedelta from viadot.exceptions import ValidationError from viadot.task_utils import credentials_loader @@ -9,6 +10,7 @@ CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") +vc = VidClub(credentials = CREDENTIALS) @pytest.fixture def var_dictionary(): @@ -26,12 +28,10 @@ def json(): @pytest.mark.init def test_default_credential_param(): - vc = VidClub(credentials = CREDENTIALS) assert vc.credentials != None and type(vc.credentials) == dict @pytest.mark.init def test_create_club_class(): - vc = VidClub(credentials = CREDENTIALS) assert vc @pytest.mark.proper @@ -39,7 +39,6 @@ def test_build_query_wrong_source(): with pytest.raises( ValidationError, match=r"Pick one these sources: jobs, product, company, survey" ): - vc = VidClub(credentials = CREDENTIALS) query = vc.build_query( source="test", from_date="2023-03-24", @@ -54,7 +53,6 @@ def test_get_response_wrong_source(): with pytest.raises( ValidationError, match=r"The source has to be: jobs, product, company or survey" ): - vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source="test") @@ -64,7 +62,6 @@ def test_get_response_wrong_source(): @pytest.mark.parametrize("source", ["jobs", "company", "product", "survey"]) @pytest.mark.proper def test_get_response_sources(mock_api_response, source): - vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source=source, to_date="2023-03-24", from_date="2023-03-24") assert isinstance(query, pd.DataFrame) @@ -75,7 +72,6 @@ def test_get_response_wrong_date(): with pytest.raises( ValidationError, match=r"from_date cannot be earlier than 2022-03-22" ): - vc = VidClub(credentials = CREDENTIALS) query = vc.get_response(source="jobs", from_date="2021-05-09") @@ -84,7 +80,57 @@ def test_get_response_wrong_date_range(): with pytest.raises( ValidationError, match=r"to_date cannot be earlier than from_date" ): - vc = VidClub(credentials = CREDENTIALS) query = vc.get_response( source="jobs", to_date="2022-05-04", from_date="2022-05-05" ) + +@pytest.mark.test_intervals_split +def test_intervals_split(): + from_date = "2022-01-01" + to_date = "2022-01-19" + days_interval = 5 + expected_starts = ["2022-01-01", "2022-01-06", "2022-01-11", "2022-01-16"] + expected_ends = ["2022-01-06", "2022-01-11", "2022-01-16", "2022-01-19"] + starts, ends = vc.intervals(from_date = from_date, to_date = to_date, days_interval = days_interval) + + assert starts == expected_starts + assert ends == expected_ends + +@pytest.mark.test_total_load_for_the_same_dates +def test_total_load_for_the_same_dates(): + from_date = "2022-04-01" + to_date = "2022-04-01" + days_interval = 10 + source = "jobs" + df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) + + assert isinstance(df, pd.DataFrame) + +@pytest.mark.test_total_load_for_intervals +def test_total_load_for_intervals(): + from_date = "2022-04-01" + to_date = "2022-04-12" + days_interval = 2 + source = "jobs" + + date_object = datetime.strptime(from_date, "%Y-%m-%d") + timedelta(days=days_interval) + one_interval = date_object.strftime("%Y-%m-%d") + + df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) + df_one_interval = vc.total_load(from_date=from_date, to_date=one_interval, days_interval = days_interval, source=source) + + assert isinstance(df, pd.DataFrame) + assert len(df) > len(df_one_interval) + +@pytest.mark.test_drop_duplicates +def test_drop_duplicates(): + from_date = "2022-04-01" + to_date = "2022-04-12" + days_interval = 2 + source = "jobs" + + df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) + dups_mask = df.duplicated() + df_check = df[dups_mask] + + assert len(df_check) == 0 \ No newline at end of file From 39b40b114b3dc93ea2c63f62e84211964296926f Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 13 Jul 2023 16:29:26 +0200 Subject: [PATCH 042/106] update docstrings --- viadot/tasks/vid_club.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 8000da5d0..003f04229 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -96,6 +96,9 @@ def run( vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str, optional): End date for the query, if empty, datetime.today() will be used. + items_per_page (int, optional): Number of entries per page. 100 entries by default. + region (str, optinal): Region filter for the query. By default, it is empty. + days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: pd.DataFrame: The query result as a pandas DataFrame. From 5dfdd5bf7046e585c1f9cc007e9b9cf312ecd279 Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Fri, 14 Jul 2023 09:18:40 +0200 Subject: [PATCH 043/106] =?UTF-8?q?=E2=9C=85=20updated=20genesys=20task=20?= =?UTF-8?q?test=20file.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/tasks/test_genesys_task.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/tasks/test_genesys_task.py b/tests/integration/tasks/test_genesys_task.py index 1d97610a8..286da51c0 100644 --- a/tests/integration/tasks/test_genesys_task.py +++ b/tests/integration/tasks/test_genesys_task.py @@ -44,7 +44,7 @@ def var_dictionary() -> None: class MockGenesysTask: report_data = [[None, "COMPLETED"], [None, "COMPLETED"]] - def genesys_generate_exports(post_data_list, end_point): + def genesys_api_connection(post_data_list, end_point): report = { "conversations": [ { @@ -232,7 +232,7 @@ def test_genesys_conversations(mock_genesys, var_dictionary): to_csv = GenesysToCSV() file_name = to_csv.run( view_type=None, - end_point="conversations/details/query", + end_point="analytics/conversations/details/query", post_data_list=var_dictionary["post_data_list_2"], start_date=var_dictionary["start_date"], ) From bf0677fbbd461e9be3da5d381f13e29638452ebd Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 17 Jul 2023 09:20:16 +0200 Subject: [PATCH 044/106] =?UTF-8?q?=F0=9F=8E=A8=20reduced=20the=20number?= =?UTF-8?q?=20of=20loggs=20to=20show.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/sources/outlook.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/viadot/sources/outlook.py b/viadot/sources/outlook.py index 508f95cfc..b49c5c7b7 100644 --- a/viadot/sources/outlook.py +++ b/viadot/sources/outlook.py @@ -226,7 +226,8 @@ def _get_messages_from_mailbox( row["Inbox"] = True data.append(row) - self.logger.info(f"folder: {key.ljust(76, '-')} messages: {count}") + if count > 0: + self.logger.info(f"folder: {key.ljust(76, '-')} messages: {count}") return data From 6f08a9fb7529ed8fb737c432b8fde23c3567452c Mon Sep 17 00:00:00 2001 From: Diego-H-S Date: Mon, 17 Jul 2023 13:08:40 +0200 Subject: [PATCH 045/106] =?UTF-8?q?=E2=9C=85=20updated=20CHANGELOG.txt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c96429c21..32eba954b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Genesys API call method and the name changed from `genesys_generate_exports` to `genesys_api_connection`. +- Added `GET` connection inside the method `genesys_api_connection`. + +### Removed - Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, `to_df`, `delete_scheduled_report_job` and `generate_reporting_export`. -- Added `GET` connection inside the method `genesys_api_connection`. ## [0.4.17] - 2023-06-15 ### Fixed From bbce513eed44f06e561840e9cc95f5438a4ca070 Mon Sep 17 00:00:00 2001 From: burzekj Date: Mon, 17 Jul 2023 14:16:54 +0200 Subject: [PATCH 046/106] =?UTF-8?q?=E2=9C=A8=20Added=20new=20function=20fo?= =?UTF-8?q?r=20the=20GET=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/flows/genesys_to_adls.py | 8 ++++++ viadot/tasks/genesys.py | 50 +++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/viadot/flows/genesys_to_adls.py b/viadot/flows/genesys_to_adls.py index bdb133be2..639598513 100644 --- a/viadot/flows/genesys_to_adls.py +++ b/viadot/flows/genesys_to_adls.py @@ -91,6 +91,8 @@ def __init__( environment: str = None, report_url: str = None, report_columns: List[str] = None, + conversationId_list: List[str] = None, + key_list: List[str] = None, local_file_path: str = "", adls_file_path: str = None, overwrite_adls: bool = True, @@ -136,6 +138,8 @@ def __init__( from credentials. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. + conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". adls_file_path (str, optional): The destination path at ADLS. Defaults to None. overwrite_adls (bool, optional): Whether to overwrite files in the data lake. Defaults to True. @@ -159,6 +163,8 @@ def __init__( self.environment = environment self.report_url = report_url self.report_columns = report_columns + self.conversationId_list = conversationId_list + self.key_list = key_list self.start_date = start_date self.end_date = end_date self.sep = sep @@ -190,6 +196,8 @@ def gen_flow(self) -> Flow: start_date=self.start_date, end_date=self.end_date, environment=self.environment, + conversationId_list=self.conversationId_list, + key_list=self.key_list, credentials_genesys=self.credentials_genesys, flow=self, ) diff --git a/viadot/tasks/genesys.py b/viadot/tasks/genesys.py index 0b5ca1043..ea07c36dc 100644 --- a/viadot/tasks/genesys.py +++ b/viadot/tasks/genesys.py @@ -1,7 +1,6 @@ import os -import sys import time -from typing import Any, Dict, List, Literal +from typing import Any, Dict, List import numpy as np import pandas as pd @@ -31,6 +30,8 @@ def __init__( report_columns: List[str] = None, local_file_path: str = "", sep: str = "\t", + conversationId_list: List[str] = None, + key_list: List[str] = None, credentials_genesys: Dict[str, Any] = None, timeout: int = 3600, *args: List[Any], @@ -51,6 +52,8 @@ def __init__( report_columns (List[str], optional): List of exisiting column in report. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". sep (str, optional): Separator in csv file. Defaults to "\t". + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. + conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. timeout(int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. """ @@ -67,6 +70,8 @@ def __init__( self.credentials_genesys = credentials_genesys self.local_file_path = local_file_path self.sep = sep + self.conversationId_list = conversationId_list + self.key_list = key_list super().__init__( name=self.report_name, @@ -286,6 +291,8 @@ def merge_conversations_dfs(self, data_to_merge: list) -> DataFrame: "end_date", "report_columns", "credentials_genesys", + "key_list", + "conversationId_list", ) def run( self, @@ -299,6 +306,8 @@ def run( start_date: str = None, end_date: str = None, report_columns: List[str] = None, + conversationId_list: List[str] = None, + key_list: List[str] = None, credentials_genesys: Dict[str, Any] = None, ) -> List[str]: """ @@ -316,6 +325,8 @@ def run( environment (str, optional): Adress of host server. Defaults to None than will be used enviroment from credentials. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. + conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. Returns: List[str]: List of file names. @@ -449,3 +460,38 @@ def run( logger.info("Downloaded the data from the Genesys into the CSV.") return [file_name] + + elif view_type is None and end_point == "conversations": + data_list = [] + + for Id in conversationId_list: + json_file = genesys.genesys_api_connection( + post_data_list=post_data_list, + end_point=f"{end_point}/{Id}", + method="GET", + ) + logger.info(f"Generated webmsg_response for {Id}") + + attributes = json_file["participants"][0]["attributes"] + temp_dict = { + key: value for (key, value) in attributes.items() if key in key_list + } + temp_dict["conversationId"] = json_file["id"] + data_list.append(temp_dict) + + df = pd.DataFrame(data_list) + df = df[df.columns[-1:]].join(df[df.columns[:-1]]) + + start = start_date.replace("-", "") + end = end_date.replace("-", "") + + file_name = f"WebMessage_{start}-{end}".upper() + ".csv" + df.to_csv( + os.path.join(file_name), + index=False, + sep="\t", + ) + + logger.info("Downloaded the data from the Genesys into the CSV.") + + return [file_name] From d536bf5922234308f1cf605cd763a529bfb7eca9 Mon Sep 17 00:00:00 2001 From: Angelika Tarnawa Date: Tue, 18 Jul 2023 13:39:50 +0200 Subject: [PATCH 047/106] =?UTF-8?q?=E2=9C=A8=20Added=20`SQLServerToParquet?= =?UTF-8?q?`=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../flows/test_sql_server_to_parquet.py | 21 +++++++ viadot/flows/__init__.py | 1 + viadot/flows/sql_server_to_parquet.py | 60 +++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 tests/integration/flows/test_sql_server_to_parquet.py create mode 100644 viadot/flows/sql_server_to_parquet.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 53b27d490..a253f2e0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added +- Added `SQLServerToParquet` flow. - Added a new `end_point` parameter in `genesys_api_connection` to make it more generic. ### Fixed diff --git a/tests/integration/flows/test_sql_server_to_parquet.py b/tests/integration/flows/test_sql_server_to_parquet.py new file mode 100644 index 000000000..7c81c1198 --- /dev/null +++ b/tests/integration/flows/test_sql_server_to_parquet.py @@ -0,0 +1,21 @@ +from prefect import Flow + +from viadot.tasks import SQLServerToDF +from viadot.flows import SQLServerToParquet + + +def test_sql_server_to_parquet_flow(): + flow = SQLServerToParquet( + name="test_flow", + sql_query="SELECT * FROM your_table", + local_file_path="test.parquet", + if_exists="fail", + if_empty="skip", + timeout=3600, + ) + flow.gen_flow() + assert isinstance(flow, Flow) + assert len(flow.tasks) == 3 # Number of tasks in the flow + tasks = list(flow.tasks) + + assert isinstance(tasks[0], SQLServerToDF) diff --git a/viadot/flows/__init__.py b/viadot/flows/__init__.py index f91cd087c..ecce1a003 100644 --- a/viadot/flows/__init__.py +++ b/viadot/flows/__init__.py @@ -39,3 +39,4 @@ from .sftp_operations import SftpToADLS, SftpToAzureSQL from .sql_server_to_duckdb import SQLServerToDuckDB from .sql_server_transform import SQLServerTransform +from .sql_server_to_parquet import SQLServerToParquet diff --git a/viadot/flows/sql_server_to_parquet.py b/viadot/flows/sql_server_to_parquet.py new file mode 100644 index 000000000..2f877cf93 --- /dev/null +++ b/viadot/flows/sql_server_to_parquet.py @@ -0,0 +1,60 @@ +from typing import Any, Dict, List, Literal + +from prefect import Flow + +from viadot.task_utils import df_to_parquet +from viadot.tasks import SQLServerToDF + + +class SQLServerToParquet(Flow): + def __init__( + self, + name, + sql_query: str, + local_file_path: str, + sqlserver_config_key: str = None, + if_exists: Literal["fail", "replace", "append", "skip", "delete"] = "fail", + if_empty: Literal["warn", "skip", "fail"] = "skip", + timeout: int = 3600, + *args: List[any], + **kwargs: Dict[str, Any], + ): + """ + Flow for upolading data from SQL Server to Parquet file. + + Args: + name (str): The name of the flow. + sql_query (str, required): The query to execute on the SQL Server database. If don't start with "SELECT" + returns empty DataFrame. + local_file_path (str): Path to output parquet file. + sqlserver_config_key (str, optional): The key inside local config containing the credentials. Defaults to None. + if_exists (Literal, optional): What to do if the table already exists. Defaults to "fail". + if_empty (Literal, optional): What to do if Parquet file is empty. Defaults to "skip". + timeout(int, optional): The amount of time (in seconds) to wait while running this task before + a timeout occurs. Defaults to 3600. + """ + # SQLServerToDF + self.sql_query = sql_query + self.sqlserver_config_key = sqlserver_config_key + self.timeout = timeout + + # DuckDBCreateTableFromParquet + self.local_file_path = local_file_path + self.if_exists = if_exists + self.if_empty = if_empty + + super().__init__(*args, name=name, **kwargs) + + self.gen_flow() + + def gen_flow(self) -> Flow: + df_task = SQLServerToDF(timeout=self.timeout) + df = df_task.bind( + config_key=self.sqlserver_config_key, query=self.sql_query, flow=self + ) + parquet = df_to_parquet.bind( + df=df, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) From 02cb6b962e2e1bbd3079fa62466ff1a566e899cb Mon Sep 17 00:00:00 2001 From: Angelika Tarnawa Date: Tue, 18 Jul 2023 13:43:16 +0200 Subject: [PATCH 048/106] =?UTF-8?q?=F0=9F=94=A5=20removed=20unused=20param?= =?UTF-8?q?eter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/flows/test_sql_server_to_parquet.py | 1 - viadot/flows/sql_server_to_parquet.py | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/integration/flows/test_sql_server_to_parquet.py b/tests/integration/flows/test_sql_server_to_parquet.py index 7c81c1198..e62ed7aa7 100644 --- a/tests/integration/flows/test_sql_server_to_parquet.py +++ b/tests/integration/flows/test_sql_server_to_parquet.py @@ -10,7 +10,6 @@ def test_sql_server_to_parquet_flow(): sql_query="SELECT * FROM your_table", local_file_path="test.parquet", if_exists="fail", - if_empty="skip", timeout=3600, ) flow.gen_flow() diff --git a/viadot/flows/sql_server_to_parquet.py b/viadot/flows/sql_server_to_parquet.py index 2f877cf93..a878abb56 100644 --- a/viadot/flows/sql_server_to_parquet.py +++ b/viadot/flows/sql_server_to_parquet.py @@ -14,7 +14,6 @@ def __init__( local_file_path: str, sqlserver_config_key: str = None, if_exists: Literal["fail", "replace", "append", "skip", "delete"] = "fail", - if_empty: Literal["warn", "skip", "fail"] = "skip", timeout: int = 3600, *args: List[any], **kwargs: Dict[str, Any], @@ -28,8 +27,7 @@ def __init__( returns empty DataFrame. local_file_path (str): Path to output parquet file. sqlserver_config_key (str, optional): The key inside local config containing the credentials. Defaults to None. - if_exists (Literal, optional): What to do if the table already exists. Defaults to "fail". - if_empty (Literal, optional): What to do if Parquet file is empty. Defaults to "skip". + if_exists (Literal, optional): What to do if the file already exists. Defaults to "fail". timeout(int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. """ @@ -38,10 +36,8 @@ def __init__( self.sqlserver_config_key = sqlserver_config_key self.timeout = timeout - # DuckDBCreateTableFromParquet self.local_file_path = local_file_path self.if_exists = if_exists - self.if_empty = if_empty super().__init__(*args, name=name, **kwargs) From de76480e4bf8c94066a617e9466ccb4fa0a765da Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 18 Jul 2023 16:23:47 +0200 Subject: [PATCH 049/106] add check_connection fun --- viadot/sources/vid_club.py | 87 ++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index c5fd6e821..01824f4e0 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -55,7 +55,7 @@ def build_query( api_url: str, items_per_page: int, source: Literal["jobs", "product", "company", "survey"] = None, - page_param: bool = True + region: str = "all", ) -> str: """ Builds the query from the inputs. @@ -66,7 +66,7 @@ def build_query( api_url (str): Generic part of the URL. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - page_param (bool, optional): + region (str, optional): Region filter for the query. Defaults to "all". Returns: str: Final query with all filters added. @@ -75,7 +75,7 @@ def build_query( ValidationError: If any source different than the ones in the list are used. """ if source in ["jobs", "product", "company"]: - url = f"{api_url}{source}?from={from_date}&to={to_date}&limit={items_per_page}" + url = f"{api_url}{source}?from={from_date}&to={to_date}®ion={region}&limit={items_per_page}" elif source in "survey": url = f"{api_url}{source}?language=en&type=question" else: @@ -118,6 +118,43 @@ def intervals( period_start = period_end return starts, ends + + def check_connection( + self, + source: Literal["jobs", "product", "company", "survey"] = None, + from_date: str = "2022-03-22", + to_date: str = None, + items_per_page: int = 100, + region: str = "all" + + ) -> Tuple[Dict[str, Any], str]: + """ + Initiate first connection to API to retrieve piece of data with information about type of pagination in API URL. + This option is added because type of pagination for endpoints is being changed in the future from page number to 'next' id. + + Args: + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. + from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. + to_date (str, optional): End date for the query. By default, datetime.today() will be used. + items_per_page (int, optional): Number of entries per page. 100 entries by default. + region (str, optional): Region filter for the query. Defaults to "all". + + Returns: + Dict[str, Any], str: First response from API with JSON containing data and used URL string + """ + first_url = self.build_query( + source = source, + from_date = from_date, + to_date = to_date, + api_url = self.credentials["url"], + items_per_page=items_per_page, + region = region + ) + headers = self.headers + response = handle_api_response(url=first_url, headers=headers, method="GET", verify=False) + response = response.json() + + return response, first_url def get_response( self, @@ -125,17 +162,17 @@ def get_response( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region="null", + region: str = "all" ) -> pd.DataFrame: """ - Gets the response from the API queried and transforms it into DataFrame. + Basing on the pagination type retrieved using check_connection function, gets the response from the API queried and transforms it into DataFrame. Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optinal): Region filter for the query. By default, it is empty. + region (str, optional): Region filter for the query. Defaults to "all". Returns: pd.DataFrame: Table of the data carried in the response. @@ -145,7 +182,7 @@ def get_response( ValidationError: If the initial date of the query is before the oldest date in the data (2022-03-22). ValidationError: If the final date of the query is before the start date. """ - + headers = self.headers if source not in ["jobs", "product", "company", "survey"]: raise ValidationError( "The source has to be: jobs, product, company or survey" @@ -166,19 +203,13 @@ def get_response( if delta.days < 0: raise ValidationError("to_date cannot be earlier than from_date.") - first_url = self.build_query( + response, first_url = self.check_connection( source = source, - from_date = from_date, to_date = to_date, - api_url = self.credentials["url"], - items_per_page=items_per_page, + items_per_page = items_per_page, + region = region ) - headers = self.headers - - response = handle_api_response(url=first_url, headers=headers, method="GET") - - response = response.json() if isinstance(response, dict): keys_list = list(response.keys()) @@ -187,22 +218,32 @@ def get_response( else: keys_list = [] + if "next" in keys_list: + ind = True + logger.info("Endpoint pagination with 'next' id") + else: + ind = False + logger.info("Endpoint pagination with 'page' number") + if "data" in keys_list: df = pd.DataFrame(response["data"]) length = df.shape[0] - page = 2 + page = 1 while length == items_per_page: - url = f"{first_url}&page={page}" - r = handle_api_response(url=url, headers=headers, method="GET") + if ind == True: + next = response["next"] + url = f"{first_url}&next={next}" + else: + page += 1 + url = f"{first_url}&page={page}" + r = handle_api_response(url=url, headers=headers, method="GET", verify=False) response = r.json() df_page = pd.DataFrame(response["data"]) if source == "product": df_page = df_page.transpose() length = df_page.shape[0] df = pd.concat((df, df_page), axis=0) - page += 1 - else: df = pd.DataFrame(response) @@ -214,7 +255,7 @@ def total_load( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "null", + region: str = "all", days_interval: int = 30 ) -> pd.DataFrame: """ @@ -226,7 +267,7 @@ def total_load( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optinal): Region filter for the query. By default, it is empty. + region (str, optional): Region filter for the query. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: From 03a0f0ebb95fa5257abb5fe72f91c0c1d83288cc Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 18 Jul 2023 18:15:07 +0200 Subject: [PATCH 050/106] update region docstring and formatting --- viadot/sources/vid_club.py | 103 ++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 01824f4e0..23c971a93 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -13,6 +13,7 @@ logger = logging.get_logger() + class VidClub(Source): """ A class implementing the Vid Club API. @@ -21,11 +22,7 @@ class VidClub(Source): There are 4 endpoints where to get the data. """ - def __init__( - self, - *args, - credentials: Dict[str, Any] = None, - **kwargs): + def __init__(self, *args, credentials: Dict[str, Any] = None, **kwargs): """ Create an instance of VidClub. @@ -66,7 +63,7 @@ def build_query( api_url (str): Generic part of the URL. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - region (str, optional): Region filter for the query. Defaults to "all". + region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". Returns: str: Final query with all filters added. @@ -85,10 +82,7 @@ def build_query( return url def intervals( - self, - from_date: str, - to_date: str, - days_interval: int + self, from_date: str, to_date: str, days_interval: int ) -> Tuple[List[str], List[str]]: """ Breaks dates range into smaller by provided days interval. @@ -118,18 +112,17 @@ def intervals( period_start = period_end return starts, ends - + def check_connection( self, source: Literal["jobs", "product", "company", "survey"] = None, from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "all" - + region: str = "all", ) -> Tuple[Dict[str, Any], str]: """ - Initiate first connection to API to retrieve piece of data with information about type of pagination in API URL. + Initiate first connection to API to retrieve piece of data with information about type of pagination in API URL. This option is added because type of pagination for endpoints is being changed in the future from page number to 'next' id. Args: @@ -137,23 +130,25 @@ def check_connection( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Defaults to "all". + region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". Returns: Dict[str, Any], str: First response from API with JSON containing data and used URL string """ first_url = self.build_query( - source = source, - from_date = from_date, - to_date = to_date, - api_url = self.credentials["url"], - items_per_page=items_per_page, - region = region + source=source, + from_date=from_date, + to_date=to_date, + api_url=self.credentials["url"], + items_per_page=items_per_page, + region=region, ) headers = self.headers - response = handle_api_response(url=first_url, headers=headers, method="GET", verify=False) + response = handle_api_response( + url=first_url, headers=headers, method="GET", verify=False + ) response = response.json() - + return response, first_url def get_response( @@ -162,7 +157,7 @@ def get_response( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "all" + region: str = "all", ) -> pd.DataFrame: """ Basing on the pagination type retrieved using check_connection function, gets the response from the API queried and transforms it into DataFrame. @@ -172,7 +167,7 @@ def get_response( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Defaults to "all". + region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". Returns: pd.DataFrame: Table of the data carried in the response. @@ -204,11 +199,11 @@ def get_response( raise ValidationError("to_date cannot be earlier than from_date.") response, first_url = self.check_connection( - source = source, - from_date = from_date, - to_date = to_date, - items_per_page = items_per_page, - region = region + source=source, + from_date=from_date, + to_date=to_date, + items_per_page=items_per_page, + region=region, ) if isinstance(response, dict): @@ -237,7 +232,9 @@ def get_response( else: page += 1 url = f"{first_url}&page={page}" - r = handle_api_response(url=url, headers=headers, method="GET", verify=False) + r = handle_api_response( + url=url, headers=headers, method="GET", verify=False + ) response = r.json() df_page = pd.DataFrame(response["data"]) if source == "product": @@ -256,10 +253,10 @@ def total_load( to_date: str = None, items_per_page: int = 100, region: str = "all", - days_interval: int = 30 + days_interval: int = 30, ) -> pd.DataFrame: """ - Looping get_response and iterating by date ranges defined in intervals. Stores outputs as DataFrames in a list. + Looping get_response and iterating by date ranges defined in intervals. Stores outputs as DataFrames in a list. At the end, daframes are concatenated in one and dropped duplicates that would appear when quering. Args: @@ -267,7 +264,7 @@ def total_load( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Defaults to "all". + region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: @@ -275,39 +272,37 @@ def total_load( """ starts, ends = self.intervals( - from_date = from_date, - to_date = to_date, - days_interval = days_interval + from_date=from_date, to_date=to_date, days_interval=days_interval ) dfs_list = [] - if len(starts) > 0 and len(ends) > 0: + if len(starts) > 0 and len(ends) > 0: for start, end in zip(starts, ends): logger.info(f"ingesting data for dates [{start}]-[{end}]...") df = self.get_response( - source = source, - from_date = start, - to_date = end, - items_per_page = items_per_page, - region = region, + source=source, + from_date=start, + to_date=end, + items_per_page=items_per_page, + region=region, ) dfs_list.append(df) if len(dfs_list) > 1: logger.info("Concatenating tables into one dataframe...") df = pd.concat(dfs_list, axis=0, ignore_index=True) else: - df = pd.DataFrame(dfs_list[0]) + df = pd.DataFrame(dfs_list[0]) else: df = self.get_response( - source = source, - from_date = from_date, - to_date = to_date, - items_per_page = items_per_page, - region = region, - ) - df.drop_duplicates(inplace = True) - + source=source, + from_date=from_date, + to_date=to_date, + items_per_page=items_per_page, + region=region, + ) + df.drop_duplicates(inplace=True) + if df.empty: logger.error("No data for this date range") - - return df \ No newline at end of file + + return df From 66a35c3fe6f56ab102c4bb8bf81e2b0d41972c37 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 10:40:31 +0200 Subject: [PATCH 051/106] add url parameter to check_connection --- viadot/sources/vid_club.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 23c971a93..c7527db16 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -120,6 +120,7 @@ def check_connection( to_date: str = None, items_per_page: int = 100, region: str = "all", + url: str = None, ) -> Tuple[Dict[str, Any], str]: """ Initiate first connection to API to retrieve piece of data with information about type of pagination in API URL. @@ -135,11 +136,14 @@ def check_connection( Returns: Dict[str, Any], str: First response from API with JSON containing data and used URL string """ + if url is None: + url = self.credentials["url"] + first_url = self.build_query( source=source, from_date=from_date, to_date=to_date, - api_url=self.credentials["url"], + api_url=url, items_per_page=items_per_page, region=region, ) From 12468df49f4ce0fdb750c1407975d47857ed5e19 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 10:41:02 +0200 Subject: [PATCH 052/106] add tests --- tests/integration/test_vid_club.py | 90 ++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 23 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index f31cf6c54..af02bc625 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -10,7 +10,8 @@ CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") -vc = VidClub(credentials = CREDENTIALS) +vc = VidClub(credentials=CREDENTIALS) + @pytest.fixture def var_dictionary(): @@ -26,14 +27,17 @@ def json(): df = pd.DataFrame() return df + @pytest.mark.init def test_default_credential_param(): assert vc.credentials != None and type(vc.credentials) == dict + @pytest.mark.init def test_create_club_class(): assert vc + @pytest.mark.proper def test_build_query_wrong_source(): with pytest.raises( @@ -48,6 +52,41 @@ def test_build_query_wrong_source(): ) +@pytest.mark.intervals +def test_intervals_split(): + from_date = "2022-01-01" + to_date = "2022-01-19" + days_interval = 5 + expected_starts = ["2022-01-01", "2022-01-06", "2022-01-11", "2022-01-16"] + expected_ends = ["2022-01-06", "2022-01-11", "2022-01-16", "2022-01-19"] + starts, ends = vc.intervals( + from_date=from_date, to_date=to_date, days_interval=days_interval + ) + + assert starts == expected_starts + assert ends == expected_ends + + +@mock.patch("viadot.sources.vid_club.VidClub.check_connection") +@pytest.mark.connection_check +def test_check_connection(mock_function): + mock_first_output = "Mocked Output" + mock_second_output = "Mocked Output" + mock_function.return_value = mock_first_output, mock_function.return_value[1] + + response, first_url = vc.check_connection( + source="jobs", + from_date="2023-03-24", + to_date="2023-03-24", + url="test", + items_per_page=1, + ) + print(response) + print(first_url) + assert isinstance(first_url, str) + assert len(first_url) > len(mock_second_output) + + @pytest.mark.proper def test_get_response_wrong_source(): with pytest.raises( @@ -65,6 +104,7 @@ def test_get_response_sources(mock_api_response, source): query = vc.get_response(source=source, to_date="2023-03-24", from_date="2023-03-24") assert isinstance(query, pd.DataFrame) + mock_api_response.assert_called_once() @pytest.mark.proper @@ -84,53 +124,57 @@ def test_get_response_wrong_date_range(): source="jobs", to_date="2022-05-04", from_date="2022-05-05" ) -@pytest.mark.test_intervals_split -def test_intervals_split(): - from_date = "2022-01-01" - to_date = "2022-01-19" - days_interval = 5 - expected_starts = ["2022-01-01", "2022-01-06", "2022-01-11", "2022-01-16"] - expected_ends = ["2022-01-06", "2022-01-11", "2022-01-16", "2022-01-19"] - starts, ends = vc.intervals(from_date = from_date, to_date = to_date, days_interval = days_interval) - assert starts == expected_starts - assert ends == expected_ends - -@pytest.mark.test_total_load_for_the_same_dates +@pytest.mark.total_load def test_total_load_for_the_same_dates(): from_date = "2022-04-01" to_date = "2022-04-01" days_interval = 10 source = "jobs" - df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) + df = vc.total_load( + from_date=from_date, to_date=to_date, days_interval=days_interval, source=source + ) assert isinstance(df, pd.DataFrame) -@pytest.mark.test_total_load_for_intervals + +@pytest.mark.total_load def test_total_load_for_intervals(): from_date = "2022-04-01" to_date = "2022-04-12" days_interval = 2 source = "jobs" - - date_object = datetime.strptime(from_date, "%Y-%m-%d") + timedelta(days=days_interval) + + date_object = datetime.strptime(from_date, "%Y-%m-%d") + timedelta( + days=days_interval + ) one_interval = date_object.strftime("%Y-%m-%d") - - df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) - df_one_interval = vc.total_load(from_date=from_date, to_date=one_interval, days_interval = days_interval, source=source) + + df = vc.total_load( + from_date=from_date, to_date=to_date, days_interval=days_interval, source=source + ) + df_one_interval = vc.total_load( + from_date=from_date, + to_date=one_interval, + days_interval=days_interval, + source=source, + ) assert isinstance(df, pd.DataFrame) assert len(df) > len(df_one_interval) -@pytest.mark.test_drop_duplicates + +@pytest.mark.total_load def test_drop_duplicates(): from_date = "2022-04-01" to_date = "2022-04-12" days_interval = 2 source = "jobs" - df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source) + df = vc.total_load( + from_date=from_date, to_date=to_date, days_interval=days_interval, source=source + ) dups_mask = df.duplicated() df_check = df[dups_mask] - assert len(df_check) == 0 \ No newline at end of file + assert len(df_check) == 0 From 33df479183a6bdfc75c5f04bb2e4034e0aa67fde Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 10:53:34 +0200 Subject: [PATCH 053/106] changelog update --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a47b74c30..611433179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### Fixed - +- Fixed issue with credentials handling in `VidClub` source class +- Fixed issue with missing arguments in `VidClubToDF` task class ### Changed - +- Changed looping structure for API calls in `VidClub` source class to use time intervals +- Changed `VidClubToDF` task class to use total_load function from source ## [0.4.17] - 2023-06-15 ### Fixed - Fixed issue with `tzlocal` for O365 package From be3c3390d2edc38aba9cc41ccb6232b073540c00 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 11:19:07 +0200 Subject: [PATCH 054/106] fix conflict --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 611433179..49ee223ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added +- Added `SAPBW` source class +- Added `SAPBWToDF` task class +- Added `SAPBWToADLS` flow class +- Added a new `end_point` parameter in `genesys_api_connection` to make it more generic. ### Fixed +- Fixed a bug in `subject` (extra separator) and in `receivers` (long strings) parameters in Outlook connector. - Fixed issue with credentials handling in `VidClub` source class - Fixed issue with missing arguments in `VidClubToDF` task class + ### Changed +- Genesys API call method and the name changed from `genesys_generate_exports` to `genesys_api_connection`. +- Added `GET` connection inside the method `genesys_api_connection`. - Changed looping structure for API calls in `VidClub` source class to use time intervals - Changed `VidClubToDF` task class to use total_load function from source + +### Removed +- Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, +`to_df`, `delete_scheduled_report_job` and `generate_reporting_export`. + ## [0.4.17] - 2023-06-15 ### Fixed - Fixed issue with `tzlocal` for O365 package From 2cab60d5507fcd113913d9d410598b9aaa11a0e4 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 11:59:04 +0200 Subject: [PATCH 055/106] remove unused params in run --- viadot/tasks/vid_club.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 003f04229..e5788dcbd 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -54,10 +54,10 @@ def __init__( self.report_name = report_name self.credentials_secret = credentials_secret self.vault_name = vault_name - + if credentials is None: self.credentials = credentials_loader.run( - credentials_secret = credentials_secret, vault_name = vault_name + credentials_secret=credentials_secret, vault_name=vault_name ) else: self.credentials = credentials @@ -73,27 +73,30 @@ def __call__(self, *args, **kwargs): """Download Vid Club data to Pandas DataFrame""" return super().__call__(*args, **kwargs) - @defaults_from_attrs("source", "credentials", "credentials_secret", "vault_name", "from_date", "to_date") + @defaults_from_attrs( + "source", + "credentials", + "credentials_secret", + "vault_name", + "from_date", + "to_date", + ) def run( self, source: Literal["jobs", "product", "company", "survey"] = None, credentials: Dict[str, Any] = None, - credentials_secret: str = "VIDCLUB", - vault_name: str = None, from_date: str = "2022-03-22", to_date: str = "", items_per_page: int = 100, region: str = "null", - days_interval: int = 30 - ) -> pd.DataFrame: + days_interval: int = 30, + ) -> pd.DataFrame: """ Task run method. Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. - credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". - vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str, optional): End date for the query, if empty, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. @@ -104,15 +107,15 @@ def run( pd.DataFrame: The query result as a pandas DataFrame. """ - vc_obj = VidClub(credentials = credentials) + vc_obj = VidClub(credentials=credentials) vc_dataframe = vc_obj.total_load( - source=source, - from_date=from_date, - to_date=to_date, - items_per_page=items_per_page, - region=region, - days_interval=days_interval + source=source, + from_date=from_date, + to_date=to_date, + items_per_page=items_per_page, + region=region, + days_interval=days_interval, ) return vc_dataframe From 5641aa14acb1bbdc210020585929095add26cc00 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 11:59:21 +0200 Subject: [PATCH 056/106] update tests --- tests/integration/tasks/test_vid_club.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/integration/tasks/test_vid_club.py b/tests/integration/tasks/test_vid_club.py index 575e2051e..9e9c46c52 100644 --- a/tests/integration/tasks/test_vid_club.py +++ b/tests/integration/tasks/test_vid_club.py @@ -4,6 +4,9 @@ import pytest from viadot.tasks import VidClubToDF +from viadot.task_utils import credentials_loader + +CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") class MockVidClubResponse: @@ -12,7 +15,13 @@ class MockVidClubResponse: @pytest.fixture(scope="session") def var_dictionary(): - variables = {"source": "jobs", "from_date": "2022-03-23", "to_date": "2022-03-24"} + variables = { + "source": "jobs", + "from_date": "2022-03-23", + "to_date": "2022-03-24", + "items_per_page": 1, + "days_interval": 1, + } yield variables @@ -23,12 +32,16 @@ def test_vid_club_to_df(var_dictionary): source = var_dictionary["source"] from_date = var_dictionary["from_date"] to_date = var_dictionary["to_date"] + items_per_page = var_dictionary["items_per_page"] + days_interval = var_dictionary["days_interval"] - vc_to_df = VidClubToDF( + vc_to_df = VidClubToDF(credentials=CREDENTIALS) + df = vc_to_df.run( source=source, to_date=to_date, from_date=from_date, + items_per_page=items_per_page, + days_interval=days_interval, ) - df = vc_to_df.run() assert isinstance(df, pd.DataFrame) From 07028755d93f393680e5096632ff18e38df91a3e Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 12:42:32 +0200 Subject: [PATCH 057/106] update region param --- viadot/tasks/vid_club.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index e5788dcbd..b6abc78aa 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -88,7 +88,7 @@ def run( from_date: str = "2022-03-22", to_date: str = "", items_per_page: int = 100, - region: str = "null", + region: str = "all", days_interval: int = 30, ) -> pd.DataFrame: """ @@ -100,7 +100,7 @@ def run( from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. to_date (str, optional): End date for the query, if empty, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optinal): Region filter for the query. By default, it is empty. + region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: From 0afad882fd3d7998fa9369a872c7037ff7bcc416 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 12:46:56 +0200 Subject: [PATCH 058/106] remove unused attrs --- viadot/tasks/vid_club.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index b6abc78aa..77860f162 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -76,8 +76,6 @@ def __call__(self, *args, **kwargs): @defaults_from_attrs( "source", "credentials", - "credentials_secret", - "vault_name", "from_date", "to_date", ) From a6b96a784b4bd4c7967eeaed3a2c972769f76cb0 Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Fri, 21 Jul 2023 13:17:16 +0200 Subject: [PATCH 059/106] =?UTF-8?q?=E2=9C=85=20Added=20docstring=20to=20bi?= =?UTF-8?q?gquery=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_bigquery.py | 59 +++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index d03e2c637..e3058c650 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -10,12 +10,24 @@ @pytest.fixture(scope="function") def BIGQ(): + """ + Fixture for creating a BigQuery class instance. This fixture initializes a BigQuery client + using the provided credentials key and yieldsthe instance. + The client instance can be used within a test function to interact with BigQuery. + + Yields: + BigQuery: A BigQuery client instance. + """ BQ = BigQuery(credentials_key="BIGQUERY_TESTS") yield BQ @pytest.fixture(scope="session") -def inset_into_tables(): +def insert_into_tables() -> None: + """ + A function to insert data into a BigQuery table. In the current version, tables are deleted + after 60 days. This operation is used to secure tests and structure in a BigQuery project. + """ table_id1 = "manigeo.manigeo_tab" table_id2 = "manigeo.space" df = pd.DataFrame({"my_value": ["val1", "val2", "val3"]}) @@ -33,29 +45,54 @@ def inset_into_tables(): def test_credentials(): + """Test to see if an exception is thrown if credentials are not provided.""" with pytest.raises(CredentialError, match=r"Credentials not found."): _ = BigQuery(credentials_key="BIGQUERY_TESTS_FAKE") def test_list_project(BIGQ): + """ + Testing the correctness of the project name. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ project = BIGQ.get_project_id() assert project == "manifest-geode-341308" def test_list_datasets(BIGQ): + """ + Testing the correctness of dataset names. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ datasets = list(BIGQ.list_datasets()) assert datasets == ["manigeo", "official_empty"] def test_list_tables(BIGQ): + """ + Testing the correctness of table names. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ datasets = BIGQ.list_datasets() tables = list(BIGQ.list_tables(datasets[0])) assert "space" and "manigeo_tab" in tables def test_list_columns(BIGQ): + """ + Testing the validity of a column name in a specific table in BigQuery and the return type. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ columns = BIGQ.list_columns(dataset_name="manigeo", table_name="space") assert "my_value" in columns @@ -63,12 +100,24 @@ def test_list_columns(BIGQ): def test_query_is_df(BIGQ): + """ + Testing the return type of `query_to_df` function. It should be a Data Frame. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ df = BIGQ.query_to_df(QUERY) assert isinstance(df, pd.DataFrame) def test_query(BIGQ): + """ + Testing the corectness of `query_to_df`execution. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ df = BIGQ.query_to_df(QUERY) total_received = df["total"].values @@ -76,6 +125,12 @@ def test_query(BIGQ): def test_wrong_query(BIGQ): + """ + Testing if the exception is raised with invalid query. + + Args: + BIGQ (Bigquery): Bigquery class instance. + """ fake_query = """ SELECT fake_name FROM `bigquery-public-data.usa_names.fake_table` @@ -83,4 +138,4 @@ def test_wrong_query(BIGQ): LIMIT 4 """ with pytest.raises(DBDataAccessError): - _ = BIGQ.query_to_df(fake_query) + BIGQ.query_to_df(fake_query) From 47f457ab1c0187023c5ed9bb19be8c047543e951 Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Fri, 21 Jul 2023 15:01:47 +0200 Subject: [PATCH 060/106] =?UTF-8?q?=E2=9C=85=20Added=20docstring=20to=20sh?= =?UTF-8?q?arepoint=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_bigquery.py | 4 +- tests/integration/test_sharepoint.py | 72 ++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index e3058c650..fdefd4f6f 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -12,8 +12,8 @@ def BIGQ(): """ Fixture for creating a BigQuery class instance. This fixture initializes a BigQuery client - using the provided credentials key and yieldsthe instance. - The client instance can be used within a test function to interact with BigQuery. + using the provided credentials key and yields the class instance. + The class instance can be used within a test function to interact with BigQuery. Yields: BigQuery: A BigQuery client instance. diff --git a/tests/integration/test_sharepoint.py b/tests/integration/test_sharepoint.py index f3013ba66..39874b650 100644 --- a/tests/integration/test_sharepoint.py +++ b/tests/integration/test_sharepoint.py @@ -11,18 +11,34 @@ from viadot.tasks.sharepoint import SharepointToDF -def get_url(): +def get_url() -> str: + """ + Function to get file URL. + + Returns: + str: File URL. + """ return local_config["SHAREPOINT"].get("url") @pytest.fixture(scope="session") def sharepoint(): + """ + Fixture for creating a Sharepoint class instance. + The class instance can be used within a test functions to interact with Sharepoint. + """ s = Sharepoint() yield s @pytest.fixture(scope="session") def FILE_NAME(sharepoint): + """ + A function built to get the path to a file. + + Args: + sharepoint (Sharepoint): Sharepoint class instance. + """ path = "Questionnaires.xlsx" sharepoint.download_file(download_to_path=path, download_from_path=get_url()) yield path @@ -30,12 +46,24 @@ def FILE_NAME(sharepoint): def test_credentials_not_found(): + """ + Testing if a VauleError is thrown when none of credentials are given. + + Args: + sharepoint (Sharepoint): Sharepoint class instance. + """ none_credentials = None with pytest.raises(CredentialError, match=r"Credentials not found."): Sharepoint(credentials=none_credentials) def test_get_connection_credentials(): + """ + Testing if a CredentialError is thrown when credentials doesn't contain required keys. + + Args: + sharepoint (Sharepoint): Sharepoint class instance. + """ credentials = {"site": "tenant.sharepoint.com", "username": "User"} s = Sharepoint(credentials=credentials) with pytest.raises(CredentialError, match="Missing credentials."): @@ -43,6 +71,12 @@ def test_get_connection_credentials(): def test_connection(sharepoint): + """ + Testing if connection is succesfull with given credentials. + + Args: + sharepoint (Sharepoint): Sharepoint class instance. + """ credentials = local_config.get("SHAREPOINT") site = f'https://{credentials["site"]}' conn = sharepoint.get_connection() @@ -51,6 +85,7 @@ def test_connection(sharepoint): def test_sharepoint_to_df_task(): + """Testing if result of `SharepointToDF` is a Data Frame.""" task = SharepointToDF() credentials_secret = PrefectSecret("SHAREPOINT_KV").run() res = task.run( @@ -63,12 +98,24 @@ def test_sharepoint_to_df_task(): os.remove("Questionnaires.xlsx") -def test_download_file(sharepoint): +def test_download_file_missing_patameters(sharepoint): + """ + Testing if a VauleError is thrown when none of the parameters are given. + + Args: + sharepoint (Sharepoint): Sharepoint class instance. + """ with pytest.raises(ValueError, match=r"Missing required parameter"): sharepoint.download_file(download_to_path=None, download_from_path=None) def test_file_download(FILE_NAME): + """ + Testing if file is downloaded. + + Args: + FILE_NAME (str): File name. + """ files = [] for file in os.listdir(): if os.path.isfile(os.path.join(file)): @@ -77,21 +124,40 @@ def test_file_download(FILE_NAME): def test_autopopulating_download_from(FILE_NAME): + """ + Testing if file name is correct. + + Args: + FILE_NAME (str): File name. + """ assert os.path.basename(get_url()) == FILE_NAME -def test_file_extension(sharepoint): +def test_file_extension(): + """Testing if file has correct extension.""" file_ext = (".xlsm", ".xlsx") assert get_url().endswith(file_ext) def test_file_to_df(FILE_NAME): + """ + Testing if downloaded file contains data and if first sheet can be build as a Data frame. + + Args: + FILE_NAME (str): File name. + """ df = pd.read_excel(FILE_NAME, sheet_name=0) df_test = pd.DataFrame(data={"col1": [1, 2]}) assert type(df) == type(df_test) def test_get_data_types(FILE_NAME): + """ + Testing if downloaded file contains data and columns have `String` type. + + Args: + FILE_NAME (str): File name. + """ df = pd.read_excel(FILE_NAME, sheet_name=0) dtypes_map = df_get_data_types_task.run(df) dtypes = dtypes_map.values() From feb22fe05266b4373a26af1513a5f3c393b01e11 Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Fri, 21 Jul 2023 15:56:04 +0200 Subject: [PATCH 061/106] =?UTF-8?q?=E2=9C=85=20Added=20docstring=20to=20bi?= =?UTF-8?q?gquery=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_bigquery.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index fdefd4f6f..d3632293b 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -34,7 +34,7 @@ def insert_into_tables() -> None: pandas_gbq.to_gbq(df, table_id1, if_exists="replace") pandas_gbq.to_gbq(df, table_id2, if_exists="replace") - +# SQL query for public dataset - user with access to Bigquery can also use public tables. QUERY = """ SELECT name, SUM(number) AS total FROM `bigquery-public-data.usa_names.usa_1910_2013` @@ -47,7 +47,7 @@ def insert_into_tables() -> None: def test_credentials(): """Test to see if an exception is thrown if credentials are not provided.""" with pytest.raises(CredentialError, match=r"Credentials not found."): - _ = BigQuery(credentials_key="BIGQUERY_TESTS_FAKE") + BigQuery(credentials_key="BIGQUERY_TESTS_FAKE") def test_list_project(BIGQ): From 86e35b51cadd9bbebbe5b9190e27423f2599ee2f Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 16:35:14 +0200 Subject: [PATCH 062/106] fix default param --- viadot/tasks/vid_club.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 77860f162..4ca376b26 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -26,7 +26,7 @@ def __init__( credentials_secret: str = "VIDCLUB", vault_name: str = None, from_date: str = "2022-03-22", - to_date: str = "", + to_date: str = None, timeout: int = 3600, report_name: str = "vid_club_to_df", *args: List[Any], @@ -41,7 +41,7 @@ def __init__( credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. - to_date (str): End date for the query, if empty, datetime.today() will be used. + to_date (str, optional): End date for the query. By default, datetime.today() will be used. timeout (int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. report_name (str, optional): Stores the report name. Defaults to "vid_club_to_df". @@ -84,7 +84,7 @@ def run( source: Literal["jobs", "product", "company", "survey"] = None, credentials: Dict[str, Any] = None, from_date: str = "2022-03-22", - to_date: str = "", + to_date: str = None, items_per_page: int = 100, region: str = "all", days_interval: int = 30, @@ -96,7 +96,7 @@ def run( source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. - to_date (str, optional): End date for the query, if empty, datetime.today() will be used. + to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. From 5f49dba4efe338c5422151894480fa9847d7a1f8 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Fri, 21 Jul 2023 16:51:58 +0200 Subject: [PATCH 063/106] removed looped loggers --- viadot/sources/vid_club.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index c7527db16..cfb21e72f 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -219,10 +219,8 @@ def get_response( if "next" in keys_list: ind = True - logger.info("Endpoint pagination with 'next' id") else: ind = False - logger.info("Endpoint pagination with 'page' number") if "data" in keys_list: df = pd.DataFrame(response["data"]) @@ -292,7 +290,6 @@ def total_load( ) dfs_list.append(df) if len(dfs_list) > 1: - logger.info("Concatenating tables into one dataframe...") df = pd.concat(dfs_list, axis=0, ignore_index=True) else: df = pd.DataFrame(dfs_list[0]) From 9f96f252f6fe9dcddc5b3b21ccfc33eb3619a324 Mon Sep 17 00:00:00 2001 From: Angelika Tarnawa Date: Mon, 24 Jul 2023 09:24:45 +0200 Subject: [PATCH 064/106] =?UTF-8?q?=F0=9F=93=9D=20updated=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/flows/sql_server_to_parquet.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/flows/sql_server_to_parquet.py b/viadot/flows/sql_server_to_parquet.py index a878abb56..ba54a0a7d 100644 --- a/viadot/flows/sql_server_to_parquet.py +++ b/viadot/flows/sql_server_to_parquet.py @@ -19,13 +19,13 @@ def __init__( **kwargs: Dict[str, Any], ): """ - Flow for upolading data from SQL Server to Parquet file. + Flow for uploading data from SQL Server to Parquet file. Args: - name (str): The name of the flow. + name (str, required): The name of the flow. sql_query (str, required): The query to execute on the SQL Server database. If don't start with "SELECT" returns empty DataFrame. - local_file_path (str): Path to output parquet file. + local_file_path (str, required): Path to output parquet file. sqlserver_config_key (str, optional): The key inside local config containing the credentials. Defaults to None. if_exists (Literal, optional): What to do if the file already exists. Defaults to "fail". timeout(int, optional): The amount of time (in seconds) to wait while running this task before From 0e2104989726217148132adaf2aed33c8a0201d2 Mon Sep 17 00:00:00 2001 From: Angelika Tarnawa Date: Mon, 24 Jul 2023 09:40:45 +0200 Subject: [PATCH 065/106] =?UTF-8?q?=E2=9C=85=20Added=20assert=20to=20check?= =?UTF-8?q?=20if=20file=20is=20created?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flows/test_sql_server_to_parquet.py | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/integration/flows/test_sql_server_to_parquet.py b/tests/integration/flows/test_sql_server_to_parquet.py index e62ed7aa7..e2c12f5b2 100644 --- a/tests/integration/flows/test_sql_server_to_parquet.py +++ b/tests/integration/flows/test_sql_server_to_parquet.py @@ -1,15 +1,31 @@ +import pytest +import os from prefect import Flow from viadot.tasks import SQLServerToDF from viadot.flows import SQLServerToParquet +from viadot.tasks.sql_server import SQLServerQuery +SCHEMA = "sandbox" +TABLE = "test" +PATH = "test.parquet" -def test_sql_server_to_parquet_flow(): + +@pytest.fixture(scope="session") +def create_table(): + query_task = SQLServerQuery("AZURE_SQL") + query_task.run(f"DROP TABLE IF EXISTS {SCHEMA}.{TABLE}") + query_task.run(f"CREATE TABLE {SCHEMA}.{TABLE} (Id INT, Name VARCHAR (10))") + yield True + + +def test_sql_server_to_parquet_flow(create_table): flow = SQLServerToParquet( name="test_flow", - sql_query="SELECT * FROM your_table", - local_file_path="test.parquet", + sql_query=f"SELECT * FROM {SCHEMA}.{TABLE}", + local_file_path=PATH, if_exists="fail", + sqlserver_config_key="AZURE_SQL", timeout=3600, ) flow.gen_flow() @@ -18,3 +34,6 @@ def test_sql_server_to_parquet_flow(): tasks = list(flow.tasks) assert isinstance(tasks[0], SQLServerToDF) + flow.run() + assert os.path.isfile(PATH) == True + os.remove(PATH) From 956700bc5788df246f8395a391e0e5abaa789f4c Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Mon, 24 Jul 2023 16:18:22 +0200 Subject: [PATCH 066/106] =?UTF-8?q?=F0=9F=93=9D=20Updated=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_bigquery.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index d3632293b..8c69fc11a 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -12,7 +12,7 @@ def BIGQ(): """ Fixture for creating a BigQuery class instance. This fixture initializes a BigQuery client - using the provided credentials key and yields the class instance. + using the provided credentials key and yields the class instance. The class instance can be used within a test function to interact with BigQuery. Yields: @@ -25,7 +25,7 @@ def BIGQ(): @pytest.fixture(scope="session") def insert_into_tables() -> None: """ - A function to insert data into a BigQuery table. In the current version, tables are deleted + A function to insert data into a BigQuery table. In the current version, tables are deleted after 60 days. This operation is used to secure tests and structure in a BigQuery project. """ table_id1 = "manigeo.manigeo_tab" @@ -34,7 +34,8 @@ def insert_into_tables() -> None: pandas_gbq.to_gbq(df, table_id1, if_exists="replace") pandas_gbq.to_gbq(df, table_id2, if_exists="replace") -# SQL query for public dataset - user with access to Bigquery can also use public tables. + +# SQL query for public dataset - user with access to Bigquery can also use public datasets and tables. QUERY = """ SELECT name, SUM(number) AS total FROM `bigquery-public-data.usa_names.usa_1910_2013` From a2790a110d8a78065f091226dad84ec1e20f3a53 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 24 Jul 2023 18:48:04 +0200 Subject: [PATCH 067/106] add cols_to_drop param to run method --- viadot/tasks/vid_club.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 4ca376b26..d730ecc7d 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -5,7 +5,6 @@ from typing import Any, Dict, List, Literal import pandas as pd -import prefect from prefect import Task from prefect.tasks.secrets import PrefectSecret from prefect.utilities import logging @@ -88,6 +87,7 @@ def run( items_per_page: int = 100, region: str = "all", days_interval: int = 30, + cols_to_drop: List[str] = None, ) -> pd.DataFrame: """ Task run method. @@ -100,6 +100,11 @@ def run( items_per_page (int, optional): Number of entries per page. 100 entries by default. region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. + cols_to_drop (List[str], optional): List of columns to drop. Defaults to None. + + Raises: + ke: When DataFrame doesn't contain columns provided in the list of columns to drop. + TypeError: When cols_to_drop is not a list type. Returns: pd.DataFrame: The query result as a pandas DataFrame. @@ -115,5 +120,17 @@ def run( region=region, days_interval=days_interval, ) + if cols_to_drop is not None: + if type(cols_to_drop) is list: + try: + vc_dataframe.drop( + columns=cols_to_drop, inplace=True, errors="raise" + ) + except KeyError as ke: + raise ke + else: + raise TypeError("Provide columns to drop in a List.") + else: + pass return vc_dataframe From 80a7d8ccc1e85ec035acdb6de32600eff11cd6ba Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 24 Jul 2023 19:21:31 +0200 Subject: [PATCH 068/106] removed default value for credentials argument --- viadot/sources/vid_club.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index cfb21e72f..52596e53c 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -22,21 +22,17 @@ class VidClub(Source): There are 4 endpoints where to get the data. """ - def __init__(self, *args, credentials: Dict[str, Any] = None, **kwargs): + def __init__(self, credentials: Dict[str, Any], *args, **kwargs): """ Create an instance of VidClub. Args: - credentials (Dict[str, Any], optional): Credentials to Vid Club APIs containing token. - Defaults to dictionary. + credentials (Dict[str, Any]): Credentials to Vid Club APIs containing token. Raises: CredentialError: If credentials are not provided as a parameter. """ - if credentials is not None: - self.credentials = credentials - else: - raise CredentialError("Credentials not provided.") + self.credentials = credentials self.headers = { "Authorization": "Bearer " + credentials["token"], From 6748f4cb6fcb852437665f79234f6d59614867d6 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 24 Jul 2023 19:22:35 +0200 Subject: [PATCH 069/106] updated type of region argument --- viadot/sources/vid_club.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 52596e53c..f887e5d13 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -48,7 +48,7 @@ def build_query( api_url: str, items_per_page: int, source: Literal["jobs", "product", "company", "survey"] = None, - region: str = "all", + region: Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", ) -> str: """ Builds the query from the inputs. @@ -59,7 +59,7 @@ def build_query( api_url (str): Generic part of the URL. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". Returns: str: Final query with all filters added. From a0ed5be46b71e84f7efe20597b83dcac4c0760ed Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 24 Jul 2023 19:30:17 +0200 Subject: [PATCH 070/106] update docstrings --- viadot/sources/vid_club.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index f887e5d13..eaa786451 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -56,7 +56,7 @@ def build_query( Args: from_date (str): Start date for the query. to_date (str): End date for the query, if empty, datetime.today() will be used. - api_url (str): Generic part of the URL. + api_url (str): Generic part of the URL to Vid Club API. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". @@ -89,7 +89,7 @@ def intervals( days_interval (int): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Returns: - List[str], List[str]: Starts abd Ends lists that contains information about date ranges for specific period and time interval. + List[str], List[str]: Starts and Ends lists that contains information about date ranges for specific period and time interval. """ if to_date == None: @@ -128,6 +128,7 @@ def check_connection( to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + url (str, optional): Generic part of the URL to Vid Club API. Defaults to None. Returns: Dict[str, Any], str: First response from API with JSON containing data and used URL string From 1e97380241de2f0796a11a7f2ef8f6eee83878da Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Mon, 24 Jul 2023 20:39:33 +0200 Subject: [PATCH 071/106] update handling wrong dates in intervals --- viadot/sources/vid_club.py | 41 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index eaa786451..354f80947 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -84,12 +84,16 @@ def intervals( Breaks dates range into smaller by provided days interval. Args: - from_date (str): Start date for the query. - to_date (str): End date for the query. By default, datetime.today() will be used. + from_date (str): Start date for the query in "%Y-%m-%d" format. + to_date (str): End date for the query in "%Y-%m-%d" format. By default, datetime.today() will be used. days_interval (int): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Returns: List[str], List[str]: Starts and Ends lists that contains information about date ranges for specific period and time interval. + + Raises: + ValidationError: If the initial date of the query is before the oldest date in the data (2022-03-22). + ValidationError: If the final date of the query is before the start date. """ if to_date == None: @@ -97,16 +101,32 @@ def intervals( else: end_date = datetime.strptime(to_date, "%Y-%m-%d").date() start_date = datetime.strptime(from_date, "%Y-%m-%d").date() + + from_date_obj = datetime.strptime(from_date, "%Y-%m-%d") + oldest_date_obj = datetime.strptime("2022-03-22", "%Y-%m-%d") + delta = from_date_obj - oldest_date_obj + + if delta.days < 0: + raise ValidationError("from_date cannot be earlier than 2022-03-22.") + + to_date_obj = datetime.strptime(to_date, "%Y-%m-%d") + delta = to_date_obj - from_date_obj + + if delta.days < 0: + raise ValidationError("to_date cannot be earlier than from_date.") interval = timedelta(days=days_interval) starts = [] ends = [] + period_start = start_date while period_start < end_date: period_end = min(period_start + interval, end_date) starts.append(period_start.strftime("%Y-%m-%d")) ends.append(period_end.strftime("%Y-%m-%d")) period_start = period_end - + if len(starts) == 0 and len(ends) == 0: + starts.append(from_date) + ends.append(to_date) return starts, ends def check_connection( @@ -175,8 +195,6 @@ def get_response( Raises: ValidationError: If any source different than the ones in the list are used. - ValidationError: If the initial date of the query is before the oldest date in the data (2022-03-22). - ValidationError: If the final date of the query is before the start date. """ headers = self.headers if source not in ["jobs", "product", "company", "survey"]: @@ -186,19 +204,6 @@ def get_response( if to_date == None: to_date = datetime.today().strftime("%Y-%m-%d") - from_date_obj = datetime.strptime(from_date, "%Y-%m-%d") - oldest_date_obj = datetime.strptime("2022-03-22", "%Y-%m-%d") - delta = from_date_obj - oldest_date_obj - - if delta.days < 0: - raise ValidationError("from_date cannot be earlier than 2022-03-22.") - - to_date_obj = datetime.strptime(to_date, "%Y-%m-%d") - delta = to_date_obj - from_date_obj - - if delta.days < 0: - raise ValidationError("to_date cannot be earlier than from_date.") - response, first_url = self.check_connection( source=source, from_date=from_date, From e7623f035a2090d6f8596dd09359f112e9af96a9 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 10:15:26 +0200 Subject: [PATCH 072/106] update docstrings --- viadot/sources/vid_club.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 354f80947..c82645441 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -59,7 +59,7 @@ def build_query( api_url (str): Generic part of the URL to Vid Club API. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". Returns: str: Final query with all filters added. @@ -151,7 +151,7 @@ def check_connection( url (str, optional): Generic part of the URL to Vid Club API. Defaults to None. Returns: - Dict[str, Any], str: First response from API with JSON containing data and used URL string + Tuple[Dict[str, Any], str]: Dictionary with first response from API with JSON containing data and used URL string. """ if url is None: url = self.credentials["url"] @@ -170,7 +170,7 @@ def check_connection( ) response = response.json() - return response, first_url + return (response, first_url) def get_response( self, From 71bf9a77a567c1abacc4bd609a825767be43c8e9 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 10:20:02 +0200 Subject: [PATCH 073/106] uodate docstrings --- viadot/tasks/vid_club.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index d730ecc7d..f9bd6782c 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -25,7 +25,7 @@ def __init__( credentials_secret: str = "VIDCLUB", vault_name: str = None, from_date: str = "2022-03-22", - to_date: str = None, + to_date: str = datetime.today(), timeout: int = 3600, report_name: str = "vid_club_to_df", *args: List[Any], @@ -40,7 +40,7 @@ def __init__( credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. - to_date (str, optional): End date for the query. By default, datetime.today() will be used. + to_date (str, optional): End date for the query. Defaults to datetime.today(). timeout (int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. report_name (str, optional): Stores the report name. Defaults to "vid_club_to_df". @@ -103,7 +103,7 @@ def run( cols_to_drop (List[str], optional): List of columns to drop. Defaults to None. Raises: - ke: When DataFrame doesn't contain columns provided in the list of columns to drop. + KeyError: When DataFrame doesn't contain columns provided in the list of columns to drop. TypeError: When cols_to_drop is not a list type. Returns: From d0a4aac9f14fee4ebc090469543e8b695e8abcd0 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 10:23:03 +0200 Subject: [PATCH 074/106] update code structure in run method --- viadot/tasks/vid_club.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index f9bd6782c..f8aeb2736 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -121,7 +121,7 @@ def run( days_interval=days_interval, ) if cols_to_drop is not None: - if type(cols_to_drop) is list: + if isinstance(cols_to_drop, list): try: vc_dataframe.drop( columns=cols_to_drop, inplace=True, errors="raise" @@ -130,7 +130,5 @@ def run( raise ke else: raise TypeError("Provide columns to drop in a List.") - else: - pass return vc_dataframe From 714ef81cde84e57a677fe9e481cdb8e229800f2c Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 12:42:32 +0200 Subject: [PATCH 075/106] update region parameter --- viadot/sources/vid_club.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index c82645441..78ffb04d0 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -59,7 +59,7 @@ def build_query( api_url (str): Generic part of the URL to Vid Club API. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] Returns: str: Final query with all filters added. @@ -135,7 +135,7 @@ def check_connection( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "all", + region: Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", url: str = None, ) -> Tuple[Dict[str, Any], str]: """ @@ -147,7 +147,7 @@ def check_connection( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] url (str, optional): Generic part of the URL to Vid Club API. Defaults to None. Returns: @@ -178,7 +178,7 @@ def get_response( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "all", + region: Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", ) -> pd.DataFrame: """ Basing on the pagination type retrieved using check_connection function, gets the response from the API queried and transforms it into DataFrame. @@ -188,7 +188,7 @@ def get_response( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] Returns: pd.DataFrame: Table of the data carried in the response. @@ -256,7 +256,7 @@ def total_load( from_date: str = "2022-03-22", to_date: str = None, items_per_page: int = 100, - region: str = "all", + region: Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", days_interval: int = 30, ) -> pd.DataFrame: """ @@ -268,7 +268,7 @@ def total_load( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: From a8873610bfb6770312489ee2dea50dccf24baec8 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 12:49:12 +0200 Subject: [PATCH 076/106] fix logic for checking literal source --- viadot/sources/vid_club.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 78ffb04d0..5e70a14eb 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -69,7 +69,7 @@ def build_query( """ if source in ["jobs", "product", "company"]: url = f"{api_url}{source}?from={from_date}&to={to_date}®ion={region}&limit={items_per_page}" - elif source in "survey": + elif source in ["survey"]: url = f"{api_url}{source}?language=en&type=question" else: raise ValidationError( From ae509bfcbf30a532474de93a40553e2818ae10e7 Mon Sep 17 00:00:00 2001 From: burzekj Date: Tue, 25 Jul 2023 14:27:07 +0200 Subject: [PATCH 077/106] Updated docstring --- viadot/flows/genesys_to_adls.py | 2 +- viadot/tasks/genesys.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/viadot/flows/genesys_to_adls.py b/viadot/flows/genesys_to_adls.py index 639598513..29bd2bb65 100644 --- a/viadot/flows/genesys_to_adls.py +++ b/viadot/flows/genesys_to_adls.py @@ -138,8 +138,8 @@ def __init__( from credentials. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. - key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". adls_file_path (str, optional): The destination path at ADLS. Defaults to None. overwrite_adls (bool, optional): Whether to overwrite files in the data lake. Defaults to True. diff --git a/viadot/tasks/genesys.py b/viadot/tasks/genesys.py index ea07c36dc..e61e2bc6a 100644 --- a/viadot/tasks/genesys.py +++ b/viadot/tasks/genesys.py @@ -52,8 +52,8 @@ def __init__( report_columns (List[str], optional): List of exisiting column in report. Defaults to None. local_file_path (str, optional): The local path from which to upload the file(s). Defaults to "". sep (str, optional): Separator in csv file. Defaults to "\t". - key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. timeout(int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. """ @@ -291,8 +291,8 @@ def merge_conversations_dfs(self, data_to_merge: list) -> DataFrame: "end_date", "report_columns", "credentials_genesys", - "key_list", "conversationId_list", + "key_list", ) def run( self, @@ -325,8 +325,8 @@ def run( environment (str, optional): Adress of host server. Defaults to None than will be used enviroment from credentials. report_url (str, optional): The url of report generated in json response. Defaults to None. report_columns (List[str], optional): List of exisiting column in report. Defaults to None. - key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. conversationId_list (List[str], optional): List of conversationId passed as attribute of GET method. Defaults to None. + key_list (List[str], optional): List of keys needed to specify the columns in the GET request method. Defaults to None. Returns: List[str]: List of file names. From d6fcb8766e95259c8d1ccd0e4a2b25626471cc63 Mon Sep 17 00:00:00 2001 From: burzekj Date: Tue, 25 Jul 2023 14:30:48 +0200 Subject: [PATCH 078/106] =?UTF-8?q?=F0=9F=8E=A8=20changed=20structure=20of?= =?UTF-8?q?=20elif=20statment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viadot/tasks/genesys.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/viadot/tasks/genesys.py b/viadot/tasks/genesys.py index e61e2bc6a..403ed7081 100644 --- a/viadot/tasks/genesys.py +++ b/viadot/tasks/genesys.py @@ -464,13 +464,13 @@ def run( elif view_type is None and end_point == "conversations": data_list = [] - for Id in conversationId_list: + for id in conversationId_list: json_file = genesys.genesys_api_connection( post_data_list=post_data_list, - end_point=f"{end_point}/{Id}", + end_point=f"{end_point}/{id}", method="GET", ) - logger.info(f"Generated webmsg_response for {Id}") + logger.info(f"Generated webmsg_response for {id}") attributes = json_file["participants"][0]["attributes"] temp_dict = { @@ -485,7 +485,7 @@ def run( start = start_date.replace("-", "") end = end_date.replace("-", "") - file_name = f"WebMessage_{start}-{end}".upper() + ".csv" + file_name = f"WEBMESSAGE_{start}-{end}.csv" df.to_csv( os.path.join(file_name), index=False, From 7422a6adeb033672633ebf65c9db0247f32cd548 Mon Sep 17 00:00:00 2001 From: burzekj Date: Tue, 25 Jul 2023 14:35:15 +0200 Subject: [PATCH 079/106] =?UTF-8?q?=E2=9C=85=20Added=20task=20test,=20CHAN?= =?UTF-8?q?GELOG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + tests/integration/tasks/test_genesys_task.py | 355 +++++++++++-------- 2 files changed, 218 insertions(+), 139 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec480b2e6..bf69dfa0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Added new if-statment for `run()` inside `GenesysToCSV` task class to extract webmessage files. ### Added - Added `SQLServerToParquet` flow. - Added `SAPBW` source class diff --git a/tests/integration/tasks/test_genesys_task.py b/tests/integration/tasks/test_genesys_task.py index 286da51c0..f49668339 100644 --- a/tests/integration/tasks/test_genesys_task.py +++ b/tests/integration/tasks/test_genesys_task.py @@ -12,6 +12,12 @@ def var_dictionary() -> None: variables = { "start_date": datetime.now().strftime("%Y-%m-%d"), + "end_date": datetime.now().strftime("%Y-%m-%d"), + "v_list": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1", + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2", + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx3"], + "key_list": ["MainIntent", "SubIntent", "Final Sub Intent", + "CustomerOutcomeTrack", "LastUtterance", "Final Main Intent"], "post_data_list": [ { "name": "AGENT_STATUS_DETAIL_VIEW", @@ -40,148 +46,198 @@ def var_dictionary() -> None: } return variables - class MockGenesysTask: - report_data = [[None, "COMPLETED"], [None, "COMPLETED"]] - - def genesys_api_connection(post_data_list, end_point): - report = { - "conversations": [ - { - "conversationEnd": "2020-01-01T00:00:00.00Z", - "conversationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "conversationStart": "2020-01-01T00:00:00.00Z", - "divisionIds": [ - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - ], - "mediaStatsMinConversationMos": 4.379712366260067, - "mediaStatsMinConversationRFactor": 79.03050231933594, - "originatingDirection": "inbound", - "participants": [ - { - "externalContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "participantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "participantName": "Mobile Number, Country", - "purpose": "customer", - "sessions": [ - { - "agentBullseyeRing": 1, - "ani": "tel:+xxxxxxxxxxx", - "direction": "inbound", - "dnis": "tel:+xxxxxxxxxxx", - "edgeId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "mediaType": "voice", - "protocolCallId": "xxxxxxxxxxxxxxxxxxx@xx.xxx.xxx.xxx", - "provider": "Edge", - "remoteNameDisplayable": "Mobile Number, Country", - "requestedRoutings": ["Standard"], - "routingRing": 1, - "selectedAgentId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "sessionDnis": "tel:+xxxxxxxxxxx", - "sessionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "usedRouting": "Standard", - "mediaEndpointStats": [ - { - "codecs": ["audio/opus"], - "eventTime": "2020-01-01T00:00:00.00Z", - "maxLatencyMs": 30, - "minMos": 4.882504366160681, - "minRFactor": 92.44775390625, - "receivedPackets": 229, - }, - ], - "metrics": [ - { - "emitDate": "2020-01-01T00:00:00.00Z", - "name": "nConnected", - "value": 1, - }, - ], - "segments": [ - { - "conference": False, - "segmentEnd": "2020-01-01T00:00:00.00Z", - "segmentStart": "2020-01-01T00:00:00.00Z", - "segmentType": "system", - }, - { - "conference": False, - "disconnectType": "peer", - "queueId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "segmentEnd": "2020-01-01T00:00:00.00Z", - "segmentStart": "2020-01-01T00:00:00.00Z", - "segmentType": "interact", - }, - ], - } - ], + report_data = [[None, "COMPLETED"], [None, "COMPLETED"]], + + def genesys_api_connection(post_data_list, end_point, method="POST"): + if method == "GET": + report = { + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "startTime": "2023-06-28T10:59:48.194Z", + "participants": [ + { + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "startTime": "2023-06-28T10:59:48.194Z", + "connectedTime": "2023-06-28T10:59:48.194Z", + "externalContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "queueId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "queueName": "dev_name", + "purpose": "customer", + "wrapupRequired": None, + "mediaRoles": [ + "full" + ], + "attributes": { + "MainIntent3": "mainintent3", + "SubIntent3": "subintent3", + "SubIntent2": "subintent2", + "MainIntent4": "mainintent4", + "MainIntent1": "mainintent1", + "SubIntent1": "subintent1", + "MainIntent2": "mainintent2", + "Final Sub Intent": "finalsubintent", + "SubIntent4": "subintent4", + "CustomerOutcomeTrack4": "customeroutcome4", + "CustomerOutcomeTrack3": "customeroutcome3", + "CustomerOutcomeTrack2": "customeroutcome2", + "CustomerOutcomeTrack1": "customeroutcome1", + "LastUtterance2": "lastutterance2", + "reached": "reach", + "LastUtterance1": "lastutterance1", + "name": "dev_name", + "Final Main Intent": "finalmainintent", + "LastUtterance4": "lastutterance4", + "LastUtterance3": "lastutterance3", + "LOB": "lob", + "memberId": "123456789" }, - { - "participantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "participantName": "xxxxxxxxxxxxxxxxxxxxx", - "purpose": "ivr", - "sessions": [ - { - "ani": "tel:+xxxxxxxxxxx", - "direction": "inbound", - "dnis": "tel:+xxxxxxxxxxx", - "edgeId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "mediaType": "voice", - "peerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "protocolCallId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "provider": "Edge", - "remote": "Mobile Number, Country", - "remoteNameDisplayable": "xxxxxxxx, Country", - "sessionDnis": "tel:+xxxxxxxxxxx", - "sessionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "mediaEndpointStats": [ - { - "codecs": ["audio/opus"], - "eventTime": "2020-01-01T00:00:00.00Z", - "maxLatencyMs": 30, - "minMos": 4.429814389713434, - "minRFactor": 79.03050231933594, - "receivedPackets": 229, - } - ], - "flow": { - "endingLanguage": "lt-lt", - "entryReason": "tel:+xxxxxxxxxxx", - "entryType": "dnis", - "exitReason": "TRANSFER", - "flowId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "flowName": "xxxxxxxxxxxxxxxxxxxxx", - "flowType": "INBOUNDCALL", - "flowVersion": "22.0", - "startingLanguage": "en-us", - "transferTargetAddress": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "transferTargetName": "xxxxxxxxxxxxxxxxxxxxx", - "transferType": "ACD", - }, - "metrics": [ - { - "emitDate": "2020-01-01T00:00:00.00Z", - "name": "nFlow", - "value": 1, - }, - ], - "segments": [ - { - "conference": False, - "segmentEnd": "2020-01-01T00:00:00.00Z", - "segmentStart": "2020-01-01T00:00:00.00Z", - "segmentType": "system", + "calls": [], + "callbacks": [], + "chats": [], + "cobrowsesessions": [], + "emails": [], + "messages": [], + } + ] + } + else: + report = { + "conversations": [ + { + "conversationEnd": "2020-01-01T00:00:00.00Z", + "conversationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "conversationStart": "2020-01-01T00:00:00.00Z", + "divisionIds": [ + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + ], + "mediaStatsMinConversationMos": 4.379712366260067, + "mediaStatsMinConversationRFactor": 79.03050231933594, + "originatingDirection": "inbound", + "participants": [ + { + "externalContactId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "participantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "participantName": "Mobile Number, Country", + "purpose": "customer", + "sessions": [ + { + "agentBullseyeRing": 1, + "ani": "tel:+xxxxxxxxxxx", + "direction": "inbound", + "dnis": "tel:+xxxxxxxxxxx", + "edgeId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "mediaType": "voice", + "protocolCallId": "xxxxxxxxxxxxxxxxxxx@xx.xxx.xxx.xxx", + "provider": "Edge", + "remoteNameDisplayable": "Mobile Number, Country", + "requestedRoutings": ["Standard"], + "routingRing": 1, + "selectedAgentId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "sessionDnis": "tel:+xxxxxxxxxxx", + "sessionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "usedRouting": "Standard", + "mediaEndpointStats": [ + { + "codecs": ["audio/opus"], + "eventTime": "2020-01-01T00:00:00.00Z", + "maxLatencyMs": 30, + "minMos": 4.882504366160681, + "minRFactor": 92.44775390625, + "receivedPackets": 229, + }, + ], + "metrics": [ + { + "emitDate": "2020-01-01T00:00:00.00Z", + "name": "nConnected", + "value": 1, + }, + ], + "segments": [ + { + "conference": False, + "segmentEnd": "2020-01-01T00:00:00.00Z", + "segmentStart": "2020-01-01T00:00:00.00Z", + "segmentType": "system", + }, + { + "conference": False, + "disconnectType": "peer", + "queueId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "segmentEnd": "2020-01-01T00:00:00.00Z", + "segmentStart": "2020-01-01T00:00:00.00Z", + "segmentType": "interact", + }, + ], + } + ], + }, + { + "participantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "participantName": "xxxxxxxxxxxxxxxxxxxxx", + "purpose": "ivr", + "sessions": [ + { + "ani": "tel:+xxxxxxxxxxx", + "direction": "inbound", + "dnis": "tel:+xxxxxxxxxxx", + "edgeId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "mediaType": "voice", + "peerId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "protocolCallId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "provider": "Edge", + "remote": "Mobile Number, Country", + "remoteNameDisplayable": "xxxxxxxx, Country", + "sessionDnis": "tel:+xxxxxxxxxxx", + "sessionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "mediaEndpointStats": [ + { + "codecs": ["audio/opus"], + "eventTime": "2020-01-01T00:00:00.00Z", + "maxLatencyMs": 30, + "minMos": 4.429814389713434, + "minRFactor": 79.03050231933594, + "receivedPackets": 229, + } + ], + "flow": { + "endingLanguage": "lt-lt", + "entryReason": "tel:+xxxxxxxxxxx", + "entryType": "dnis", + "exitReason": "TRANSFER", + "flowId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "flowName": "xxxxxxxxxxxxxxxxxxxxx", + "flowType": "INBOUNDCALL", + "flowVersion": "22.0", + "startingLanguage": "en-us", + "transferTargetAddress": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "transferTargetName": "xxxxxxxxxxxxxxxxxxxxx", + "transferType": "ACD", }, - ], - } - ], - }, - ], - } - ], - "totalHits": 100, - } + "metrics": [ + { + "emitDate": "2020-01-01T00:00:00.00Z", + "name": "nFlow", + "value": 1, + }, + ], + "segments": [ + { + "conference": False, + "segmentEnd": "2020-01-01T00:00:00.00Z", + "segmentStart": "2020-01-01T00:00:00.00Z", + "segmentType": "system", + }, + ], + } + ], + }, + ], + } + ], + "totalHits": 100, + } return report def get_reporting_exports_data(): @@ -240,3 +296,24 @@ def test_genesys_conversations(mock_genesys, var_dictionary): mock_genesys.assert_called_once() assert file_name[0] == f"conversations_detail_{date}".upper() + ".csv" + + +@mock.patch("viadot.tasks.genesys.Genesys", return_value=MockGenesysTask) +@pytest.mark.conv +def test_genesys_webmsg(mock_genesys, var_dictionary): + to_csv = GenesysToCSV() + file_name = to_csv.run( + view_type=None, + end_point="conversations", + conversationId_list=var_dictionary["v_list"], + post_data_list=[""], + key_list=var_dictionary["key_list"], + start_date=var_dictionary["start_date"], + end_date=var_dictionary["end_date"] + ) + + start = var_dictionary["start_date"].replace("-", "") + end = var_dictionary["end_date"].replace("-", "") + + mock_genesys.assert_called_once() + assert file_name[0] == f"WEBMESSAGE_{start}-{end}.csv" \ No newline at end of file From 431ba251f7933645dd54aa940b8db081b5a0e3c1 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 14:45:22 +0200 Subject: [PATCH 080/106] add valueerror for from_date in get_response --- viadot/sources/vid_club.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 5e70a14eb..426e67280 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -195,6 +195,7 @@ def get_response( Raises: ValidationError: If any source different than the ones in the list are used. + ValidationError: If from_date is earlier than 2022-03-22. """ headers = self.headers if source not in ["jobs", "product", "company", "survey"]: @@ -204,6 +205,9 @@ def get_response( if to_date == None: to_date = datetime.today().strftime("%Y-%m-%d") + if from_date < "2022-03-22": + raise ValidationError("from_date cannot be earlier than 2022-03-22.") + response, first_url = self.check_connection( source=source, from_date=from_date, From 7e01476a600075bb01e8fc7fd27e345e68d1d0a1 Mon Sep 17 00:00:00 2001 From: Jakub Burzec <125436423+burzekj@users.noreply.github.com> Date: Tue, 25 Jul 2023 14:49:16 +0200 Subject: [PATCH 081/106] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rafał Ziemianek <49795849+Rafalz13@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf69dfa0e..eb7792e4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Changed -- Added new if-statment for `run()` inside `GenesysToCSV` task class to extract webmessage files. +- Added new parameters in the `GenesysToCSV` task to be able to extract `web message` files. ### Added - Added `SQLServerToParquet` flow. - Added `SAPBW` source class From 2387163e64f4c9e55d7becdf642fea8b831a95b1 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:01:03 +0200 Subject: [PATCH 082/106] update dealing with wrong date ranges --- viadot/sources/vid_club.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 426e67280..61ee18408 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -92,7 +92,6 @@ def intervals( List[str], List[str]: Starts and Ends lists that contains information about date ranges for specific period and time interval. Raises: - ValidationError: If the initial date of the query is before the oldest date in the data (2022-03-22). ValidationError: If the final date of the query is before the start date. """ @@ -103,17 +102,13 @@ def intervals( start_date = datetime.strptime(from_date, "%Y-%m-%d").date() from_date_obj = datetime.strptime(from_date, "%Y-%m-%d") - oldest_date_obj = datetime.strptime("2022-03-22", "%Y-%m-%d") - delta = from_date_obj - oldest_date_obj - - if delta.days < 0: - raise ValidationError("from_date cannot be earlier than 2022-03-22.") to_date_obj = datetime.strptime(to_date, "%Y-%m-%d") delta = to_date_obj - from_date_obj if delta.days < 0: raise ValidationError("to_date cannot be earlier than from_date.") + interval = timedelta(days=days_interval) starts = [] ends = [] @@ -152,7 +147,18 @@ def check_connection( Returns: Tuple[Dict[str, Any], str]: Dictionary with first response from API with JSON containing data and used URL string. + + Raises: + ValidationError: If from_date is earlier than 2022-03-22. + ValidationError: If to_date is earlier than from_date. """ + + if from_date < "2022-03-22": + raise ValidationError("from_date cannot be earlier than 2022-03-22.") + + if to_date < from_date: + raise ValidationError("to_date cannot be earlier than from_date.") + if url is None: url = self.credentials["url"] @@ -195,7 +201,6 @@ def get_response( Raises: ValidationError: If any source different than the ones in the list are used. - ValidationError: If from_date is earlier than 2022-03-22. """ headers = self.headers if source not in ["jobs", "product", "company", "survey"]: @@ -205,9 +210,6 @@ def get_response( if to_date == None: to_date = datetime.today().strftime("%Y-%m-%d") - if from_date < "2022-03-22": - raise ValidationError("from_date cannot be earlier than 2022-03-22.") - response, first_url = self.check_connection( source=source, from_date=from_date, From 1de394d028a5c1ec0be7d48bc624f0d0aa894e93 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:01:57 +0200 Subject: [PATCH 083/106] update elif --- viadot/sources/vid_club.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 61ee18408..20f9f7815 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -69,7 +69,7 @@ def build_query( """ if source in ["jobs", "product", "company"]: url = f"{api_url}{source}?from={from_date}&to={to_date}®ion={region}&limit={items_per_page}" - elif source in ["survey"]: + elif source == "survey": url = f"{api_url}{source}?language=en&type=question" else: raise ValidationError( From ccac7d9bf7da3bfdc56a2035c56fecf9a57c991d Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:04:34 +0200 Subject: [PATCH 084/106] update docstring --- viadot/sources/vid_club.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 20f9f7815..11af2cb3e 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -59,7 +59,7 @@ def build_query( api_url (str): Generic part of the URL to Vid Club API. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] Returns: str: Final query with all filters added. From 6bac993b6ec913e4fbb8639293e34afb3dec9dc3 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:05:21 +0200 Subject: [PATCH 085/106] remove credentials param assignment in init --- viadot/sources/vid_club.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 11af2cb3e..a0fbf6409 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -32,8 +32,6 @@ def __init__(self, credentials: Dict[str, Any], *args, **kwargs): Raises: CredentialError: If credentials are not provided as a parameter. """ - self.credentials = credentials - self.headers = { "Authorization": "Bearer " + credentials["token"], "Content-Type": "application/json", From 83f2d8bfde4c037e544efb89655b7c165f7efd0b Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:06:18 +0200 Subject: [PATCH 086/106] update docstring --- viadot/sources/vid_club.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index a0fbf6409..3044ef10a 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -140,7 +140,7 @@ def check_connection( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] url (str, optional): Generic part of the URL to Vid Club API. Defaults to None. Returns: @@ -192,7 +192,7 @@ def get_response( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] Returns: pd.DataFrame: Table of the data carried in the response. @@ -272,7 +272,7 @@ def total_load( from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. to_date (str, optional): End date for the query. By default, datetime.today() will be used. items_per_page (int, optional): Number of entries per page. 100 entries by default. - region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2022 status: parameter works only for 'all' on API] + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. Returns: From a604802a57be9c3f2cbea898015a079ca614e835 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:14:07 +0200 Subject: [PATCH 087/106] update tests with build_query test and docstrings --- tests/integration/test_vid_club.py | 105 +++++++++++++++++++++++------ 1 file changed, 86 insertions(+), 19 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index af02bc625..35dabbba5 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -30,16 +30,18 @@ def json(): @pytest.mark.init def test_default_credential_param(): - assert vc.credentials != None and type(vc.credentials) == dict - + """ + Checks if credentials are loaded from Azure Key Vault or PrefectSecret or from local config ursing credentials_loader and if it's dictionary type. -@pytest.mark.init -def test_create_club_class(): - assert vc + """ + assert vc.credentials != None and type(vc.credentials) == dict -@pytest.mark.proper +@pytest.mark.build_query def test_build_query_wrong_source(): + """ + Checks if passing different source than Literal["jobs", "product", "company", "survey"] is catched and returns error. + """ with pytest.raises( ValidationError, match=r"Pick one these sources: jobs, product, company, survey" ): @@ -52,8 +54,42 @@ def test_build_query_wrong_source(): ) +@pytest.mark.build_query +def test_url_string(): + """ + Checks if fucntion generates URL with needed parameters. + """ + source = "jobs" + from_date = "2023-03-24" + to_date = "2023-03-24" + api_url = "https://api/test/" + items_per_page = 1 + + expected_elements = [ + f"from={from_date}", + f"to={to_date}", + "region=all", + f"limit={items_per_page}", + api_url, + ] + + query = vc.build_query( + source=source, + from_date=from_date, + to_date=to_date, + api_url=api_url, + items_per_page=items_per_page, + ) + + for ex in expected_elements: + assert ex in query + + @pytest.mark.intervals def test_intervals_split(): + """ + Checks if prrovided date range with days_interval creates list with expected split. + """ from_date = "2022-01-01" to_date = "2022-01-19" days_interval = 5 @@ -67,28 +103,35 @@ def test_intervals_split(): assert ends == expected_ends -@mock.patch("viadot.sources.vid_club.VidClub.check_connection") @pytest.mark.connection_check -def test_check_connection(mock_function): - mock_first_output = "Mocked Output" - mock_second_output = "Mocked Output" - mock_function.return_value = mock_first_output, mock_function.return_value[1] +def test_check_connection(): + """ + Checks if check_connection method returns tuple with dictionary and string. + """ + output = vc.check_connection( + source="jobs", + from_date="2023-03-24", + to_date="2023-03-24", + items_per_page=1, + ) response, first_url = vc.check_connection( source="jobs", from_date="2023-03-24", to_date="2023-03-24", - url="test", items_per_page=1, ) - print(response) - print(first_url) + + assert isinstance(output, tuple) + assert isinstance(response, dict) assert isinstance(first_url, str) - assert len(first_url) > len(mock_second_output) @pytest.mark.proper def test_get_response_wrong_source(): + """ + Checks if ValidationError is returned when passing wrong source name. + """ with pytest.raises( ValidationError, match=r"The source has to be: jobs, product, company or survey" ): @@ -101,6 +144,14 @@ def test_get_response_wrong_source(): @pytest.mark.parametrize("source", ["jobs", "company", "product", "survey"]) @pytest.mark.proper def test_get_response_sources(mock_api_response, source): + """ + Checks if get_response method returnes DataFrame for each of the 4 possible sources. + Test assert that the mock was called exactly once. + + Args: + mock_api_response: Mocked return_value for get_response method. + source: The endpoint source to be accessed. + """ query = vc.get_response(source=source, to_date="2023-03-24", from_date="2023-03-24") assert isinstance(query, pd.DataFrame) @@ -109,24 +160,32 @@ def test_get_response_sources(mock_api_response, source): @pytest.mark.proper def test_get_response_wrong_date(): + """ + Checks if ValidationError is returned when passing from_date earlier than 2022-03-22. + """ with pytest.raises( ValidationError, match=r"from_date cannot be earlier than 2022-03-22" ): - query = vc.get_response(source="jobs", from_date="2021-05-09") + vc.get_response(source="jobs", from_date="2021-05-09") @pytest.mark.proper def test_get_response_wrong_date_range(): + """ + Checks if ValidationError is returned when passing to_date earlier than from_date. + """ with pytest.raises( ValidationError, match=r"to_date cannot be earlier than from_date" ): - query = vc.get_response( - source="jobs", to_date="2022-05-04", from_date="2022-05-05" - ) + vc.get_response(source="jobs", to_date="2022-05-04", from_date="2022-05-05") @pytest.mark.total_load def test_total_load_for_the_same_dates(): + """ + total_load method includes logic for situation when from_date == to_date. In this scenario interval split is skipped and used just get_response method. + This test checks if this logic is executed without error and returned object if DataFrame. + """ from_date = "2022-04-01" to_date = "2022-04-01" days_interval = 10 @@ -140,6 +199,10 @@ def test_total_load_for_the_same_dates(): @pytest.mark.total_load def test_total_load_for_intervals(): + """ + Checks if interval function is properly looped in the total_load method. At first we check if returned object is DataFrame, + then we check if returned DataFrame for smaller date range contains less rows than DataFrame returned for bigger date range. + """ from_date = "2022-04-01" to_date = "2022-04-12" days_interval = 2 @@ -166,6 +229,10 @@ def test_total_load_for_intervals(): @pytest.mark.total_load def test_drop_duplicates(): + """ + Checks logic for dropping duplicated rows, that is included in total_load method. + Test checks if returned DataFrame has duplicates. + """ from_date = "2022-04-01" to_date = "2022-04-12" days_interval = 2 From 128d2d878ec5d5e9e965ac7b1c093bcb3d6d7d3a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 25 Jul 2023 13:15:51 +0000 Subject: [PATCH 088/106] =?UTF-8?q?=F0=9F=8E=A8=20Format=20Python=20code?= =?UTF-8?q?=20with=20Black?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/flows/test_sap_bw_to_adls.py | 3 +- .../flows/test_sql_server_to_parquet.py | 5 +-- tests/integration/tasks/test_genesys_task.py | 35 +++++++++++-------- tests/integration/tasks/test_sap_bw.py | 5 +-- tests/integration/test_sap_bw.py | 4 +-- tests/unit/test_base.py | 3 +- tests/unit/test_outlook.py | 6 ++-- viadot/flows/__init__.py | 2 +- viadot/flows/genesys_to_adls.py | 5 +-- viadot/flows/sap_bw_to_adls.py | 9 ++--- viadot/sources/business_core.py | 4 +-- viadot/sources/genesys.py | 2 +- viadot/sources/outlook.py | 3 +- viadot/sources/sap_bw.py | 8 +++-- viadot/tasks/sap_bw.py | 1 + 15 files changed, 53 insertions(+), 42 deletions(-) diff --git a/tests/integration/flows/test_sap_bw_to_adls.py b/tests/integration/flows/test_sap_bw_to_adls.py index d63d04e5e..c337336de 100644 --- a/tests/integration/flows/test_sap_bw_to_adls.py +++ b/tests/integration/flows/test_sap_bw_to_adls.py @@ -1,8 +1,9 @@ import os +from unittest import mock + import pandas as pd import pytest -from unittest import mock from viadot.flows import SAPBWToADLS DATA = { diff --git a/tests/integration/flows/test_sql_server_to_parquet.py b/tests/integration/flows/test_sql_server_to_parquet.py index e2c12f5b2..9be9c34ed 100644 --- a/tests/integration/flows/test_sql_server_to_parquet.py +++ b/tests/integration/flows/test_sql_server_to_parquet.py @@ -1,9 +1,10 @@ -import pytest import os + +import pytest from prefect import Flow -from viadot.tasks import SQLServerToDF from viadot.flows import SQLServerToParquet +from viadot.tasks import SQLServerToDF from viadot.tasks.sql_server import SQLServerQuery SCHEMA = "sandbox" diff --git a/tests/integration/tasks/test_genesys_task.py b/tests/integration/tasks/test_genesys_task.py index f49668339..eb4978fa6 100644 --- a/tests/integration/tasks/test_genesys_task.py +++ b/tests/integration/tasks/test_genesys_task.py @@ -13,11 +13,19 @@ def var_dictionary() -> None: variables = { "start_date": datetime.now().strftime("%Y-%m-%d"), "end_date": datetime.now().strftime("%Y-%m-%d"), - "v_list": ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1", - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2", - "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx3"], - "key_list": ["MainIntent", "SubIntent", "Final Sub Intent", - "CustomerOutcomeTrack", "LastUtterance", "Final Main Intent"], + "v_list": [ + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1", + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2", + "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx3", + ], + "key_list": [ + "MainIntent", + "SubIntent", + "Final Sub Intent", + "CustomerOutcomeTrack", + "LastUtterance", + "Final Main Intent", + ], "post_data_list": [ { "name": "AGENT_STATUS_DETAIL_VIEW", @@ -46,8 +54,9 @@ def var_dictionary() -> None: } return variables + class MockGenesysTask: - report_data = [[None, "COMPLETED"], [None, "COMPLETED"]], + report_data = ([[None, "COMPLETED"], [None, "COMPLETED"]],) def genesys_api_connection(post_data_list, end_point, method="POST"): if method == "GET": @@ -64,9 +73,7 @@ def genesys_api_connection(post_data_list, end_point, method="POST"): "queueName": "dev_name", "purpose": "customer", "wrapupRequired": None, - "mediaRoles": [ - "full" - ], + "mediaRoles": ["full"], "attributes": { "MainIntent3": "mainintent3", "SubIntent3": "subintent3", @@ -89,7 +96,7 @@ def genesys_api_connection(post_data_list, end_point, method="POST"): "LastUtterance4": "lastutterance4", "LastUtterance3": "lastutterance3", "LOB": "lob", - "memberId": "123456789" + "memberId": "123456789", }, "calls": [], "callbacks": [], @@ -98,9 +105,9 @@ def genesys_api_connection(post_data_list, end_point, method="POST"): "emails": [], "messages": [], } - ] + ], } - else: + else: report = { "conversations": [ { @@ -309,11 +316,11 @@ def test_genesys_webmsg(mock_genesys, var_dictionary): post_data_list=[""], key_list=var_dictionary["key_list"], start_date=var_dictionary["start_date"], - end_date=var_dictionary["end_date"] + end_date=var_dictionary["end_date"], ) start = var_dictionary["start_date"].replace("-", "") end = var_dictionary["end_date"].replace("-", "") mock_genesys.assert_called_once() - assert file_name[0] == f"WEBMESSAGE_{start}-{end}.csv" \ No newline at end of file + assert file_name[0] == f"WEBMESSAGE_{start}-{end}.csv" diff --git a/tests/integration/tasks/test_sap_bw.py b/tests/integration/tasks/test_sap_bw.py index dd1dfdeb1..6aea385aa 100644 --- a/tests/integration/tasks/test_sap_bw.py +++ b/tests/integration/tasks/test_sap_bw.py @@ -1,7 +1,8 @@ -import pytest import pandas as pd -from viadot.tasks import SAPBWToDF +import pytest + from viadot.task_utils import credentials_loader +from viadot.tasks import SAPBWToDF CREDENTIALS = credentials_loader.run(credentials_secret="SAP") sapbw_task = SAPBWToDF(sapbw_credentials=CREDENTIALS.get("BW")) diff --git a/tests/integration/test_sap_bw.py b/tests/integration/test_sap_bw.py index 44f579578..ce8fd046f 100644 --- a/tests/integration/test_sap_bw.py +++ b/tests/integration/test_sap_bw.py @@ -1,8 +1,8 @@ import pytest -from viadot.sources import SAPBW -from viadot.task_utils import credentials_loader from pyrfc import Connection +from viadot.sources import SAPBW +from viadot.task_utils import credentials_loader CREDENTIALS = credentials_loader.run(credentials_secret="SAP") SAPBW = SAPBW(credentials=CREDENTIALS.get("BW")) diff --git a/tests/unit/test_base.py b/tests/unit/test_base.py index f36115b6f..c20336b29 100644 --- a/tests/unit/test_base.py +++ b/tests/unit/test_base.py @@ -1,5 +1,6 @@ -import os import logging +import os + import pandas as pd import pyarrow as pa import pytest diff --git a/tests/unit/test_outlook.py b/tests/unit/test_outlook.py index 29d291157..d2935ca93 100644 --- a/tests/unit/test_outlook.py +++ b/tests/unit/test_outlook.py @@ -1,13 +1,13 @@ import os -import pytest -from unittest import mock from datetime import datetime +from unittest import mock import pandas as pd +import pytest from O365.account import Account -from viadot.sources import Outlook from viadot.exceptions import CredentialError +from viadot.sources import Outlook @pytest.fixture diff --git a/viadot/flows/__init__.py b/viadot/flows/__init__.py index 1e1bccd8b..b8113c1a1 100644 --- a/viadot/flows/__init__.py +++ b/viadot/flows/__init__.py @@ -43,5 +43,5 @@ from .mindful_to_adls import MindfulToADLS from .sftp_operations import SftpToADLS, SftpToAzureSQL from .sql_server_to_duckdb import SQLServerToDuckDB -from .sql_server_transform import SQLServerTransform from .sql_server_to_parquet import SQLServerToParquet +from .sql_server_transform import SQLServerTransform diff --git a/viadot/flows/genesys_to_adls.py b/viadot/flows/genesys_to_adls.py index 29bd2bb65..4f8c54f3e 100644 --- a/viadot/flows/genesys_to_adls.py +++ b/viadot/flows/genesys_to_adls.py @@ -5,11 +5,8 @@ import pandas as pd from prefect import Flow, task +from viadot.task_utils import add_ingestion_metadata_task, adls_bulk_upload from viadot.tasks.genesys import GenesysToCSV -from viadot.task_utils import ( - add_ingestion_metadata_task, - adls_bulk_upload, -) @task(timeout=3600) diff --git a/viadot/flows/sap_bw_to_adls.py b/viadot/flows/sap_bw_to_adls.py index bd8e0c474..375f30775 100644 --- a/viadot/flows/sap_bw_to_adls.py +++ b/viadot/flows/sap_bw_to_adls.py @@ -1,18 +1,19 @@ import os -import pendulum from pathlib import Path from typing import Any, Dict, List, Literal + +import pendulum from prefect import Flow from prefect.backend import set_key_value from viadot.task_utils import ( - df_to_parquet, - df_to_csv, add_ingestion_metadata_task, df_get_data_types_task, df_map_mixed_dtypes_for_parquet, - update_dtypes_dict, + df_to_csv, + df_to_parquet, dtypes_to_json_task, + update_dtypes_dict, ) from viadot.tasks import AzureDataLakeUpload, SAPBWToDF diff --git a/viadot/sources/business_core.py b/viadot/sources/business_core.py index 2409f5ffe..3495cecd9 100644 --- a/viadot/sources/business_core.py +++ b/viadot/sources/business_core.py @@ -1,8 +1,8 @@ -import pandas as pd import json -from prefect.utilities import logging from typing import Any, Dict, Literal +import pandas as pd +from prefect.utilities import logging from ..config import local_config from ..exceptions import APIError, CredentialError diff --git a/viadot/sources/genesys.py b/viadot/sources/genesys.py index e2fb31090..4556ededf 100644 --- a/viadot/sources/genesys.py +++ b/viadot/sources/genesys.py @@ -8,8 +8,8 @@ import aiohttp import pandas as pd -from aiolimiter import AsyncLimiter import prefect +from aiolimiter import AsyncLimiter from prefect.engine import signals from viadot.config import local_config diff --git a/viadot/sources/outlook.py b/viadot/sources/outlook.py index b49c5c7b7..266b28b45 100644 --- a/viadot/sources/outlook.py +++ b/viadot/sources/outlook.py @@ -1,11 +1,10 @@ import sys -import pytz from datetime import date, datetime, timedelta from typing import Any, Dict, List -import prefect import pandas as pd import prefect +import pytz from O365 import Account from O365.mailbox import MailBox diff --git a/viadot/sources/sap_bw.py b/viadot/sources/sap_bw.py index 2cb8b8749..73b1d2efa 100644 --- a/viadot/sources/sap_bw.py +++ b/viadot/sources/sap_bw.py @@ -1,8 +1,10 @@ +import textwrap from typing import List -from viadot.sources.base import Source -from viadot.exceptions import CredentialError, ValidationError + from pyrfc import Connection -import textwrap + +from viadot.exceptions import CredentialError, ValidationError +from viadot.sources.base import Source class SAPBW(Source): diff --git a/viadot/tasks/sap_bw.py b/viadot/tasks/sap_bw.py index e2d8bab43..4d34f9960 100644 --- a/viadot/tasks/sap_bw.py +++ b/viadot/tasks/sap_bw.py @@ -2,6 +2,7 @@ from prefect import Task from prefect.tasks.secrets import PrefectSecret from prefect.utilities import logging + from viadot.exceptions import ValidationError from viadot.sources import SAPBW from viadot.task_utils import * From f09c380c5e01f595537f424024f85956ea3dd2d5 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 15:18:15 +0200 Subject: [PATCH 089/106] add loggers to dropping columns --- viadot/tasks/vid_club.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index f8aeb2736..06ec2c33f 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -123,11 +123,15 @@ def run( if cols_to_drop is not None: if isinstance(cols_to_drop, list): try: + logger.info(f"Dropping following columns: {cols_to_drop}...") vc_dataframe.drop( columns=cols_to_drop, inplace=True, errors="raise" ) except KeyError as ke: - raise ke + logger.error( + f"Column(s): {cols_to_drop} don't exist in the DataFrame. No columns were dropped. Returning full DataFrame..." + ) + logger.info(f"Existing columns: {vc_dataframe.columns}") else: raise TypeError("Provide columns to drop in a List.") From ebd538bedecdba5bba05ae135bb808355e9387a3 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 16:50:34 +0200 Subject: [PATCH 090/106] update tests for task --- tests/integration/tasks/test_vid_club.py | 104 ++++++++++++++++++++--- 1 file changed, 94 insertions(+), 10 deletions(-) diff --git a/tests/integration/tasks/test_vid_club.py b/tests/integration/tasks/test_vid_club.py index 9e9c46c52..2a4802cc2 100644 --- a/tests/integration/tasks/test_vid_club.py +++ b/tests/integration/tasks/test_vid_club.py @@ -29,19 +29,103 @@ def var_dictionary(): "viadot.tasks.VidClubToDF.run", return_value=MockVidClubResponse.response_data ) def test_vid_club_to_df(var_dictionary): - source = var_dictionary["source"] - from_date = var_dictionary["from_date"] - to_date = var_dictionary["to_date"] - items_per_page = var_dictionary["items_per_page"] - days_interval = var_dictionary["days_interval"] + """ + Checks if run method returns DataFrame. + Args: + var_dictionary: Dictionary with example arguments for run method. + """ vc_to_df = VidClubToDF(credentials=CREDENTIALS) + df = vc_to_df.run( - source=source, - to_date=to_date, - from_date=from_date, - items_per_page=items_per_page, - days_interval=days_interval, + source=var_dictionary["source"], + to_date=var_dictionary["to_date"], + from_date=var_dictionary["from_date"], + items_per_page=var_dictionary["items_per_page"], + days_interval=var_dictionary["days_interval"], ) assert isinstance(df, pd.DataFrame) + + +@pytest.mark.drop_cols +def test_drop_columns(var_dictionary): + """ + Tests cols_to_drop argument in function. + + Args: + var_dictionary: Dictionary with example arguments for run method. + """ + cols_to_drop = ["regionID", "submissionDate"] + vc_to_df = VidClubToDF(credentials=CREDENTIALS) + + output_with_all = vc_to_df.run( + source=var_dictionary["source"], + to_date=var_dictionary["to_date"], + from_date=var_dictionary["from_date"], + items_per_page=var_dictionary["items_per_page"], + days_interval=var_dictionary["days_interval"], + ) + output_with_dropped = vc_to_df.run( + source=var_dictionary["source"], + to_date=var_dictionary["to_date"], + from_date=var_dictionary["from_date"], + items_per_page=var_dictionary["items_per_page"], + days_interval=var_dictionary["days_interval"], + cols_to_drop=cols_to_drop, + ) + + assert set(list(output_with_all.columns)) - set( + list(output_with_dropped.columns) + ) == set(cols_to_drop) + + +@pytest.mark.drop_cols +def test_drop_columns_KeyError(var_dictionary, caplog): + """ + Tests if in case of KeyError (when passed columns in cols_to_drop are not included in DataFrame), there is returned error logger.. + + Args: + var_dictionary: Dictionary with example arguments for run method. + """ + cols_to_drop = ["Test", "submissionDate"] + vc_to_df = VidClubToDF(credentials=CREDENTIALS) + + vc_to_df.run( + source=var_dictionary["source"], + to_date=var_dictionary["to_date"], + from_date=var_dictionary["from_date"], + items_per_page=var_dictionary["items_per_page"], + days_interval=var_dictionary["days_interval"], + cols_to_drop=cols_to_drop, + ) + assert len(caplog.records) == 1 + assert caplog.records[0].levelname == "ERROR" + assert ( + f"Column(s): {cols_to_drop} don't exist in the DataFrame" + in caplog.records[0].message + ) + # assert caplog.records[1].levelname == "INFO" + # assert "Existing columns:" in caplog.records[1].message + + +@pytest.mark.drop_cols +def test_drop_columns_TypeError(var_dictionary): + """ + Tests raising TypeError if passed columns in cols_to_drop is not a List. + + Args: + var_dictionary: Dictionary with example arguments for run method. + """ + with pytest.raises(TypeError, match="Provide columns to drop in a List."): + cols_to_drop = "Test" + vc_to_df = VidClubToDF(credentials=CREDENTIALS) + + output_with_dropped = vc_to_df.run( + source=var_dictionary["source"], + to_date=var_dictionary["to_date"], + from_date=var_dictionary["from_date"], + items_per_page=var_dictionary["items_per_page"], + days_interval=var_dictionary["days_interval"], + cols_to_drop=cols_to_drop, + ) From d9302ffc4befb38beb0bce8a3e17d0da635d0ac7 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 16:57:25 +0200 Subject: [PATCH 091/106] removed space --- .vscode/settings.json | 7 +- data_flows | 1 + test.json | 1 + test.parquet | Bin 0 -> 445166 bytes tests/integration/test_vid_club.py | 1 - viadot/flows/__init__.py | 1 + viadot/flows/vid_club_to_adls.py | 164 + vid_club_tests.ipynb | 7149 ++++++++++++++++++++++++++++ 8 files changed, 7321 insertions(+), 3 deletions(-) create mode 160000 data_flows create mode 100644 test.json create mode 100644 test.parquet create mode 100644 viadot/flows/vid_club_to_adls.py create mode 100644 vid_club_tests.ipynb diff --git a/.vscode/settings.json b/.vscode/settings.json index 8fd5218a8..95454c294 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "autoDocstring.docstringFormat": "google", - "python.formatting.provider": "black", + "python.formatting.provider": "none", "python.formatting.blackArgs": [ "--line-length", "88" @@ -48,5 +48,8 @@ "work", "zfill" ], - "git.autofetch": true + "git.autofetch": true, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + } } \ No newline at end of file diff --git a/data_flows b/data_flows new file mode 160000 index 000000000..3469019c8 --- /dev/null +++ b/data_flows @@ -0,0 +1 @@ +Subproject commit 3469019c8c5a2b8bedb4cdff6973417aa1a8eeed diff --git a/test.json b/test.json new file mode 100644 index 000000000..ce19911f7 --- /dev/null +++ b/test.json @@ -0,0 +1 @@ +{"submissionID": "Integer", "submissionAddress": "String", "regionID": "String", "submissionPostcode": "String", "submissionDate": "String", "customerID": "String", "status": "String", "submissionQuantity": "Integer", "points": "Integer", "q1Core": "String", "q2Core": "String", "q2CoreOther": "String", "q3Core": "String", "q4Core": "String", "q5Core": "Integer", "q5CoreOther": "Integer", "q6Core": "Integer", "q6CoreOther": "Integer", "q7Core": "Integer", "q7CoreOther": "Integer", "q8Core": "Integer", "q8CoreOther": "Integer", "q9Core": "Integer", "_viadot_downloaded_at_utc": "DateTime"} \ No newline at end of file diff --git a/test.parquet b/test.parquet new file mode 100644 index 0000000000000000000000000000000000000000..2832fc41e96b36e54583cbe055f81c15d6c56126 GIT binary patch literal 445166 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 z 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%0DCDnvx8Hg=D_1xung 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

j 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

xjNy^g49qP)o%RJSCwI5{$4vt{Pd-@)nkh2 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 Koo Flow: + vid_club_df_task = VidClubToDF( + timeout=self.timeout, + source=self.source, + credentials=self.vid_club_credentials, + credentials_secret=self.vidclub_credentials_secret, + vault_name=self.vidclub_vault_name, + ) + + vid_club_df = vid_club_df_task.bind( + from_date=self.from_date, + to_date=self.to_date, + items_per_page=self.items_per_page, + region=self.region, + days_interval=self.days_interval, + flow=self, + ) + + df_with_metadata = add_ingestion_metadata_task.bind(df, flow=self) + + dtypes_dict = df_get_data_types_task.bind(df_with_metadata, flow=self) + df_mapped = df_map_mixed_dtypes_for_parquet.bind( + df_with_metadata, dtypes_dict, flow=self + ) + + if self.output_file_extension == ".parquet": + df_to_file = df_to_parquet.bind( + df=df_mapped, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + else: + df_to_file = df_to_csv.bind( + df=df_with_metadata, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + + file_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) + file_to_adls_task.bind( + from_path=self.local_file_path, + to_path=self.adls_file_path, + overwrite=self.overwrite, + sp_credentials_secret=self.adls_sp_credentials_secret, + flow=self, + ) + + dtypes_updated = update_dtypes_dict(dtypes_dict, flow=self) + dtypes_to_json_task.bind( + dtypes_dict=dtypes_updated, local_json_path=self.local_json_path, flow=self + ) + json_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) + json_to_adls_task.bind( + from_path=self.local_json_path, + to_path=self.adls_schema_file_dir_file, + overwrite=self.overwrite, + sp_credentials_secret=self.adls_sp_credentials_secret, + flow=self, + ) + + file_to_adls_task.set_upstream(df_to_file, flow=self) + json_to_adls_task.set_upstream(dtypes_to_json_task, flow=self) + set_key_value(key=self.adls_dir_path, value=self.adls_file_path) diff --git a/vid_club_tests.ipynb b/vid_club_tests.ipynb new file mode 100644 index 000000000..37bb32d5c --- /dev/null +++ b/vid_club_tests.ipynb @@ -0,0 +1,7149 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "d2cbca7f-1c9a-4a38-9e16-c580b4def675", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " dev\u001b[m\n", + " dev_add_url_customer_gauge\u001b[m\n", + "* \u001b[32mdev_vidclub_update\u001b[m\n", + " main\u001b[m\n", + " orion\u001b[m\n" + ] + } + ], + "source": [ + "!git branch" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "3ea17add-8682-4ee5-b72f-36f2acddd3db", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 08:10:46+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + } + ], + "source": [ + "from viadot.task_utils import credentials_loader\n", + "from viadot.sources import VidClub\n", + "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", + "\n", + "# def test_default_credential_param():\n", + "vc = VidClub(credentials = CREDENTIALS)\n", + "assert vc.credentials != None and type(vc.credentials) == dict" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a1649601-4e08-4191-bded-0ca848d486ff", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 13:03:25+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + } + ], + "source": [ + "import time\n", + "from viadot.task_utils import credentials_loader\n", + "from viadot.sources import VidClub\n", + "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "06ecea54-eb6b-4a53-afd7-f5f602fe234f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'url': 'https://api.club.velux.com/api/v1/datalake/',\n", + " 'token': 'Oit6TLXA8Gxcf9cOSnH6YvHqtNELDae1CWedodSMJtgu03hKteSSGcbLS0GqnhLT'}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "CREDENTIALS" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b67de55a-ada8-424f-a956-3ae96f0b5a63", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 13:03:50+0000] INFO - prefect | ingesting data for dates [2022-06-01]-[2022-06-01]...\n" + ] + } + ], + "source": [ + "from_date = \"2022-06-01\"\n", + "to_date = \"2022-06-01\"\n", + "days_interval = 10\n", + "source = \"jobs\"\n", + "df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "70329e10-ffe9-40e4-8f11-dbdcb5315e1a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
submissionIDsubmissionAddressregionIDsubmissionPostcodesubmissionDatecustomerIDstatussubmissionQuantitypointsq1Core...q4Coreq5Coreq5CoreOtherq6Coreq6CoreOtherq7Coreq7CoreOtherq8Coreq8CoreOtherq9Core
01071ŻurawiaPolandNone06/02/2022 20:45tYYcTKIfszynwmf4Closed420True...Concrete/ceramic tiles101010000
11070Juliana OpaniPolandNone06/02/2022 20:37pwg7XoKFF5FMfLZFClosed1390Part of new build house...Concrete/ceramic tiles100001010
21067Strada EgalităţiiRomaniaNone06/03/2022 07:54fd4ppEcGKm1HSYq7Closed664Part of new build house...Concrete/ceramic tiles000001010
31066SienkiewiczaPolandNone06/03/2022 16:18Yaddrbn2IY2ccDPpClosed945Part of new build house...Concrete/ceramic tiles110010000
41065ChrobregoPolandNone06/02/2022 13:56H3BjABhm0dl0jJh1Closed770Part of new build house...Concrete/ceramic tiles100011000
51064JankowickaPolandNone06/21/2022 13:04H3BjABhm0dl0jJh1Closed440Part of new build house...Concrete/ceramic tiles100110000
61063RembielińskaPolandNone06/02/2022 13:28H3BjABhm0dl0jJh1Closed15Part of new build house...Concrete/ceramic tiles100010000
71062RembielińskaPolandNone06/02/2022 13:26H3BjABhm0dl0jJh1Closed15Part of new build house...Concrete/ceramic tiles100000000
81061MałopolskaPolandNone06/10/2022 10:19JQTpXoVija32uEzBClosed420Part of new build house...Concrete/ceramic tiles000000001
91060SendlerowejPolandNone07/20/2022 10:54MxGqVCykMPUCZey3Closed210Part of new build house...Concrete/ceramic tiles000001000
101059Strada JiuluiRomaniaNone06/02/2022 12:44y78f0kWqfaIB5F6gClosed17Part of new build house...Concrete/ceramic tiles100000000
111058PięknaPolandNoneNot started yetDzHdosS0tf1zsYu8In progress00True...True000000000
121057PływackaPolandNone06/02/2022 10:26tYYcTKIfszynwmf4Closed210Part of new build house...Concrete/ceramic tiles100000000
131056PływackaPolandNone06/02/2022 10:20tYYcTKIfszynwmf4Closed210Part of new build house...Concrete/ceramic tiles000001000
141055LechówPolandNoneNot started yetAYpEmrYTeaSRZyiSIn progress00True...True000000000
151054Generała Edmunda TaczanowskiegoPolandNone06/02/2022 14:34ymIzPDdYXqECNNrQClosed770Part of new build house...Concrete/ceramic tiles100001000
161053Calea DomneascăRomaniaNone06/02/2022 08:40grEokZxpPfoH2gdrClosed17Part of new build house...Concrete/ceramic tiles100000000
171052OsinieckaPolandNone06/02/2022 08:35rDGLcq4Og2elwesBClosed15Part of new build house...Concrete/ceramic tiles000000010
181051Zofii KossakPolandNone10/11/2022 09:259ab5ekacidsz0IRxClosed15Part of new build house...Concrete/ceramic tiles001000000
191050Strada Anghel I. SalignyRomaniaNone06/02/2022 08:102MS738MaZ8ytUtwuClosed214Part of new build house...Concrete/ceramic tiles100000000
201049JodłowaPolandNone06/02/2022 13:16H3BjABhm0dl0jJh1Closed840Part of new build house...Concrete/ceramic tiles100011000
211048LotniczaPolandNone06/03/2022 08:41xczTna3SQKI4D6CNClosed420Part of new build house...Concrete/ceramic tiles100110000
221047CzereśniowaPolandNone06/02/2022 06:32FUugbtnE8kEVeabDClosed210True...Concrete/ceramic tiles000010000
231046LechitówPolandNone06/07/2022 19:29RBo3MHMT4Ix6vvPTClosed19140Part of new build house...Concrete/ceramic tiles000011001
241045LechitówPolandNone06/05/2022 13:06RBo3MHMT4Ix6vvPTClosed10100Part of new build house...Concrete/ceramic tiles000010001
251044GrzybowaPolandNone06/01/2022 19:0314ksdmnGL0FzkSvOClosed630Part of new build house...Concrete/ceramic tiles111011010
261042GrzybiarzyPolandNone06/01/2022 17:07sPvG8pNLClGkjABwClosed7110Part of new build house...Concrete/ceramic tiles100011110
271041Aleea VerdeRomaniaNone06/01/2022 16:54Yq1MoCoSyEpqvqEpClosed434Part of new build house...Concrete/ceramic tiles110000000
281040Nad SpławkąPolandNone06/01/2022 16:21iXgEj1jstJtWOofoClosed430True...Concrete/ceramic tiles110010000
291039Str. MăguraRomaniaNone06/02/2022 07:03VaQrq1nDkYqVlqOAClosed1087Part of new build house...Concrete/ceramic tiles100010000
301038RetkińskaPolandNone06/01/2022 14:44ymIzPDdYXqECNNrQClosed770Part of new build house...Concrete/ceramic tiles100011000
311036RetorykaPolandNone10/12/2022 09:21ymIzPDdYXqECNNrQClosed240Part of new build house...Concrete/ceramic tiles100000000
321034Strada Avram IancuRomaniaNone06/01/2022 13:25BtxqL3tDbcvKX8EsClosed428Part of new build house...Concrete/ceramic tiles000000001
331033PiaskiPolandNone06/01/2022 12:46JAK9G1O4vXpaAFuvClosed420Part of new build house...Concrete/ceramic tiles100010000
341032KwiatowaPolandNoneNot started yetJAK9G1O4vXpaAFuvIn progress00True...True000000000
351031GórnaPolandNone06/01/2022 12:39pwg7XoKFF5FMfLZFClosed210Part of new build house...Concrete/ceramic tiles100010000
361030Bulevardul VictorieiRomaniaNone06/05/2022 16:09PRhfCDdZSpBQ6tdPClosed15Part of new build house...Concrete/ceramic tiles000000010
371029TrudnaPolandNone06/01/2022 12:16Yaddrbn2IY2ccDPpClosed15Part of new build house...Concrete/ceramic tiles000100000
381026ŻonkilowaPolandNone06/01/2022 11:12UzgRnEeTpJRojd2wClosed15Part of new build house...Concrete/ceramic tiles000010000
391024CegielnianaPolandNone06/09/2022 04:21Lzy0ra2ramJqUYGyClosed315Part of new build house...Concrete/ceramic tiles000001000
401022LubelskaPolandNone06/01/2022 09:21s10GO5LdAKLlkWxHClosed210Part of new build house...Concrete/ceramic tiles001100000
411020ParkowaPolandNone06/08/2022 12:16m4Gq60TvlLF85KGHClosed115Part of new build house...Concrete/ceramic tiles000010000
421018DziałkowaPolandNone09/22/2022 07:48nuaUHDy7rbKJta8gLost00True...True000000000
431017MałaPolandNone07/05/2022 09:50xExXWy0kskxQg3gBClosed210Part of new build house...Concrete/ceramic tiles000011000
441016MałaPolandNone07/05/2022 09:53xExXWy0kskxQg3gBClosed210Part of new build house...Concrete/ceramic tiles110000000
451015MałaPolandNone07/05/2022 09:57xExXWy0kskxQg3gBClosed15Part of new build house...Concrete/ceramic tiles100000000
461013SzafirowaPolandNone06/01/2022 08:38QPE1v6DtFgXvo1VnClosed840Part of new build house...Concrete/ceramic tiles100010000
471012Strada George EnescuRomaniaNone06/01/2022 10:438CAZhYrPJa3i9BWkClosed432Part of new build house...Concrete/ceramic tiles010000000
481011MałaPolandNoneNot started yetEeaOIdBkC2uxlmzJIn progress00True...True000000000
491010George Emil PaladeRomaniaNone10/28/2022 06:068CAZhYrPJa3i9BWkClosed17Part of new build house...Concrete/ceramic tiles010000000
501008Str. BotosRomaniaNone06/01/2022 07:48fAGWNcu46Z1wT06PClosed210Part of new build house...Concrete/ceramic tiles100010000
511007OlszankowaPolandNone06/01/2022 06:52qw4uw4uHwmk5WSi4Closed945Part of new build house...Concrete/ceramic tiles100000000
521006Ul. SzczygłówPolandNone06/01/2022 06:58NI1iorIXQce7Dxj5Closed210Part of new build house...Concrete/ceramic tiles100010000
531005KompasowaPolandNone06/01/2022 04:41jBliksyS9zZgGgRwClosed210Part of new build house...Concrete/ceramic tiles100000000
\n", + "

54 rows × 23 columns

\n", + "
" + ], + "text/plain": [ + " submissionID submissionAddress regionID submissionPostcode \\\n", + "0 1071 Żurawia Poland None \n", + "1 1070 Juliana Opani Poland None \n", + "2 1067 Strada Egalităţii Romania None \n", + "3 1066 Sienkiewicza Poland None \n", + "4 1065 Chrobrego Poland None \n", + "5 1064 Jankowicka Poland None \n", + "6 1063 Rembielińska Poland None \n", + "7 1062 Rembielińska Poland None \n", + "8 1061 Małopolska Poland None \n", + "9 1060 Sendlerowej Poland None \n", + "10 1059 Strada Jiului Romania None \n", + "11 1058 Piękna Poland None \n", + "12 1057 Pływacka Poland None \n", + "13 1056 Pływacka Poland None \n", + "14 1055 Lechów Poland None \n", + "15 1054 Generała Edmunda Taczanowskiego Poland None \n", + "16 1053 Calea Domnească Romania None \n", + "17 1052 Osiniecka Poland None \n", + "18 1051 Zofii Kossak Poland None \n", + "19 1050 Strada Anghel I. Saligny Romania None \n", + "20 1049 Jodłowa Poland None \n", + "21 1048 Lotnicza Poland None \n", + "22 1047 Czereśniowa Poland None \n", + "23 1046 Lechitów Poland None \n", + "24 1045 Lechitów Poland None \n", + "25 1044 Grzybowa Poland None \n", + "26 1042 Grzybiarzy Poland None \n", + "27 1041 Aleea Verde Romania None \n", + "28 1040 Nad Spławką Poland None \n", + "29 1039 Str. Măgura Romania None \n", + "30 1038 Retkińska Poland None \n", + "31 1036 Retoryka Poland None \n", + "32 1034 Strada Avram Iancu Romania None \n", + "33 1033 Piaski Poland None \n", + "34 1032 Kwiatowa Poland None \n", + "35 1031 Górna Poland None \n", + "36 1030 Bulevardul Victoriei Romania None \n", + "37 1029 Trudna Poland None \n", + "38 1026 Żonkilowa Poland None \n", + "39 1024 Cegielniana Poland None \n", + "40 1022 Lubelska Poland None \n", + "41 1020 Parkowa Poland None \n", + "42 1018 Działkowa Poland None \n", + "43 1017 Mała Poland None \n", + "44 1016 Mała Poland None \n", + "45 1015 Mała Poland None \n", + "46 1013 Szafirowa Poland None \n", + "47 1012 Strada George Enescu Romania None \n", + "48 1011 Mała Poland None \n", + "49 1010 George Emil Palade Romania None \n", + "50 1008 Str. Botos Romania None \n", + "51 1007 Olszankowa Poland None \n", + "52 1006 Ul. Szczygłów Poland None \n", + "53 1005 Kompasowa Poland None \n", + "\n", + " submissionDate customerID status submissionQuantity \\\n", + "0 06/02/2022 20:45 tYYcTKIfszynwmf4 Closed 4 \n", + "1 06/02/2022 20:37 pwg7XoKFF5FMfLZF Closed 13 \n", + "2 06/03/2022 07:54 fd4ppEcGKm1HSYq7 Closed 6 \n", + "3 06/03/2022 16:18 Yaddrbn2IY2ccDPp Closed 9 \n", + "4 06/02/2022 13:56 H3BjABhm0dl0jJh1 Closed 7 \n", + "5 06/21/2022 13:04 H3BjABhm0dl0jJh1 Closed 4 \n", + "6 06/02/2022 13:28 H3BjABhm0dl0jJh1 Closed 1 \n", + "7 06/02/2022 13:26 H3BjABhm0dl0jJh1 Closed 1 \n", + "8 06/10/2022 10:19 JQTpXoVija32uEzB Closed 4 \n", + "9 07/20/2022 10:54 MxGqVCykMPUCZey3 Closed 2 \n", + "10 06/02/2022 12:44 y78f0kWqfaIB5F6g Closed 1 \n", + "11 Not started yet DzHdosS0tf1zsYu8 In progress 0 \n", + "12 06/02/2022 10:26 tYYcTKIfszynwmf4 Closed 2 \n", + "13 06/02/2022 10:20 tYYcTKIfszynwmf4 Closed 2 \n", + "14 Not started yet AYpEmrYTeaSRZyiS In progress 0 \n", + "15 06/02/2022 14:34 ymIzPDdYXqECNNrQ Closed 7 \n", + "16 06/02/2022 08:40 grEokZxpPfoH2gdr Closed 1 \n", + "17 06/02/2022 08:35 rDGLcq4Og2elwesB Closed 1 \n", + "18 10/11/2022 09:25 9ab5ekacidsz0IRx Closed 1 \n", + "19 06/02/2022 08:10 2MS738MaZ8ytUtwu Closed 2 \n", + "20 06/02/2022 13:16 H3BjABhm0dl0jJh1 Closed 8 \n", + "21 06/03/2022 08:41 xczTna3SQKI4D6CN Closed 4 \n", + "22 06/02/2022 06:32 FUugbtnE8kEVeabD Closed 2 \n", + "23 06/07/2022 19:29 RBo3MHMT4Ix6vvPT Closed 19 \n", + "24 06/05/2022 13:06 RBo3MHMT4Ix6vvPT Closed 10 \n", + "25 06/01/2022 19:03 14ksdmnGL0FzkSvO Closed 6 \n", + "26 06/01/2022 17:07 sPvG8pNLClGkjABw Closed 7 \n", + "27 06/01/2022 16:54 Yq1MoCoSyEpqvqEp Closed 4 \n", + "28 06/01/2022 16:21 iXgEj1jstJtWOofo Closed 4 \n", + "29 06/02/2022 07:03 VaQrq1nDkYqVlqOA Closed 10 \n", + "30 06/01/2022 14:44 ymIzPDdYXqECNNrQ Closed 7 \n", + "31 10/12/2022 09:21 ymIzPDdYXqECNNrQ Closed 2 \n", + "32 06/01/2022 13:25 BtxqL3tDbcvKX8Es Closed 4 \n", + "33 06/01/2022 12:46 JAK9G1O4vXpaAFuv Closed 4 \n", + "34 Not started yet JAK9G1O4vXpaAFuv In progress 0 \n", + "35 06/01/2022 12:39 pwg7XoKFF5FMfLZF Closed 2 \n", + "36 06/05/2022 16:09 PRhfCDdZSpBQ6tdP Closed 1 \n", + "37 06/01/2022 12:16 Yaddrbn2IY2ccDPp Closed 1 \n", + "38 06/01/2022 11:12 UzgRnEeTpJRojd2w Closed 1 \n", + "39 06/09/2022 04:21 Lzy0ra2ramJqUYGy Closed 3 \n", + "40 06/01/2022 09:21 s10GO5LdAKLlkWxH Closed 2 \n", + "41 06/08/2022 12:16 m4Gq60TvlLF85KGH Closed 1 \n", + "42 09/22/2022 07:48 nuaUHDy7rbKJta8g Lost 0 \n", + "43 07/05/2022 09:50 xExXWy0kskxQg3gB Closed 2 \n", + "44 07/05/2022 09:53 xExXWy0kskxQg3gB Closed 2 \n", + "45 07/05/2022 09:57 xExXWy0kskxQg3gB Closed 1 \n", + "46 06/01/2022 08:38 QPE1v6DtFgXvo1Vn Closed 8 \n", + "47 06/01/2022 10:43 8CAZhYrPJa3i9BWk Closed 4 \n", + "48 Not started yet EeaOIdBkC2uxlmzJ In progress 0 \n", + "49 10/28/2022 06:06 8CAZhYrPJa3i9BWk Closed 1 \n", + "50 06/01/2022 07:48 fAGWNcu46Z1wT06P Closed 2 \n", + "51 06/01/2022 06:52 qw4uw4uHwmk5WSi4 Closed 9 \n", + "52 06/01/2022 06:58 NI1iorIXQce7Dxj5 Closed 2 \n", + "53 06/01/2022 04:41 jBliksyS9zZgGgRw Closed 2 \n", + "\n", + " points q1Core ... q4Core q5Core \\\n", + "0 20 True ... Concrete/ceramic tiles 1 \n", + "1 90 Part of new build house ... Concrete/ceramic tiles 1 \n", + "2 64 Part of new build house ... Concrete/ceramic tiles 0 \n", + "3 45 Part of new build house ... Concrete/ceramic tiles 1 \n", + "4 70 Part of new build house ... Concrete/ceramic tiles 1 \n", + "5 40 Part of new build house ... Concrete/ceramic tiles 1 \n", + "6 5 Part of new build house ... Concrete/ceramic tiles 1 \n", + "7 5 Part of new build house ... Concrete/ceramic tiles 1 \n", + "8 20 Part of new build house ... Concrete/ceramic tiles 0 \n", + "9 10 Part of new build house ... Concrete/ceramic tiles 0 \n", + "10 7 Part of new build house ... Concrete/ceramic tiles 1 \n", + "11 0 True ... True 0 \n", + "12 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "13 10 Part of new build house ... Concrete/ceramic tiles 0 \n", + "14 0 True ... True 0 \n", + "15 70 Part of new build house ... Concrete/ceramic tiles 1 \n", + "16 7 Part of new build house ... Concrete/ceramic tiles 1 \n", + "17 5 Part of new build house ... Concrete/ceramic tiles 0 \n", + "18 5 Part of new build house ... Concrete/ceramic tiles 0 \n", + "19 14 Part of new build house ... Concrete/ceramic tiles 1 \n", + "20 40 Part of new build house ... Concrete/ceramic tiles 1 \n", + "21 20 Part of new build house ... Concrete/ceramic tiles 1 \n", + "22 10 True ... Concrete/ceramic tiles 0 \n", + "23 140 Part of new build house ... Concrete/ceramic tiles 0 \n", + "24 100 Part of new build house ... Concrete/ceramic tiles 0 \n", + "25 30 Part of new build house ... Concrete/ceramic tiles 1 \n", + "26 110 Part of new build house ... Concrete/ceramic tiles 1 \n", + "27 34 Part of new build house ... Concrete/ceramic tiles 1 \n", + "28 30 True ... Concrete/ceramic tiles 1 \n", + "29 87 Part of new build house ... Concrete/ceramic tiles 1 \n", + "30 70 Part of new build house ... Concrete/ceramic tiles 1 \n", + "31 40 Part of new build house ... Concrete/ceramic tiles 1 \n", + "32 28 Part of new build house ... Concrete/ceramic tiles 0 \n", + "33 20 Part of new build house ... Concrete/ceramic tiles 1 \n", + "34 0 True ... True 0 \n", + "35 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "36 5 Part of new build house ... Concrete/ceramic tiles 0 \n", + "37 5 Part of new build house ... Concrete/ceramic tiles 0 \n", + "38 5 Part of new build house ... Concrete/ceramic tiles 0 \n", + "39 15 Part of new build house ... Concrete/ceramic tiles 0 \n", + "40 10 Part of new build house ... Concrete/ceramic tiles 0 \n", + "41 15 Part of new build house ... Concrete/ceramic tiles 0 \n", + "42 0 True ... True 0 \n", + "43 10 Part of new build house ... Concrete/ceramic tiles 0 \n", + "44 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "45 5 Part of new build house ... Concrete/ceramic tiles 1 \n", + "46 40 Part of new build house ... Concrete/ceramic tiles 1 \n", + "47 32 Part of new build house ... Concrete/ceramic tiles 0 \n", + "48 0 True ... True 0 \n", + "49 7 Part of new build house ... Concrete/ceramic tiles 0 \n", + "50 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "51 45 Part of new build house ... Concrete/ceramic tiles 1 \n", + "52 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "53 10 Part of new build house ... Concrete/ceramic tiles 1 \n", + "\n", + " q5CoreOther q6Core q6CoreOther q7Core q7CoreOther q8Core q8CoreOther \\\n", + "0 0 1 0 1 0 0 0 \n", + "1 0 0 0 0 1 0 1 \n", + "2 0 0 0 0 1 0 1 \n", + "3 1 0 0 1 0 0 0 \n", + "4 0 0 0 1 1 0 0 \n", + "5 0 0 1 1 0 0 0 \n", + "6 0 0 0 1 0 0 0 \n", + "7 0 0 0 0 0 0 0 \n", + "8 0 0 0 0 0 0 0 \n", + "9 0 0 0 0 1 0 0 \n", + "10 0 0 0 0 0 0 0 \n", + "11 0 0 0 0 0 0 0 \n", + "12 0 0 0 0 0 0 0 \n", + "13 0 0 0 0 1 0 0 \n", + "14 0 0 0 0 0 0 0 \n", + "15 0 0 0 0 1 0 0 \n", + "16 0 0 0 0 0 0 0 \n", + "17 0 0 0 0 0 0 1 \n", + "18 0 1 0 0 0 0 0 \n", + "19 0 0 0 0 0 0 0 \n", + "20 0 0 0 1 1 0 0 \n", + "21 0 0 1 1 0 0 0 \n", + "22 0 0 0 1 0 0 0 \n", + "23 0 0 0 1 1 0 0 \n", + "24 0 0 0 1 0 0 0 \n", + "25 1 1 0 1 1 0 1 \n", + "26 0 0 0 1 1 1 1 \n", + "27 1 0 0 0 0 0 0 \n", + "28 1 0 0 1 0 0 0 \n", + "29 0 0 0 1 0 0 0 \n", + "30 0 0 0 1 1 0 0 \n", + "31 0 0 0 0 0 0 0 \n", + "32 0 0 0 0 0 0 0 \n", + "33 0 0 0 1 0 0 0 \n", + "34 0 0 0 0 0 0 0 \n", + "35 0 0 0 1 0 0 0 \n", + "36 0 0 0 0 0 0 1 \n", + "37 0 0 1 0 0 0 0 \n", + "38 0 0 0 1 0 0 0 \n", + "39 0 0 0 0 1 0 0 \n", + "40 0 1 1 0 0 0 0 \n", + "41 0 0 0 1 0 0 0 \n", + "42 0 0 0 0 0 0 0 \n", + "43 0 0 0 1 1 0 0 \n", + "44 1 0 0 0 0 0 0 \n", + "45 0 0 0 0 0 0 0 \n", + "46 0 0 0 1 0 0 0 \n", + "47 1 0 0 0 0 0 0 \n", + "48 0 0 0 0 0 0 0 \n", + "49 1 0 0 0 0 0 0 \n", + "50 0 0 0 1 0 0 0 \n", + "51 0 0 0 0 0 0 0 \n", + "52 0 0 0 1 0 0 0 \n", + "53 0 0 0 0 0 0 0 \n", + "\n", + " q9Core \n", + "0 0 \n", + "1 0 \n", + "2 0 \n", + "3 0 \n", + "4 0 \n", + "5 0 \n", + "6 0 \n", + "7 0 \n", + "8 1 \n", + "9 0 \n", + "10 0 \n", + "11 0 \n", + "12 0 \n", + "13 0 \n", + "14 0 \n", + "15 0 \n", + "16 0 \n", + "17 0 \n", + "18 0 \n", + "19 0 \n", + "20 0 \n", + "21 0 \n", + "22 0 \n", + "23 1 \n", + "24 1 \n", + "25 0 \n", + "26 0 \n", + "27 0 \n", + "28 0 \n", + "29 0 \n", + "30 0 \n", + "31 0 \n", + "32 1 \n", + "33 0 \n", + "34 0 \n", + "35 0 \n", + "36 0 \n", + "37 0 \n", + "38 0 \n", + "39 0 \n", + "40 0 \n", + "41 0 \n", + "42 0 \n", + "43 0 \n", + "44 0 \n", + "45 0 \n", + "46 0 \n", + "47 0 \n", + "48 0 \n", + "49 0 \n", + "50 0 \n", + "51 0 \n", + "52 0 \n", + "53 0 \n", + "\n", + "[54 rows x 23 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6aa9bf8c-f225-4038-bc49-b7a921f246ca", + "metadata": {}, + "outputs": [], + "source": [ + "vc = VidClub(credentials = CREDENTIALS)\n", + "a, b = vc.check_connection(from_date = \"2022-05-01\", to_date=\"2022-06-01\", source = \"jobs\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f4ef3287-c005-49d9-aa38-dc89ff117880", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'current_page': 1,\n", + " 'data': [{'submissionID': 1071,\n", + " 'submissionAddress': 'Żurawia',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 20:45',\n", + " 'customerID': 'tYYcTKIfszynwmf4',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1070,\n", + " 'submissionAddress': 'Juliana Opani',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 20:37',\n", + " 'customerID': 'pwg7XoKFF5FMfLZF',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 13,\n", + " 'points': 90,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1067,\n", + " 'submissionAddress': 'Strada Egalităţii',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 07:54',\n", + " 'customerID': 'fd4ppEcGKm1HSYq7',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 6,\n", + " 'points': 64,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1066,\n", + " 'submissionAddress': 'Sienkiewicza',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 16:18',\n", + " 'customerID': 'Yaddrbn2IY2ccDPp',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 9,\n", + " 'points': 45,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1065,\n", + " 'submissionAddress': 'Chrobrego',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 13:56',\n", + " 'customerID': 'H3BjABhm0dl0jJh1',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 7,\n", + " 'points': 70,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1064,\n", + " 'submissionAddress': 'Jankowicka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/21/2022 13:04',\n", + " 'customerID': 'H3BjABhm0dl0jJh1',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 40,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1063,\n", + " 'submissionAddress': 'Rembielińska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 13:28',\n", + " 'customerID': 'H3BjABhm0dl0jJh1',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1062,\n", + " 'submissionAddress': 'Rembielińska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 13:26',\n", + " 'customerID': 'H3BjABhm0dl0jJh1',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1061,\n", + " 'submissionAddress': 'Małopolska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/10/2022 10:19',\n", + " 'customerID': 'JQTpXoVija32uEzB',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 1060,\n", + " 'submissionAddress': 'Sendlerowej',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/20/2022 10:54',\n", + " 'customerID': 'MxGqVCykMPUCZey3',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1059,\n", + " 'submissionAddress': 'Strada Jiului',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 12:44',\n", + " 'customerID': 'y78f0kWqfaIB5F6g',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 7,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1058,\n", + " 'submissionAddress': 'Piękna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'DzHdosS0tf1zsYu8',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1057,\n", + " 'submissionAddress': 'Pływacka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 10:26',\n", + " 'customerID': 'tYYcTKIfszynwmf4',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1056,\n", + " 'submissionAddress': 'Pływacka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 10:20',\n", + " 'customerID': 'tYYcTKIfszynwmf4',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1055,\n", + " 'submissionAddress': 'Lechów',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'AYpEmrYTeaSRZyiS',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1054,\n", + " 'submissionAddress': 'Generała Edmunda Taczanowskiego',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 14:34',\n", + " 'customerID': 'ymIzPDdYXqECNNrQ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 7,\n", + " 'points': 70,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1053,\n", + " 'submissionAddress': 'Calea Domnească',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 08:40',\n", + " 'customerID': 'grEokZxpPfoH2gdr',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 7,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1052,\n", + " 'submissionAddress': 'Osiniecka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 08:35',\n", + " 'customerID': 'rDGLcq4Og2elwesB',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1051,\n", + " 'submissionAddress': 'Zofii Kossak',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/11/2022 09:25',\n", + " 'customerID': '9ab5ekacidsz0IRx',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1050,\n", + " 'submissionAddress': 'Strada Anghel I. Saligny',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 08:10',\n", + " 'customerID': '2MS738MaZ8ytUtwu',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 14,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1049,\n", + " 'submissionAddress': 'Jodłowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 13:16',\n", + " 'customerID': 'H3BjABhm0dl0jJh1',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 8,\n", + " 'points': 40,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1048,\n", + " 'submissionAddress': 'Lotnicza',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 08:41',\n", + " 'customerID': 'xczTna3SQKI4D6CN',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1047,\n", + " 'submissionAddress': 'Czereśniowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 06:32',\n", + " 'customerID': 'FUugbtnE8kEVeabD',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1046,\n", + " 'submissionAddress': 'Lechitów',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/07/2022 19:29',\n", + " 'customerID': 'RBo3MHMT4Ix6vvPT',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 19,\n", + " 'points': 140,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 1045,\n", + " 'submissionAddress': 'Lechitów',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/05/2022 13:06',\n", + " 'customerID': 'RBo3MHMT4Ix6vvPT',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 10,\n", + " 'points': 100,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 1044,\n", + " 'submissionAddress': 'Grzybowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 19:03',\n", + " 'customerID': '14ksdmnGL0FzkSvO',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 6,\n", + " 'points': 30,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1042,\n", + " 'submissionAddress': 'Grzybiarzy',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 17:07',\n", + " 'customerID': 'sPvG8pNLClGkjABw',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 7,\n", + " 'points': 110,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1041,\n", + " 'submissionAddress': 'Aleea Verde',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 16:54',\n", + " 'customerID': 'Yq1MoCoSyEpqvqEp',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 34,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1040,\n", + " 'submissionAddress': 'Nad Spławką',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 16:21',\n", + " 'customerID': 'iXgEj1jstJtWOofo',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 30,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1039,\n", + " 'submissionAddress': 'Str. Măgura',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 07:03',\n", + " 'customerID': 'VaQrq1nDkYqVlqOA',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 10,\n", + " 'points': 87,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1038,\n", + " 'submissionAddress': 'Retkińska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 14:44',\n", + " 'customerID': 'ymIzPDdYXqECNNrQ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 7,\n", + " 'points': 70,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1036,\n", + " 'submissionAddress': 'Retoryka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/12/2022 09:21',\n", + " 'customerID': 'ymIzPDdYXqECNNrQ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 40,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1034,\n", + " 'submissionAddress': 'Strada Avram Iancu',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 13:25',\n", + " 'customerID': 'BtxqL3tDbcvKX8Es',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 28,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 1033,\n", + " 'submissionAddress': 'Piaski',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 12:46',\n", + " 'customerID': 'JAK9G1O4vXpaAFuv',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1032,\n", + " 'submissionAddress': 'Kwiatowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'JAK9G1O4vXpaAFuv',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1031,\n", + " 'submissionAddress': 'Górna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 12:39',\n", + " 'customerID': 'pwg7XoKFF5FMfLZF',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1030,\n", + " 'submissionAddress': 'Bulevardul Victoriei',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/05/2022 16:09',\n", + " 'customerID': 'PRhfCDdZSpBQ6tdP',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1029,\n", + " 'submissionAddress': 'Trudna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 12:16',\n", + " 'customerID': 'Yaddrbn2IY2ccDPp',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1026,\n", + " 'submissionAddress': 'Żonkilowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 11:12',\n", + " 'customerID': 'UzgRnEeTpJRojd2w',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1024,\n", + " 'submissionAddress': 'Cegielniana',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/09/2022 04:21',\n", + " 'customerID': 'Lzy0ra2ramJqUYGy',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 3,\n", + " 'points': 15,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1022,\n", + " 'submissionAddress': 'Lubelska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 09:21',\n", + " 'customerID': 's10GO5LdAKLlkWxH',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1020,\n", + " 'submissionAddress': 'Parkowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/08/2022 12:16',\n", + " 'customerID': 'm4Gq60TvlLF85KGH',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 15,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1018,\n", + " 'submissionAddress': 'Działkowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '09/22/2022 07:48',\n", + " 'customerID': 'nuaUHDy7rbKJta8g',\n", + " 'status': 'Lost',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1017,\n", + " 'submissionAddress': 'Mała',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/05/2022 09:50',\n", + " 'customerID': 'xExXWy0kskxQg3gB',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1016,\n", + " 'submissionAddress': 'Mała',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/05/2022 09:53',\n", + " 'customerID': 'xExXWy0kskxQg3gB',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1015,\n", + " 'submissionAddress': 'Mała',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/05/2022 09:57',\n", + " 'customerID': 'xExXWy0kskxQg3gB',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1013,\n", + " 'submissionAddress': 'Szafirowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 08:38',\n", + " 'customerID': 'QPE1v6DtFgXvo1Vn',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 8,\n", + " 'points': 40,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1012,\n", + " 'submissionAddress': 'Strada George Enescu',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 10:43',\n", + " 'customerID': '8CAZhYrPJa3i9BWk',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 32,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1011,\n", + " 'submissionAddress': 'Mała',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'EeaOIdBkC2uxlmzJ',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1010,\n", + " 'submissionAddress': 'George Emil Palade',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/28/2022 06:06',\n", + " 'customerID': '8CAZhYrPJa3i9BWk',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 7,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1008,\n", + " 'submissionAddress': 'Str. Botos',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 07:48',\n", + " 'customerID': 'fAGWNcu46Z1wT06P',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1007,\n", + " 'submissionAddress': 'Olszankowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 06:52',\n", + " 'customerID': 'qw4uw4uHwmk5WSi4',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 9,\n", + " 'points': 45,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1006,\n", + " 'submissionAddress': 'Ul. Szczygłów',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 06:58',\n", + " 'customerID': 'NI1iorIXQce7Dxj5',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1005,\n", + " 'submissionAddress': 'Kompasowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 04:41',\n", + " 'customerID': 'jBliksyS9zZgGgRw',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1004,\n", + " 'submissionAddress': 'Nagietkowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 18:53',\n", + " 'customerID': 't95kphNuXAk3BzDu',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1001,\n", + " 'submissionAddress': 'Wolska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/20/2022 07:11',\n", + " 'customerID': 'VVJUVZsPrJ6m7CPH',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 24,\n", + " 'points': 310,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 1000,\n", + " 'submissionAddress': 'Strada Școlii',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 15:39',\n", + " 'customerID': '5TcALQxaZa4ALOaV',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 26,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 999,\n", + " 'submissionAddress': 'Karkonoska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 15:31',\n", + " 'customerID': 'm4Gq60TvlLF85KGH',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 5,\n", + " 'points': 75,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 998,\n", + " 'submissionAddress': 'Strada Erszenyek',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 12:34',\n", + " 'customerID': 'VaQrq1nDkYqVlqOA',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 24,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 997,\n", + " 'submissionAddress': 'Wiśniowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 12:24',\n", + " 'customerID': 'SxmD88RaahgrY4lU',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 3,\n", + " 'points': 15,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 996,\n", + " 'submissionAddress': 'Strada Tudor Vladimirescu',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 11:43',\n", + " 'customerID': 'h2qn885wUBK1aaQZ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 36,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 1},\n", + " {'submissionID': 995,\n", + " 'submissionAddress': 'Galati Bucuresti',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '08/02/2022 10:47',\n", + " 'customerID': 'h2qn885wUBK1aaQZ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 994,\n", + " 'submissionAddress': 'Słowackiego',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 11:23',\n", + " 'customerID': 'TLasOT27yxUHpdn5',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 993,\n", + " 'submissionAddress': 'Główna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 10:50',\n", + " 'customerID': 'onYNuls6zlB70qFp',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 992,\n", + " 'submissionAddress': 'Słowiańska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 10:48',\n", + " 'customerID': 'e1INJmUP6Jp0FTTD',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 991,\n", + " 'submissionAddress': 'Opolska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 11:44',\n", + " 'customerID': 's7dGH9KhTleXHxaJ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 990,\n", + " 'submissionAddress': 'Śliwkowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 't4osYrdhNX0UeH1d',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 989,\n", + " 'submissionAddress': 'Czarnieckiego',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/24/2022 05:06',\n", + " 'customerID': 'xfEPGc6H1pfJ1uqE',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 27,\n", + " 'points': 365,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 1,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 988,\n", + " 'submissionAddress': 'Kalwaryjska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 09:15',\n", + " 'customerID': 'uzUwcxoWQwAR8tYu',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 987,\n", + " 'submissionAddress': 'Michałowice',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 12:24',\n", + " 'customerID': 'blkrYoZhoangAoGi',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 9,\n", + " 'points': 225,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 986,\n", + " 'submissionAddress': '1 Maja',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 09:18',\n", + " 'customerID': 'p1PPyh7NyTI6ANu7',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 8,\n", + " 'points': 40,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 984,\n", + " 'submissionAddress': 'Mickiewicza',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 09:04',\n", + " 'customerID': '1ofjNaQMxXCVjZHn',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 983,\n", + " 'submissionAddress': 'Strada Nicolae Brana',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 08:20',\n", + " 'customerID': 'l4fhYiZNmtAqnvSO',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 6,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 982,\n", + " 'submissionAddress': 'Wantuły',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 07:46',\n", + " 'customerID': 'koEBCWlIvJK859TZ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 5,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 981,\n", + " 'submissionAddress': 'Str. Iancu Gonțea',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/01/2022 12:28',\n", + " 'customerID': '2MS738MaZ8ytUtwu',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 5,\n", + " 'points': 32,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 980,\n", + " 'submissionAddress': 'Mostowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 16:44',\n", + " 'customerID': 'm4Gq60TvlLF85KGH',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 45,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 979,\n", + " 'submissionAddress': 'Strada Vidra',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/02/2022 18:47',\n", + " 'customerID': 'rjvfQg0XGfKJh2YX',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 8,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 978,\n", + " 'submissionAddress': 'Str. Zada',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 13:42',\n", + " 'customerID': 'h2qn885wUBK1aaQZ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 5,\n", + " 'points': 31,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 977,\n", + " 'submissionAddress': 'Strada Sânmartin',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 12:30',\n", + " 'customerID': 'kKAnAdxa2nWDbnJt',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 8,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 1},\n", + " {'submissionID': 975,\n", + " 'submissionAddress': 'Piekary',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 11:01',\n", + " 'customerID': 'blkrYoZhoangAoGi',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 50,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 974,\n", + " 'submissionAddress': 'Wolności',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'X1mW0U6sMcJAQ6Vo',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 973,\n", + " 'submissionAddress': 'Jabłeczna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 10:17',\n", + " 'customerID': 'Zddpqa837WHCBjaE',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 10,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 972,\n", + " 'submissionAddress': 'Szmaragdowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 10:48',\n", + " 'customerID': 'LgkN2NOEimhpQVcn',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 13,\n", + " 'points': 105,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 971,\n", + " 'submissionAddress': 'Szmaragdowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/21/2022 07:51',\n", + " 'customerID': 'LgkN2NOEimhpQVcn',\n", + " 'status': 'Lost',\n", + " 'submissionQuantity': 2,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 970,\n", + " 'submissionAddress': 'Strada Morii',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 09:01',\n", + " 'customerID': '2MS738MaZ8ytUtwu',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 1,\n", + " 'points': 8,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 969,\n", + " 'submissionAddress': 'Szkolna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 11:36',\n", + " 'customerID': 'Crt4lekT4HnoQczX',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 31,\n", + " 'points': 305,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 1},\n", + " {'submissionID': 968,\n", + " 'submissionAddress': 'Szkolna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/12/2022 11:28',\n", + " 'customerID': 'Crt4lekT4HnoQczX',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 5,\n", + " 'points': 95,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 967,\n", + " 'submissionAddress': 'Szkolna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '10/03/2022 06:52',\n", + " 'customerID': 'Crt4lekT4HnoQczX',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 60,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 966,\n", + " 'submissionAddress': 'Okrzei',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'H2sdQEtAHZDCvZMt',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 965,\n", + " 'submissionAddress': 'Strada Avram Iancu',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/30/2022 08:20',\n", + " 'customerID': 'EUBmrscWDtzAFqdr',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 8,\n", + " 'points': 73,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 1,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 1,\n", + " 'q9Core': 0},\n", + " {'submissionID': 964,\n", + " 'submissionAddress': 'Woszczerowicza',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '06/03/2022 06:13',\n", + " 'customerID': 'HrxyZ0VAApk5XG2P',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 4,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 963,\n", + " 'submissionAddress': 'Główna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 07:06',\n", + " 'customerID': '4j03DDh801vSMZhJ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 6,\n", + " 'points': 90,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 1,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 962,\n", + " 'submissionAddress': 'Józefa Poniatowskiego',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': 'Not started yet',\n", + " 'customerID': 'h1df7MlQrCl6UWzF',\n", + " 'status': 'In progress',\n", + " 'submissionQuantity': 0,\n", + " 'points': 0,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': True,\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 961,\n", + " 'submissionAddress': 'Konwaliowa',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '07/07/2022 06:15',\n", + " 'customerID': 'pu5srX4R7jKC3PDZ',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 5,\n", + " 'points': 125,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 960,\n", + " 'submissionAddress': 'Lutycka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/29/2022 07:54',\n", + " 'customerID': 'sPvG8pNLClGkjABw',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 18,\n", + " 'points': 250,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 959,\n", + " 'submissionAddress': 'Lutycka',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/29/2022 07:26',\n", + " 'customerID': 'sPvG8pNLClGkjABw',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 10,\n", + " 'points': 100,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 958,\n", + " 'submissionAddress': 'Nadmorska',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/31/2022 08:36',\n", + " 'customerID': 'IeTrq05cYIn9UIAd',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 20,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': 'Family house, summer house',\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 957,\n", + " 'submissionAddress': 'Strada Satu Batrân',\n", + " 'regionID': 'Romania',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/28/2022 10:45',\n", + " 'customerID': 'kKAnAdxa2nWDbnJt',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 18,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 1,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 1,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 956,\n", + " 'submissionAddress': 'Planetarna',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/28/2022 10:18',\n", + " 'customerID': 'qiBGyBskoGlKx2vw',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 3,\n", + " 'points': 15,\n", + " 'q1Core': 'Part of new build house',\n", + " 'q2Core': True,\n", + " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", + " 'q3Core': True,\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 0,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 1,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0},\n", + " {'submissionID': 954,\n", + " 'submissionAddress': 'Osiedle Pomorskie',\n", + " 'regionID': 'Poland',\n", + " 'submissionPostcode': None,\n", + " 'submissionDate': '05/28/2022 11:32',\n", + " 'customerID': 'gM5O1pze2HjjsJU7',\n", + " 'status': 'Closed',\n", + " 'submissionQuantity': 2,\n", + " 'points': 15,\n", + " 'q1Core': True,\n", + " 'q2Core': True,\n", + " 'q2CoreOther': True,\n", + " 'q3Core': 'VELUX',\n", + " 'q4Core': 'Concrete/ceramic tiles',\n", + " 'q5Core': 1,\n", + " 'q5CoreOther': 0,\n", + " 'q6Core': 0,\n", + " 'q6CoreOther': 0,\n", + " 'q7Core': 0,\n", + " 'q7CoreOther': 0,\n", + " 'q8Core': 0,\n", + " 'q8CoreOther': 0,\n", + " 'q9Core': 0}],\n", + " 'first_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=1',\n", + " 'from': 1,\n", + " 'last_page': 7,\n", + " 'last_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=7',\n", + " 'links': [{'url': None, 'label': 'Previous', 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=1',\n", + " 'label': '1',\n", + " 'active': True},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", + " 'label': '2',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=3',\n", + " 'label': '3',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=4',\n", + " 'label': '4',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=5',\n", + " 'label': '5',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=6',\n", + " 'label': '6',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=7',\n", + " 'label': '7',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", + " 'label': 'Next',\n", + " 'active': False}],\n", + " 'next_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", + " 'path': 'http://api.club.velux.com/api/v1/datalake/jobs',\n", + " 'per_page': 100,\n", + " 'prev_page_url': None,\n", + " 'to': 100,\n", + " 'total': 646}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "610e3e48-2882-46ac-ae2b-f186285e28fd", + "metadata": {}, + "outputs": [], + "source": [ + "source=\"jobs\"\n", + "from_date=\"2023-03-24\"\n", + "to_date=\"2023-03-24\"\n", + "api_url=\"https://api/test/\"\n", + "items_per_page=1" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6f22cfa6-eb85-41f8-8baf-aa0b7ae995d1", + "metadata": {}, + "outputs": [], + "source": [ + "query = vc.build_query(\n", + " source=source,\n", + " from_date=from_date,\n", + " to_date=to_date,\n", + " api_url=api_url,\n", + " items_per_page=items_per_page,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a6696832-a7ab-42c6-a149-ce0f870399ba", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'https://api/test/jobs?from=2023-03-24&to=2023-03-24®ion=all&limit=1'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "query" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "5dd537d3-450d-430a-91be-11a35745b345", + "metadata": {}, + "outputs": [], + "source": [ + "expected = [f\"from={from_date}\", f\"to={to_date}\", \"region=all\", f\"limit={items_per_page}\", api_url]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "8a611252-9259-4e48-b63d-1285c28e8d1d", + "metadata": {}, + "outputs": [], + "source": [ + "for ex in expected:\n", + " assert ex in query" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "52f53d45-0883-47fa-93e3-ca1853808f6d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "execution time for 20 is 212.32157516479492 seconds\n" + ] + } + ], + "source": [ + "# Record start time\n", + "start_time = time.time()\n", + "\n", + "vc = VidClub(credentials = CREDENTIALS)\n", + "\n", + "interval = 20\n", + "listaaa=vc.total_load(source = \"jobs\", days_interval = interval)\n", + "\n", + "end_time = time.time()\n", + "execution_time = end_time - start_time\n", + "print(f\"execution time for {interval} is {execution_time} seconds\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "92c8022b-c96f-4771-87c6-6845ca9c0ba3", + "metadata": {}, + "outputs": [], + "source": [ + "listaaa=vc.total_load(source = \"company\", to_date=\"2022-08-22\")" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d3eebe7b-2abe-4068-bac4-537f2488568d", + "metadata": {}, + "outputs": [], + "source": [ + "from viadot.flows import VidClubToADLS, CustomerGaugeToADLS" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9fe8843a-3c06-462a-b687-b08d5e14552f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 10:37:10+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + }, + { + "ename": "NameError", + "evalue": "name 'df' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m flow \u001b[38;5;241m=\u001b[39m \u001b[43mVidClubToADLS\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtest\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43msource\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msurvey\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_dir_path\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mraw/test\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_file_name\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtest.parquet\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_sp_credentials_secret\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mApp-Azure-CR-DatalakeGen2-AIA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 6\u001b[0m \u001b[43m \u001b[49m\u001b[43moverwrite_adls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 7\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# schedule=schedule,\u001b[39;49;00m\n\u001b[1;32m 8\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# state_handlers=[slack_handler],\u001b[39;49;00m\n\u001b[1;32m 9\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# storage=STORAGE,\u001b[39;49;00m\n\u001b[1;32m 10\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# run_config=RUN_CONFIG\u001b[39;49;00m\n\u001b[1;32m 11\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 12\u001b[0m flow\u001b[38;5;241m.\u001b[39mrun()\n", + "File \u001b[0;32m~/viadot/flows/vid_club_to_adls.py:94\u001b[0m, in \u001b[0;36mVidClubToADLS.__init__\u001b[0;34m(self, name, source, from_date, to_date, items_per_page, region, days_interval, vid_club_credentials, vidclub_credentials_secret, vidclub_vault_name, output_file_extension, adls_dir_path, local_file_path, adls_file_name, vault_name, adls_sp_credentials_secret, overwrite_adls, if_exists, timeout, *args, **kwargs)\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madls_schema_file_dir_file \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(\n\u001b[1;32m 89\u001b[0m adls_dir_path, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mschema\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnow \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.json\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 90\u001b[0m )\n\u001b[1;32m 92\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;241m*\u001b[39margs, name\u001b[38;5;241m=\u001b[39mname, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m---> 94\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgen_flow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/viadot/flows/vid_club_to_adls.py:118\u001b[0m, in \u001b[0;36mVidClubToADLS.gen_flow\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 101\u001b[0m vid_club_df_task \u001b[38;5;241m=\u001b[39m VidClubToDF(\n\u001b[1;32m 102\u001b[0m timeout\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimeout,\n\u001b[1;32m 103\u001b[0m source\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msource,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 106\u001b[0m vault_name\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvidclub_vault_name,\n\u001b[1;32m 107\u001b[0m )\n\u001b[1;32m 109\u001b[0m vid_club_df \u001b[38;5;241m=\u001b[39m vid_club_df_task\u001b[38;5;241m.\u001b[39mbind(\n\u001b[1;32m 110\u001b[0m from_date\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfrom_date,\n\u001b[1;32m 111\u001b[0m to_date\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mto_date,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 115\u001b[0m flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 116\u001b[0m )\n\u001b[0;32m--> 118\u001b[0m df_with_metadata \u001b[38;5;241m=\u001b[39m add_ingestion_metadata_task\u001b[38;5;241m.\u001b[39mbind(\u001b[43mdf\u001b[49m, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 120\u001b[0m dtypes_dict \u001b[38;5;241m=\u001b[39m df_get_data_types_task\u001b[38;5;241m.\u001b[39mbind(df_with_metadata, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 121\u001b[0m df_mapped \u001b[38;5;241m=\u001b[39m df_map_mixed_dtypes_for_parquet\u001b[38;5;241m.\u001b[39mbind(\n\u001b[1;32m 122\u001b[0m df_with_metadata, dtypes_dict, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\n\u001b[1;32m 123\u001b[0m )\n", + "\u001b[0;31mNameError\u001b[0m: name 'df' is not defined" + ] + } + ], + "source": [ + "flow = VidClubToADLS('test', \n", + " source = \"survey\",\n", + " adls_dir_path = \"raw/test\", \n", + " adls_file_name = \"test.parquet\", \n", + " adls_sp_credentials_secret=\"App-Azure-CR-DatalakeGen2-AIA\", \n", + " overwrite_adls=True,\n", + " # schedule=schedule,\n", + " # state_handlers=[slack_handler],\n", + " # storage=STORAGE,\n", + " # run_config=RUN_CONFIG\n", + " )\n", + "flow.run()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1b2ced76-5f2a-4e58-98c9-dd127737fd17", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-24 17:40:22+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + } + ], + "source": [ + "from viadot.task_utils import credentials_loader\n", + "from viadot.utils import handle_api_response\n", + "from viadot.sources import VidClub\n", + "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", + "# CREDENTIALS = {'url': 'https://api.club-t.velux.com/api/v1/datalake/',\n", + "# 'token': 'HRHCyv0Z8AVsF0cJDZD4snCLxjTdszH6VNnwG1DCQn66UGmoaB1fau4Fhrqsauqs'}\n", + "url = \"https://api.club-t.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=2\"\n", + "url = \"https://api.club-t.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=12\"\n", + "headers = {\n", + " \"Authorization\": \"Bearer \" + CREDENTIALS[\"token\"],\n", + " \"Content-Type\": \"application/json\",\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "76f9b77c-75ef-470e-9423-b08c4e3cfca0", + "metadata": {}, + "outputs": [], + "source": [ + "resp = handle_api_response(url=\"https://api.club.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=2®ion=xd\", headers=headers, method=\"GET\", verify=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "31dcf87e-2a50-45d4-bb3a-a425c131baa5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'current_page': 1,\n", + " 'data': [{'customerID': '01h59hdm9fghc8ttg893adv8ka',\n", + " 'companyName': 'Ciesielstwo Dekarstwo Wojciech Kandulski',\n", + " 'address1': 'Kozłowo 44d',\n", + " 'town': 'Opalenica',\n", + " 'postcode': '64-330',\n", + " 'companyNumber': '788 134 57 53',\n", + " 'country': 'Poland',\n", + " 'serviceTechnician': 'Piotr Polak',\n", + " 'areaManager': 'Michał Janiak',\n", + " 'ASEID': '15682844',\n", + " 'customerType': 'INCLUDED',\n", + " 'membershipDate': '2023-07-14T06:29:11.000000Z',\n", + " 'status': 'ACTIVE',\n", + " 'firstName': 'Wojciech',\n", + " 'lastName': 'Kandulski',\n", + " 'email': 'wojtekkandulski@o2.pl',\n", + " 'msisdn': '+48606954064',\n", + " 'languageID': None,\n", + " 'numberOfClosedProjects': 0,\n", + " 'numberOfOpenProjects': 0,\n", + " 'numberOfScans': 0,\n", + " 'totalPoints': 25,\n", + " 'pointsSpent': 0,\n", + " 'currentPoints': 25,\n", + " 'pendingPoints': None,\n", + " 'expiredPoints': None,\n", + " 'expiringPoints': None,\n", + " 'rewardsOrdered': 0,\n", + " 'optinsms': None,\n", + " 'optinemail': None,\n", + " 'optinMarketing': None,\n", + " 'lastlogin': '2023-07-14 06:32:35',\n", + " 'totalLogins': None,\n", + " 'q1Core': 'Slope roofing',\n", + " 'Column 1': 'Roof window installation',\n", + " 'Column 2': '',\n", + " 'q2Core': '26-50%',\n", + " 'q3Core': '1-5%',\n", + " 'q4Core': '2',\n", + " 'q5Core': '5',\n", + " 'q6Core': 'VELUX representative',\n", + " 'q7Core': 'Standard windows',\n", + " 'q8Core': 'Roof windows replacement',\n", + " 'Column 4': '',\n", + " 'Column 3': '',\n", + " 'Column 5': '',\n", + " 'Column 6': '',\n", + " 'Column 7': '',\n", + " 'Column 8': '',\n", + " 'Column 9': '',\n", + " 'Column 10': '',\n", + " 'Column 11': '',\n", + " 'Column 12': '',\n", + " 'Column 13': ''},\n", + " {'customerID': '01h57vg88543yp6hxa85fvw7py',\n", + " 'companyName': 'RuloCleanSolar',\n", + " 'address1': 'strada Plopilor 2B',\n", + " 'town': 'Botosani',\n", + " 'postcode': '710300',\n", + " 'companyNumber': None,\n", + " 'country': 'Romania',\n", + " 'serviceTechnician': 'Constantin Tigita',\n", + " 'areaManager': None,\n", + " 'ASEID': None,\n", + " 'customerType': 'INCLUDED',\n", + " 'membershipDate': '2023-07-13T14:46:54.000000Z',\n", + " 'status': 'ACTIVE',\n", + " 'firstName': 'Romica',\n", + " 'lastName': 'Vatamaniuc',\n", + " 'email': 'rulo.cleansolar@gmail.com',\n", + " 'msisdn': '+40746346463',\n", + " 'languageID': None,\n", + " 'numberOfClosedProjects': 1,\n", + " 'numberOfOpenProjects': 0,\n", + " 'numberOfScans': 14,\n", + " 'totalPoints': 194,\n", + " 'pointsSpent': 0,\n", + " 'currentPoints': 194,\n", + " 'pendingPoints': None,\n", + " 'expiredPoints': None,\n", + " 'expiringPoints': None,\n", + " 'rewardsOrdered': 0,\n", + " 'optinsms': None,\n", + " 'optinemail': None,\n", + " 'optinMarketing': None,\n", + " 'lastlogin': '2023-07-14 06:09:16',\n", + " 'totalLogins': None,\n", + " 'q1Core': 'Slope roofing',\n", + " 'Column 1': 'Carpentry/joinery',\n", + " 'Column 2': 'Roof window installation',\n", + " 'q2Core': '',\n", + " 'q3Core': '51-75%',\n", + " 'q4Core': '11-25%',\n", + " 'q5Core': '3-5',\n", + " 'q6Core': '9',\n", + " 'q7Core': 'VELUX representative',\n", + " 'q8Core': 'Standard windows',\n", + " 'Column 4': 'Roof windows replacement',\n", + " 'Column 3': 'Sun tunnels',\n", + " 'Column 5': '',\n", + " 'Column 6': '',\n", + " 'Column 7': '',\n", + " 'Column 8': '',\n", + " 'Column 9': '',\n", + " 'Column 10': '',\n", + " 'Column 11': '',\n", + " 'Column 12': '',\n", + " 'Column 13': ''}],\n", + " 'first_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=1',\n", + " 'from': 1,\n", + " 'last_page': 1045,\n", + " 'last_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=1045',\n", + " 'links': [{'url': None, 'label': 'Previous', 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1',\n", + " 'label': '1',\n", + " 'active': True},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", + " 'label': '2',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=3',\n", + " 'label': '3',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=4',\n", + " 'label': '4',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=5',\n", + " 'label': '5',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=6',\n", + " 'label': '6',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=7',\n", + " 'label': '7',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=8',\n", + " 'label': '8',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=9',\n", + " 'label': '9',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=10',\n", + " 'label': '10',\n", + " 'active': False},\n", + " {'url': None, 'label': '...', 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1044',\n", + " 'label': '1044',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1045',\n", + " 'label': '1045',\n", + " 'active': False},\n", + " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", + " 'label': 'Next',\n", + " 'active': False}],\n", + " 'next_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", + " 'path': 'http://api.club.velux.com/api/v1/datalake/company',\n", + " 'per_page': 2,\n", + " 'prev_page_url': None,\n", + " 'to': 2,\n", + " 'total': 2090}" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "resp.json()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9f1df1e7-48d9-4814-9337-81a3191b167e", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'pd' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241m.\u001b[39mDataFrame(rere[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdata\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 2\u001b[0m df\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m]\n", + "\u001b[0;31mNameError\u001b[0m: name 'pd' is not defined" + ] + } + ], + "source": [ + "df = pd.DataFrame(rere[\"data\"])\n", + "df.shape[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8479b235-62f5-4ac9-8c62-540798bbbe05", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'rere' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mpd\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m pd\u001b[38;5;241m.\u001b[39mDataFrame(\u001b[43mrere\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdata\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n", + "\u001b[0;31mNameError\u001b[0m: name 'rere' is not defined" + ] + } + ], + "source": [ + "import pandas as pd\n", + "pd.DataFrame(rere[\"data\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b6e8a9bd-8260-4fbd-9069-40a45ac07999", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-24 18:01:30+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + } + ], + "source": [ + "from viadot.task_utils import credentials_loader\n", + "from viadot.utils import handle_api_response\n", + "from viadot.sources import VidClub\n", + "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", + "vc = VidClub(credentials = CREDENTIALS)\n", + "# vc.total_load(source=\"company\", from_date = \"2022-03-22\", to_date = \"2022-04-17\", items_per_page=30, region = \"hr\")\n", + "# df = vc.get_response(source=\"company\")\n", + "# response, first_url = vc.check_connection(\n", + "# source=\"jobs\",\n", + "# from_date=\"2023-03-24\",\n", + "# to_date=\"2023-03-24\",\n", + "# url=\"test\",\n", + "# items_per_page=1,\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4f607195-f589-4734-b0b3-1a6d673298d9", + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "time data '2023' does not match format '%Y-%m-%d'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mvc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mintervals\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfrom_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m2023\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mto_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m2023-04-01\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdays_interval\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/viadot/sources/vid_club.py:99\u001b[0m, in \u001b[0;36mVidClub.intervals\u001b[0;34m(self, from_date, to_date, days_interval)\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mintervals\u001b[39m(\n\u001b[1;32m 81\u001b[0m \u001b[38;5;28mself\u001b[39m, from_date: \u001b[38;5;28mstr\u001b[39m, to_date: \u001b[38;5;28mstr\u001b[39m, days_interval: \u001b[38;5;28mint\u001b[39m\n\u001b[1;32m 82\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Tuple[List[\u001b[38;5;28mstr\u001b[39m], List[\u001b[38;5;28mstr\u001b[39m]]:\n\u001b[1;32m 83\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 84\u001b[0m \u001b[38;5;124;03m Breaks dates range into smaller by provided days interval.\u001b[39;00m\n\u001b[1;32m 85\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;124;03m ValidationError: If the final date of the query is before the start date.\u001b[39;00m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 99\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_date \u001b[38;5;241m==\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 100\u001b[0m end_date \u001b[38;5;241m=\u001b[39m datetime\u001b[38;5;241m.\u001b[39mtoday()\u001b[38;5;241m.\u001b[39mdate()\n\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "File \u001b[0;32m/usr/local/lib/python3.8/_strptime.py:568\u001b[0m, in \u001b[0;36m_strptime_datetime\u001b[0;34m(cls, data_string, format)\u001b[0m\n\u001b[1;32m 565\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_strptime_datetime\u001b[39m(\u001b[38;5;28mcls\u001b[39m, data_string, \u001b[38;5;28mformat\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m%a\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mb \u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mH:\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mM:\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mS \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mY\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 566\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Return a class cls instance based on the input string and the\u001b[39;00m\n\u001b[1;32m 567\u001b[0m \u001b[38;5;124;03m format string.\"\"\"\u001b[39;00m\n\u001b[0;32m--> 568\u001b[0m tt, fraction, gmtoff_fraction \u001b[38;5;241m=\u001b[39m \u001b[43m_strptime\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata_string\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 569\u001b[0m tzname, gmtoff \u001b[38;5;241m=\u001b[39m tt[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m2\u001b[39m:]\n\u001b[1;32m 570\u001b[0m args \u001b[38;5;241m=\u001b[39m tt[:\u001b[38;5;241m6\u001b[39m] \u001b[38;5;241m+\u001b[39m (fraction,)\n", + "File \u001b[0;32m/usr/local/lib/python3.8/_strptime.py:349\u001b[0m, in \u001b[0;36m_strptime\u001b[0;34m(data_string, format)\u001b[0m\n\u001b[1;32m 347\u001b[0m found \u001b[38;5;241m=\u001b[39m format_regex\u001b[38;5;241m.\u001b[39mmatch(data_string)\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m found:\n\u001b[0;32m--> 349\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtime data \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m does not match format \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 350\u001b[0m (data_string, \u001b[38;5;28mformat\u001b[39m))\n\u001b[1;32m 351\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(data_string) \u001b[38;5;241m!=\u001b[39m found\u001b[38;5;241m.\u001b[39mend():\n\u001b[1;32m 352\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124munconverted data remains: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 353\u001b[0m data_string[found\u001b[38;5;241m.\u001b[39mend():])\n", + "\u001b[0;31mValueError\u001b[0m: time data '2023' does not match format '%Y-%m-%d'" + ] + } + ], + "source": [ + "vc.intervals(from_date = '2023', to_date = '2023-04-01', days_interval = 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "286b694f-c32d-4bad-9595-6fef097e12ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
customerIDcompanyNameaddress1townpostcodecompanyNumbercountryserviceTechnicianareaManagerASEID...Column 3Column 5Column 6Column 7Column 8Column 9Column 10Column 11Column 12Column 13
001h5mej1wvwkkr01jmtd5vsvjqRs-DomFrezerów 3Lublin20-209NonePolandNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Shutters and remote controlled awning blindsSun tunnels
101h5ma3j1npx22b5925gcg5n7rKrovstvo Kleparstvo Robert Vek s.pPtujska Gora 100aPtujska gora232316823079SloveniaCiril BadokoJurij Saletinger48193...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof terrace and balconyShutters and remote controlled awning blinds
001h5m918wrkypx3wwjdmd85wpzBlacharstwo-dekarstwo Krzysztof ZawadzkiKiedrzyn 48Gózd26-6347961871484PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Shutters and remote controlled awning blindsSun tunnelsRoof window repair / maintenance
101h5m6hty8rhj2w4vv12014yg8Tim starVasif H Zejcirevic 5Brčko761004700620460008Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m63bz6eyn80ff1msncerg7Cer KomercDEVETA ULICA 5Zvornik754004400233640002Bosnia and HerzegovinaNoneNoneNone...Roof window combinations with vertical window ...Roof window repair / maintenance
101h5m5jv9eaqfd42ewgrqwy040Slavuj d.o.o.Nikole Tesle b.b.Brčko76101600014990005Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m5hkxxa1tj159h1t9nh7acSZD ,,Došenović,,Kozarska Dubica jošik bbKozarska Dubica792404511800620006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h5m53gw4e5dqdptpfncrf8gmSZD \"Došenović\"Jošik BBKozarska Dubica792400101979100001Bosnia and HerzegovinaNoneNoneNone...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenanceRoof window combinations with vertical window ...Install home automatization / smart home solutionElectrical and solar INTEGRA solutions (roof w...
001h5m51zbqy23xv1v8ae6b1svsWestalBulevar VII korpusa 50Sanski Most79260263722240001Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsRoof window repair / maintenance
101h5m4mympp0b49jpcbhz3cdfsApisMokri dolovi bbTrebinje89101401341230003Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsRoof window repair / maintenance
001h5m4dvbyw4f7cctz01fhnkx3DOO TemikaCara Dusana BbFoca73300403921900009Bosnia and HerzegovinaNoneNoneNone...Roof windows replacement
101h5m4aj80qwkdax5a09m97av2Parter d.o.o.Bleiburških žrtava 134Mostar88000227173590007Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m47m3qnyz5c0jjrxyk30yhTrgometalKovači bbPosušje88240272038500001Bosnia and HerzegovinaNoneNoneNone...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h5m440b8k38xfqwxhkr7sbqgDESC dooNikole Tesle 53dLukavica711244404522490006Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m43qrhp6660zmfzycv10ktLima-LozicVakuf bb 030516058Travnik72270NoneBosnia and HerzegovinaNoneNoneNone...
101h5m40a0xwyt75jw18y2qc8wtMegraDoglodska 2Zenica720004218299430006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m3wwbpknrs8nqn3rjh6dj4OD.ResicBranislava Nušića 173Sarajevo71000421868396004Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsRoof window repair / maintenanceFlat roof windowsSun tunnels
101h5m3tvagx8fbqtrqhzqdked9Limarija HamoGuvna 26Travnik722704337740010009Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Install home automatization / smart home solutionRoof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m3rn5y9gfctjff64je0b51LimFix ŽepčePapratnica BbŽepče722304320177890005Bosnia and HerzegovinaNoneNoneNone...
101h5m34992emrafttpjeqww13dHado GradnjaDonjaVisca BBŽivinice75270311396510006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5ktxk4m66ay8wkhd6q7agayWitek Firma Handlowo UsługowaOsusz 32Krotoszyn63-700621 161 88 52PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnels
101h59typva56yvvd79gyqrxa7cPantes 2017Ержебет Силађи 3Суботица24000110116303SerbiaNoneNoneNone...Lining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Install home automatization / smart home solutionRoof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h59ttph5fnwff3y6ytc36mm5SB RoloplastХерцеговачка 27Зрењанин2310156215816SerbiaNoneNoneNone...Sun tunnelsShutters and remote controlled awning blindsRoof window repair / maintenance
101h59tsxds6k98bmmk5kqbrzq8SB RolosplastХерцеговачка 27Зрењанин2300056215816SerbiaNoneNoneNone...Roof windows replacementSun tunnelsShutters and remote controlled awning blinds
001h59trfz5scnsnkafrcjk49p9KrovomontBošnjakMatije Gupca 12Sonta2526464247620SerbiaNoneNoneNone...Roof windows replacement
101h59tgn306tjepd2rst6t2yqtSZR\"Haus majstor\"Marije Bursać 30Kikinda2330062425911SerbiaNoneNoneNone...Roof windows replacementLining preparationSun tunnelsRoof window repair / maintenance
001h59tf315qn76cegzwnymdsjhIntegra021Trg Cara Lazara 5Beocin21300108997552SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof terrace and balconyRoof window combinations with vertical window ...Flat roof windowsSun tunnelsRoof window repair / maintenanceShutters and remote controlled awning blinds
101h59hdm9fghc8ttg893adv8kaCiesielstwo Dekarstwo Wojciech KandulskiKozłowo 44dOpalenica64-330788 134 57 53PolandNoneNoneNone...
001h58bvwtb8b8w19typshbkqtyPRO.MAX.TEAMМилице Српкиње 13Београд1100020177438SerbiaNoneNoneNone...Lining preparationElectrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsRoof window repair / maintenance
101h57vg88543yp6hxa85fvw7pyRuloCleanSolarstrada Plopilor 2BBotosani710300NoneRomaniaConstantin TigitaNoneNone...Sun tunnels
001h57ftmsjvr65jddzs9vkaxmkGZR Majstor PantaMalo crnice BbMalo crnice1231164082795SerbiaNoneNoneNone...Roof windows replacementInstall home automatization / smart home solutionRoof window combinations with vertical window ...Shutters and remote controlled awning blindsRoof window repair / maintenance
101h57fsq0mqgmwetyc1mwkyntqProzor PlusКраља Петра 14Београд11130108908193SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57fp2519nnz1w5jpc64e1wbUnlimited gradnja BeogradТрговачка 4Београд11030111911923SerbiaNoneNoneNone...Warm installation solutions (BDX, BBX)Lining preparationRoof window repair / maintenance
101h57fjevd411bf7pcj2xnafn9Pro 5Trbunje 5Blace1842064714996SerbiaNoneNoneNone...Warm installation solutions (BDX, BBX)Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57fe5adpyj2t2meeye5wg7vVizart sistemБраће Вучковић 62Београд1114766665097SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h57fe0x3715en0m6h9esaytkNas Krov PlusСрбичка 15Београд1108562885297SerbiaNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57f7wbfs75mzeen7amrmw11Zr MiskovicSrpskih serdara 2Београд11000105628951SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof terrace and balconyFlat roof windowsSun tunnelsShutters and remote controlled awning blindsRoof window repair / maintenance
101h57c7abjx278gdy820dc0v6bQuartz Impex srlCalea Națională 8Botoșani717007NoneRomaniaConstantin TigitaNoneNone...Roof window repair / maintenanceSun tunnels
001h57adcnb4y1g6y06q73wn7r3QuartzCalea nationala 8Botoșani710098NoneRomaniaConstantin TigitaNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solution
101h577vaspgjpzhahvk15h0fagPrzem- BudPoznańska 9/3Kórnik62-035785 17 32 793PolandNoneNoneNone...Roof windows replacementShutters and remote controlled awning blinds
001h54xw4ebfhm7vfwq9wwskstdRussa-fix d.o.o.Zagrebačka ulica 48Sveti ivan zelina1038078413994889CroatiaTomislav DelačŽeljko PetrovićNone...
101h54wm99h2geyrj8kdc28y709Efekt Dachy Marcin BoguszProsta 7Krzywda21-470825 20 41 333PolandNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsSun tunnelsRoof window repair / maintenance
001h54tb1r8j8djfyf1v4rsn0p1Architect Line Stúdió kftLiget utca 16/1Kiskőrös620003-09-121591HungaryNoneMészáros Zoltán2662...Flat roof windowsShutters and remote controlled awning blindsElectrical and solar INTEGRA solutions (roof w...Lining preparationRoof windows replacementWarm installation solutions (BDX, BBX)Standard windowsRoof terrace and balcony
101h52sexkw5c8b71n614nw6919KARDEK-DACHYStanowice 2Stanowice55-2008961229251PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof terrace and balconyShutters and remote controlled awning blindsSun tunnels
001h529q6p9cbde0f9x2epqknrpPalka Andrzej FUHandlowa Palka-Dach-Budul. Ryszarda Moskały 11Zagórze32-5557371953169PolandNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Shutters and remote controlled awning blindsFlat roof windowsSun tunnels
101h52099qx6mb3jek851xg4q5sStanila Nicolae George pfaSat hapria nr 228Alba Iulia51724327479852RomaniaIoan IacobNoneNone...Roof windows replacementRoof terrace and balconyFlat roof windowsSun tunnels
001h4zyj42emdy4key1y8shhdhtПокриви ЕООДс. Лозен 10София1151203932976BulgariaNoneNoneNone...
\n", + "

47 rows × 54 columns

\n", + "
" + ], + "text/plain": [ + " customerID companyName \\\n", + "0 01h5mej1wvwkkr01jmtd5vsvjq Rs-Dom \n", + "1 01h5ma3j1npx22b5925gcg5n7r Krovstvo Kleparstvo Robert Vek s.p \n", + "0 01h5m918wrkypx3wwjdmd85wpz Blacharstwo-dekarstwo Krzysztof Zawadzki \n", + "1 01h5m6hty8rhj2w4vv12014yg8 Tim star \n", + "0 01h5m63bz6eyn80ff1msncerg7 Cer Komerc \n", + "1 01h5m5jv9eaqfd42ewgrqwy040 Slavuj d.o.o. \n", + "0 01h5m5hkxxa1tj159h1t9nh7ac SZD ,,Došenović,, \n", + "1 01h5m53gw4e5dqdptpfncrf8gm SZD \"Došenović\" \n", + "0 01h5m51zbqy23xv1v8ae6b1svs Westal \n", + "1 01h5m4mympp0b49jpcbhz3cdfs Apis \n", + "0 01h5m4dvbyw4f7cctz01fhnkx3 DOO Temika \n", + "1 01h5m4aj80qwkdax5a09m97av2 Parter d.o.o. \n", + "0 01h5m47m3qnyz5c0jjrxyk30yh Trgometal \n", + "1 01h5m440b8k38xfqwxhkr7sbqg DESC doo \n", + "0 01h5m43qrhp6660zmfzycv10kt Lima-Lozic \n", + "1 01h5m40a0xwyt75jw18y2qc8wt Megra \n", + "0 01h5m3wwbpknrs8nqn3rjh6dj4 OD.Resic \n", + "1 01h5m3tvagx8fbqtrqhzqdked9 Limarija Hamo \n", + "0 01h5m3rn5y9gfctjff64je0b51 LimFix Žepče \n", + "1 01h5m34992emrafttpjeqww13d Hado Gradnja \n", + "0 01h5ktxk4m66ay8wkhd6q7agay Witek Firma Handlowo Usługowa \n", + "1 01h59typva56yvvd79gyqrxa7c Pantes 2017 \n", + "0 01h59ttph5fnwff3y6ytc36mm5 SB Roloplast \n", + "1 01h59tsxds6k98bmmk5kqbrzq8 SB Rolosplast \n", + "0 01h59trfz5scnsnkafrcjk49p9 KrovomontBošnjak \n", + "1 01h59tgn306tjepd2rst6t2yqt SZR\"Haus majstor\" \n", + "0 01h59tf315qn76cegzwnymdsjh Integra021 \n", + "1 01h59hdm9fghc8ttg893adv8ka Ciesielstwo Dekarstwo Wojciech Kandulski \n", + "0 01h58bvwtb8b8w19typshbkqty PRO.MAX.TEAM \n", + "1 01h57vg88543yp6hxa85fvw7py RuloCleanSolar \n", + "0 01h57ftmsjvr65jddzs9vkaxmk GZR Majstor Panta \n", + "1 01h57fsq0mqgmwetyc1mwkyntq Prozor Plus \n", + "0 01h57fp2519nnz1w5jpc64e1wb Unlimited gradnja Beograd \n", + "1 01h57fjevd411bf7pcj2xnafn9 Pro 5 \n", + "0 01h57fe5adpyj2t2meeye5wg7v Vizart sistem \n", + "1 01h57fe0x3715en0m6h9esaytk Nas Krov Plus \n", + "0 01h57f7wbfs75mzeen7amrmw11 Zr Miskovic \n", + "1 01h57c7abjx278gdy820dc0v6b Quartz Impex srl \n", + "0 01h57adcnb4y1g6y06q73wn7r3 Quartz \n", + "1 01h577vaspgjpzhahvk15h0fag Przem- Bud \n", + "0 01h54xw4ebfhm7vfwq9wwskstd Russa-fix d.o.o. \n", + "1 01h54wm99h2geyrj8kdc28y709 Efekt Dachy Marcin Bogusz \n", + "0 01h54tb1r8j8djfyf1v4rsn0p1 Architect Line Stúdió kft \n", + "1 01h52sexkw5c8b71n614nw6919 KARDEK-DACHY \n", + "0 01h529q6p9cbde0f9x2epqknrp Palka Andrzej FUHandlowa Palka-Dach-Bud \n", + "1 01h52099qx6mb3jek851xg4q5s Stanila Nicolae George pfa \n", + "0 01h4zyj42emdy4key1y8shhdht Покриви ЕООД \n", + "\n", + " address1 town postcode companyNumber \\\n", + "0 Frezerów 3 Lublin 20-209 None \n", + "1 Ptujska Gora 100a Ptujska gora 2323 16823079 \n", + "0 Kiedrzyn 48 Gózd 26-634 7961871484 \n", + "1 Vasif H Zejcirevic 5 Brčko 76100 4700620460008 \n", + "0 DEVETA ULICA 5 Zvornik 75400 4400233640002 \n", + "1 Nikole Tesle b.b. Brčko 76101 600014990005 \n", + "0 Kozarska Dubica jošik bb Kozarska Dubica 79240 4511800620006 \n", + "1 Jošik BB Kozarska Dubica 79240 0101979100001 \n", + "0 Bulevar VII korpusa 50 Sanski Most 79260 263722240001 \n", + "1 Mokri dolovi bb Trebinje 89101 401341230003 \n", + "0 Cara Dusana Bb Foca 73300 403921900009 \n", + "1 Bleiburških žrtava 134 Mostar 88000 227173590007 \n", + "0 Kovači bb Posušje 88240 272038500001 \n", + "1 Nikole Tesle 53d Lukavica 71124 4404522490006 \n", + "0 Vakuf bb 030516058 Travnik 72270 None \n", + "1 Doglodska 2 Zenica 72000 4218299430006 \n", + "0 Branislava Nušića 173 Sarajevo 71000 421868396004 \n", + "1 Guvna 26 Travnik 72270 4337740010009 \n", + "0 Papratnica Bb Žepče 72230 4320177890005 \n", + "1 DonjaVisca BB Živinice 75270 311396510006 \n", + "0 Osusz 32 Krotoszyn 63-700 621 161 88 52 \n", + "1 Ержебет Силађи 3 Суботица 24000 110116303 \n", + "0 Херцеговачка 27 Зрењанин 23101 56215816 \n", + "1 Херцеговачка 27 Зрењанин 23000 56215816 \n", + "0 Matije Gupca 12 Sonta 25264 64247620 \n", + "1 Marije Bursać 30 Kikinda 23300 62425911 \n", + "0 Trg Cara Lazara 5 Beocin 21300 108997552 \n", + "1 Kozłowo 44d Opalenica 64-330 788 134 57 53 \n", + "0 Милице Српкиње 13 Београд 11000 20177438 \n", + "1 strada Plopilor 2B Botosani 710300 None \n", + "0 Malo crnice Bb Malo crnice 12311 64082795 \n", + "1 Краља Петра 14 Београд 11130 108908193 \n", + "0 Трговачка 4 Београд 11030 111911923 \n", + "1 Trbunje 5 Blace 18420 64714996 \n", + "0 Браће Вучковић 62 Београд 11147 66665097 \n", + "1 Србичка 15 Београд 11085 62885297 \n", + "0 Srpskih serdara 2 Београд 11000 105628951 \n", + "1 Calea Națională 8 Botoșani 717007 None \n", + "0 Calea nationala 8 Botoșani 710098 None \n", + "1 Poznańska 9/3 Kórnik 62-035 785 17 32 793 \n", + "0 Zagrebačka ulica 48 Sveti ivan zelina 10380 78413994889 \n", + "1 Prosta 7 Krzywda 21-470 825 20 41 333 \n", + "0 Liget utca 16/1 Kiskőrös 6200 03-09-121591 \n", + "1 Stanowice 2 Stanowice 55-200 8961229251 \n", + "0 ul. Ryszarda Moskały 11 Zagórze 32-555 7371953169 \n", + "1 Sat hapria nr 228 Alba Iulia 517243 27479852 \n", + "0 с. Лозен 10 София 1151 203932976 \n", + "\n", + " country serviceTechnician areaManager ASEID ... \\\n", + "0 Poland None None None ... \n", + "1 Slovenia Ciril Badoko Jurij Saletinger 48193 ... \n", + "0 Poland None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Bosnia and Herzegovina None None None ... \n", + "1 Bosnia and Herzegovina None None None ... \n", + "0 Poland None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Poland None None None ... \n", + "0 Serbia None None None ... \n", + "1 Romania Constantin Tigita None None ... \n", + "0 Serbia None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Serbia None None None ... \n", + "0 Serbia None None None ... \n", + "1 Romania Constantin Tigita None None ... \n", + "0 Romania Constantin Tigita None None ... \n", + "1 Poland None None None ... \n", + "0 Croatia Tomislav Delač Željko Petrović None ... \n", + "1 Poland None None None ... \n", + "0 Hungary None Mészáros Zoltán 2662 ... \n", + "1 Poland None None None ... \n", + "0 Poland None None None ... \n", + "1 Romania Ioan Iacob None None ... \n", + "0 Bulgaria None None None ... \n", + "\n", + " Column 3 \\\n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof windows replacement \n", + "0 Roof windows replacement \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Roof window combinations with vertical window ... \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof windows replacement \n", + "0 Roof windows replacement \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Roof windows replacement \n", + "0 \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof windows replacement \n", + "0 \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Roof windows replacement \n", + "1 Lining preparation \n", + "0 Sun tunnels \n", + "1 Roof windows replacement \n", + "0 Roof windows replacement \n", + "1 Roof windows replacement \n", + "0 Roof windows replacement \n", + "1 \n", + "0 Lining preparation \n", + "1 Sun tunnels \n", + "0 Roof windows replacement \n", + "1 Roof windows replacement \n", + "0 Warm installation solutions (BDX, BBX) \n", + "1 Warm installation solutions (BDX, BBX) \n", + "0 Roof windows replacement \n", + "1 Roof windows replacement \n", + "0 Roof windows replacement \n", + "1 Roof window repair / maintenance \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof windows replacement \n", + "0 \n", + "1 Roof windows replacement \n", + "0 Flat roof windows \n", + "1 Roof windows replacement \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof windows replacement \n", + "0 \n", + "\n", + " Column 5 \\\n", + "0 Install home automatization / smart home solution \n", + "1 Lining preparation \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Roof window repair / maintenance \n", + "1 Install home automatization / smart home solution \n", + "0 Install home automatization / smart home solution \n", + "1 Flat roof windows \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Lining preparation \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Flat roof windows \n", + "1 Lining preparation \n", + "0 \n", + "1 Install home automatization / smart home solution \n", + "0 Install home automatization / smart home solution \n", + "1 Lining preparation \n", + "0 \n", + "1 Install home automatization / smart home solution \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Sun tunnels \n", + "0 \n", + "1 Lining preparation \n", + "0 Lining preparation \n", + "1 \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 \n", + "0 Install home automatization / smart home solution \n", + "1 Lining preparation \n", + "0 Lining preparation \n", + "1 Roof window combinations with vertical window ... \n", + "0 Lining preparation \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Lining preparation \n", + "1 Sun tunnels \n", + "0 Install home automatization / smart home solution \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 Lining preparation \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Roof window combinations with vertical window ... \n", + "1 Roof terrace and balcony \n", + "0 \n", + "\n", + " Column 6 \\\n", + "0 Roof window combinations with vertical window ... \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Roof window combinations with vertical window ... \n", + "1 Flat roof windows \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 Roof window combinations with vertical window ... \n", + "1 Sun tunnels \n", + "0 Roof window repair / maintenance \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 \n", + "1 Flat roof windows \n", + "0 Sun tunnels \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 Roof window combinations with vertical window ... \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Roof window combinations with vertical window ... \n", + "0 Roof window repair / maintenance \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 Sun tunnels \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 \n", + "0 Shutters and remote controlled awning blinds \n", + "1 \n", + "0 Roof window combinations with vertical window ... \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Roof window repair / maintenance \n", + "1 Roof terrace and balcony \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof window combinations with vertical window ... \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 Electrical and solar INTEGRA solutions (roof w... \n", + "1 Roof terrace and balcony \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Flat roof windows \n", + "0 \n", + "\n", + " Column 7 \\\n", + "0 Shutters and remote controlled awning blinds \n", + "1 Roof terrace and balcony \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Sun tunnels \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 Roof terrace and balcony \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 \n", + "1 Sun tunnels \n", + "0 Roof window repair / maintenance \n", + "1 Install home automatization / smart home solution \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 Roof terrace and balcony \n", + "1 Roof window combinations with vertical window ... \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 Flat roof windows \n", + "1 Install home automatization / smart home solution \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 Install home automatization / smart home solution \n", + "1 \n", + "0 Flat roof windows \n", + "1 \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Install home automatization / smart home solution \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Install home automatization / smart home solution \n", + "1 Roof terrace and balcony \n", + "0 Install home automatization / smart home solution \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 Lining preparation \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Flat roof windows \n", + "1 Sun tunnels \n", + "0 \n", + "\n", + " Column 8 \\\n", + "0 Sun tunnels \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Sun tunnels \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Roof window combinations with vertical window ... \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 Roof window combinations with vertical window ... \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Install home automatization / smart home solution \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Sun tunnels \n", + "1 Roof terrace and balcony \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Roof terrace and balcony \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 Roof window combinations with vertical window ... \n", + "0 \n", + "1 Flat roof windows \n", + "0 Roof window combinations with vertical window ... \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Roof terrace and balcony \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 Roof windows replacement \n", + "1 Sun tunnels \n", + "0 Sun tunnels \n", + "1 \n", + "0 \n", + "\n", + " Column 9 \\\n", + "0 \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 \n", + "1 Flat roof windows \n", + "0 Flat roof windows \n", + "1 Install home automatization / smart home solution \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 \n", + "1 Flat roof windows \n", + "0 Roof window repair / maintenance \n", + "1 Roof terrace and balcony \n", + "0 \n", + "1 Flat roof windows \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Roof window combinations with vertical window ... \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof terrace and balcony \n", + "0 \n", + "1 Sun tunnels \n", + "0 Roof terrace and balcony \n", + "1 Flat roof windows \n", + "0 Flat roof windows \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 Warm installation solutions (BDX, BBX) \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "\n", + " Column 10 \\\n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Sun tunnels \n", + "0 Sun tunnels \n", + "1 Electrical and solar INTEGRA solutions (roof w... \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 Sun tunnels \n", + "0 Flat roof windows \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 Sun tunnels \n", + "0 \n", + "1 Flat roof windows \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Flat roof windows \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Shutters and remote controlled awning blinds \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 Shutters and remote controlled awning blinds \n", + "1 Sun tunnels \n", + "0 Sun tunnels \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Sun tunnels \n", + "0 Standard windows \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "\n", + " Column 11 \\\n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Flat roof windows \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 Sun tunnels \n", + "1 Flat roof windows \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 Sun tunnels \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Sun tunnels \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Flat roof windows \n", + "0 \n", + "1 \n", + "0 Flat roof windows \n", + "1 Roof window repair / maintenance \n", + "0 Shutters and remote controlled awning blinds \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 Roof terrace and balcony \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "\n", + " Column 12 \\\n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Sun tunnels \n", + "0 \n", + "1 \n", + "0 \n", + "1 Sun tunnels \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Sun tunnels \n", + "0 \n", + "1 \n", + "0 Sun tunnels \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "\n", + " Column 13 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 Shutters and remote controlled awning blinds \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 Roof window repair / maintenance \n", + "0 \n", + "1 \n", + "0 Roof window repair / maintenance \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "1 \n", + "0 \n", + "\n", + "[47 rows x 54 columns]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "d9e52c0f-0205-4a29-8ef3-fb22dc43f72f", + "metadata": {}, + "outputs": [], + "source": [ + "mask = df.duplicated()" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "5ce19ea1-dbaa-4572-bf48-843aff47c4e3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
customerIDcompanyNameaddress1townpostcodecompanyNumbercountryserviceTechnicianareaManagerASEID...Column 3Column 5Column 6Column 7Column 8Column 9Column 10Column 11Column 12Column 13
\n", + "

0 rows × 54 columns

\n", + "
" + ], + "text/plain": [ + "Empty DataFrame\n", + "Columns: [customerID, companyName, address1, town, postcode, companyNumber, country, serviceTechnician, areaManager, ASEID, customerType, membershipDate, status, firstName, lastName, email, msisdn, languageID, numberOfClosedProjects, numberOfOpenProjects, numberOfScans, totalPoints, pointsSpent, currentPoints, pendingPoints, expiredPoints, expiringPoints, rewardsOrdered, optinsms, optinemail, optinMarketing, lastlogin, totalLogins, q1Core, Column 1, Column 2, q2Core, q3Core, q4Core, q5Core, q6Core, q7Core, q8Core, Column 4, Column 3, Column 5, Column 6, Column 7, Column 8, Column 9, Column 10, Column 11, Column 12, Column 13]\n", + "Index: []\n", + "\n", + "[0 rows x 54 columns]" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[mask]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "29a88b03-6614-483c-90e7-44409529206f", + "metadata": {}, + "outputs": [], + "source": [ + "new_structure = list(df.columns)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "8599228f-5675-402d-881c-c5bc545731b0", + "metadata": {}, + "outputs": [], + "source": [ + "lista = ['__v',\n", + " '_id',\n", + " 'countrySlug',\n", + " 'createdAt',\n", + " 'id',\n", + " 'negativePointsByYear',\n", + " 'positivePointsByYear',\n", + " 'survey']" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "352e705b-0583-427f-a781-01c0cafd9e31", + "metadata": {}, + "outputs": [], + "source": [ + "new_structure = df.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "039fa415-cfa4-4970-bf66-93b84afb09ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 13:33:16+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" + ] + } + ], + "source": [ + "from viadot.tasks import VidClubToDF\n", + "from datetime import datetime, date, timedelta\n", + "\n", + "VC = VidClubToDF(source = \"jobs\", to_date=\"2023-07-12\", from_date=\"2023-07-01\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "19918ac7-9810-47c1-9ab9-f1063ac4dffa", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 13:27:03+0000] INFO - prefect | ingesting data for dates [2023-07-01]-[2023-07-12]...\n", + "[2023-07-25 13:27:07+0000] INFO - prefect | Dropping following columns: ['regionID', 'submissionDate']...\n" + ] + } + ], + "source": [ + "df = VC.run(cols_to_drop = ['regionID', 'submissionDate'])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e6397bd2-97dc-41a1-aa98-00ba83e4b6fc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'customerID',\n", + " 'points',\n", + " 'q1Core',\n", + " 'q2Core',\n", + " 'q2CoreOther',\n", + " 'q3Core',\n", + " 'q4Core',\n", + " 'q5Core',\n", + " 'q5CoreOther',\n", + " 'q6Core',\n", + " 'q6CoreOther',\n", + " 'q7Core',\n", + " 'q7CoreOther',\n", + " 'q8Core',\n", + " 'q8CoreOther',\n", + " 'q9Core',\n", + " 'status',\n", + " 'submissionAddress',\n", + " 'submissionID',\n", + " 'submissionPostcode',\n", + " 'submissionQuantity'}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set(list(df.columns)) - set(list(['regionID', 'submissionDate']))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "c60bea39-39b1-49b9-9aad-ec18c6306933", + "metadata": {}, + "outputs": [], + "source": [ + "to_date = None\n", + "from_date = \"2022-04-01\"\n", + "days_interval = 30" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5b0a2b7b-a794-4832-a274-d6bf9739ef50", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2022-04-01\n" + ] + } + ], + "source": [ + "date_str = \"2022-04-01\"\n", + "date_obj = datetime.strptime(date_str, \"%Y-%m-%d\").date()\n", + "print(date_obj) " + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "80a4c756-c3b6-4424-a898-e2e543a68c00", + "metadata": {}, + "outputs": [], + "source": [ + "if to_date == None:\n", + " end_date = datetime.today().date()\n", + "else:\n", + " end_date = datetime.strptime(to_date, \"%Y-%m-%d\").date()\n", + "start_date = datetime.strptime(from_date, \"%Y-%m-%d\").date()\n", + "interval = timedelta(days=days_interval)\n", + "starts = []\n", + "ends = []\n", + "period_start = start_date\n", + "while period_start < end_date:\n", + " period_end = min(period_start + interval, end_date)\n", + " starts.append(period_start.strftime(\"%Y-%m-%d\"))\n", + " ends.append(period_end.strftime(\"%Y-%m-%d\"))\n", + " period_start = period_end" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "14488d7b-937a-486c-8c2a-78189156cb9f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 13:34:29+0000] INFO - prefect | ingesting data for dates [2022-03-23]-[2022-03-24]...\n", + "[2023-07-25 13:34:35+0000] INFO - prefect | ingesting data for dates [2022-03-23]-[2022-03-24]...\n", + "[2023-07-25 13:34:41+0000] INFO - prefect | Dropping following columns: ['regionID', 'submissionDate']...\n" + ] + } + ], + "source": [ + "cols_to_drop = [\"regionID\", \"submissionDate\"]\n", + "var_dictionary = {\n", + " \"source\": \"jobs\",\n", + " \"from_date\": \"2022-03-23\",\n", + " \"to_date\": \"2022-03-24\",\n", + " \"items_per_page\": 1,\n", + " \"days_interval\": 1,\n", + "}\n", + "\n", + "output_with_all = VC.run(\n", + " source=var_dictionary[\"source\"],\n", + " to_date=var_dictionary[\"to_date\"],\n", + " from_date=var_dictionary[\"from_date\"],\n", + " items_per_page=var_dictionary[\"items_per_page\"],\n", + " days_interval=var_dictionary[\"days_interval\"],\n", + ")\n", + "output_with_dropped = VC.run(\n", + " source=var_dictionary[\"source\"],\n", + " to_date=var_dictionary[\"to_date\"],\n", + " from_date=var_dictionary[\"from_date\"],\n", + " items_per_page=var_dictionary[\"items_per_page\"],\n", + " days_interval=var_dictionary[\"days_interval\"],\n", + " cols_to_drop=cols_to_drop,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "13303ab5-05eb-4e40-b79a-b9f12f9b1a1f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'customerID',\n", + " 'points',\n", + " 'q1Core',\n", + " 'q2Core',\n", + " 'q2CoreOther',\n", + " 'q3Core',\n", + " 'q4Core',\n", + " 'q5Core',\n", + " 'q5CoreOther',\n", + " 'q6Core',\n", + " 'q6CoreOther',\n", + " 'q7Core',\n", + " 'q7CoreOther',\n", + " 'q8Core',\n", + " 'q8CoreOther',\n", + " 'q9Core',\n", + " 'regionID',\n", + " 'status',\n", + " 'submissionAddress',\n", + " 'submissionDate',\n", + " 'submissionID',\n", + " 'submissionPostcode',\n", + " 'submissionQuantity'}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set(list(output_with_all.columns))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f43b9be4-a3bd-49e3-9627-a2667ca34d19", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-25 14:21:13+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n", + "[2023-07-25 14:21:13+0000] INFO - prefect | ingesting data for dates [2023-07-01]-[2023-07-12]...\n", + "[2023-07-25 14:21:17+0000] INFO - prefect | Dropping following columns: ['Test', 'submissionDate']...\n", + "[2023-07-25 14:21:17+0000] ERROR - prefect | Column(s): ['Test', 'submissionDate'] don't exist in the DataFrame. No columns were dropped. Returning full DataFrame...\n", + "[2023-07-25 14:21:17+0000] INFO - prefect | Existing columns: Index(['submissionID', 'submissionAddress', 'regionID', 'submissionPostcode',\n", + " 'submissionDate', 'customerID', 'status', 'submissionQuantity',\n", + " 'points', 'q1Core', 'q2Core', 'q2CoreOther', 'q3Core', 'q4Core',\n", + " 'q5Core', 'q5CoreOther', 'q6Core', 'q6CoreOther', 'q7Core',\n", + " 'q7CoreOther', 'q8Core', 'q8CoreOther', 'q9Core'],\n", + " dtype='object')\n" + ] + }, + { + "ename": "NameError", + "evalue": "name 'caplog' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[19], line 16\u001b[0m\n\u001b[1;32m 13\u001b[0m VC\u001b[38;5;241m.\u001b[39mrun(cols_to_drop \u001b[38;5;241m=\u001b[39m cols_to_drop) \u001b[38;5;66;03m# Call your function with appropriate arguments\u001b[39;00m\n\u001b[1;32m 15\u001b[0m \u001b[38;5;66;03m# Verify the loggers\u001b[39;00m\n\u001b[0;32m---> 16\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mcaplog\u001b[49m\u001b[38;5;241m.\u001b[39mrecords)\n\u001b[1;32m 17\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(caplog\u001b[38;5;241m.\u001b[39mrecords) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m2\u001b[39m \u001b[38;5;66;03m# Two log messages should be captured\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m caplog\u001b[38;5;241m.\u001b[39mrecords[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mlevelname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mERROR\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[0;31mNameError\u001b[0m: name 'caplog' is not defined" + ] + } + ], + "source": [ + "import pytest # Replace 'your_module' with the actual module containing your function\n", + "from viadot.tasks import VidClubToDF\n", + "from datetime import datetime, date, timedelta\n", + "cols_to_drop = [\"Test\", \"submissionDate\"]\n", + "VC = VidClubToDF(source = \"jobs\", to_date=\"2023-07-12\", from_date=\"2023-07-01\")\n", + "# Assuming you have a function named 'your_function' in 'your_module'\n", + "# def test_your_function_with_keyerror(caplog):\n", + " # Your test data and setup here\n", + " # ...\n", + "\n", + " # Call your function that might raise KeyError\n", + "# with pytest.raises(KeyError):\n", + "VC.run(cols_to_drop = cols_to_drop) # Call your function with appropriate arguments\n", + "\n", + "# Verify the loggers\n", + "print(caplog.records)\n", + "assert len(caplog.records) == 2 # Two log messages should be captured\n", + "assert caplog.records[0].levelname == \"ERROR\"\n", + "assert \"Column(s): {cols_to_drop} don't exist in the DataFrame\" in caplog.records[0].message\n", + "assert caplog.records[1].levelname == \"INFO\"\n", + "assert \"Existing columns:\" in caplog.records[1].message\n", + "\n", + " # You can add more specific checks on the content of the log messages if needed\n", + " # For example, you can check if the correct column names are logged in the messages.\n", + "\n", + " # Optional: Clear the log for the next test (if any)\n", + " # caplog.clear()" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "91514d5a-1eba-491b-80d5-efb03fb1abe4", + "metadata": {}, + "outputs": [], + "source": [ + "# my_module.py\n", + "\n", + "from prefect.utilities import logging\n", + "\n", + "logger = logging.get_logger(__name__)\n", + "\n", + "def my_function(a):\n", + "\n", + " try:\n", + " a-2\n", + " logger.info(f\"Dropping following columns: {cols_to_drop}...\")\n", + "\n", + " except TypeError as ke:\n", + " logger.error(\n", + " f\"Column(s): {a} don't exist in the DataFrame. No columns were dropped. Returning full DataFrame...\"\n", + " )\n", + " logger.info(f\"Existing columns: {a}\")\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "# test_my_module.py\n", + "\n", + "import pytest\n", + "# from viadot.tasks import VidClubToDF\n", + "\n", + "def test_my_function_with_keyerror(caplog):\n", + " # Call your function that might raise KeyError\n", + " with pytest.raises(KeyError):\n", + " my_function()\n", + "\n", + " # Verify the loggers\n", + " print(len(caplog.records))\n", + " assert len(caplog.records) == 2\n", + " assert caplog.records[0].levelname == \"ERROR\"\n", + " assert \"An error occurred: Some KeyError message\" in caplog.records[0].message\n", + " assert caplog.records[1].levelname == \"INFO\"\n", + " assert \"Additional info about the error\" in caplog.records[1].message\n", + "\n", + " # Optional: Clear the log for the next test (if any)\n", + " caplog.clear()" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "f773a59b-c195-4b5b-b769-a4f31fafccd3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m============================= test session starts ==============================\u001b[0m\n", + "platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0\n", + "rootdir: /home/viadot, configfile: pyproject.toml\n", + "plugins: cov-3.0.0, anyio-3.7.0\n", + "collecting 0 items \u001b[0m\u001b[1m[2023-07-25 14:45:20+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "\n", + "\u001b[1m----------------------------- live log collection ------------------------------\u001b[0m\n", + "2023-07-25 14:45:20 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "[2023-07-25 14:45:20+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:20 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "Flow URL: https://cloud.prefect.io/dyvenia/flow/0888201f-6acb-4bc0-8897-f8ea170e9f21\n", + " └── ID: 0d183787-bcc3-4754-b813-60b60ed81613\n", + " └── Project: Marketing KPI\n", + " └── Labels: ['prod']\n", + "collecting 0 items \u001b[0m[2023-07-25 14:45:22+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:22 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "[2023-07-25 14:45:22+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:22 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "Flow URL: https://cloud.prefect.io/dyvenia/flow/13b9ec80-7536-484a-b1a5-497d90c4f981\n", + " └── ID: b50fca66-10b6-457b-8202-553ce0736c00\n", + " └── Project: dev\n", + " └── Labels: ['prod']\n", + "collecting 0 items \u001b[0m[2023-07-25 14:45:24+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:24 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "[2023-07-25 14:45:25+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:25 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "Flow URL: https://cloud.prefect.io/dyvenia/flow/4d5d69e5-c9cf-446a-b6a5-a740b2a6e608\n", + " └── ID: 2bda058d-512d-40ba-8fa6-d6405fa1f6f9\n", + " └── Project: dev\n", + " └── Labels: ['prod']\n", + "collecting 0 items \u001b[0m[2023-07-25 14:45:26+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:26 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "[2023-07-25 14:45:27+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "2023-07-25 14:45:27 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", + "^C\n" + ] + } + ], + "source": [ + "!pytest -s" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ef84d02a-7582-4fd5-8106-3b6efa9cb758", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "set(list(output_with_all.columns)) - set(list(output_with_dropped.columns)) == set(cols_to_drop)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d70a3efa-d2da-435f-978d-ad25a66261fe", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2023-07-24 16:36:51+0000] INFO - prefect.adls_to_df | Downloading data from azuwevelcedls01p/raw/test/test.parquet to a DataFrame...\n", + "[2023-07-24 16:36:54+0000] INFO - prefect.adls_to_df | Successfully loaded data.\n" + ] + } + ], + "source": [ + "df = AzureDataLakeToDF().run(path='raw/test/test.parquet', sp_credentials_secret = \"App-Azure-CR-DatalakeGen2-AIA\")" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "e4f25a24-5c50-49aa-9715-c564029198f4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "datetime.datetime(2021, 5, 9, 0, 0)" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from datetime import datetime, date, timedelta\n", + "from_date=\"2021-05-09\"\n", + "datetime.strptime(from_date, \"%Y-%m-%d\")" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "48c1f745-9c4e-4d7f-b8c4-921a0c6bfee6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from_date > \"2020-05-05\"" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "57d8e3ac-e9ea-4513-b162-37c3602dfcfe", + "metadata": {}, + "outputs": [ + { + "ename": "ValidationError", + "evalue": "to_date cannot be earlier than from_date.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mvc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_response\u001b[49m\u001b[43m(\u001b[49m\u001b[43msource\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mjobs\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfrom_date\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m2022-05-09\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mto_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m2022-05-05\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/viadot/sources/vid_club.py:213\u001b[0m, in \u001b[0;36mVidClub.get_response\u001b[0;34m(self, source, from_date, to_date, items_per_page, region)\u001b[0m\n\u001b[1;32m 210\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfrom_date cannot be earlier than 2022-03-22.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 212\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_date \u001b[38;5;241m<\u001b[39m from_date:\n\u001b[0;32m--> 213\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mto_date cannot be earlier than from_date.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 215\u001b[0m response, first_url \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcheck_connection(\n\u001b[1;32m 216\u001b[0m source\u001b[38;5;241m=\u001b[39msource,\n\u001b[1;32m 217\u001b[0m from_date\u001b[38;5;241m=\u001b[39mfrom_date,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 220\u001b[0m region\u001b[38;5;241m=\u001b[39mregion,\n\u001b[1;32m 221\u001b[0m )\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(response, \u001b[38;5;28mdict\u001b[39m):\n", + "\u001b[0;31mValidationError\u001b[0m: to_date cannot be earlier than from_date." + ] + } + ], + "source": [ + "vc.get_response(source=\"jobs\", from_date=\"2022-05-09\", to_date = \"2022-05-05\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "bdc58560-41cd-4407-8e30-3c53b7fb4a1e", + "metadata": {}, + "outputs": [], + "source": [ + "dups_mask = df.duplicated()\n", + "df_check = df[dups_mask]" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "e6484860-ab60-4b46-9b6c-20756615e1f7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
col1col2col3
22bb99
\n", + "
" + ], + "text/plain": [ + " col1 col2 col3\n", + "2 2 bb 99" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_check" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From e2e210d7d74a3dabfd2c6ec1b6c31de16b104f58 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Tue, 25 Jul 2023 17:07:25 +0200 Subject: [PATCH 092/106] Revert "removed space" This reverts commit d9302ffc4befb38beb0bce8a3e17d0da635d0ac7. --- .vscode/settings.json | 7 +- data_flows | 1 - test.json | 1 - test.parquet | Bin 445166 -> 0 bytes tests/integration/test_vid_club.py | 1 + viadot/flows/__init__.py | 1 - viadot/flows/vid_club_to_adls.py | 164 - vid_club_tests.ipynb | 7149 ---------------------------- 8 files changed, 3 insertions(+), 7321 deletions(-) delete mode 160000 data_flows delete mode 100644 test.json delete mode 100644 test.parquet delete mode 100644 viadot/flows/vid_club_to_adls.py delete mode 100644 vid_club_tests.ipynb diff --git a/.vscode/settings.json b/.vscode/settings.json index 95454c294..8fd5218a8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "autoDocstring.docstringFormat": "google", - "python.formatting.provider": "none", + "python.formatting.provider": "black", "python.formatting.blackArgs": [ "--line-length", "88" @@ -48,8 +48,5 @@ "work", "zfill" ], - "git.autofetch": true, - "[python]": { - "editor.defaultFormatter": "ms-python.black-formatter" - } + "git.autofetch": true } \ No newline at end of file diff --git a/data_flows b/data_flows deleted file mode 160000 index 3469019c8..000000000 --- a/data_flows +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3469019c8c5a2b8bedb4cdff6973417aa1a8eeed diff --git a/test.json b/test.json deleted file mode 100644 index ce19911f7..000000000 --- a/test.json +++ /dev/null @@ -1 +0,0 @@ -{"submissionID": "Integer", "submissionAddress": "String", "regionID": "String", "submissionPostcode": "String", "submissionDate": "String", "customerID": "String", "status": "String", "submissionQuantity": "Integer", "points": "Integer", "q1Core": "String", "q2Core": "String", "q2CoreOther": "String", "q3Core": "String", "q4Core": "String", "q5Core": "Integer", "q5CoreOther": "Integer", "q6Core": "Integer", "q6CoreOther": "Integer", "q7Core": "Integer", "q7CoreOther": "Integer", "q8Core": "Integer", "q8CoreOther": "Integer", "q9Core": "Integer", "_viadot_downloaded_at_utc": "DateTime"} \ No newline at end of file diff --git a/test.parquet b/test.parquet deleted file mode 100644 index 2832fc41e96b36e54583cbe055f81c15d6c56126..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 445166 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 z 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%0DCDnvx8Hg=D_1xung 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

j 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

xjNy^g49qP)o%RJSCwI5{$4vt{Pd-@)nkh2 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 Koo Flow: - vid_club_df_task = VidClubToDF( - timeout=self.timeout, - source=self.source, - credentials=self.vid_club_credentials, - credentials_secret=self.vidclub_credentials_secret, - vault_name=self.vidclub_vault_name, - ) - - vid_club_df = vid_club_df_task.bind( - from_date=self.from_date, - to_date=self.to_date, - items_per_page=self.items_per_page, - region=self.region, - days_interval=self.days_interval, - flow=self, - ) - - df_with_metadata = add_ingestion_metadata_task.bind(df, flow=self) - - dtypes_dict = df_get_data_types_task.bind(df_with_metadata, flow=self) - df_mapped = df_map_mixed_dtypes_for_parquet.bind( - df_with_metadata, dtypes_dict, flow=self - ) - - if self.output_file_extension == ".parquet": - df_to_file = df_to_parquet.bind( - df=df_mapped, - path=self.local_file_path, - if_exists=self.if_exists, - flow=self, - ) - else: - df_to_file = df_to_csv.bind( - df=df_with_metadata, - path=self.local_file_path, - if_exists=self.if_exists, - flow=self, - ) - - file_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) - file_to_adls_task.bind( - from_path=self.local_file_path, - to_path=self.adls_file_path, - overwrite=self.overwrite, - sp_credentials_secret=self.adls_sp_credentials_secret, - flow=self, - ) - - dtypes_updated = update_dtypes_dict(dtypes_dict, flow=self) - dtypes_to_json_task.bind( - dtypes_dict=dtypes_updated, local_json_path=self.local_json_path, flow=self - ) - json_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) - json_to_adls_task.bind( - from_path=self.local_json_path, - to_path=self.adls_schema_file_dir_file, - overwrite=self.overwrite, - sp_credentials_secret=self.adls_sp_credentials_secret, - flow=self, - ) - - file_to_adls_task.set_upstream(df_to_file, flow=self) - json_to_adls_task.set_upstream(dtypes_to_json_task, flow=self) - set_key_value(key=self.adls_dir_path, value=self.adls_file_path) diff --git a/vid_club_tests.ipynb b/vid_club_tests.ipynb deleted file mode 100644 index 37bb32d5c..000000000 --- a/vid_club_tests.ipynb +++ /dev/null @@ -1,7149 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 2, - "id": "d2cbca7f-1c9a-4a38-9e16-c580b4def675", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " dev\u001b[m\n", - " dev_add_url_customer_gauge\u001b[m\n", - "* \u001b[32mdev_vidclub_update\u001b[m\n", - " main\u001b[m\n", - " orion\u001b[m\n" - ] - } - ], - "source": [ - "!git branch" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "3ea17add-8682-4ee5-b72f-36f2acddd3db", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 08:10:46+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - } - ], - "source": [ - "from viadot.task_utils import credentials_loader\n", - "from viadot.sources import VidClub\n", - "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", - "\n", - "# def test_default_credential_param():\n", - "vc = VidClub(credentials = CREDENTIALS)\n", - "assert vc.credentials != None and type(vc.credentials) == dict" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "a1649601-4e08-4191-bded-0ca848d486ff", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 13:03:25+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - } - ], - "source": [ - "import time\n", - "from viadot.task_utils import credentials_loader\n", - "from viadot.sources import VidClub\n", - "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "06ecea54-eb6b-4a53-afd7-f5f602fe234f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'url': 'https://api.club.velux.com/api/v1/datalake/',\n", - " 'token': 'Oit6TLXA8Gxcf9cOSnH6YvHqtNELDae1CWedodSMJtgu03hKteSSGcbLS0GqnhLT'}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "CREDENTIALS" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "b67de55a-ada8-424f-a956-3ae96f0b5a63", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 13:03:50+0000] INFO - prefect | ingesting data for dates [2022-06-01]-[2022-06-01]...\n" - ] - } - ], - "source": [ - "from_date = \"2022-06-01\"\n", - "to_date = \"2022-06-01\"\n", - "days_interval = 10\n", - "source = \"jobs\"\n", - "df = vc.total_load(from_date=from_date, to_date=to_date, days_interval = days_interval, source=source)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "70329e10-ffe9-40e4-8f11-dbdcb5315e1a", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "

\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
submissionIDsubmissionAddressregionIDsubmissionPostcodesubmissionDatecustomerIDstatussubmissionQuantitypointsq1Core...q4Coreq5Coreq5CoreOtherq6Coreq6CoreOtherq7Coreq7CoreOtherq8Coreq8CoreOtherq9Core
01071ŻurawiaPolandNone06/02/2022 20:45tYYcTKIfszynwmf4Closed420True...Concrete/ceramic tiles101010000
11070Juliana OpaniPolandNone06/02/2022 20:37pwg7XoKFF5FMfLZFClosed1390Part of new build house...Concrete/ceramic tiles100001010
21067Strada EgalităţiiRomaniaNone06/03/2022 07:54fd4ppEcGKm1HSYq7Closed664Part of new build house...Concrete/ceramic tiles000001010
31066SienkiewiczaPolandNone06/03/2022 16:18Yaddrbn2IY2ccDPpClosed945Part of new build house...Concrete/ceramic tiles110010000
41065ChrobregoPolandNone06/02/2022 13:56H3BjABhm0dl0jJh1Closed770Part of new build house...Concrete/ceramic tiles100011000
51064JankowickaPolandNone06/21/2022 13:04H3BjABhm0dl0jJh1Closed440Part of new build house...Concrete/ceramic tiles100110000
61063RembielińskaPolandNone06/02/2022 13:28H3BjABhm0dl0jJh1Closed15Part of new build house...Concrete/ceramic tiles100010000
71062RembielińskaPolandNone06/02/2022 13:26H3BjABhm0dl0jJh1Closed15Part of new build house...Concrete/ceramic tiles100000000
81061MałopolskaPolandNone06/10/2022 10:19JQTpXoVija32uEzBClosed420Part of new build house...Concrete/ceramic tiles000000001
91060SendlerowejPolandNone07/20/2022 10:54MxGqVCykMPUCZey3Closed210Part of new build house...Concrete/ceramic tiles000001000
101059Strada JiuluiRomaniaNone06/02/2022 12:44y78f0kWqfaIB5F6gClosed17Part of new build house...Concrete/ceramic tiles100000000
111058PięknaPolandNoneNot started yetDzHdosS0tf1zsYu8In progress00True...True000000000
121057PływackaPolandNone06/02/2022 10:26tYYcTKIfszynwmf4Closed210Part of new build house...Concrete/ceramic tiles100000000
131056PływackaPolandNone06/02/2022 10:20tYYcTKIfszynwmf4Closed210Part of new build house...Concrete/ceramic tiles000001000
141055LechówPolandNoneNot started yetAYpEmrYTeaSRZyiSIn progress00True...True000000000
151054Generała Edmunda TaczanowskiegoPolandNone06/02/2022 14:34ymIzPDdYXqECNNrQClosed770Part of new build house...Concrete/ceramic tiles100001000
161053Calea DomneascăRomaniaNone06/02/2022 08:40grEokZxpPfoH2gdrClosed17Part of new build house...Concrete/ceramic tiles100000000
171052OsinieckaPolandNone06/02/2022 08:35rDGLcq4Og2elwesBClosed15Part of new build house...Concrete/ceramic tiles000000010
181051Zofii KossakPolandNone10/11/2022 09:259ab5ekacidsz0IRxClosed15Part of new build house...Concrete/ceramic tiles001000000
191050Strada Anghel I. SalignyRomaniaNone06/02/2022 08:102MS738MaZ8ytUtwuClosed214Part of new build house...Concrete/ceramic tiles100000000
201049JodłowaPolandNone06/02/2022 13:16H3BjABhm0dl0jJh1Closed840Part of new build house...Concrete/ceramic tiles100011000
211048LotniczaPolandNone06/03/2022 08:41xczTna3SQKI4D6CNClosed420Part of new build house...Concrete/ceramic tiles100110000
221047CzereśniowaPolandNone06/02/2022 06:32FUugbtnE8kEVeabDClosed210True...Concrete/ceramic tiles000010000
231046LechitówPolandNone06/07/2022 19:29RBo3MHMT4Ix6vvPTClosed19140Part of new build house...Concrete/ceramic tiles000011001
241045LechitówPolandNone06/05/2022 13:06RBo3MHMT4Ix6vvPTClosed10100Part of new build house...Concrete/ceramic tiles000010001
251044GrzybowaPolandNone06/01/2022 19:0314ksdmnGL0FzkSvOClosed630Part of new build house...Concrete/ceramic tiles111011010
261042GrzybiarzyPolandNone06/01/2022 17:07sPvG8pNLClGkjABwClosed7110Part of new build house...Concrete/ceramic tiles100011110
271041Aleea VerdeRomaniaNone06/01/2022 16:54Yq1MoCoSyEpqvqEpClosed434Part of new build house...Concrete/ceramic tiles110000000
281040Nad SpławkąPolandNone06/01/2022 16:21iXgEj1jstJtWOofoClosed430True...Concrete/ceramic tiles110010000
291039Str. MăguraRomaniaNone06/02/2022 07:03VaQrq1nDkYqVlqOAClosed1087Part of new build house...Concrete/ceramic tiles100010000
301038RetkińskaPolandNone06/01/2022 14:44ymIzPDdYXqECNNrQClosed770Part of new build house...Concrete/ceramic tiles100011000
311036RetorykaPolandNone10/12/2022 09:21ymIzPDdYXqECNNrQClosed240Part of new build house...Concrete/ceramic tiles100000000
321034Strada Avram IancuRomaniaNone06/01/2022 13:25BtxqL3tDbcvKX8EsClosed428Part of new build house...Concrete/ceramic tiles000000001
331033PiaskiPolandNone06/01/2022 12:46JAK9G1O4vXpaAFuvClosed420Part of new build house...Concrete/ceramic tiles100010000
341032KwiatowaPolandNoneNot started yetJAK9G1O4vXpaAFuvIn progress00True...True000000000
351031GórnaPolandNone06/01/2022 12:39pwg7XoKFF5FMfLZFClosed210Part of new build house...Concrete/ceramic tiles100010000
361030Bulevardul VictorieiRomaniaNone06/05/2022 16:09PRhfCDdZSpBQ6tdPClosed15Part of new build house...Concrete/ceramic tiles000000010
371029TrudnaPolandNone06/01/2022 12:16Yaddrbn2IY2ccDPpClosed15Part of new build house...Concrete/ceramic tiles000100000
381026ŻonkilowaPolandNone06/01/2022 11:12UzgRnEeTpJRojd2wClosed15Part of new build house...Concrete/ceramic tiles000010000
391024CegielnianaPolandNone06/09/2022 04:21Lzy0ra2ramJqUYGyClosed315Part of new build house...Concrete/ceramic tiles000001000
401022LubelskaPolandNone06/01/2022 09:21s10GO5LdAKLlkWxHClosed210Part of new build house...Concrete/ceramic tiles001100000
411020ParkowaPolandNone06/08/2022 12:16m4Gq60TvlLF85KGHClosed115Part of new build house...Concrete/ceramic tiles000010000
421018DziałkowaPolandNone09/22/2022 07:48nuaUHDy7rbKJta8gLost00True...True000000000
431017MałaPolandNone07/05/2022 09:50xExXWy0kskxQg3gBClosed210Part of new build house...Concrete/ceramic tiles000011000
441016MałaPolandNone07/05/2022 09:53xExXWy0kskxQg3gBClosed210Part of new build house...Concrete/ceramic tiles110000000
451015MałaPolandNone07/05/2022 09:57xExXWy0kskxQg3gBClosed15Part of new build house...Concrete/ceramic tiles100000000
461013SzafirowaPolandNone06/01/2022 08:38QPE1v6DtFgXvo1VnClosed840Part of new build house...Concrete/ceramic tiles100010000
471012Strada George EnescuRomaniaNone06/01/2022 10:438CAZhYrPJa3i9BWkClosed432Part of new build house...Concrete/ceramic tiles010000000
481011MałaPolandNoneNot started yetEeaOIdBkC2uxlmzJIn progress00True...True000000000
491010George Emil PaladeRomaniaNone10/28/2022 06:068CAZhYrPJa3i9BWkClosed17Part of new build house...Concrete/ceramic tiles010000000
501008Str. BotosRomaniaNone06/01/2022 07:48fAGWNcu46Z1wT06PClosed210Part of new build house...Concrete/ceramic tiles100010000
511007OlszankowaPolandNone06/01/2022 06:52qw4uw4uHwmk5WSi4Closed945Part of new build house...Concrete/ceramic tiles100000000
521006Ul. SzczygłówPolandNone06/01/2022 06:58NI1iorIXQce7Dxj5Closed210Part of new build house...Concrete/ceramic tiles100010000
531005KompasowaPolandNone06/01/2022 04:41jBliksyS9zZgGgRwClosed210Part of new build house...Concrete/ceramic tiles100000000
\n", - "

54 rows × 23 columns

\n", - "
" - ], - "text/plain": [ - " submissionID submissionAddress regionID submissionPostcode \\\n", - "0 1071 Żurawia Poland None \n", - "1 1070 Juliana Opani Poland None \n", - "2 1067 Strada Egalităţii Romania None \n", - "3 1066 Sienkiewicza Poland None \n", - "4 1065 Chrobrego Poland None \n", - "5 1064 Jankowicka Poland None \n", - "6 1063 Rembielińska Poland None \n", - "7 1062 Rembielińska Poland None \n", - "8 1061 Małopolska Poland None \n", - "9 1060 Sendlerowej Poland None \n", - "10 1059 Strada Jiului Romania None \n", - "11 1058 Piękna Poland None \n", - "12 1057 Pływacka Poland None \n", - "13 1056 Pływacka Poland None \n", - "14 1055 Lechów Poland None \n", - "15 1054 Generała Edmunda Taczanowskiego Poland None \n", - "16 1053 Calea Domnească Romania None \n", - "17 1052 Osiniecka Poland None \n", - "18 1051 Zofii Kossak Poland None \n", - "19 1050 Strada Anghel I. Saligny Romania None \n", - "20 1049 Jodłowa Poland None \n", - "21 1048 Lotnicza Poland None \n", - "22 1047 Czereśniowa Poland None \n", - "23 1046 Lechitów Poland None \n", - "24 1045 Lechitów Poland None \n", - "25 1044 Grzybowa Poland None \n", - "26 1042 Grzybiarzy Poland None \n", - "27 1041 Aleea Verde Romania None \n", - "28 1040 Nad Spławką Poland None \n", - "29 1039 Str. Măgura Romania None \n", - "30 1038 Retkińska Poland None \n", - "31 1036 Retoryka Poland None \n", - "32 1034 Strada Avram Iancu Romania None \n", - "33 1033 Piaski Poland None \n", - "34 1032 Kwiatowa Poland None \n", - "35 1031 Górna Poland None \n", - "36 1030 Bulevardul Victoriei Romania None \n", - "37 1029 Trudna Poland None \n", - "38 1026 Żonkilowa Poland None \n", - "39 1024 Cegielniana Poland None \n", - "40 1022 Lubelska Poland None \n", - "41 1020 Parkowa Poland None \n", - "42 1018 Działkowa Poland None \n", - "43 1017 Mała Poland None \n", - "44 1016 Mała Poland None \n", - "45 1015 Mała Poland None \n", - "46 1013 Szafirowa Poland None \n", - "47 1012 Strada George Enescu Romania None \n", - "48 1011 Mała Poland None \n", - "49 1010 George Emil Palade Romania None \n", - "50 1008 Str. Botos Romania None \n", - "51 1007 Olszankowa Poland None \n", - "52 1006 Ul. Szczygłów Poland None \n", - "53 1005 Kompasowa Poland None \n", - "\n", - " submissionDate customerID status submissionQuantity \\\n", - "0 06/02/2022 20:45 tYYcTKIfszynwmf4 Closed 4 \n", - "1 06/02/2022 20:37 pwg7XoKFF5FMfLZF Closed 13 \n", - "2 06/03/2022 07:54 fd4ppEcGKm1HSYq7 Closed 6 \n", - "3 06/03/2022 16:18 Yaddrbn2IY2ccDPp Closed 9 \n", - "4 06/02/2022 13:56 H3BjABhm0dl0jJh1 Closed 7 \n", - "5 06/21/2022 13:04 H3BjABhm0dl0jJh1 Closed 4 \n", - "6 06/02/2022 13:28 H3BjABhm0dl0jJh1 Closed 1 \n", - "7 06/02/2022 13:26 H3BjABhm0dl0jJh1 Closed 1 \n", - "8 06/10/2022 10:19 JQTpXoVija32uEzB Closed 4 \n", - "9 07/20/2022 10:54 MxGqVCykMPUCZey3 Closed 2 \n", - "10 06/02/2022 12:44 y78f0kWqfaIB5F6g Closed 1 \n", - "11 Not started yet DzHdosS0tf1zsYu8 In progress 0 \n", - "12 06/02/2022 10:26 tYYcTKIfszynwmf4 Closed 2 \n", - "13 06/02/2022 10:20 tYYcTKIfszynwmf4 Closed 2 \n", - "14 Not started yet AYpEmrYTeaSRZyiS In progress 0 \n", - "15 06/02/2022 14:34 ymIzPDdYXqECNNrQ Closed 7 \n", - "16 06/02/2022 08:40 grEokZxpPfoH2gdr Closed 1 \n", - "17 06/02/2022 08:35 rDGLcq4Og2elwesB Closed 1 \n", - "18 10/11/2022 09:25 9ab5ekacidsz0IRx Closed 1 \n", - "19 06/02/2022 08:10 2MS738MaZ8ytUtwu Closed 2 \n", - "20 06/02/2022 13:16 H3BjABhm0dl0jJh1 Closed 8 \n", - "21 06/03/2022 08:41 xczTna3SQKI4D6CN Closed 4 \n", - "22 06/02/2022 06:32 FUugbtnE8kEVeabD Closed 2 \n", - "23 06/07/2022 19:29 RBo3MHMT4Ix6vvPT Closed 19 \n", - "24 06/05/2022 13:06 RBo3MHMT4Ix6vvPT Closed 10 \n", - "25 06/01/2022 19:03 14ksdmnGL0FzkSvO Closed 6 \n", - "26 06/01/2022 17:07 sPvG8pNLClGkjABw Closed 7 \n", - "27 06/01/2022 16:54 Yq1MoCoSyEpqvqEp Closed 4 \n", - "28 06/01/2022 16:21 iXgEj1jstJtWOofo Closed 4 \n", - "29 06/02/2022 07:03 VaQrq1nDkYqVlqOA Closed 10 \n", - "30 06/01/2022 14:44 ymIzPDdYXqECNNrQ Closed 7 \n", - "31 10/12/2022 09:21 ymIzPDdYXqECNNrQ Closed 2 \n", - "32 06/01/2022 13:25 BtxqL3tDbcvKX8Es Closed 4 \n", - "33 06/01/2022 12:46 JAK9G1O4vXpaAFuv Closed 4 \n", - "34 Not started yet JAK9G1O4vXpaAFuv In progress 0 \n", - "35 06/01/2022 12:39 pwg7XoKFF5FMfLZF Closed 2 \n", - "36 06/05/2022 16:09 PRhfCDdZSpBQ6tdP Closed 1 \n", - "37 06/01/2022 12:16 Yaddrbn2IY2ccDPp Closed 1 \n", - "38 06/01/2022 11:12 UzgRnEeTpJRojd2w Closed 1 \n", - "39 06/09/2022 04:21 Lzy0ra2ramJqUYGy Closed 3 \n", - "40 06/01/2022 09:21 s10GO5LdAKLlkWxH Closed 2 \n", - "41 06/08/2022 12:16 m4Gq60TvlLF85KGH Closed 1 \n", - "42 09/22/2022 07:48 nuaUHDy7rbKJta8g Lost 0 \n", - "43 07/05/2022 09:50 xExXWy0kskxQg3gB Closed 2 \n", - "44 07/05/2022 09:53 xExXWy0kskxQg3gB Closed 2 \n", - "45 07/05/2022 09:57 xExXWy0kskxQg3gB Closed 1 \n", - "46 06/01/2022 08:38 QPE1v6DtFgXvo1Vn Closed 8 \n", - "47 06/01/2022 10:43 8CAZhYrPJa3i9BWk Closed 4 \n", - "48 Not started yet EeaOIdBkC2uxlmzJ In progress 0 \n", - "49 10/28/2022 06:06 8CAZhYrPJa3i9BWk Closed 1 \n", - "50 06/01/2022 07:48 fAGWNcu46Z1wT06P Closed 2 \n", - "51 06/01/2022 06:52 qw4uw4uHwmk5WSi4 Closed 9 \n", - "52 06/01/2022 06:58 NI1iorIXQce7Dxj5 Closed 2 \n", - "53 06/01/2022 04:41 jBliksyS9zZgGgRw Closed 2 \n", - "\n", - " points q1Core ... q4Core q5Core \\\n", - "0 20 True ... Concrete/ceramic tiles 1 \n", - "1 90 Part of new build house ... Concrete/ceramic tiles 1 \n", - "2 64 Part of new build house ... Concrete/ceramic tiles 0 \n", - "3 45 Part of new build house ... Concrete/ceramic tiles 1 \n", - "4 70 Part of new build house ... Concrete/ceramic tiles 1 \n", - "5 40 Part of new build house ... Concrete/ceramic tiles 1 \n", - "6 5 Part of new build house ... Concrete/ceramic tiles 1 \n", - "7 5 Part of new build house ... Concrete/ceramic tiles 1 \n", - "8 20 Part of new build house ... Concrete/ceramic tiles 0 \n", - "9 10 Part of new build house ... Concrete/ceramic tiles 0 \n", - "10 7 Part of new build house ... Concrete/ceramic tiles 1 \n", - "11 0 True ... True 0 \n", - "12 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "13 10 Part of new build house ... Concrete/ceramic tiles 0 \n", - "14 0 True ... True 0 \n", - "15 70 Part of new build house ... Concrete/ceramic tiles 1 \n", - "16 7 Part of new build house ... Concrete/ceramic tiles 1 \n", - "17 5 Part of new build house ... Concrete/ceramic tiles 0 \n", - "18 5 Part of new build house ... Concrete/ceramic tiles 0 \n", - "19 14 Part of new build house ... Concrete/ceramic tiles 1 \n", - "20 40 Part of new build house ... Concrete/ceramic tiles 1 \n", - "21 20 Part of new build house ... Concrete/ceramic tiles 1 \n", - "22 10 True ... Concrete/ceramic tiles 0 \n", - "23 140 Part of new build house ... Concrete/ceramic tiles 0 \n", - "24 100 Part of new build house ... Concrete/ceramic tiles 0 \n", - "25 30 Part of new build house ... Concrete/ceramic tiles 1 \n", - "26 110 Part of new build house ... Concrete/ceramic tiles 1 \n", - "27 34 Part of new build house ... Concrete/ceramic tiles 1 \n", - "28 30 True ... Concrete/ceramic tiles 1 \n", - "29 87 Part of new build house ... Concrete/ceramic tiles 1 \n", - "30 70 Part of new build house ... Concrete/ceramic tiles 1 \n", - "31 40 Part of new build house ... Concrete/ceramic tiles 1 \n", - "32 28 Part of new build house ... Concrete/ceramic tiles 0 \n", - "33 20 Part of new build house ... Concrete/ceramic tiles 1 \n", - "34 0 True ... True 0 \n", - "35 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "36 5 Part of new build house ... Concrete/ceramic tiles 0 \n", - "37 5 Part of new build house ... Concrete/ceramic tiles 0 \n", - "38 5 Part of new build house ... Concrete/ceramic tiles 0 \n", - "39 15 Part of new build house ... Concrete/ceramic tiles 0 \n", - "40 10 Part of new build house ... Concrete/ceramic tiles 0 \n", - "41 15 Part of new build house ... Concrete/ceramic tiles 0 \n", - "42 0 True ... True 0 \n", - "43 10 Part of new build house ... Concrete/ceramic tiles 0 \n", - "44 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "45 5 Part of new build house ... Concrete/ceramic tiles 1 \n", - "46 40 Part of new build house ... Concrete/ceramic tiles 1 \n", - "47 32 Part of new build house ... Concrete/ceramic tiles 0 \n", - "48 0 True ... True 0 \n", - "49 7 Part of new build house ... Concrete/ceramic tiles 0 \n", - "50 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "51 45 Part of new build house ... Concrete/ceramic tiles 1 \n", - "52 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "53 10 Part of new build house ... Concrete/ceramic tiles 1 \n", - "\n", - " q5CoreOther q6Core q6CoreOther q7Core q7CoreOther q8Core q8CoreOther \\\n", - "0 0 1 0 1 0 0 0 \n", - "1 0 0 0 0 1 0 1 \n", - "2 0 0 0 0 1 0 1 \n", - "3 1 0 0 1 0 0 0 \n", - "4 0 0 0 1 1 0 0 \n", - "5 0 0 1 1 0 0 0 \n", - "6 0 0 0 1 0 0 0 \n", - "7 0 0 0 0 0 0 0 \n", - "8 0 0 0 0 0 0 0 \n", - "9 0 0 0 0 1 0 0 \n", - "10 0 0 0 0 0 0 0 \n", - "11 0 0 0 0 0 0 0 \n", - "12 0 0 0 0 0 0 0 \n", - "13 0 0 0 0 1 0 0 \n", - "14 0 0 0 0 0 0 0 \n", - "15 0 0 0 0 1 0 0 \n", - "16 0 0 0 0 0 0 0 \n", - "17 0 0 0 0 0 0 1 \n", - "18 0 1 0 0 0 0 0 \n", - "19 0 0 0 0 0 0 0 \n", - "20 0 0 0 1 1 0 0 \n", - "21 0 0 1 1 0 0 0 \n", - "22 0 0 0 1 0 0 0 \n", - "23 0 0 0 1 1 0 0 \n", - "24 0 0 0 1 0 0 0 \n", - "25 1 1 0 1 1 0 1 \n", - "26 0 0 0 1 1 1 1 \n", - "27 1 0 0 0 0 0 0 \n", - "28 1 0 0 1 0 0 0 \n", - "29 0 0 0 1 0 0 0 \n", - "30 0 0 0 1 1 0 0 \n", - "31 0 0 0 0 0 0 0 \n", - "32 0 0 0 0 0 0 0 \n", - "33 0 0 0 1 0 0 0 \n", - "34 0 0 0 0 0 0 0 \n", - "35 0 0 0 1 0 0 0 \n", - "36 0 0 0 0 0 0 1 \n", - "37 0 0 1 0 0 0 0 \n", - "38 0 0 0 1 0 0 0 \n", - "39 0 0 0 0 1 0 0 \n", - "40 0 1 1 0 0 0 0 \n", - "41 0 0 0 1 0 0 0 \n", - "42 0 0 0 0 0 0 0 \n", - "43 0 0 0 1 1 0 0 \n", - "44 1 0 0 0 0 0 0 \n", - "45 0 0 0 0 0 0 0 \n", - "46 0 0 0 1 0 0 0 \n", - "47 1 0 0 0 0 0 0 \n", - "48 0 0 0 0 0 0 0 \n", - "49 1 0 0 0 0 0 0 \n", - "50 0 0 0 1 0 0 0 \n", - "51 0 0 0 0 0 0 0 \n", - "52 0 0 0 1 0 0 0 \n", - "53 0 0 0 0 0 0 0 \n", - "\n", - " q9Core \n", - "0 0 \n", - "1 0 \n", - "2 0 \n", - "3 0 \n", - "4 0 \n", - "5 0 \n", - "6 0 \n", - "7 0 \n", - "8 1 \n", - "9 0 \n", - "10 0 \n", - "11 0 \n", - "12 0 \n", - "13 0 \n", - "14 0 \n", - "15 0 \n", - "16 0 \n", - "17 0 \n", - "18 0 \n", - "19 0 \n", - "20 0 \n", - "21 0 \n", - "22 0 \n", - "23 1 \n", - "24 1 \n", - "25 0 \n", - "26 0 \n", - "27 0 \n", - "28 0 \n", - "29 0 \n", - "30 0 \n", - "31 0 \n", - "32 1 \n", - "33 0 \n", - "34 0 \n", - "35 0 \n", - "36 0 \n", - "37 0 \n", - "38 0 \n", - "39 0 \n", - "40 0 \n", - "41 0 \n", - "42 0 \n", - "43 0 \n", - "44 0 \n", - "45 0 \n", - "46 0 \n", - "47 0 \n", - "48 0 \n", - "49 0 \n", - "50 0 \n", - "51 0 \n", - "52 0 \n", - "53 0 \n", - "\n", - "[54 rows x 23 columns]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "6aa9bf8c-f225-4038-bc49-b7a921f246ca", - "metadata": {}, - "outputs": [], - "source": [ - "vc = VidClub(credentials = CREDENTIALS)\n", - "a, b = vc.check_connection(from_date = \"2022-05-01\", to_date=\"2022-06-01\", source = \"jobs\")" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "f4ef3287-c005-49d9-aa38-dc89ff117880", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'current_page': 1,\n", - " 'data': [{'submissionID': 1071,\n", - " 'submissionAddress': 'Żurawia',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 20:45',\n", - " 'customerID': 'tYYcTKIfszynwmf4',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1070,\n", - " 'submissionAddress': 'Juliana Opani',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 20:37',\n", - " 'customerID': 'pwg7XoKFF5FMfLZF',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 13,\n", - " 'points': 90,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1067,\n", - " 'submissionAddress': 'Strada Egalităţii',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 07:54',\n", - " 'customerID': 'fd4ppEcGKm1HSYq7',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 6,\n", - " 'points': 64,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1066,\n", - " 'submissionAddress': 'Sienkiewicza',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 16:18',\n", - " 'customerID': 'Yaddrbn2IY2ccDPp',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 9,\n", - " 'points': 45,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1065,\n", - " 'submissionAddress': 'Chrobrego',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 13:56',\n", - " 'customerID': 'H3BjABhm0dl0jJh1',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 7,\n", - " 'points': 70,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1064,\n", - " 'submissionAddress': 'Jankowicka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/21/2022 13:04',\n", - " 'customerID': 'H3BjABhm0dl0jJh1',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 40,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1063,\n", - " 'submissionAddress': 'Rembielińska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 13:28',\n", - " 'customerID': 'H3BjABhm0dl0jJh1',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1062,\n", - " 'submissionAddress': 'Rembielińska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 13:26',\n", - " 'customerID': 'H3BjABhm0dl0jJh1',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1061,\n", - " 'submissionAddress': 'Małopolska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/10/2022 10:19',\n", - " 'customerID': 'JQTpXoVija32uEzB',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 1060,\n", - " 'submissionAddress': 'Sendlerowej',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/20/2022 10:54',\n", - " 'customerID': 'MxGqVCykMPUCZey3',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1059,\n", - " 'submissionAddress': 'Strada Jiului',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 12:44',\n", - " 'customerID': 'y78f0kWqfaIB5F6g',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 7,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1058,\n", - " 'submissionAddress': 'Piękna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'DzHdosS0tf1zsYu8',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1057,\n", - " 'submissionAddress': 'Pływacka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 10:26',\n", - " 'customerID': 'tYYcTKIfszynwmf4',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1056,\n", - " 'submissionAddress': 'Pływacka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 10:20',\n", - " 'customerID': 'tYYcTKIfszynwmf4',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1055,\n", - " 'submissionAddress': 'Lechów',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'AYpEmrYTeaSRZyiS',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1054,\n", - " 'submissionAddress': 'Generała Edmunda Taczanowskiego',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 14:34',\n", - " 'customerID': 'ymIzPDdYXqECNNrQ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 7,\n", - " 'points': 70,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1053,\n", - " 'submissionAddress': 'Calea Domnească',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 08:40',\n", - " 'customerID': 'grEokZxpPfoH2gdr',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 7,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1052,\n", - " 'submissionAddress': 'Osiniecka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 08:35',\n", - " 'customerID': 'rDGLcq4Og2elwesB',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1051,\n", - " 'submissionAddress': 'Zofii Kossak',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/11/2022 09:25',\n", - " 'customerID': '9ab5ekacidsz0IRx',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1050,\n", - " 'submissionAddress': 'Strada Anghel I. Saligny',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 08:10',\n", - " 'customerID': '2MS738MaZ8ytUtwu',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 14,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1049,\n", - " 'submissionAddress': 'Jodłowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 13:16',\n", - " 'customerID': 'H3BjABhm0dl0jJh1',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 8,\n", - " 'points': 40,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1048,\n", - " 'submissionAddress': 'Lotnicza',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 08:41',\n", - " 'customerID': 'xczTna3SQKI4D6CN',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1047,\n", - " 'submissionAddress': 'Czereśniowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 06:32',\n", - " 'customerID': 'FUugbtnE8kEVeabD',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1046,\n", - " 'submissionAddress': 'Lechitów',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/07/2022 19:29',\n", - " 'customerID': 'RBo3MHMT4Ix6vvPT',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 19,\n", - " 'points': 140,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 1045,\n", - " 'submissionAddress': 'Lechitów',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/05/2022 13:06',\n", - " 'customerID': 'RBo3MHMT4Ix6vvPT',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 10,\n", - " 'points': 100,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 1044,\n", - " 'submissionAddress': 'Grzybowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 19:03',\n", - " 'customerID': '14ksdmnGL0FzkSvO',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 6,\n", - " 'points': 30,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1042,\n", - " 'submissionAddress': 'Grzybiarzy',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 17:07',\n", - " 'customerID': 'sPvG8pNLClGkjABw',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 7,\n", - " 'points': 110,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1041,\n", - " 'submissionAddress': 'Aleea Verde',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 16:54',\n", - " 'customerID': 'Yq1MoCoSyEpqvqEp',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 34,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1040,\n", - " 'submissionAddress': 'Nad Spławką',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 16:21',\n", - " 'customerID': 'iXgEj1jstJtWOofo',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 30,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1039,\n", - " 'submissionAddress': 'Str. Măgura',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 07:03',\n", - " 'customerID': 'VaQrq1nDkYqVlqOA',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 10,\n", - " 'points': 87,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1038,\n", - " 'submissionAddress': 'Retkińska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 14:44',\n", - " 'customerID': 'ymIzPDdYXqECNNrQ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 7,\n", - " 'points': 70,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1036,\n", - " 'submissionAddress': 'Retoryka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/12/2022 09:21',\n", - " 'customerID': 'ymIzPDdYXqECNNrQ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 40,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1034,\n", - " 'submissionAddress': 'Strada Avram Iancu',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 13:25',\n", - " 'customerID': 'BtxqL3tDbcvKX8Es',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 28,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 1033,\n", - " 'submissionAddress': 'Piaski',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 12:46',\n", - " 'customerID': 'JAK9G1O4vXpaAFuv',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1032,\n", - " 'submissionAddress': 'Kwiatowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'JAK9G1O4vXpaAFuv',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1031,\n", - " 'submissionAddress': 'Górna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 12:39',\n", - " 'customerID': 'pwg7XoKFF5FMfLZF',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1030,\n", - " 'submissionAddress': 'Bulevardul Victoriei',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/05/2022 16:09',\n", - " 'customerID': 'PRhfCDdZSpBQ6tdP',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1029,\n", - " 'submissionAddress': 'Trudna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 12:16',\n", - " 'customerID': 'Yaddrbn2IY2ccDPp',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1026,\n", - " 'submissionAddress': 'Żonkilowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 11:12',\n", - " 'customerID': 'UzgRnEeTpJRojd2w',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1024,\n", - " 'submissionAddress': 'Cegielniana',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/09/2022 04:21',\n", - " 'customerID': 'Lzy0ra2ramJqUYGy',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 3,\n", - " 'points': 15,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1022,\n", - " 'submissionAddress': 'Lubelska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 09:21',\n", - " 'customerID': 's10GO5LdAKLlkWxH',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1020,\n", - " 'submissionAddress': 'Parkowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/08/2022 12:16',\n", - " 'customerID': 'm4Gq60TvlLF85KGH',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 15,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1018,\n", - " 'submissionAddress': 'Działkowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '09/22/2022 07:48',\n", - " 'customerID': 'nuaUHDy7rbKJta8g',\n", - " 'status': 'Lost',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1017,\n", - " 'submissionAddress': 'Mała',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/05/2022 09:50',\n", - " 'customerID': 'xExXWy0kskxQg3gB',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1016,\n", - " 'submissionAddress': 'Mała',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/05/2022 09:53',\n", - " 'customerID': 'xExXWy0kskxQg3gB',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1015,\n", - " 'submissionAddress': 'Mała',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/05/2022 09:57',\n", - " 'customerID': 'xExXWy0kskxQg3gB',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1013,\n", - " 'submissionAddress': 'Szafirowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 08:38',\n", - " 'customerID': 'QPE1v6DtFgXvo1Vn',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 8,\n", - " 'points': 40,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1012,\n", - " 'submissionAddress': 'Strada George Enescu',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 10:43',\n", - " 'customerID': '8CAZhYrPJa3i9BWk',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 32,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1011,\n", - " 'submissionAddress': 'Mała',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'EeaOIdBkC2uxlmzJ',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1010,\n", - " 'submissionAddress': 'George Emil Palade',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/28/2022 06:06',\n", - " 'customerID': '8CAZhYrPJa3i9BWk',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 7,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1008,\n", - " 'submissionAddress': 'Str. Botos',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 07:48',\n", - " 'customerID': 'fAGWNcu46Z1wT06P',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1007,\n", - " 'submissionAddress': 'Olszankowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 06:52',\n", - " 'customerID': 'qw4uw4uHwmk5WSi4',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 9,\n", - " 'points': 45,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1006,\n", - " 'submissionAddress': 'Ul. Szczygłów',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 06:58',\n", - " 'customerID': 'NI1iorIXQce7Dxj5',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1005,\n", - " 'submissionAddress': 'Kompasowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 04:41',\n", - " 'customerID': 'jBliksyS9zZgGgRw',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1004,\n", - " 'submissionAddress': 'Nagietkowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 18:53',\n", - " 'customerID': 't95kphNuXAk3BzDu',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1001,\n", - " 'submissionAddress': 'Wolska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/20/2022 07:11',\n", - " 'customerID': 'VVJUVZsPrJ6m7CPH',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 24,\n", - " 'points': 310,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 1000,\n", - " 'submissionAddress': 'Strada Școlii',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 15:39',\n", - " 'customerID': '5TcALQxaZa4ALOaV',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 26,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 999,\n", - " 'submissionAddress': 'Karkonoska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 15:31',\n", - " 'customerID': 'm4Gq60TvlLF85KGH',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 5,\n", - " 'points': 75,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 998,\n", - " 'submissionAddress': 'Strada Erszenyek',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 12:34',\n", - " 'customerID': 'VaQrq1nDkYqVlqOA',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 24,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 997,\n", - " 'submissionAddress': 'Wiśniowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 12:24',\n", - " 'customerID': 'SxmD88RaahgrY4lU',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 3,\n", - " 'points': 15,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 996,\n", - " 'submissionAddress': 'Strada Tudor Vladimirescu',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 11:43',\n", - " 'customerID': 'h2qn885wUBK1aaQZ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 36,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 1},\n", - " {'submissionID': 995,\n", - " 'submissionAddress': 'Galati Bucuresti',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '08/02/2022 10:47',\n", - " 'customerID': 'h2qn885wUBK1aaQZ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 994,\n", - " 'submissionAddress': 'Słowackiego',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 11:23',\n", - " 'customerID': 'TLasOT27yxUHpdn5',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 993,\n", - " 'submissionAddress': 'Główna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 10:50',\n", - " 'customerID': 'onYNuls6zlB70qFp',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 992,\n", - " 'submissionAddress': 'Słowiańska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 10:48',\n", - " 'customerID': 'e1INJmUP6Jp0FTTD',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 991,\n", - " 'submissionAddress': 'Opolska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 11:44',\n", - " 'customerID': 's7dGH9KhTleXHxaJ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 990,\n", - " 'submissionAddress': 'Śliwkowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 't4osYrdhNX0UeH1d',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 989,\n", - " 'submissionAddress': 'Czarnieckiego',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/24/2022 05:06',\n", - " 'customerID': 'xfEPGc6H1pfJ1uqE',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 27,\n", - " 'points': 365,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 1,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 988,\n", - " 'submissionAddress': 'Kalwaryjska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 09:15',\n", - " 'customerID': 'uzUwcxoWQwAR8tYu',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 987,\n", - " 'submissionAddress': 'Michałowice',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 12:24',\n", - " 'customerID': 'blkrYoZhoangAoGi',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 9,\n", - " 'points': 225,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 986,\n", - " 'submissionAddress': '1 Maja',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 09:18',\n", - " 'customerID': 'p1PPyh7NyTI6ANu7',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 8,\n", - " 'points': 40,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 984,\n", - " 'submissionAddress': 'Mickiewicza',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 09:04',\n", - " 'customerID': '1ofjNaQMxXCVjZHn',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 983,\n", - " 'submissionAddress': 'Strada Nicolae Brana',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 08:20',\n", - " 'customerID': 'l4fhYiZNmtAqnvSO',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 6,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 982,\n", - " 'submissionAddress': 'Wantuły',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 07:46',\n", - " 'customerID': 'koEBCWlIvJK859TZ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 5,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 981,\n", - " 'submissionAddress': 'Str. Iancu Gonțea',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/01/2022 12:28',\n", - " 'customerID': '2MS738MaZ8ytUtwu',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 5,\n", - " 'points': 32,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 980,\n", - " 'submissionAddress': 'Mostowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 16:44',\n", - " 'customerID': 'm4Gq60TvlLF85KGH',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 45,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 979,\n", - " 'submissionAddress': 'Strada Vidra',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/02/2022 18:47',\n", - " 'customerID': 'rjvfQg0XGfKJh2YX',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 8,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 978,\n", - " 'submissionAddress': 'Str. Zada',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 13:42',\n", - " 'customerID': 'h2qn885wUBK1aaQZ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 5,\n", - " 'points': 31,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 977,\n", - " 'submissionAddress': 'Strada Sânmartin',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 12:30',\n", - " 'customerID': 'kKAnAdxa2nWDbnJt',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 8,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 1},\n", - " {'submissionID': 975,\n", - " 'submissionAddress': 'Piekary',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 11:01',\n", - " 'customerID': 'blkrYoZhoangAoGi',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 50,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 974,\n", - " 'submissionAddress': 'Wolności',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'X1mW0U6sMcJAQ6Vo',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 973,\n", - " 'submissionAddress': 'Jabłeczna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 10:17',\n", - " 'customerID': 'Zddpqa837WHCBjaE',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 10,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 972,\n", - " 'submissionAddress': 'Szmaragdowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 10:48',\n", - " 'customerID': 'LgkN2NOEimhpQVcn',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 13,\n", - " 'points': 105,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 971,\n", - " 'submissionAddress': 'Szmaragdowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/21/2022 07:51',\n", - " 'customerID': 'LgkN2NOEimhpQVcn',\n", - " 'status': 'Lost',\n", - " 'submissionQuantity': 2,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 970,\n", - " 'submissionAddress': 'Strada Morii',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 09:01',\n", - " 'customerID': '2MS738MaZ8ytUtwu',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 1,\n", - " 'points': 8,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 969,\n", - " 'submissionAddress': 'Szkolna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 11:36',\n", - " 'customerID': 'Crt4lekT4HnoQczX',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 31,\n", - " 'points': 305,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 1},\n", - " {'submissionID': 968,\n", - " 'submissionAddress': 'Szkolna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/12/2022 11:28',\n", - " 'customerID': 'Crt4lekT4HnoQczX',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 5,\n", - " 'points': 95,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 967,\n", - " 'submissionAddress': 'Szkolna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '10/03/2022 06:52',\n", - " 'customerID': 'Crt4lekT4HnoQczX',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 60,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 966,\n", - " 'submissionAddress': 'Okrzei',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'H2sdQEtAHZDCvZMt',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 965,\n", - " 'submissionAddress': 'Strada Avram Iancu',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/30/2022 08:20',\n", - " 'customerID': 'EUBmrscWDtzAFqdr',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 8,\n", - " 'points': 73,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 1,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 1,\n", - " 'q9Core': 0},\n", - " {'submissionID': 964,\n", - " 'submissionAddress': 'Woszczerowicza',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '06/03/2022 06:13',\n", - " 'customerID': 'HrxyZ0VAApk5XG2P',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 4,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 963,\n", - " 'submissionAddress': 'Główna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 07:06',\n", - " 'customerID': '4j03DDh801vSMZhJ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 6,\n", - " 'points': 90,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 1,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 962,\n", - " 'submissionAddress': 'Józefa Poniatowskiego',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': 'Not started yet',\n", - " 'customerID': 'h1df7MlQrCl6UWzF',\n", - " 'status': 'In progress',\n", - " 'submissionQuantity': 0,\n", - " 'points': 0,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': True,\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 961,\n", - " 'submissionAddress': 'Konwaliowa',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '07/07/2022 06:15',\n", - " 'customerID': 'pu5srX4R7jKC3PDZ',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 5,\n", - " 'points': 125,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 960,\n", - " 'submissionAddress': 'Lutycka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/29/2022 07:54',\n", - " 'customerID': 'sPvG8pNLClGkjABw',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 18,\n", - " 'points': 250,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 959,\n", - " 'submissionAddress': 'Lutycka',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/29/2022 07:26',\n", - " 'customerID': 'sPvG8pNLClGkjABw',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 10,\n", - " 'points': 100,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 958,\n", - " 'submissionAddress': 'Nadmorska',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/31/2022 08:36',\n", - " 'customerID': 'IeTrq05cYIn9UIAd',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 20,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': 'Family house, summer house',\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 957,\n", - " 'submissionAddress': 'Strada Satu Batrân',\n", - " 'regionID': 'Romania',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/28/2022 10:45',\n", - " 'customerID': 'kKAnAdxa2nWDbnJt',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 18,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 1,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 1,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 956,\n", - " 'submissionAddress': 'Planetarna',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/28/2022 10:18',\n", - " 'customerID': 'qiBGyBskoGlKx2vw',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 3,\n", - " 'points': 15,\n", - " 'q1Core': 'Part of new build house',\n", - " 'q2Core': True,\n", - " 'q2CoreOther': 'Refurbishment: Remodelling the rooms',\n", - " 'q3Core': True,\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 0,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 1,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0},\n", - " {'submissionID': 954,\n", - " 'submissionAddress': 'Osiedle Pomorskie',\n", - " 'regionID': 'Poland',\n", - " 'submissionPostcode': None,\n", - " 'submissionDate': '05/28/2022 11:32',\n", - " 'customerID': 'gM5O1pze2HjjsJU7',\n", - " 'status': 'Closed',\n", - " 'submissionQuantity': 2,\n", - " 'points': 15,\n", - " 'q1Core': True,\n", - " 'q2Core': True,\n", - " 'q2CoreOther': True,\n", - " 'q3Core': 'VELUX',\n", - " 'q4Core': 'Concrete/ceramic tiles',\n", - " 'q5Core': 1,\n", - " 'q5CoreOther': 0,\n", - " 'q6Core': 0,\n", - " 'q6CoreOther': 0,\n", - " 'q7Core': 0,\n", - " 'q7CoreOther': 0,\n", - " 'q8Core': 0,\n", - " 'q8CoreOther': 0,\n", - " 'q9Core': 0}],\n", - " 'first_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=1',\n", - " 'from': 1,\n", - " 'last_page': 7,\n", - " 'last_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=7',\n", - " 'links': [{'url': None, 'label': 'Previous', 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=1',\n", - " 'label': '1',\n", - " 'active': True},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", - " 'label': '2',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=3',\n", - " 'label': '3',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=4',\n", - " 'label': '4',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=5',\n", - " 'label': '5',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=6',\n", - " 'label': '6',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=7',\n", - " 'label': '7',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", - " 'label': 'Next',\n", - " 'active': False}],\n", - " 'next_page_url': 'http://api.club.velux.com/api/v1/datalake/jobs?page=2',\n", - " 'path': 'http://api.club.velux.com/api/v1/datalake/jobs',\n", - " 'per_page': 100,\n", - " 'prev_page_url': None,\n", - " 'to': 100,\n", - " 'total': 646}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "610e3e48-2882-46ac-ae2b-f186285e28fd", - "metadata": {}, - "outputs": [], - "source": [ - "source=\"jobs\"\n", - "from_date=\"2023-03-24\"\n", - "to_date=\"2023-03-24\"\n", - "api_url=\"https://api/test/\"\n", - "items_per_page=1" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "6f22cfa6-eb85-41f8-8baf-aa0b7ae995d1", - "metadata": {}, - "outputs": [], - "source": [ - "query = vc.build_query(\n", - " source=source,\n", - " from_date=from_date,\n", - " to_date=to_date,\n", - " api_url=api_url,\n", - " items_per_page=items_per_page,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a6696832-a7ab-42c6-a149-ce0f870399ba", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'https://api/test/jobs?from=2023-03-24&to=2023-03-24®ion=all&limit=1'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "query" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "5dd537d3-450d-430a-91be-11a35745b345", - "metadata": {}, - "outputs": [], - "source": [ - "expected = [f\"from={from_date}\", f\"to={to_date}\", \"region=all\", f\"limit={items_per_page}\", api_url]" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "8a611252-9259-4e48-b63d-1285c28e8d1d", - "metadata": {}, - "outputs": [], - "source": [ - "for ex in expected:\n", - " assert ex in query" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "52f53d45-0883-47fa-93e3-ca1853808f6d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "execution time for 20 is 212.32157516479492 seconds\n" - ] - } - ], - "source": [ - "# Record start time\n", - "start_time = time.time()\n", - "\n", - "vc = VidClub(credentials = CREDENTIALS)\n", - "\n", - "interval = 20\n", - "listaaa=vc.total_load(source = \"jobs\", days_interval = interval)\n", - "\n", - "end_time = time.time()\n", - "execution_time = end_time - start_time\n", - "print(f\"execution time for {interval} is {execution_time} seconds\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "92c8022b-c96f-4771-87c6-6845ca9c0ba3", - "metadata": {}, - "outputs": [], - "source": [ - "listaaa=vc.total_load(source = \"company\", to_date=\"2022-08-22\")" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "d3eebe7b-2abe-4068-bac4-537f2488568d", - "metadata": {}, - "outputs": [], - "source": [ - "from viadot.flows import VidClubToADLS, CustomerGaugeToADLS" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "9fe8843a-3c06-462a-b687-b08d5e14552f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 10:37:10+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'df' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m flow \u001b[38;5;241m=\u001b[39m \u001b[43mVidClubToADLS\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtest\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43msource\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msurvey\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_dir_path\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mraw/test\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_file_name\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mtest.parquet\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m \u001b[49m\u001b[43madls_sp_credentials_secret\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mApp-Azure-CR-DatalakeGen2-AIA\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 6\u001b[0m \u001b[43m \u001b[49m\u001b[43moverwrite_adls\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 7\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# schedule=schedule,\u001b[39;49;00m\n\u001b[1;32m 8\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# state_handlers=[slack_handler],\u001b[39;49;00m\n\u001b[1;32m 9\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# storage=STORAGE,\u001b[39;49;00m\n\u001b[1;32m 10\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;66;43;03m# run_config=RUN_CONFIG\u001b[39;49;00m\n\u001b[1;32m 11\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 12\u001b[0m flow\u001b[38;5;241m.\u001b[39mrun()\n", - "File \u001b[0;32m~/viadot/flows/vid_club_to_adls.py:94\u001b[0m, in \u001b[0;36mVidClubToADLS.__init__\u001b[0;34m(self, name, source, from_date, to_date, items_per_page, region, days_interval, vid_club_credentials, vidclub_credentials_secret, vidclub_vault_name, output_file_extension, adls_dir_path, local_file_path, adls_file_name, vault_name, adls_sp_credentials_secret, overwrite_adls, if_exists, timeout, *args, **kwargs)\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madls_schema_file_dir_file \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(\n\u001b[1;32m 89\u001b[0m adls_dir_path, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mschema\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnow \u001b[38;5;241m+\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.json\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 90\u001b[0m )\n\u001b[1;32m 92\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;241m*\u001b[39margs, name\u001b[38;5;241m=\u001b[39mname, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[0;32m---> 94\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgen_flow\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/viadot/flows/vid_club_to_adls.py:118\u001b[0m, in \u001b[0;36mVidClubToADLS.gen_flow\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 101\u001b[0m vid_club_df_task \u001b[38;5;241m=\u001b[39m VidClubToDF(\n\u001b[1;32m 102\u001b[0m timeout\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimeout,\n\u001b[1;32m 103\u001b[0m source\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msource,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 106\u001b[0m vault_name\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvidclub_vault_name,\n\u001b[1;32m 107\u001b[0m )\n\u001b[1;32m 109\u001b[0m vid_club_df \u001b[38;5;241m=\u001b[39m vid_club_df_task\u001b[38;5;241m.\u001b[39mbind(\n\u001b[1;32m 110\u001b[0m from_date\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfrom_date,\n\u001b[1;32m 111\u001b[0m to_date\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mto_date,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 115\u001b[0m flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 116\u001b[0m )\n\u001b[0;32m--> 118\u001b[0m df_with_metadata \u001b[38;5;241m=\u001b[39m add_ingestion_metadata_task\u001b[38;5;241m.\u001b[39mbind(\u001b[43mdf\u001b[49m, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 120\u001b[0m dtypes_dict \u001b[38;5;241m=\u001b[39m df_get_data_types_task\u001b[38;5;241m.\u001b[39mbind(df_with_metadata, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m)\n\u001b[1;32m 121\u001b[0m df_mapped \u001b[38;5;241m=\u001b[39m df_map_mixed_dtypes_for_parquet\u001b[38;5;241m.\u001b[39mbind(\n\u001b[1;32m 122\u001b[0m df_with_metadata, dtypes_dict, flow\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\n\u001b[1;32m 123\u001b[0m )\n", - "\u001b[0;31mNameError\u001b[0m: name 'df' is not defined" - ] - } - ], - "source": [ - "flow = VidClubToADLS('test', \n", - " source = \"survey\",\n", - " adls_dir_path = \"raw/test\", \n", - " adls_file_name = \"test.parquet\", \n", - " adls_sp_credentials_secret=\"App-Azure-CR-DatalakeGen2-AIA\", \n", - " overwrite_adls=True,\n", - " # schedule=schedule,\n", - " # state_handlers=[slack_handler],\n", - " # storage=STORAGE,\n", - " # run_config=RUN_CONFIG\n", - " )\n", - "flow.run()" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "1b2ced76-5f2a-4e58-98c9-dd127737fd17", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-24 17:40:22+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - } - ], - "source": [ - "from viadot.task_utils import credentials_loader\n", - "from viadot.utils import handle_api_response\n", - "from viadot.sources import VidClub\n", - "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", - "# CREDENTIALS = {'url': 'https://api.club-t.velux.com/api/v1/datalake/',\n", - "# 'token': 'HRHCyv0Z8AVsF0cJDZD4snCLxjTdszH6VNnwG1DCQn66UGmoaB1fau4Fhrqsauqs'}\n", - "url = \"https://api.club-t.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=2\"\n", - "url = \"https://api.club-t.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=12\"\n", - "headers = {\n", - " \"Authorization\": \"Bearer \" + CREDENTIALS[\"token\"],\n", - " \"Content-Type\": \"application/json\",\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "76f9b77c-75ef-470e-9423-b08c4e3cfca0", - "metadata": {}, - "outputs": [], - "source": [ - "resp = handle_api_response(url=\"https://api.club.velux.com/api/v1/datalake/company?from=2022-03-22&to=2023-07-17&limit=2®ion=xd\", headers=headers, method=\"GET\", verify=False)" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "31dcf87e-2a50-45d4-bb3a-a425c131baa5", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'current_page': 1,\n", - " 'data': [{'customerID': '01h59hdm9fghc8ttg893adv8ka',\n", - " 'companyName': 'Ciesielstwo Dekarstwo Wojciech Kandulski',\n", - " 'address1': 'Kozłowo 44d',\n", - " 'town': 'Opalenica',\n", - " 'postcode': '64-330',\n", - " 'companyNumber': '788 134 57 53',\n", - " 'country': 'Poland',\n", - " 'serviceTechnician': 'Piotr Polak',\n", - " 'areaManager': 'Michał Janiak',\n", - " 'ASEID': '15682844',\n", - " 'customerType': 'INCLUDED',\n", - " 'membershipDate': '2023-07-14T06:29:11.000000Z',\n", - " 'status': 'ACTIVE',\n", - " 'firstName': 'Wojciech',\n", - " 'lastName': 'Kandulski',\n", - " 'email': 'wojtekkandulski@o2.pl',\n", - " 'msisdn': '+48606954064',\n", - " 'languageID': None,\n", - " 'numberOfClosedProjects': 0,\n", - " 'numberOfOpenProjects': 0,\n", - " 'numberOfScans': 0,\n", - " 'totalPoints': 25,\n", - " 'pointsSpent': 0,\n", - " 'currentPoints': 25,\n", - " 'pendingPoints': None,\n", - " 'expiredPoints': None,\n", - " 'expiringPoints': None,\n", - " 'rewardsOrdered': 0,\n", - " 'optinsms': None,\n", - " 'optinemail': None,\n", - " 'optinMarketing': None,\n", - " 'lastlogin': '2023-07-14 06:32:35',\n", - " 'totalLogins': None,\n", - " 'q1Core': 'Slope roofing',\n", - " 'Column 1': 'Roof window installation',\n", - " 'Column 2': '',\n", - " 'q2Core': '26-50%',\n", - " 'q3Core': '1-5%',\n", - " 'q4Core': '2',\n", - " 'q5Core': '5',\n", - " 'q6Core': 'VELUX representative',\n", - " 'q7Core': 'Standard windows',\n", - " 'q8Core': 'Roof windows replacement',\n", - " 'Column 4': '',\n", - " 'Column 3': '',\n", - " 'Column 5': '',\n", - " 'Column 6': '',\n", - " 'Column 7': '',\n", - " 'Column 8': '',\n", - " 'Column 9': '',\n", - " 'Column 10': '',\n", - " 'Column 11': '',\n", - " 'Column 12': '',\n", - " 'Column 13': ''},\n", - " {'customerID': '01h57vg88543yp6hxa85fvw7py',\n", - " 'companyName': 'RuloCleanSolar',\n", - " 'address1': 'strada Plopilor 2B',\n", - " 'town': 'Botosani',\n", - " 'postcode': '710300',\n", - " 'companyNumber': None,\n", - " 'country': 'Romania',\n", - " 'serviceTechnician': 'Constantin Tigita',\n", - " 'areaManager': None,\n", - " 'ASEID': None,\n", - " 'customerType': 'INCLUDED',\n", - " 'membershipDate': '2023-07-13T14:46:54.000000Z',\n", - " 'status': 'ACTIVE',\n", - " 'firstName': 'Romica',\n", - " 'lastName': 'Vatamaniuc',\n", - " 'email': 'rulo.cleansolar@gmail.com',\n", - " 'msisdn': '+40746346463',\n", - " 'languageID': None,\n", - " 'numberOfClosedProjects': 1,\n", - " 'numberOfOpenProjects': 0,\n", - " 'numberOfScans': 14,\n", - " 'totalPoints': 194,\n", - " 'pointsSpent': 0,\n", - " 'currentPoints': 194,\n", - " 'pendingPoints': None,\n", - " 'expiredPoints': None,\n", - " 'expiringPoints': None,\n", - " 'rewardsOrdered': 0,\n", - " 'optinsms': None,\n", - " 'optinemail': None,\n", - " 'optinMarketing': None,\n", - " 'lastlogin': '2023-07-14 06:09:16',\n", - " 'totalLogins': None,\n", - " 'q1Core': 'Slope roofing',\n", - " 'Column 1': 'Carpentry/joinery',\n", - " 'Column 2': 'Roof window installation',\n", - " 'q2Core': '',\n", - " 'q3Core': '51-75%',\n", - " 'q4Core': '11-25%',\n", - " 'q5Core': '3-5',\n", - " 'q6Core': '9',\n", - " 'q7Core': 'VELUX representative',\n", - " 'q8Core': 'Standard windows',\n", - " 'Column 4': 'Roof windows replacement',\n", - " 'Column 3': 'Sun tunnels',\n", - " 'Column 5': '',\n", - " 'Column 6': '',\n", - " 'Column 7': '',\n", - " 'Column 8': '',\n", - " 'Column 9': '',\n", - " 'Column 10': '',\n", - " 'Column 11': '',\n", - " 'Column 12': '',\n", - " 'Column 13': ''}],\n", - " 'first_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=1',\n", - " 'from': 1,\n", - " 'last_page': 1045,\n", - " 'last_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=1045',\n", - " 'links': [{'url': None, 'label': 'Previous', 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1',\n", - " 'label': '1',\n", - " 'active': True},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", - " 'label': '2',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=3',\n", - " 'label': '3',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=4',\n", - " 'label': '4',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=5',\n", - " 'label': '5',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=6',\n", - " 'label': '6',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=7',\n", - " 'label': '7',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=8',\n", - " 'label': '8',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=9',\n", - " 'label': '9',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=10',\n", - " 'label': '10',\n", - " 'active': False},\n", - " {'url': None, 'label': '...', 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1044',\n", - " 'label': '1044',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=1045',\n", - " 'label': '1045',\n", - " 'active': False},\n", - " {'url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", - " 'label': 'Next',\n", - " 'active': False}],\n", - " 'next_page_url': 'http://api.club.velux.com/api/v1/datalake/company?page=2',\n", - " 'path': 'http://api.club.velux.com/api/v1/datalake/company',\n", - " 'per_page': 2,\n", - " 'prev_page_url': None,\n", - " 'to': 2,\n", - " 'total': 2090}" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "resp.json()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "9f1df1e7-48d9-4814-9337-81a3191b167e", - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'pd' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[43mpd\u001b[49m\u001b[38;5;241m.\u001b[39mDataFrame(rere[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdata\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 2\u001b[0m df\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m]\n", - "\u001b[0;31mNameError\u001b[0m: name 'pd' is not defined" - ] - } - ], - "source": [ - "df = pd.DataFrame(rere[\"data\"])\n", - "df.shape[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "8479b235-62f5-4ac9-8c62-540798bbbe05", - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'rere' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[11], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mpd\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m pd\u001b[38;5;241m.\u001b[39mDataFrame(\u001b[43mrere\u001b[49m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdata\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n", - "\u001b[0;31mNameError\u001b[0m: name 'rere' is not defined" - ] - } - ], - "source": [ - "import pandas as pd\n", - "pd.DataFrame(rere[\"data\"])" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "b6e8a9bd-8260-4fbd-9069-40a45ac07999", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-24 18:01:30+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - } - ], - "source": [ - "from viadot.task_utils import credentials_loader\n", - "from viadot.utils import handle_api_response\n", - "from viadot.sources import VidClub\n", - "CREDENTIALS = credentials_loader.run(credentials_secret=\"VIDCLUB\")\n", - "vc = VidClub(credentials = CREDENTIALS)\n", - "# vc.total_load(source=\"company\", from_date = \"2022-03-22\", to_date = \"2022-04-17\", items_per_page=30, region = \"hr\")\n", - "# df = vc.get_response(source=\"company\")\n", - "# response, first_url = vc.check_connection(\n", - "# source=\"jobs\",\n", - "# from_date=\"2023-03-24\",\n", - "# to_date=\"2023-03-24\",\n", - "# url=\"test\",\n", - "# items_per_page=1,\n", - "# )" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "4f607195-f589-4734-b0b3-1a6d673298d9", - "metadata": {}, - "outputs": [ - { - "ename": "ValueError", - "evalue": "time data '2023' does not match format '%Y-%m-%d'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mvc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mintervals\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfrom_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m2023\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mto_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m2023-04-01\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdays_interval\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/viadot/sources/vid_club.py:99\u001b[0m, in \u001b[0;36mVidClub.intervals\u001b[0;34m(self, from_date, to_date, days_interval)\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mintervals\u001b[39m(\n\u001b[1;32m 81\u001b[0m \u001b[38;5;28mself\u001b[39m, from_date: \u001b[38;5;28mstr\u001b[39m, to_date: \u001b[38;5;28mstr\u001b[39m, days_interval: \u001b[38;5;28mint\u001b[39m\n\u001b[1;32m 82\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Tuple[List[\u001b[38;5;28mstr\u001b[39m], List[\u001b[38;5;28mstr\u001b[39m]]:\n\u001b[1;32m 83\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 84\u001b[0m \u001b[38;5;124;03m Breaks dates range into smaller by provided days interval.\u001b[39;00m\n\u001b[1;32m 85\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;124;03m ValidationError: If the final date of the query is before the start date.\u001b[39;00m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 99\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_date \u001b[38;5;241m==\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 100\u001b[0m end_date \u001b[38;5;241m=\u001b[39m datetime\u001b[38;5;241m.\u001b[39mtoday()\u001b[38;5;241m.\u001b[39mdate()\n\u001b[1;32m 101\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", - "File \u001b[0;32m/usr/local/lib/python3.8/_strptime.py:568\u001b[0m, in \u001b[0;36m_strptime_datetime\u001b[0;34m(cls, data_string, format)\u001b[0m\n\u001b[1;32m 565\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_strptime_datetime\u001b[39m(\u001b[38;5;28mcls\u001b[39m, data_string, \u001b[38;5;28mformat\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m%a\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mb \u001b[39m\u001b[38;5;132;01m%d\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mH:\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mM:\u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mS \u001b[39m\u001b[38;5;124m%\u001b[39m\u001b[38;5;124mY\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 566\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Return a class cls instance based on the input string and the\u001b[39;00m\n\u001b[1;32m 567\u001b[0m \u001b[38;5;124;03m format string.\"\"\"\u001b[39;00m\n\u001b[0;32m--> 568\u001b[0m tt, fraction, gmtoff_fraction \u001b[38;5;241m=\u001b[39m \u001b[43m_strptime\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata_string\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mformat\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 569\u001b[0m tzname, gmtoff \u001b[38;5;241m=\u001b[39m tt[\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m2\u001b[39m:]\n\u001b[1;32m 570\u001b[0m args \u001b[38;5;241m=\u001b[39m tt[:\u001b[38;5;241m6\u001b[39m] \u001b[38;5;241m+\u001b[39m (fraction,)\n", - "File \u001b[0;32m/usr/local/lib/python3.8/_strptime.py:349\u001b[0m, in \u001b[0;36m_strptime\u001b[0;34m(data_string, format)\u001b[0m\n\u001b[1;32m 347\u001b[0m found \u001b[38;5;241m=\u001b[39m format_regex\u001b[38;5;241m.\u001b[39mmatch(data_string)\n\u001b[1;32m 348\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m found:\n\u001b[0;32m--> 349\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtime data \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m does not match format \u001b[39m\u001b[38;5;132;01m%r\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 350\u001b[0m (data_string, \u001b[38;5;28mformat\u001b[39m))\n\u001b[1;32m 351\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(data_string) \u001b[38;5;241m!=\u001b[39m found\u001b[38;5;241m.\u001b[39mend():\n\u001b[1;32m 352\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124munconverted data remains: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 353\u001b[0m data_string[found\u001b[38;5;241m.\u001b[39mend():])\n", - "\u001b[0;31mValueError\u001b[0m: time data '2023' does not match format '%Y-%m-%d'" - ] - } - ], - "source": [ - "vc.intervals(from_date = '2023', to_date = '2023-04-01', days_interval = 3)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "286b694f-c32d-4bad-9595-6fef097e12ce", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
customerIDcompanyNameaddress1townpostcodecompanyNumbercountryserviceTechnicianareaManagerASEID...Column 3Column 5Column 6Column 7Column 8Column 9Column 10Column 11Column 12Column 13
001h5mej1wvwkkr01jmtd5vsvjqRs-DomFrezerów 3Lublin20-209NonePolandNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Shutters and remote controlled awning blindsSun tunnels
101h5ma3j1npx22b5925gcg5n7rKrovstvo Kleparstvo Robert Vek s.pPtujska Gora 100aPtujska gora232316823079SloveniaCiril BadokoJurij Saletinger48193...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof terrace and balconyShutters and remote controlled awning blinds
001h5m918wrkypx3wwjdmd85wpzBlacharstwo-dekarstwo Krzysztof ZawadzkiKiedrzyn 48Gózd26-6347961871484PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Shutters and remote controlled awning blindsSun tunnelsRoof window repair / maintenance
101h5m6hty8rhj2w4vv12014yg8Tim starVasif H Zejcirevic 5Brčko761004700620460008Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m63bz6eyn80ff1msncerg7Cer KomercDEVETA ULICA 5Zvornik754004400233640002Bosnia and HerzegovinaNoneNoneNone...Roof window combinations with vertical window ...Roof window repair / maintenance
101h5m5jv9eaqfd42ewgrqwy040Slavuj d.o.o.Nikole Tesle b.b.Brčko76101600014990005Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m5hkxxa1tj159h1t9nh7acSZD ,,Došenović,,Kozarska Dubica jošik bbKozarska Dubica792404511800620006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h5m53gw4e5dqdptpfncrf8gmSZD \"Došenović\"Jošik BBKozarska Dubica792400101979100001Bosnia and HerzegovinaNoneNoneNone...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenanceRoof window combinations with vertical window ...Install home automatization / smart home solutionElectrical and solar INTEGRA solutions (roof w...
001h5m51zbqy23xv1v8ae6b1svsWestalBulevar VII korpusa 50Sanski Most79260263722240001Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsRoof window repair / maintenance
101h5m4mympp0b49jpcbhz3cdfsApisMokri dolovi bbTrebinje89101401341230003Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsRoof window repair / maintenance
001h5m4dvbyw4f7cctz01fhnkx3DOO TemikaCara Dusana BbFoca73300403921900009Bosnia and HerzegovinaNoneNoneNone...Roof windows replacement
101h5m4aj80qwkdax5a09m97av2Parter d.o.o.Bleiburških žrtava 134Mostar88000227173590007Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m47m3qnyz5c0jjrxyk30yhTrgometalKovači bbPosušje88240272038500001Bosnia and HerzegovinaNoneNoneNone...Shutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h5m440b8k38xfqwxhkr7sbqgDESC dooNikole Tesle 53dLukavica711244404522490006Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m43qrhp6660zmfzycv10ktLima-LozicVakuf bb 030516058Travnik72270NoneBosnia and HerzegovinaNoneNoneNone...
101h5m40a0xwyt75jw18y2qc8wtMegraDoglodska 2Zenica720004218299430006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m3wwbpknrs8nqn3rjh6dj4OD.ResicBranislava Nušića 173Sarajevo71000421868396004Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsRoof window repair / maintenanceFlat roof windowsSun tunnels
101h5m3tvagx8fbqtrqhzqdked9Limarija HamoGuvna 26Travnik722704337740010009Bosnia and HerzegovinaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Install home automatization / smart home solutionRoof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5m3rn5y9gfctjff64je0b51LimFix ŽepčePapratnica BbŽepče722304320177890005Bosnia and HerzegovinaNoneNoneNone...
101h5m34992emrafttpjeqww13dHado GradnjaDonjaVisca BBŽivinice75270311396510006Bosnia and HerzegovinaNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h5ktxk4m66ay8wkhd6q7agayWitek Firma Handlowo UsługowaOsusz 32Krotoszyn63-700621 161 88 52PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsSun tunnels
101h59typva56yvvd79gyqrxa7cPantes 2017Ержебет Силађи 3Суботица24000110116303SerbiaNoneNoneNone...Lining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Install home automatization / smart home solutionRoof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h59ttph5fnwff3y6ytc36mm5SB RoloplastХерцеговачка 27Зрењанин2310156215816SerbiaNoneNoneNone...Sun tunnelsShutters and remote controlled awning blindsRoof window repair / maintenance
101h59tsxds6k98bmmk5kqbrzq8SB RolosplastХерцеговачка 27Зрењанин2300056215816SerbiaNoneNoneNone...Roof windows replacementSun tunnelsShutters and remote controlled awning blinds
001h59trfz5scnsnkafrcjk49p9KrovomontBošnjakMatije Gupca 12Sonta2526464247620SerbiaNoneNoneNone...Roof windows replacement
101h59tgn306tjepd2rst6t2yqtSZR\"Haus majstor\"Marije Bursać 30Kikinda2330062425911SerbiaNoneNoneNone...Roof windows replacementLining preparationSun tunnelsRoof window repair / maintenance
001h59tf315qn76cegzwnymdsjhIntegra021Trg Cara Lazara 5Beocin21300108997552SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof terrace and balconyRoof window combinations with vertical window ...Flat roof windowsSun tunnelsRoof window repair / maintenanceShutters and remote controlled awning blinds
101h59hdm9fghc8ttg893adv8kaCiesielstwo Dekarstwo Wojciech KandulskiKozłowo 44dOpalenica64-330788 134 57 53PolandNoneNoneNone...
001h58bvwtb8b8w19typshbkqtyPRO.MAX.TEAMМилице Српкиње 13Београд1100020177438SerbiaNoneNoneNone...Lining preparationElectrical and solar INTEGRA solutions (roof w...Shutters and remote controlled awning blindsFlat roof windowsRoof window repair / maintenance
101h57vg88543yp6hxa85fvw7pyRuloCleanSolarstrada Plopilor 2BBotosani710300NoneRomaniaConstantin TigitaNoneNone...Sun tunnels
001h57ftmsjvr65jddzs9vkaxmkGZR Majstor PantaMalo crnice BbMalo crnice1231164082795SerbiaNoneNoneNone...Roof windows replacementInstall home automatization / smart home solutionRoof window combinations with vertical window ...Shutters and remote controlled awning blindsRoof window repair / maintenance
101h57fsq0mqgmwetyc1mwkyntqProzor PlusКраља Петра 14Београд11130108908193SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57fp2519nnz1w5jpc64e1wbUnlimited gradnja BeogradТрговачка 4Београд11030111911923SerbiaNoneNoneNone...Warm installation solutions (BDX, BBX)Lining preparationRoof window repair / maintenance
101h57fjevd411bf7pcj2xnafn9Pro 5Trbunje 5Blace1842064714996SerbiaNoneNoneNone...Warm installation solutions (BDX, BBX)Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57fe5adpyj2t2meeye5wg7vVizart sistemБраће Вучковић 62Београд1114766665097SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
101h57fe0x3715en0m6h9esaytkNas Krov PlusСрбичка 15Београд1108562885297SerbiaNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsFlat roof windowsSun tunnelsRoof window repair / maintenance
001h57f7wbfs75mzeen7amrmw11Zr MiskovicSrpskih serdara 2Београд11000105628951SerbiaNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solutionRoof terrace and balconyFlat roof windowsSun tunnelsShutters and remote controlled awning blindsRoof window repair / maintenance
101h57c7abjx278gdy820dc0v6bQuartz Impex srlCalea Națională 8Botoșani717007NoneRomaniaConstantin TigitaNoneNone...Roof window repair / maintenanceSun tunnels
001h57adcnb4y1g6y06q73wn7r3QuartzCalea nationala 8Botoșani710098NoneRomaniaConstantin TigitaNoneNone...Electrical and solar INTEGRA solutions (roof w...Install home automatization / smart home solution
101h577vaspgjpzhahvk15h0fagPrzem- BudPoznańska 9/3Kórnik62-035785 17 32 793PolandNoneNoneNone...Roof windows replacementShutters and remote controlled awning blinds
001h54xw4ebfhm7vfwq9wwskstdRussa-fix d.o.o.Zagrebačka ulica 48Sveti ivan zelina1038078413994889CroatiaTomislav DelačŽeljko PetrovićNone...
101h54wm99h2geyrj8kdc28y709Efekt Dachy Marcin BoguszProsta 7Krzywda21-470825 20 41 333PolandNoneNoneNone...Roof windows replacementLining preparationElectrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Roof terrace and balconyShutters and remote controlled awning blindsSun tunnelsRoof window repair / maintenance
001h54tb1r8j8djfyf1v4rsn0p1Architect Line Stúdió kftLiget utca 16/1Kiskőrös620003-09-121591HungaryNoneMészáros Zoltán2662...Flat roof windowsShutters and remote controlled awning blindsElectrical and solar INTEGRA solutions (roof w...Lining preparationRoof windows replacementWarm installation solutions (BDX, BBX)Standard windowsRoof terrace and balcony
101h52sexkw5c8b71n614nw6919KARDEK-DACHYStanowice 2Stanowice55-2008961229251PolandNoneNoneNone...Roof windows replacementElectrical and solar INTEGRA solutions (roof w...Roof terrace and balconyShutters and remote controlled awning blindsSun tunnels
001h529q6p9cbde0f9x2epqknrpPalka Andrzej FUHandlowa Palka-Dach-Budul. Ryszarda Moskały 11Zagórze32-5557371953169PolandNoneNoneNone...Electrical and solar INTEGRA solutions (roof w...Roof window combinations with vertical window ...Shutters and remote controlled awning blindsFlat roof windowsSun tunnels
101h52099qx6mb3jek851xg4q5sStanila Nicolae George pfaSat hapria nr 228Alba Iulia51724327479852RomaniaIoan IacobNoneNone...Roof windows replacementRoof terrace and balconyFlat roof windowsSun tunnels
001h4zyj42emdy4key1y8shhdhtПокриви ЕООДс. Лозен 10София1151203932976BulgariaNoneNoneNone...
\n", - "

47 rows × 54 columns

\n", - "
" - ], - "text/plain": [ - " customerID companyName \\\n", - "0 01h5mej1wvwkkr01jmtd5vsvjq Rs-Dom \n", - "1 01h5ma3j1npx22b5925gcg5n7r Krovstvo Kleparstvo Robert Vek s.p \n", - "0 01h5m918wrkypx3wwjdmd85wpz Blacharstwo-dekarstwo Krzysztof Zawadzki \n", - "1 01h5m6hty8rhj2w4vv12014yg8 Tim star \n", - "0 01h5m63bz6eyn80ff1msncerg7 Cer Komerc \n", - "1 01h5m5jv9eaqfd42ewgrqwy040 Slavuj d.o.o. \n", - "0 01h5m5hkxxa1tj159h1t9nh7ac SZD ,,Došenović,, \n", - "1 01h5m53gw4e5dqdptpfncrf8gm SZD \"Došenović\" \n", - "0 01h5m51zbqy23xv1v8ae6b1svs Westal \n", - "1 01h5m4mympp0b49jpcbhz3cdfs Apis \n", - "0 01h5m4dvbyw4f7cctz01fhnkx3 DOO Temika \n", - "1 01h5m4aj80qwkdax5a09m97av2 Parter d.o.o. \n", - "0 01h5m47m3qnyz5c0jjrxyk30yh Trgometal \n", - "1 01h5m440b8k38xfqwxhkr7sbqg DESC doo \n", - "0 01h5m43qrhp6660zmfzycv10kt Lima-Lozic \n", - "1 01h5m40a0xwyt75jw18y2qc8wt Megra \n", - "0 01h5m3wwbpknrs8nqn3rjh6dj4 OD.Resic \n", - "1 01h5m3tvagx8fbqtrqhzqdked9 Limarija Hamo \n", - "0 01h5m3rn5y9gfctjff64je0b51 LimFix Žepče \n", - "1 01h5m34992emrafttpjeqww13d Hado Gradnja \n", - "0 01h5ktxk4m66ay8wkhd6q7agay Witek Firma Handlowo Usługowa \n", - "1 01h59typva56yvvd79gyqrxa7c Pantes 2017 \n", - "0 01h59ttph5fnwff3y6ytc36mm5 SB Roloplast \n", - "1 01h59tsxds6k98bmmk5kqbrzq8 SB Rolosplast \n", - "0 01h59trfz5scnsnkafrcjk49p9 KrovomontBošnjak \n", - "1 01h59tgn306tjepd2rst6t2yqt SZR\"Haus majstor\" \n", - "0 01h59tf315qn76cegzwnymdsjh Integra021 \n", - "1 01h59hdm9fghc8ttg893adv8ka Ciesielstwo Dekarstwo Wojciech Kandulski \n", - "0 01h58bvwtb8b8w19typshbkqty PRO.MAX.TEAM \n", - "1 01h57vg88543yp6hxa85fvw7py RuloCleanSolar \n", - "0 01h57ftmsjvr65jddzs9vkaxmk GZR Majstor Panta \n", - "1 01h57fsq0mqgmwetyc1mwkyntq Prozor Plus \n", - "0 01h57fp2519nnz1w5jpc64e1wb Unlimited gradnja Beograd \n", - "1 01h57fjevd411bf7pcj2xnafn9 Pro 5 \n", - "0 01h57fe5adpyj2t2meeye5wg7v Vizart sistem \n", - "1 01h57fe0x3715en0m6h9esaytk Nas Krov Plus \n", - "0 01h57f7wbfs75mzeen7amrmw11 Zr Miskovic \n", - "1 01h57c7abjx278gdy820dc0v6b Quartz Impex srl \n", - "0 01h57adcnb4y1g6y06q73wn7r3 Quartz \n", - "1 01h577vaspgjpzhahvk15h0fag Przem- Bud \n", - "0 01h54xw4ebfhm7vfwq9wwskstd Russa-fix d.o.o. \n", - "1 01h54wm99h2geyrj8kdc28y709 Efekt Dachy Marcin Bogusz \n", - "0 01h54tb1r8j8djfyf1v4rsn0p1 Architect Line Stúdió kft \n", - "1 01h52sexkw5c8b71n614nw6919 KARDEK-DACHY \n", - "0 01h529q6p9cbde0f9x2epqknrp Palka Andrzej FUHandlowa Palka-Dach-Bud \n", - "1 01h52099qx6mb3jek851xg4q5s Stanila Nicolae George pfa \n", - "0 01h4zyj42emdy4key1y8shhdht Покриви ЕООД \n", - "\n", - " address1 town postcode companyNumber \\\n", - "0 Frezerów 3 Lublin 20-209 None \n", - "1 Ptujska Gora 100a Ptujska gora 2323 16823079 \n", - "0 Kiedrzyn 48 Gózd 26-634 7961871484 \n", - "1 Vasif H Zejcirevic 5 Brčko 76100 4700620460008 \n", - "0 DEVETA ULICA 5 Zvornik 75400 4400233640002 \n", - "1 Nikole Tesle b.b. Brčko 76101 600014990005 \n", - "0 Kozarska Dubica jošik bb Kozarska Dubica 79240 4511800620006 \n", - "1 Jošik BB Kozarska Dubica 79240 0101979100001 \n", - "0 Bulevar VII korpusa 50 Sanski Most 79260 263722240001 \n", - "1 Mokri dolovi bb Trebinje 89101 401341230003 \n", - "0 Cara Dusana Bb Foca 73300 403921900009 \n", - "1 Bleiburških žrtava 134 Mostar 88000 227173590007 \n", - "0 Kovači bb Posušje 88240 272038500001 \n", - "1 Nikole Tesle 53d Lukavica 71124 4404522490006 \n", - "0 Vakuf bb 030516058 Travnik 72270 None \n", - "1 Doglodska 2 Zenica 72000 4218299430006 \n", - "0 Branislava Nušića 173 Sarajevo 71000 421868396004 \n", - "1 Guvna 26 Travnik 72270 4337740010009 \n", - "0 Papratnica Bb Žepče 72230 4320177890005 \n", - "1 DonjaVisca BB Živinice 75270 311396510006 \n", - "0 Osusz 32 Krotoszyn 63-700 621 161 88 52 \n", - "1 Ержебет Силађи 3 Суботица 24000 110116303 \n", - "0 Херцеговачка 27 Зрењанин 23101 56215816 \n", - "1 Херцеговачка 27 Зрењанин 23000 56215816 \n", - "0 Matije Gupca 12 Sonta 25264 64247620 \n", - "1 Marije Bursać 30 Kikinda 23300 62425911 \n", - "0 Trg Cara Lazara 5 Beocin 21300 108997552 \n", - "1 Kozłowo 44d Opalenica 64-330 788 134 57 53 \n", - "0 Милице Српкиње 13 Београд 11000 20177438 \n", - "1 strada Plopilor 2B Botosani 710300 None \n", - "0 Malo crnice Bb Malo crnice 12311 64082795 \n", - "1 Краља Петра 14 Београд 11130 108908193 \n", - "0 Трговачка 4 Београд 11030 111911923 \n", - "1 Trbunje 5 Blace 18420 64714996 \n", - "0 Браће Вучковић 62 Београд 11147 66665097 \n", - "1 Србичка 15 Београд 11085 62885297 \n", - "0 Srpskih serdara 2 Београд 11000 105628951 \n", - "1 Calea Națională 8 Botoșani 717007 None \n", - "0 Calea nationala 8 Botoșani 710098 None \n", - "1 Poznańska 9/3 Kórnik 62-035 785 17 32 793 \n", - "0 Zagrebačka ulica 48 Sveti ivan zelina 10380 78413994889 \n", - "1 Prosta 7 Krzywda 21-470 825 20 41 333 \n", - "0 Liget utca 16/1 Kiskőrös 6200 03-09-121591 \n", - "1 Stanowice 2 Stanowice 55-200 8961229251 \n", - "0 ul. Ryszarda Moskały 11 Zagórze 32-555 7371953169 \n", - "1 Sat hapria nr 228 Alba Iulia 517243 27479852 \n", - "0 с. Лозен 10 София 1151 203932976 \n", - "\n", - " country serviceTechnician areaManager ASEID ... \\\n", - "0 Poland None None None ... \n", - "1 Slovenia Ciril Badoko Jurij Saletinger 48193 ... \n", - "0 Poland None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Bosnia and Herzegovina None None None ... \n", - "1 Bosnia and Herzegovina None None None ... \n", - "0 Poland None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Poland None None None ... \n", - "0 Serbia None None None ... \n", - "1 Romania Constantin Tigita None None ... \n", - "0 Serbia None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Serbia None None None ... \n", - "0 Serbia None None None ... \n", - "1 Romania Constantin Tigita None None ... \n", - "0 Romania Constantin Tigita None None ... \n", - "1 Poland None None None ... \n", - "0 Croatia Tomislav Delač Željko Petrović None ... \n", - "1 Poland None None None ... \n", - "0 Hungary None Mészáros Zoltán 2662 ... \n", - "1 Poland None None None ... \n", - "0 Poland None None None ... \n", - "1 Romania Ioan Iacob None None ... \n", - "0 Bulgaria None None None ... \n", - "\n", - " Column 3 \\\n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof windows replacement \n", - "0 Roof windows replacement \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Roof window combinations with vertical window ... \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof windows replacement \n", - "0 Roof windows replacement \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Roof windows replacement \n", - "0 \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof windows replacement \n", - "0 \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Roof windows replacement \n", - "1 Lining preparation \n", - "0 Sun tunnels \n", - "1 Roof windows replacement \n", - "0 Roof windows replacement \n", - "1 Roof windows replacement \n", - "0 Roof windows replacement \n", - "1 \n", - "0 Lining preparation \n", - "1 Sun tunnels \n", - "0 Roof windows replacement \n", - "1 Roof windows replacement \n", - "0 Warm installation solutions (BDX, BBX) \n", - "1 Warm installation solutions (BDX, BBX) \n", - "0 Roof windows replacement \n", - "1 Roof windows replacement \n", - "0 Roof windows replacement \n", - "1 Roof window repair / maintenance \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof windows replacement \n", - "0 \n", - "1 Roof windows replacement \n", - "0 Flat roof windows \n", - "1 Roof windows replacement \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof windows replacement \n", - "0 \n", - "\n", - " Column 5 \\\n", - "0 Install home automatization / smart home solution \n", - "1 Lining preparation \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Roof window repair / maintenance \n", - "1 Install home automatization / smart home solution \n", - "0 Install home automatization / smart home solution \n", - "1 Flat roof windows \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Lining preparation \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Flat roof windows \n", - "1 Lining preparation \n", - "0 \n", - "1 Install home automatization / smart home solution \n", - "0 Install home automatization / smart home solution \n", - "1 Lining preparation \n", - "0 \n", - "1 Install home automatization / smart home solution \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Sun tunnels \n", - "0 \n", - "1 Lining preparation \n", - "0 Lining preparation \n", - "1 \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 \n", - "0 Install home automatization / smart home solution \n", - "1 Lining preparation \n", - "0 Lining preparation \n", - "1 Roof window combinations with vertical window ... \n", - "0 Lining preparation \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Lining preparation \n", - "1 Sun tunnels \n", - "0 Install home automatization / smart home solution \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 Lining preparation \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Roof window combinations with vertical window ... \n", - "1 Roof terrace and balcony \n", - "0 \n", - "\n", - " Column 6 \\\n", - "0 Roof window combinations with vertical window ... \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Roof window combinations with vertical window ... \n", - "1 Flat roof windows \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 Roof window combinations with vertical window ... \n", - "1 Sun tunnels \n", - "0 Roof window repair / maintenance \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 \n", - "1 Flat roof windows \n", - "0 Sun tunnels \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 Roof window combinations with vertical window ... \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Roof window combinations with vertical window ... \n", - "0 Roof window repair / maintenance \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 Sun tunnels \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 \n", - "0 Shutters and remote controlled awning blinds \n", - "1 \n", - "0 Roof window combinations with vertical window ... \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Roof window repair / maintenance \n", - "1 Roof terrace and balcony \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof window combinations with vertical window ... \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 Electrical and solar INTEGRA solutions (roof w... \n", - "1 Roof terrace and balcony \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Flat roof windows \n", - "0 \n", - "\n", - " Column 7 \\\n", - "0 Shutters and remote controlled awning blinds \n", - "1 Roof terrace and balcony \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Sun tunnels \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 Roof terrace and balcony \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 \n", - "1 Sun tunnels \n", - "0 Roof window repair / maintenance \n", - "1 Install home automatization / smart home solution \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 Roof terrace and balcony \n", - "1 Roof window combinations with vertical window ... \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 Flat roof windows \n", - "1 Install home automatization / smart home solution \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 Install home automatization / smart home solution \n", - "1 \n", - "0 Flat roof windows \n", - "1 \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Install home automatization / smart home solution \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Install home automatization / smart home solution \n", - "1 Roof terrace and balcony \n", - "0 Install home automatization / smart home solution \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 Lining preparation \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Flat roof windows \n", - "1 Sun tunnels \n", - "0 \n", - "\n", - " Column 8 \\\n", - "0 Sun tunnels \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Sun tunnels \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Roof window combinations with vertical window ... \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 Roof window combinations with vertical window ... \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Install home automatization / smart home solution \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Sun tunnels \n", - "1 Roof terrace and balcony \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Roof terrace and balcony \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 Roof window combinations with vertical window ... \n", - "0 \n", - "1 Flat roof windows \n", - "0 Roof window combinations with vertical window ... \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Roof terrace and balcony \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 Roof windows replacement \n", - "1 Sun tunnels \n", - "0 Sun tunnels \n", - "1 \n", - "0 \n", - "\n", - " Column 9 \\\n", - "0 \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 \n", - "1 Flat roof windows \n", - "0 Flat roof windows \n", - "1 Install home automatization / smart home solution \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 \n", - "1 Flat roof windows \n", - "0 Roof window repair / maintenance \n", - "1 Roof terrace and balcony \n", - "0 \n", - "1 Flat roof windows \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Roof window combinations with vertical window ... \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof terrace and balcony \n", - "0 \n", - "1 Sun tunnels \n", - "0 Roof terrace and balcony \n", - "1 Flat roof windows \n", - "0 Flat roof windows \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 Warm installation solutions (BDX, BBX) \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "\n", - " Column 10 \\\n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Sun tunnels \n", - "0 Sun tunnels \n", - "1 Electrical and solar INTEGRA solutions (roof w... \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 Sun tunnels \n", - "0 Flat roof windows \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 Sun tunnels \n", - "0 \n", - "1 Flat roof windows \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Flat roof windows \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Shutters and remote controlled awning blinds \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 Shutters and remote controlled awning blinds \n", - "1 Sun tunnels \n", - "0 Sun tunnels \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Sun tunnels \n", - "0 Standard windows \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "\n", - " Column 11 \\\n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Flat roof windows \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 Sun tunnels \n", - "1 Flat roof windows \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 Sun tunnels \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Sun tunnels \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Flat roof windows \n", - "0 \n", - "1 \n", - "0 Flat roof windows \n", - "1 Roof window repair / maintenance \n", - "0 Shutters and remote controlled awning blinds \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 Roof terrace and balcony \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "\n", - " Column 12 \\\n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Sun tunnels \n", - "0 \n", - "1 \n", - "0 \n", - "1 Sun tunnels \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Sun tunnels \n", - "0 \n", - "1 \n", - "0 Sun tunnels \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "\n", - " Column 13 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 Shutters and remote controlled awning blinds \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 Roof window repair / maintenance \n", - "0 \n", - "1 \n", - "0 Roof window repair / maintenance \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "1 \n", - "0 \n", - "\n", - "[47 rows x 54 columns]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "id": "d9e52c0f-0205-4a29-8ef3-fb22dc43f72f", - "metadata": {}, - "outputs": [], - "source": [ - "mask = df.duplicated()" - ] - }, - { - "cell_type": "code", - "execution_count": 71, - "id": "5ce19ea1-dbaa-4572-bf48-843aff47c4e3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
customerIDcompanyNameaddress1townpostcodecompanyNumbercountryserviceTechnicianareaManagerASEID...Column 3Column 5Column 6Column 7Column 8Column 9Column 10Column 11Column 12Column 13
\n", - "

0 rows × 54 columns

\n", - "
" - ], - "text/plain": [ - "Empty DataFrame\n", - "Columns: [customerID, companyName, address1, town, postcode, companyNumber, country, serviceTechnician, areaManager, ASEID, customerType, membershipDate, status, firstName, lastName, email, msisdn, languageID, numberOfClosedProjects, numberOfOpenProjects, numberOfScans, totalPoints, pointsSpent, currentPoints, pendingPoints, expiredPoints, expiringPoints, rewardsOrdered, optinsms, optinemail, optinMarketing, lastlogin, totalLogins, q1Core, Column 1, Column 2, q2Core, q3Core, q4Core, q5Core, q6Core, q7Core, q8Core, Column 4, Column 3, Column 5, Column 6, Column 7, Column 8, Column 9, Column 10, Column 11, Column 12, Column 13]\n", - "Index: []\n", - "\n", - "[0 rows x 54 columns]" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df[mask]" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "29a88b03-6614-483c-90e7-44409529206f", - "metadata": {}, - "outputs": [], - "source": [ - "new_structure = list(df.columns)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "8599228f-5675-402d-881c-c5bc545731b0", - "metadata": {}, - "outputs": [], - "source": [ - "lista = ['__v',\n", - " '_id',\n", - " 'countrySlug',\n", - " 'createdAt',\n", - " 'id',\n", - " 'negativePointsByYear',\n", - " 'positivePointsByYear',\n", - " 'survey']" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "352e705b-0583-427f-a781-01c0cafd9e31", - "metadata": {}, - "outputs": [], - "source": [ - "new_structure = df.columns" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "039fa415-cfa4-4970-bf66-93b84afb09ba", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 13:33:16+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n" - ] - } - ], - "source": [ - "from viadot.tasks import VidClubToDF\n", - "from datetime import datetime, date, timedelta\n", - "\n", - "VC = VidClubToDF(source = \"jobs\", to_date=\"2023-07-12\", from_date=\"2023-07-01\")" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "19918ac7-9810-47c1-9ab9-f1063ac4dffa", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 13:27:03+0000] INFO - prefect | ingesting data for dates [2023-07-01]-[2023-07-12]...\n", - "[2023-07-25 13:27:07+0000] INFO - prefect | Dropping following columns: ['regionID', 'submissionDate']...\n" - ] - } - ], - "source": [ - "df = VC.run(cols_to_drop = ['regionID', 'submissionDate'])" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "e6397bd2-97dc-41a1-aa98-00ba83e4b6fc", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'customerID',\n", - " 'points',\n", - " 'q1Core',\n", - " 'q2Core',\n", - " 'q2CoreOther',\n", - " 'q3Core',\n", - " 'q4Core',\n", - " 'q5Core',\n", - " 'q5CoreOther',\n", - " 'q6Core',\n", - " 'q6CoreOther',\n", - " 'q7Core',\n", - " 'q7CoreOther',\n", - " 'q8Core',\n", - " 'q8CoreOther',\n", - " 'q9Core',\n", - " 'status',\n", - " 'submissionAddress',\n", - " 'submissionID',\n", - " 'submissionPostcode',\n", - " 'submissionQuantity'}" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "set(list(df.columns)) - set(list(['regionID', 'submissionDate']))" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "c60bea39-39b1-49b9-9aad-ec18c6306933", - "metadata": {}, - "outputs": [], - "source": [ - "to_date = None\n", - "from_date = \"2022-04-01\"\n", - "days_interval = 30" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "5b0a2b7b-a794-4832-a274-d6bf9739ef50", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2022-04-01\n" - ] - } - ], - "source": [ - "date_str = \"2022-04-01\"\n", - "date_obj = datetime.strptime(date_str, \"%Y-%m-%d\").date()\n", - "print(date_obj) " - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "80a4c756-c3b6-4424-a898-e2e543a68c00", - "metadata": {}, - "outputs": [], - "source": [ - "if to_date == None:\n", - " end_date = datetime.today().date()\n", - "else:\n", - " end_date = datetime.strptime(to_date, \"%Y-%m-%d\").date()\n", - "start_date = datetime.strptime(from_date, \"%Y-%m-%d\").date()\n", - "interval = timedelta(days=days_interval)\n", - "starts = []\n", - "ends = []\n", - "period_start = start_date\n", - "while period_start < end_date:\n", - " period_end = min(period_start + interval, end_date)\n", - " starts.append(period_start.strftime(\"%Y-%m-%d\"))\n", - " ends.append(period_end.strftime(\"%Y-%m-%d\"))\n", - " period_start = period_end" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "14488d7b-937a-486c-8c2a-78189156cb9f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 13:34:29+0000] INFO - prefect | ingesting data for dates [2022-03-23]-[2022-03-24]...\n", - "[2023-07-25 13:34:35+0000] INFO - prefect | ingesting data for dates [2022-03-23]-[2022-03-24]...\n", - "[2023-07-25 13:34:41+0000] INFO - prefect | Dropping following columns: ['regionID', 'submissionDate']...\n" - ] - } - ], - "source": [ - "cols_to_drop = [\"regionID\", \"submissionDate\"]\n", - "var_dictionary = {\n", - " \"source\": \"jobs\",\n", - " \"from_date\": \"2022-03-23\",\n", - " \"to_date\": \"2022-03-24\",\n", - " \"items_per_page\": 1,\n", - " \"days_interval\": 1,\n", - "}\n", - "\n", - "output_with_all = VC.run(\n", - " source=var_dictionary[\"source\"],\n", - " to_date=var_dictionary[\"to_date\"],\n", - " from_date=var_dictionary[\"from_date\"],\n", - " items_per_page=var_dictionary[\"items_per_page\"],\n", - " days_interval=var_dictionary[\"days_interval\"],\n", - ")\n", - "output_with_dropped = VC.run(\n", - " source=var_dictionary[\"source\"],\n", - " to_date=var_dictionary[\"to_date\"],\n", - " from_date=var_dictionary[\"from_date\"],\n", - " items_per_page=var_dictionary[\"items_per_page\"],\n", - " days_interval=var_dictionary[\"days_interval\"],\n", - " cols_to_drop=cols_to_drop,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "13303ab5-05eb-4e40-b79a-b9f12f9b1a1f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'customerID',\n", - " 'points',\n", - " 'q1Core',\n", - " 'q2Core',\n", - " 'q2CoreOther',\n", - " 'q3Core',\n", - " 'q4Core',\n", - " 'q5Core',\n", - " 'q5CoreOther',\n", - " 'q6Core',\n", - " 'q6CoreOther',\n", - " 'q7Core',\n", - " 'q7CoreOther',\n", - " 'q8Core',\n", - " 'q8CoreOther',\n", - " 'q9Core',\n", - " 'regionID',\n", - " 'status',\n", - " 'submissionAddress',\n", - " 'submissionDate',\n", - " 'submissionID',\n", - " 'submissionPostcode',\n", - " 'submissionQuantity'}" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "set(list(output_with_all.columns))" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "f43b9be4-a3bd-49e3-9627-a2667ca34d19", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-25 14:21:13+0000] INFO - prefect | Successfully loaded credentials from Azure Key Vault.\n", - "[2023-07-25 14:21:13+0000] INFO - prefect | ingesting data for dates [2023-07-01]-[2023-07-12]...\n", - "[2023-07-25 14:21:17+0000] INFO - prefect | Dropping following columns: ['Test', 'submissionDate']...\n", - "[2023-07-25 14:21:17+0000] ERROR - prefect | Column(s): ['Test', 'submissionDate'] don't exist in the DataFrame. No columns were dropped. Returning full DataFrame...\n", - "[2023-07-25 14:21:17+0000] INFO - prefect | Existing columns: Index(['submissionID', 'submissionAddress', 'regionID', 'submissionPostcode',\n", - " 'submissionDate', 'customerID', 'status', 'submissionQuantity',\n", - " 'points', 'q1Core', 'q2Core', 'q2CoreOther', 'q3Core', 'q4Core',\n", - " 'q5Core', 'q5CoreOther', 'q6Core', 'q6CoreOther', 'q7Core',\n", - " 'q7CoreOther', 'q8Core', 'q8CoreOther', 'q9Core'],\n", - " dtype='object')\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'caplog' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[19], line 16\u001b[0m\n\u001b[1;32m 13\u001b[0m VC\u001b[38;5;241m.\u001b[39mrun(cols_to_drop \u001b[38;5;241m=\u001b[39m cols_to_drop) \u001b[38;5;66;03m# Call your function with appropriate arguments\u001b[39;00m\n\u001b[1;32m 15\u001b[0m \u001b[38;5;66;03m# Verify the loggers\u001b[39;00m\n\u001b[0;32m---> 16\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mcaplog\u001b[49m\u001b[38;5;241m.\u001b[39mrecords)\n\u001b[1;32m 17\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(caplog\u001b[38;5;241m.\u001b[39mrecords) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m2\u001b[39m \u001b[38;5;66;03m# Two log messages should be captured\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m caplog\u001b[38;5;241m.\u001b[39mrecords[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m.\u001b[39mlevelname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mERROR\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", - "\u001b[0;31mNameError\u001b[0m: name 'caplog' is not defined" - ] - } - ], - "source": [ - "import pytest # Replace 'your_module' with the actual module containing your function\n", - "from viadot.tasks import VidClubToDF\n", - "from datetime import datetime, date, timedelta\n", - "cols_to_drop = [\"Test\", \"submissionDate\"]\n", - "VC = VidClubToDF(source = \"jobs\", to_date=\"2023-07-12\", from_date=\"2023-07-01\")\n", - "# Assuming you have a function named 'your_function' in 'your_module'\n", - "# def test_your_function_with_keyerror(caplog):\n", - " # Your test data and setup here\n", - " # ...\n", - "\n", - " # Call your function that might raise KeyError\n", - "# with pytest.raises(KeyError):\n", - "VC.run(cols_to_drop = cols_to_drop) # Call your function with appropriate arguments\n", - "\n", - "# Verify the loggers\n", - "print(caplog.records)\n", - "assert len(caplog.records) == 2 # Two log messages should be captured\n", - "assert caplog.records[0].levelname == \"ERROR\"\n", - "assert \"Column(s): {cols_to_drop} don't exist in the DataFrame\" in caplog.records[0].message\n", - "assert caplog.records[1].levelname == \"INFO\"\n", - "assert \"Existing columns:\" in caplog.records[1].message\n", - "\n", - " # You can add more specific checks on the content of the log messages if needed\n", - " # For example, you can check if the correct column names are logged in the messages.\n", - "\n", - " # Optional: Clear the log for the next test (if any)\n", - " # caplog.clear()" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "id": "91514d5a-1eba-491b-80d5-efb03fb1abe4", - "metadata": {}, - "outputs": [], - "source": [ - "# my_module.py\n", - "\n", - "from prefect.utilities import logging\n", - "\n", - "logger = logging.get_logger(__name__)\n", - "\n", - "def my_function(a):\n", - "\n", - " try:\n", - " a-2\n", - " logger.info(f\"Dropping following columns: {cols_to_drop}...\")\n", - "\n", - " except TypeError as ke:\n", - " logger.error(\n", - " f\"Column(s): {a} don't exist in the DataFrame. No columns were dropped. Returning full DataFrame...\"\n", - " )\n", - " logger.info(f\"Existing columns: {a}\")\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "# test_my_module.py\n", - "\n", - "import pytest\n", - "# from viadot.tasks import VidClubToDF\n", - "\n", - "def test_my_function_with_keyerror(caplog):\n", - " # Call your function that might raise KeyError\n", - " with pytest.raises(KeyError):\n", - " my_function()\n", - "\n", - " # Verify the loggers\n", - " print(len(caplog.records))\n", - " assert len(caplog.records) == 2\n", - " assert caplog.records[0].levelname == \"ERROR\"\n", - " assert \"An error occurred: Some KeyError message\" in caplog.records[0].message\n", - " assert caplog.records[1].levelname == \"INFO\"\n", - " assert \"Additional info about the error\" in caplog.records[1].message\n", - "\n", - " # Optional: Clear the log for the next test (if any)\n", - " caplog.clear()" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "f773a59b-c195-4b5b-b769-a4f31fafccd3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1m============================= test session starts ==============================\u001b[0m\n", - "platform linux -- Python 3.8.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0\n", - "rootdir: /home/viadot, configfile: pyproject.toml\n", - "plugins: cov-3.0.0, anyio-3.7.0\n", - "collecting 0 items \u001b[0m\u001b[1m[2023-07-25 14:45:20+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "\n", - "\u001b[1m----------------------------- live log collection ------------------------------\u001b[0m\n", - "2023-07-25 14:45:20 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "[2023-07-25 14:45:20+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:20 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "Flow URL: https://cloud.prefect.io/dyvenia/flow/0888201f-6acb-4bc0-8897-f8ea170e9f21\n", - " └── ID: 0d183787-bcc3-4754-b813-60b60ed81613\n", - " └── Project: Marketing KPI\n", - " └── Labels: ['prod']\n", - "collecting 0 items \u001b[0m[2023-07-25 14:45:22+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:22 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "[2023-07-25 14:45:22+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:22 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "Flow URL: https://cloud.prefect.io/dyvenia/flow/13b9ec80-7536-484a-b1a5-497d90c4f981\n", - " └── ID: b50fca66-10b6-457b-8202-553ce0736c00\n", - " └── Project: dev\n", - " └── Labels: ['prod']\n", - "collecting 0 items \u001b[0m[2023-07-25 14:45:24+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:24 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "[2023-07-25 14:45:25+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:25 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "Flow URL: https://cloud.prefect.io/dyvenia/flow/4d5d69e5-c9cf-446a-b6a5-a740b2a6e608\n", - " └── ID: 2bda058d-512d-40ba-8fa6-d6405fa1f6f9\n", - " └── Project: dev\n", - " └── Labels: ['prod']\n", - "collecting 0 items \u001b[0m[2023-07-25 14:45:26+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:26 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "[2023-07-25 14:45:27+0000] WARNING - prefect.Git | Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "2023-07-25 14:45:27 \u001b[33mWARNING\u001b[0m Git storage initialized with a `git_clone_url_secret_name`. The value of this Secret will be used to clone the repository, ignoring `repo`, `repo_host`, `git_token_secret_name`, `git_token_username`, `use_ssh`, and `format_access_token`.\n", - "^C\n" - ] - } - ], - "source": [ - "!pytest -s" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "ef84d02a-7582-4fd5-8106-3b6efa9cb758", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "set(list(output_with_all.columns)) - set(list(output_with_dropped.columns)) == set(cols_to_drop)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "d70a3efa-d2da-435f-978d-ad25a66261fe", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2023-07-24 16:36:51+0000] INFO - prefect.adls_to_df | Downloading data from azuwevelcedls01p/raw/test/test.parquet to a DataFrame...\n", - "[2023-07-24 16:36:54+0000] INFO - prefect.adls_to_df | Successfully loaded data.\n" - ] - } - ], - "source": [ - "df = AzureDataLakeToDF().run(path='raw/test/test.parquet', sp_credentials_secret = \"App-Azure-CR-DatalakeGen2-AIA\")" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "id": "e4f25a24-5c50-49aa-9715-c564029198f4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "datetime.datetime(2021, 5, 9, 0, 0)" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from datetime import datetime, date, timedelta\n", - "from_date=\"2021-05-09\"\n", - "datetime.strptime(from_date, \"%Y-%m-%d\")" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "id": "48c1f745-9c4e-4d7f-b8c4-921a0c6bfee6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from_date > \"2020-05-05\"" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "57d8e3ac-e9ea-4513-b162-37c3602dfcfe", - "metadata": {}, - "outputs": [ - { - "ename": "ValidationError", - "evalue": "to_date cannot be earlier than from_date.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mvc\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_response\u001b[49m\u001b[43m(\u001b[49m\u001b[43msource\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mjobs\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfrom_date\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m2022-05-09\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mto_date\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m2022-05-05\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/viadot/sources/vid_club.py:213\u001b[0m, in \u001b[0;36mVidClub.get_response\u001b[0;34m(self, source, from_date, to_date, items_per_page, region)\u001b[0m\n\u001b[1;32m 210\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfrom_date cannot be earlier than 2022-03-22.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 212\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_date \u001b[38;5;241m<\u001b[39m from_date:\n\u001b[0;32m--> 213\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ValidationError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mto_date cannot be earlier than from_date.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 215\u001b[0m response, first_url \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcheck_connection(\n\u001b[1;32m 216\u001b[0m source\u001b[38;5;241m=\u001b[39msource,\n\u001b[1;32m 217\u001b[0m from_date\u001b[38;5;241m=\u001b[39mfrom_date,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 220\u001b[0m region\u001b[38;5;241m=\u001b[39mregion,\n\u001b[1;32m 221\u001b[0m )\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(response, \u001b[38;5;28mdict\u001b[39m):\n", - "\u001b[0;31mValidationError\u001b[0m: to_date cannot be earlier than from_date." - ] - } - ], - "source": [ - "vc.get_response(source=\"jobs\", from_date=\"2022-05-09\", to_date = \"2022-05-05\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "id": "bdc58560-41cd-4407-8e30-3c53b7fb4a1e", - "metadata": {}, - "outputs": [], - "source": [ - "dups_mask = df.duplicated()\n", - "df_check = df[dups_mask]" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "id": "e6484860-ab60-4b46-9b6c-20756615e1f7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
col1col2col3
22bb99
\n", - "
" - ], - "text/plain": [ - " col1 col2 col3\n", - "2 2 bb 99" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df_check" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} From 8b4f7add44f08dbcc3b5ce49aecca94cb03b0c0b Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 10:59:17 +0200 Subject: [PATCH 093/106] update tests for task --- tests/integration/tasks/test_vid_club.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/integration/tasks/test_vid_club.py b/tests/integration/tasks/test_vid_club.py index 2a4802cc2..d686f853d 100644 --- a/tests/integration/tasks/test_vid_club.py +++ b/tests/integration/tasks/test_vid_club.py @@ -59,13 +59,6 @@ def test_drop_columns(var_dictionary): cols_to_drop = ["regionID", "submissionDate"] vc_to_df = VidClubToDF(credentials=CREDENTIALS) - output_with_all = vc_to_df.run( - source=var_dictionary["source"], - to_date=var_dictionary["to_date"], - from_date=var_dictionary["from_date"], - items_per_page=var_dictionary["items_per_page"], - days_interval=var_dictionary["days_interval"], - ) output_with_dropped = vc_to_df.run( source=var_dictionary["source"], to_date=var_dictionary["to_date"], @@ -75,9 +68,7 @@ def test_drop_columns(var_dictionary): cols_to_drop=cols_to_drop, ) - assert set(list(output_with_all.columns)) - set( - list(output_with_dropped.columns) - ) == set(cols_to_drop) + assert all(col not in output_with_dropped.columns for col in cols_to_drop) @pytest.mark.drop_cols @@ -105,8 +96,6 @@ def test_drop_columns_KeyError(var_dictionary, caplog): f"Column(s): {cols_to_drop} don't exist in the DataFrame" in caplog.records[0].message ) - # assert caplog.records[1].levelname == "INFO" - # assert "Existing columns:" in caplog.records[1].message @pytest.mark.drop_cols From d3a685fb0031d1a394c8d6b4f38942246825e640 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 11:01:28 +0200 Subject: [PATCH 094/106] update asserts in source test --- tests/integration/test_vid_club.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index 35dabbba5..d6daadd47 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -32,9 +32,8 @@ def json(): def test_default_credential_param(): """ Checks if credentials are loaded from Azure Key Vault or PrefectSecret or from local config ursing credentials_loader and if it's dictionary type. - """ - assert vc.credentials != None and type(vc.credentials) == dict + assert vc.credentials is not None and isinstance(vc.credentials, dict) @pytest.mark.build_query @@ -81,8 +80,7 @@ def test_url_string(): items_per_page=items_per_page, ) - for ex in expected_elements: - assert ex in query + assert all(ex in query for ex in expected_elements) @pytest.mark.intervals From e1e11a32f58b8db7b973e680b3d14d8ccc721886 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 11:59:57 +0200 Subject: [PATCH 095/106] fix assigning today date in intervals --- viadot/sources/vid_club.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index 3044ef10a..eccda5b40 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -94,9 +94,9 @@ def intervals( """ if to_date == None: - end_date = datetime.today().date() - else: - end_date = datetime.strptime(to_date, "%Y-%m-%d").date() + to_date = datetime.today().strftime("%Y-%m-%d") + + end_date = datetime.strptime(to_date, "%Y-%m-%d").date() start_date = datetime.strptime(from_date, "%Y-%m-%d").date() from_date_obj = datetime.strptime(from_date, "%Y-%m-%d") From 3770125a5889826fe5401d805b741197829b74cc Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Wed, 26 Jul 2023 14:20:08 +0200 Subject: [PATCH 096/106] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Changed=20variable?= =?UTF-8?q?=20name=20to=20lower=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/test_sharepoint.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/integration/test_sharepoint.py b/tests/integration/test_sharepoint.py index 39874b650..c784fa682 100644 --- a/tests/integration/test_sharepoint.py +++ b/tests/integration/test_sharepoint.py @@ -32,7 +32,7 @@ def sharepoint(): @pytest.fixture(scope="session") -def FILE_NAME(sharepoint): +def file_name(sharepoint): """ A function built to get the path to a file. @@ -109,28 +109,28 @@ def test_download_file_missing_patameters(sharepoint): sharepoint.download_file(download_to_path=None, download_from_path=None) -def test_file_download(FILE_NAME): +def test_file_download(file_name): """ Testing if file is downloaded. Args: - FILE_NAME (str): File name. + file_name (str): File name. """ files = [] for file in os.listdir(): if os.path.isfile(os.path.join(file)): files.append(file) - assert FILE_NAME in files + assert file_name in files -def test_autopopulating_download_from(FILE_NAME): +def test_autopopulating_download_from(file_name): """ Testing if file name is correct. Args: - FILE_NAME (str): File name. + file_name (str): File name. """ - assert os.path.basename(get_url()) == FILE_NAME + assert os.path.basename(get_url()) == file_name def test_file_extension(): @@ -139,26 +139,26 @@ def test_file_extension(): assert get_url().endswith(file_ext) -def test_file_to_df(FILE_NAME): +def test_file_to_df(file_name): """ Testing if downloaded file contains data and if first sheet can be build as a Data frame. Args: - FILE_NAME (str): File name. + file_name (str): File name. """ - df = pd.read_excel(FILE_NAME, sheet_name=0) + df = pd.read_excel(file_name, sheet_name=0) df_test = pd.DataFrame(data={"col1": [1, 2]}) assert type(df) == type(df_test) -def test_get_data_types(FILE_NAME): +def test_get_data_types(file_name): """ Testing if downloaded file contains data and columns have `String` type. Args: - FILE_NAME (str): File name. + file_name (str): File name. """ - df = pd.read_excel(FILE_NAME, sheet_name=0) + df = pd.read_excel(file_name, sheet_name=0) dtypes_map = df_get_data_types_task.run(df) dtypes = dtypes_map.values() From 8a8183501dd83df2bb6e684da076380f09edf24d Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 15:27:01 +0200 Subject: [PATCH 097/106] add vid club to adls flow --- viadot/flows/vid_club_to_adls.py | 196 +++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 viadot/flows/vid_club_to_adls.py diff --git a/viadot/flows/vid_club_to_adls.py b/viadot/flows/vid_club_to_adls.py new file mode 100644 index 000000000..0452baf46 --- /dev/null +++ b/viadot/flows/vid_club_to_adls.py @@ -0,0 +1,196 @@ +import os +from pathlib import Path +from typing import Any, Dict, List, Literal +import pandas as pd + +import pendulum +from prefect import Flow +from prefect.backend import set_key_value +from prefect.utilities import logging + +from viadot.task_utils import ( + add_ingestion_metadata_task, + df_get_data_types_task, + df_map_mixed_dtypes_for_parquet, + df_to_csv, + df_to_parquet, + dtypes_to_json_task, + update_dtypes_dict, +) +from viadot.tasks import AzureDataLakeUpload, VidClubToDF + +logger = logging.get_logger(__name__) + + +class VidClubToADLS(Flow): + def __init__( + self, + name: str, + source: Literal["jobs", "product", "company", "survey"] = None, + from_date: str = "2022-03-22", + to_date: str = None, + items_per_page: int = 100, + region: Literal["bg", "hu", "hr", "pl", "ro", "si", "all"] = "all", + days_interval: int = 30, + cols_to_drop: List[str] = None, + vid_club_credentials: Dict[str, Any] = None, + vidclub_credentials_secret: str = "VIDCLUB", + vidclub_vault_name: str = None, + output_file_extension: str = ".parquet", + adls_dir_path: str = None, + local_file_path: str = None, + adls_file_name: str = None, + vault_name: str = None, + adls_sp_credentials_secret: str = None, + overwrite_adls: bool = False, + if_exists: str = "replace", + timeout: int = 3600, + *args: List[Any], + **kwargs: Dict[str, Any] + ): + """ + Flow for downloading data from the Vid Club via API to a CSV or Parquet file. + Then upload it to Azure Data Lake. + + Args: + name (str): The name of the flow. + source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. + from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. + to_date (str, optional): End date for the query. Defaults to None. + items_per_page (int, optional): Number of entries per page. Defaults to 100. + region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] + days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. + cols_to_drop (List[str], optional): List of columns to drop. Defaults to None. + vid_club_credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. + vidclub_credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". + vidclub_vault_name (str, optional): For Vid Club credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. + output_file_extension (str, optional): Output file extension - to allow selection of .csv for data + which is not easy to handle with parquet. Defaults to ".parquet". + adls_dir_path (str, optional): Azure Data Lake destination folder/catalog path. Defaults to None. + local_file_path (str, optional): Local destination path. Defaults to None. + adls_file_name (str, optional): Name of file in ADLS. Defaults to None. + vault_name (str, optional): For ADLS credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. + adls_sp_credentials_secret (str, optional): The name of the Azure Key Vault secret containing a dictionary with + ACCOUNT_NAME and Service Principal credentials (TENANT_ID, CLIENT_ID, CLIENT_SECRET) for the Azure Data Lake. + Defaults to None. + overwrite_adls (bool, optional): Whether to overwrite files in the lake. Defaults to False. + if_exists (str, optional): What to do if the file exists. Defaults to "replace". + timeout (int, optional): The time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. + """ + # VidClubToDF + self.source = source + self.from_date = from_date + self.to_date = to_date + self.items_per_page = items_per_page + self.region = region + self.days_interval = days_interval + self.cols_to_drop = cols_to_drop + self.vid_club_credentials = vid_club_credentials + self.vidclub_credentials_secret = vidclub_credentials_secret + self.vidclub_vault_name = vidclub_vault_name + + # AzureDataLakeUpload + self.adls_file_name = adls_file_name + self.adls_dir_path = adls_dir_path + self.local_file_path = local_file_path + self.overwrite = overwrite_adls + self.vault_name = vault_name + self.adls_sp_credentials_secret = adls_sp_credentials_secret + self.if_exists = if_exists + self.output_file_extension = output_file_extension + self.timeout = timeout + self.now = str(pendulum.now("utc")) + + self.local_file_path = ( + local_file_path or self.slugify(name) + self.output_file_extension + ) + self.local_json_path = self.slugify(name) + ".json" + self.adls_dir_path = adls_dir_path + + if adls_file_name is not None: + self.adls_file_path = os.path.join(adls_dir_path, adls_file_name) + self.adls_schema_file_dir_file = os.path.join( + adls_dir_path, "schema", Path(adls_file_name).stem + ".json" + ) + else: + self.adls_file_path = os.path.join( + adls_dir_path, self.now + self.output_file_extension + ) + self.adls_schema_file_dir_file = os.path.join( + adls_dir_path, "schema", self.now + ".json" + ) + + super().__init__(*args, name=name, **kwargs) + + self.gen_flow() + + @staticmethod + def slugify(name): + return name.replace(" ", "_").lower() + + def gen_flow(self) -> Flow: + vid_club_df_task = VidClubToDF( + timeout=self.timeout, + source=self.source, + credentials=self.vid_club_credentials, + credentials_secret=self.vidclub_credentials_secret, + vault_name=self.vidclub_vault_name, + ) + + vid_club_df = vid_club_df_task.bind( + from_date=self.from_date, + to_date=self.to_date, + items_per_page=self.items_per_page, + region=self.region, + days_interval=self.days_interval, + cols_to_drop = self.cols_to_drop, + flow=self, + ) + + df_with_metadata = add_ingestion_metadata_task.bind(vid_club_df, flow=self) + + dtypes_dict = df_get_data_types_task.bind(df_with_metadata, flow=self) + df_mapped = df_map_mixed_dtypes_for_parquet.bind( + df_with_metadata, dtypes_dict, flow=self + ) + + if self.output_file_extension == ".parquet": + df_to_file = df_to_parquet.bind( + df=df_mapped, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + else: + df_to_file = df_to_csv.bind( + df=df_with_metadata, + path=self.local_file_path, + if_exists=self.if_exists, + flow=self, + ) + + file_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) + file_to_adls_task.bind( + from_path=self.local_file_path, + to_path=self.adls_file_path, + overwrite=self.overwrite, + sp_credentials_secret=self.adls_sp_credentials_secret, + flow=self, + ) + + dtypes_updated = update_dtypes_dict(dtypes_dict, flow=self) + dtypes_to_json_task.bind( + dtypes_dict=dtypes_updated, local_json_path=self.local_json_path, flow=self + ) + json_to_adls_task = AzureDataLakeUpload(timeout=self.timeout) + json_to_adls_task.bind( + from_path=self.local_json_path, + to_path=self.adls_schema_file_dir_file, + overwrite=self.overwrite, + sp_credentials_secret=self.adls_sp_credentials_secret, + flow=self, + ) + + file_to_adls_task.set_upstream(df_to_file, flow=self) + json_to_adls_task.set_upstream(dtypes_to_json_task, flow=self) + set_key_value(key=self.adls_dir_path, value=self.adls_file_path) From acf5c1975c21408a66778997ea21cc6233196179 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 15:27:32 +0200 Subject: [PATCH 098/106] add vid club to adls flow to init --- viadot/flows/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/viadot/flows/__init__.py b/viadot/flows/__init__.py index b8113c1a1..332a010bd 100644 --- a/viadot/flows/__init__.py +++ b/viadot/flows/__init__.py @@ -45,3 +45,4 @@ from .sql_server_to_duckdb import SQLServerToDuckDB from .sql_server_to_parquet import SQLServerToParquet from .sql_server_transform import SQLServerTransform +from .vid_club_to_adls import VidClubToADLS From 9d05c1d871bf23b3ba3e37b420b15e7ca91fda4f Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 15:29:25 +0200 Subject: [PATCH 099/106] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c79e9aaf3..d16baa752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `SAPBWToDF` task class - Added `SAPBWToADLS` flow class - Added a new `end_point` parameter in `genesys_api_connection` to make it more generic. +- Added `VidClubToADLS` flow class. ### Fixed - Fixed a bug in `subject` (extra separator) and in `receivers` (long strings) parameters in Outlook connector. From 9b209c8ce04123ab771ac1617517886af4b67984 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 15:38:10 +0200 Subject: [PATCH 100/106] add tests --- .../integration/flows/test_vidclub_to_adls.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/integration/flows/test_vidclub_to_adls.py diff --git a/tests/integration/flows/test_vidclub_to_adls.py b/tests/integration/flows/test_vidclub_to_adls.py new file mode 100644 index 000000000..bbf788808 --- /dev/null +++ b/tests/integration/flows/test_vidclub_to_adls.py @@ -0,0 +1,31 @@ +import os +from unittest import mock + +import pandas as pd +import pytest + +from viadot.flows import VidClubToADLS + +DATA = {"col1": ["aaa", "bbb", "ccc"], "col2": [11, 22, 33]} +ADLS_FILE_NAME = "test_vid_club.parquet" +ADLS_DIR_PATH = "raw/test/" + + +@mock.patch( + "viadot.tasks.VidClubToDF.run", + return_value=pd.DataFrame(data=DATA), +) +@pytest.mark.run +def test_vidclub_to_adls_run_flow(mocked_class): + flow = VidClubToADLS( + "test_vidclub_to_adls_flow_run", + source=["test"], + from_date = "2023-06-05", + overwrite_adls=True, + adls_dir_path=ADLS_DIR_PATH, + adls_file_name=ADLS_FILE_NAME, + ) + result = flow.run() + assert result.is_successful() + os.remove("test_vidclub_to_adls_flow_run.parquet") + os.remove("test_vidclub_to_adls_flow_run.json") From f38b742b8aadbbf109d6e8206fbec98deb004024 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Wed, 26 Jul 2023 16:52:13 +0200 Subject: [PATCH 101/106] update docstring --- viadot/flows/vid_club_to_adls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/viadot/flows/vid_club_to_adls.py b/viadot/flows/vid_club_to_adls.py index 0452baf46..639e81653 100644 --- a/viadot/flows/vid_club_to_adls.py +++ b/viadot/flows/vid_club_to_adls.py @@ -59,7 +59,7 @@ def __init__( to_date (str, optional): End date for the query. Defaults to None. items_per_page (int, optional): Number of entries per page. Defaults to 100. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] - days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. + days_interval (int, optional): Days specified in date range per API call (test showed that 30-40 is optimal for performance). Defaults to 30. cols_to_drop (List[str], optional): List of columns to drop. Defaults to None. vid_club_credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. vidclub_credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". From 24391948aaae34b4c05ba2cffce66f7d6c3b597b Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 27 Jul 2023 10:18:10 +0200 Subject: [PATCH 102/106] Update to_date default value and docstring --- viadot/tasks/vid_club.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/viadot/tasks/vid_club.py b/viadot/tasks/vid_club.py index 06ec2c33f..0814a306f 100644 --- a/viadot/tasks/vid_club.py +++ b/viadot/tasks/vid_club.py @@ -25,7 +25,7 @@ def __init__( credentials_secret: str = "VIDCLUB", vault_name: str = None, from_date: str = "2022-03-22", - to_date: str = datetime.today(), + to_date: str = None, timeout: int = 3600, report_name: str = "vid_club_to_df", *args: List[Any], @@ -40,7 +40,7 @@ def __init__( credentials_secret (str, optional): The name of the secret in Azure Key Vault or Prefect or local_config file. Defaults to "VIDCLUB". vault_name (str, optional): For credentials stored in Azure Key Vault. The name of the vault from which to obtain the secret. Defaults to None. from_date (str): Start date for the query, by default is the oldest date in the data, '2022-03-22'. - to_date (str, optional): End date for the query. Defaults to datetime.today(). + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. timeout (int, optional): The amount of time (in seconds) to wait while running this task before a timeout occurs. Defaults to 3600. report_name (str, optional): Stores the report name. Defaults to "vid_club_to_df". @@ -96,7 +96,7 @@ def run( source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. credentials (Dict[str, Any], optional): Stores the credentials information. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data, '2022-03-22'. - to_date (str, optional): End date for the query. By default, datetime.today() will be used. + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (str, optional): Region filter for the query. Valid inputs: ["bg", "hu", "hr", "pl", "ro", "si", "all"]. Defaults to "all". days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. From 1faa2f3656479f291ab20a5d8921fde0d77a4677 Mon Sep 17 00:00:00 2001 From: "hha.ext" Date: Thu, 27 Jul 2023 10:21:06 +0200 Subject: [PATCH 103/106] Update to_date default value and docstring --- viadot/flows/vid_club_to_adls.py | 2 +- viadot/sources/vid_club.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/viadot/flows/vid_club_to_adls.py b/viadot/flows/vid_club_to_adls.py index 639e81653..6ff7f7bcd 100644 --- a/viadot/flows/vid_club_to_adls.py +++ b/viadot/flows/vid_club_to_adls.py @@ -56,7 +56,7 @@ def __init__( name (str): The name of the flow. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. - to_date (str, optional): End date for the query. Defaults to None. + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. items_per_page (int, optional): Number of entries per page. Defaults to 100. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] days_interval (int, optional): Days specified in date range per API call (test showed that 30-40 is optimal for performance). Defaults to 30. diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index eccda5b40..bf6455f0f 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -53,7 +53,7 @@ def build_query( Args: from_date (str): Start date for the query. - to_date (str): End date for the query, if empty, datetime.today() will be used. + to_date (str): End date for the query, if empty, will be executed as datetime.today().strftime("%Y-%m-%d"). api_url (str): Generic part of the URL to Vid Club API. items_per_page (int): number of entries per page. source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. @@ -83,7 +83,7 @@ def intervals( Args: from_date (str): Start date for the query in "%Y-%m-%d" format. - to_date (str): End date for the query in "%Y-%m-%d" format. By default, datetime.today() will be used. + to_date (str): End date for the query, if empty, will be executed as datetime.today().strftime("%Y-%m-%d"). days_interval (int): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Returns: @@ -138,7 +138,7 @@ def check_connection( Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. - to_date (str, optional): End date for the query. By default, datetime.today() will be used. + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] url (str, optional): Generic part of the URL to Vid Club API. Defaults to None. @@ -190,7 +190,7 @@ def get_response( Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. - to_date (str, optional): End date for the query. By default, datetime.today() will be used. + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] @@ -270,7 +270,7 @@ def total_load( Args: source (Literal["jobs", "product", "company", "survey"], optional): The endpoint source to be accessed. Defaults to None. from_date (str, optional): Start date for the query, by default is the oldest date in the data 2022-03-22. - to_date (str, optional): End date for the query. By default, datetime.today() will be used. + to_date (str, optional): End date for the query. By default None, which will be executed as datetime.today().strftime("%Y-%m-%d") in code. items_per_page (int, optional): Number of entries per page. 100 entries by default. region (Literal["bg", "hu", "hr", "pl", "ro", "si", "all"], optional): Region filter for the query. Defaults to "all". [July 2023 status: parameter works only for 'all' on API] days_interval (int, optional): Days specified in date range per api call (test showed that 30-40 is optimal for performance). Defaults to 30. From 90a71a7a18bdebfda9121482457d9afc7e5ee837 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 27 Jul 2023 08:30:45 +0000 Subject: [PATCH 104/106] =?UTF-8?q?=F0=9F=8E=A8=20Format=20Python=20code?= =?UTF-8?q?=20with=20Black?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/flows/test_vidclub_to_adls.py | 2 +- tests/integration/tasks/test_vid_club.py | 2 +- tests/integration/test_bigquery.py | 1 + tests/integration/test_vid_club.py | 5 ++--- viadot/flows/vid_club_to_adls.py | 4 ++-- viadot/sources/vid_club.py | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/integration/flows/test_vidclub_to_adls.py b/tests/integration/flows/test_vidclub_to_adls.py index bbf788808..a0c86c2ec 100644 --- a/tests/integration/flows/test_vidclub_to_adls.py +++ b/tests/integration/flows/test_vidclub_to_adls.py @@ -20,7 +20,7 @@ def test_vidclub_to_adls_run_flow(mocked_class): flow = VidClubToADLS( "test_vidclub_to_adls_flow_run", source=["test"], - from_date = "2023-06-05", + from_date="2023-06-05", overwrite_adls=True, adls_dir_path=ADLS_DIR_PATH, adls_file_name=ADLS_FILE_NAME, diff --git a/tests/integration/tasks/test_vid_club.py b/tests/integration/tasks/test_vid_club.py index d686f853d..8fad7fdde 100644 --- a/tests/integration/tasks/test_vid_club.py +++ b/tests/integration/tasks/test_vid_club.py @@ -3,8 +3,8 @@ import pandas as pd import pytest -from viadot.tasks import VidClubToDF from viadot.task_utils import credentials_loader +from viadot.tasks import VidClubToDF CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") diff --git a/tests/integration/test_bigquery.py b/tests/integration/test_bigquery.py index 8c69fc11a..f60092346 100644 --- a/tests/integration/test_bigquery.py +++ b/tests/integration/test_bigquery.py @@ -1,4 +1,5 @@ from typing import List + import pandas as pd import pandas_gbq import pytest diff --git a/tests/integration/test_vid_club.py b/tests/integration/test_vid_club.py index d6daadd47..6c2bd4544 100644 --- a/tests/integration/test_vid_club.py +++ b/tests/integration/test_vid_club.py @@ -1,13 +1,12 @@ +from datetime import datetime, timedelta from unittest import mock import pandas as pd import pytest -from datetime import datetime, timedelta from viadot.exceptions import ValidationError -from viadot.task_utils import credentials_loader from viadot.sources import VidClub - +from viadot.task_utils import credentials_loader CREDENTIALS = credentials_loader.run(credentials_secret="VIDCLUB") vc = VidClub(credentials=CREDENTIALS) diff --git a/viadot/flows/vid_club_to_adls.py b/viadot/flows/vid_club_to_adls.py index 6ff7f7bcd..59d676c51 100644 --- a/viadot/flows/vid_club_to_adls.py +++ b/viadot/flows/vid_club_to_adls.py @@ -1,8 +1,8 @@ import os from pathlib import Path from typing import Any, Dict, List, Literal -import pandas as pd +import pandas as pd import pendulum from prefect import Flow from prefect.backend import set_key_value @@ -143,7 +143,7 @@ def gen_flow(self) -> Flow: items_per_page=self.items_per_page, region=self.region, days_interval=self.days_interval, - cols_to_drop = self.cols_to_drop, + cols_to_drop=self.cols_to_drop, flow=self, ) diff --git a/viadot/sources/vid_club.py b/viadot/sources/vid_club.py index bf6455f0f..e7819577a 100644 --- a/viadot/sources/vid_club.py +++ b/viadot/sources/vid_club.py @@ -1,10 +1,10 @@ import json import os import urllib -from datetime import datetime, date, timedelta +from datetime import date, datetime, timedelta from typing import Any, Dict, List, Literal, Tuple -import pandas as pd +import pandas as pd from prefect.utilities import logging from ..exceptions import CredentialError, ValidationError From ea8f8157f932609ed2ab2ebfa929d5d7f7300546 Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Thu, 27 Jul 2023 11:52:29 +0200 Subject: [PATCH 105/106] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20tests=20for=20Bi?= =?UTF-8?q?gqueryToDF=20task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/integration/tasks/test_bigquery.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/tasks/test_bigquery.py b/tests/integration/tasks/test_bigquery.py index 963284e60..3cf184d85 100644 --- a/tests/integration/tasks/test_bigquery.py +++ b/tests/integration/tasks/test_bigquery.py @@ -17,10 +17,10 @@ def test_bigquery_to_df_success(): credentials_key=CREDENTIALS_KEY, ) df = bigquery_to_df_task.run() - expectation_columns = ["date", "name", "count", "refresh"] + expected_column = ["my_value"] assert isinstance(df, pd.DataFrame) - assert expectation_columns == list(df.columns) + assert expected_column == list(df.columns) def test_bigquery_to_df_wrong_table_name(caplog): @@ -46,7 +46,7 @@ def test_bigquery_to_df_wrong_column_name(caplog): with caplog.at_level(logging.WARNING): df = bigquery_to_df_task.run() assert f"'wrong_column_name' column is not recognized." in caplog.text - assert df.empty + assert isinstance(df, pd.DataFrame) def test_bigquery_to_df_wrong_query(caplog): From 2cdcea085843051ebaa00a926bd4389d8c224dee Mon Sep 17 00:00:00 2001 From: Rafalz13 Date: Thu, 27 Jul 2023 12:31:25 +0200 Subject: [PATCH 106/106] =?UTF-8?q?=F0=9F=93=9D=20Updated=20Changelog=20be?= =?UTF-8?q?fore=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d16baa752..5f21229d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,32 +4,39 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +### Fixed + ### Changed -- Added new parameters in the `GenesysToCSV` task to be able to extract `web message` files. + + +## [0.4.18] - 2023-07-27 ### Added - Added `SQLServerToParquet` flow. -- Added `SAPBW` source class -- Added `SAPBWToDF` task class -- Added `SAPBWToADLS` flow class +- Added `SAPBW` source class. +- Added `SAPBWToDF` task class. +- Added `SAPBWToADLS` flow class. - Added a new `end_point` parameter in `genesys_api_connection` to make it more generic. - Added `VidClubToADLS` flow class. ### Fixed -- Fixed a bug in `subject` (extra separator) and in `receivers` (long strings) parameters in Outlook connector. -- Fixed issue with credentials handling in `VidClub` source class -- Fixed issue with missing arguments in `VidClubToDF` task class - +- Fixed a bug in `subject` (extra separator) and in `receivers` (long strings) parameters in `Outlook` connector. +- Fixed issue with credentials handling in `VidClub` source class. +- Fixed issue with missing arguments in `VidClubToDF` task class. ### Changed - Genesys API call method and the name changed from `genesys_generate_exports` to `genesys_api_connection`. - Added `GET` connection inside the method `genesys_api_connection`. -- Changed looping structure for API calls in `VidClub` source class to use time intervals -- Changed `VidClubToDF` task class to use total_load function from source +- Added new parameters in the `GenesysToCSV` task to be able to extract `web message` files. +- Changed looping structure for API calls in `VidClub` source class to use time intervals. +- Changed `VidClubToDF` task class to use total_load function from source. ### Removed - Removed methods never used in production: `get_analitics_url_report`, `get_all_schedules_job`, `schedule_report`, `to_df`, `delete_scheduled_report_job` and `generate_reporting_export`. + ## [0.4.17] - 2023-06-15 ### Fixed - Fixed issue with `tzlocal` for O365 package

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