diff --git a/.github/workflows/publish-command.yml b/.github/workflows/publish-command.yml index d34de21c4d5c91..0e79bbe2f854b3 100644 --- a/.github/workflows/publish-command.yml +++ b/.github/workflows/publish-command.yml @@ -122,6 +122,7 @@ jobs: SNOWFLAKE_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_INTEGRATION_TEST_CREDS }} SNOWFLAKE_S3_COPY_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_S3_COPY_INTEGRATION_TEST_CREDS }} SNOWFLAKE_GCS_COPY_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_GCS_COPY_INTEGRATION_TEST_CREDS }} + SOURCE_SQUARE_CREDS: ${{ secrets.SOURCE_SQUARE_CREDS }} SOURCE_MARKETO_SINGER_INTEGRATION_TEST_CONFIG: ${{ secrets.SOURCE_MARKETO_SINGER_INTEGRATION_TEST_CONFIG }} SOURCE_RECURLY_INTEGRATION_TEST_CREDS: ${{ secrets.SOURCE_RECURLY_INTEGRATION_TEST_CREDS }} STRIPE_INTEGRATION_TEST_CREDS: ${{ secrets.STRIPE_INTEGRATION_TEST_CREDS }} diff --git a/.github/workflows/test-command.yml b/.github/workflows/test-command.yml index 250093f37ca13e..7b9f3983ee8ccd 100644 --- a/.github/workflows/test-command.yml +++ b/.github/workflows/test-command.yml @@ -120,6 +120,7 @@ jobs: SNOWFLAKE_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_INTEGRATION_TEST_CREDS }} SNOWFLAKE_S3_COPY_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_S3_COPY_INTEGRATION_TEST_CREDS }} SNOWFLAKE_GCS_COPY_INTEGRATION_TEST_CREDS: ${{ secrets.SNOWFLAKE_GCS_COPY_INTEGRATION_TEST_CREDS }} + SOURCE_SQUARE_CREDS: ${{ secrets.SOURCE_SQUARE_CREDS }} SOURCE_MARKETO_SINGER_INTEGRATION_TEST_CONFIG: ${{ secrets.SOURCE_MARKETO_SINGER_INTEGRATION_TEST_CONFIG }} SOURCE_RECURLY_INTEGRATION_TEST_CREDS: ${{ secrets.SOURCE_RECURLY_INTEGRATION_TEST_CREDS }} STRIPE_INTEGRATION_TEST_CREDS: ${{ secrets.STRIPE_INTEGRATION_TEST_CREDS }} diff --git a/airbyte-config/init/src/main/resources/config/STANDARD_SOURCE_DEFINITION/77225a51-cd15-4a13-af02-65816bd0ecf4.json b/airbyte-config/init/src/main/resources/config/STANDARD_SOURCE_DEFINITION/77225a51-cd15-4a13-af02-65816bd0ecf4.json new file mode 100644 index 00000000000000..d10a442f9c0481 --- /dev/null +++ b/airbyte-config/init/src/main/resources/config/STANDARD_SOURCE_DEFINITION/77225a51-cd15-4a13-af02-65816bd0ecf4.json @@ -0,0 +1,7 @@ +{ + "sourceDefinitionId": "77225a51-cd15-4a13-af02-65816bd0ecf4", + "name": "Square", + "dockerRepository": "airbyte/source-square", + "dockerImageTag": "0.1.0", + "documentationUrl": "https://docs.airbyte.io/integrations/sources/square" +} diff --git a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml index 848a7a05c5eb8a..c52e2c5cd90c32 100644 --- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml @@ -348,3 +348,8 @@ dockerRepository: airbyte/source-okta dockerImageTag: 0.1.2 documentationUrl: https://docs.airbyte.io/integrations/sources/okta +- sourceDefinitionId: 77225a51-cd15-4a13-af02-65816bd0ecf4 + name: Square + dockerRepository: airbyte/source-square + dockerImageTag: 0.1.0 + documentationUrl: https://docs.airbyte.io/integrations/sources/square diff --git a/airbyte-integrations/builds.md b/airbyte-integrations/builds.md index a5362365989ed7..a38a0e751041f7 100644 --- a/airbyte-integrations/builds.md +++ b/airbyte-integrations/builds.md @@ -103,6 +103,8 @@ Snowflake [![source-snowflake](https://img.shields.io/endpoint?url=https%3A%2F%2Fstatus-api.airbyte.io%2Ftests%2Fsummary%2Fsource-snowflake%2Fbadge.json)](https://status-api.airbyte.io/tests/summary/source-snowflake) + Square [![source-square](https://img.shields.io/endpoint?url=https%3A%2F%2Fstatus-api.airbyte.io%2Ftests%2Fsummary%2Fsource-square%2Fbadge.json)](https://status-api.airbyte.io/tests/summary/source-square) + Stripe [![source-stripe](https://img.shields.io/endpoint?url=https%3A%2F%2Fstatus-api.airbyte.io%2Ftests%2Fsummary%2Fsource-stripe%2Fbadge.json)](https://status-api.airbyte.io/tests/summary/source-stripe) Tempo [![source-tempo](https://img.shields.io/endpoint?url=https%3A%2F%2Fstatus-api.airbyte.io%2Ftests%2Fsummary%2Fsource-tempo%2Fbadge.json)](https://status-api.airbyte.io/tests/summary/source-tempo) diff --git a/airbyte-integrations/connectors/source-square/.dockerignore b/airbyte-integrations/connectors/source-square/.dockerignore new file mode 100644 index 00000000000000..ca1960f9bcfdaa --- /dev/null +++ b/airbyte-integrations/connectors/source-square/.dockerignore @@ -0,0 +1,7 @@ +* +!Dockerfile +!Dockerfile.test +!main.py +!source_square +!setup.py +!secrets diff --git a/airbyte-integrations/connectors/source-square/Dockerfile b/airbyte-integrations/connectors/source-square/Dockerfile new file mode 100644 index 00000000000000..eb8116a4578950 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.7-slim + +# Bash is installed for more convenient debugging. +RUN apt-get update && apt-get install -y bash && rm -rf /var/lib/apt/lists/* + +WORKDIR /airbyte/integration_code +COPY source_square ./source_square +COPY main.py ./ +COPY setup.py ./ +RUN pip install . + +ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" +ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] + +LABEL io.airbyte.version=0.1.0 +LABEL io.airbyte.name=airbyte/source-square diff --git a/airbyte-integrations/connectors/source-square/README.md b/airbyte-integrations/connectors/source-square/README.md new file mode 100644 index 00000000000000..19f698a729e9f8 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/README.md @@ -0,0 +1,131 @@ +# Square Source + +This is the repository for the Square source connector, written in Python. +For information about how to use this connector within Airbyte, see [the documentation](https://docs.airbyte.io/integrations/sources/square). + +## Local development + +### Prerequisites +**To iterate on this connector, make sure to complete this prerequisites section.** + +#### Minimum Python version required `= 3.7.0` + +#### Build & Activate Virtual Environment and install dependencies +From this connector directory, create a virtual environment: +``` +python -m venv .venv +``` + +This will generate a virtualenv for this module in `.venv/`. Make sure this venv is active in your +development environment of choice. To activate it from the terminal, run: +``` +source .venv/bin/activate +pip install -r requirements.txt +``` +If you are in an IDE, follow your IDE's instructions to activate the virtualenv. + +Note that while we are installing dependencies from `requirements.txt`, you should only edit `setup.py` for your dependencies. `requirements.txt` is +used for editable installs (`pip install -e`) to pull in Python dependencies from the monorepo and will call `setup.py`. +If this is mumbo jumbo to you, don't worry about it, just put your deps in `setup.py` but install using `pip install -r requirements.txt` and everything +should work as you expect. + +#### Building via Gradle +You can also build the connector in Gradle. This is typically used in CI and not needed for your development workflow. + +To build using Gradle, from the Airbyte repository root, run: +``` +./gradlew :airbyte-integrations:connectors:source-square:build +``` + +#### Create credentials +**If you are a community contributor**, follow the instructions in the [documentation](https://docs.airbyte.io/integrations/sources/square) +to generate the necessary credentials. Then create a file `secrets/config.json` conforming to the `source_square/spec.json` file. +Note that any directory named `secrets` is gitignored across the entire Airbyte repo, so there is no danger of accidentally checking in sensitive information. +See `integration_tests/sample_config.json` for a sample config file. + +**If you are an Airbyte core member**, copy the credentials in Lastpass under the secret name `source square test creds` +and place them into `secrets/config.json`. + +### Locally running the connector +``` +python main.py spec +python main.py check --config secrets/config.json +python main.py discover --config secrets/config.json +python main.py read --config secrets/config.json --catalog integration_tests/configured_catalog.json +``` + +### Locally running the connector docker image + +#### Build +First, make sure you build the latest Docker image: +``` +docker build . -t airbyte/source-square:dev +``` + +You can also build the connector image via Gradle: +``` +./gradlew :airbyte-integrations:connectors:source-square:airbyteDocker +``` +When building via Gradle, the docker image name and tag, respectively, are the values of the `io.airbyte.name` and `io.airbyte.version` `LABEL`s in +the Dockerfile. + +#### Run +Then run any of the connector commands as follows: +``` +docker run --rm airbyte/source-square:dev spec +docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-square:dev check --config /secrets/config.json +docker run --rm -v $(pwd)/secrets:/secrets airbyte/source-square:dev discover --config /secrets/config.json +docker run --rm -v $(pwd)/secrets:/secrets -v $(pwd)/integration_tests:/integration_tests airbyte/source-square:dev read --config /secrets/config.json --catalog /integration_tests/configured_catalog.json +``` +## Testing +Make sure to familiarize yourself with [pytest test discovery](https://docs.pytest.org/en/latest/goodpractices.html#test-discovery) to know how your test files and methods should be named. +First install test dependencies into your virtual environment: +``` +pip install .[tests] +``` +### Unit Tests +To run unit tests locally, from the connector directory run: +``` +python -m pytest unit_tests +``` + +### Integration Tests +There are two types of integration tests: Acceptance Tests (Airbyte's test suite for all source connectors) and custom integration tests (which are specific to this connector). +#### Custom Integration tests +Place custom tests inside `integration_tests/` folder, then, from the connector root, run +``` +python -m pytest integration_tests +``` +#### Acceptance Tests +Customize `acceptance-test-config.yml` file to configure tests. See [Source Acceptance Tests](source-acceptance-tests.md) for more information. +If your connector requires to create or destroy resources for use during acceptance tests create fixtures for it and place them inside integration_tests/acceptance.py. +To run your integration tests with acceptance tests, from the connector root, run +``` +python -m pytest integration_tests -p integration_tests.acceptance +``` +To run your integration tests with docker + +### Using gradle to run tests +All commands should be run from airbyte project root. +To run unit tests: +``` +./gradlew :airbyte-integrations:connectors:source-square:unitTest +``` +To run acceptance and custom integration tests: +``` +./gradlew :airbyte-integrations:connectors:source-square:integrationTest +``` + +## Dependency Management +All of your dependencies should go in `setup.py`, NOT `requirements.txt`. The requirements file is only used to connect internal Airbyte dependencies in the monorepo for local development. +We split dependencies between two groups, dependencies that are: +* required for your connector to work need to go to `MAIN_REQUIREMENTS` list. +* required for the testing need to go to `TEST_REQUIREMENTS` list + +### Publishing a new version of the connector +You've checked out the repo, implemented a million dollar feature, and you're ready to share your changes with the world. Now what? +1. Make sure your changes are passing unit and integration tests. +1. Bump the connector version in `Dockerfile` -- just increment the value of the `LABEL io.airbyte.version` appropriately (we use [SemVer](https://semver.org/)). +1. Create a Pull Request. +1. Pat yourself on the back for being an awesome contributor. +1. Someone from Airbyte will take a look at your PR and iterate with you to merge it into master. diff --git a/airbyte-integrations/connectors/source-square/acceptance-test-config.yml b/airbyte-integrations/connectors/source-square/acceptance-test-config.yml new file mode 100644 index 00000000000000..07585ea6a8cf3a --- /dev/null +++ b/airbyte-integrations/connectors/source-square/acceptance-test-config.yml @@ -0,0 +1,22 @@ +connector_image: airbyte/source-square:dev +tests: + spec: + - spec_path: "source_square/spec.json" + connection: + - config_path: "secrets/config.json" + status: "succeed" + - config_path: "integration_tests/invalid_config.json" + status: "failed" + discovery: + - config_path: "secrets/config.json" + basic_read: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" + validate_output_from_all_streams: yes + incremental: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" + future_state_path: "integration_tests/abnormal_state.json" + full_refresh: + - config_path: "secrets/config.json" + configured_catalog_path: "integration_tests/configured_catalog.json" diff --git a/airbyte-integrations/connectors/source-square/acceptance-test-docker.sh b/airbyte-integrations/connectors/source-square/acceptance-test-docker.sh new file mode 100755 index 00000000000000..1425ff74f15112 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/acceptance-test-docker.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh +docker run --rm -it \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /tmp:/tmp \ + -v $(pwd):/test_input \ + airbyte/source-acceptance-test \ + --acceptance-test-config /test_input diff --git a/airbyte-integrations/connectors/source-square/build.gradle b/airbyte-integrations/connectors/source-square/build.gradle new file mode 100644 index 00000000000000..bb09f0af06d430 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/build.gradle @@ -0,0 +1,14 @@ +plugins { + id 'airbyte-python' + id 'airbyte-docker' + id 'airbyte-source-acceptance-test' +} + +airbytePython { + moduleDirectory 'source_square' +} + +dependencies { + implementation files(project(':airbyte-integrations:bases:source-acceptance-test').airbyteDocker.outputs) + implementation files(project(':airbyte-integrations:bases:base-python').airbyteDocker.outputs) +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/__init__.py b/airbyte-integrations/connectors/source-square/integration_tests/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/airbyte-integrations/connectors/source-square/integration_tests/abnormal_state.json b/airbyte-integrations/connectors/source-square/integration_tests/abnormal_state.json new file mode 100644 index 00000000000000..412f778cf1061b --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/abnormal_state.json @@ -0,0 +1,23 @@ +{ + "items": { + "updated_at": "2200-01-01T00:00:00+00:00" + }, + "categories": { + "updated_at": "2200-01-01T00:00:00+00:00" + }, + "discounts": { + "updated_at": "2200-01-01T00:00:00+00:00" + }, + "taxes": { + "updated_at": "2200-01-01T00:00:00+00:00" + }, + "modifier_list": { + "updated_at": "2200-01-01T00:00:00+00:00" + }, + "refunds": { + "created_at": "2200-01-01T00:00:00+00:00" + }, + "payments": { + "created_at": "2200-01-01T00:00:00+00:00" + } +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/acceptance.py b/airbyte-integrations/connectors/source-square/integration_tests/acceptance.py new file mode 100644 index 00000000000000..d6cbdc97c495c2 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/acceptance.py @@ -0,0 +1,34 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + + +import pytest + +pytest_plugins = ("source_acceptance_test.plugin",) + + +@pytest.fixture(scope="session", autouse=True) +def connector_setup(): + """ This fixture is a placeholder for external resources that acceptance test might require.""" + yield diff --git a/airbyte-integrations/connectors/source-square/integration_tests/configured_catalog.json b/airbyte-integrations/connectors/source-square/integration_tests/configured_catalog.json new file mode 100644 index 00000000000000..53a0cbc1754aa3 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/configured_catalog.json @@ -0,0 +1,2074 @@ +{ + "streams": [ + { + "stream": { + "name": "items", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "custom_attribute_values": { + "type": ["null", "object"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "category_id": { + "type": ["null", "string"] + }, + "modifier_list_info": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "modifier_list_id": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "min_selected_modifiers": { + "type": ["null", "integer"] + }, + "max_selected_modifiers": { + "type": ["null", "integer"] + }, + "enabled": { + "type": ["null", "boolean"] + } + } + } + }, + "variations": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_variation_data": { + "type": ["null", "object"], + "properties": { + "item_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "sku": { + "type": ["null", "string"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "pricing_type": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "location_overrides": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "location_id": { + "type": ["null", "string"] + }, + "track_inventory": { + "type": ["null", "boolean"] + } + } + } + }, + "item_option_values": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + }, + "item_option_value_id": { + "type": ["null", "string"] + } + } + } + } + } + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + } + }, + "product_type": { + "type": ["null", "string"] + }, + "skip_modifier_screen": { + "type": ["null", "boolean"] + }, + "item_options": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + } + } + } + }, + "ecom_visibility": { + "type": ["null", "string"] + }, + "tax_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "image_id": { + "type": ["null", "string"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "categories", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "category_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "discounts", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "discount_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "discount_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "application_method": { + "type": ["null", "string"] + }, + "modify_tax_basis": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "pin_required": { + "type": ["null", "boolean"] + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "taxes", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "tax_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "inclusion_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applies_to_custom_amounts": { + "type": ["null", "boolean"] + }, + "enabled": { + "type": ["null", "boolean"] + }, + "tax_type_id": { + "type": ["null", "string"] + }, + "tax_type_name": { + "type": ["null", "string"] + } + } + }, + "absent_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "locations", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + } + } + }, + "timezone": { + "type": ["null", "string"] + }, + "capabilities": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "status": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "merchant_id": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "language_code": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "business_name": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "website_url": { + "type": ["null", "string"] + }, + "business_hours": { + "type": ["null", "object"] + }, + "business_email": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "twitter_username": { + "type": ["null", "string"] + }, + "instagram_username": { + "type": ["null", "string"] + }, + "facebook_url": { + "type": ["null", "string"] + }, + "mcc": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "team_members", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "is_owner": { + "type": ["null", "boolean"] + }, + "status": { + "type": ["null", "string"] + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "assigned_locations": { + "type": ["null", "object"], + "properties": { + "assignment_type": { + "type": ["null", "string"] + } + } + }, + "reference_id": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "team_member_wages", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "refunds", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["created_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["created_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "payments", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + }, + "delay_duration": { + "type": ["null", "string"] + }, + "source_type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "card_type": { + "type": ["null", "string"] + }, + "prepaid_type": { + "type": ["null", "string"] + }, + "bin": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + }, + "cvv_status": { + "type": ["null", "string"] + }, + "avs_status": { + "type": ["null", "string"] + }, + "statement_description": { + "type": ["null", "string"] + }, + "card_payment_timeline": { + "type": ["null", "object"], + "properties": { + "authorized_at": { + "type": ["null", "string"] + }, + "captured_at": { + "type": ["null", "string"] + }, + "voided_at": { + "type": ["null", "string"] + } + } + } + } + }, + "location_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "risk_evaluation": { + "type": ["null", "object"], + "properties": { + "created_at": { + "type": ["null", "string"] + }, + "risk_level": { + "type": ["null", "string"] + } + } + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "approved_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "receipt_number": { + "type": ["null", "string"] + }, + "receipt_url": { + "type": ["null", "string"] + }, + "delay_action": { + "type": ["null", "string"] + }, + "delayed_until": { + "type": ["null", "string"] + }, + "version_token": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "refunded_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "refund_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["created_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["created_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "customers", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "cards": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "cardholder_name": { + "type": ["null", "string"] + }, + "billing_address": { + "type": ["null", "object"], + "properties": { + "postal_code": { + "type": ["null", "string"] + } + } + } + } + } + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "address_line_2": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + }, + "phone_number": { + "type": ["null", "string"] + }, + "reference_id": { + "type": ["null", "string"] + }, + "company_name": { + "type": ["null", "string"] + }, + "preferences": { + "type": ["null", "object"], + "properties": { + "email_unsubscribed": { + "type": "boolean" + } + } + }, + "creation_source": { + "type": ["null", "string"] + }, + "birthday": { + "type": ["null", "string"] + }, + "segment_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "group_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "version": { + "type": ["null", "integer"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "modifier_list", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_list_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "selection_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "on_by_default": { + "type": ["null", "boolean"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "modifier_list_id": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "shifts", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "timezone": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "wage": { + "type": ["null", "object"], + "properties": { + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "breaks": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "break_type_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "expected_duration": { + "type": ["null", "string"] + }, + "is_paid": { + "type": ["null", "boolean"] + } + } + } + }, + "status": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "orders", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "variation_name": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_sales_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "item_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "name": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + } + } + } + }, + "applied_discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "discount_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "applied_taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "tax_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "fulfillments": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "pickup_details": { + "type": ["null", "object"], + "properties": { + "expires_at": { + "type": ["null", "string"] + }, + "pickup_at": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "accepted_at": { + "type": ["null", "string"] + }, + "ready_at": { + "type": ["null", "string"] + }, + "schedule_type": { + "type": ["null", "string"] + }, + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } + }, + "auto_complete_duration": { + "type": ["null", "string"] + }, + "picked_up_at": { + "type": ["null", "string"] + } + } + }, + "shipment_details": { + "type": ["null", "object"], + "properties": { + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + } + } + }, + "carrier": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "packaged_at": { + "type": ["null", "string"] + }, + "shipped_at": { + "type": ["null", "string"] + }, + "expected_shipped_at": { + "type": ["null", "string"] + }, + "in_progress_at": { + "type": ["null", "string"] + } + } + } + } + } + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "closed_at": { + "type": ["null", "string"] + }, + "tenders": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] + }, + "cash_details": { + "type": ["null", "object"], + "properties": { + "buyer_tendered_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "change_back_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "total_service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "net_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "source": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + }, + "returns": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "source_order_id": { + "type": ["null", "string"] + }, + "return_line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "item_type": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_return_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + }, + "return_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "refunds": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "tender_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + } + } + } + }, + "service_charges": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "scope": { + "type": ["null", "string"] + } + } + } + }, + "taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "scope": { + "type": ["null", "string"] + } + } + } + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/invalid_config.json b/airbyte-integrations/connectors/source-square/integration_tests/invalid_config.json new file mode 100644 index 00000000000000..b679b36c8db8f0 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/invalid_config.json @@ -0,0 +1,6 @@ +{ + "api_key": "API_KEY", + "is_sandbox": true, + "start_date": "START_DATE", + "include_deleted_objects": false +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/state.json b/airbyte-integrations/connectors/source-square/integration_tests/state.json new file mode 100644 index 00000000000000..0a5873d5af3011 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/state.json @@ -0,0 +1,23 @@ +{ + "items": { + "updated_at": "1970-01-01T00:00:00+00:00" + }, + "categories": { + "updated_at": "1970-01-01T00:00:00+00:00" + }, + "discounts": { + "updated_at": "1970-01-01T00:00:00+00:00" + }, + "taxes": { + "updated_at": "1970-01-01T00:00:00+00:00" + }, + "modifier_list": { + "updated_at": "1970-01-01T00:00:00+00:00" + }, + "refunds": { + "created_at": "1970-01-01T00:00:00+00:00" + }, + "payments": { + "created_at": "1970-01-01T00:00:00+00:00" + } +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/categories.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/categories.json new file mode 100644 index 00000000000000..0fe7bc92c8dc1c --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/categories.json @@ -0,0 +1,46 @@ +{ + "streams": [ + { + "stream": { + "name": "categories", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "category_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/customers.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/customers.json new file mode 100644 index 00000000000000..da06d2cf10ce56 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/customers.json @@ -0,0 +1,130 @@ +{ + "streams": [ + { + "stream": { + "name": "customers", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "cards": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "cardholder_name": { + "type": ["null", "string"] + }, + "billing_address": { + "type": ["null", "object"], + "properties": { + "postal_code": { + "type": ["null", "string"] + } + } + } + } + } + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "address_line_2": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + }, + "phone_number": { + "type": ["null", "string"] + }, + "reference_id": { + "type": ["null", "string"] + }, + "company_name": { + "type": ["null", "string"] + }, + "preferences": { + "type": ["null", "object"], + "properties": { + "email_unsubscribed": { + "type": "boolean" + } + } + }, + "creation_source": { + "type": ["null", "string"] + }, + "birthday": { + "type": ["null", "string"] + }, + "segment_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "group_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "version": { + "type": ["null", "integer"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/discounts.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/discounts.json new file mode 100644 index 00000000000000..2c645f446fffa6 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/discounts.json @@ -0,0 +1,78 @@ +{ + "streams": [ + { + "stream": { + "name": "discounts", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "discount_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "discount_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "application_method": { + "type": ["null", "string"] + }, + "modify_tax_basis": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "pin_required": { + "type": ["null", "boolean"] + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/items.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/items.json new file mode 100644 index 00000000000000..7ce87281a4b7b4 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/items.json @@ -0,0 +1,207 @@ +{ + "streams": [ + { + "stream": { + "name": "items", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "custom_attribute_values": { + "type": ["null", "object"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "category_id": { + "type": ["null", "string"] + }, + "modifier_list_info": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "modifier_list_id": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "min_selected_modifiers": { + "type": ["null", "integer"] + }, + "max_selected_modifiers": { + "type": ["null", "integer"] + }, + "enabled": { + "type": ["null", "boolean"] + } + } + } + }, + "variations": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_variation_data": { + "type": ["null", "object"], + "properties": { + "item_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "sku": { + "type": ["null", "string"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "pricing_type": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "location_overrides": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "location_id": { + "type": ["null", "string"] + }, + "track_inventory": { + "type": ["null", "boolean"] + } + } + } + }, + "item_option_values": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + }, + "item_option_value_id": { + "type": ["null", "string"] + } + } + } + } + } + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + } + }, + "product_type": { + "type": ["null", "string"] + }, + "skip_modifier_screen": { + "type": ["null", "boolean"] + }, + "item_options": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + } + } + } + }, + "ecom_visibility": { + "type": ["null", "string"] + }, + "tax_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "image_id": { + "type": ["null", "string"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/locations.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/locations.json new file mode 100644 index 00000000000000..f26ad5fdbe2954 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/locations.json @@ -0,0 +1,106 @@ +{ + "streams": [ + { + "stream": { + "name": "locations", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + } + } + }, + "timezone": { + "type": ["null", "string"] + }, + "capabilities": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "status": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "merchant_id": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "language_code": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "business_name": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "website_url": { + "type": ["null", "string"] + }, + "business_hours": { + "type": ["null", "object"] + }, + "business_email": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "twitter_username": { + "type": ["null", "string"] + }, + "instagram_username": { + "type": ["null", "string"] + }, + "facebook_url": { + "type": ["null", "string"] + }, + "mcc": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/modifier_list.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/modifier_list.json new file mode 100644 index 00000000000000..cd0f4f1f1c8b6a --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/modifier_list.json @@ -0,0 +1,103 @@ +{ + "streams": [ + { + "stream": { + "name": "modifier_list", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_list_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "selection_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "on_by_default": { + "type": ["null", "boolean"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "modifier_list_id": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/orders.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/orders.json new file mode 100644 index 00000000000000..c4bef27551a64f --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/orders.json @@ -0,0 +1,886 @@ +{ + "streams": [ + { + "stream": { + "name": "orders", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "variation_name": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_sales_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "item_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "name": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + } + } + } + }, + "applied_discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "discount_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "applied_taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "tax_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "fulfillments": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "pickup_details": { + "type": ["null", "object"], + "properties": { + "expires_at": { + "type": ["null", "string"] + }, + "pickup_at": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "accepted_at": { + "type": ["null", "string"] + }, + "ready_at": { + "type": ["null", "string"] + }, + "schedule_type": { + "type": ["null", "string"] + }, + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } + }, + "auto_complete_duration": { + "type": ["null", "string"] + }, + "picked_up_at": { + "type": ["null", "string"] + } + } + }, + "shipment_details": { + "type": ["null", "object"], + "properties": { + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + } + } + }, + "carrier": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "packaged_at": { + "type": ["null", "string"] + }, + "shipped_at": { + "type": ["null", "string"] + }, + "expected_shipped_at": { + "type": ["null", "string"] + }, + "in_progress_at": { + "type": ["null", "string"] + } + } + } + } + } + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "closed_at": { + "type": ["null", "string"] + }, + "tenders": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] + }, + "cash_details": { + "type": ["null", "object"], + "properties": { + "buyer_tendered_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "change_back_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "total_service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "net_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "source": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + }, + "returns": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "source_order_id": { + "type": ["null", "string"] + }, + "return_line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "item_type": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_return_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + }, + "return_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "refunds": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "tender_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + } + } + } + }, + "service_charges": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "scope": { + "type": ["null", "string"] + } + } + } + }, + "taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "scope": { + "type": ["null", "string"] + } + } + } + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/payments.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/payments.json new file mode 100644 index 00000000000000..2922a151a79c49 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/payments.json @@ -0,0 +1,214 @@ +{ + "streams": [ + { + "stream": { + "name": "payments", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + }, + "delay_duration": { + "type": ["null", "string"] + }, + "source_type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "card_type": { + "type": ["null", "string"] + }, + "prepaid_type": { + "type": ["null", "string"] + }, + "bin": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + }, + "cvv_status": { + "type": ["null", "string"] + }, + "avs_status": { + "type": ["null", "string"] + }, + "statement_description": { + "type": ["null", "string"] + }, + "card_payment_timeline": { + "type": ["null", "object"], + "properties": { + "authorized_at": { + "type": ["null", "string"] + }, + "captured_at": { + "type": ["null", "string"] + }, + "voided_at": { + "type": ["null", "string"] + } + } + } + } + }, + "location_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "risk_evaluation": { + "type": ["null", "object"], + "properties": { + "created_at": { + "type": ["null", "string"] + }, + "risk_level": { + "type": ["null", "string"] + } + } + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "approved_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "receipt_number": { + "type": ["null", "string"] + }, + "receipt_url": { + "type": ["null", "string"] + }, + "delay_action": { + "type": ["null", "string"] + }, + "delayed_until": { + "type": ["null", "string"] + }, + "version_token": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "refunded_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "refund_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["created_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["created_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/refunds.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/refunds.json new file mode 100644 index 00000000000000..3309362bdfe44e --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/refunds.json @@ -0,0 +1,80 @@ +{ + "streams": [ + { + "stream": { + "name": "refunds", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["created_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["created_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/shifts.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/shifts.json new file mode 100644 index 00000000000000..0e9c8ba3626d95 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/shifts.json @@ -0,0 +1,101 @@ +{ + "streams": [ + { + "stream": { + "name": "shifts", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "timezone": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "wage": { + "type": ["null", "object"], + "properties": { + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "breaks": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "break_type_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "expected_duration": { + "type": ["null", "string"] + }, + "is_paid": { + "type": ["null", "boolean"] + } + } + } + }, + "status": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/taxes.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/taxes.json new file mode 100644 index 00000000000000..bd1d45e123c701 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/taxes.json @@ -0,0 +1,73 @@ +{ + "streams": [ + { + "stream": { + "name": "taxes", + "json_schema": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "tax_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "inclusion_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applies_to_custom_amounts": { + "type": ["null", "boolean"] + }, + "enabled": { + "type": ["null", "boolean"] + }, + "tax_type_id": { + "type": ["null", "string"] + }, + "tax_type_name": { + "type": ["null", "string"] + } + } + }, + "absent_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "supported_sync_modes": ["incremental", "full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["updated_at"] + }, + "sync_mode": "incremental", + "cursor_field": ["updated_at"], + "destination_sync_mode": "append" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_member_wages.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_member_wages.json new file mode 100644 index 00000000000000..1dfc117361393d --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_member_wages.json @@ -0,0 +1,40 @@ +{ + "streams": [ + { + "stream": { + "name": "team_member_wages", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_members.json b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_members.json new file mode 100644 index 00000000000000..5bf462a9c4d566 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/integration_tests/test_streams/team_members.json @@ -0,0 +1,58 @@ +{ + "streams": [ + { + "stream": { + "name": "team_members", + "json_schema": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "is_owner": { + "type": ["null", "boolean"] + }, + "status": { + "type": ["null", "string"] + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "assigned_locations": { + "type": ["null", "object"], + "properties": { + "assignment_type": { + "type": ["null", "string"] + } + } + }, + "reference_id": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } + }, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": true, + "default_cursor_field": ["id"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["id"], + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-square/main.py b/airbyte-integrations/connectors/source-square/main.py new file mode 100644 index 00000000000000..38e4472c46132e --- /dev/null +++ b/airbyte-integrations/connectors/source-square/main.py @@ -0,0 +1,33 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + + +import sys + +from airbyte_cdk.entrypoint import launch +from source_square import SourceSquare + +if __name__ == "__main__": + source = SourceSquare() + launch(source, sys.argv[1:]) diff --git a/airbyte-integrations/connectors/source-square/requirements.txt b/airbyte-integrations/connectors/source-square/requirements.txt new file mode 100644 index 00000000000000..0411042aa0911f --- /dev/null +++ b/airbyte-integrations/connectors/source-square/requirements.txt @@ -0,0 +1,2 @@ +-e ../../bases/source-acceptance-test +-e . diff --git a/airbyte-integrations/connectors/source-square/setup.py b/airbyte-integrations/connectors/source-square/setup.py new file mode 100644 index 00000000000000..37ce791d5f50dc --- /dev/null +++ b/airbyte-integrations/connectors/source-square/setup.py @@ -0,0 +1,48 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + + +from setuptools import find_packages, setup + +MAIN_REQUIREMENTS = [ + "airbyte-cdk", +] + +TEST_REQUIREMENTS = [ + "pytest~=6.1", + "source-acceptance-test", +] + +setup( + name="source_square", + description="Source implementation for Square.", + author="Airbyte", + author_email="contact@airbyte.io", + packages=find_packages(), + install_requires=MAIN_REQUIREMENTS, + package_data={"": ["*.json", "schemas/*.json", "schemas/shared/*.json"]}, + extras_require={ + "tests": TEST_REQUIREMENTS, + }, +) diff --git a/airbyte-integrations/connectors/source-square/source_square/__init__.py b/airbyte-integrations/connectors/source-square/source_square/__init__.py new file mode 100644 index 00000000000000..2876bb61117e93 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/__init__.py @@ -0,0 +1,27 @@ +""" +MIT License + +Copyright (c) 2020 Airbyte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from .source import SourceSquare + +__all__ = ["SourceSquare"] diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/TODO.md b/airbyte-integrations/connectors/source-square/source_square/schemas/TODO.md new file mode 100644 index 00000000000000..cf1efadb3c9c9b --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/TODO.md @@ -0,0 +1,25 @@ +# TODO: Define your stream schemas +Your connector must describe the schema of each stream it can output using [JSONSchema](https://json-schema.org). + +The simplest way to do this is to describe the schema of your streams using one `.json` file per stream. You can also dynamically generate the schema of your stream in code, or you can combine both approaches: start with a `.json` file and dynamically add properties to it. + +The schema of a stream is the return value of `Stream.get_json_schema`. + +## Static schemas +By default, `Stream.get_json_schema` reads a `.json` file in the `schemas/` directory whose name is equal to the value of the `Stream.name` property. In turn `Stream.name` by default returns the name of the class in snake case. Therefore, if you have a class `class EmployeeBenefits(HttpStream)` the default behavior will look for a file called `schemas/employee_benefits.json`. You can override any of these behaviors as you need. + +Important note: any objects referenced via `$ref` should be placed in the `shared/` directory in their own `.json` files. + +## Dynamic schemas +If you'd rather define your schema in code, override `Stream.get_json_schema` in your stream class to return a `dict` describing the schema using [JSONSchema](https://json-schema.org). + +## Dynamically modifying static schemas +Override `Stream.get_json_schema` to run the default behavior, edit the returned value, then return the edited value: +``` +def get_json_schema(self): + schema = super().get_json_schema() + schema['dynamically_determined_property'] = "property" + return schema +``` + +Delete this file once you're done. Or don't. Up to you :) diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/categories.json b/airbyte-integrations/connectors/source-square/source_square/schemas/categories.json new file mode 100644 index 00000000000000..0af06a07948b69 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/categories.json @@ -0,0 +1,31 @@ +{ + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "category_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/customers.json b/airbyte-integrations/connectors/source-square/source_square/schemas/customers.json new file mode 100644 index 00000000000000..f4ed4d04742471 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/customers.json @@ -0,0 +1,115 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "cards": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "cardholder_name": { + "type": ["null", "string"] + }, + "billing_address": { + "type": ["null", "object"], + "properties": { + "postal_code": { + "type": ["null", "string"] + } + } + } + } + } + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "address_line_2": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + }, + "phone_number": { + "type": ["null", "string"] + }, + "reference_id": { + "type": ["null", "string"] + }, + "company_name": { + "type": ["null", "string"] + }, + "preferences": { + "type": ["null", "object"], + "properties": { + "email_unsubscribed": { + "type": "boolean" + } + } + }, + "creation_source": { + "type": ["null", "string"] + }, + "birthday": { + "type": ["null", "string"] + }, + "segment_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "group_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "version": { + "type": ["null", "integer"] + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/discounts.json b/airbyte-integrations/connectors/source-square/source_square/schemas/discounts.json new file mode 100644 index 00000000000000..d44e55aa8314f6 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/discounts.json @@ -0,0 +1,63 @@ +{ + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "discount_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "discount_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "application_method": { + "type": ["null", "string"] + }, + "modify_tax_basis": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "pin_required": { + "type": ["null", "boolean"] + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/items.json b/airbyte-integrations/connectors/source-square/source_square/schemas/items.json new file mode 100644 index 00000000000000..f1246c08460419 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/items.json @@ -0,0 +1,192 @@ +{ + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "custom_attribute_values": { + "type": ["null", "object"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "category_id": { + "type": ["null", "string"] + }, + "modifier_list_info": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "modifier_list_id": { + "type": ["null", "string"] + }, + "visibility": { + "type": ["null", "string"] + }, + "min_selected_modifiers": { + "type": ["null", "integer"] + }, + "max_selected_modifiers": { + "type": ["null", "integer"] + }, + "enabled": { + "type": ["null", "boolean"] + } + } + } + }, + "variations": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "item_variation_data": { + "type": ["null", "object"], + "properties": { + "item_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "sku": { + "type": ["null", "string"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "pricing_type": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "location_overrides": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "location_id": { + "type": ["null", "string"] + }, + "track_inventory": { + "type": ["null", "boolean"] + } + } + } + }, + "item_option_values": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + }, + "item_option_value_id": { + "type": ["null", "string"] + } + } + } + } + } + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + } + }, + "product_type": { + "type": ["null", "string"] + }, + "skip_modifier_screen": { + "type": ["null", "boolean"] + }, + "item_options": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "item_option_id": { + "type": ["null", "string"] + } + } + } + }, + "ecom_visibility": { + "type": ["null", "string"] + }, + "tax_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } + }, + "image_id": { + "type": ["null", "string"] + }, + "present_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/locations.json b/airbyte-integrations/connectors/source-square/source_square/schemas/locations.json new file mode 100644 index 00000000000000..f7a3a7b742d9ca --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/locations.json @@ -0,0 +1,91 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + } + } + }, + "timezone": { + "type": ["null", "string"] + }, + "capabilities": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + }, + "status": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "merchant_id": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "language_code": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "business_name": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "website_url": { + "type": ["null", "string"] + }, + "business_hours": { + "type": ["null", "object"] + }, + "business_email": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "twitter_username": { + "type": ["null", "string"] + }, + "instagram_username": { + "type": ["null", "string"] + }, + "facebook_url": { + "type": ["null", "string"] + }, + "mcc": { + "type": ["null", "string"] + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/modifier_list.json b/airbyte-integrations/connectors/source-square/source_square/schemas/modifier_list.json new file mode 100644 index 00000000000000..d3b77200d5aeaf --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/modifier_list.json @@ -0,0 +1,88 @@ +{ + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_list_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "selection_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "modifier_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "on_by_default": { + "type": ["null", "boolean"] + }, + "ordinal": { + "type": ["null", "integer"] + }, + "modifier_list_id": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/orders.json b/airbyte-integrations/connectors/source-square/source_square/schemas/orders.json new file mode 100644 index 00000000000000..952d03495d6f9b --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/orders.json @@ -0,0 +1,871 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "variation_name": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_sales_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "item_type": { + "type": ["null", "string"] + }, + "modifiers": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "name": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + } + } + } + }, + "applied_discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "discount_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "applied_taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "tax_uid": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "fulfillments": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "pickup_details": { + "type": ["null", "object"], + "properties": { + "expires_at": { + "type": ["null", "string"] + }, + "pickup_at": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "accepted_at": { + "type": ["null", "string"] + }, + "ready_at": { + "type": ["null", "string"] + }, + "schedule_type": { + "type": ["null", "string"] + }, + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } + }, + "auto_complete_duration": { + "type": ["null", "string"] + }, + "picked_up_at": { + "type": ["null", "string"] + } + } + }, + "shipment_details": { + "type": ["null", "object"], + "properties": { + "recipient": { + "type": ["null", "object"], + "properties": { + "display_name": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "address_line_1": { + "type": ["null", "string"] + }, + "locality": { + "type": ["null", "string"] + }, + "administrative_district_level_1": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + } + } + } + } + }, + "carrier": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + }, + "placed_at": { + "type": ["null", "string"] + }, + "packaged_at": { + "type": ["null", "string"] + }, + "shipped_at": { + "type": ["null", "string"] + }, + "expected_shipped_at": { + "type": ["null", "string"] + }, + "in_progress_at": { + "type": ["null", "string"] + } + } + } + } + } + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "closed_at": { + "type": ["null", "string"] + }, + "tenders": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + } + } + }, + "payment_id": { + "type": ["null", "string"] + }, + "cash_details": { + "type": ["null", "object"], + "properties": { + "buyer_tendered_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "change_back_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "note": { + "type": ["null", "string"] + } + } + } + }, + "total_service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "net_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "source": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + } + } + }, + "returns": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "source_order_id": { + "type": ["null", "string"] + }, + "return_line_items": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "string"] + }, + "item_type": { + "type": ["null", "string"] + }, + "base_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "variation_total_price_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "gross_return_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } + } + }, + "return_amounts": { + "type": ["null", "object"], + "properties": { + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "discount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "tip_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "service_charge_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "refunds": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "transaction_id": { + "type": ["null", "string"] + }, + "tender_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + } + } + } + }, + "service_charges": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "taxable": { + "type": ["null", "boolean"] + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "total_tax_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "discounts": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "type": { + "type": ["null", "string"] + }, + "scope": { + "type": ["null", "string"] + } + } + } + }, + "taxes": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "uid": { + "type": ["null", "string"] + }, + "catalog_object_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "applied_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "scope": { + "type": ["null", "string"] + } + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/payments.json b/airbyte-integrations/connectors/source-square/source_square/schemas/payments.json new file mode 100644 index 00000000000000..bb414b66076d63 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/payments.json @@ -0,0 +1,199 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "status": { + "type": ["null", "string"] + }, + "delay_duration": { + "type": ["null", "string"] + }, + "source_type": { + "type": ["null", "string"] + }, + "card_details": { + "type": ["null", "object"], + "properties": { + "status": { + "type": ["null", "string"] + }, + "card": { + "type": ["null", "object"], + "properties": { + "card_brand": { + "type": ["null", "string"] + }, + "last_4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "card_type": { + "type": ["null", "string"] + }, + "prepaid_type": { + "type": ["null", "string"] + }, + "bin": { + "type": ["null", "string"] + } + } + }, + "entry_method": { + "type": ["null", "string"] + }, + "cvv_status": { + "type": ["null", "string"] + }, + "avs_status": { + "type": ["null", "string"] + }, + "statement_description": { + "type": ["null", "string"] + }, + "card_payment_timeline": { + "type": ["null", "object"], + "properties": { + "authorized_at": { + "type": ["null", "string"] + }, + "captured_at": { + "type": ["null", "string"] + }, + "voided_at": { + "type": ["null", "string"] + } + } + } + } + }, + "location_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "risk_evaluation": { + "type": ["null", "object"], + "properties": { + "created_at": { + "type": ["null", "string"] + }, + "risk_level": { + "type": ["null", "string"] + } + } + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + }, + "total_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "approved_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "receipt_number": { + "type": ["null", "string"] + }, + "receipt_url": { + "type": ["null", "string"] + }, + "delay_action": { + "type": ["null", "string"] + }, + "delayed_until": { + "type": ["null", "string"] + }, + "version_token": { + "type": ["null", "string"] + }, + "note": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "refunded_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + }, + "refund_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/refunds.json b/airbyte-integrations/connectors/source-square/source_square/schemas/refunds.json new file mode 100644 index 00000000000000..18b2c97819ff9e --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/refunds.json @@ -0,0 +1,66 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + }, + "required": ["amount", "currency"] + }, + "payment_id": { + "type": ["null", "string"] + }, + "order_id": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "processing_fee": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "effective_at": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "amount_money": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/shifts.json b/airbyte-integrations/connectors/source-square/source_square/schemas/shifts.json new file mode 100644 index 00000000000000..66f0c3af29cd3a --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/shifts.json @@ -0,0 +1,86 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "employee_id": { + "type": ["null", "string"] + }, + "location_id": { + "type": ["null", "string"] + }, + "timezone": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "wage": { + "type": ["null", "object"], + "properties": { + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } + }, + "breaks": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "start_at": { + "type": ["null", "string"] + }, + "end_at": { + "type": ["null", "string"] + }, + "break_type_id": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "expected_duration": { + "type": ["null", "string"] + }, + "is_paid": { + "type": ["null", "boolean"] + } + } + } + }, + "status": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/taxes.json b/airbyte-integrations/connectors/source-square/source_square/schemas/taxes.json new file mode 100644 index 00000000000000..93ae1b32c29a45 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/taxes.json @@ -0,0 +1,58 @@ +{ + "type": ["null", "object"], + "properties": { + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "version": { + "type": ["null", "integer"] + }, + "is_deleted": { + "type": ["null", "boolean"] + }, + "present_at_all_locations": { + "type": ["null", "boolean"] + }, + "tax_data": { + "type": ["null", "object"], + "properties": { + "name": { + "type": ["null", "string"] + }, + "calculation_phase": { + "type": ["null", "string"] + }, + "inclusion_type": { + "type": ["null", "string"] + }, + "percentage": { + "type": ["null", "string"] + }, + "applies_to_custom_amounts": { + "type": ["null", "boolean"] + }, + "enabled": { + "type": ["null", "boolean"] + }, + "tax_type_id": { + "type": ["null", "string"] + }, + "tax_type_name": { + "type": ["null", "string"] + } + } + }, + "absent_at_location_ids": { + "type": ["null", "array"], + "items": { + "type": ["null", "string"] + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/team_member_wages.json b/airbyte-integrations/connectors/source-square/source_square/schemas/team_member_wages.json new file mode 100644 index 00000000000000..300e5e81fae984 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/team_member_wages.json @@ -0,0 +1,25 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "team_member_id": { + "type": ["null", "string"] + }, + "title": { + "type": ["null", "string"] + }, + "hourly_rate": { + "type": ["null", "object"], + "properties": { + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/schemas/team_members.json b/airbyte-integrations/connectors/source-square/source_square/schemas/team_members.json new file mode 100644 index 00000000000000..df47fbbd7776a7 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/schemas/team_members.json @@ -0,0 +1,43 @@ +{ + "type": ["null", "object"], + "properties": { + "id": { + "type": ["null", "string"] + }, + "is_owner": { + "type": ["null", "boolean"] + }, + "status": { + "type": ["null", "string"] + }, + "given_name": { + "type": ["null", "string"] + }, + "family_name": { + "type": ["null", "string"] + }, + "email_address": { + "type": ["null", "string"] + }, + "created_at": { + "type": ["null", "string"] + }, + "updated_at": { + "type": ["null", "string"] + }, + "assigned_locations": { + "type": ["null", "object"], + "properties": { + "assignment_type": { + "type": ["null", "string"] + } + } + }, + "reference_id": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/source.py b/airbyte-integrations/connectors/source-square/source_square/source.py new file mode 100644 index 00000000000000..53ec57864b4f79 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/source.py @@ -0,0 +1,424 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +import json +from abc import ABC, abstractmethod +from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple + +import pendulum +import requests +from airbyte_cdk.models import SyncMode +from airbyte_cdk.sources import AbstractSource +from airbyte_cdk.sources.streams import Stream +from airbyte_cdk.sources.streams.http import HttpStream +from airbyte_cdk.sources.streams.http.auth import TokenAuthenticator +from source_square.utils import separate_items_by_count + + +class SquareException(Exception): + """ Just for formatting the exception as Square""" + + def __init__(self, status_code, errors): + self.status_code = status_code + self.errors = errors + + def __str__(self): + return f"Code: {self.status_code}, Detail: {self.errors}" + + +def parse_square_error_response(error: requests.exceptions.HTTPError) -> SquareException: + if error.response.content: + content = json.loads(error.response.content.decode()) + if content and "errors" in content: + return SquareException(error.response.status_code, content["errors"]) + + +class SquareStream(HttpStream, ABC): + def __init__(self, is_sandbox: bool, api_version: str, start_date: str, include_deleted_objects: bool, **kwargs): + super().__init__(**kwargs) + self.is_sandbox = is_sandbox + self.api_version = api_version + # Converting users ISO 8601 format (YYYY-MM-DD) to RFC 3339 (2021-06-14T13:47:56.799Z) + # Because this standard is used by square in 'updated_at' records field + self.start_date = pendulum.parse(start_date).to_rfc3339_string() + self.include_deleted_objects = include_deleted_objects + + data_field = None + primary_key = "id" + items_per_page_limit = 100 + + @property + def url_base(self) -> str: + return "https://connect.squareup{}.com/v2/".format("sandbox" if self.is_sandbox else "") + + def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: + next_page_cursor = response.json().get("cursor", False) + if next_page_cursor: + return {"cursor": next_page_cursor} + + def request_headers( + self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None + ) -> Mapping[str, Any]: + return {"Square-Version": self.api_version, "Content-Type": "application/json"} + + def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: + json_response = response.json() + records = json_response.get(self.data_field, []) if self.data_field is not None else json_response + yield from records + + def _send_request(self, request: requests.PreparedRequest) -> requests.Response: + try: + return super()._send_request(request) + except requests.exceptions.HTTPError as e: + square_exception = parse_square_error_response(e) + if square_exception: + self.logger.error(str(square_exception)) + # Exiting is made for not to have a huge traceback in the airbyte log. + # The explicit square error message already been out with the command above. + exit(1) + + raise e + + +# Some streams require next_page_token in request query parameters (TeamMemberWages, Customers) +# but others in JSON payload (Items, Discounts, Orders, etc) +# That's why this 2 classes SquareStreamPageParam and SquareStreamPageJson are made +class SquareStreamPageParam(SquareStream, ABC): + def request_params( + self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None + ) -> MutableMapping[str, Any]: + return {"cursor": next_page_token["cursor"]} if next_page_token else {} + + +class SquareStreamPageJson(SquareStream, ABC): + def request_body_json( + self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None + ) -> Optional[Mapping]: + return {"cursor": next_page_token["cursor"]} if next_page_token else {} + + +class SquareStreamPageJsonAndLimit(SquareStreamPageJson, ABC): + def request_body_json( + self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None + ) -> Optional[Mapping]: + json_payload = {"limit": self.items_per_page_limit} + if next_page_token: + json_payload.update(next_page_token) + + return json_payload + + +class SquareCatalogObjectsStream(SquareStreamPageJson): + data_field = "objects" + http_method = "POST" + items_per_page_limit = 1000 + + def path(self, **kwargs) -> str: + return "catalog/search" + + def request_body_json( + self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None + ) -> Optional[Mapping]: + json_payload = super().request_body_json(stream_state, stream_slice, next_page_token) + + if self.path() == "catalog/search": + json_payload["include_deleted_objects"] = self.include_deleted_objects + json_payload["include_related_objects"] = False + json_payload["limit"] = self.items_per_page_limit + + return json_payload + + +class IncrementalSquareGenericStream(SquareStream, ABC): + def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: + if current_stream_state is not None and self.cursor_field in current_stream_state: + return {self.cursor_field: max(current_stream_state[self.cursor_field], latest_record[self.cursor_field])} + else: + return {self.cursor_field: self.start_date} + + +class IncrementalSquareCatalogObjectsStream(SquareCatalogObjectsStream, IncrementalSquareGenericStream, ABC): + @property + @abstractmethod + def object_type(self): + """Object type property""" + + state_checkpoint_interval = SquareCatalogObjectsStream.items_per_page_limit + + cursor_field = "updated_at" + + def request_body_json(self, stream_state: Mapping[str, Any], **kwargs) -> Optional[Mapping]: + json_payload = super().request_body_json(stream_state, **kwargs) + + if stream_state: + json_payload["begin_time"] = stream_state[self.cursor_field] + + json_payload["object_types"] = [self.object_type] + return json_payload + + +class IncrementalSquareStream(IncrementalSquareGenericStream, SquareStreamPageParam, ABC): + state_checkpoint_interval = SquareStream.items_per_page_limit + + cursor_field = "created_at" + + def request_params( + self, + stream_state: Mapping[str, Any], + stream_slice: Mapping[str, Any] = None, + next_page_token: Mapping[str, Any] = None, + ) -> MutableMapping[str, Any]: + params_payload = super().request_params(stream_state, stream_slice, next_page_token) + + if stream_state: + params_payload["begin_time"] = stream_state[self.cursor_field] + + params_payload["limit"] = self.items_per_page_limit + + return params_payload + + +class Items(IncrementalSquareCatalogObjectsStream): + """Docs: https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects + with object_types = ITEM""" + + object_type = "ITEM" + + +class Categories(IncrementalSquareCatalogObjectsStream): + """Docs: https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects + with object_types = CATEGORY""" + + object_type = "CATEGORY" + + +class Discounts(IncrementalSquareCatalogObjectsStream): + """Docs: https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects + with object_types = DISCOUNT""" + + object_type = "DISCOUNT" + + +class Taxes(IncrementalSquareCatalogObjectsStream): + """Docs: https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects + with object_types = TAX""" + + object_type = "TAX" + + +class ModifierList(IncrementalSquareCatalogObjectsStream): + """Docs: https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects + with object_types = MODIFIER_LIST""" + + object_type = "MODIFIER_LIST" + + +class Refunds(IncrementalSquareStream): + """ Docs: https://developer.squareup.com/reference/square_2021-06-16/refunds-api/list-payment-refunds """ + + data_field = "refunds" + + def path(self, **kwargs) -> str: + return "refunds" + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + params_payload = super().request_params(**kwargs) + params_payload["sort_order"] = "ASC" + + return params_payload + + +class Payments(IncrementalSquareStream): + """ Docs: https://developer.squareup.com/reference/square_2021-06-16/payments-api/list-payments """ + + data_field = "payments" + + def path(self, **kwargs) -> str: + return "payments" + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + params_payload = super().request_params(**kwargs) + params_payload["sort_order"] = "ASC" + + return params_payload + + +class Locations(SquareStream): + """ Docs: https://developer.squareup.com/explorer/square/locations-api/list-locations """ + + data_field = "locations" + + def path(self, **kwargs) -> str: + return "locations" + + +class Shifts(SquareStreamPageJsonAndLimit): + """ Docs: https://developer.squareup.com/reference/square/labor-api/search-shifts """ + + data_field = "shifts" + http_method = "POST" + items_per_page_limit = 200 + + def path(self, **kwargs) -> str: + return "labor/shifts/search" + + +class TeamMembers(SquareStreamPageJsonAndLimit): + """ Docs: https://developer.squareup.com/reference/square/team-api/search-team-members """ + + data_field = "team_members" + http_method = "POST" + + def path(self, **kwargs) -> str: + return "team-members/search" + + +class TeamMemberWages(SquareStreamPageParam): + """ Docs: https://developer.squareup.com/reference/square_2021-06-16/labor-api/list-team-member-wages """ + + data_field = "team_member_wages" + items_per_page_limit = 200 + + def path(self, **kwargs) -> str: + return "labor/team-member-wages" + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + params_payload = super().request_params(**kwargs) + params_payload = params_payload or {} + + params_payload["limit"] = self.items_per_page_limit + return params_payload + + +class Customers(SquareStreamPageParam): + """ Docs: https://developer.squareup.com/reference/square_2021-06-16/customers-api/list-customers """ + + data_field = "customers" + + def path(self, **kwargs) -> str: + return "customers" + + def request_params(self, **kwargs) -> MutableMapping[str, Any]: + params_payload = super().request_params(**kwargs) + params_payload = params_payload or {} + + params_payload["sort_order"] = "ASC" + params_payload["sort_field"] = "CREATED_AT" + return params_payload + + +class Orders(SquareStreamPageJson): + """ Docs: https://developer.squareup.com/reference/square/orders-api/search-orders """ + + data_field = "orders" + http_method = "POST" + items_per_page_limit = 500 + # There is a restriction in the documentation where only 10 locations can be send at one request + # https://developer.squareup.com/reference/square/orders-api/search-orders#request__property-location_ids + locations_per_requets = 10 + + def path(self, **kwargs) -> str: + return "orders/search" + + def request_body_json(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> Optional[Mapping]: + json_payload = super().request_body_json(stream_slice=stream_slice, **kwargs) + json_payload = json_payload or {} + + if stream_slice: + json_payload.update(stream_slice) + + json_payload["limit"] = self.items_per_page_limit + return json_payload + + def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]: + locations_stream = Locations( + authenticator=self.authenticator, + is_sandbox=self.is_sandbox, + api_version=self.api_version, + start_date=self.start_date, + include_deleted_objects=self.include_deleted_objects, + ) + locations_records = locations_stream.read_records(sync_mode=SyncMode.full_refresh) + location_ids = [location["id"] for location in locations_records] + + if not location_ids: + self.logger.error( + "No locations found. Orders cannot be extracted without locations. " + "Check https://developer.squareup.com/explorer/square/locations-api/list-locations" + ) + exit(1) + + separated_locations = separate_items_by_count(location_ids, self.locations_per_requets) + for location in separated_locations: + yield {"location_ids": location} + + +class SourceSquare(AbstractSource): + api_version = "2021-06-16" # Latest Stable Release + + def check_connection(self, logger, config) -> Tuple[bool, any]: + + headers = { + "Square-Version": self.api_version, + "Authorization": "Bearer {}".format(config["api_key"]), + "Content-Type": "application/json", + } + url = "https://connect.squareup{}.com/v2/catalog/info".format("sandbox" if config["is_sandbox"] else "") + + try: + session = requests.get(url, headers=headers) + session.raise_for_status() + return True, None + except requests.exceptions.RequestException as e: + square_exception = parse_square_error_response(e) + if square_exception: + return False, square_exception.errors[0]["detail"] + + return False, e + + def streams(self, config: Mapping[str, Any]) -> List[Stream]: + + auth = TokenAuthenticator(token=config["api_key"]) + args = { + "authenticator": auth, + "is_sandbox": config["is_sandbox"], + "api_version": self.api_version, + "start_date": config["start_date"], + "include_deleted_objects": config["include_deleted_objects"], + } + return [ + Items(**args), + Categories(**args), + Discounts(**args), + Taxes(**args), + Locations(**args), + TeamMembers(**args), + TeamMemberWages(**args), + Refunds(**args), + Payments(**args), + Customers(**args), + ModifierList(**args), + Shifts(**args), + Orders(**args), + ] diff --git a/airbyte-integrations/connectors/source-square/source_square/spec.json b/airbyte-integrations/connectors/source-square/source_square/spec.json new file mode 100644 index 00000000000000..46dd0b4f681f12 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/spec.json @@ -0,0 +1,36 @@ +{ + "documentationUrl": "https://docs.airbyte.io/integrations/sources/square", + "connectionSpecification": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Square Source CDK Specifications", + "type": "object", + "required": ["api_key", "is_sandbox"], + "additionalProperties": false, + "properties": { + "api_key": { + "type": "string", + "description": "The API key for a Square application", + "airbyte_secret": true + }, + "is_sandbox": { + "type": "boolean", + "description": "Determines the sandbox (true) or production (false) API version", + "examples": [true, false], + "default": true + }, + "start_date": { + "type": "string", + "description": "The start date to sync data. Leave blank for full sync. Format: YYYY-MM-DD.", + "examples": ["2021-01-01"], + "default": "1970-01-01", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" + }, + "include_deleted_objects": { + "type": "boolean", + "description": "In some streams there is and option to include deleted objects (Items, Categories, Discounts, Taxes)", + "examples": [true, false], + "default": false + } + } + } +} diff --git a/airbyte-integrations/connectors/source-square/source_square/utils.py b/airbyte-integrations/connectors/source-square/source_square/utils.py new file mode 100644 index 00000000000000..cbeec5fd030f00 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/source_square/utils.py @@ -0,0 +1,55 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +from typing import Union + + +def separate_by_count(total_length: int, part_count: int) -> (int, int): + """ + Calculates parts needed to separate count by part_count value + For example: separate_by_count(total_length=196582, part_count=10000) returns (19, 6582) -> 19*10000 + 6582=196582 + + :param total_length: + :param part_count: + :return: Returns the total_parts and last part count + """ + total_parts = total_length // part_count + last_part = total_length - (part_count * total_parts) + return total_parts, last_part + + +def separate_items_by_count(item_list: Union[list, tuple], part_count: int) -> list: + if not item_list: + return [] + + total_parts, _ = separate_by_count(len(item_list), part_count) + + result_list = [] + for i in range(total_parts): + result_list.append(item_list[part_count * i : part_count * (i + 1)]) + + if len(item_list) % part_count != 0: + result_list.append(item_list[total_parts * part_count :]) + + return result_list diff --git a/airbyte-integrations/connectors/source-square/unit_tests/connection_test.py b/airbyte-integrations/connectors/source-square/unit_tests/connection_test.py new file mode 100644 index 00000000000000..f0fae5e4e31e31 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/unit_tests/connection_test.py @@ -0,0 +1,32 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +from airbyte_cdk.logger import AirbyteLogger +from source_square.source import SourceSquare + + +def test_source_wrong_credentials(): + source = SourceSquare() + status, error = source.check_connection(logger=AirbyteLogger(), config={"api_key": "wrong.api.key", "is_sandbox": True}) + assert not status diff --git a/airbyte-integrations/connectors/source-square/unit_tests/utils_test.py b/airbyte-integrations/connectors/source-square/unit_tests/utils_test.py new file mode 100644 index 00000000000000..3c7b6b0c25b886 --- /dev/null +++ b/airbyte-integrations/connectors/source-square/unit_tests/utils_test.py @@ -0,0 +1,85 @@ +# +# MIT License +# +# Copyright (c) 2020 Airbyte +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +import math + +import pytest +from source_square.utils import separate_by_count, separate_items_by_count + + +def test_separate_by_count(): + total_parts, last_part = separate_by_count(total_length=196582, part_count=10000) + assert total_parts == 19 + assert last_part == 6582 + + total_parts, last_part = separate_by_count(total_length=1, part_count=10) + assert total_parts == 0 + assert last_part == 1 + + total_parts, last_part = separate_by_count(total_length=10000, part_count=10000) + assert total_parts == 1 + assert last_part == 0 + + with pytest.raises(ZeroDivisionError): + separate_by_count(total_length=0, part_count=0) + + total_parts, last_part = separate_by_count(total_length=0, part_count=10) + assert total_parts == 0 + assert last_part == 0 + + total_parts, last_part = separate_by_count(total_length=math.inf, part_count=10) + assert math.isnan(total_parts) is True + assert math.isnan(last_part) is True + + total_parts, last_part = separate_by_count(total_length=math.inf, part_count=math.inf) + assert math.isnan(total_parts) is True + assert math.isnan(last_part) is True + + +def test_separate_items_by_count(): + item_list = [i for i in range(10)] + + result_list = separate_items_by_count(item_list=[], part_count=10) + assert result_list == [] + + result_list = separate_items_by_count(item_list=item_list, part_count=1) + assert result_list == [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]] + + result_list = separate_items_by_count(item_list=item_list, part_count=10) + assert result_list == [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + + result_list = separate_items_by_count(item_list=item_list, part_count=15) + assert result_list == [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] + + result_list = separate_items_by_count(item_list=item_list, part_count=4) + assert result_list == [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]] + + result_list = separate_items_by_count(item_list=item_list, part_count=5) + assert result_list == [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] + + result_list = separate_items_by_count(item_list=item_list, part_count=9) + assert result_list == [[0, 1, 2, 3, 4, 5, 6, 7, 8], [9]] + + result_list = separate_items_by_count(item_list=None, part_count=5) + assert result_list == [] diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index ca11caef2cf836..072ccfd542f28c 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -87,6 +87,7 @@ * [Slack](integrations/sources/slack.md) * [Smartsheets](integrations/sources/smartsheets.md) * [Snowflake](integrations/sources/snowflake.md) + * [Square](integrations/sources/square.md) * [Stripe](integrations/sources/stripe.md) * [Tempo](integrations/sources/tempo.md) * [Twilio](integrations/sources/twilio.md) diff --git a/docs/integrations/sources/square.md b/docs/integrations/sources/square.md new file mode 100644 index 00000000000000..ae51d12d19284b --- /dev/null +++ b/docs/integrations/sources/square.md @@ -0,0 +1,82 @@ +# Square API + +## Overview + +The Square Source can sync data from the [Square API](https://developer.squareup.com/reference/square) + +Useful links: +- [Square API Explorer](https://developer.squareup.com/explorer/square) +- [Square API Docs](https://developer.squareup.com/reference/square) +- [Square Developer Dashboard](https://developer.squareup.com/apps) + +#### Output schema + +This Source is capable of syncing the following Streams: + +- [Items](https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects) (Incremental) +- [Categories](https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects) (Incremental) +- [Discounts](https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects) (Incremental) +- [Taxes](https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects) (Incremental) +- [ModifierLists](https://developer.squareup.com/explorer/square/catalog-api/search-catalog-objects) (Incremental) +- [Payments](https://developer.squareup.com/reference/square_2021-06-16/payments-api/list-payments) (Incremental) +- [Refunds](https://developer.squareup.com/reference/square_2021-06-16/refunds-api/list-payment-refunds) (Incremental) +- [Locations](https://developer.squareup.com/explorer/square/locations-api/list-locations) +- [Team Members](https://developer.squareup.com/reference/square_2021-06-16/team-api/search-team-members) (old V1 Employees API) +- [List Team Member Wages](https://developer.squareup.com/explorer/square/labor-api/list-team-member-wages) (old V1 Roles API) +- [Customers](https://developer.squareup.com/explorer/square/customers-api/list-customers) +- [Shifts](https://developer.squareup.com/reference/square/labor-api/search-shifts) +- [Orders](https://developer.squareup.com/reference/square/orders-api/search-orders) + +#### Data type mapping + +| Integration Type | Airbyte Type | Notes | +| :--- | :--- | :--- | +| `string` | `string` | | +| `integer` | `integer` | | +| `array` | `array` | | +| `object` | `object` | | +| `boolean` | `boolean` | | + +#### Features + +| Feature | Supported? | +| :--- | :--- | +| Full Refresh Sync | Yes | +| Incremental - Append Sync | Yes | +| Namespaces | No | + +### Requirements + +* api_key - The Square API key token +* is_sandbox - the switch between sandbox (true) and production (false) environments + +### Setup guide + +To get the API key for your square application follow [Geting started](https://developer.squareup.com/docs/get-started) +and [Access token](https://developer.squareup.com/docs/build-basics/access-tokens) guides + +## Performance considerations + +No defined API rate limits were found in Square documentation however considering +[this information](https://stackoverflow.com/questions/28033966/whats-the-rate-limit-on-the-square-connect-api/28053836#28053836) +it has 10 QPS limits. The connector doesn't handle rate limits exceptions, but no errors were raised during testing. + +Some Square API endpoints has different page size limitation + +- Items - 1000 +- Categories - 1000 +- Discounts - 1000 +- Taxes - 1000 +- ModifierLists - 1000 +- Payments - 100 +- Refunds - 100 +- TeamMembers - 100 +- ListTeamMemberWages - 200 +- Shifts - 200 +- Orders - 500 + +## Changelog + +| Version | Date | Pull Request | Subject | +| :------ | :-------- | :----- | :------ | +| 0.1.0 | 2021-06-30 | [4439](https://github.com/airbytehq/airbyte/pull/4439) | Initial release supporting the Square API | \ No newline at end of file diff --git a/tools/bin/ci_credentials.sh b/tools/bin/ci_credentials.sh index e00b693db10757..a81384d060f223 100755 --- a/tools/bin/ci_credentials.sh +++ b/tools/bin/ci_credentials.sh @@ -86,6 +86,7 @@ write_standard_creds source-slack "$SOURCE_SLACK_TEST_CREDS" write_standard_creds source-slack-singer "$SLACK_TEST_CREDS" write_standard_creds source-smartsheets "$SMARTSHEETS_TEST_CREDS" write_standard_creds source-snowflake "$SNOWFLAKE_INTEGRATION_TEST_CREDS" "config.json" +write_standard_creds source-square "$SOURCE_SQUARE_CREDS" write_standard_creds source-stripe "$STRIPE_INTEGRATION_TEST_CREDS" write_standard_creds source-stripe "$STRIPE_INTEGRATION_CONNECTED_ACCOUNT_TEST_CREDS" "connected_account_config.json" write_standard_creds source-surveymonkey "$SURVEYMONKEY_TEST_CREDS"