Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release version 0.15.0 #123

Merged
merged 14 commits into from
Sep 13, 2024
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: dotnet test --no-build --settings coverlet.runsettings --verbosity normal

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.15.0 | 2024-09-13
* Add support for Send an invoice operation in the `Sales invoice` endpoint

## 0.14.0 | 2024-07-07
* Add support for `Time entry` endpoint
* Refactoring of the `Note` entity from `ContactNote` to a generic `Note` used in multiple entity types
Expand Down Expand Up @@ -37,7 +40,7 @@
## 0.9.0 | 2023-06-04
* Add support for `Tax rates` endpoint.
* Add support for `Ledger account` endpoint.
* Add support for `Sales invoices endpoint` endpoint (limited operations).
* Add support for `Sales invoices` endpoint endpoint (limited operations).
* Add support for `External sales invoices` endpoint (limited operations).
* Change names (classes, enums, interfaces) and their namespaces.

Expand Down
10 changes: 10 additions & 0 deletions src/Moneybird.Net/Endpoints/Abstractions/ISalesInvoiceEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ public interface ISalesInvoiceEndpoint :
IUpdateEndpoint<SalesInvoice, SalesInvoiceUpdateOptions>,
IDeleteEndpoint
{
/// <summary>
/// Send an invoice to a customer.
/// </summary>
/// <param name="administrationId">The administration id.</param>
/// <param name="salesInvoiceId">The sales invoice id.</param>
/// <param name="options">The options to send the invoice with.</param>
/// <param name="accessToken">The access token.</param>
/// <returns></returns>
Task<SalesInvoice> SendInvoice(string administrationId, string salesInvoiceId, SalesInvoiceSendOptions options, string accessToken);

/// <summary>
/// Add an attachment to a sales invoice.
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions src/Moneybird.Net/Endpoints/SalesInvoiceEndpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class SalesInvoiceEndpoint : ISalesInvoiceEndpoint
{
private const string SalesInvoiceUri = "/{0}/sales_invoices.json";
private const string SalesInvoiceIdUri = "/{0}/sales_invoices/{1}.json";
private const string SalesInvoiceSendInvoiceUri = "/{0}/sales_invoices/{1}/send_invoice.json";
private const string SalesInvoiceAttachmentUri = "/{0}/external_sales_invoices/{1}/attachment";

private readonly MoneybirdConfig _config;
Expand Down Expand Up @@ -96,6 +97,17 @@ public async Task<bool> DeleteByIdAsync(string administrationId, string salesInv
return response;
}

public async Task<SalesInvoice> SendInvoice(string administrationId, string salesInvoiceId, SalesInvoiceSendOptions options, string accessToken)
{
var relativeUrl = string.Format(SalesInvoiceSendInvoiceUri, administrationId, salesInvoiceId);
var body = JsonSerializer.Serialize(options, _config.SerializerOptions);
var responseJson = await _requester
.CreatePatchRequestAsync(_config.ApiUri, relativeUrl, accessToken, body)
.ConfigureAwait(false);

return JsonSerializer.Deserialize<SalesInvoice>(responseJson, _config.SerializerOptions); ;
}

public async Task AddAttachmentAsync(string administrationId, string salesInvoiceId, Stream body, string accessToken, string fileName = "invoice.pdf")
{
var relativeUrl = string.Format(SalesInvoiceAttachmentUri, administrationId, salesInvoiceId);
Expand Down
29 changes: 29 additions & 0 deletions src/Moneybird.Net/Models/SalesInvoices/SalesInvoiceSendOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Moneybird.Net.Misc;
using System.Text.Json.Serialization;

namespace Moneybird.Net.Models.SalesInvoices
{
public class SalesInvoiceSendOptions
{
[JsonPropertyName("delivery_method")]
public DeliveryMethod DeliveryMethod { get; set; }

[JsonPropertyName("sending_scheduled")]
public bool SendingScheduled { get; set; }

[JsonPropertyName("deliver_ubl")]
public bool DeliverUbl { get; set; }

[JsonPropertyName("mergable")]
public bool Mergeable { get; set; }

[JsonPropertyName("email_address")]
public string EmailAddress { get; set; }

[JsonPropertyName("email_message")]
public string EmailMessage { get; set; }

[JsonPropertyName("invoice_date")]
public string InvoiceDate { get; set; }
}
}
6 changes: 3 additions & 3 deletions src/Moneybird.Net/Moneybird.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>9</LangVersion>
<PackageId>Moneybird.Net</PackageId>
<Version>0.14.0</Version>
<Version>0.15.0</Version>
<Authors>Vincent Vrijburg</Authors>
<Description>A wrapper for the Moneybird API.</Description>
<Copyright>Copyright © Vincent Vrijburg 2021</Copyright>
Expand All @@ -12,12 +12,12 @@
<PackageTags>dotnet dotnet-core dotnet-standard client wrapper moneybird</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageVersion>0.14.0</PackageVersion>
<PackageVersion>0.15.0</PackageVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Macross.Json.Extensions" Version="3.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.3" />
<PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup>

<ItemGroup>
Expand Down
32 changes: 32 additions & 0 deletions tests/Moneybird.Net.Tests/Endpoints/SalesInvoiceEndpointTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Moneybird.Net.Entities.CustomFields;
using Moneybird.Net.Entities.SalesInvoices;
using Moneybird.Net.Http;
using Moneybird.Net.Misc;
using Moneybird.Net.Models.SalesInvoices;
using Moq;
using Xunit;
Expand All @@ -23,6 +24,7 @@ public class SalesInvoiceEndpointTests : SalesInvoiceTestBase
private const string GetSalesInvoicesResponsePath = "./Responses/Endpoints/SalesInvoices/getSalesInvoices.json";
private const string GetSalesInvoiceResponsePath = "./Responses/Endpoints/SalesInvoices/getSalesInvoice.json";
private const string PostSalesInvoiceResponsePath = "./Responses/Endpoints/SalesInvoices/postSalesInvoice.json";
private const string SendSalesInvoiceResponsePath = "./Responses/Endpoints/SalesInvoices/sendSalesInvoice.json";

public SalesInvoiceEndpointTests()
{
Expand Down Expand Up @@ -267,6 +269,36 @@ public async void DeleteSalesInvoiceAsync_ByAccessToken_Returns_True()
Assert.True(actualSalesInvoice);
}

[Fact]
public async void SendSalesInvoiceAsync_ByAccessToken_Returns_UpdatedSalesInvoice()
{
var salesInvoiceJson = await File.ReadAllTextAsync(SendSalesInvoiceResponsePath);
var salesInvoiceSendOptions = new SalesInvoiceSendOptions
{
DeliveryMethod = DeliveryMethod.Email,
SendingScheduled = false,
DeliverUbl = false,
Mergeable = false,
EmailAddress = "[email protected]",
EmailMessage = "Geachte Foobar Holding B.V.,\n\nIn de bijlage kunt u factuur 2024-0001 voor onze diensten vinden. Wij verzoeken u vriendelijk de factuur voor 30-07-2024 te voldoen.\n\nMet vriendelijke groet,\n\nParkietje B.V.",
InvoiceDate = null
};

var serializedSalesInvoiceSendOptions = JsonSerializer.Serialize(salesInvoiceSendOptions, _config.SerializerOptions);

_requester.Setup(moq => moq.CreatePatchRequestAsync(It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<string>(), It.Is<string>(s => s.Equals(serializedSalesInvoiceSendOptions)), It.IsAny<List<string>>()))
.ReturnsAsync(salesInvoiceJson);

var salesInvoice = JsonSerializer.Deserialize<SalesInvoice>(salesInvoiceJson, _config.SerializerOptions);
Assert.NotNull(salesInvoice);

var actualSalesInvoice = await _salesInvoiceEndpoint.SendInvoice(AdministrationId, SalesInvoiceId, salesInvoiceSendOptions, AccessToken);
Assert.NotNull(actualSalesInvoice);

salesInvoice.Should().BeEquivalentTo(actualSalesInvoice);
}

[Fact]
public async void AddSalesInvoiceAttachmentAsync_ByAccessToken_Returns()
{
Expand Down
10 changes: 5 additions & 5 deletions tests/Moneybird.Net.Tests/Moneybird.Net.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.18.1" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="Moq" Version="4.20.70" />
<PackageReference Include="xunit" Version="2.8.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
<PackageReference Include="FluentAssertions" Version="6.12.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
{
"id": "426664263209191199",
"administration_id": "281289699686381606",
"contact_id": "426664263157810972",
"contact": {
"id": "426664263157810972",
"administration_id": "281289699686381606",
"company_name": "Foobar Holding B.V.",
"firstname": "",
"lastname": "",
"address1": "Hoofdstraat 12",
"address2": "",
"zipcode": "1234AB",
"city": "Amsterdam",
"country": "NL",
"phone": "",
"delivery_method": "Email",
"customer_id": "1",
"tax_number": "",
"chamber_of_commerce": "",
"bank_account": "",
"attention": "",
"email": "[email protected]",
"email_ubl": true,
"send_invoices_to_attention": "",
"send_invoices_to_email": "[email protected]",
"send_estimates_to_attention": "",
"send_estimates_to_email": "[email protected]",
"sepa_active": false,
"sepa_iban": "",
"sepa_iban_account_name": "",
"sepa_bic": "",
"sepa_mandate_id": "",
"sepa_mandate_date": null,
"sepa_sequence_type": "RCUR",
"credit_card_number": "",
"credit_card_reference": "",
"credit_card_type": null,
"tax_number_validated_at": null,
"tax_number_valid": null,
"invoice_workflow_id": null,
"estimate_workflow_id": null,
"si_identifier": "",
"si_identifier_type": null,
"moneybird_payments_mandate": false,
"created_at": "2024-07-16T08:32:51.222Z",
"updated_at": "2024-07-16T08:32:51.222Z",
"version": 1721118771,
"sales_invoices_url": "https://moneybird.dev/123/sales_invoices/844adf6b1bc4707699d9dd99a1b98993098ad5de1e4879f7e3b9ae7ab4f19093/all",
"notes": [

],
"custom_fields": [

],
"contact_people": [

],
"archived": false
},
"contact_person_id": null,
"contact_person": null,
"invoice_id": "2024-0001",
"recurring_sales_invoice_id": null,
"subscription_id": null,
"workflow_id": "426664036392764982",
"document_style_id": "426664036528031296",
"identity_id": "426664036248061493",
"draft_id": null,
"state": "open",
"invoice_date": "2024-07-16",
"due_date": "2024-07-30",
"payment_conditions": "We verzoeken u vriendelijk het bovenstaande bedrag van {document.total_price} voor {document.due_date} te voldoen op onze bankrekening onder vermelding van de omschrijving {document.payment_reference}. Voor vragen kunt u contact opnemen per e-mail.",
"payment_reference": "RF020000000000000S42QAK2U",
"short_payment_reference": "RF02S42QAK2U",
"reference": "Project X",
"language": "nl",
"currency": "EUR",
"discount": "0.0",
"original_sales_invoice_id": null,
"paused": false,
"paid_at": null,
"sent_at": "2024-07-16",
"created_at": "2024-07-16T08:32:51.271Z",
"updated_at": "2024-07-16T08:32:51.413Z",
"public_view_code": "690819",
"public_view_code_expires_at": "2024-10-16T08:32:51.375Z",
"version": 1721118771,
"details": [
{
"id": "426664263213385504",
"administration_id": "281289699686381606",
"tax_rate_id": "426664036220798511",
"ledger_account_id": "426664036164175387",
"project_id": null,
"product_id": null,
"amount": "1 x",
"amount_decimal": "1.0",
"description": "Project X",
"price": "300.0",
"period": null,
"row_order": 1,
"total_price_excl_tax_with_discount": "300.0",
"total_price_excl_tax_with_discount_base": "300.0",
"tax_report_reference": [
"NL/1a"
],
"mandatory_tax_text": null,
"created_at": "2024-07-16T08:32:51.275Z",
"updated_at": "2024-07-16T08:32:51.412Z"
}
],
"payments": [

],
"total_paid": "0.0",
"total_unpaid": "363.0",
"total_unpaid_base": "363.0",
"prices_are_incl_tax": false,
"total_price_excl_tax": "300.0",
"total_price_excl_tax_base": "300.0",
"total_price_incl_tax": "363.0",
"total_price_incl_tax_base": "363.0",
"total_discount": "0.0",
"marked_dubious_on": null,
"marked_uncollectible_on": null,
"reminder_count": 0,
"next_reminder": "2024-07-30",
"original_estimate_id": null,
"url": "http://moneybird.dev/123/sales_invoices/d0584001cffb56da9149dec560fabc41d697d79ab4bdd74569d9b5aa27872ddf/844adf6b1bc4707699d9dd99a1b98993098ad5de1e4879f7e3b9ae7ab4f19093",
"payment_url": "http://moneybird.dev/123/online_sales_invoices/d0584001cffb56da9149dec560fabc41d697d79ab4bdd74569d9b5aa27872ddf/844adf6b1bc4707699d9dd99a1b98993098ad5de1e4879f7e3b9ae7ab4f19093/pay_invoice",
"custom_fields": [

],
"notes": [

],
"attachments": [

],
"events": [
{
"administration_id": "281289699686381606",
"user_id": 17211185545521,
"action": "sales_invoice_created",
"link_entity_id": null,
"link_entity_type": null,
"data": {
},
"created_at": "2024-07-16T08:32:51.279Z",
"updated_at": "2024-07-16T08:32:51.279Z"
},
{
"administration_id": "281289699686381606",
"user_id": 17211185545521,
"action": "sales_invoice_state_changed_to_open",
"link_entity_id": null,
"link_entity_type": null,
"data": {
},
"created_at": "2024-07-16T08:32:51.388Z",
"updated_at": "2024-07-16T08:32:51.388Z"
},
{
"administration_id": "281289699686381606",
"user_id": 17211185545521,
"action": "sales_invoice_send_email",
"link_entity_id": null,
"link_entity_type": null,
"data": {
"email_address": "[email protected]",
"email_message": "Geachte Foobar Holding B.V.,\n\nIn de bijlage kunt u factuur 2024-0001 voor onze diensten vinden. Wij verzoeken u vriendelijk de factuur voor 30-07-2024 te voldoen.\n\nMet vriendelijke groet,\n\nParkietje B.V."
},
"created_at": "2024-07-16T08:32:51.429Z",
"updated_at": "2024-07-16T08:32:51.429Z"
}
],
"tax_totals": [
{
"tax_rate_id": "426664036220798511",
"taxable_amount": "300.0",
"taxable_amount_base": "300.0",
"tax_amount": "63.0",
"tax_amount_base": "63.0"
}
]
}
Loading