Skip to content

Commit

Permalink
Merge branch 'release/ident-1.1.103'
Browse files Browse the repository at this point in the history
  • Loading branch information
sipsorcery committed Jun 24, 2024
2 parents 73b242a + 4726cbe commit ddac4c4
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 69 deletions.
92 changes: 51 additions & 41 deletions src/NoFrixion.MoneyMoov/Mapping/CsvMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,67 +57,77 @@ public static class CsvMapper
csv.Read();
csv.ReadHeader();

while (csv.Read())
if (csv.Context.Parser == null)
{
var result = new CsvMapResult<T>();
result.CsvRow = csv.Context.Parser.RawRecord;
result.Problem = new NoFrixionProblem("Unable to parse the header row as valid csv.");
yield return result;
}
else
{
while (csv.Read())
{
var result = new CsvMapResult<T>();

var record = csv.GetRecord<dynamic>();
result.CsvRow = csv.Context.Parser.RawRecord;

if (record == null)
{
result.Problem = new NoFrixionProblem("Unable to parse the row as valid csv.");
}
else
{
result.CsvMappedRow = (IDictionary<string, object>)record;
var record = csv.GetRecord<dynamic>();

try
if (record == null)
{
foreach (var property in typeof(T).GetProperties())
result.Problem = new NoFrixionProblem("Unable to parse the row as valid csv.");
}
else
{
result.CsvMappedRow = (IDictionary<string, object>)record;

try
{
if (mapping.ContainsKey(property.Name))
foreach (var property in typeof(T).GetProperties())
{
string template = mapping[property.Name];
string formattedValue = template.Substitute((IDictionary<string, object>)record);

if (property.PropertyType == typeof(Guid))
if (mapping.ContainsKey(property.Name))
{
if (Guid.TryParse(formattedValue, out Guid guidValue))
string template = mapping[property.Name];
string formattedValue = template.Substitute((IDictionary<string, object>)record);

if (property.PropertyType == typeof(Guid))
{
property.SetValue(result.Model, guidValue);
if (Guid.TryParse(formattedValue, out Guid guidValue))
{
property.SetValue(result.Model, guidValue);
}
}
}
else if (property.PropertyType.IsEnum)
{
if (!string.IsNullOrEmpty(formattedValue))
else if (property.PropertyType.IsEnum)
{
var enumValue = Enum.Parse(property.PropertyType, formattedValue, true);
property.SetValue(result.Model, enumValue);
if (!string.IsNullOrEmpty(formattedValue))
{
var enumValue = Enum.Parse(property.PropertyType, formattedValue, true);
property.SetValue(result.Model, enumValue);
}
}
}
else if (property.PropertyType == typeof(List<string>))
{
if (!string.IsNullOrEmpty(formattedValue))
else if (property.PropertyType == typeof(List<string>))
{
var stringItems = formattedValue.FromJson<List<string>>();
property.SetValue(result.Model, stringItems);
if (!string.IsNullOrEmpty(formattedValue))
{
var stringItems = formattedValue.FromJson<List<string>>();
property.SetValue(result.Model, stringItems);
}
}
else
{
property.SetValue(result.Model, Convert.ChangeType(formattedValue, property.PropertyType));
}
}
else
{
property.SetValue(result.Model, Convert.ChangeType(formattedValue, property.PropertyType));
}
}
}
catch (Exception excp)
{
result.Problem = new NoFrixionProblem($"Exception mapping csv row to {typeof(T)}. {excp.Message}");
}
}
catch (Exception excp)
{
result.Problem = new NoFrixionProblem($"Exception mapping csv row to {typeof(T)}. {excp.Message}");
}
}

yield return result;
yield return result;
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/NoFrixion.MoneyMoov/Models/Account/AccountIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace NoFrixion.MoneyMoov.Models;

public class AccountIdentifier: IValidatableObject
{
public const int SORT_CODE_LENGTH = 6;

/// <summary>
/// The type of the account identifier.
/// </summary>
Expand Down Expand Up @@ -118,7 +120,7 @@ public string SortCode
{
if (!string.IsNullOrEmpty(value))
{
_sortCode = value.Trim().Replace(" ", string.Empty);
_sortCode = value.Trim().Replace(" ", string.Empty).Replace("-", string.Empty);
}
else
{
Expand Down Expand Up @@ -186,7 +188,7 @@ public string BitcoinAddress
"No identifier.";

public string DisplayScanSummary =>
!string.IsNullOrEmpty(SortCode) && !string.IsNullOrEmpty(AccountNumber) && SortCode.Length == 6
!string.IsNullOrEmpty(SortCode) && !string.IsNullOrEmpty(AccountNumber) && SortCode.Length == SORT_CODE_LENGTH
? $"{SortCode[..2]}-{SortCode.Substring(2, 2)}-{SortCode.Substring(4, 2)} {AccountNumber}"
: "No identifier.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public string SortCode
{
if (!string.IsNullOrEmpty(value))
{
_sortCode = value.Trim().Replace(" ", string.Empty);
_sortCode = value.Trim().Replace(" ", string.Empty).Replace("-", string.Empty);
}
else
{
Expand Down
5 changes: 5 additions & 0 deletions src/NoFrixion.MoneyMoov/Models/Account/PaymentAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,9 @@ public string Summary
/// The date that the external account will expire
/// </summary>
public DateTimeOffset? ExpiryDate { get; set; }

/// <summary>
/// Indicates if the payment account is connected to a Xero bank feed.
/// </summary>
public bool IsXeroBankFeed { get; set; }
}
4 changes: 3 additions & 1 deletion src/NoFrixion.MoneyMoov/Models/Beneficiary/Beneficiary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Newtonsoft.Json;

#nullable disable

namespace NoFrixion.MoneyMoov.Models;

public class Beneficiary : IValidatableObject
Expand All @@ -44,10 +45,11 @@ public class Beneficiary : IValidatableObject
public CurrencyTypeEnum Currency { get; set; }

public Counterparty Destination { get; set; }

/// <summary>
/// The ID of the beneficiary identifier.
/// </summary>
[Obsolete("No longer used.")]
public Guid BeneficiaryIdentifierID { get; set; }

public string ApprovalCallbackUrl { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.ComponentModel.DataAnnotations;

#nullable disable

namespace NoFrixion.MoneyMoov.Models;

public class BeneficiaryCreate : IValidatableObject
Expand Down
5 changes: 5 additions & 0 deletions src/NoFrixion.MoneyMoov/Models/Merchant/Merchant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ public class Merchant
/// </summary>
public bool DisplayQrOnHostedPay { get; set; }

/// <summary>
/// For internal use only.
/// </summary>
public string? ModulrCustomerID { get; set; }

/// <summary>
/// The role of the identity that loaded the merchant record.
/// </summary>
Expand Down
5 changes: 3 additions & 2 deletions src/NoFrixion.MoneyMoov/Models/Payouts/Payout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,13 @@ public Counterparty? DestinationAccount
/// <summary>
/// If the payout destination is a beneficiary this will be the ID of it's identifier.
/// </summary>
[Obsolete("No longer used.")]
public Guid? BeneficiaryIdentifierID { get; set; }

/// <summary>
/// If the payout is using a beneficiary for the destination this is the name of the it.
/// </summary>
[Obsolete("Please use Beneficiary.")]
[Obsolete("Please use Beneificiary.")]
public string? BeneficiaryName { get; set; }

/// <summary>
Expand Down
18 changes: 12 additions & 6 deletions src/NoFrixion.MoneyMoov/Models/Payouts/PayoutsValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ public static class PayoutsValidator
/// and account number (SCAN) payments . Note that length gets calculated after
/// certain non-counted characters have been removed.
/// </summary>
public const int THEIR_REFERENCE_SCAN_MAXIMUM_MODULR_LENGTH = 17;
public const int THEIR_REFERENCE_SCAN_MAXIMUM_MODULR_LENGTH = 18;

/// <summary>
/// The maximum allowed length for the Their Reference field for International Bank Account Number
/// (IBAN) payments . Note that length gets calculated after / certain non-counted characters
/// have been removed.
/// </summary>
public const int THEIR_REFERENCE_IBAN_MAXIMUM_MODULR_LENGTH = 139;
public const int THEIR_REFERENCE_IBAN_MAXIMUM_MODULR_LENGTH = 140;

/// <summary>
/// Maximum length of the Your, or External Reference, field.
Expand Down Expand Up @@ -229,13 +229,19 @@ public static bool ValidateModulrTheirReference(
Regex replaceRegex = new Regex(THEIR_REFERENCE_NON_COUNTED_CHARS_MODULR_REGEX);
var refClean = replaceRegex.Replace(theirReference, "");

if (refClean.Length<THEIR_REFERENCE_MINIMUM_MODULR_LENGTH
|| refClean.Length> maxLength
if (refClean.Length < THEIR_REFERENCE_MINIMUM_MODULR_LENGTH
|| !matchRegex.IsMatch(theirReference))
{
return false;
}

// It's not particularly clear but it seems the non-counted characters are only for the minimum length
// requirement. The maximum length is the total length of the string after irrespective of the characters.
if(theirReference.Length > maxLength)
{
return false;
}

return theirReference.ToCharArray().Distinct().Count() > 1;
}

Expand Down Expand Up @@ -425,7 +431,7 @@ public static string MakeSafeTheirReference(AccountIdentifierType identifierType

if (ValidateTheirReference(theirReference, identifierType, paymentProcessor))
{
return theirReference;
return theirReference.Trim();
}
else
{
Expand All @@ -452,7 +458,7 @@ public static string MakeSafeTheirReference(AccountIdentifierType identifierType
theirReference;
}

return ValidateTheirReference(theirReference, identifierType, paymentProcessor) ? theirReference : fallbackTheirReference;
return ValidateTheirReference(theirReference, identifierType, paymentProcessor) ? theirReference.Trim() : fallbackTheirReference;
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/NoFrixion.MoneyMoov/Models/Payruns/PayrunInvoice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ public class PayrunInvoice : IValidatableObject

[Obsolete("Please use Reference instead.")]
public string? InvoiceNumber { get; set; }

[Required]

public required string Reference { get; set; }

public string? PaymentTerms { get; set; }
Expand Down
10 changes: 5 additions & 5 deletions src/NoFrixion.MoneyMoov/NoFrixion.MoneyMoov.csproj
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyVersion>1.1.284.0</AssemblyVersion>
<FileVersion>1.1.284.0</FileVersion>
<AssemblyVersion>1.1.103.0</AssemblyVersion>
<FileVersion>1.1.103.0</FileVersion>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Ardalis.GuardClauses" Version="4.0.1" />
<PackageReference Include="CsvHelper" Version="32.0.3" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
<PackageReference Include="IdentityModel" Version="7.0.0" />
<PackageReference Include="LanguageExt.Core" Version="4.4.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.6.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.6.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Quartz" Version="3.9.0" />
</ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions src/NoFrixion.MoneyMoov/NoFrixionProblem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public static NoFrixionProblem Empty
/// 501 Not Implemented.
/// etc.
/// </example>
public int Status { get; set; }
public int Status { get; set; } = (int)HttpStatusCode.BadRequest;

/// <summary>
/// A human-readable explanation specific to this occurrence of the problem.
Expand Down Expand Up @@ -233,13 +233,13 @@ public NoFrixionProblem(HttpStatusCode status, string errorDetail)
Detail = errorDetail;
}

public NoFrixionProblem(string errorMessage, int errorCode = 400)
public NoFrixionProblem(string errorMessage, int errorCode = (int)HttpStatusCode.BadRequest)
{
Detail = errorMessage;
Status = errorCode;
}

public NoFrixionProblem(string errorMessage, ValidationResult validationError, int errorCode = 400)
public NoFrixionProblem(string errorMessage, ValidationResult validationError, int errorCode = (int)HttpStatusCode.BadRequest)
{
Detail = errorMessage;
Status= errorCode;
Expand All @@ -250,7 +250,7 @@ public NoFrixionProblem(string errorMessage, ValidationResult validationError, i
}
}

public NoFrixionProblem(string errorMessage, IEnumerable<ValidationResult> validationErrors, int errorCode = 400)
public NoFrixionProblem(string errorMessage, IEnumerable<ValidationResult> validationErrors, int errorCode = (int)HttpStatusCode.BadRequest)
{
Detail = errorMessage;
Status = errorCode;
Expand Down
11 changes: 8 additions & 3 deletions src/NoFrixion.MoneyMoov/RestClient/RestApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
using LanguageExt;
using System.Net;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace NoFrixion.MoneyMoov;

Expand Down Expand Up @@ -220,7 +218,14 @@ private NoFrixionProblem DeserialiseProblem(HttpStatusCode responseStatusCode, s
{
return responseContent.FromJson<NoFrixionProblem>() ?? NoFrixionProblem.Empty;
}
catch (JsonException)
catch (System.Text.Json.JsonException)
{
var problem = new NoFrixionProblem(responseStatusCode, $"API error response was not in the recognised problem format.");
problem.RawError = responseContent;

return problem;
}
catch (Newtonsoft.Json.JsonException)
{
var problem = new NoFrixionProblem(responseStatusCode, $"API error response was not in the recognised problem format.");
problem.RawError = responseContent;
Expand Down
Loading

0 comments on commit ddac4c4

Please sign in to comment.