Skip to content

Commit 2470ed5

Browse files
tobiascadeeclaude
andauthored
feat: add deleted stream (#295)
* feat: add `deleted` stream with `ExactBulkStream` and `ExactSyncStream` base classes - Add `ExactBulkStream` and `ExactSyncStream` as specialised base classes for bulk and sync endpoints respectively - Add `deleted_schema` and `DeletedStream` to expose the Exact sync/Deleted endpoint - Switch `TransactionLinesStream` and `GLAccountsStream` to `ExactBulkStream` - Switch `GLClassificationsStream` to `ExactSyncStream` - Simplify schema imports in streams.py to use the `schemas` module directly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * revert: restore meltano.yml to main branch version Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * update `GLClassificationsStream` to `ExactBulkStream` --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8455b91 commit 2470ed5

File tree

4 files changed

+55
-17
lines changed

4 files changed

+55
-17
lines changed

tap_exact/client.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,26 @@ def post_process(
180180
def select(self) -> str:
181181
"""Return the select query parameter."""
182182
return ",".join(self.schema["properties"].keys())
183+
184+
185+
class ExactBulkStream(ExactStream):
186+
"""Exact bulk stream class."""
187+
188+
def get_new_paginator(self) -> BaseOffsetPaginator:
189+
"""Create a new pagination helper instance."""
190+
return ExactPaginator(self, start_value=None, page_size=1000)
191+
192+
193+
class ExactSyncStream(ExactBulkStream):
194+
"""Exact stream class for sync endpoints."""
195+
196+
def get_url_params(self, context: dict | None, next_page_token: str) -> dict[str, Any]:
197+
"""Return a dictionary of parameters to use in the API request."""
198+
params: dict = {}
199+
if self.select:
200+
params["$select"] = self.select
201+
starting_timestamp = self.get_starting_replication_key_value(context)
202+
params["$filter"] = f"Timestamp gt {starting_timestamp if type(starting_timestamp) is int else 1}"
203+
if next_page_token:
204+
params["$skiptoken"] = next_page_token
205+
return params

tap_exact/schemas.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,13 @@
223223
Property("TransactionEntryNo", IntegerType), # Entry number of transaction
224224
Property("Type", StringType), # Asset type (0=Other Assets, 1=Commercial Building)
225225
).to_dict()
226+
227+
deleted_schema = PropertiesList(
228+
Property("ID", StringType), # Primary key
229+
Property("Timestamp", IntegerType), # Deletion timestamp
230+
Property("Division", IntegerType), # Division code
231+
Property("DeletedBy", StringType), # User ID of the person who deleted the record
232+
Property("DeletedDate", DateTimeType), # Date when the record was deleted
233+
Property("EntityKey", StringType), # The primary key of the deleted record
234+
Property("EntityType", IntegerType), # The type of the deleted record
235+
).to_dict()

tap_exact/streams.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,37 @@
44

55
import typing as t
66

7-
from tap_exact.client import ExactStream
8-
from tap_exact.schemas import (
9-
assets_schema,
10-
gl_account_classification_mappings_schema,
11-
gl_accounts_schema,
12-
gl_classifications_schema,
13-
transaction_lines_schema,
14-
)
7+
from tap_exact import schemas
8+
from tap_exact.client import ExactBulkStream, ExactStream, ExactSyncStream
159

1610

17-
class TransactionLinesStream(ExactStream):
11+
class TransactionLinesStream(ExactBulkStream):
1812
"""Define TransactionLines stream."""
1913

2014
name = "transaction_lines"
2115
path = "/bulk/Financial/TransactionLines"
2216
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
2317
replication_key: t.ClassVar[str] = "Modified"
24-
schema = transaction_lines_schema # pyright: ignore[reportAssignmentType]
18+
schema = schemas.transaction_lines_schema # pyright: ignore[reportAssignmentType]
2519

2620

27-
class GLAccountsStream(ExactStream):
21+
class GLAccountsStream(ExactBulkStream):
2822
"""Define GLAccounts stream."""
2923

3024
name = "gl_accounts"
3125
path = "/bulk/Financial/GLAccounts"
3226
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
3327
replication_key: t.ClassVar[str] = "Modified"
34-
schema = gl_accounts_schema # pyright: ignore[reportAssignmentType]
28+
schema = schemas.gl_accounts_schema # pyright: ignore[reportAssignmentType]
3529

3630

37-
class GLClassificationsStream(ExactStream):
31+
class GLClassificationsStream(ExactBulkStream):
3832
"""Define GLClassifications stream."""
3933

4034
name = "gl_classifications"
41-
path = "/sync/Financial/GLClassifications"
35+
path = "/bulk/Financial/GLClassifications"
4236
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
43-
schema = gl_classifications_schema # pyright: ignore[reportAssignmentType]
37+
schema = schemas.gl_classifications_schema # pyright: ignore[reportAssignmentType]
4438

4539

4640
class GLAccountClassificationMappingsStream(ExactStream):
@@ -49,7 +43,7 @@ class GLAccountClassificationMappingsStream(ExactStream):
4943
name = "gl_account_classification_mappings"
5044
path = "/Financial/GLAccountClassificationMappings"
5145
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
52-
schema = gl_account_classification_mappings_schema # pyright: ignore[reportAssignmentType]
46+
schema = schemas.gl_account_classification_mappings_schema # pyright: ignore[reportAssignmentType]
5347

5448

5549
class AssetsStream(ExactStream):
@@ -58,4 +52,14 @@ class AssetsStream(ExactStream):
5852
name = "assets"
5953
path = "/assets/Assets"
6054
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
61-
schema = assets_schema # pyright: ignore[reportAssignmentType]
55+
schema = schemas.assets_schema # pyright: ignore[reportAssignmentType]
56+
57+
58+
class DeletedStream(ExactSyncStream):
59+
"""Define Deleted stream."""
60+
61+
name = "deleted"
62+
path = "/sync/Deleted"
63+
primary_keys: t.ClassVar[list[str]] = ["ID", "Division"]
64+
replication_key: t.ClassVar[str] = "Timestamp"
65+
schema = schemas.deleted_schema # pyright: ignore[reportAssignmentType]

tap_exact/tap.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def discover_streams(self) -> list[streams.ExactStream]:
4040
streams.GLAccountClassificationMappingsStream(self),
4141
streams.TransactionLinesStream(self),
4242
streams.AssetsStream(self),
43+
streams.DeletedStream(self),
4344
]
4445

4546

0 commit comments

Comments
 (0)