-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
Epicor
connector, tasks, and flow (#1002)
* π§ Added epicor prefect connector * π¨ Format code * π¨ Format code * π¨ Adjust code to pre-comit requirements * π¨ Adjust code to pre-comit requirements * π¨ Remove whitespace * π¨ Remove whitespace * π¨ Remove whitespace * π₯ removed credentials dict * π Fix a typo in import * π Updated docstrings * π¨ Moved `filters_xml` * β Add test for each epicor xml schema * π Update doctring with example * π§ Added epicor prefect connector * π¨ Format code * π¨ Format code * π¨ Adjust code to pre-comit requirements * π¨ Adjust code to pre-comit requirements * π¨ Remove whitespace * π¨ Remove whitespace * π¨ Remove whitespace * π₯ removed credentials dict * π Updated docstrings * π¨ Moved `filters_xml` * β Add test for each epicor xml schema * π Update doctring with example * π₯ remove unused code * π Bump viadot version --------- Co-authored-by: angelika233 <[email protected]>
- Loading branch information
1 parent
c8fe0e4
commit b0c4dac
Showing
11 changed files
with
781 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[project] | ||
name = "viadot2" | ||
version = "2.1.14" | ||
version = "2.1.15" | ||
description = "A simple data ingestion library to guide data flows from some places to other places." | ||
authors = [ | ||
{ name = "acivitillo", email = "[email protected]" }, | ||
|
@@ -32,6 +32,8 @@ dependencies = [ | |
"pyarrow>=10.0, <10.1.0", | ||
# numpy>=2.0 is not compatible with the old pyarrow v10.x. | ||
"numpy>=1.23.4, <2.0", | ||
"defusedxml>=0.7.1", | ||
|
||
] | ||
requires-python = ">=3.10" | ||
readme = "README.md" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
src/viadot/orchestration/prefect/flows/epicor_to_parquet.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
"""Flows for downloading data from Epicor Prelude API to Parquet file.""" | ||
|
||
from typing import Literal | ||
|
||
from prefect import flow | ||
|
||
from viadot.orchestration.prefect.tasks import epicor_to_df | ||
from viadot.orchestration.prefect.tasks.task_utils import df_to_parquet | ||
|
||
|
||
@flow( | ||
name="extract--epicor--parquet", | ||
description="Extract data from Epicor Prelude API and load it into Parquet file", | ||
retries=1, | ||
retry_delay_seconds=60, | ||
) | ||
def epicor_to_parquet( | ||
path: str, | ||
base_url: str, | ||
filters_xml: str, | ||
if_exists: Literal["append", "replace", "skip"] = "replace", | ||
validate_date_filter: bool = True, | ||
start_date_field: str = "BegInvoiceDate", | ||
end_date_field: str = "EndInvoiceDate", | ||
epicor_credentials_secret: str | None = None, | ||
epicor_config_key: str | None = None, | ||
) -> None: | ||
"""Download a pandas `DataFrame` from Epicor Prelude API load it into Parquet file. | ||
Args: | ||
path (str): Path to Parquet file, where the data will be located. | ||
Defaults to None. | ||
base_url (str, required): Base url to Epicor. | ||
filters_xml (str, required): Filters in form of XML. The date filter | ||
is required. | ||
if_exists (Literal["append", "replace", "skip"], optional): Information what | ||
has to be done, if the file exists. Defaults to "replace" | ||
validate_date_filter (bool, optional): Whether or not validate xml date filters. | ||
Defaults to True. | ||
start_date_field (str, optional) The name of filters field containing | ||
start date. Defaults to "BegInvoiceDate". | ||
end_date_field (str, optional) The name of filters field containing end date. | ||
Defaults to "EndInvoiceDate". | ||
epicor_credentials_secret (str, optional): The name of the secret storing | ||
the credentials. Defaults to None. | ||
More info on: https://docs.prefect.io/concepts/blocks/ | ||
epicor_config_key (str, optional): The key in the viadot config holding relevant | ||
credentials. Defaults to None. | ||
Examples: | ||
>>> epicor_to_parquet( | ||
>>> path = "my_parquet.parquet", | ||
>>> base_url = "/api/data/import/ORDER.QUERY", | ||
>>> filters_xml = "<OrderQuery> | ||
>>> <QueryFields> | ||
>>> <CompanyNumber>001</CompanyNumber> | ||
>>> <CustomerNumber></CustomerNumber> | ||
>>> <SellingWarehouse></SellingWarehouse> | ||
>>> <OrderNumber></OrderNumber> | ||
>>> <WrittenBy></WrittenBy> | ||
>>> <CustomerPurchaseOrderNumber></CustomerPurchaseOrderNumber> | ||
>>> <CustomerReleaseNumber></CustomerReleaseNumber> | ||
>>> <CustomerJobNumber></CustomerJobNumber> | ||
>>> <InvoiceNumber></InvoiceNumber> | ||
>>> <EcommerceId></EcommerceId> | ||
>>> <EcommerceOrderNumber></EcommerceOrderNumber> | ||
>>> <QuoteNumber></QuoteNumber> | ||
>>> <BegInvoiceDate>{yesterday}</BegInvoiceDate> | ||
>>> <EndInvoiceDate>{yesterday}</EndInvoiceDate> | ||
>>> <SortXMLTagName></SortXMLTagName> | ||
>>> <SortMethod></SortMethod> | ||
>>> <RecordCount></RecordCount> | ||
>>> <RecordCountPage></RecordCountPage> | ||
>>> </QueryFields> | ||
>>> </OrderQuery>", | ||
>>> epicor_config_key = "epicor" | ||
>>> ) | ||
""" | ||
df = epicor_to_df( | ||
base_url=base_url, | ||
filters_xml=filters_xml, | ||
validate_date_filter=validate_date_filter, | ||
start_date_field=start_date_field, | ||
end_date_field=end_date_field, | ||
credentials_secret=epicor_credentials_secret, | ||
config_key=epicor_config_key, | ||
) | ||
|
||
return df_to_parquet( | ||
df=df, | ||
path=path, | ||
if_exists=if_exists, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
"""Task for downloading data from Epicor Prelude API.""" | ||
|
||
import pandas as pd | ||
from prefect import task | ||
from prefect.logging import get_run_logger | ||
|
||
from viadot.config import get_source_credentials | ||
from viadot.orchestration.prefect.exceptions import MissingSourceCredentialsError | ||
from viadot.orchestration.prefect.utils import get_credentials | ||
from viadot.sources.epicor import Epicor | ||
|
||
|
||
@task(retries=3, retry_delay_seconds=10, timeout_seconds=60 * 60 * 3) | ||
def epicor_to_df( | ||
base_url: str, | ||
filters_xml: str, | ||
validate_date_filter: bool = True, | ||
start_date_field: str = "BegInvoiceDate", | ||
end_date_field: str = "EndInvoiceDate", | ||
credentials_secret: str | None = None, | ||
config_key: str | None = None, | ||
) -> pd.DataFrame: | ||
"""Load the data from Epicor Prelude API into a pandas DataFrame. | ||
Args: | ||
base_url (str, required): Base url to Epicor. | ||
filters_xml (str, required): Filters in form of XML. The date filter | ||
is required. | ||
validate_date_filter (bool, optional): Whether or not validate xml date filters. | ||
Defaults to True. | ||
start_date_field (str, optional) The name of filters field containing | ||
start date. Defaults to "BegInvoiceDate". | ||
end_date_field (str, optional) The name of filters field containing end date. | ||
Defaults to "EndInvoiceDate". | ||
credentials_secret (str, optional): The name of the secret storing | ||
the credentials. Defaults to None. | ||
More info on: https://docs.prefect.io/concepts/blocks/ | ||
config_key (str, optional): The key in the viadot config holding relevant | ||
credentials. Defaults to None. | ||
""" | ||
if not (credentials_secret or config_key): | ||
raise MissingSourceCredentialsError | ||
|
||
logger = get_run_logger() | ||
|
||
credentials = get_source_credentials(config_key) or get_credentials( | ||
credentials_secret | ||
) | ||
epicor = Epicor( | ||
credentials=credentials, | ||
base_url=base_url, | ||
validate_date_filter=validate_date_filter, | ||
start_date_field=start_date_field, | ||
end_date_field=end_date_field, | ||
) | ||
df = epicor.to_df(filters_xml=filters_xml) | ||
nrows = df.shape[0] | ||
ncols = df.shape[1] | ||
|
||
logger.info( | ||
f"Successfully downloaded {nrows} rows and {ncols} columns of data to a DataFrame." | ||
) | ||
return df |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.