diff --git a/components/adyen/adyen.app.mjs b/components/adyen/adyen.app.mjs index 14f3080bdb22d..fad4791b3f88f 100644 --- a/components/adyen/adyen.app.mjs +++ b/components/adyen/adyen.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/autoblogger/autoblogger.app.mjs b/components/autoblogger/autoblogger.app.mjs index 977c564f05a55..9e54a87dfec80 100644 --- a/components/autoblogger/autoblogger.app.mjs +++ b/components/autoblogger/autoblogger.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/tess_ai_by_pareto/tess_ai_by_pareto.app.mjs b/components/tess_ai_by_pareto/tess_ai_by_pareto.app.mjs index 50e938b2e49d1..a07f40f61533f 100644 --- a/components/tess_ai_by_pareto/tess_ai_by_pareto.app.mjs +++ b/components/tess_ai_by_pareto/tess_ai_by_pareto.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/zenventory/actions/create-customer-order/create-customer-order.mjs b/components/zenventory/actions/create-customer-order/create-customer-order.mjs new file mode 100644 index 0000000000000..b2d4f6545f087 --- /dev/null +++ b/components/zenventory/actions/create-customer-order/create-customer-order.mjs @@ -0,0 +1,345 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { POSTAGE_ACCOUNT_OPTIONS } from "../../common/constants.mjs"; +import { parseObject } from "../../common/utils.mjs"; +import zenventory from "../../zenventory.app.mjs"; + +export default { + key: "zenventory-create-customer-order", + name: "Create Customer Order", + description: "Creates a new customer order. [See the documentation](https://docs.zenventory.com/#tag/customer_order/paths/~1customer-orders/post)", + version: "0.0.1", + type: "action", + props: { + zenventory, + orderNumber: { + type: "string", + label: "Order Number", + description: "Order number for the customer order.", + optional: true, + }, + clientId: { + propDefinition: [ + zenventory, + "clientId", + ], + optional: true, + }, + clientName: { + propDefinition: [ + zenventory, + "clientName", + ], + optional: true, + }, + customerId: { + type: "integer", + label: "Customer Id", + description: "Id of the customer. If none is provided, will attempt to find an existing customer based on the other customer fields and shipping address. Other fields not used if id is provided.", + optional: true, + }, + title: { + type: "string", + label: "Customer Title", + description: "The title of the customer.", + optional: true, + }, + name: { + type: "string", + label: "Customer Name", + description: "A combination of name and surname is required if the customer is new.", + optional: true, + }, + surname: { + type: "string", + label: "Customer Surname", + description: "A combination of name and surname is required if the customer is new.", + optional: true, + }, + email: { + type: "string", + label: "Customer Email", + description: "The email of the customer.", + optional: true, + }, + customerCompany: { + type: "string", + label: "Customer Company", + description: "The company of the customer.", + optional: true, + }, + accountNumber: { + type: "string", + label: "Customer Account Number", + description: "Will only match a customer on this field if provided.", + optional: true, + }, + shippingAddressId: { + type: "integer", + label: "Shipping Address Id", + description: "Id of the shipping address. **Other Shipping fields will not be used if provided.**", + optional: true, + }, + shippingAddressCode: { + type: "string", + label: "Shipping Address Code", + description: "Used to find an existing address. Other fields not used if an address is successfully found.", + optional: true, + }, + shippingAddressCompany: { + type: "string", + label: "Shipping Address Company", + description: "The company of the shipping address.", + optional: true, + }, + shippingAddressName: { + type: "string", + label: "Shipping Address Name", + description: "The name of the shipping address.", + optional: true, + }, + shippingAddressline1: { + type: "string", + label: "Shipping Address Line 1", + description: "The shipping address line 1.", + optional: true, + }, + shippingAddressline2: { + type: "string", + label: "Shipping Address Line 2", + description: "The shipping address line 2.", + optional: true, + }, + shippingAddressline3: { + type: "string", + label: "Shipping Address Line 3", + description: "The shipping address line 3.", + optional: true, + }, + shippingAddressCity: { + type: "string", + label: "Shipping Address City", + description: "The city of the shipping address.", + optional: true, + }, + shippingAddressState: { + type: "string", + label: "Shipping Address State", + description: "The state of the shipping address.", + optional: true, + }, + shippingAddressZip: { + type: "string", + label: "Shipping Address Zip", + description: "The zip of the shipping address.", + optional: true, + }, + shippingAddressCountryCode: { + type: "string", + label: "Shipping Address Country Code", + description: "The country code of the shipping address. [See the ISO 3166 codes](https://www.iban.com/country-codes).", + optional: true, + }, + shippingAddressPhone: { + type: "string", + label: "Shipping Address Phone", + description: "The phone of the shipping address.", + optional: true, + }, + sameAsShipping: { + type: "boolean", + label: "Same As Shipping", + description: "True if the billing address is the same as the shipping address.", + reloadProps: true, + optional: true, + }, + shipFromWarehouseId: { + type: "string", + label: "Ship From Warehouse Id", + description: "Id of the warehouse the ordered items will be allocated from. If no warehouse parameters are given, then the user's current warehouse will be used.", + optional: true, + }, + shipFromWarehouseName: { + type: "string", + label: "Ship From Warehouse Name", + description: "Name of the warehouse the ordered items will be allocated from. Ignored if warehouseId is provided.", + optional: true, + }, + shipVia: { + type: "string", + label: "Ship Via", + description: "Code of the carrier or service to use for shipping.", + optional: true, + }, + postageAccount: { + type: "string", + label: "Postage Account", + description: "Who to bill for shipping.", + options: POSTAGE_ACCOUNT_OPTIONS, + optional: true, + }, + items: { + type: "string[]", + label: "Items", + description: "An array of objects of ordered items. **Example: {\"itemId\": \"123\", \"sku\": \"SKU123\", \"quantity\": 1}** [See the documentation](https://docs.zenventory.com/#tag/customer_order/paths/~1customer-orders/post) fro further information.", + optional: true, + }, + }, + async additionalProps() { + const props = {}; + + if (!this.sameAsShipping) { + props.billingAddressId = { + type: "integer", + label: "Billing Address Id", + description: "Id of the billing address. **Other Billing fields will not be used if provided.**", + optional: true, + }; + props.billingAddressCode = { + type: "string", + label: "Billing Address Code", + description: "Used to find an existing address. Other fields not used if an address is successfully found.", + optional: true, + }; + props.billingAddressCompany = { + type: "string", + label: "Billing Address Company", + description: "The company of the billing address.", + optional: true, + }; + props.billingAddressName = { + type: "string", + label: "Billing Address Name", + description: "The name of the billing address.", + optional: true, + }; + props.billingAddressline1 = { + type: "string", + label: "Billing Address Line 1", + description: "The billing address line 1.", + optional: true, + }; + props.billingAddressline2 = { + type: "string", + label: "Billing Address Line 2", + description: "The billing address line 2.", + optional: true, + }; + props.billingAddressline3 = { + type: "string", + label: "Billing Address Line 3", + description: "The billing address line 3.", + optional: true, + }; + props.billingAddressCity = { + type: "string", + label: "Billing Address City", + description: "The city of the billing address.", + optional: true, + }; + props.billingAddressState = { + type: "string", + label: "Billing Address State", + description: "The state of the billing address.", + optional: true, + }; + props.billingAddressZip = { + type: "string", + label: "Billing Address Zip", + description: "The zip of the billing address.", + optional: true, + }; + props.billingAddressCountryCode = { + type: "string", + label: "Billing Address Country Code", + description: "The country code of the billing address. [See the ISO 3166 codes](https://www.iban.com/country-codes).", + optional: true, + }; + props.billingAddressPhone = { + type: "string", + label: "Billing Address Phone", + description: "The phone of the billing address.", + optional: true, + }; + } + return props; + }, + async run({ $ }) { + if (!this.customerId && + !this.title && + !this.name && + !this.surname && + !this.email && + !this.customerCompany && + !this.accountNumber) { + throw new ConfigurationError("You must provide at least 'Customer Id', 'Customer Title', 'Customer Name', 'Customer Surname', 'Customer Email', 'Customer Company' or 'Customer Account Number'."); + } + + if (!this.shippingAddressId && + !this.shippingAddressline1 && + !this.shippingAddressCountryCode) { + throw new ConfigurationError("You must provide at least 'Shipping Address Id' or 'Shipping Address Line1' and 'Shipping Address Country Code'."); + } + + if (!this.sameAsShipping && + !this.billingAddressId && + !this.billingAddressline1 && + !this.billingAddressCountryCode) { + throw new ConfigurationError("When 'Same As Shipping' is set **False** you must provide at least 'Billing Address Id' or 'Billing Address Line1' and 'Billing Address Country Code'."); + } + + const response = await this.zenventory.createCustomerOrder({ + $, + data: { + orderNumber: this.orderNumber, + clientId: this.clientId, + clientName: this.clientName, + customer: { + id: this.customerId, + title: this.title, + name: this.name, + surname: this.surname, + email: this.email, + company: this.customerCompany, + accountNumber: this.accountNumber, + }, + shippingAddress: { + id: this.shippingAddressId, + code: this.shippingAddressCode, + company: this.shippingAddressCompany, + name: this.shippingAddressName, + line1: this.shippingAddressline1, + line2: this.shippingAddressline2, + line3: this.shippingAddressline3, + city: this.shippingAddressCity, + state: this.shippingAddressState, + zip: this.shippingAddressZip, + countryCode: this.shippingAddressCountryCode, + phone: this.shippingAddressPhone, + }, + billingAddress: { + sameAsShipping: this.sameAsShipping, + id: this.billingAddressId, + code: this.billingAddressCode, + company: this.billingAddressCompany, + name: this.billingAddressName, + line1: this.billingAddressline1, + line2: this.billingAddressline2, + line3: this.billingAddressline3, + city: this.billingAddressCity, + state: this.billingAddressState, + zip: this.billingAddressZip, + countryCode: this.billingAddressCountryCode, + phone: this.billingAddressPhone, + }, + shipFromWarehouseId: this.shipFromWarehouseId, + shipFromWarehouseName: this.shipFromWarehouseName, + shipVia: this.shipVia, + postageAccount: this.postageAccount, + items: parseObject(this.items), + }, + }); + + $.export("$summary", `Successfully created customer order with ID ${response.id}`); + return response; + }, +}; diff --git a/components/zenventory/actions/create-item/create-item.mjs b/components/zenventory/actions/create-item/create-item.mjs new file mode 100644 index 0000000000000..23c74e727ba66 --- /dev/null +++ b/components/zenventory/actions/create-item/create-item.mjs @@ -0,0 +1,284 @@ +import zenventory from "../../zenventory.app.mjs"; + +export default { + key: "zenventory-create-item", + name: "Create Item", + description: "Generates a new item. [See the documentation](https://docs.zenventory.com/#tag/items/paths/~1items/post)", + version: "0.0.1", + type: "action", + props: { + zenventory, + sku: { + type: "string", + label: "SKU", + description: "The item's SKU.", + }, + clientId: { + propDefinition: [ + zenventory, + "clientId", + ], + description: "Id of the client that the item belongs to. Defaults to the user's client id.", + optional: true, + }, + clientName: { + propDefinition: [ + zenventory, + "clientName", + ], + description: "Name of the client that the item belongs to. Ignored if clientId is provided and is nonzero.", + optional: true, + }, + upc: { + type: "string", + label: "UPC", + description: "The item's UPC.", + optional: true, + }, + description: { + type: "string", + label: "Description", + description: "The item's description.", + optional: true, + }, + category: { + type: "string", + label: "Category", + description: "The item's category to be grouped by.", + optional: true, + }, + baseUom: { + type: "string", + label: "Base UOM", + description: "The item's base unit of measurement.", + optional: true, + }, + unitCost: { + type: "string", + label: "Unit Cost", + description: "How much the item costs you to stock.", + optional: true, + }, + leadTime: { + type: "integer", + label: "Lead Time", + description: "The item's lead time.", + optional: true, + }, + defaultEconOrder: { + type: "integer", + label: "Default Econ Order", + description: "The item's default order quantity for purchase orders.", + optional: true, + }, + orderLimit: { + type: "integer", + label: "Order Limit", + description: "The item's order limit.", + optional: true, + }, + rrp: { + type: "string", + label: "RRP", + description: "The item's recommended retail price.", + optional: true, + }, + price: { + type: "string", + label: "Price", + description: "How much the item is sold for.", + optional: true, + }, + active: { + type: "boolean", + label: "Active", + description: "True if the item is active. Inactive items are hidden from most processes.", + optional: true, + }, + kit: { + type: "boolean", + label: "Kit", + description: "True if the item is a kit item made up of other items. An item cannot both be a kit and an assembly item.", + optional: true, + }, + assembly: { + type: "boolean", + label: "Assembly", + description: "True if the item is stocked by combining other items together. An item cannot both be a kit and an assembly item.", + optional: true, + }, + perishable: { + type: "boolean", + label: "Perishable", + description: "True if the item has an expiration date. A non-inventory or serialized item cannot also be this.", + optional: true, + }, + trackLot: { + type: "boolean", + label: "Track Lot", + description: "True if the item is tracked by lot numbers. A non-inventory or serialized item cannot also be this.", + optional: true, + }, + serialized: { + type: "boolean", + label: "Serialized", + description: "True if the item is tracked by serial numbers. A non-inventory item cannot be serialized.", + optional: true, + }, + nonInventory: { + type: "boolean", + label: "Non Inventory", + description: "True if the item does not have inventory. A kit or assembly cannot also be non-inventory.", + optional: true, + }, + weight: { + type: "string", + label: "Weight", + description: "The item's weight.", + optional: true, + }, + storageLength: { + type: "string", + label: "Storage Length", + description: "Part of the dimensions the item takes to store.", + optional: true, + }, + storageWidth: { + type: "string", + label: "Storage Width", + description: "Part of the dimensions the item takes to store.", + optional: true, + }, + storageHeight: { + type: "string", + label: "Storage Height", + description: "Part of the dimensions the item takes to store.", + optional: true, + }, + safetyStock: { + type: "integer", + label: "Safety Stock", + description: "How much stock should be withheld when reporting stock levels to marketplace integrations.", + optional: true, + }, + userField1: { + type: "string", + label: "User Field 1", + description: "User defined field for the item.", + optional: true, + }, + userField2: { + type: "string", + label: "User Field 2", + description: "User defined field for the item.", + optional: true, + }, + userField3: { + type: "string", + label: "User Field 3", + description: "User defined field for the item.", + optional: true, + }, + userField4: { + type: "string", + label: "User Field 4", + description: "User defined field for the item.", + optional: true, + }, + userField5: { + type: "string", + label: "User Field 5", + description: "User defined field for the item.", + optional: true, + }, + userField6: { + type: "string", + label: "User Field 6", + description: "User defined field for the item.", + optional: true, + }, + notes: { + type: "string", + label: "Notes", + description: "Notes for the item.", + optional: true, + }, + assignToAllWarehouses: { + type: "boolean", + label: "Assign To All Warehouses", + description: "True to assign to all warehouses on creation.", + optional: true, + }, + assignToWarehouse: { + type: "boolean", + label: "Assign To Warehouse", + description: "True to assign the item to a specific warehouse.", + optional: true, + }, + warehouseId: { + type: "integer", + label: "Warehouse Id", + description: "Id of the warehouse the item will be assigned to. If no warehouse parameters are given, then the user's current warehouse will be used.", + optional: true, + }, + warehouseName: { + type: "string", + label: "Warehouse Name", + description: "Name of the warehouse the item will be assigned to. Ignored if warehouseId is provided.", + optional: true, + }, + reorderLevel: { + type: "integer", + label: "Reorder Level", + description: "Reorder level for the item's warehouse assignment.", + optional: true, + }, + }, + async run({ $ }) { + const response = await this.zenventory.createItem({ + $, + data: { + sku: this.sku, + clientId: this.clientId, + clientName: this.clientName, + upc: this.upc, + description: this.description, + category: this.category, + baseUom: this.baseUom, + unitCost: this.unitCost && parseFloat(this.unitCost), + leadTime: this.leadTime, + defaultEconOrder: this.defaultEconOrder, + orderLimit: this.orderLimit, + rrp: this.rrp && parseFloat(this.rrp), + price: this.price && parseFloat(this.price), + active: this.active, + kit: this.kit, + assembly: this.assembly, + perishable: this.perishable, + trackLot: this.trackLot, + serialized: this.serialized, + nonInventory: this.nonInventory, + weight: this.weight && parseFloat(this.weight), + storageLength: this.storageLength && parseFloat(this.storageLength), + storageWidth: this.storageWidth && parseFloat(this.storageWidth), + storageHeight: this.storageHeight && parseFloat(this.storageHeight), + safetyStock: this.safetyStock, + userField1: this.userField1, + userField2: this.userField2, + userField3: this.userField3, + userField4: this.userField4, + userField5: this.userField5, + userField6: this.userField6, + notes: this.notes, + assignToAllWarehouses: this.assignToAllWarehouses, + assignToWarehouse: this.assignToWarehouse, + warehouseId: this.warehouseId, + warehouseName: this.warehouseName, + reorderLevel: this.reorderLevel, + }, + }); + + $.export("$summary", `Successfully created purchase order with ID ${response.id}`); + return response; + }, +}; diff --git a/components/zenventory/actions/create-purchase-order/create-purchase-order.mjs b/components/zenventory/actions/create-purchase-order/create-purchase-order.mjs new file mode 100644 index 0000000000000..f69431adca7a5 --- /dev/null +++ b/components/zenventory/actions/create-purchase-order/create-purchase-order.mjs @@ -0,0 +1,112 @@ +import { ConfigurationError } from "@pipedream/platform"; +import { parseObject } from "../../common/utils.mjs"; +import zenventory from "../../zenventory.app.mjs"; + +export default { + key: "zenventory-create-purchase-order", + name: "Create Purchase Order", + description: "Generates a new purchase order. [See the documentation](https://docs.zenventory.com/)", + version: "0.0.1", + type: "action", + props: { + zenventory, + supplierId: { + type: "integer", + label: "Supplier Id", + description: "Id of the supplier that is being ordered from.", + optional: true, + }, + supplierName: { + type: "string", + label: "Supplier Name", + description: "Name of the supplier that is being ordered from. Ignored if supplierId is provided.", + optional: true, + }, + warehouseId: { + type: "integer", + label: "Warehouse Id", + description: "Id of the warehouse the items will be delivered to. If no warehouse parameters are given, then the user's current warehouse will be used.", + optional: true, + }, + warehouseName: { + type: "string", + label: "Warehouse Name", + description: "Name of the warehouse the items will be delivered to. Ignored if warehouseId is provided.", + optional: true, + }, + clientId: { + type: "integer", + label: "Client Id", + description: "Id of the client that the purchase order is for. Defaults to the user's client id.", + optional: true, + }, + clientName: { + type: "string", + label: "Client Name", + description: "Name of the client that the purchase order is for. Ignored if clientId is provided and is nonzero.", + optional: true, + }, + orderNumber: { + type: "string", + label: "Order Number", + description: "Order number for the purchase order. If blank, one will automatically be generated.", + optional: true, + }, + draft: { + type: "boolean", + label: "Draft", + description: "True if the purchase order should be created as a draft to allow future editing.", + optional: true, + }, + requiredByDate: { + type: "string", + label: "Required By.", + description: "The date of the purchase. **Format: YYYY-MM-DD**", + optional: true, + }, + projectNumber: { + type: "string", + label: "Project Number", + description: "The number of the project.", + optional: true, + }, + notes: { + type: "string", + label: "Notes", + description: "A note of the purchase.", + optional: true, + }, + items: { + type: "string[]", + label: "Items", + description: "A list of object of ordered items. **Example: {\"itemId\": 123, \"sku\": \"SKU123\", \"description\": \"description\", \"quantity\": 1}**. [See the documentation](https://docs.zenventory.com/#tag/purchase_order/paths/~1purchase-orders/post) for further information.", + optional: true, + }, + }, + async run({ $ }) { + if (!this.supplierId && !this.supplierName) { + throw new ConfigurationError("You must provide at least 'Supplier Id' or 'Supplier Name'."); + } + + const response = await this.zenventory.createPurchaseOrder({ + $, + data: { + supplierId: this.supplierId, + supplierName: this.supplierName, + warehouseId: this.warehouseId, + warehouseName: this.warehouseName, + clientId: this.clientId, + clientName: this.clientName, + orderNumber: this.orderNumber, + draft: this.draft, + requiredByDate: this.requiredByDate, + projectNumber: this.projectNumber, + notes: this.notes, + items: parseObject(this.items), + }, + }); + + $.export("$summary", `Successfully created purchase order with ID ${response.id}`); + return response; + }, +}; diff --git a/components/zenventory/common/constants.mjs b/components/zenventory/common/constants.mjs new file mode 100644 index 0000000000000..a3deffb7fea4d --- /dev/null +++ b/components/zenventory/common/constants.mjs @@ -0,0 +1,5 @@ +export const POSTAGE_ACCOUNT_OPTIONS = [ + "sender", + "client", + "recipient", +]; diff --git a/components/zenventory/common/utils.mjs b/components/zenventory/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/zenventory/common/utils.mjs @@ -0,0 +1,24 @@ +export const parseObject = (obj) => { + if (!obj) return undefined; + + if (Array.isArray(obj)) { + return obj.map((item) => { + if (typeof item === "string") { + try { + return JSON.parse(item); + } catch (e) { + return item; + } + } + return item; + }); + } + if (typeof obj === "string") { + try { + return JSON.parse(obj); + } catch (e) { + return obj; + } + } + return obj; +}; diff --git a/components/zenventory/package.json b/components/zenventory/package.json index 661634cbd9795..472c998de416a 100644 --- a/components/zenventory/package.json +++ b/components/zenventory/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/zenventory", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Zenventory Components", "main": "zenventory.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.3" } -} \ No newline at end of file +} diff --git a/components/zenventory/sources/common/base.mjs b/components/zenventory/sources/common/base.mjs new file mode 100644 index 0000000000000..bd8177f772a9f --- /dev/null +++ b/components/zenventory/sources/common/base.mjs @@ -0,0 +1,72 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import zenventory from "../../zenventory.app.mjs"; + +export default { + props: { + zenventory, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || "1970-01-01T00:00:01"; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + prepareData({ + responseArray, fieldDate, + }) { + if (responseArray.length) { + this._setLastDate(responseArray[0][fieldDate]); + } + return responseArray; + }, + emitData(data) { + for (const item of data.reverse()) { + this.$emit(item, { + id: item.id, + summary: this.getSummary(item), + ts: Date.parse(new Date()), + }); + } + }, + async emitEvent(maxResults = false) { + const lastDate = this._getLastDate(); + const fieldDate = this.getFieldDate(); + + const response = this.zenventory.paginate({ + fn: this.getFunction(), + params: this.getParams(lastDate), + dataField: this.getDataField(), + maxResults, + }); + + let responseArray = []; + for await (const item of response) { + responseArray.push(item); + } + + const preparedData = this.prepareData({ + responseArray, + fieldDate, + maxResults, + }); + + this.emitData(preparedData); + }, + }, + hooks: { + async deploy() { + await this.emitEvent(25); + }, + }, + async run() { + await this.emitEvent(); + }, +}; diff --git a/components/zenventory/sources/new-customer-order/new-customer-order.mjs b/components/zenventory/sources/new-customer-order/new-customer-order.mjs new file mode 100644 index 0000000000000..62da2a2003e41 --- /dev/null +++ b/components/zenventory/sources/new-customer-order/new-customer-order.mjs @@ -0,0 +1,46 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "zenventory-new-customer-order", + name: "New Customer Order Created", + description: "Emit new event when a new customer order is created.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + prepareData({ + responseArray, fieldDate, maxResults, + }) { + responseArray.reverse(); + if (responseArray.length) { + if (maxResults && responseArray.length > maxResults) { + responseArray.length = maxResults; + } + this._setLastDate(responseArray[0][fieldDate]); + } + return responseArray; + }, + getParams(orderedDate) { + return { + orderedDate, + orderedDateConditional: "on_or_after", + }; + }, + getFunction() { + return this.zenventory.listCustomerOrders; + }, + getDataField() { + return "customerOrders"; + }, + getFieldDate() { + return "orderedDate"; + }, + getSummary(item) { + return `New Customer Order: ${item.orderNumber}`; + }, + }, + sampleEmit, +}; diff --git a/components/zenventory/sources/new-customer-order/test-event.mjs b/components/zenventory/sources/new-customer-order/test-event.mjs new file mode 100644 index 0000000000000..aa1d145c03e70 --- /dev/null +++ b/components/zenventory/sources/new-customer-order/test-event.mjs @@ -0,0 +1,109 @@ +export default { + "id": 103717, + "orderNumber": "Test-Order-001", + "orderReference": "", + "customer": { + "id": 7089, + "title": "", + "name": "Test Customer 1", + "surname": "", + "email": "testcustomer1@testserver.com", + "company": "Test Company", + "accountNumber": "" + }, + "client": null, + "orderedDate": "2021-12-13T00:00:00-07:00", + "createdDate": "2024-09-13T13:02:58-07:00", + "modifiedDate": "2024-09-13T13:02:58-07:00", + "orderPlaced": true, + "createdBy": { + "id": 520, + "name": "Pipedream Support" + }, + "completed": false, + "completedDate": "", + "cancelled": false, + "cancelledDate": "", + "cancelledReason": "", + "cancelledBy": null, + "onHold": false, + "onHoldUntil": "", + "postageAccount": "sender", + "buyerPaidShipping": 0, + "shippingAddress": { + "id": 12517, + "company": "", + "name": "", + "line1": "515 E Grant St", + "line2": "", + "line3": "", + "city": "Phoenix", + "state": "AZ", + "zip": "85004", + "country": "United States", + "countryCode": "US", + "phone": "", + "code": "", + "verifiedStatus": "awaiting", + "verifiedDate": "", + "verifiedMessage": "" + }, + "billingAddress": { + "id": 12518, + "company": "", + "name": "", + "line1": "N/A", + "line2": "", + "line3": "", + "city": "", + "state": "", + "zip": "", + "country": "United States", + "countryCode": "US", + "phone": "", + "code": "", + "verifiedStatus": "awaiting", + "verifiedDate": "", + "verifiedMessage": "" + }, + "shipVia": "Standard", + "shipViaPackaging": "", + "shipViaConfirmation": "", + "dryIceWeight": 0, + "packageSku": "", + "shipFromWarehouse": { + "id": 187, + "name": "Main Warehouse" + }, + "projectNumber": "", + "discountPercentage": 0, + "orderSource": "CSV Import", + "internalNote": "", + "noteFromCustomer": "", + "noteToCustomer": "", + "notificationEmail": "", + "userField1": "", + "userField2": "", + "userField3": "", + "myList1": "", + "myList2": "", + "tags": [], + "items": [ + { + "id": 214405, + "itemId": 12063, + "sku": "TEST-SKU-101", + "description": "Baseball Cap", + "orderQuantity": 1, + "uom": "Each", + "quantity": 1, + "allocatedQuantity": 1, + "pickedQuantity": 0, + "price": 49, + "discountPercentage": 0, + "partOfKit": false, + "componentOf": 0, + "additionalFields": null + } + ] +} \ No newline at end of file diff --git a/components/zenventory/sources/new-item-created/new-item-created.mjs b/components/zenventory/sources/new-item-created/new-item-created.mjs new file mode 100644 index 0000000000000..9e8d9319da152 --- /dev/null +++ b/components/zenventory/sources/new-item-created/new-item-created.mjs @@ -0,0 +1,56 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "zenventory-new-item-created", + name: "New Item Created", + description: "Emit new event when a new item is created.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getFieldDate() { + return "createdDate"; + }, + getSummary(item) { + return `New Item: ${item.sku}`; + }, + _getLastId() { + return this.db.get("lastId") || 0; + }, + _setLastId(lastId) { + this.db.set("lastId", lastId); + }, + async emitEvent(maxResults = false) { + const lastId = this._getLastId(); + + const response = this.zenventory.paginate({ + fn: this.zenventory.listItems, + params: { + orderBy: "id", + orderDir: "desc", + }, + dataField: "items", + maxResults, + }); + + let responseArray = []; + for await (const item of response) { + if (item.id <= lastId) break; + responseArray.push(item); + } + + if (responseArray.length) { + if (maxResults && responseArray.length > maxResults) { + responseArray.length = maxResults; + } + this._setLastId(responseArray[0].id); + } + + this.emitData(responseArray); + }, + }, + sampleEmit, +}; diff --git a/components/zenventory/sources/new-item-created/test-event.mjs b/components/zenventory/sources/new-item-created/test-event.mjs new file mode 100644 index 0000000000000..bde5e051fb52e --- /dev/null +++ b/components/zenventory/sources/new-item-created/test-event.mjs @@ -0,0 +1,44 @@ +export default { + "id": 2306, + "sku": "FumoFumo-002", + "upc": "", + "description": "Marisa Kirisame", + "category": "Fumo", + "client": null, + "baseUom": "Each", + "unitCost": 10, + "leadTime": 0, + "defaultEconOrder": 0, + "rrp": 0, + "price": 50, + "active": true, + "kit": false, + "assembly": false, + "perishable": false, + "trackLot": false, + "serialized": false, + "nonInventory": false, + "weight": 0, + "storageLength": 0, + "storageWidth": 0, + "storageHeight": 0, + "storageVolume": 0, + "safetyStock": 0, + "userField1": "", + "userField2": "", + "userField3": "", + "userField4": "", + "userField5": "", + "userField6": "", + "createdDate": "2017-08-06T10:45:53-07:00", + "modifiedDate": "2017-08-06T10:45:53-07:00", + "notes": "", + "additionalFields": { + "units": [ + { + "name": "Each", + "quantity": 1 + } + ] + } +} \ No newline at end of file diff --git a/components/zenventory/sources/new-purchase-order/new-purchase-order.mjs b/components/zenventory/sources/new-purchase-order/new-purchase-order.mjs new file mode 100644 index 0000000000000..9c979313317de --- /dev/null +++ b/components/zenventory/sources/new-purchase-order/new-purchase-order.mjs @@ -0,0 +1,35 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "zenventory-new-purchase-order", + name: "New Purchase Order Created", + description: "Emit new event when a new purchase order is created.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getParams(lastDate) { + return { + createdFrom: lastDate, + orderBy: "createdDate", + orderDir: "desc", + }; + }, + getFunction() { + return this.zenventory.listPurchaseOrders; + }, + getDataField() { + return "purchaseOrders"; + }, + getFieldDate() { + return "createdDate"; + }, + getSummary(item) { + return `New Purchase Order: ${item.orderNumber}`; + }, + }, + sampleEmit, +}; diff --git a/components/zenventory/sources/new-purchase-order/test-event.mjs b/components/zenventory/sources/new-purchase-order/test-event.mjs new file mode 100644 index 0000000000000..5e0b55e3aed9e --- /dev/null +++ b/components/zenventory/sources/new-purchase-order/test-event.mjs @@ -0,0 +1,32 @@ +export default { + "id": 3858, + "orderNumber": "000000", + "supplier": { + "id": 569, + "name": "Default Supplier" + }, + "warehouse": { + "id": 187, + "name": "Main Warehouse" + }, + "client": null, + "user": { + "id": 123, + "name": "User Name" + }, + "draft": true, + "completed": false, + "deleted": false, + "createdDate": "2024-10-07T11:00:31-07:00", + "preparedDate": "", + "requiredByDate": "2024-10-07", + "completedDate": "", + "projectNumber": "", + "notes": "", + "shipMethod": "", + "terms": "", + "userField1": "", + "userField2": "", + "userField3": "", + "items": [] +} \ No newline at end of file diff --git a/components/zenventory/zenventory.app.mjs b/components/zenventory/zenventory.app.mjs index 89694bc52cc9b..325b26763d724 100644 --- a/components/zenventory/zenventory.app.mjs +++ b/components/zenventory/zenventory.app.mjs @@ -1,11 +1,103 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "zenventory", - propDefinitions: {}, + propDefinitions: { + clientId: { + type: "integer", + label: "Client Id", + description: "Id of the client that the customer order is for.", + }, + clientName: { + type: "string", + label: "Client Name", + description: "Name of the client that the customer order is for. **Ignored if clientId is provided and is nonzero.**", + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://app.zenventory.com/rest"; + }, + _auth() { + return { + username: `${this.$auth.api_key}`, + password: `${this.$auth.api_secret}`, + }; + }, + _makeRequest({ + $ = this, method = "GET", path, ...opts + }) { + return axios($, { + method, + url: this._baseUrl() + path, + auth: this._auth(), + ...opts, + }); + }, + createItem(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/items", + ...opts, + }); + }, + createCustomerOrder(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/customer-orders", + ...opts, + }); + }, + createPurchaseOrder(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/purchase-orders", + ...opts, + }); + }, + listCustomerOrders(opts = {}) { + return this._makeRequest({ + path: "/customer-orders", + ...opts, + }); + }, + listPurchaseOrders(opts = {}) { + return this._makeRequest({ + path: "/purchase-orders", + ...opts, + }); + }, + listItems(opts = {}) { + return this._makeRequest({ + path: "/items", + ...opts, + }); + }, + async *paginate({ + fn, params = {}, dataField, maxResults = null, ...opts + }) { + let hasMore = false; + let count = 0; + let page = 0; + + do { + params.page = ++page; + const response = await fn({ + params, + ...opts, + }); + for (const d of response[dataField]) { + yield d; + + if (maxResults && ++count === maxResults) { + return count; + } + } + + hasMore = page < response.meta.totalPages; + + } while (hasMore); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4f738769868e4..c5838400db1f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11456,7 +11456,10 @@ importers: specifiers: {} components/zenventory: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.3 + dependencies: + '@pipedream/platform': 3.0.3 components/zerobounce: specifiers: {} @@ -13012,55 +13015,6 @@ packages: - aws-crt dev: false - /@aws-sdk/client-sso-oidc/3.600.0_tdq3komn4zwyd65w7klbptsu34: - resolution: {integrity: sha512-7+I8RWURGfzvChyNQSyj5/tKrqRbzRl7H+BnTOf/4Vsw1nFOi5ROhlhD4X/Y0QCTacxnaoNcIrqnY7uGGvVRzw==} - engines: {node: '>=16.0.0'} - dependencies: - '@aws-crypto/sha256-browser': 5.2.0 - '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sts': 3.600.0 - '@aws-sdk/core': 3.598.0 - '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 - '@aws-sdk/middleware-host-header': 3.598.0 - '@aws-sdk/middleware-logger': 3.598.0 - '@aws-sdk/middleware-recursion-detection': 3.598.0 - '@aws-sdk/middleware-user-agent': 3.598.0 - '@aws-sdk/region-config-resolver': 3.598.0 - '@aws-sdk/types': 3.598.0 - '@aws-sdk/util-endpoints': 3.598.0 - '@aws-sdk/util-user-agent-browser': 3.598.0 - '@aws-sdk/util-user-agent-node': 3.598.0 - '@smithy/config-resolver': 3.0.3 - '@smithy/core': 2.2.3 - '@smithy/fetch-http-handler': 3.2.1 - '@smithy/hash-node': 3.0.2 - '@smithy/invalid-dependency': 3.0.2 - '@smithy/middleware-content-length': 3.0.2 - '@smithy/middleware-endpoint': 3.0.4 - '@smithy/middleware-retry': 3.0.6 - '@smithy/middleware-serde': 3.0.3 - '@smithy/middleware-stack': 3.0.3 - '@smithy/node-config-provider': 3.1.3 - '@smithy/node-http-handler': 3.1.2 - '@smithy/protocol-http': 4.0.3 - '@smithy/smithy-client': 3.1.6 - '@smithy/types': 3.3.0 - '@smithy/url-parser': 3.0.3 - '@smithy/util-base64': 3.0.0 - '@smithy/util-body-length-browser': 3.0.0 - '@smithy/util-body-length-node': 3.0.0 - '@smithy/util-defaults-mode-browser': 3.0.6 - '@smithy/util-defaults-mode-node': 3.0.6 - '@smithy/util-endpoints': 2.0.3 - '@smithy/util-middleware': 3.0.3 - '@smithy/util-retry': 3.0.2 - '@smithy/util-utf8': 3.0.0 - tslib: 2.6.3 - transitivePeerDependencies: - - '@aws-sdk/client-sts' - - aws-crt - dev: false - /@aws-sdk/client-sso/3.423.0: resolution: {integrity: sha512-znIufHkwhCIePgaYciIs3x/+BpzR57CZzbCKHR9+oOvGyufEPPpUT5bFLvbwTgfiVkTjuk6sG/ES3U5Bc+xtrA==} engines: {node: '>=14.0.0'} @@ -13296,7 +13250,7 @@ packages: dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/client-sso-oidc': 3.600.0_tdq3komn4zwyd65w7klbptsu34 + '@aws-sdk/client-sso-oidc': 3.600.0 '@aws-sdk/core': 3.598.0 '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 '@aws-sdk/middleware-host-header': 3.598.0 @@ -13338,6 +13292,55 @@ packages: - aws-crt dev: false + /@aws-sdk/client-sts/3.600.0_dseaa2p5u2yk67qiepewcq3hkq: + resolution: {integrity: sha512-KQG97B7LvTtTiGmjlrG1LRAY8wUvCQzrmZVV5bjrJ/1oXAU7DITYwVbSJeX9NWg6hDuSk0VE3MFwIXS2SvfLIA==} + engines: {node: '>=16.0.0'} + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.600.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0_f7n47caigsrjd2lr2szmwfuee4 + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.3 + '@smithy/core': 2.2.3 + '@smithy/fetch-http-handler': 3.2.1 + '@smithy/hash-node': 3.0.2 + '@smithy/invalid-dependency': 3.0.2 + '@smithy/middleware-content-length': 3.0.2 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.6 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.2 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.6 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.6 + '@smithy/util-defaults-mode-node': 3.0.6 + '@smithy/util-endpoints': 2.0.3 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.2 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - aws-crt + dev: false + /@aws-sdk/core/3.556.0: resolution: {integrity: sha512-vJaSaHw2kPQlo11j/Rzuz0gk1tEaKdz+2ser0f0qZ5vwFlANjt08m/frU17ctnVKC1s58bxpctO/1P894fHLrA==} engines: {node: '>=14.0.0'} @@ -17630,7 +17633,7 @@ packages: '@aws-sdk/client-sns': 3.423.0 '@aws-sdk/client-sqs': 3.423.0 '@aws-sdk/client-ssm': 3.423.0 - '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/client-sts': 3.600.0_dseaa2p5u2yk67qiepewcq3hkq '@aws-sdk/s3-request-presigner': 3.609.0 '@pipedream/helper_functions': 0.3.12 '@pipedream/platform': 1.6.6