From e42f6b795cc736154581d14d16206e4c8a0ee577 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Mon, 16 Sep 2024 16:44:56 -0300 Subject: [PATCH 1/7] fakturoid init --- .../cancel-uncancel-invoice.mjs | 50 +++++ .../actions/create-invoice/create-invoice.mjs | 58 ++++++ .../pay-remove-payment-invoice.mjs | 73 ++++++++ components/fakturoid/fakturoid.app.mjs | 174 +++++++++++++++++- components/fakturoid/package.json | 2 +- .../invoice-status-change-instant.mjs | 100 ++++++++++ .../sources/new-contact/new-contact.mjs | 75 ++++++++ .../sources/new-invoice/new-invoice.mjs | 86 +++++++++ 8 files changed, 614 insertions(+), 4 deletions(-) create mode 100644 components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs create mode 100644 components/fakturoid/actions/create-invoice/create-invoice.mjs create mode 100644 components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs create mode 100644 components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs create mode 100644 components/fakturoid/sources/new-contact/new-contact.mjs create mode 100644 components/fakturoid/sources/new-invoice/new-invoice.mjs diff --git a/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs b/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs new file mode 100644 index 0000000000000..2738af04a9e18 --- /dev/null +++ b/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs @@ -0,0 +1,50 @@ +import fakturoid from "../../fakturoid.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "fakturoid-cancel-uncancel-invoice", + name: "Cancel or Uncancel Invoice", + description: "Cancels an existing invoice or revokes previous cancellation. [See the documentation](https://www.fakturoid.cz/api/v3)", + version: "0.0.{{ts}}", + type: "action", + props: { + fakturoid, + invoiceId: { + propDefinition: [ + fakturoid, + "invoiceId", + ], + }, + action: { + type: "string", + label: "Action", + description: "The action to perform on the invoice (cancel or uncancel)", + options: [ + { + label: "Cancel", + value: "cancel", + }, + { + label: "Uncancel", + value: "undo_cancel", + }, + ], + }, + }, + async run({ $ }) { + const { + invoiceId, action, + } = this; + const method = action === "cancel" + ? "cancelInvoice" + : "undoCancelInvoice"; + const response = await this.fakturoid[method]({ + invoiceId, + }); + + $.export("$summary", `${action === "cancel" + ? "Cancelled" + : "Uncancelled"} invoice with ID ${invoiceId}`); + return response; + }, +}; diff --git a/components/fakturoid/actions/create-invoice/create-invoice.mjs b/components/fakturoid/actions/create-invoice/create-invoice.mjs new file mode 100644 index 0000000000000..431e2bd5c6147 --- /dev/null +++ b/components/fakturoid/actions/create-invoice/create-invoice.mjs @@ -0,0 +1,58 @@ +import fakturoid from "../../fakturoid.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "fakturoid-create-invoice", + name: "Create Invoice", + description: "Creates a new invoice. [See the documentation](https://www.fakturoid.cz/api/v3/invoices)", + version: "0.0.{{ts}}", + type: "action", + props: { + fakturoid, + contactId: { + propDefinition: [ + fakturoid, + "contactId", + ], + }, + lines: { + propDefinition: [ + fakturoid, + "lines", + ], + }, + number: { + propDefinition: [ + fakturoid, + "number", + ], + optional: true, + }, + due: { + propDefinition: [ + fakturoid, + "due", + ], + optional: true, + }, + note: { + propDefinition: [ + fakturoid, + "note", + ], + optional: true, + }, + }, + async run({ $ }) { + const response = await this.fakturoid.createInvoice({ + contactId: this.contactId, + lines: this.lines.map(JSON.parse), + number: this.number, + due: this.due, + note: this.note, + }); + + $.export("$summary", `Successfully created invoice with ID ${response.id}`); + return response; + }, +}; diff --git a/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs b/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs new file mode 100644 index 0000000000000..daa8755542a11 --- /dev/null +++ b/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs @@ -0,0 +1,73 @@ +import fakturoid from "../../fakturoid.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "fakturoid-pay-remove-payment-invoice", + name: "Pay or Remove Payment for Invoice", + description: "Executes payment for an invoice or removes an already applied payment. [See the documentation](https://www.fakturoid.cz/api/v3/invoice-payments)", + version: "0.0.{{ts}}", + type: "action", + props: { + fakturoid, + invoiceId: { + propDefinition: [ + fakturoid, + "invoiceId", + ], + }, + paymentValue: { + propDefinition: [ + fakturoid, + "paymentValue", + ], + optional: true, + }, + actionType: { + type: "string", + label: "Action Type", + description: "Specify if you want to execute or remove a payment", + options: [ + { + label: "Execute Payment", + value: "execute", + }, + { + label: "Remove Payment", + value: "remove", + }, + ], + }, + paymentId: { + type: "string", + label: "Payment ID", + description: "ID of the payment to be removed. Required if action type is remove.", + optional: true, + }, + }, + async run({ $ }) { + const { + actionType, invoiceId, paymentValue, paymentId, + } = this; + + if (actionType === "execute") { + const response = await this.fakturoid.payInvoice({ + invoiceId, + paymentValue, + }); + $.export("$summary", `Successfully executed payment for invoice ID ${invoiceId}`); + return response; + } else if (actionType === "remove") { + if (!paymentId) { + throw new Error("Payment ID must be provided to remove a payment"); + } + const response = await this.fakturoid.removePayment({ + invoiceId, + paymentId, + }); + $.export("$summary", `Successfully removed payment ID ${paymentId} from invoice ID ${invoiceId}`); + return response; + } else { + throw new Error("Invalid action type"); + } + }, +}; diff --git a/components/fakturoid/fakturoid.app.mjs b/components/fakturoid/fakturoid.app.mjs index a6c9980621f13..973bc22763f36 100644 --- a/components/fakturoid/fakturoid.app.mjs +++ b/components/fakturoid/fakturoid.app.mjs @@ -1,11 +1,179 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "fakturoid", - propDefinitions: {}, + propDefinitions: { + invoiceId: { + type: "string", + label: "Invoice ID", + description: "Unique identifier for the invoice", + }, + newStatus: { + type: "string", + label: "New Status", + description: "The new status of the invoice (overdue or paid)", + options: [ + { + label: "Overdue", + value: "overdue", + }, + { + label: "Paid", + value: "paid", + }, + ], + }, + customerId: { + type: "string", + label: "Customer ID", + description: "Identifier for the customer (optional)", + optional: true, + }, + contactId: { + type: "string", + label: "Contact ID", + description: "Identifier for the contact related to the invoice", + }, + lines: { + type: "string[]", + label: "Lines", + description: "Lines that describe the items in the invoice, as a JSON array", + }, + number: { + type: "string", + label: "Number", + description: "The invoice number (optional)", + optional: true, + }, + due: { + type: "string", + label: "Due", + description: "The due date of the invoice (optional)", + optional: true, + }, + note: { + type: "string", + label: "Note", + description: "Additional notes for the invoice (optional)", + optional: true, + }, + paymentValue: { + type: "string", + label: "Payment Value", + description: "Amount of payment to be executed (optional)", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data authKeys() { console.log(Object.keys(this.$auth)); }, + _baseUrl() { + return "https://app.fakturoid.cz/api/v3"; + }, + async _makeRequest(opts = {}) { + const { + $ = this, + method = "GET", + path = "/", + headers, + ...otherOpts + } = opts; + + return axios($, { + ...otherOpts, + method, + url: this._baseUrl() + path, + headers: { + ...headers, + "User-Agent": "YourApp (yourname@example.com)", + "Authorization": `Bearer ${this.$auth.oauth_access_token}`, + }, + }); + }, + async createInvoice({ + contactId, lines, number, due, note, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/accounts/${this.$auth.account_slug}/invoices.json`, + data: { + subject_id: contactId, + lines: lines.map(JSON.parse), + custom_id: number, + due, + note, + }, + ...opts, + }); + }, + async cancelInvoice({ + invoiceId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/fire.json`, + params: { + event: "cancel", + }, + ...opts, + }); + }, + async undoCancelInvoice({ + invoiceId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/fire.json`, + params: { + event: "undo_cancel", + }, + ...opts, + }); + }, + async payInvoice({ + invoiceId, paymentValue, ...opts + }) { + const data = paymentValue + ? { + amount: paymentValue, + } + : {}; + return this._makeRequest({ + method: "POST", + path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/payments.json`, + data, + ...opts, + }); + }, + async removePayment({ + invoiceId, paymentId, ...opts + }) { + return this._makeRequest({ + method: "DELETE", + path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/payments/${paymentId}.json`, + ...opts, + }); + }, + async watchInvoiceStatusChange({ + invoiceId, newStatus, + }) { + return { + event_name: `invoice_${newStatus}`, + invoice_id: invoiceId, + }; + }, + async watchContactsAdded() { + return { + event_name: "subject_created", + }; + }, + async watchNewInvoiceCreated({ customerId }) { + return { + event_name: "invoice_created", + customer_id: customerId, + }; + }, }, -}; \ No newline at end of file +}; diff --git a/components/fakturoid/package.json b/components/fakturoid/package.json index 0b465740c1174..8f3e3e00b7ce4 100644 --- a/components/fakturoid/package.json +++ b/components/fakturoid/package.json @@ -12,4 +12,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs b/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs new file mode 100644 index 0000000000000..034fd5e3bbb5c --- /dev/null +++ b/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs @@ -0,0 +1,100 @@ +import fakturoid from "../../fakturoid.app.mjs"; +import { axios } from "@pipedream/platform"; +import crypto from "crypto"; + +export default { + key: "fakturoid-invoice-status-change-instant", + name: "Fakturoid Invoice Status Change Instant", + description: "Emit new event when an invoice status changes to 'overdue' or 'paid'. [See the documentation](https://www.fakturoid.cz/api/v3/webhooks)", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + fakturoid, + http: { + type: "$.interface.http", + customResponse: true, + }, + db: "$.service.db", + invoiceId: { + propDefinition: [ + fakturoid, + "invoiceId", + ], + }, + newStatus: { + propDefinition: [ + fakturoid, + "newStatus", + ], + }, + }, + methods: { + _getWebhookId() { + return this.db.get("webhookId"); + }, + _setWebhookId(id) { + this.db.set("webhookId", id); + }, + }, + hooks: { + async deploy() { + // No historical data fetching needed for this component. + }, + async activate() { + const config = { + url: this.http.endpoint, + events: [ + `invoice_${this.newStatus}`, + ], + }; + const response = await axios(this, { + method: "POST", + url: `${this.fakturoid._baseUrl()}/accounts/${this.fakturoid.$auth.account_slug}/webhooks.json`, + data: config, + }); + this._setWebhookId(response.id); + }, + async deactivate() { + const webhookId = this._getWebhookId(); + if (webhookId) { + await axios(this, { + method: "DELETE", + url: `${this.fakturoid._baseUrl()}/accounts/${this.fakturoid.$auth.account_slug}/webhooks/${webhookId}.json`, + }); + this.db.set("webhookId", null); + } + }, + }, + async run(event) { + const { + headers, body, + } = event; + + const signature = headers["x-fakturoid-signature"]; + const generatedSignature = crypto + .createHmac("sha256", this.fakturoid.$auth.signing_secret) + .update(JSON.stringify(body)) + .digest("base64"); + + if (signature !== generatedSignature) { + this.http.respond({ + status: 401, + body: "Unauthorized", + }); + return; + } + + this.http.respond({ + status: 200, + }); + + if (body.event_name === `invoice_${this.newStatus}` && body.invoice.id === parseInt(this.invoiceId)) { + this.$emit(body, { + id: `${body.invoice.id}-${body.event_name}-${Date.now()}`, + summary: `Invoice ${body.invoice.id} status changed to ${this.newStatus}`, + ts: Date.parse(body.created_at), + }); + } + }, +}; diff --git a/components/fakturoid/sources/new-contact/new-contact.mjs b/components/fakturoid/sources/new-contact/new-contact.mjs new file mode 100644 index 0000000000000..6b7934cfee8f3 --- /dev/null +++ b/components/fakturoid/sources/new-contact/new-contact.mjs @@ -0,0 +1,75 @@ +import fakturoid from "../../fakturoid.app.mjs"; +import { axios } from "@pipedream/platform"; + +export default { + key: "fakturoid-new-contact", + name: "New Contact Added", + description: "Emit new event when a contact (subject) is added in Fakturoid. [See the documentation](https://www.fakturoid.cz/api/v3/subjects)", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + fakturoid, + db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: 60 * 15, // Poll every 15 minutes + }, + }, + }, + methods: { + _getLastTimestamp() { + return this.db.get("lastTimestamp") || 0; + }, + _setLastTimestamp(timestamp) { + this.db.set("lastTimestamp", timestamp); + }, + }, + hooks: { + async deploy() { + const subjects = await this.fakturoid._makeRequest({ + method: "GET", + path: `/accounts/${this.fakturoid.$auth.account_slug}/subjects.json`, + }); + + subjects.slice(-50).forEach((contact) => { + this.$emit(contact, { + id: contact.id, + summary: `New Contact Added: ${contact.name}`, + ts: contact.created_at + ? new Date(contact.created_at).getTime() + : Date.now(), + }); + }); + + if (subjects.length) { + const lastTimestamp = new Date(subjects[subjects.length - 1].created_at).getTime(); + this._setLastTimestamp(lastTimestamp); + } + }, + }, + async run() { + const lastTimestamp = this._getLastTimestamp(); + const subjects = await this.fakturoid._makeRequest({ + method: "GET", + path: `/accounts/${this.fakturoid.$auth.account_slug}/subjects.json`, + }); + + subjects.forEach((contact) => { + const contactTimestamp = new Date(contact.created_at).getTime(); + if (contactTimestamp > lastTimestamp) { + this.$emit(contact, { + id: contact.id, + summary: `New Contact Added: ${contact.name}`, + ts: contactTimestamp, + }); + } + }); + + if (subjects.length) { + const latestTimestamp = new Date(subjects[0].created_at).getTime(); + this._setLastTimestamp(latestTimestamp); + } + }, +}; diff --git a/components/fakturoid/sources/new-invoice/new-invoice.mjs b/components/fakturoid/sources/new-invoice/new-invoice.mjs new file mode 100644 index 0000000000000..7a85561600d19 --- /dev/null +++ b/components/fakturoid/sources/new-invoice/new-invoice.mjs @@ -0,0 +1,86 @@ +import { axios } from "@pipedream/platform"; +import fakturoid from "../../fakturoid.app.mjs"; + +export default { + key: "fakturoid-new-invoice", + name: "New Invoice Created", + description: "Emit new event when a new invoice is created in Fakturoid. [See the documentation](https://www.fakturoid.cz/api/v3/invoices)", + version: "0.0.{{ts}}", + type: "source", + dedupe: "unique", + props: { + fakturoid, + db: "$.service.db", + customerId: { + propDefinition: [ + fakturoid, + "customerId", + ], + optional: true, + }, + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: 60 * 15, + }, + }, + }, + methods: { + async _getInvoices(params) { + return this.fakturoid._makeRequest({ + path: `/accounts/${this.fakturoid.$auth.account_slug}/invoices.json`, + params, + }); + }, + _getLastInvoiceId() { + return this.db.get("lastInvoiceId"); + }, + _setLastInvoiceId(invoiceId) { + this.db.set("lastInvoiceId", invoiceId); + }, + }, + hooks: { + async deploy() { + const params = { + order: "created_at desc", + since: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(), + }; + if (this.customerId) { + params.subject_id = this.customerId; + } + const invoices = await this._getInvoices(params); + invoices.slice(0, 50).forEach((invoice) => { + this.$emit(invoice, { + id: invoice.id, + summary: `New invoice created: ${invoice.number}`, + ts: Date.parse(invoice.created_at), + }); + }); + if (invoices.length) { + this._setLastInvoiceId(invoices[0].id); + } + }, + }, + async run() { + const lastInvoiceId = this._getLastInvoiceId(); + const params = { + order: "created_at desc", + since_id: lastInvoiceId, + }; + if (this.customerId) { + params.subject_id = this.customerId; + } + + const invoices = await this._getInvoices(params); + if (invoices.length) { + invoices.forEach((invoice) => { + this.$emit(invoice, { + id: invoice.id, + summary: `New invoice created: ${invoice.number}`, + ts: Date.parse(invoice.created_at), + }); + }); + this._setLastInvoiceId(invoices[0].id); + } + }, +}; From b754a4bfa9cead3972b8803ad986f643e0c53ff5 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 17 Sep 2024 17:57:44 -0300 Subject: [PATCH 2/7] [Components] fakturoid #13809 Sources - Invoice Status Change (Instant) - New Contact - New Invoice Actions - Create Invoice - Cancel Uncancel Invoice - Pay Remove Payment Invoice --- .../cancel-uncancel-invoice.mjs | 43 ++-- .../actions/create-invoice/create-invoice.mjs | 131 ++++++++--- .../pay-remove-payment-invoice.mjs | 116 ++++++---- components/fakturoid/common/constants.mjs | 159 +++++++++++++ components/fakturoid/common/utils.mjs | 24 ++ components/fakturoid/fakturoid.app.mjs | 208 ++++++++++-------- components/fakturoid/package.json | 6 +- components/fakturoid/sources/common/base.mjs | 58 +++++ .../invoice-status-change-instant.mjs | 102 ++------- .../test-event.mjs | 7 + .../sources/new-contact/test-event.mjs | 7 + .../sources/new-invoice/test-event.mjs | 7 + 12 files changed, 607 insertions(+), 261 deletions(-) create mode 100644 components/fakturoid/common/constants.mjs create mode 100644 components/fakturoid/common/utils.mjs create mode 100644 components/fakturoid/sources/common/base.mjs create mode 100644 components/fakturoid/sources/invoice-status-change-instant/test-event.mjs create mode 100644 components/fakturoid/sources/new-contact/test-event.mjs create mode 100644 components/fakturoid/sources/new-invoice/test-event.mjs diff --git a/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs b/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs index 2738af04a9e18..783fc302950e8 100644 --- a/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs +++ b/components/fakturoid/actions/cancel-uncancel-invoice/cancel-uncancel-invoice.mjs @@ -1,50 +1,49 @@ +import constants from "../../common/constants.mjs"; import fakturoid from "../../fakturoid.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "fakturoid-cancel-uncancel-invoice", name: "Cancel or Uncancel Invoice", description: "Cancels an existing invoice or revokes previous cancellation. [See the documentation](https://www.fakturoid.cz/api/v3)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", props: { fakturoid, + accountSlug: { + propDefinition: [ + fakturoid, + "accountSlug", + ], + }, invoiceId: { propDefinition: [ fakturoid, "invoiceId", + ({ accountSlug }) => ({ + accountSlug, + }), ], }, action: { type: "string", label: "Action", description: "The action to perform on the invoice (cancel or uncancel)", - options: [ - { - label: "Cancel", - value: "cancel", - }, - { - label: "Uncancel", - value: "undo_cancel", - }, - ], + options: constants.ACTION_OPTIONS, }, }, async run({ $ }) { - const { - invoiceId, action, - } = this; - const method = action === "cancel" - ? "cancelInvoice" - : "undoCancelInvoice"; - const response = await this.fakturoid[method]({ - invoiceId, + const response = await this.fakturoid.fireInvoice({ + $, + accountSlug: this.accountSlug, + invoiceId: this.invoiceId, + params: { + event: this.action, + }, }); - $.export("$summary", `${action === "cancel" + $.export("$summary", `${this.action === "cancel" ? "Cancelled" - : "Uncancelled"} invoice with ID ${invoiceId}`); + : "Uncancelled"} invoice with ID ${this.invoiceId}`); return response; }, }; diff --git a/components/fakturoid/actions/create-invoice/create-invoice.mjs b/components/fakturoid/actions/create-invoice/create-invoice.mjs index 431e2bd5c6147..b9f88b9bd2ae9 100644 --- a/components/fakturoid/actions/create-invoice/create-invoice.mjs +++ b/components/fakturoid/actions/create-invoice/create-invoice.mjs @@ -1,55 +1,136 @@ +import constants, { parseObject } from "../../common/constants.mjs"; import fakturoid from "../../fakturoid.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "fakturoid-create-invoice", name: "Create Invoice", description: "Creates a new invoice. [See the documentation](https://www.fakturoid.cz/api/v3/invoices)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", props: { fakturoid, - contactId: { + accountSlug: { propDefinition: [ fakturoid, - "contactId", + "accountSlug", ], }, - lines: { - propDefinition: [ - fakturoid, - "lines", - ], + customId: { + type: "string", + label: "Custom Id", + description: "Identifier in your application", + optional: true, }, - number: { - propDefinition: [ - fakturoid, - "number", - ], + documentType: { + type: "string", + label: "Document Type", + description: "Type of document", + options: constants.DOCUMENT_TYPE_OPTIONS, + reloadProps: true, optional: true, }, - due: { + subjectId: { propDefinition: [ fakturoid, - "due", + "subjectId", + ({ accountSlug }) => ({ + accountSlug, + }), ], + }, + orderNumber: { + type: "string", + label: "Order Number", + description: "Order number in your application", optional: true, }, note: { - propDefinition: [ - fakturoid, - "note", - ], + type: "string", + label: "Note", + description: "Additional notes for the invoice", + optional: true, + }, + due: { + type: "string", + label: "Due", + description: "Invoice due date in number of days from today", optional: true, }, + issuedOn: { + type: "string", + label: "Issued On", + description: "Date of issue. **Format: YYYY-MM-DD**", + optional: true, + }, + taxableFulfillmentDue: { + type: "string", + label: "Taxable Fulfillment Due", + description: "Chargeable event date.", + optional: true, + }, + tags: { + type: "string[]", + label: "Tags", + description: "List of tags", + optional: true, + }, + roundTotal: { + type: "boolean", + label: "Tound Total", + description: "Round total amount (VAT included)", + optional: true, + }, + subtotal: { + type: "string", + label: "Subtotal", + description: "Total without VAT", + optional: true, + }, + total: { + type: "string", + label: "Total", + description: "Total with VAT", + optional: true, + }, + lines: { + type: "string[]", + label: "Lines", + description: "List of object lines to invoice. [See the documentation](https://www.fakturoid.cz/api/v3/invoices#attributes). **Example: {\"name\": \"Hard work\",\"quantity\": \"1.0\",\"unit_name\": \"h\",\"unit_price\": \"40000\",\"vat_rate\": \"21\"}**", + }, + }, + async additionalProps() { + const props = {}; + if (this.documentType === "proforma") { + props.proformaFollowupDocument = { + type: "string", + label: "Proforma Followup Document", + description: "What to issue after a proforma is paid.", + options: constants.PROFORMA_OPTIONS, + optional: true, + }; + } + return props; }, async run({ $ }) { const response = await this.fakturoid.createInvoice({ - contactId: this.contactId, - lines: this.lines.map(JSON.parse), - number: this.number, - due: this.due, - note: this.note, + $, + accountSlug: this.accountSlug, + data: { + custom_id: this.customId, + document_type: this.documentType, + proforma_followup_document: this.proformaFollowupDocument, + subject_id: this.subjectId, + order_number: this.orderNumber, + note: this.note, + due: this.due, + issued_on: this.issuedOn, + taxable_fulfillment_due: this.taxableFulfillmentDue, + tags: parseObject(this.tags), + round_total: this.roundTotal, + subtotal: this.subtotal && parseFloat(this.subtotal), + total: this.total && parseFloat(this.total), + lines: parseObject(this.lines), + }, }); $.export("$summary", `Successfully created invoice with ID ${response.id}`); diff --git a/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs b/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs index daa8755542a11..135fa078c2374 100644 --- a/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs +++ b/components/fakturoid/actions/pay-remove-payment-invoice/pay-remove-payment-invoice.mjs @@ -1,73 +1,109 @@ +import constants from "../../common/constants.mjs"; import fakturoid from "../../fakturoid.app.mjs"; -import { axios } from "@pipedream/platform"; export default { key: "fakturoid-pay-remove-payment-invoice", name: "Pay or Remove Payment for Invoice", description: "Executes payment for an invoice or removes an already applied payment. [See the documentation](https://www.fakturoid.cz/api/v3/invoice-payments)", - version: "0.0.{{ts}}", + version: "0.0.1", type: "action", props: { fakturoid, - invoiceId: { + accountSlug: { propDefinition: [ fakturoid, - "invoiceId", + "accountSlug", ], }, - paymentValue: { + invoiceId: { propDefinition: [ fakturoid, - "paymentValue", + "invoiceId", + ({ accountSlug }) => ({ + accountSlug, + }), ], - optional: true, }, actionType: { type: "string", label: "Action Type", description: "Specify if you want to execute or remove a payment", - options: [ - { - label: "Execute Payment", - value: "execute", - }, - { - label: "Remove Payment", - value: "remove", - }, - ], - }, - paymentId: { - type: "string", - label: "Payment ID", - description: "ID of the payment to be removed. Required if action type is remove.", - optional: true, + options: constants.ACTION_TYPE_OPTIONS, + reloadProps: true, }, }, - async run({ $ }) { - const { - actionType, invoiceId, paymentValue, paymentId, - } = this; + async additionalProps() { + const props = {}; + if (this.actionType === "execute") { + props.paidOn = { + type: "string", + label: "Paid On", + description: "Payment date. **Format: YYYY-MM-DD** Default: Today", + optional: true, + }; + props.currency = { + type: "string", + label: "Currency", + description: "Currency [ISO Code](https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes) (same as invoice currency)", + optional: true, + }; + props.amount = { + type: "string", + label: "Amount", + description: "Paid amount in document currency. Default: Remaining amount to pay", + optional: true, + }; + props.markDocumentAsPaid = { + type: "boolean", + label: "Mark Document As Paid", + description: "Mark document as paid? Default: true if the total paid amount becomes greater or equal to remaining amount to pay", + optional: true, + }; + } else if (this.actionType === "remove") { + props.paymentId = { + type: "string", + label: "Payment ID", + description: "ID of the payment to be removed.", + options: async () => { + const { payments } = await this.fakturoid.getInvoice({ + accountSlug: this.accountSlug, + invoiceId: this.invoiceId, + }); - if (actionType === "execute") { + return payments.map(({ + id: value, paid_on: pOn, currency, amount, + }) => ({ + label: `${currency} ${amount} (${pOn})`, + value, + })); + }, + }; + } + return props; + }, + async run({ $ }) { + if (this.actionType === "execute") { const response = await this.fakturoid.payInvoice({ - invoiceId, - paymentValue, + accountSlug: this.accountSlug, + invoiceId: this.invoiceId, + data: { + paid_on: this.paidOn, + currency: this.currency, + amount: this.amount && parseFloat(this.amount), + mark_document_as_paid: this.markDocumentAsPaid, + }, }); - $.export("$summary", `Successfully executed payment for invoice ID ${invoiceId}`); + $.export("$summary", `Successfully executed payment for invoice ID ${this.invoiceId}`); return response; - } else if (actionType === "remove") { - if (!paymentId) { - throw new Error("Payment ID must be provided to remove a payment"); - } + } else if (this.actionType === "remove") { const response = await this.fakturoid.removePayment({ - invoiceId, - paymentId, + $, + accountSlug: this.accountSlug, + invoiceId: this.invoiceId, + paymentId: this.paymentId, }); - $.export("$summary", `Successfully removed payment ID ${paymentId} from invoice ID ${invoiceId}`); + $.export("$summary", `Successfully removed payment ID ${this.paymentId} from invoice ID ${this.invoiceId}`); return response; - } else { - throw new Error("Invalid action type"); } }, }; diff --git a/components/fakturoid/common/constants.mjs b/components/fakturoid/common/constants.mjs new file mode 100644 index 0000000000000..97dbb8ff255b2 --- /dev/null +++ b/components/fakturoid/common/constants.mjs @@ -0,0 +1,159 @@ +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; +}; + +const DOCUMENT_TYPE_OPTIONS = [ + { + label: "Invoice", + value: "invoice", + }, + { + label: "Proforma", + value: "proforma", + }, + { + label: "Legacy partial proforma (cannot be set for new documents)", + value: "partial_proforma", + }, + { + label: "Correction document for an invoice", + value: "correction", + }, + { + label: "Tax document for a received payment", + value: "tax_document", + }, + { + label: "Final invoice for tax documents", + value: "final_invoice", + }, +]; + +const PROFORMA_OPTIONS = [ + { + label: "Invoice paid", + value: "final_invoice_paid", + }, + { + label: "Invoice with edit", + value: "final_invoice", + }, + { + label: "Document to payment", + value: "tax_document", + }, + { + label: "None", + value: "none", + }, +]; + +const ACTION_OPTIONS = [ + { + label: "Cancel", + value: "cancel", + }, + { + label: "Uncancel", + value: "undo_cancel", + }, +]; + +const ACTION_TYPE_OPTIONS = [ + { + label: "Execute Payment", + value: "execute", + }, + { + label: "Remove Payment", + value: "remove", + }, +]; + +const EVENT_OPTIONS = [ + { + label: "Invoice was updated", + value: "invoice_updated", + }, + { + label: "Invoice was deleted and moved to the trash", + value: "invoice_removed", + }, + { + label: "Invoice was restored from the trash", + value: "invoice_restored", + }, + { + label: "Invoice was marked as overdue", + value: "invoice_overdue", + }, + { + label: "Payment was added to document and marked it as paid", + value: "invoice_paid", + }, + { + label: "Payment was added to the invoice, but didn't mark it as paid", + value: "invoice_payment_added", + }, + { + label: "Invoice was marked as unpaid, and the payments in the additional payload were removed", + value: "invoice_payment_removed", + }, + { + label: "Email with the invoice was sent to the subject", + value: "invoice_sent", + }, + { + label: "Invoice was locked", + value: "invoice_locked", + }, + { + label: "Invoice was unlocked", + value: "invoice_unlocked", + }, + { + label: "Invoice was marked as cancelled", + value: "invoice_cancelled", + }, + { + label: "Cancellation was removed", + value: "invoice_cancellation_removed", + }, + { + label: "Invoice was marked as uncollectible", + value: "invoice_uncollectible", + }, + { + label: "Uncollectibility was removed", + value: "invoice_uncollectible_removed", + }, +]; + +export default { + DOCUMENT_TYPE_OPTIONS, + PROFORMA_OPTIONS, + ACTION_OPTIONS, + ACTION_TYPE_OPTIONS, + EVENT_OPTIONS, +}; diff --git a/components/fakturoid/common/utils.mjs b/components/fakturoid/common/utils.mjs new file mode 100644 index 0000000000000..dcc9cc61f6f41 --- /dev/null +++ b/components/fakturoid/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/fakturoid/fakturoid.app.mjs b/components/fakturoid/fakturoid.app.mjs index 973bc22763f36..8969a9af843a8 100644 --- a/components/fakturoid/fakturoid.app.mjs +++ b/components/fakturoid/fakturoid.app.mjs @@ -4,10 +4,64 @@ export default { type: "app", app: "fakturoid", propDefinitions: { + accountSlug: { + type: "string", + label: "Account", + description: "The account you want to use", + async options() { + const { accounts } = await this.getLoggedUser(); + + return accounts.map(({ + slug: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + subjectId: { + type: "string", + label: "Subject Id", + description: "The id of the subject", + async options({ + page, accountSlug, + }) { + const data = await this.listSubjects({ + accountSlug, + params: { + page: page + 1, + }, + }); + + return data.map(({ + id: value, name, full_name: fName, + }) => ({ + label: fName || name, + value, + })); + }, + }, invoiceId: { type: "string", label: "Invoice ID", description: "Unique identifier for the invoice", + async options({ + page, accountSlug, + }) { + const data = await this.listInvoices({ + accountSlug, + params: { + page: page + 1, + }, + }); + + return data.map(({ + id: value, client_name: cName, due_on: due, currency, total, + }) => ({ + label: `${cName} - ${currency} ${total} - Due On: ${due}`, + value, + })); + }, }, newStatus: { type: "string", @@ -35,29 +89,12 @@ export default { label: "Contact ID", description: "Identifier for the contact related to the invoice", }, - lines: { - type: "string[]", - label: "Lines", - description: "Lines that describe the items in the invoice, as a JSON array", - }, number: { type: "string", label: "Number", description: "The invoice number (optional)", optional: true, }, - due: { - type: "string", - label: "Due", - description: "The due date of the invoice (optional)", - optional: true, - }, - note: { - type: "string", - label: "Note", - description: "Additional notes for the invoice (optional)", - optional: true, - }, paymentValue: { type: "string", label: "Payment Value", @@ -66,114 +103,101 @@ export default { }, }, methods: { - authKeys() { - console.log(Object.keys(this.$auth)); - }, - _baseUrl() { - return "https://app.fakturoid.cz/api/v3"; - }, - async _makeRequest(opts = {}) { - const { - $ = this, - method = "GET", - path = "/", - headers, - ...otherOpts - } = opts; - - return axios($, { - ...otherOpts, - method, - url: this._baseUrl() + path, - headers: { - ...headers, - "User-Agent": "YourApp (yourname@example.com)", - "Authorization": `Bearer ${this.$auth.oauth_access_token}`, - }, - }); + _baseUrl(accountSlug) { + return `https://app.fakturoid.cz/api/v3${accountSlug + ? `/accounts/${accountSlug}` + : ""}`; + }, + _headers() { + return { + Authorization: `Bearer ${this.$auth.oauth_access_token}`, + }; }, - async createInvoice({ - contactId, lines, number, due, note, ...opts + _makeRequest({ + $ = this, accountSlug, path, ...opts }) { - return this._makeRequest({ - method: "POST", - path: `/accounts/${this.$auth.account_slug}/invoices.json`, - data: { - subject_id: contactId, - lines: lines.map(JSON.parse), - custom_id: number, - due, - note, - }, + const config = { + url: this._baseUrl(accountSlug) + path, + headers: this._headers(), ...opts, + }; + console.log("config: ", config); + return axios($, config); + }, + getLoggedUser() { + return this._makeRequest({ + path: "/user.json", }); }, - async cancelInvoice({ + getInvoice({ invoiceId, ...opts }) { + return this._makeRequest({ + path: `/invoices/${invoiceId}.json`, + ...opts, + }); + }, + listSubjects(opts = {}) { + return this._makeRequest({ + path: "/subjects.json", + ...opts, + }); + }, + listInvoices(opts = {}) { + return this._makeRequest({ + path: "/invoices.json", + ...opts, + }); + }, + createInvoice(opts = {}) { return this._makeRequest({ method: "POST", - path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/fire.json`, - params: { - event: "cancel", - }, + path: "/invoices.json", ...opts, }); }, - async undoCancelInvoice({ + fireInvoice({ invoiceId, ...opts }) { return this._makeRequest({ method: "POST", - path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/fire.json`, - params: { - event: "undo_cancel", - }, + path: `/invoices/${invoiceId}/fire.json`, ...opts, }); }, - async payInvoice({ - invoiceId, paymentValue, ...opts + payInvoice({ + invoiceId, ...opts }) { - const data = paymentValue - ? { - amount: paymentValue, - } - : {}; return this._makeRequest({ method: "POST", - path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/payments.json`, - data, + path: `/invoices/${invoiceId}/payments.json`, ...opts, }); }, - async removePayment({ + removePayment({ invoiceId, paymentId, ...opts }) { return this._makeRequest({ method: "DELETE", - path: `/accounts/${this.$auth.account_slug}/invoices/${invoiceId}/payments/${paymentId}.json`, + path: `/invoices/${invoiceId}/payments/${paymentId}.json`, ...opts, }); }, - async watchInvoiceStatusChange({ - invoiceId, newStatus, - }) { - return { - event_name: `invoice_${newStatus}`, - invoice_id: invoiceId, - }; - }, - async watchContactsAdded() { - return { - event_name: "subject_created", - }; + createWebhook(opts = {}) { + return this._makeRequest({ + method: "POST", + path: "/webhooks.json", + ...opts, + }); }, - async watchNewInvoiceCreated({ customerId }) { - return { - event_name: "invoice_created", - customer_id: customerId, - }; + deleteWebhook({ + webhookId, ...opts + }) { + return this._makeRequest({ + method: "POST", + path: `/webhooks${webhookId}.json`, + ...opts, + }); }, }, }; diff --git a/components/fakturoid/package.json b/components/fakturoid/package.json index 8f3e3e00b7ce4..08662045c4063 100644 --- a/components/fakturoid/package.json +++ b/components/fakturoid/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/fakturoid", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Fakturoid Components", "main": "fakturoid.app.mjs", "keywords": [ @@ -11,5 +11,9 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.0.1" } } + diff --git a/components/fakturoid/sources/common/base.mjs b/components/fakturoid/sources/common/base.mjs new file mode 100644 index 0000000000000..c33148cbdf467 --- /dev/null +++ b/components/fakturoid/sources/common/base.mjs @@ -0,0 +1,58 @@ +import fakturoid from "../../fakturoid.app.mjs"; + +export default { + props: { + fakturoid, + http: { + type: "$.interface.http", + customResponse: false, + }, + db: "$.service.db", + accountSlug: { + propDefinition: [ + fakturoid, + "accountSlug", + ], + }, + }, + methods: { + _setHookId(hookId) { + this.db.set("hookId", hookId); + }, + _getHookId() { + return this.db.get("hookId"); + }, + }, + hooks: { + async activate() { + const response = await this.fakturoid.createWebhook({ + accountSlug: this.accountSlug, + data: { + events: this.getEvents(), + webhook_url: this.http.endpoint, + }, + }); + this._setHookId(response.id); + }, + async deactivate() { + const webhookId = this._getHookId(); + await this.fakturoid.deleteWebhook({ + accountSlug: this.accountSlug, + webhookId, + }); + }, + }, + async run({ + body, created_at: createdAt, event_name: eventName, + }) { + const ts = Date.parse(createdAt); + this.$emit(body, { + id: `${body.resource}-${ts}`, + summary: this.getSummary({ + eventName, + body, + }), + ts: ts, + }); + }, +}; diff --git a/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs b/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs index 034fd5e3bbb5c..a39db0ae34e34 100644 --- a/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs +++ b/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs @@ -1,100 +1,40 @@ -import fakturoid from "../../fakturoid.app.mjs"; -import { axios } from "@pipedream/platform"; -import crypto from "crypto"; +import constants from "../../common/constants.mjs"; +import { parseObject } from "../../common/utils.mjs"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "fakturoid-invoice-status-change-instant", - name: "Fakturoid Invoice Status Change Instant", - description: "Emit new event when an invoice status changes to 'overdue' or 'paid'. [See the documentation](https://www.fakturoid.cz/api/v3/webhooks)", + name: "New Fakturoid Invoice Status Change (Instant)", + description: "Emit new event when an invoice status changes.", version: "0.0.{{ts}}", type: "source", dedupe: "unique", props: { - fakturoid, + ...common.props, http: { type: "$.interface.http", customResponse: true, }, db: "$.service.db", - invoiceId: { - propDefinition: [ - fakturoid, - "invoiceId", - ], - }, - newStatus: { - propDefinition: [ - fakturoid, - "newStatus", - ], + events: { + type: "string[]", + label: "Events", + description: "List of events when webhook is fired", + options: constants.EVENT_OPTIONS, }, }, methods: { - _getWebhookId() { - return this.db.get("webhookId"); - }, - _setWebhookId(id) { - this.db.set("webhookId", id); - }, - }, - hooks: { - async deploy() { - // No historical data fetching needed for this component. - }, - async activate() { - const config = { - url: this.http.endpoint, - events: [ - `invoice_${this.newStatus}`, - ], - }; - const response = await axios(this, { - method: "POST", - url: `${this.fakturoid._baseUrl()}/accounts/${this.fakturoid.$auth.account_slug}/webhooks.json`, - data: config, - }); - this._setWebhookId(response.id); + ...common.methods, + getEvents() { + return parseObject(this.events); }, - async deactivate() { - const webhookId = this._getWebhookId(); - if (webhookId) { - await axios(this, { - method: "DELETE", - url: `${this.fakturoid._baseUrl()}/accounts/${this.fakturoid.$auth.account_slug}/webhooks/${webhookId}.json`, - }); - this.db.set("webhookId", null); - } + getSummary({ + eventName, body, + }) { + return `Invoice ${body.id} status changed to ${eventName}`; }, }, - async run(event) { - const { - headers, body, - } = event; - - const signature = headers["x-fakturoid-signature"]; - const generatedSignature = crypto - .createHmac("sha256", this.fakturoid.$auth.signing_secret) - .update(JSON.stringify(body)) - .digest("base64"); - - if (signature !== generatedSignature) { - this.http.respond({ - status: 401, - body: "Unauthorized", - }); - return; - } - - this.http.respond({ - status: 200, - }); - - if (body.event_name === `invoice_${this.newStatus}` && body.invoice.id === parseInt(this.invoiceId)) { - this.$emit(body, { - id: `${body.invoice.id}-${body.event_name}-${Date.now()}`, - summary: `Invoice ${body.invoice.id} status changed to ${this.newStatus}`, - ts: Date.parse(body.created_at), - }); - } - }, + sampleEmit, }; diff --git a/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs b/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs new file mode 100644 index 0000000000000..912a48198cf59 --- /dev/null +++ b/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs @@ -0,0 +1,7 @@ +export default { + "project": "project_slug", + "translated": 100, + "resource": "resource_slug", + "event": "translation_completed", + "language": "lang_code" +} \ No newline at end of file diff --git a/components/fakturoid/sources/new-contact/test-event.mjs b/components/fakturoid/sources/new-contact/test-event.mjs new file mode 100644 index 0000000000000..912a48198cf59 --- /dev/null +++ b/components/fakturoid/sources/new-contact/test-event.mjs @@ -0,0 +1,7 @@ +export default { + "project": "project_slug", + "translated": 100, + "resource": "resource_slug", + "event": "translation_completed", + "language": "lang_code" +} \ No newline at end of file diff --git a/components/fakturoid/sources/new-invoice/test-event.mjs b/components/fakturoid/sources/new-invoice/test-event.mjs new file mode 100644 index 0000000000000..912a48198cf59 --- /dev/null +++ b/components/fakturoid/sources/new-invoice/test-event.mjs @@ -0,0 +1,7 @@ +export default { + "project": "project_slug", + "translated": 100, + "resource": "resource_slug", + "event": "translation_completed", + "language": "lang_code" +} \ No newline at end of file From 2163ec649e6b0773d16adea3477558bf1bbe0ef8 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 17 Sep 2024 18:03:05 -0300 Subject: [PATCH 3/7] pnpm update --- pnpm-lock.yaml | 107 +++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e0d493a69875..3fbf3c3ca585a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3178,7 +3178,10 @@ importers: fs: 0.0.1-security components/fakturoid: - specifiers: {} + specifiers: + '@pipedream/platform': ^3.0.1 + dependencies: + '@pipedream/platform': 3.0.1 components/faraday: specifiers: @@ -12698,55 +12701,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'} @@ -12982,7 +12936,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 @@ -13024,6 +12978,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'} @@ -17322,7 +17325,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 From a66356e4b1078ccc9b5c0b08b66ce54024c4e852 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 15 Oct 2024 11:15:09 -0300 Subject: [PATCH 4/7] [Components] fakturoid #13809 Sources - Invoice Updated - New Contact - New Invoice Actions - Create Invoice - Cancel Uncancel Invoice - Pay Remove Payment Invoice --- components/fakturoid/fakturoid.app.mjs | 76 +++------ components/fakturoid/sources/common/base.mjs | 89 +++++++---- .../invoice-status-change-instant.mjs | 40 ----- .../test-event.mjs | 7 - .../invoice-updated/invoice-updated.mjs | 30 ++++ .../sources/invoice-updated/test-event.mjs | 146 +++++++++++++++++ .../sources/new-contact/new-contact.mjs | 75 ++------- .../sources/new-contact/test-event.mjs | 56 ++++++- .../sources/new-invoice/new-invoice.mjs | 86 ++-------- .../sources/new-invoice/test-event.mjs | 149 +++++++++++++++++- 10 files changed, 467 insertions(+), 287 deletions(-) delete mode 100644 components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs delete mode 100644 components/fakturoid/sources/invoice-status-change-instant/test-event.mjs create mode 100644 components/fakturoid/sources/invoice-updated/invoice-updated.mjs create mode 100644 components/fakturoid/sources/invoice-updated/test-event.mjs diff --git a/components/fakturoid/fakturoid.app.mjs b/components/fakturoid/fakturoid.app.mjs index 8969a9af843a8..e4c7d5228ab71 100644 --- a/components/fakturoid/fakturoid.app.mjs +++ b/components/fakturoid/fakturoid.app.mjs @@ -63,44 +63,6 @@ export default { })); }, }, - newStatus: { - type: "string", - label: "New Status", - description: "The new status of the invoice (overdue or paid)", - options: [ - { - label: "Overdue", - value: "overdue", - }, - { - label: "Paid", - value: "paid", - }, - ], - }, - customerId: { - type: "string", - label: "Customer ID", - description: "Identifier for the customer (optional)", - optional: true, - }, - contactId: { - type: "string", - label: "Contact ID", - description: "Identifier for the contact related to the invoice", - }, - number: { - type: "string", - label: "Number", - description: "The invoice number (optional)", - optional: true, - }, - paymentValue: { - type: "string", - label: "Payment Value", - description: "Amount of payment to be executed (optional)", - optional: true, - }, }, methods: { _baseUrl(accountSlug) { @@ -116,13 +78,11 @@ export default { _makeRequest({ $ = this, accountSlug, path, ...opts }) { - const config = { + return axios($, { url: this._baseUrl(accountSlug) + path, headers: this._headers(), ...opts, - }; - console.log("config: ", config); - return axios($, config); + }); }, getLoggedUser() { return this._makeRequest({ @@ -183,21 +143,25 @@ export default { ...opts, }); }, - createWebhook(opts = {}) { - return this._makeRequest({ - method: "POST", - path: "/webhooks.json", - ...opts, - }); - }, - deleteWebhook({ - webhookId, ...opts + async *paginate({ + fn, params = {}, ...opts }) { - return this._makeRequest({ - method: "POST", - path: `/webhooks${webhookId}.json`, - ...opts, - }); + let hasMore = false; + let page = 0; + + do { + params.page = ++page; + const data = await fn({ + params, + ...opts, + }); + for (const d of data) { + yield d; + } + + hasMore = data.length; + + } while (hasMore); }, }, }; diff --git a/components/fakturoid/sources/common/base.mjs b/components/fakturoid/sources/common/base.mjs index c33148cbdf467..45859d6c232b8 100644 --- a/components/fakturoid/sources/common/base.mjs +++ b/components/fakturoid/sources/common/base.mjs @@ -1,13 +1,16 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; import fakturoid from "../../fakturoid.app.mjs"; export default { props: { fakturoid, - http: { - type: "$.interface.http", - customResponse: false, - }, db: "$.service.db", + timer: { + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, accountSlug: { propDefinition: [ fakturoid, @@ -16,43 +19,59 @@ export default { }, }, methods: { - _setHookId(hookId) { - this.db.set("hookId", hookId); + _getLastDate() { + return this.db.get("lastDate") || "1970-01-01T00:00:00"; }, - _getHookId() { - return this.db.get("hookId"); + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); }, - }, - hooks: { - async activate() { - const response = await this.fakturoid.createWebhook({ - accountSlug: this.accountSlug, - data: { - events: this.getEvents(), - webhook_url: this.http.endpoint, - }, - }); - this._setHookId(response.id); + getParams(lastDate) { + return { + since: lastDate, + }; + }, + getDateField() { + return "created_at"; }, - async deactivate() { - const webhookId = this._getHookId(); - await this.fakturoid.deleteWebhook({ + async emitEvent(maxResults = false) { + const lastDate = this._getLastDate(); + const dateField = this.getDateField(); + const response = this.fakturoid.paginate({ + fn: this.getFunction(), accountSlug: this.accountSlug, - webhookId, + params: this.getParams(lastDate), }); + + let responseArray = []; + for await (const item of response) { + responseArray.push(item); + } + + if (responseArray.length) { + responseArray = responseArray + .sort((a, b) => Date.parse(b[dateField]) - Date.parse(a[dateField])); + + if (maxResults && (responseArray.length > maxResults)) { + responseArray.length = maxResults; + } + this._setLastDate(responseArray[0][dateField]); + } + + for (const item of responseArray.reverse()) { + this.$emit(item, { + id: `${item.id}-${item[dateField]}`, + summary: this.getSummary(item), + ts: Date.parse(item[dateField]), + }); + } + }, + }, + hooks: { + async deploy() { + await this.emitEvent(25); }, }, - async run({ - body, created_at: createdAt, event_name: eventName, - }) { - const ts = Date.parse(createdAt); - this.$emit(body, { - id: `${body.resource}-${ts}`, - summary: this.getSummary({ - eventName, - body, - }), - ts: ts, - }); + async run() { + await this.emitEvent(); }, }; diff --git a/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs b/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs deleted file mode 100644 index a39db0ae34e34..0000000000000 --- a/components/fakturoid/sources/invoice-status-change-instant/invoice-status-change-instant.mjs +++ /dev/null @@ -1,40 +0,0 @@ -import constants from "../../common/constants.mjs"; -import { parseObject } from "../../common/utils.mjs"; -import common from "../common/base.mjs"; -import sampleEmit from "./test-event.mjs"; - -export default { - ...common, - key: "fakturoid-invoice-status-change-instant", - name: "New Fakturoid Invoice Status Change (Instant)", - description: "Emit new event when an invoice status changes.", - version: "0.0.{{ts}}", - type: "source", - dedupe: "unique", - props: { - ...common.props, - http: { - type: "$.interface.http", - customResponse: true, - }, - db: "$.service.db", - events: { - type: "string[]", - label: "Events", - description: "List of events when webhook is fired", - options: constants.EVENT_OPTIONS, - }, - }, - methods: { - ...common.methods, - getEvents() { - return parseObject(this.events); - }, - getSummary({ - eventName, body, - }) { - return `Invoice ${body.id} status changed to ${eventName}`; - }, - }, - sampleEmit, -}; diff --git a/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs b/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs deleted file mode 100644 index 912a48198cf59..0000000000000 --- a/components/fakturoid/sources/invoice-status-change-instant/test-event.mjs +++ /dev/null @@ -1,7 +0,0 @@ -export default { - "project": "project_slug", - "translated": 100, - "resource": "resource_slug", - "event": "translation_completed", - "language": "lang_code" -} \ No newline at end of file diff --git a/components/fakturoid/sources/invoice-updated/invoice-updated.mjs b/components/fakturoid/sources/invoice-updated/invoice-updated.mjs new file mode 100644 index 0000000000000..7a632c6c3615a --- /dev/null +++ b/components/fakturoid/sources/invoice-updated/invoice-updated.mjs @@ -0,0 +1,30 @@ +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + ...common, + key: "fakturoid-invoice-updated", + name: "New Invoice Updated", + description: "Emit new event when an invoice is created or updated.", + version: "0.0.1", + type: "source", + dedupe: "unique", + methods: { + ...common.methods, + getFunction() { + return this.fakturoid.listInvoices; + }, + getSummary(invoice) { + return `New invoice updated: ${invoice.number}`; + }, + getParams(lastDate) { + return { + updated_since: lastDate, + }; + }, + getDateField() { + return "updated_at"; + }, + }, + sampleEmit, +}; diff --git a/components/fakturoid/sources/invoice-updated/test-event.mjs b/components/fakturoid/sources/invoice-updated/test-event.mjs new file mode 100644 index 0000000000000..63e50c797044c --- /dev/null +++ b/components/fakturoid/sources/invoice-updated/test-event.mjs @@ -0,0 +1,146 @@ +export default { + "id": 27, + "custom_id": null, + "document_type": "invoice", + "proforma_followup_document": null, + "correction_id": null, + "number": "2023-0021", + "number_format_id": 31, + "variable_symbol": "20230021", + "your_name": "Alexandr Hejsek", + "your_street": "Hopsinková 14", + "your_city": "Praha", + "your_zip": "10000", + "your_country": "CZ", + "your_registration_no": "87654321", + "your_vat_no": "CZ12121212", + "your_local_vat_no": null, + "client_name": "Apple Czech s.r.o.", + "client_street": "Klimentská 1216/46", + "client_city": "Praha", + "client_zip": "11000", + "client_country": "CZ", + "client_registration_no": "28897501", + "client_vat_no": "CZ28897501", + "client_local_vat_no": null, + "client_has_delivery_address": false, + "client_delivery_name": null, + "client_delivery_street": null, + "client_delivery_city": null, + "client_delivery_zip": null, + "client_delivery_country": null, + "subject_id": 16, + "subject_custom_id": null, + "generator_id": null, + "related_id": null, + "paypal": false, + "gopay": false, + "token": "69UqMuxhiA", + "status": "sent", + "order_number": null, + "issued_on": "2023-11-30", + "taxable_fulfillment_due": "2023-11-30", + "due": 14, + "due_on": "2023-12-14", + "sent_at": "2023-12-01T09:05:47.117+01:00", + "paid_on": null, + "reminder_sent_at": null, + "cancelled_at": null, + "uncollectible_at": null, + "locked_at": null, + "webinvoice_seen_on": null, + "note": "Fakturujeme Vám následující položky", + "footer_note": "", + "private_note": null, + "tags": [], + "bank_account": "1234/2010", + "iban": null, + "swift_bic": null, + "iban_visibility": "automatically", + "show_already_paid_note_in_pdf": false, + "payment_method": "bank", + "custom_payment_method": null, + "hide_bank_account": false, + "currency": "CZK", + "exchange_rate": "1.0", + "language": "cz", + "transferred_tax_liability": false, + "supply_code": null, + "oss": "disabled", + "vat_price_mode": "with_vat", + "subtotal": "9133.6", + "total": "11000.0", + "native_subtotal": "9133.6", + "native_total": "11000.0", + "remaining_amount": "11000.0", + "remaining_native_amount": "11000.0", + "eet_records": [], + "lines": [ + { + "id": 46, + "name": "Grafická karta", + "quantity": "1.0", + "unit_name": "", + "unit_price": "8264.0", + "vat_rate": 21, + "unit_price_without_vat": "8264.0", + "unit_price_with_vat": "10000.0", + "total_price_without_vat": "8264.0", + "total_vat": "1736.0", + "native_total_price_without_vat": "8264.0", + "native_total_vat": "1736.0", + "inventory": { + "item_id": 26, + "sku": "KU994RUR8465", + "article_number_type": null, + "article_number": null, + "move_id": 56 + } + }, + { + "id": 47, + "name": "Jídlo", + "quantity": "5.0", + "unit_name": "", + "unit_price": "173.92", + "vat_rate": 15, + "unit_price_without_vat": "173.92", + "unit_price_with_vat": "200.0", + "total_price_without_vat": "869.6", + "total_vat": "130.4", + "native_total_price_without_vat": "869.6", + "native_total_vat": "130.4", + "inventory": null + } + ], + "vat_rates_summary": [ + { + "vat_rate": 21, + "base": "8264.0", + "vat": "1736.0", + "currency": "CZK", + "native_base": "8264.0", + "native_vat": "1736.0", + "native_currency": "CZK" + }, + { + "vat_rate": 15, + "base": "869.6", + "vat": "130.4", + "currency": "CZK", + "native_base": "869.6", + "native_vat": "130.4", + "native_currency": "CZK" + } + ], + "paid_advances": [], + "payments": [], + "attachments": null, + "html_url": "https://app.fakturoid.cz/applecorp/invoices/27", + "public_html_url": "https://app.fakturoid.cz/applecorp/p/69UqMuxhiA/2023-0021", + "url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/invoices/27.json", + "pdf_url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/invoices/27/download.pdf", + "subject_url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/subjects/16.json", + "created_at": "2023-11-30T13:50:45.848+01:00", + "updated_at": "2023-12-01T09:05:47.187+01:00" +} \ No newline at end of file diff --git a/components/fakturoid/sources/new-contact/new-contact.mjs b/components/fakturoid/sources/new-contact/new-contact.mjs index 6b7934cfee8f3..b90f04af741cf 100644 --- a/components/fakturoid/sources/new-contact/new-contact.mjs +++ b/components/fakturoid/sources/new-contact/new-contact.mjs @@ -1,75 +1,22 @@ -import fakturoid from "../../fakturoid.app.mjs"; -import { axios } from "@pipedream/platform"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "fakturoid-new-contact", name: "New Contact Added", - description: "Emit new event when a contact (subject) is added in Fakturoid. [See the documentation](https://www.fakturoid.cz/api/v3/subjects)", - version: "0.0.{{ts}}", + description: "Emit new event when a contact (subject) is added in Fakturoid.", + version: "0.0.1", type: "source", dedupe: "unique", - props: { - fakturoid, - db: "$.service.db", - timer: { - type: "$.interface.timer", - default: { - intervalSeconds: 60 * 15, // Poll every 15 minutes - }, - }, - }, methods: { - _getLastTimestamp() { - return this.db.get("lastTimestamp") || 0; + ...common.methods, + getFunction() { + return this.fakturoid.listSubjects; }, - _setLastTimestamp(timestamp) { - this.db.set("lastTimestamp", timestamp); + getSummary(contact) { + return `New Contact Added: ${contact.name}`; }, }, - hooks: { - async deploy() { - const subjects = await this.fakturoid._makeRequest({ - method: "GET", - path: `/accounts/${this.fakturoid.$auth.account_slug}/subjects.json`, - }); - - subjects.slice(-50).forEach((contact) => { - this.$emit(contact, { - id: contact.id, - summary: `New Contact Added: ${contact.name}`, - ts: contact.created_at - ? new Date(contact.created_at).getTime() - : Date.now(), - }); - }); - - if (subjects.length) { - const lastTimestamp = new Date(subjects[subjects.length - 1].created_at).getTime(); - this._setLastTimestamp(lastTimestamp); - } - }, - }, - async run() { - const lastTimestamp = this._getLastTimestamp(); - const subjects = await this.fakturoid._makeRequest({ - method: "GET", - path: `/accounts/${this.fakturoid.$auth.account_slug}/subjects.json`, - }); - - subjects.forEach((contact) => { - const contactTimestamp = new Date(contact.created_at).getTime(); - if (contactTimestamp > lastTimestamp) { - this.$emit(contact, { - id: contact.id, - summary: `New Contact Added: ${contact.name}`, - ts: contactTimestamp, - }); - } - }); - - if (subjects.length) { - const latestTimestamp = new Date(subjects[0].created_at).getTime(); - this._setLastTimestamp(latestTimestamp); - } - }, + sampleEmit, }; diff --git a/components/fakturoid/sources/new-contact/test-event.mjs b/components/fakturoid/sources/new-contact/test-event.mjs index 912a48198cf59..4e23ba4496728 100644 --- a/components/fakturoid/sources/new-contact/test-event.mjs +++ b/components/fakturoid/sources/new-contact/test-event.mjs @@ -1,7 +1,53 @@ export default { - "project": "project_slug", - "translated": 100, - "resource": "resource_slug", - "event": "translation_completed", - "language": "lang_code" + "id": 16, + "custom_id": null, + "user_id": null, + "type": "customer", + "name": "Apple Czech s.r.o.", + "full_name": null, + "email": "pokus@test.cz", + "email_copy": null, + "phone": null, + "web": "https://www.apple.cz", + "street": "Klimentská 1216/46", + "city": "Praha", + "zip": "11000", + "country": "CZ", + "has_delivery_address": false, + "delivery_name": null, + "delivery_street": null, + "delivery_city": null, + "delivery_zip": null, + "delivery_country": null, + "due": null, + "currency": null, + "language": null, + "private_note": null, + "registration_no": "28897501", + "vat_no": "CZ28897501", + "local_vat_no": null, + "unreliable": null, + "unreliable_checked_at": null, + "legal_form": null, + "vat_mode": null, + "bank_account": null, + "iban": null, + "swift_bic": null, + "variable_symbol": null, + "setting_update_from_ares": "inherit", + "ares_update": false, + "setting_invoice_pdf_attachments": "inherit", + "setting_estimate_pdf_attachments": "inherit", + "setting_invoice_send_reminders": "inherit", + "suggestion_enabled": true, + "custom_email_text": null, + "overdue_email_text": null, + "invoice_from_proforma_email_text": null, + "thank_you_email_text": null, + "custom_estimate_email_text": null, + "webinvoice_history": null, + "html_url": "https://app.fakturoid.cz/applecorp/subjects/16", + "url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/subjects/16.json", + "created_at": "2023-08-22T10:59:00.330+02:00", + "updated_at": "2023-08-22T10:59:00.330+02:00" } \ No newline at end of file diff --git a/components/fakturoid/sources/new-invoice/new-invoice.mjs b/components/fakturoid/sources/new-invoice/new-invoice.mjs index 7a85561600d19..9369ed5788fc9 100644 --- a/components/fakturoid/sources/new-invoice/new-invoice.mjs +++ b/components/fakturoid/sources/new-invoice/new-invoice.mjs @@ -1,86 +1,22 @@ -import { axios } from "@pipedream/platform"; -import fakturoid from "../../fakturoid.app.mjs"; +import common from "../common/base.mjs"; +import sampleEmit from "./test-event.mjs"; export default { + ...common, key: "fakturoid-new-invoice", name: "New Invoice Created", - description: "Emit new event when a new invoice is created in Fakturoid. [See the documentation](https://www.fakturoid.cz/api/v3/invoices)", - version: "0.0.{{ts}}", + description: "Emit new event when a new invoice is created in Fakturoid.", + version: "0.0.1", type: "source", dedupe: "unique", - props: { - fakturoid, - db: "$.service.db", - customerId: { - propDefinition: [ - fakturoid, - "customerId", - ], - optional: true, - }, - timer: { - type: "$.interface.timer", - default: { - intervalSeconds: 60 * 15, - }, - }, - }, methods: { - async _getInvoices(params) { - return this.fakturoid._makeRequest({ - path: `/accounts/${this.fakturoid.$auth.account_slug}/invoices.json`, - params, - }); - }, - _getLastInvoiceId() { - return this.db.get("lastInvoiceId"); + ...common.methods, + getFunction() { + return this.fakturoid.listInvoices; }, - _setLastInvoiceId(invoiceId) { - this.db.set("lastInvoiceId", invoiceId); + getSummary(invoice) { + return `New invoice created: ${invoice.number}`; }, }, - hooks: { - async deploy() { - const params = { - order: "created_at desc", - since: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(), - }; - if (this.customerId) { - params.subject_id = this.customerId; - } - const invoices = await this._getInvoices(params); - invoices.slice(0, 50).forEach((invoice) => { - this.$emit(invoice, { - id: invoice.id, - summary: `New invoice created: ${invoice.number}`, - ts: Date.parse(invoice.created_at), - }); - }); - if (invoices.length) { - this._setLastInvoiceId(invoices[0].id); - } - }, - }, - async run() { - const lastInvoiceId = this._getLastInvoiceId(); - const params = { - order: "created_at desc", - since_id: lastInvoiceId, - }; - if (this.customerId) { - params.subject_id = this.customerId; - } - - const invoices = await this._getInvoices(params); - if (invoices.length) { - invoices.forEach((invoice) => { - this.$emit(invoice, { - id: invoice.id, - summary: `New invoice created: ${invoice.number}`, - ts: Date.parse(invoice.created_at), - }); - }); - this._setLastInvoiceId(invoices[0].id); - } - }, + sampleEmit, }; diff --git a/components/fakturoid/sources/new-invoice/test-event.mjs b/components/fakturoid/sources/new-invoice/test-event.mjs index 912a48198cf59..63e50c797044c 100644 --- a/components/fakturoid/sources/new-invoice/test-event.mjs +++ b/components/fakturoid/sources/new-invoice/test-event.mjs @@ -1,7 +1,146 @@ export default { - "project": "project_slug", - "translated": 100, - "resource": "resource_slug", - "event": "translation_completed", - "language": "lang_code" + "id": 27, + "custom_id": null, + "document_type": "invoice", + "proforma_followup_document": null, + "correction_id": null, + "number": "2023-0021", + "number_format_id": 31, + "variable_symbol": "20230021", + "your_name": "Alexandr Hejsek", + "your_street": "Hopsinková 14", + "your_city": "Praha", + "your_zip": "10000", + "your_country": "CZ", + "your_registration_no": "87654321", + "your_vat_no": "CZ12121212", + "your_local_vat_no": null, + "client_name": "Apple Czech s.r.o.", + "client_street": "Klimentská 1216/46", + "client_city": "Praha", + "client_zip": "11000", + "client_country": "CZ", + "client_registration_no": "28897501", + "client_vat_no": "CZ28897501", + "client_local_vat_no": null, + "client_has_delivery_address": false, + "client_delivery_name": null, + "client_delivery_street": null, + "client_delivery_city": null, + "client_delivery_zip": null, + "client_delivery_country": null, + "subject_id": 16, + "subject_custom_id": null, + "generator_id": null, + "related_id": null, + "paypal": false, + "gopay": false, + "token": "69UqMuxhiA", + "status": "sent", + "order_number": null, + "issued_on": "2023-11-30", + "taxable_fulfillment_due": "2023-11-30", + "due": 14, + "due_on": "2023-12-14", + "sent_at": "2023-12-01T09:05:47.117+01:00", + "paid_on": null, + "reminder_sent_at": null, + "cancelled_at": null, + "uncollectible_at": null, + "locked_at": null, + "webinvoice_seen_on": null, + "note": "Fakturujeme Vám následující položky", + "footer_note": "", + "private_note": null, + "tags": [], + "bank_account": "1234/2010", + "iban": null, + "swift_bic": null, + "iban_visibility": "automatically", + "show_already_paid_note_in_pdf": false, + "payment_method": "bank", + "custom_payment_method": null, + "hide_bank_account": false, + "currency": "CZK", + "exchange_rate": "1.0", + "language": "cz", + "transferred_tax_liability": false, + "supply_code": null, + "oss": "disabled", + "vat_price_mode": "with_vat", + "subtotal": "9133.6", + "total": "11000.0", + "native_subtotal": "9133.6", + "native_total": "11000.0", + "remaining_amount": "11000.0", + "remaining_native_amount": "11000.0", + "eet_records": [], + "lines": [ + { + "id": 46, + "name": "Grafická karta", + "quantity": "1.0", + "unit_name": "", + "unit_price": "8264.0", + "vat_rate": 21, + "unit_price_without_vat": "8264.0", + "unit_price_with_vat": "10000.0", + "total_price_without_vat": "8264.0", + "total_vat": "1736.0", + "native_total_price_without_vat": "8264.0", + "native_total_vat": "1736.0", + "inventory": { + "item_id": 26, + "sku": "KU994RUR8465", + "article_number_type": null, + "article_number": null, + "move_id": 56 + } + }, + { + "id": 47, + "name": "Jídlo", + "quantity": "5.0", + "unit_name": "", + "unit_price": "173.92", + "vat_rate": 15, + "unit_price_without_vat": "173.92", + "unit_price_with_vat": "200.0", + "total_price_without_vat": "869.6", + "total_vat": "130.4", + "native_total_price_without_vat": "869.6", + "native_total_vat": "130.4", + "inventory": null + } + ], + "vat_rates_summary": [ + { + "vat_rate": 21, + "base": "8264.0", + "vat": "1736.0", + "currency": "CZK", + "native_base": "8264.0", + "native_vat": "1736.0", + "native_currency": "CZK" + }, + { + "vat_rate": 15, + "base": "869.6", + "vat": "130.4", + "currency": "CZK", + "native_base": "869.6", + "native_vat": "130.4", + "native_currency": "CZK" + } + ], + "paid_advances": [], + "payments": [], + "attachments": null, + "html_url": "https://app.fakturoid.cz/applecorp/invoices/27", + "public_html_url": "https://app.fakturoid.cz/applecorp/p/69UqMuxhiA/2023-0021", + "url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/invoices/27.json", + "pdf_url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/invoices/27/download.pdf", + "subject_url": "https://app.fakturoid.cz/api/v3/accounts/applecorp/subjects/16.json", + "created_at": "2023-11-30T13:50:45.848+01:00", + "updated_at": "2023-12-01T09:05:47.187+01:00" } \ No newline at end of file From 36f387315e603101ca5adaff367c519f873a0c2c Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 15 Oct 2024 11:16:04 -0300 Subject: [PATCH 5/7] update @pipedream/platform dependence version --- components/fakturoid/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/fakturoid/package.json b/components/fakturoid/package.json index 08662045c4063..31085d2cedd89 100644 --- a/components/fakturoid/package.json +++ b/components/fakturoid/package.json @@ -13,7 +13,7 @@ "access": "public" }, "dependencies": { - "@pipedream/platform": "^3.0.1" + "@pipedream/platform": "^3.0.3" } } From 1fbd4d88449a7c3ed52cf9b97a7a04b1dcce29de Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Tue, 15 Oct 2024 11:16:44 -0300 Subject: [PATCH 6/7] pnpm update --- pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75020bcd357ad..a854a4f227da4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,7 +60,7 @@ importers: pnpm: 7.33.6 putout: 32.2.0_typescript@5.2.2 renamer: 4.0.0 - ts-jest: 29.1.1_py5cyg2l76gggsf4xgc65fzuzq + ts-jest: 29.1.1_s6pp5jfszqvqftxetajx5tybba tsc-esm-fix: 2.20.17 tsc-watch: 5.0.3_typescript@5.2.2 typescript: 5.2.2 @@ -3278,9 +3278,9 @@ importers: components/fakturoid: specifiers: - '@pipedream/platform': ^3.0.1 + '@pipedream/platform': ^3.0.3 dependencies: - '@pipedream/platform': 3.0.1 + '@pipedream/platform': 3.0.3 components/faraday: specifiers: @@ -34624,7 +34624,7 @@ packages: engines: {node: '>=6'} dev: true - /ts-jest/29.1.1_py5cyg2l76gggsf4xgc65fzuzq: + /ts-jest/29.1.1_s6pp5jfszqvqftxetajx5tybba: resolution: {integrity: sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -34645,7 +34645,7 @@ packages: esbuild: optional: true dependencies: - '@babel/core': 7.23.0 + '@babel/core': 7.25.2 bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 jest: 29.7.0_@types+node@20.9.2 From 115031f718523bec3ce9ad6c47289d91da7f5a10 Mon Sep 17 00:00:00 2001 From: Luan Cazarine Date: Wed, 16 Oct 2024 10:11:59 -0300 Subject: [PATCH 7/7] Update components/fakturoid/actions/create-invoice/create-invoice.mjs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- components/fakturoid/actions/create-invoice/create-invoice.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/fakturoid/actions/create-invoice/create-invoice.mjs b/components/fakturoid/actions/create-invoice/create-invoice.mjs index b9f88b9bd2ae9..f11db2fb28c54 100644 --- a/components/fakturoid/actions/create-invoice/create-invoice.mjs +++ b/components/fakturoid/actions/create-invoice/create-invoice.mjs @@ -76,7 +76,7 @@ export default { }, roundTotal: { type: "boolean", - label: "Tound Total", + label: "Round Total", description: "Round total amount (VAT included)", optional: true, },