diff --git a/source-hubspot-native/acmeCo/flow.yaml b/source-hubspot-native/acmeCo/flow.yaml index 546e37f99c..3009c01d26 100644 --- a/source-hubspot-native/acmeCo/flow.yaml +++ b/source-hubspot-native/acmeCo/flow.yaml @@ -24,6 +24,10 @@ collections: schema: engagements.schema.yaml key: - /id + acmeCo/line_items: + schema: line_items.schema.yaml + key: + - /id acmeCo/owners: schema: owners.schema.yaml key: diff --git a/source-hubspot-native/acmeCo/line_items.schema.yaml b/source-hubspot-native/acmeCo/line_items.schema.yaml new file mode 100644 index 0000000000..4772ed86d4 --- /dev/null +++ b/source-hubspot-native/acmeCo/line_items.schema.yaml @@ -0,0 +1,152 @@ +--- +$defs: + History: + additionalProperties: false + properties: + _meta: + allOf: + - $ref: "#/$defs/Meta" + default: + op: u + row_id: -1 + description: Document metadata + timestamp: + format: date-time + title: Timestamp + type: string + value: + title: Value + type: string + sourceType: + title: Sourcetype + type: string + sourceId: + anyOf: + - type: string + - type: "null" + default: ~ + title: Sourceid + sourceLabel: + anyOf: + - type: string + - type: "null" + default: ~ + title: Sourcelabel + updatedByUserId: + anyOf: + - type: integer + - type: "null" + default: ~ + title: Updatedbyuserid + required: + - timestamp + - value + - sourceType + title: History + type: object + Meta: + properties: + op: + default: u + description: "Operation type (c: Create, u: Update, d: Delete)" + enum: + - c + - u + - d + title: Op + type: string + row_id: + default: -1 + description: "Row ID of the Document, counting up from zero, or -1 if not known" + title: Row Id + type: integer + title: Meta + type: object +additionalProperties: false +properties: + _meta: + allOf: + - $ref: "#/$defs/Meta" + default: + op: u + row_id: -1 + description: Document metadata + id: + title: Id + type: integer + createdAt: + format: date-time + title: Createdat + type: string + updatedAt: + format: date-time + title: Updatedat + type: string + archived: + title: Archived + type: boolean + properties: + type: object + additionalProperties: + anyOf: + - type: string + - type: "null" + title: Properties + propertiesWithHistory: + additionalProperties: + items: + $ref: "#/$defs/History" + type: array + default: {} + title: Propertieswithhistory + type: object + associations: + additionalProperties: false + default: {} + title: Associations + type: object + commerce_payments: + default: [] + items: + type: integer + title: Commerce Payments + type: array + products: + default: [] + items: + type: integer + title: Products + type: array + deals: + default: [] + items: + type: integer + title: Deals + type: array + invoices: + default: [] + items: + type: integer + title: Invoices + type: array + quotes: + default: [] + items: + type: integer + title: Quotes + type: array + subscriptions: + default: [] + items: + type: integer + title: Subscriptions + type: array +required: + - id + - createdAt + - updatedAt + - archived + - properties +title: LineItem +type: object +x-infer-schema: true diff --git a/source-hubspot-native/source_hubspot_native/api.py b/source-hubspot-native/source_hubspot_native/api.py index cd3d468c4a..95d71cc080 100644 --- a/source-hubspot-native/source_hubspot_native/api.py +++ b/source-hubspot-native/source_hubspot_native/api.py @@ -35,6 +35,7 @@ EmailEvent, EmailEventsResponse, Engagement, + LineItem, Names, OldRecentCompanies, OldRecentContacts, @@ -952,10 +953,33 @@ async def do_fetch(page: PageCursor, count: int) -> tuple[Iterable[tuple[datetim return await fetch_search_objects(Names.products, log, http, since, until, page) return fetch_changes_with_associations( - Names.contacts, Product, do_fetch, log, http, since, until + Names.products, Product, do_fetch, log, http, since, until + ) + + +def fetch_recent_line_items( + log: Logger, http: HTTPSession, since: datetime, until: datetime | None +) -> AsyncGenerator[tuple[datetime, str, LineItem], None]: + + async def do_fetch(page: PageCursor, count: int) -> tuple[Iterable[tuple[datetime, str]], PageCursor]: + return await fetch_search_objects(Names.line_items, log, http, since, until, page) + + return fetch_changes_with_associations( + Names.line_items, LineItem, do_fetch, log, http, since, until ) +def fetch_delayed_line_items( + log: Logger, http: HTTPSession, since: datetime, until: datetime +) -> AsyncGenerator[tuple[datetime, str, LineItem], None]: + + async def do_fetch(page: PageCursor, count: int) -> tuple[Iterable[tuple[datetime, str]], PageCursor]: + return await fetch_search_objects(Names.line_items, log, http, since, until, page) + + return fetch_changes_with_associations( + Names.line_items, LineItem, do_fetch, log, http, since, until + ) + async def list_custom_objects( log: Logger, http: HTTPSession, diff --git a/source-hubspot-native/source_hubspot_native/models.py b/source-hubspot-native/source_hubspot_native/models.py index f35e30e03e..d2f45b0933 100644 --- a/source-hubspot-native/source_hubspot_native/models.py +++ b/source-hubspot-native/source_hubspot_native/models.py @@ -89,16 +89,20 @@ class EndpointConfig(BaseModel): # Names of things within the HubSpot API domain. class Names(StrEnum): + commerce_payments = auto() companies = auto() contacts = auto() deal_pipelines = auto() deals = auto() email_events = auto() engagements = auto() + invoices = auto() line_items = auto() owners = auto() products = auto() properties = auto() + quotes = auto() + subscriptions = auto() tickets = auto() @@ -228,6 +232,17 @@ class Product(BaseCRMObject): ASSOCIATED_ENTITIES = [] +class LineItem(BaseCRMObject): + ASSOCIATED_ENTITIES = [Names.commerce_payments, Names.products, Names.deals, Names.invoices, Names.quotes, Names.subscriptions] + + commerce_payments: list[int] = [] + products: list[int] = [] + deals: list[int] = [] + invoices: list[int] = [] + quotes: list[int] = [] + subscriptions: list[int] = [] + + # An Association, as returned by the v4 associations API. class Association(BaseModel, extra="forbid"): diff --git a/source-hubspot-native/source_hubspot_native/resources.py b/source-hubspot-native/source_hubspot_native/resources.py index 610d377447..fbd86c39e2 100644 --- a/source-hubspot-native/source_hubspot_native/resources.py +++ b/source-hubspot-native/source_hubspot_native/resources.py @@ -19,6 +19,7 @@ fetch_delayed_deals, fetch_delayed_email_events, fetch_delayed_engagements, + fetch_delayed_line_items, fetch_delayed_products, fetch_delayed_tickets, fetch_email_events_page, @@ -31,6 +32,7 @@ fetch_recent_deals, fetch_recent_email_events, fetch_recent_engagements, + fetch_recent_line_items, fetch_recent_products, fetch_recent_tickets, list_custom_objects, @@ -47,6 +49,7 @@ EmailEvent, EndpointConfig, Engagement, + LineItem, Names, Owner, Product, @@ -96,6 +99,7 @@ async def all_resources( crm_object_with_associations(Engagement, Names.engagements, Names.engagements, http, fetch_recent_engagements, fetch_delayed_engagements), crm_object_with_associations(Ticket, Names.tickets, Names.tickets, http, fetch_recent_tickets, fetch_delayed_tickets), crm_object_with_associations(Product, Names.products, Names.products, http, fetch_recent_products, fetch_delayed_products), + crm_object_with_associations(LineItem, Names.line_items, Names.line_items, http, fetch_recent_line_items, fetch_delayed_line_items), properties(http, itertools.chain(standard_object_names, custom_object_path_components)), email_events(http), deal_pipelines(http), diff --git a/source-hubspot-native/test.flow.yaml b/source-hubspot-native/test.flow.yaml index b727fb5df6..ad3cefad2b 100644 --- a/source-hubspot-native/test.flow.yaml +++ b/source-hubspot-native/test.flow.yaml @@ -8,6 +8,11 @@ captures: command: - python - "-m" + # - "-m" + # - "debugpy" + # - "--listen" + # - "0.0.0.0:5678" + # - "--wait-for-client" - source_hubspot_native config: config.yaml bindings: @@ -29,6 +34,9 @@ captures: - resource: name: products target: acmeCo/products + - resource: + name: line_items + target: acmeCo/line_items - resource: name: properties interval: P1D diff --git a/source-hubspot-native/tests/snapshots/snapshots__discover__stdout.json b/source-hubspot-native/tests/snapshots/snapshots__discover__stdout.json index 90f0bc0e59..4b4dfe00a4 100644 --- a/source-hubspot-native/tests/snapshots/snapshots__discover__stdout.json +++ b/source-hubspot-native/tests/snapshots/snapshots__discover__stdout.json @@ -1177,6 +1177,237 @@ "/id" ] }, + { + "recommendedName": "line_items", + "resourceConfig": { + "name": "line_items" + }, + "documentSchema": { + "$defs": { + "History": { + "additionalProperties": false, + "properties": { + "_meta": { + "allOf": [ + { + "$ref": "#/$defs/Meta" + } + ], + "default": { + "op": "u", + "row_id": -1 + }, + "description": "Document metadata" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + }, + "sourceType": { + "title": "Sourcetype", + "type": "string" + }, + "sourceId": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sourceid" + }, + "sourceLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sourcelabel" + }, + "updatedByUserId": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Updatedbyuserid" + } + }, + "required": [ + "timestamp", + "value", + "sourceType" + ], + "title": "History", + "type": "object" + }, + "Meta": { + "properties": { + "op": { + "default": "u", + "description": "Operation type (c: Create, u: Update, d: Delete)", + "enum": [ + "c", + "u", + "d" + ], + "title": "Op", + "type": "string" + }, + "row_id": { + "default": -1, + "description": "Row ID of the Document, counting up from zero, or -1 if not known", + "title": "Row Id", + "type": "integer" + } + }, + "title": "Meta", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "_meta": { + "allOf": [ + { + "$ref": "#/$defs/Meta" + } + ], + "default": { + "op": "u", + "row_id": -1 + }, + "description": "Document metadata" + }, + "id": { + "title": "Id", + "type": "integer" + }, + "createdAt": { + "format": "date-time", + "title": "Createdat", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "title": "Updatedat", + "type": "string" + }, + "archived": { + "title": "Archived", + "type": "boolean" + }, + "properties": { + "type": "object", + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "title": "Properties" + }, + "propertiesWithHistory": { + "additionalProperties": { + "items": { + "$ref": "#/$defs/History" + }, + "type": "array" + }, + "default": {}, + "title": "Propertieswithhistory", + "type": "object" + }, + "associations": { + "additionalProperties": false, + "default": {}, + "title": "Associations", + "type": "object" + }, + "commerce_payments": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Commerce Payments", + "type": "array" + }, + "products": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Products", + "type": "array" + }, + "deals": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Deals", + "type": "array" + }, + "invoices": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Invoices", + "type": "array" + }, + "quotes": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Quotes", + "type": "array" + }, + "subscriptions": { + "default": [], + "items": { + "type": "integer" + }, + "title": "Subscriptions", + "type": "array" + } + }, + "required": [ + "id", + "createdAt", + "updatedAt", + "archived", + "properties" + ], + "title": "LineItem", + "type": "object", + "x-infer-schema": true + }, + "key": [ + "/id" + ] + }, { "recommendedName": "properties", "resourceConfig": {