Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {
key: "fortnox-create-article",
name: "Create Article",
description: "Creates a new article in the Fortnox API. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Articles/operation/1_create_3).",
version: "0.0.1",
version: "0.0.2",
type: "action",
annotations: {
destructiveHint: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {
key: "fortnox-create-customer",
name: "Create Customer",
description: "Creates a new customer in the Fortnox API. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Customers/operation/create_16).",
version: "0.0.1",
version: "0.0.2",
type: "action",
annotations: {
destructiveHint: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {
key: "fortnox-create-invoice-payment",
name: "Create Invoice Payment",
description: "Creates a new invoice payment in the Fortnox API. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_InvoicePayments/operation/create_22).",
version: "0.0.1",
version: "0.0.2",
type: "action",
annotations: {
destructiveHint: false,
Expand All @@ -25,12 +25,6 @@ export default {
description: "The amount of the payment",
optional: true,
},
booked: {
type: "boolean",
label: "Booked",
description: "Whether the payment is booked",
optional: true,
},
customerNumber: {
propDefinition: [
fortnox,
Expand All @@ -41,13 +35,13 @@ export default {
dueDate: {
type: "string",
label: "Due Date",
description: "The due date of the invoice",
description: "The due date of the invoice. Format DD/MM/YYYY",
optional: true,
},
paymentDate: {
type: "string",
label: "Payment Date",
description: "The date of the payment",
description: "The date of the payment. Format DD/MM/YYYY",
optional: true,
},
invoiceTotal: {
Expand Down Expand Up @@ -78,7 +72,6 @@ export default {
Amount: this.amount
? +this.amount
: undefined,
Booked: this.booked,
InvoiceCustomerNumber: this.customerNumber,
InvoiceDueDate: this.dueDate,
InvoiceTotal: this.invoiceTotal
Expand Down
20 changes: 11 additions & 9 deletions components/fortnox/actions/create-invoice/create-invoice.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import fortnox from "../../fortnox.app.mjs";
import { parseObject } from "../../common/utils.mjs";
import fortnox from "../../fortnox.app.mjs";

export default {
key: "fortnox-create-invoice",
name: "Create Invoice",
description: "Creates a new invoice in the Fortnox API. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Invoices/operation/create_23).",
version: "0.0.1",
version: "0.0.2",
type: "action",
annotations: {
destructiveHint: false,
Expand Down Expand Up @@ -105,16 +105,18 @@ export default {
description: "The freight of the invoice",
optional: true,
},
termsOfDelivery: {
type: "string",
label: "Terms of Delivery",
description: "The terms of delivery of the invoice",
termsOfDeliveries: {
propDefinition: [
fortnox,
"termsOfDeliveries",
],
optional: true,
},
termsOfPayment: {
type: "string",
label: "Terms of Payment",
description: "The terms of payment of the invoice",
propDefinition: [
fortnox,
"termsOfPayments",
],
optional: true,
Comment on lines +108 to 120
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix mismatch between termsOfDeliveries prop and TermsOfDelivery payload field

You renamed the prop to termsOfDeliveries, but the payload still reads from this.termsOfDelivery, so TermsOfDelivery is always undefined and never sent.

Update the payload to use the actual prop name:

     termsOfDeliveries: {
       propDefinition: [
         fortnox,
         "termsOfDeliveries",
       ],
       optional: true,
     },
@@
-          TermsOfDelivery: this.termsOfDelivery,
+          TermsOfDelivery: this.termsOfDeliveries,
           TermsOfPayment: this.termsOfPayment,

This wires the selected term of delivery into the created invoice correctly.

Also applies to: 148-150

🤖 Prompt for AI Agents
In components/fortnox/actions/create-invoice/create-invoice.mjs around lines
108-120 (and similarly at 148-150), the code renamed the prop to
termsOfDeliveries but the payload still reads this.termsOfDelivery, causing
TermsOfDelivery to be undefined; update the payload to read
this.termsOfDeliveries (and any other occurrences) so the TermsOfDelivery field
is set from the actual prop name and sent in the created invoice.

},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import app from "../../fortnox.app.mjs";

export default {
key: "fortnox-get-supplier-invoice",
name: "Get Supplier Invoice",
description: "Retrieve a supplier invoice. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_SupplierInvoices/operation/get_39)",
version: "0.0.1",
type: "action",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
props: {
app,
supplierInvoiceNumber: {
propDefinition: [
app,
"supplierInvoiceNumber",
],
},
},
async run({ $ }) {
const { SupplierInvoice } = await this.app.getSupplierInvoice({
$,
supplierInvoiceNumber: this.supplierInvoiceNumber,
});

$.export("$summary", `Successfully retrieved supplier invoice with number ${this.supplierInvoiceNumber}`);
return SupplierInvoice;
},
};
27 changes: 27 additions & 0 deletions components/fortnox/actions/list-accounts/list-accounts.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import app from "../../fortnox.app.mjs";

export default {
key: "fortnox-list-accounts",
name: "List Accounts",
description: "List all accounts in Fortnox. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Accounts/operation/list_2)",
version: "0.0.1",
type: "action",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
props: {
app,
},
async run({ $ }) {
const { Accounts: accounts } = await this.app.listAccounts({
$,
});

$.export("$summary", `Successfully retrieved ${accounts.length} account${accounts.length === 1
? ""
: "s"}`);
return accounts;
Comment on lines +17 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Default accounts to an empty array to avoid potential runtime errors

If the API ever omits or nulls the Accounts field, accounts.length will throw. A small defensive tweak keeps behavior the same when data is present:

-    const { Accounts: accounts } = await this.app.listAccounts({
+    const { Accounts: accounts = [] } = await this.app.listAccounts({
       $,
     });

This also guarantees the action always returns an array.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async run({ $ }) {
const { Accounts: accounts } = await this.app.listAccounts({
$,
});
$.export("$summary", `Successfully retrieved ${accounts.length} account${accounts.length === 1
? ""
: "s"}`);
return accounts;
async run({ $ }) {
const { Accounts: accounts = [] } = await this.app.listAccounts({
$,
});
$.export("$summary", `Successfully retrieved ${accounts.length} account${accounts.length === 1
? ""
: "s"}`);
return accounts;
🤖 Prompt for AI Agents
In components/fortnox/actions/list-accounts/list-accounts.mjs around lines 17 to
25, the code assumes this.app.listAccounts() always returns an Accounts array so
accounts.length can be read; if Accounts is null/undefined this will throw.
Change the destructuring to default Accounts to an empty array (e.g., const {
Accounts: accounts = [] } = ...) or assign accounts = Accounts || [] after the
call, then use accounts.length for the $summary and return accounts so the
action always returns an array.

},
};
109 changes: 109 additions & 0 deletions components/fortnox/actions/list-articles/list-articles.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import app from "../../fortnox.app.mjs";

export default {
key: "fortnox-list-articles",
name: "List Articles",
description: "List all articles in Fortnox. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Articles/operation/list_4)",
version: "0.0.1",
type: "action",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
props: {
app,
filter: {
type: "string",
label: "Filter",
description: "Filter the articles by Active or Inactive",
options: [
"active",
"inactive",
],
optional: true,
},
articlenumber: {
type: "string",
label: "Article Number",
description: "Filter by article number",
optional: true,
},
description: {
type: "string",
label: "Description",
description: "Filter by description",
optional: true,
},
ean: {
type: "string",
label: "EAN",
description: "Filter by EAN",
optional: true,
},
suppliernumber: {
type: "string",
label: "Supplier Number",
description: "Filter by supplier number",
optional: true,
},
manufacturer: {
type: "string",
label: "Manufacturer",
description: "Filter by manufacturer",
optional: true,
},
manufacturerarticlenumber: {
type: "string",
label: "Manufacturer Article Number",
description: "Filter by manufacturer article number",
optional: true,
},
webshop: {
type: "string",
label: "Webshop",
description: "Filter by web shop",
optional: true,
},
lastmodified: {
type: "string",
label: "Last Modified",
description: "Filter by last modified date",
optional: true,
},
sortby: {
type: "string",
label: "Sort By",
description: "Sort the articles by the specified field",
optional: true,
options: [
"articlenumber",
"quantityinstock",
"reservedquantity",
"stockvalue",
],
},
},
async run({ $ }) {
const { Articles } = await this.app.listArticles({
$,
params: {
filter: this.filter,
articlenumber: this.articlenumber,
description: this.description,
ean: this.ean,
suppliernumber: this.suppliernumber,
manufacturer: this.manufacturer,
manufacturerarticlenumber: this.manufacturerarticlenumber,
webshop: this.webshop,
lastmodified: this.lastmodified,
sortby: this.sortby,
},
});

$.export("$summary", `Successfully retrieved ${Articles.length} article${Articles.length === 1
? ""
: "s"}`);
return Articles;
},
};
121 changes: 121 additions & 0 deletions components/fortnox/actions/list-customers/list-customers.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import app from "../../fortnox.app.mjs";

export default {
key: "fortnox-list-customers",
name: "List Customers",
description: "List all customers in Fortnox. [See the documentation](https://api.fortnox.se/apidocs#tag/fortnox_Customers/operation/list_15)",
version: "0.0.1",
type: "action",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
props: {
app,
filter: {
type: "string",
label: "Filter",
description: "Filter the customers by Active or Inactive",
options: [
"active",
"inactive",
],
optional: true,
},
customernumber: {
type: "string",
label: "Customer Number",
description: "Filter by customer number",
optional: true,
},
name: {
type: "string",
label: "Name",
description: "Filter by name",
optional: true,
},
zipcode: {
type: "string",
label: "Zip Code",
description: "Filter by zip code",
optional: true,
},
city: {
type: "string",
label: "City",
description: "Filter by city",
optional: true,
},
email: {
type: "string",
label: "Email",
description: "Filter by email",
optional: true,
},
phone: {
type: "string",
label: "Phone",
description: "Filter by phone",
optional: true,
},
organisationnumber: {
type: "string",
label: "Organisation Number",
description: "Filter by organisation number",
optional: true,
},
gln: {
type: "string",
label: "GLN",
description: "Filter by GLN",
optional: true,
},
glndelivery: {
type: "string",
label: "GLN Delivery",
description: "Filter by GLN Delivery",
optional: true,
},
lastmodified: {
type: "string",
label: "Last Modified",
description: "Filter by last modified date",
optional: true,
},
sortby: {
type: "string",
label: "Sort By",
description: "Sort the customers by the specified field",
optional: true,
options: [
"customernumber",
"name",
],
},
},
async run({ $ }) {
const { Customers } = await this.app.listCustomers({
$,
params: {
filter: this.filter,
customernumber: this.customernumber,
name: this.name,
zipcode: this.zipcode,
city: this.city,
email: this.email,
phone: this.phone,
organisationnumber: this.organisationnumber,
gln: this.gln,
glndelivery: this.glndelivery,
lastmodified: this.lastmodified,
sortby: this.sortby,
},
});

$.export("$summary", `Successfully retrieved ${Customers.length} customer${Customers.length === 1
? ""
: "s"}`);
return Customers;
},
};
Loading
Loading