Skip to content

Commit 494d817

Browse files
committed
TaxFileService added
1 parent d729c53 commit 494d817

File tree

8 files changed

+175
-111
lines changed

8 files changed

+175
-111
lines changed

Abstractions/IFiscalApiClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ public interface IFiscalApiClient
66
IPersonService Persons { get; }
77
IProductService Products { get; }
88
IApiKeyService ApiKeys { get; }
9+
10+
ITaxFileService TaxFiles { get; }
911
ICatalogService Catalogs { get; }
1012
}
1113
}

Abstractions/IPersonService.cs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,8 @@
1-
using System.Collections.Generic;
2-
using System.Threading.Tasks;
3-
using Fiscalapi.Common;
4-
using Fiscalapi.Models;
1+
using Fiscalapi.Models;
52

63
namespace Fiscalapi.Abstractions
74
{
85
public interface IPersonService : IFiscalApiService<Person>
96
{
10-
// Add tax file
11-
12-
// POST /api/v4/users/{userId}/taxfiles
13-
Task<ApiResponse<TaxFile>> AddTaxFileAsync(TaxFile taxFile);
14-
15-
16-
// GET /api/v4/users/{userId}/taxfiles/{id}
17-
Task<ApiResponse<TaxFile>> GetTaxFileAsync(string userId, string id);
18-
19-
20-
// DELETE /api/v4/users/{userId}/taxfiles/{id}
21-
Task<ApiResponse<bool>> DeleteTaxFileAsync(string userId, string id);
22-
23-
// GET /api/v4/users/{userId}/taxfiles/last
24-
Task<ApiResponse<List<TaxFile>>> GetLatestTaxFilesAsync(string userId);
25-
267
}
278
}

Abstractions/ITaxFileService.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Fiscalapi.Common;
2+
using Fiscalapi.Models;
3+
using System.Collections.Generic;
4+
using System.Threading.Tasks;
5+
6+
namespace Fiscalapi.Abstractions
7+
{
8+
/// <summary>
9+
/// Servicio para gestionar los certificados CSD de emisores y receptores
10+
/// </summary>
11+
public interface ITaxFileService : IFiscalApiService<TaxFile>
12+
{
13+
/// <summary>
14+
/// Obtiene el último par de ids de certificados válidos y vigente de una persona. Es decir sus certificados por defecto (ids)
15+
/// </summary>
16+
/// <param name="personId">Id de la persona dueña de los certificados</param>
17+
/// <returns>Lista con un par de certificados, pero sin con tenido, solo sus Ids.</returns>
18+
Task<ApiResponse<List<TaxFile>>> GetDefaultReferencesAsync(string personId);
19+
20+
21+
/// <summary>
22+
/// Obtiene el último par de certificados válidos y vigente de una persona. Es decir sus certificados por defecto
23+
/// </summary>
24+
/// <param name="personId">Id de la persona dueña de los certificados</param>
25+
/// <returns>Lista con un par de certificados</returns>
26+
Task<ApiResponse<List<TaxFile>>> GetDefaultValuesAsync(string personId);
27+
}
28+
}

Http/FiscalApiHttpClient.cs

Lines changed: 94 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,54 @@ public async Task<ApiResponse<T>> PatchAsync<T>(string endpoint, object payload)
4747
public async Task<ApiResponse<bool>> DeleteAsync(string endpoint)
4848
=> await SendRequestAsync<bool>(HttpMethod.Delete, endpoint);
4949

50-
private async Task<ApiResponse<T>> SendRequestAsync<T>(
51-
HttpMethod method,
52-
string endpoint,
53-
object content = null
54-
)
50+
//private async Task<ApiResponse<T>> SendRequestAsync<T>(
51+
// HttpMethod method,
52+
// string endpoint,
53+
// object content = null
54+
//)
55+
//{
56+
// var request = new HttpRequestMessage(method, endpoint);
57+
58+
// if (content != null)
59+
// {
60+
// var json = JsonConvert.SerializeObject(content, _jsonSettings);
61+
// request.Content = new StringContent(json, Encoding.UTF8, "application/json");
62+
// }
63+
64+
// var response = await _httpClient.SendAsync(request);
65+
// var responseContent = await response.Content.ReadAsStringAsync();
66+
67+
// return response.IsSuccessStatusCode
68+
// ? JsonConvert.DeserializeObject<ApiResponse<T>>(responseContent, _jsonSettings)
69+
// : HandleFailureAsync<T>(responseContent);
70+
//}
71+
72+
//private ApiResponse<T> HandleFailureAsync<T>(string responseContent)
73+
//{
74+
// var failureResponse =
75+
// JsonConvert.DeserializeObject<ApiResponse<List<ValidationFailure>>>(responseContent, _jsonSettings);
76+
77+
// var failures = failureResponse.Data;
78+
79+
// var friendlyErrorMessage = "";
80+
// if (failures != null && failures.Count > 0)
81+
// {
82+
// friendlyErrorMessage = string.Join("; ",
83+
// failures.Select(x => $"{x.PropertyName}: {x.ErrorMessage}"));
84+
// }
85+
86+
// return new ApiResponse<T>
87+
// {
88+
// Succeeded = false,
89+
// HttpStatusCode = failureResponse.HttpStatusCode,
90+
// Message = failureResponse.Message,
91+
// Details = !string.IsNullOrEmpty(friendlyErrorMessage)
92+
// ? friendlyErrorMessage
93+
// : failureResponse.Details,
94+
// Data = default
95+
// };
96+
//}
97+
public async Task<ApiResponse<T>> SendRequestAsync<T>(HttpMethod method, string endpoint, object content = null)
5598
{
5699
var request = new HttpRequestMessage(method, endpoint);
57100

@@ -66,33 +109,58 @@ private async Task<ApiResponse<T>> SendRequestAsync<T>(
66109

67110
return response.IsSuccessStatusCode
68111
? JsonConvert.DeserializeObject<ApiResponse<T>>(responseContent, _jsonSettings)
69-
: HandleFailureAsync<T>(responseContent);
112+
: HandleFailureResponse<T>(responseContent, (int)response.StatusCode);
70113
}
71114

72-
private ApiResponse<T> HandleFailureAsync<T>(string responseContent)
115+
private ApiResponse<T> HandleFailureResponse<T>(string responseContent, int statusCode)
73116
{
74-
var failureResponse =
75-
JsonConvert.DeserializeObject<ApiResponse<List<ValidationFailure>>>(responseContent, _jsonSettings);
76-
77-
var failures = failureResponse.Data;
78-
79-
var friendlyErrorMessage = "";
80-
if (failures != null && failures.Count > 0)
117+
try
81118
{
82-
friendlyErrorMessage = string.Join("; ",
83-
failures.Select(x => $"{x.PropertyName}: {x.ErrorMessage}"));
119+
// First try to deserialize as a generic response
120+
var failureResponse = JsonConvert.DeserializeObject<ApiResponse<object>>(responseContent, _jsonSettings);
121+
122+
// If status is 400, try to deserialize ValidationFailures
123+
if (statusCode == 400)
124+
{
125+
var validationResponse = JsonConvert.DeserializeObject<ApiResponse<List<ValidationFailure>>>(responseContent, _jsonSettings);
126+
var failures = validationResponse?.Data;
127+
128+
var validationErrors = failures != null && failures.Count > 0
129+
? string.Join("; ", failures.Select(x => $"{x.PropertyName}: {x.ErrorMessage}"))
130+
: null;
131+
132+
return new ApiResponse<T>
133+
{
134+
Succeeded = false,
135+
HttpStatusCode = statusCode,
136+
Message = validationResponse?.Message,
137+
Details = validationErrors ?? validationResponse?.Details,
138+
Data = default
139+
};
140+
}
141+
142+
// For other error codes (401, 403, 404, 500, etc.)
143+
return new ApiResponse<T>
144+
{
145+
Succeeded = false,
146+
HttpStatusCode = statusCode,
147+
Message = failureResponse?.Message,
148+
Details = failureResponse?.Details,
149+
Data = default
150+
};
84151
}
85-
86-
return new ApiResponse<T>
152+
catch (JsonException)
87153
{
88-
Succeeded = false,
89-
HttpStatusCode = failureResponse.HttpStatusCode,
90-
Message = failureResponse.Message,
91-
Details = !string.IsNullOrEmpty(friendlyErrorMessage)
92-
? friendlyErrorMessage
93-
: failureResponse.Details,
94-
Data = default
95-
};
154+
// If we can't deserialize the response, create a generic error response
155+
return new ApiResponse<T>
156+
{
157+
Succeeded = false,
158+
HttpStatusCode = statusCode,
159+
Message = "Error processing server response",
160+
Details = responseContent,
161+
Data = default
162+
};
163+
}
96164
}
97165
}
98166
}

Models/Invoice.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using Newtonsoft.Json;
22
using System;
33
using System.Collections.Generic;
4-
using FiscalApi;
54
using Fiscalapi.Common;
65

76
namespace Fiscalapi.Models
@@ -85,12 +84,12 @@ public class GlobalInformation
8584
{
8685
public string PeriodicityCode { get; set; }
8786
public string MonthCode { get; set; }
88-
public decimal? Year { get; set; }
87+
public int Year { get; set; }
8988
}
9089

9190
public class Addendum
9291
{
93-
// Add properties as needed
92+
public string Any { get; set; }
9493
}
9594

9695
public class InvoiceItem : BaseDto

Services/FiscalApiClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class FiscalApiClient : IFiscalApiClient
1313
public IPersonService Persons { get; }
1414
public IApiKeyService ApiKeys { get; }
1515
public ICatalogService Catalogs { get; }
16+
public ITaxFileService TaxFiles { get; }
1617

1718

1819
private FiscalApiClient(FiscalApiOptions settings)
@@ -27,6 +28,7 @@ private FiscalApiClient(FiscalApiOptions settings)
2728
Persons = new PersonService(httpClient, apiVersion);
2829
ApiKeys = new ApiKeyService(httpClient, apiVersion);
2930
Catalogs = new CatalogService(httpClient, apiVersion);
31+
TaxFiles = new TaxFileService(httpClient, apiVersion);
3032
}
3133

3234
public static IFiscalApiClient Create(FiscalApiOptions settings)

Services/PersonService.cs

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
using System.Collections.Generic;
2-
using System.Threading.Tasks;
3-
using Fiscalapi.Abstractions;
4-
using Fiscalapi.Common;
1+
using Fiscalapi.Abstractions;
52
using Fiscalapi.Http;
63
using Fiscalapi.Models;
74

@@ -10,65 +7,8 @@ namespace Fiscalapi.Services
107
public class PersonService : BaseFiscalApiService<Person>, IPersonService
118
{
129
public PersonService(IFiscalApiHttpClient httpClient, string apiVersion)
13-
: base(httpClient, "users", apiVersion)
10+
: base(httpClient, "people", apiVersion)
1411
{
1512
}
16-
17-
/// <summary>
18-
/// Agrega un archivo certificado o llave privada a una persona.
19-
/// </summary>
20-
/// <param name="taxFile"></param>
21-
/// <returns></returns>
22-
public Task<ApiResponse<TaxFile>> AddTaxFileAsync(TaxFile taxFile)
23-
{
24-
// POST /api/v4/users/{userId}/taxfiles
25-
var path = $"{taxFile.PersonId}/taxfiles";
26-
var endpoint = BuildEndpoint(path);
27-
return HttpClient.PostAsync<TaxFile>(endpoint, taxFile);
28-
}
29-
30-
31-
/// <summary>
32-
/// Obtiene un archivo certificado o llave privada de una persona.
33-
/// </summary>
34-
/// <param name="userId"></param>
35-
/// <param name="id"></param>
36-
/// <returns></returns>
37-
public Task<ApiResponse<TaxFile>> GetTaxFileAsync(string userId, string id)
38-
{
39-
// GET /api/v4/users/{userId}/taxfiles/{id}
40-
var path = $"{userId}/taxfiles/{id}";
41-
var endpoint = BuildEndpoint(path);
42-
return HttpClient.GetAsync<TaxFile>(endpoint);
43-
}
44-
45-
46-
/// <summary>
47-
/// Elimina un archivo certificado o llave privada de una persona.
48-
/// </summary>
49-
/// <param name="userId"></param>
50-
/// <param name="id"></param>
51-
/// <returns></returns>
52-
public Task<ApiResponse<bool>> DeleteTaxFileAsync(string userId, string id)
53-
{
54-
// DELETE /api/v4/users/{userId}/taxfiles/{id}
55-
var path = $"{userId}/taxfiles/{id}";
56-
var endpoint = BuildEndpoint(path);
57-
return HttpClient.DeleteAsync(endpoint);
58-
}
59-
60-
61-
/// <summary>
62-
/// Obtiene los últimos archivos certificados o llaves privadas válidos de una persona.
63-
/// </summary>
64-
/// <param name="userId"></param>
65-
/// <returns></returns>
66-
public Task<ApiResponse<List<TaxFile>>> GetLatestTaxFilesAsync(string userId)
67-
{
68-
// GET /api/v4/users/{userId}/taxfiles/last
69-
var path = $"{userId}/taxfiles/last";
70-
var endpoint = BuildEndpoint(path);
71-
return HttpClient.GetAsync<List<TaxFile>>(endpoint);
72-
}
7313
}
7414
}

Services/TaxFileService.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Fiscalapi.Abstractions;
2+
using Fiscalapi.Models;
3+
using System.Collections.Generic;
4+
using System.Threading.Tasks;
5+
using Fiscalapi.Common;
6+
using Fiscalapi.Http;
7+
8+
namespace Fiscalapi.Services
9+
{
10+
public class TaxFileService : BaseFiscalApiService<TaxFile>, ITaxFileService
11+
{
12+
public TaxFileService(IFiscalApiHttpClient httpClient, string apiVersion)
13+
: base(httpClient, "tax-files", apiVersion)
14+
{
15+
}
16+
17+
18+
/// <summary>
19+
/// Obtiene el último par de ids de certificados válidos y vigente de una persona. Es decir sus certificados por defecto (ids)
20+
/// </summary>
21+
/// <param name="personId">Id de la persona dueña de los certificados</param>
22+
/// <returns>Lista con un par de certificados, pero sin con tenido, solo sus Ids.</returns>
23+
public Task<ApiResponse<List<TaxFile>>> GetDefaultReferencesAsync(string personId)
24+
{
25+
// GET /api/v4/tax-files/{personId}/default-references
26+
var path = $"{personId}/default-references";
27+
var endpoint = BuildEndpoint(path);
28+
return HttpClient.GetAsync<List<TaxFile>>(endpoint);
29+
}
30+
31+
/// <summary>
32+
/// Obtiene el último par de certificados válidos y vigente de una persona. Es decir sus certificados por defecto
33+
/// </summary>
34+
/// <param name="personId">Id de la persona dueña de los certificados</param>
35+
/// <returns>Lista con un par de certificados</returns>
36+
public Task<ApiResponse<List<TaxFile>>> GetDefaultValuesAsync(string personId)
37+
{
38+
//GET /api/v4/tax-files/{personId}/default-values
39+
var path = $"{personId}/default-values";
40+
var endpoint = BuildEndpoint(path);
41+
return HttpClient.GetAsync<List<TaxFile>>(endpoint);
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)