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 553215d1fc6b9..bede96b69fdfa 100644 --- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml @@ -351,7 +351,7 @@ - name: Linnworks sourceDefinitionId: 7b86879e-26c5-4ef6-a5ce-2be5c7b46d1e dockerRepository: airbyte/source-linnworks - dockerImageTag: 0.1.3 + dockerImageTag: 0.1.4 documentationUrl: https://docs.airbyte.io/integrations/sources/linnworks icon: linnworks.svg sourceType: api diff --git a/airbyte-config/init/src/main/resources/seed/source_specs.yaml b/airbyte-config/init/src/main/resources/seed/source_specs.yaml index e9dc69872809f..85f12994147c4 100644 --- a/airbyte-config/init/src/main/resources/seed/source_specs.yaml +++ b/airbyte-config/init/src/main/resources/seed/source_specs.yaml @@ -3436,9 +3436,9 @@ - - "client_secret" oauthFlowOutputParameters: - - "refresh_token" -- dockerImage: "airbyte/source-linnworks:0.1.3" +- dockerImage: "airbyte/source-linnworks:0.1.4" spec: - documentationUrl: "https://docsurl.com" + documentationUrl: "https://docs.airbyte.io/integrations/sources/linnworks" connectionSpecification: $schema: "http://json-schema.org/draft-07/schema#" title: "Linnworks Spec" diff --git a/airbyte-integrations/connectors/source-linnworks/Dockerfile b/airbyte-integrations/connectors/source-linnworks/Dockerfile index 48fb7c3246dbf..af8d5dd41494f 100644 --- a/airbyte-integrations/connectors/source-linnworks/Dockerfile +++ b/airbyte-integrations/connectors/source-linnworks/Dockerfile @@ -34,5 +34,5 @@ COPY source_linnworks ./source_linnworks ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] -LABEL io.airbyte.version=0.1.3 +LABEL io.airbyte.version=0.1.4 LABEL io.airbyte.name=airbyte/source-linnworks diff --git a/airbyte-integrations/connectors/source-linnworks/integration_tests/abnormal_state.json b/airbyte-integrations/connectors/source-linnworks/integration_tests/abnormal_state.json index 753bb769cc9bf..fc503ae2fd7f6 100644 --- a/airbyte-integrations/connectors/source-linnworks/integration_tests/abnormal_state.json +++ b/airbyte-integrations/connectors/source-linnworks/integration_tests/abnormal_state.json @@ -1,5 +1,8 @@ { "processed_orders": { - "dReceivedDate": "2050-01-01T00:00:00+00:00" + "dProcessedOn": "2050-01-01T00:00:00+00:00" + }, + "processed_order_details": { + "ProcessedDateTime": "2050-01-01T00:00:00+00:00" } } diff --git a/airbyte-integrations/connectors/source-linnworks/integration_tests/catalog.json b/airbyte-integrations/connectors/source-linnworks/integration_tests/catalog.json index 0014dca6ca3ad..2b51b72441c18 100644 --- a/airbyte-integrations/connectors/source-linnworks/integration_tests/catalog.json +++ b/airbyte-integrations/connectors/source-linnworks/integration_tests/catalog.json @@ -28,7 +28,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { @@ -225,7 +225,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { @@ -271,7 +271,7 @@ "description": "if( Quantity == 0 ) dbo.StockItem.PurchasePrice Else CurrentStockValue / Quantity" }, "SKU": { - "type": "string", + "type": ["null", "string"], "description": "Product SKU" }, "AutoAdjust": { @@ -495,7 +495,7 @@ "description": "Url to full size image" }, "CheckSumValue": { - "type": "string", + "type": ["null", "string"], "description": "Image check sum" }, "pkRowId": { @@ -511,11 +511,11 @@ "description": "Sort order for the image" }, "ChecksumValue": { - "type": "string", + "type": ["null", "string"], "description": "Internal checksum value" }, "RawChecksum": { - "type": "string", + "type": ["null", "string"], "description": "Raw file checksum (Used for UI to determine if the image file is the same before submitting for upload)" }, "StockItemId": { @@ -582,7 +582,7 @@ "description": "Default package group id" }, "PackageGroupName": { - "type": "string", + "type": ["null", "string"], "description": "Default package group name" }, "Height": { @@ -643,7 +643,7 @@ "description": "Order ID" }, "cShippingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer's shipping address" }, "dReceivedDate": { @@ -725,11 +725,11 @@ "description": "Postal service code" }, "Vendor": { - "type": "string", + "type": ["null", "string"], "description": "Courier name (e.g. DPD)" }, "BillingEmailAddress": { - "type": "string" + "type": ["null", "string"] }, "ReferenceNum": { "type": "string", @@ -806,11 +806,11 @@ "description": "When order was cancelled" }, "PackageCategory": { - "type": "string", + "type": ["null", "string"], "description": "Package category" }, "PackageTitle": { - "type": "string", + "type": ["null", "string"], "description": "Package name" }, "ItemWeight": { @@ -822,51 +822,51 @@ "description": "Total order weight" }, "FolderCollection": { - "type": "string", + "type": ["null", "string"], "description": "Folder name of an order" }, "cBillingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing address" }, "BillingName": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing name" }, "BillingCompany": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing company" }, "BillingAddress1": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line one" }, "BillingAddress2": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line two" }, "BillingAddress3": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line three" }, "BillingTown": { - "type": "string", + "type": ["null", "string"], "description": "Billing town" }, "BillingRegion": { - "type": "string", + "type": ["null", "string"], "description": "Billing region, area, county" }, "BillingPostCode": { - "type": "string", + "type": ["null", "string"], "description": "Billing postcode" }, "BillingCountryName": { - "type": "string", + "type": ["null", "string"], "description": "Billing country" }, "BillingPhoneNumber": { - "type": "string", + "type": ["null", "string"], "description": "Billing phone number" }, "HoldOrCancel": { @@ -893,8 +893,879 @@ }, "supported_sync_modes": ["full_refresh", "incremental"], "source_defined_cursor": true, - "default_cursor_field": ["dReceivedDate"], + "default_cursor_field": ["dProcessedOn"], "source_defined_primary_key": [["nOrderId"]] + }, + { + "name": "processed_order_details", + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "OrderId": { + "type": "string", + "description": "Order ID (pkOrderId)" + }, + "NumOrderId": { + "type": "integer", + "description": "Linnworks order number" + }, + "Processed": { + "type": "boolean", + "description": "If order is processed" + }, + "ProcessedDateTime": { + "type": ["null", "string"], + "format": "date-time", + "description": "Date and time when order was processed" + }, + "FulfilmentLocationId": { + "type": "string", + "description": "Location ID" + }, + "GeneralInfo": { + "type": "object", + "description": "General information about order", + "additionalProperties": false, + "properties": { + "Status": { + "type": "integer", + "description": "Order Status (0 = UNPAID, 1 = PAID, 2 = RETURN, 3 = PENDING, 4 = RESEND)" + }, + "LabelPrinted": { + "type": "boolean", + "description": "Is label printed" + }, + "LabelError": { + "type": "string", + "description": "Is there a label error" + }, + "InvoicePrinted": { + "type": "boolean", + "description": "Is invoice printed" + }, + "PickListPrinted": { + "type": "boolean", + "description": "Is pick list printed" + }, + "IsRuleRun": { + "type": "boolean", + "description": "If rules engine rule ran on an order" + }, + "Notes": { + "type": "integer", + "description": "Quantity of order notes" + }, + "PartShipped": { + "type": "boolean", + "description": "If order partly shipped" + }, + "Marker": { + "type": ["null", "integer"], + "description": "Order marker (0 = NOT TAG, 1 = Tag 1, 2 = Tag 2, 3 = Tag 3, 4 = Tag 4, 5 = Tag 5, 6 = Tag 6, 7 = Parked)" + }, + "IsParked": { + "type": "boolean", + "description": "Is the order parked?" + }, + "Identifiers": { + "type": "array", + "description": "Order identifiers. [Prime | Scheduled]", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "IdentifierId": { + "type": "integer", + "description": "Internal identifier id. Use to update image and name." + }, + "IsCustom": { + "type": "boolean", + "description": "Is the tag user or system defined?" + }, + "ImageId": { + "type": "string" + }, + "ImageUrl": { + "type": "string" + }, + "Tag": { + "type": "string", + "description": "Internal tag for identification purposes" + }, + "Name": { + "type": "string", + "description": "Name displayed where the tag is used" + } + } + } + }, + "ReferenceNum": { + "type": "string", + "description": "Order reference number (Channel defined)" + }, + "SecondaryReference": { + "type": "string", + "description": "An additional reference number for the orderr (Used by some channels)" + }, + "ExternalReferenceNum": { + "type": "string", + "description": "This is an additional reference number from the sales channel, typically used by eBay" + }, + "ReceivedDate": { + "type": "string", + "format": "date-time", + "description": "The date and time at which the order was placed on the sales channel" + }, + "Source": { + "type": "string", + "description": "Order ChannelName/Source (e.g. EBAY)" + }, + "SubSource": { + "type": "string", + "description": "Order Subsource (e.g. EBAY1)" + }, + "SiteCode": { + "type": "string", + "description": "SiteCode used to differentiate between different sites from a single channel (eg. Amazon UK, Amazon US, Amazon FR...)" + }, + "HoldOrCancel": { + "type": "boolean", + "description": "This shows whether the order has been marked as on hold, for processed orders if the order has been cancelled OnHold = 1" + }, + "DespatchByDate": { + "type": "string", + "format": "date-time", + "description": "Despatch by Date" + }, + "ScheduledDelivery": { + "type": "object", + "description": "Scheduled delivery dates. Take priority over despatch by date", + "additionalProperties": false, + "properties": { + "From": { + "type": "string", + "format": "date-time" + }, + "To": { + "type": "string", + "format": "date-time" + } + } + }, + "HasScheduledDelivery": { + "type": "boolean" + }, + "Location": { + "type": "string", + "description": "Order location ID" + }, + "NumItems": { + "type": "integer", + "description": "Quantity of order items" + }, + "PickwaveIds": { + "type": "array", + "description": "All related Pickwave Ids", + "items": { + "type": "integer" + } + }, + "StockAllocationType": { + "type": ["null", "string"] + } + } + }, + "ShippingInfo": { + "type": "object", + "description": "Order shipping information", + "additionalProperties": false, + "properties": { + "Vendor": { + "type": "string", + "description": "Courier name (e.g. Royal Mail)" + }, + "PostalServiceId": { + "type": "string", + "description": "Postal service ID" + }, + "PostalServiceName": { + "type": "string", + "description": "Postal service name (e.g. Next day delivery)" + }, + "TotalWeight": { + "type": "number", + "description": "Order total weight" + }, + "ItemWeight": { + "type": "number", + "description": "If order is processed" + }, + "PackageCategoryId": { + "type": "string", + "description": "Package category ID" + }, + "PackageCategory": { + "type": "string", + "description": "Package category name" + }, + "PackageTypeId": { + "type": ["null", "string"], + "description": "Package type ID" + }, + "PackageType": { + "type": "string", + "description": "Package type name" + }, + "PostageCost": { + "type": "number", + "description": "Order postage cost" + }, + "PostageCostExTax": { + "type": "number", + "description": "Order postage cost excluding tax" + }, + "TrackingNumber": { + "type": "string", + "description": "Order tracking number provided by courier" + }, + "ManualAdjust": { + "type": "boolean", + "description": "If there is an adjustment to shipping cost was made" + } + } + }, + "CustomerInfo": { + "type": "object", + "description": "Order Customer information (Name, email etc)", + "additionalProperties": false, + "properties": { + "ChannelBuyerName": { + "type": "string", + "description": "Username of customer (Comes from channel)" + }, + "Address": { + "type": "object", + "description": "Customer address", + "additionalProperties": false, + "properties": { + "EmailAddress": { + "type": "string", + "description": "Customer's email address." + }, + "Address1": { + "type": "string", + "description": "First line of customer address." + }, + "Address2": { + "type": "string", + "description": "Second line of customer address." + }, + "Address3": { + "type": "string", + "description": "Third line of customer address." + }, + "Town": { + "type": "string", + "description": "Customer's town." + }, + "Region": { + "type": "string", + "description": "Customer's region." + }, + "PostCode": { + "type": "string", + "description": "Customer's postcode." + }, + "Country": { + "type": "string", + "description": "Customer's country." + }, + "Continent": { + "type": "string", + "description": "Customer's continent" + }, + "FullName": { + "type": "string", + "description": "Customer's first and second name." + }, + "Company": { + "type": "string", + "description": "Customer's company name." + }, + "PhoneNumber": { + "type": "string", + "description": "Customer's telephone number." + }, + "CountryId": { + "type": "string" + } + } + }, + "BillingAddress": { + "type": "object", + "description": "Customer billing address", + "additionalProperties": false, + "properties": { + "EmailAddress": { + "type": "string", + "description": "Customer's email address." + }, + "Address1": { + "type": "string", + "description": "First line of customer address." + }, + "Address2": { + "type": "string", + "description": "Second line of customer address." + }, + "Address3": { + "type": "string", + "description": "Third line of customer address." + }, + "Town": { + "type": "string", + "description": "Customer's town." + }, + "Region": { + "type": "string", + "description": "Customer's region." + }, + "PostCode": { + "type": "string", + "description": "Customer's postcode." + }, + "Country": { + "type": "string", + "description": "Customer's country." + }, + "Continent": { + "type": "string", + "description": "Customer's continent" + }, + "FullName": { + "type": "string", + "description": "Customer's first and second name." + }, + "Company": { + "type": "string", + "description": "Customer's company name." + }, + "PhoneNumber": { + "type": "string", + "description": "Customer's telephone number." + }, + "CountryId": { + "type": "string" + } + } + } + } + }, + "TotalsInfo": { + "type": "object", + "description": "Order totals information", + "additionalProperties": false, + "properties": { + "pkOrderId": { + "type": "string", + "description": "Order Id" + }, + "Subtotal": { + "type": "number", + "description": "Order subtotal" + }, + "PostageCost": { + "type": "number", + "description": "Order postage cost" + }, + "PostageCostExTax": { + "type": "number", + "description": "Order postage cost ex. tax" + }, + "Tax": { + "type": "number", + "description": "Tax" + }, + "TotalCharge": { + "type": "number", + "description": "Total charge" + }, + "PaymentMethod": { + "type": "string", + "description": "Payment method" + }, + "PaymentMethodId": { + "type": "string", + "description": "Payment method ID" + }, + "ProfitMargin": { + "type": "number", + "description": "Profit margin" + }, + "TotalDiscount": { + "type": "number", + "description": "Total discount applied to the order" + }, + "Currency": { + "type": "string", + "description": "Order currency" + }, + "CountryTaxRate": { + "type": "number", + "description": "Country tax rate" + }, + "ConversionRate": { + "type": "number", + "description": "Currency conversion rate. Set at point of save by the currency" + } + } + }, + "ExtendedProperties": { + "type": "array", + "description": "Extended properties of an order", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "RowId": { + "type": "string", + "description": "Record row ID" + }, + "Name": { + "type": "string", + "description": "Extended property name" + }, + "Value": { + "type": "string", + "description": "Extended property value" + }, + "Type": { + "type": "string", + "description": "Extended property type" + } + } + } + }, + "FolderName": { + "type": "array", + "description": "Folder names assigned to an order", + "items": { + "type": "string" + } + }, + "Items": { + "type": "array", + "description": "List of order items", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "ItemId": { + "type": "string", + "description": "Stock Item ID" + }, + "ItemNumber": { + "type": "string", + "description": "Item number as on channel" + }, + "SKU": { + "type": "string", + "description": "Product SKU" + }, + "ItemSource": { + "type": "string", + "description": "Item source / channel name" + }, + "Title": { + "type": "string", + "description": "Item title" + }, + "Quantity": { + "type": "integer", + "description": "Quantity" + }, + "CategoryId": { + "type": "string" + }, + "CategoryName": { + "type": "string", + "description": "Product category" + }, + "CompositeAvailablity": { + "type": ["null", "integer"], + "description": "Composite availability" + }, + "StockLevelsSpecified": { + "type": "boolean", + "description": "If stock level specified" + }, + "OnOrder": { + "type": "integer", + "description": "Level due in purchase orders" + }, + "OnPurchaseOrder": { + "type": "object", + "description": "Purchase order bound to this item", + "additionalProperties": false, + "properties": { + "pkPurchaseItemId": { + "type": "string", + "description": "Primary key of the bound" + }, + "Rowid": { + "type": "string" + }, + "pkPurchaseId": { + "type": "string" + }, + "ExternalInvoiceNumber": { + "type": "string" + }, + "fkSupplierId": { + "type": "string" + }, + "DateOfDelivery": { + "type": "string", + "format": "date-time" + }, + "QuotedDeliveryDate": { + "type": "string", + "format": "date-time" + }, + "SupplierName": { + "type": "string" + }, + "fkLocationId": { + "type": "string" + } + } + }, + "InOrderBook": { + "type": ["null", "integer"], + "description": "Quantity currently in open orders" + }, + "Level": { + "type": "integer", + "description": "Current stock level" + }, + "MinimumLevel": { + "type": ["null", "integer"], + "description": "Minimum level" + }, + "AvailableStock": { + "type": "integer", + "description": "Currently available stock level (Level-InOrderBook)" + }, + "PricePerUnit": { + "type": "number", + "description": "Unit price" + }, + "UnitCost": { + "type": "number", + "description": "Unit cost" + }, + "DespatchStockUnitCost": { + "type": "number", + "description": "Despatch stock unit cost" + }, + "Discount": { + "type": "number", + "description": "Percentage (0%, 10%, 20%, etc...)" + }, + "Tax": { + "type": "number", + "description": "Actual tax value on an item" + }, + "TaxRate": { + "type": "number", + "description": "Tax rate" + }, + "Cost": { + "type": "number", + "description": "Total item cost (exc tax)" + }, + "CostIncTax": { + "type": "number", + "description": "Total item cost (inc tax)" + }, + "CompositeSubItems": { + "$comment": "It should be \"$ref\": \"#/properties/Items\" but Airbyte doesn't support recursive $refs.", + "type": "array", + "items": { + "type": "object" + } + }, + "IsService": { + "type": "boolean", + "description": "if item is a service" + }, + "SalesTax": { + "type": "number", + "description": "Sales Tax" + }, + "TaxCostInclusive": { + "type": "boolean", + "description": "If tax is included in a cost" + }, + "PartShipped": { + "type": "boolean", + "description": "If order is partly shipped" + }, + "Weight": { + "type": "number", + "description": "Order weight" + }, + "BarcodeNumber": { + "type": "string", + "description": "Product barcode" + }, + "Market": { + "type": "integer", + "description": "Market" + }, + "ChannelSKU": { + "type": "string", + "description": "Channel product SKU" + }, + "ChannelTitle": { + "type": "string", + "description": "Channel product title" + }, + "DiscountValue": { + "type": "number" + }, + "HasImage": { + "type": "boolean", + "description": "If item got an image" + }, + "ImageId": { + "type": ["null", "string"], + "description": "Image ID" + }, + "AdditionalInfo": { + "type": "array", + "description": "List of order item options", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "pkOptionId": { + "type": "string", + "description": "Option ID" + }, + "Property": { + "type": "string", + "description": "Option property" + }, + "Value": { + "type": "string", + "description": "Value of the option" + } + } + } + }, + "StockLevelIndicator": { + "type": "integer", + "description": "Stock level indicator" + }, + "ShippingCost": { + "type": "number", + "description": "If batch number scan required" + }, + "PartShippedQty": { + "type": "integer", + "description": "ShippingCost" + }, + "ItemName": { + "type": "string", + "description": "PartShippedQty" + }, + "BatchNumberScanRequired": { + "type": "boolean", + "description": "ItemName" + }, + "SerialNumberScanRequired": { + "type": "boolean", + "description": "If serial number scan required" + }, + "BinRack": { + "type": "string", + "description": "Binrack location" + }, + "BinRacks": { + "type": "array", + "description": "List of BinRacks used for OrderItem", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "Quantity": { + "type": "integer", + "description": "Quantity for BinRack per Location" + }, + "BinRack": { + "type": "string", + "description": "BinRack" + }, + "Location": { + "type": "string", + "description": "LocationId of the BinRack" + }, + "BatchId": { + "type": ["null", "integer"], + "description": "If the item is batched, identifies the batch number" + }, + "OrderItemBatchId": { + "type": ["null", "integer"], + "description": "If the item is batched, identifies the unique order item batch row" + } + } + } + }, + "InventoryTrackingType": { + "type": "integer", + "description": "Identifies whether the item has a sell by date or other defined order in which inventory is to be sold" + }, + "isBatchedStockItem": { + "type": "boolean", + "description": "If item has batches" + }, + "IsWarehouseManaged": { + "type": "boolean" + }, + "IsUnlinked": { + "type": "boolean" + }, + "ParentItemId": { + "type": "string" + }, + "StockItemIntId": { + "type": "integer" + }, + "Boxes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "BoxId": { + "type": "integer", + "description": "Unique box id." + }, + "StockItemIntId": { + "type": "integer" + }, + "BoxName": { + "type": "string", + "description": "Box name max 16 characters" + }, + "Width": { + "type": "number", + "description": "Width of the box" + }, + "Height": { + "type": "number", + "description": "Height of the box" + }, + "Length": { + "type": "number", + "description": "Depth of the box" + }, + "Weight": { + "type": "number", + "description": "Total weight of the box." + }, + "ValuePercentage": { + "type": "number", + "description": "Value break down percentage" + }, + "Barcode": { + "type": "string", + "description": "Box barcode, max 64 characters." + }, + "PackagingTypeId": { + "type": "string", + "description": "Packaging type id" + }, + "LogicalDelete": { + "type": "boolean", + "description": "IsDeleted flag." + } + } + } + }, + "RowId": { + "type": "string", + "description": "Record row ID" + }, + "OrderId": { + "type": "string", + "description": "Order ID (pkOrderID)" + }, + "StockItemId": { + "type": "string", + "description": "Stock Item ID" + }, + "StockId": { + "type": "string" + } + } + } + }, + "Notes": { + "type": "array", + "description": "List of order notes", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "OrderNoteId": { + "type": "string", + "description": "Order note ID" + }, + "OrderId": { + "type": "string", + "description": "Order Id" + }, + "NoteDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when note was added" + }, + "Internal": { + "type": "boolean", + "description": "order note type (Internal or External)" + }, + "Note": { + "type": "string", + "description": "Note's text" + }, + "CreatedBy": { + "type": "string", + "description": "User that created note" + }, + "NoteTypeId": { + "type": ["null", "string"] + } + } + } + }, + "PaidDateTime": { + "type": ["null", "string"], + "format": "date-time", + "description": "Date and time when the order was marked as paid" + }, + "TaxId": { + "type": "string", + "description": "Buyer's tax number." + } + } + }, + "supported_sync_modes": ["full_refresh", "incremental"], + "source_defined_cursor": true, + "default_cursor_field": ["ProcessedDateTime"], + "source_defined_primary_key": [["NumOrderId"]] } ] } diff --git a/airbyte-integrations/connectors/source-linnworks/integration_tests/configured_catalog.json b/airbyte-integrations/connectors/source-linnworks/integration_tests/configured_catalog.json index d161cde9de956..42b4a9d179e02 100644 --- a/airbyte-integrations/connectors/source-linnworks/integration_tests/configured_catalog.json +++ b/airbyte-integrations/connectors/source-linnworks/integration_tests/configured_catalog.json @@ -29,7 +29,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { @@ -234,7 +234,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { @@ -280,7 +280,7 @@ "description": "if( Quantity == 0 ) dbo.StockItem.PurchasePrice Else CurrentStockValue / Quantity" }, "SKU": { - "type": "string", + "type": ["null", "string"], "description": "Product SKU" }, "AutoAdjust": { @@ -504,7 +504,7 @@ "description": "Url to full size image" }, "CheckSumValue": { - "type": "string", + "type": ["null", "string"], "description": "Image check sum" }, "pkRowId": { @@ -520,11 +520,11 @@ "description": "Sort order for the image" }, "ChecksumValue": { - "type": "string", + "type": ["null", "string"], "description": "Internal checksum value" }, "RawChecksum": { - "type": "string", + "type": ["null", "string"], "description": "Raw file checksum (Used for UI to determine if the image file is the same before submitting for upload)" }, "StockItemId": { @@ -591,7 +591,7 @@ "description": "Default package group id" }, "PackageGroupName": { - "type": "string", + "type": ["null", "string"], "description": "Default package group name" }, "Height": { @@ -656,7 +656,7 @@ "description": "Order ID" }, "cShippingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer's shipping address" }, "dReceivedDate": { @@ -738,11 +738,11 @@ "description": "Postal service code" }, "Vendor": { - "type": "string", + "type": ["null", "string"], "description": "Courier name (e.g. DPD)" }, "BillingEmailAddress": { - "type": "string" + "type": ["null", "string"] }, "ReferenceNum": { "type": "string", @@ -819,11 +819,11 @@ "description": "When order was cancelled" }, "PackageCategory": { - "type": "string", + "type": ["null", "string"], "description": "Package category" }, "PackageTitle": { - "type": "string", + "type": ["null", "string"], "description": "Package name" }, "ItemWeight": { @@ -835,51 +835,51 @@ "description": "Total order weight" }, "FolderCollection": { - "type": "string", + "type": ["null", "string"], "description": "Folder name of an order" }, "cBillingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing address" }, "BillingName": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing name" }, "BillingCompany": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing company" }, "BillingAddress1": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line one" }, "BillingAddress2": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line two" }, "BillingAddress3": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line three" }, "BillingTown": { - "type": "string", + "type": ["null", "string"], "description": "Billing town" }, "BillingRegion": { - "type": "string", + "type": ["null", "string"], "description": "Billing region, area, county" }, "BillingPostCode": { - "type": "string", + "type": ["null", "string"], "description": "Billing postcode" }, "BillingCountryName": { - "type": "string", + "type": ["null", "string"], "description": "Billing country" }, "BillingPhoneNumber": { - "type": "string", + "type": ["null", "string"], "description": "Billing phone number" }, "HoldOrCancel": { @@ -906,11 +906,886 @@ }, "supported_sync_modes": ["full_refresh", "incremental"], "source_defined_cursor": true, - "default_cursor_field": ["dReceivedDate"], + "default_cursor_field": ["dProcessedOn"], "source_defined_primary_key": [["nOrderId"]] }, "sync_mode": "incremental", "destination_sync_mode": "append_dedup" + }, + { + "stream": { + "name": "processed_order_details", + "json_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "OrderId": { + "type": "string", + "description": "Order ID (pkOrderId)" + }, + "NumOrderId": { + "type": "integer", + "description": "Linnworks order number" + }, + "Processed": { + "type": "boolean", + "description": "If order is processed" + }, + "ProcessedDateTime": { + "type": ["null", "string"], + "format": "date-time", + "description": "Date and time when order was processed" + }, + "FulfilmentLocationId": { + "type": "string", + "description": "Location ID" + }, + "GeneralInfo": { + "type": "object", + "description": "General information about order", + "additionalProperties": false, + "properties": { + "Status": { + "type": "integer", + "description": "Order Status (0 = UNPAID, 1 = PAID, 2 = RETURN, 3 = PENDING, 4 = RESEND)" + }, + "LabelPrinted": { + "type": "boolean", + "description": "Is label printed" + }, + "LabelError": { + "type": "string", + "description": "Is there a label error" + }, + "InvoicePrinted": { + "type": "boolean", + "description": "Is invoice printed" + }, + "PickListPrinted": { + "type": "boolean", + "description": "Is pick list printed" + }, + "IsRuleRun": { + "type": "boolean", + "description": "If rules engine rule ran on an order" + }, + "Notes": { + "type": "integer", + "description": "Quantity of order notes" + }, + "PartShipped": { + "type": "boolean", + "description": "If order partly shipped" + }, + "Marker": { + "type": ["null", "integer"], + "description": "Order marker (0 = NOT TAG, 1 = Tag 1, 2 = Tag 2, 3 = Tag 3, 4 = Tag 4, 5 = Tag 5, 6 = Tag 6, 7 = Parked)" + }, + "IsParked": { + "type": "boolean", + "description": "Is the order parked?" + }, + "Identifiers": { + "type": "array", + "description": "Order identifiers. [Prime | Scheduled]", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "IdentifierId": { + "type": "integer", + "description": "Internal identifier id. Use to update image and name." + }, + "IsCustom": { + "type": "boolean", + "description": "Is the tag user or system defined?" + }, + "ImageId": { + "type": "string" + }, + "ImageUrl": { + "type": "string" + }, + "Tag": { + "type": "string", + "description": "Internal tag for identification purposes" + }, + "Name": { + "type": "string", + "description": "Name displayed where the tag is used" + } + } + } + }, + "ReferenceNum": { + "type": "string", + "description": "Order reference number (Channel defined)" + }, + "SecondaryReference": { + "type": "string", + "description": "An additional reference number for the orderr (Used by some channels)" + }, + "ExternalReferenceNum": { + "type": "string", + "description": "This is an additional reference number from the sales channel, typically used by eBay" + }, + "ReceivedDate": { + "type": "string", + "format": "date-time", + "description": "The date and time at which the order was placed on the sales channel" + }, + "Source": { + "type": "string", + "description": "Order ChannelName/Source (e.g. EBAY)" + }, + "SubSource": { + "type": "string", + "description": "Order Subsource (e.g. EBAY1)" + }, + "SiteCode": { + "type": "string", + "description": "SiteCode used to differentiate between different sites from a single channel (eg. Amazon UK, Amazon US, Amazon FR...)" + }, + "HoldOrCancel": { + "type": "boolean", + "description": "This shows whether the order has been marked as on hold, for processed orders if the order has been cancelled OnHold = 1" + }, + "DespatchByDate": { + "type": "string", + "format": "date-time", + "description": "Despatch by Date" + }, + "ScheduledDelivery": { + "type": "object", + "description": "Scheduled delivery dates. Take priority over despatch by date", + "additionalProperties": false, + "properties": { + "From": { + "type": "string", + "format": "date-time" + }, + "To": { + "type": "string", + "format": "date-time" + } + } + }, + "HasScheduledDelivery": { + "type": "boolean" + }, + "Location": { + "type": "string", + "description": "Order location ID" + }, + "NumItems": { + "type": "integer", + "description": "Quantity of order items" + }, + "PickwaveIds": { + "type": "array", + "description": "All related Pickwave Ids", + "items": { + "type": "integer" + } + }, + "StockAllocationType": { + "type": ["null", "string"] + } + } + }, + "ShippingInfo": { + "type": "object", + "description": "Order shipping information", + "additionalProperties": false, + "properties": { + "Vendor": { + "type": "string", + "description": "Courier name (e.g. Royal Mail)" + }, + "PostalServiceId": { + "type": "string", + "description": "Postal service ID" + }, + "PostalServiceName": { + "type": "string", + "description": "Postal service name (e.g. Next day delivery)" + }, + "TotalWeight": { + "type": "number", + "description": "Order total weight" + }, + "ItemWeight": { + "type": "number", + "description": "If order is processed" + }, + "PackageCategoryId": { + "type": "string", + "description": "Package category ID" + }, + "PackageCategory": { + "type": "string", + "description": "Package category name" + }, + "PackageTypeId": { + "type": ["null", "string"], + "description": "Package type ID" + }, + "PackageType": { + "type": "string", + "description": "Package type name" + }, + "PostageCost": { + "type": "number", + "description": "Order postage cost" + }, + "PostageCostExTax": { + "type": "number", + "description": "Order postage cost excluding tax" + }, + "TrackingNumber": { + "type": "string", + "description": "Order tracking number provided by courier" + }, + "ManualAdjust": { + "type": "boolean", + "description": "If there is an adjustment to shipping cost was made" + } + } + }, + "CustomerInfo": { + "type": "object", + "description": "Order Customer information (Name, email etc)", + "additionalProperties": false, + "properties": { + "ChannelBuyerName": { + "type": "string", + "description": "Username of customer (Comes from channel)" + }, + "Address": { + "type": "object", + "description": "Customer address", + "additionalProperties": false, + "properties": { + "EmailAddress": { + "type": "string", + "description": "Customer's email address." + }, + "Address1": { + "type": "string", + "description": "First line of customer address." + }, + "Address2": { + "type": "string", + "description": "Second line of customer address." + }, + "Address3": { + "type": "string", + "description": "Third line of customer address." + }, + "Town": { + "type": "string", + "description": "Customer's town." + }, + "Region": { + "type": "string", + "description": "Customer's region." + }, + "PostCode": { + "type": "string", + "description": "Customer's postcode." + }, + "Country": { + "type": "string", + "description": "Customer's country." + }, + "Continent": { + "type": "string", + "description": "Customer's continent" + }, + "FullName": { + "type": "string", + "description": "Customer's first and second name." + }, + "Company": { + "type": "string", + "description": "Customer's company name." + }, + "PhoneNumber": { + "type": "string", + "description": "Customer's telephone number." + }, + "CountryId": { + "type": "string" + } + } + }, + "BillingAddress": { + "type": "object", + "description": "Customer billing address", + "additionalProperties": false, + "properties": { + "EmailAddress": { + "type": "string", + "description": "Customer's email address." + }, + "Address1": { + "type": "string", + "description": "First line of customer address." + }, + "Address2": { + "type": "string", + "description": "Second line of customer address." + }, + "Address3": { + "type": "string", + "description": "Third line of customer address." + }, + "Town": { + "type": "string", + "description": "Customer's town." + }, + "Region": { + "type": "string", + "description": "Customer's region." + }, + "PostCode": { + "type": "string", + "description": "Customer's postcode." + }, + "Country": { + "type": "string", + "description": "Customer's country." + }, + "Continent": { + "type": "string", + "description": "Customer's continent" + }, + "FullName": { + "type": "string", + "description": "Customer's first and second name." + }, + "Company": { + "type": "string", + "description": "Customer's company name." + }, + "PhoneNumber": { + "type": "string", + "description": "Customer's telephone number." + }, + "CountryId": { + "type": "string" + } + } + } + } + }, + "TotalsInfo": { + "type": "object", + "description": "Order totals information", + "additionalProperties": false, + "properties": { + "pkOrderId": { + "type": "string", + "description": "Order Id" + }, + "Subtotal": { + "type": "number", + "description": "Order subtotal" + }, + "PostageCost": { + "type": "number", + "description": "Order postage cost" + }, + "PostageCostExTax": { + "type": "number", + "description": "Order postage cost ex. tax" + }, + "Tax": { + "type": "number", + "description": "Tax" + }, + "TotalCharge": { + "type": "number", + "description": "Total charge" + }, + "PaymentMethod": { + "type": "string", + "description": "Payment method" + }, + "PaymentMethodId": { + "type": "string", + "description": "Payment method ID" + }, + "ProfitMargin": { + "type": "number", + "description": "Profit margin" + }, + "TotalDiscount": { + "type": "number", + "description": "Total discount applied to the order" + }, + "Currency": { + "type": "string", + "description": "Order currency" + }, + "CountryTaxRate": { + "type": "number", + "description": "Country tax rate" + }, + "ConversionRate": { + "type": "number", + "description": "Currency conversion rate. Set at point of save by the currency" + } + } + }, + "ExtendedProperties": { + "type": "array", + "description": "Extended properties of an order", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "RowId": { + "type": "string", + "description": "Record row ID" + }, + "Name": { + "type": "string", + "description": "Extended property name" + }, + "Value": { + "type": "string", + "description": "Extended property value" + }, + "Type": { + "type": "string", + "description": "Extended property type" + } + } + } + }, + "FolderName": { + "type": "array", + "description": "Folder names assigned to an order", + "items": { + "type": "string" + } + }, + "Items": { + "type": "array", + "description": "List of order items", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "ItemId": { + "type": "string", + "description": "Stock Item ID" + }, + "ItemNumber": { + "type": "string", + "description": "Item number as on channel" + }, + "SKU": { + "type": "string", + "description": "Product SKU" + }, + "ItemSource": { + "type": "string", + "description": "Item source / channel name" + }, + "Title": { + "type": "string", + "description": "Item title" + }, + "Quantity": { + "type": "integer", + "description": "Quantity" + }, + "CategoryId": { + "type": "string" + }, + "CategoryName": { + "type": "string", + "description": "Product category" + }, + "CompositeAvailablity": { + "type": ["null", "integer"], + "description": "Composite availability" + }, + "StockLevelsSpecified": { + "type": "boolean", + "description": "If stock level specified" + }, + "OnOrder": { + "type": "integer", + "description": "Level due in purchase orders" + }, + "OnPurchaseOrder": { + "type": "object", + "description": "Purchase order bound to this item", + "additionalProperties": false, + "properties": { + "pkPurchaseItemId": { + "type": "string", + "description": "Primary key of the bound" + }, + "Rowid": { + "type": "string" + }, + "pkPurchaseId": { + "type": "string" + }, + "ExternalInvoiceNumber": { + "type": "string" + }, + "fkSupplierId": { + "type": "string" + }, + "DateOfDelivery": { + "type": "string", + "format": "date-time" + }, + "QuotedDeliveryDate": { + "type": "string", + "format": "date-time" + }, + "SupplierName": { + "type": "string" + }, + "fkLocationId": { + "type": "string" + } + } + }, + "InOrderBook": { + "type": ["null", "integer"], + "description": "Quantity currently in open orders" + }, + "Level": { + "type": "integer", + "description": "Current stock level" + }, + "MinimumLevel": { + "type": ["null", "integer"], + "description": "Minimum level" + }, + "AvailableStock": { + "type": "integer", + "description": "Currently available stock level (Level-InOrderBook)" + }, + "PricePerUnit": { + "type": "number", + "description": "Unit price" + }, + "UnitCost": { + "type": "number", + "description": "Unit cost" + }, + "DespatchStockUnitCost": { + "type": "number", + "description": "Despatch stock unit cost" + }, + "Discount": { + "type": "number", + "description": "Percentage (0%, 10%, 20%, etc...)" + }, + "Tax": { + "type": "number", + "description": "Actual tax value on an item" + }, + "TaxRate": { + "type": "number", + "description": "Tax rate" + }, + "Cost": { + "type": "number", + "description": "Total item cost (exc tax)" + }, + "CostIncTax": { + "type": "number", + "description": "Total item cost (inc tax)" + }, + "CompositeSubItems": { + "$comment": "It should be \"$ref\": \"#/properties/Items\" but Airbyte doesn't support recursive $refs.", + "type": "array", + "items": { + "type": "object" + } + }, + "IsService": { + "type": "boolean", + "description": "if item is a service" + }, + "SalesTax": { + "type": "number", + "description": "Sales Tax" + }, + "TaxCostInclusive": { + "type": "boolean", + "description": "If tax is included in a cost" + }, + "PartShipped": { + "type": "boolean", + "description": "If order is partly shipped" + }, + "Weight": { + "type": "number", + "description": "Order weight" + }, + "BarcodeNumber": { + "type": "string", + "description": "Product barcode" + }, + "Market": { + "type": "integer", + "description": "Market" + }, + "ChannelSKU": { + "type": "string", + "description": "Channel product SKU" + }, + "ChannelTitle": { + "type": "string", + "description": "Channel product title" + }, + "DiscountValue": { + "type": "number" + }, + "HasImage": { + "type": "boolean", + "description": "If item got an image" + }, + "ImageId": { + "type": ["null", "string"], + "description": "Image ID" + }, + "AdditionalInfo": { + "type": "array", + "description": "List of order item options", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "pkOptionId": { + "type": "string", + "description": "Option ID" + }, + "Property": { + "type": "string", + "description": "Option property" + }, + "Value": { + "type": "string", + "description": "Value of the option" + } + } + } + }, + "StockLevelIndicator": { + "type": "integer", + "description": "Stock level indicator" + }, + "ShippingCost": { + "type": "number", + "description": "If batch number scan required" + }, + "PartShippedQty": { + "type": "integer", + "description": "ShippingCost" + }, + "ItemName": { + "type": "string", + "description": "PartShippedQty" + }, + "BatchNumberScanRequired": { + "type": "boolean", + "description": "ItemName" + }, + "SerialNumberScanRequired": { + "type": "boolean", + "description": "If serial number scan required" + }, + "BinRack": { + "type": "string", + "description": "Binrack location" + }, + "BinRacks": { + "type": "array", + "description": "List of BinRacks used for OrderItem", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "Quantity": { + "type": "integer", + "description": "Quantity for BinRack per Location" + }, + "BinRack": { + "type": "string", + "description": "BinRack" + }, + "Location": { + "type": "string", + "description": "LocationId of the BinRack" + }, + "BatchId": { + "type": ["null", "integer"], + "description": "If the item is batched, identifies the batch number" + }, + "OrderItemBatchId": { + "type": ["null", "integer"], + "description": "If the item is batched, identifies the unique order item batch row" + } + } + } + }, + "InventoryTrackingType": { + "type": "integer", + "description": "Identifies whether the item has a sell by date or other defined order in which inventory is to be sold" + }, + "isBatchedStockItem": { + "type": "boolean", + "description": "If item has batches" + }, + "IsWarehouseManaged": { + "type": "boolean" + }, + "IsUnlinked": { + "type": "boolean" + }, + "ParentItemId": { + "type": "string" + }, + "StockItemIntId": { + "type": "integer" + }, + "Boxes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "BoxId": { + "type": "integer", + "description": "Unique box id." + }, + "StockItemIntId": { + "type": "integer" + }, + "BoxName": { + "type": "string", + "description": "Box name max 16 characters" + }, + "Width": { + "type": "number", + "description": "Width of the box" + }, + "Height": { + "type": "number", + "description": "Height of the box" + }, + "Length": { + "type": "number", + "description": "Depth of the box" + }, + "Weight": { + "type": "number", + "description": "Total weight of the box." + }, + "ValuePercentage": { + "type": "number", + "description": "Value break down percentage" + }, + "Barcode": { + "type": "string", + "description": "Box barcode, max 64 characters." + }, + "PackagingTypeId": { + "type": "string", + "description": "Packaging type id" + }, + "LogicalDelete": { + "type": "boolean", + "description": "IsDeleted flag." + } + } + } + }, + "RowId": { + "type": "string", + "description": "Record row ID" + }, + "OrderId": { + "type": "string", + "description": "Order ID (pkOrderID)" + }, + "StockItemId": { + "type": "string", + "description": "Stock Item ID" + }, + "StockId": { + "type": "string" + } + } + } + }, + "Notes": { + "type": "array", + "description": "List of order notes", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "OrderNoteId": { + "type": "string", + "description": "Order note ID" + }, + "OrderId": { + "type": "string", + "description": "Order Id" + }, + "NoteDate": { + "type": "string", + "format": "date-time", + "description": "Date and time when note was added" + }, + "Internal": { + "type": "boolean", + "description": "order note type (Internal or External)" + }, + "Note": { + "type": "string", + "description": "Note's text" + }, + "CreatedBy": { + "type": "string", + "description": "User that created note" + }, + "NoteTypeId": { + "type": ["null", "string"] + } + } + } + }, + "PaidDateTime": { + "type": ["null", "string"], + "format": "date-time", + "description": "Date and time when the order was marked as paid" + }, + "TaxId": { + "type": "string", + "description": "Buyer's tax number." + } + } + }, + "supported_sync_modes": ["full_refresh", "incremental"], + "source_defined_cursor": true, + "default_cursor_field": ["ProcessedDateTime"], + "source_defined_primary_key": [["NumOrderId"]] + }, + "sync_mode": "incremental", + "destination_sync_mode": "append_dedup" } ] } diff --git a/airbyte-integrations/connectors/source-linnworks/integration_tests/sample_state.json b/airbyte-integrations/connectors/source-linnworks/integration_tests/sample_state.json index fc0bacca9d82f..023f9db9a5dc6 100644 --- a/airbyte-integrations/connectors/source-linnworks/integration_tests/sample_state.json +++ b/airbyte-integrations/connectors/source-linnworks/integration_tests/sample_state.json @@ -1,5 +1,8 @@ { "processed_orders": { - "dReceivedDate": "2021-01-01T00:00:00+00:00" + "dProcessedOn": "2021-11-24T00:00:00+00:00" + }, + "processed_order_details": { + "ProcessedDateTime": "2021-11-24T00:00:00+00:00" } } diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_order_details.json b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_order_details.json index a5afaaf4ca60a..f7c206789d2d9 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_order_details.json +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_order_details.json @@ -182,7 +182,7 @@ "additionalProperties": false, "properties": { "Vendor": { - "type": "string", + "type": ["null", "string"], "description": "Courier name (e.g. Royal Mail)" }, "PostalServiceId": { @@ -206,7 +206,7 @@ "description": "Package category ID" }, "PackageCategory": { - "type": "string", + "type": ["null", "string"], "description": "Package category name" }, "PackageTypeId": { @@ -470,7 +470,7 @@ "description": "Item number as on channel" }, "SKU": { - "type": "string", + "type": ["null", "string"], "description": "Product SKU" }, "ItemSource": { @@ -690,7 +690,7 @@ "description": "If serial number scan required" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Binrack location" }, "BinRacks": { diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_orders.json b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_orders.json index f6c5e796183f7..c2a7addf04b54 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_orders.json +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/processed_orders.json @@ -8,11 +8,11 @@ "description": "Order ID" }, "cShippingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer's shipping address" }, "dReceivedDate": { - "type": "string", + "type": ["null", "string"], "format": "date-time", "description": "Date when order was received on a channel" }, @@ -90,11 +90,11 @@ "description": "Postal service code" }, "Vendor": { - "type": "string", + "type": ["null", "string"], "description": "Courier name (e.g. DPD)" }, "BillingEmailAddress": { - "type": "string" + "type": ["null", "string"] }, "ReferenceNum": { "type": "string", @@ -171,11 +171,11 @@ "description": "When order was cancelled" }, "PackageCategory": { - "type": "string", + "type": ["null", "string"], "description": "Package category" }, "PackageTitle": { - "type": "string", + "type": ["null", "string"], "description": "Package name" }, "ItemWeight": { @@ -187,51 +187,51 @@ "description": "Total order weight" }, "FolderCollection": { - "type": "string", + "type": ["null", "string"], "description": "Folder name of an order" }, "cBillingAddress": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing address" }, "BillingName": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing name" }, "BillingCompany": { - "type": "string", + "type": ["null", "string"], "description": "Customer billing company" }, "BillingAddress1": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line one" }, "BillingAddress2": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line two" }, "BillingAddress3": { - "type": "string", + "type": ["null", "string"], "description": "Billing address line three" }, "BillingTown": { - "type": "string", + "type": ["null", "string"], "description": "Billing town" }, "BillingRegion": { - "type": "string", + "type": ["null", "string"], "description": "Billing region, area, county" }, "BillingPostCode": { - "type": "string", + "type": ["null", "string"], "description": "Billing postcode" }, "BillingCountryName": { - "type": "string", + "type": ["null", "string"], "description": "Billing country" }, "BillingPhoneNumber": { - "type": "string", + "type": ["null", "string"], "description": "Billing phone number" }, "HoldOrCancel": { diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_items.json b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_items.json index c878db0ee6335..115c4ccdc98e4 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_items.json +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_items.json @@ -110,7 +110,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { @@ -156,7 +156,7 @@ "description": "if( Quantity == 0 ) dbo.StockItem.PurchasePrice Else CurrentStockValue / Quantity" }, "SKU": { - "type": "string", + "type": ["null", "string"], "description": "Product SKU" }, "AutoAdjust": { @@ -380,7 +380,7 @@ "description": "Url to full size image" }, "CheckSumValue": { - "type": "string", + "type": ["null", "string"], "description": "Image check sum" }, "pkRowId": { @@ -396,11 +396,11 @@ "description": "Sort order for the image" }, "ChecksumValue": { - "type": "string", + "type": ["null", "string"], "description": "Internal checksum value" }, "RawChecksum": { - "type": "string", + "type": ["null", "string"], "description": "Raw file checksum (Used for UI to determine if the image file is the same before submitting for upload)" }, "StockItemId": { @@ -467,7 +467,7 @@ "description": "Default package group id" }, "PackageGroupName": { - "type": "string", + "type": ["null", "string"], "description": "Default package group name" }, "Height": { diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_locations.json b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_locations.json index 8ecb0bf69a214..dfdde21d0c11e 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_locations.json +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/schemas/stock_locations.json @@ -24,7 +24,7 @@ "description": "Location tag" }, "BinRack": { - "type": "string", + "type": ["null", "string"], "description": "Bin rack" }, "IsWarehouseManaged": { diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/spec.json b/airbyte-integrations/connectors/source-linnworks/source_linnworks/spec.json index d1217998871cf..7a310afa5c3ca 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/spec.json +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/spec.json @@ -1,5 +1,5 @@ { - "documentationUrl": "https://docsurl.com", + "documentationUrl": "https://docs.airbyte.io/integrations/sources/linnworks", "connectionSpecification": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Linnworks Spec", diff --git a/airbyte-integrations/connectors/source-linnworks/source_linnworks/streams.py b/airbyte-integrations/connectors/source-linnworks/source_linnworks/streams.py index 8954264048cd9..676e1c375fbe9 100644 --- a/airbyte-integrations/connectors/source-linnworks/source_linnworks/streams.py +++ b/airbyte-integrations/connectors/source-linnworks/source_linnworks/streams.py @@ -172,7 +172,7 @@ class ProcessedOrders(LinnworksGenericPagedResult, IncrementalLinnworksStream): # Response: SearchProcessedOrdersResponse https://apps.linnworks.net/Api/Class/API_Linnworks-Controllers-ProcessedOrders-Responses-SearchProcessedOrdersResponse # Allows 150 calls per minute primary_key = "nOrderId" - cursor_field = "dReceivedDate" + cursor_field = "dProcessedOn" page_size = 500 use_cache = True @@ -207,12 +207,12 @@ def request_body_data( self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None ) -> MutableMapping[str, Any]: request = { - "DateField": "received", + "DateField": "processed", "FromDate": stream_slice["FromDate"], "ToDate": stream_slice["ToDate"], "PageNumber": 1 if not next_page_token else next_page_token["PageNumber"], "ResultsPerPage": self.page_size, - "SearchSorting": {"SortField": "dReceivedDate", "SortDirection": "ASC"}, + "SearchSorting": {"SortField": "dProcessedOn", "SortDirection": "ASC"}, } return { @@ -240,11 +240,12 @@ def request_cache(self) -> Cassette: ) -class ProcessedOrderDetails(HttpSubStream, LinnworksStream): +class ProcessedOrderDetails(HttpSubStream, IncrementalLinnworksStream): # https://apps.linnworks.net/Api/Method/Orders-GetOrdersById # Response: List https://apps.linnworks.net/Api/Class/linnworks-spa-commondata-OrderManagement-ClassBase-OrderDetails # Allows 250 calls per minute primary_key = "NumOrderId" + cursor_field = "ProcessedDateTime" page_size = 100 def __init__(self, **kwargs): @@ -253,9 +254,13 @@ def __init__(self, **kwargs): def path(self, **kwargs) -> str: return "/api/Orders/GetOrdersById" - def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, any]]]: + def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, any]]]: + parent_stream_state = None + if stream_state: + parent_stream_state = {"dProcessedOn": stream_state["ProcessedDateTime"]} + buffer = [] - for slice in HttpSubStream.stream_slices(self, **kwargs): + for slice in HttpSubStream.stream_slices(self, stream_state=parent_stream_state, **kwargs): buffer.append(slice["parent"]["pkOrderID"]) if len(buffer) == self.page_size: yield buffer diff --git a/airbyte-integrations/connectors/source-linnworks/unit_tests/test_incremental_streams.py b/airbyte-integrations/connectors/source-linnworks/unit_tests/test_incremental_streams.py index febe8764fccc1..7ce246831db99 100644 --- a/airbyte-integrations/connectors/source-linnworks/unit_tests/test_incremental_streams.py +++ b/airbyte-integrations/connectors/source-linnworks/unit_tests/test_incremental_streams.py @@ -11,7 +11,9 @@ import pytest import requests import vcr -from source_linnworks.streams import IncrementalLinnworksStream, ProcessedOrders +from airbyte_cdk.models.airbyte_protocol import SyncMode +from airbyte_cdk.sources.streams.http.http import HttpSubStream +from source_linnworks.streams import IncrementalLinnworksStream, ProcessedOrderDetails, ProcessedOrders @pytest.fixture @@ -93,10 +95,10 @@ def date(*args): [ (None, None, 24, date(2050, 1, 1), date(2050, 1, 2)), (date(2050, 1, 2), None, 48, date(2050, 1, 1), date(2050, 1, 3)), - (None, {"dReceivedDate": date(2050, 1, 4)}, 1, date(2050, 1, 4), date(2050, 1, 4)), + (None, {"dProcessedOn": date(2050, 1, 4)}, 1, date(2050, 1, 4), date(2050, 1, 4)), ( date(2050, 1, 5), - {"dReceivedDate": date(2050, 1, 4)}, + {"dProcessedOn": date(2050, 1, 4)}, 48, date(2050, 1, 4), date(2050, 1, 6), @@ -104,7 +106,7 @@ def date(*args): ( # Yearly date(2052, 1, 1), - {"dReceivedDate": date(2050, 1, 1)}, + {"dProcessedOn": date(2050, 1, 1)}, 25, date(2050, 1, 1), date(2052, 1, 2), @@ -112,7 +114,7 @@ def date(*args): ( # Monthly date(2050, 4, 1), - {"dReceivedDate": date(2050, 1, 1)}, + {"dProcessedOn": date(2050, 1, 1)}, 13, date(2050, 1, 1), date(2050, 4, 2), @@ -120,7 +122,7 @@ def date(*args): ( # Weekly date(2050, 1, 31), - {"dReceivedDate": date(2050, 1, 1)}, + {"dProcessedOn": date(2050, 1, 1)}, 5, date(2050, 1, 1), date(2050, 2, 1), @@ -128,7 +130,7 @@ def date(*args): ( # Daily date(2050, 1, 1, 23, 59, 59), - {"dReceivedDate": date(2050, 1, 1)}, + {"dProcessedOn": date(2050, 1, 1)}, 24, date(2050, 1, 1), date(2050, 1, 2), @@ -213,3 +215,34 @@ def test_processed_orders_request_cache(patch_incremental_base_class, mocker): serializer="yaml", match_on=["method", "scheme", "host", "port", "path", "query", "body"], ) + + +@pytest.mark.parametrize( + ("count", "stream_state"), + [ + (5, None), + (205, None), + (5, {"ProcessedDateTime": "a-date"}), + ], +) +def test_processed_order_details_stream_slices(patch_incremental_base_class, mocker, count, stream_state): + parent_stream_slices = MagicMock(return_value=[{"parent": {"pkOrderID": str(n)}} for n in range(count)]) + mocker.patch.object(HttpSubStream, "stream_slices", parent_stream_slices) + + stream = ProcessedOrderDetails() + expected_slices = [[str(m) for m in range(count)[i : i + stream.page_size]] for i in range(0, count, stream.page_size)] + + stream_slices = stream.stream_slices(sync_mode=SyncMode.full_refresh, stream_state=stream_state) + + assert list(stream_slices) == list(expected_slices) + + actual_state = parent_stream_slices.call_args.kwargs["stream_state"] + if actual_state: + assert actual_state["dProcessedOn"] == stream_state["ProcessedDateTime"] + + +def test_processed_order_details_request_body_data(patch_incremental_base_class): + stream = ProcessedOrderDetails() + request_body_data = stream.request_body_data(None, ["abc", "def", "ghi"]) + + assert request_body_data == {"pkOrderIds": '["abc","def","ghi"]'} diff --git a/airbyte-integrations/connectors/source-linnworks/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-linnworks/unit_tests/test_streams.py index 397aaead93bfb..c29a05f410538 100644 --- a/airbyte-integrations/connectors/source-linnworks/unit_tests/test_streams.py +++ b/airbyte-integrations/connectors/source-linnworks/unit_tests/test_streams.py @@ -6,15 +6,7 @@ import pytest import requests -from airbyte_cdk.models.airbyte_protocol import SyncMode -from source_linnworks.streams import ( - LinnworksStream, - ProcessedOrderDetails, - ProcessedOrders, - StockItems, - StockLocationDetails, - StockLocations, -) +from source_linnworks.streams import LinnworksStream, StockItems, StockLocationDetails, StockLocations @pytest.fixture @@ -158,31 +150,3 @@ def test_stock_items_request_params(mocker, requests_mock, next_page_token, expe assert ("NextPageTokenKey" in params) == expected if next_page_token: assert next_page_token.items() <= params.items() - - -@pytest.mark.parametrize( - ("count"), - [ - (5), - (205), - ], -) -def test_processed_order_details_stream_slices(patch_base_class, mocker, count): - parent_records = [{"pkOrderID": str(n)} for n in range(count)] - - mocker.patch.object(ProcessedOrders, "stream_slices", MagicMock(return_value=[{}])) - mocker.patch.object(ProcessedOrders, "read_records", MagicMock(return_value=parent_records)) - - stream = ProcessedOrderDetails() - expected_slices = [[str(m) for m in range(count)[i : i + stream.page_size]] for i in range(0, count, stream.page_size)] - - stream_slices = stream.stream_slices(sync_mode=SyncMode.full_refresh) - - assert list(stream_slices) == list(expected_slices) - - -def test_processed_order_details_request_body_data(patch_base_class): - stream = ProcessedOrderDetails() - request_body_data = stream.request_body_data(None, ["abc", "def", "ghi"]) - - assert request_body_data == {"pkOrderIds": '["abc","def","ghi"]'} diff --git a/docs/integrations/sources/linnworks.md b/docs/integrations/sources/linnworks.md index d62a7fa0a9061..91423978e3f8f 100644 --- a/docs/integrations/sources/linnworks.md +++ b/docs/integrations/sources/linnworks.md @@ -54,7 +54,8 @@ Authentication credentials can be obtained on developer portal section Applicati | Version | Date | Pull Request | Subject | | :--- | :--- | :--- | :--- | -| 0.2.0 | 2021-11-24 | [8169](https://github.com/airbytehq/airbyte/pull/8169) | Source Linnworks: refactor stream StockLocations | +| 0.1.4 | 2021-11-24 | [8226](https://github.com/airbytehq/airbyte/pull/8226) | Source Linnworks: improve streams ProcessedOrders and ProcessedOrderDetails | +| 0.1.3 | 2021-11-24 | [8169](https://github.com/airbytehq/airbyte/pull/8169) | Source Linnworks: refactor stream StockLocations | | 0.1.2 | 2021-11-23 | [8177](https://github.com/airbytehq/airbyte/pull/8177) | Source Linnworks: add stream ProcessedOrderDetails | | 0.1.0 | 2021-11-09 | [7588](https://github.com/airbytehq/airbyte/pull/7588) | New Source: Linnworks |