diff --git a/source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs b/source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs index 5ee2fe5..6d28916 100644 --- a/source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs +++ b/source/VMelnalksnis.PaperlessDotNet.DependencyInjection/ServiceCollectionExtensions.cs @@ -12,6 +12,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using VMelnalksnis.PaperlessDotNet.Correspondents; using VMelnalksnis.PaperlessDotNet.Documents; using VMelnalksnis.PaperlessDotNet.Serialization; @@ -46,6 +47,12 @@ public static IHttpClientBuilder AddPaperlessDotNet( return serviceCollection .AddSingleton() .AddTransient() + .AddTransient(provider => + { + var httpClient = provider.GetRequiredService().CreateClient(PaperlessOptions.Name); + var options = provider.GetRequiredService(); + return new(httpClient, options); + }) .AddTransient(provider => { var httpClient = provider.GetRequiredService().CreateClient(PaperlessOptions.Name); diff --git a/source/VMelnalksnis.PaperlessDotNet/Correspondents/Correspondent.cs b/source/VMelnalksnis.PaperlessDotNet/Correspondents/Correspondent.cs new file mode 100644 index 0000000..4d26570 --- /dev/null +++ b/source/VMelnalksnis.PaperlessDotNet/Correspondents/Correspondent.cs @@ -0,0 +1,35 @@ +// Copyright 2022 Valters Melnalksnis +// Licensed under the Apache License 2.0. +// See LICENSE file in the project root for full license information. + +using NodaTime; + +namespace VMelnalksnis.PaperlessDotNet.Correspondents; + +/// Someone with whom documents were exchanged with. +public sealed class Correspondent +{ + /// Gets or sets the id of the correspondent. + public int Id { get; set; } + + /// Gets or sets the normalized - lowercased and with whitespace replaced with '-'. + public string Slug { get; set; } = null!; + + /// Gets or sets the name of the correspondent. + public string Name { get; set; } = null!; + + /// Gets or sets the pattern by which to match the correspondent to documents. + public string MatchingPattern { get; set; } = null!; + + /// Gets or sets the id of the matching algorithm used to match the correspondent to documents. + public int MatchingAlgorithmId { get; set; } + + /// Gets or sets a value indicating whether to ignore case when matching the correspondent to documents. + public bool CaseInsensitiveMatching { get; set; } + + /// Gets or sets the number of documents with the correspondent. + public int DocumentCount { get; set; } + + /// Gets or sets the instant when the last document with the correspondent was created. + public Instant? LastCorrespondence { get; set; } +} diff --git a/source/VMelnalksnis.PaperlessDotNet/Correspondents/CorrespondentClient.cs b/source/VMelnalksnis.PaperlessDotNet/Correspondents/CorrespondentClient.cs new file mode 100644 index 0000000..1444741 --- /dev/null +++ b/source/VMelnalksnis.PaperlessDotNet/Correspondents/CorrespondentClient.cs @@ -0,0 +1,57 @@ +// Copyright 2022 Valters Melnalksnis +// Licensed under the Apache License 2.0. +// See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Json; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +using VMelnalksnis.PaperlessDotNet.Serialization; + +namespace VMelnalksnis.PaperlessDotNet.Correspondents; + +/// +public sealed class CorrespondentClient : ICorrespondentClient +{ + private readonly HttpClient _httpClient; + private readonly PaperlessJsonSerializerContext _context; + + /// Initializes a new instance of the class. + /// Http client configured for making requests to the Paperless API. + /// Paperless specific instance of . + public CorrespondentClient(HttpClient httpClient, PaperlessJsonSerializerOptions serializerOptions) + { + _httpClient = httpClient; + _context = serializerOptions.Context; + } + + /// + public IAsyncEnumerable GetAll(CancellationToken cancellationToken = default) + { + return _httpClient.GetPaginated( + "/api/correspondents/", + _context.PaginatedListCorrespondent, + cancellationToken); + } + + /// + public IAsyncEnumerable GetAll(int pageSize, CancellationToken cancellationToken = default) + { + return _httpClient.GetPaginated( + $"/api/correspondents/?page_size={pageSize}", + _context.PaginatedListCorrespondent, + cancellationToken); + } + + /// + public Task Get(int id, CancellationToken cancellationToken = default) + { + return _httpClient.GetFromJsonAsync( + $"/api/correspondents/{id}/", + _context.Correspondent, + cancellationToken); + } +} diff --git a/source/VMelnalksnis.PaperlessDotNet/Correspondents/ICorrespondentClient.cs b/source/VMelnalksnis.PaperlessDotNet/Correspondents/ICorrespondentClient.cs new file mode 100644 index 0000000..b19b4ba --- /dev/null +++ b/source/VMelnalksnis.PaperlessDotNet/Correspondents/ICorrespondentClient.cs @@ -0,0 +1,30 @@ +// Copyright 2022 Valters Melnalksnis +// Licensed under the Apache License 2.0. +// See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace VMelnalksnis.PaperlessDotNet.Correspondents; + +/// Paperless API client for working with correspondents. +public interface ICorrespondentClient +{ + /// Gets all correspondents. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A enumerable which will asynchronously iterate over all available pages of correspondents. + IAsyncEnumerable GetAll(CancellationToken cancellationToken = default); + + /// Gets all correspondents. + /// The number of correspondents to get in a single request. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A enumerable which will asynchronously iterate over all available pages of correspondents. + IAsyncEnumerable GetAll(int pageSize, CancellationToken cancellationToken = default); + + /// Gets the correspondent with the specified id. + /// The id of the correspondent to get. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// The correspondent with the specified id if it exists; otherwise . + Task Get(int id, CancellationToken cancellationToken = default); +} diff --git a/source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs b/source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs index 44c500b..50fa6ee 100644 --- a/source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs +++ b/source/VMelnalksnis.PaperlessDotNet/Documents/DocumentClient.cs @@ -31,18 +31,27 @@ public DocumentClient(HttpClient httpClient, PaperlessJsonSerializerOptions seri /// public IAsyncEnumerable GetAll(CancellationToken cancellationToken = default) { - return _httpClient.GetPaginated("/api/documents/", _context.PaginatedListDocument, cancellationToken); + return _httpClient.GetPaginated( + "/api/documents/", + _context.PaginatedListDocument, + cancellationToken); } /// public IAsyncEnumerable GetAll(int pageSize, CancellationToken cancellationToken = default) { - return _httpClient.GetPaginated($"/api/documents/?page_size={pageSize}", _context.PaginatedListDocument, cancellationToken); + return _httpClient.GetPaginated( + $"/api/documents/?page_size={pageSize}", + _context.PaginatedListDocument, + cancellationToken); } /// public Task Get(int id, CancellationToken cancellationToken = default) { - return _httpClient.GetFromJsonAsync($"/api/documents/{id}/", _context.Document, cancellationToken); + return _httpClient.GetFromJsonAsync( + $"/api/documents/{id}/", + _context.Document, + cancellationToken); } } diff --git a/source/VMelnalksnis.PaperlessDotNet/IPaperlessClient.cs b/source/VMelnalksnis.PaperlessDotNet/IPaperlessClient.cs index 9255f70..32efcfd 100644 --- a/source/VMelnalksnis.PaperlessDotNet/IPaperlessClient.cs +++ b/source/VMelnalksnis.PaperlessDotNet/IPaperlessClient.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License 2.0. // See LICENSE file in the project root for full license information. +using VMelnalksnis.PaperlessDotNet.Correspondents; using VMelnalksnis.PaperlessDotNet.Documents; namespace VMelnalksnis.PaperlessDotNet; @@ -9,6 +10,9 @@ namespace VMelnalksnis.PaperlessDotNet; /// All available Paperless APIs. public interface IPaperlessClient { + /// Gets the documents API client. + ICorrespondentClient Correspondents { get; } + /// Gets the documents API client. IDocumentClient Documents { get; } } diff --git a/source/VMelnalksnis.PaperlessDotNet/PaperlessClient.cs b/source/VMelnalksnis.PaperlessDotNet/PaperlessClient.cs index 6caf1d0..2593433 100644 --- a/source/VMelnalksnis.PaperlessDotNet/PaperlessClient.cs +++ b/source/VMelnalksnis.PaperlessDotNet/PaperlessClient.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License 2.0. // See LICENSE file in the project root for full license information. +using VMelnalksnis.PaperlessDotNet.Correspondents; using VMelnalksnis.PaperlessDotNet.Documents; namespace VMelnalksnis.PaperlessDotNet; @@ -10,12 +11,17 @@ namespace VMelnalksnis.PaperlessDotNet; public sealed class PaperlessClient : IPaperlessClient { /// Initializes a new instance of the class. + /// Correspondents API client. /// Documents API client. - public PaperlessClient(IDocumentClient documents) + public PaperlessClient(ICorrespondentClient correspondents, IDocumentClient documents) { + Correspondents = correspondents; Documents = documents; } + /// + public ICorrespondentClient Correspondents { get; } + /// public IDocumentClient Documents { get; } } diff --git a/source/VMelnalksnis.PaperlessDotNet/Serialization/PaperlessJsonSerializerContext.cs b/source/VMelnalksnis.PaperlessDotNet/Serialization/PaperlessJsonSerializerContext.cs index b22d92e..c5ea1af 100644 --- a/source/VMelnalksnis.PaperlessDotNet/Serialization/PaperlessJsonSerializerContext.cs +++ b/source/VMelnalksnis.PaperlessDotNet/Serialization/PaperlessJsonSerializerContext.cs @@ -4,12 +4,15 @@ using System.Text.Json.Serialization; +using VMelnalksnis.PaperlessDotNet.Correspondents; using VMelnalksnis.PaperlessDotNet.Documents; namespace VMelnalksnis.PaperlessDotNet.Serialization; /// [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] +[JsonSerializable(typeof(PaginatedList))] +[JsonSerializable(typeof(Correspondent))] [JsonSerializable(typeof(PaginatedList))] [JsonSerializable(typeof(Document))] internal partial class PaperlessJsonSerializerContext : JsonSerializerContext diff --git a/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Correspondents/CorrespondentClientTests.cs b/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Correspondents/CorrespondentClientTests.cs new file mode 100644 index 0000000..b6ca4a4 --- /dev/null +++ b/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Correspondents/CorrespondentClientTests.cs @@ -0,0 +1,43 @@ +// Copyright 2022 Valters Melnalksnis +// Licensed under the Apache License 2.0. +// See LICENSE file in the project root for full license information. + +using System.Linq; +using System.Threading.Tasks; + +using Xunit.Abstractions; + +namespace VMelnalksnis.PaperlessDotNet.Tests.Integration.Correspondents; + +public sealed class CorrespondentClientTests : IClassFixture +{ + private readonly IPaperlessClient _paperlessClient; + + public CorrespondentClientTests(ITestOutputHelper testOutputHelper, ServiceProviderFixture serviceProviderFixture) + { + _paperlessClient = serviceProviderFixture.GetPaperlessClient(testOutputHelper); + } + + [Fact(Skip = "Requires a running Paperless instance")] + public async Task GetAll_ShouldReturnExpected() + { + var correspondents = await _paperlessClient.Correspondents.GetAll().ToListAsync(); + + correspondents.Should().HaveCount(37); + + var expectedCorrespondent = correspondents.First(); + + var correspondent = await _paperlessClient.Correspondents.Get(expectedCorrespondent.Id); + + correspondent.Should().BeEquivalentTo(expectedCorrespondent); + } + + [Fact(Skip = "Requires a running Paperless instance")] + public async Task GetAll_PageSizeShouldNotChangeResult() + { + var correspondents = await _paperlessClient.Correspondents.GetAll().ToListAsync(); + var pageSizeCorrespondents = await _paperlessClient.Correspondents.GetAll(1).ToListAsync(); + + correspondents.Should().BeEquivalentTo(pageSizeCorrespondents); + } +} diff --git a/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Documents/DocumentClientTests.cs b/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Documents/DocumentClientTests.cs index 6024d2f..cfaafd0 100644 --- a/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Documents/DocumentClientTests.cs +++ b/tests/VMelnalksnis.PaperlessDotNet.Tests.Integration/Documents/DocumentClientTests.cs @@ -18,9 +18,6 @@ public DocumentClientTests(ITestOutputHelper testOutputHelper, ServiceProviderFi _paperlessClient = serviceProviderFixture.GetPaperlessClient(testOutputHelper); } - [Fact] - public void Pass() => Assert.True(true); - [Fact(Skip = "Requires a running Paperless instance")] public async Task GetAll_ShouldReturnExpected() { @@ -34,4 +31,13 @@ public async Task GetAll_ShouldReturnExpected() document.Should().BeEquivalentTo(expectedDocument); } + + [Fact(Skip = "Requires a running Paperless instance")] + public async Task GetAll_PageSizeShouldNotChangeResult() + { + var documents = await _paperlessClient.Documents.GetAll().ToListAsync(); + var pageSizeDocuments = await _paperlessClient.Documents.GetAll(1).ToListAsync(); + + documents.Should().BeEquivalentTo(pageSizeDocuments); + } }