Skip to content

Commit 5840940

Browse files
committed
Merge branch 'release/biz-0.1.82'
2 parents 4c5f974 + a75a960 commit 5840940

24 files changed

+537
-47
lines changed

src/NoFrixion.MoneyMoov/ApiClients/MerchantClient.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public interface IMerchantClient
5656
Task<RestApiResponse<Merchant>> GetMerchantAsync(string userAccessToken, Guid merchantID);
5757

5858
Task<RestApiResponse<Merchant>> UpdateMerchantAsync(string userAccessToken, Guid merchantID, MerchantUpdate merchantUpdate);
59+
60+
Task<RestApiResponse<MerchantPageResponse>> GetChildMerchantsAsync(string userAccessToken, Guid parentMerchantID,
61+
int pageNumber = 1,
62+
int pageSize = 20,
63+
string? search = null,
64+
string? sort = null);
5965
}
6066

6167
public class MerchantClient : IMerchantClient
@@ -365,4 +371,36 @@ public Task<RestApiResponse<Merchant>> UpdateMerchantAsync(string userAccessToke
365371
_ => Task.FromResult(new RestApiResponse<Merchant>(HttpStatusCode.PreconditionFailed, new Uri(url), prob))
366372
};
367373
}
374+
375+
/// <summary>
376+
/// Calls the MoneyMoov Merchant get child merchants endpoint to get a paged list of child merchants.
377+
/// </summary>
378+
/// <param name="userAccessToken">A user-scoped JWT access token.</param>
379+
/// <param name="parentMerchantID">The unique identifier of the parent merchant.</param>
380+
/// <param name="pageNumber">The page number of the result set to retrieve.</param>
381+
/// <param name="pageSize">The number of records to return per page.</param>
382+
/// <param name="search">A search filter to apply to the child merchant list. Typically searches against merchant name or ID.</param>
383+
/// <param name="sort">The sort expression for the result set, e.g., "Name asc".</param>
384+
/// <returns>A paged response containing a list of child merchants if successful.</returns>
385+
public Task<RestApiResponse<MerchantPageResponse>> GetChildMerchantsAsync(string userAccessToken, Guid parentMerchantID,
386+
int pageNumber = 1,
387+
int pageSize = 20,
388+
string? search = null,
389+
string? sort = null)
390+
{
391+
var url = MoneyMoovUrlBuilder.MerchantsApi.ChildMerchantsUrl(_apiClient.GetBaseUri().ToString(),
392+
parentMerchantID,
393+
pageNumber,
394+
pageSize,
395+
search,
396+
sort);
397+
398+
var prob = _apiClient.CheckAccessToken(userAccessToken, nameof(GetMerchantTokenAsync));
399+
400+
return prob switch
401+
{
402+
var p when p.IsEmpty => _apiClient.GetAsync<MerchantPageResponse>(url, userAccessToken),
403+
_ => Task.FromResult(new RestApiResponse<MerchantPageResponse>(HttpStatusCode.PreconditionFailed, new Uri(url), prob))
404+
};
405+
}
368406
}

src/NoFrixion.MoneyMoov/ApiClients/UserInviteClient.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public interface IUserInviteClient
2626

2727
Task<RestApiResponse<UserInvite>> GetUserInviteAsync(string accessToken, Guid userInviteID);
2828

29+
Task<RestApiResponse<UserInvite>> GetUserInviteDetailsAsync(string accessToken, Guid userInviteID);
30+
2931
Task<RestApiResponse<UserInvite>> SendInviteAsync(string userAccessToken, Guid merchantID,
3032
string inviteeEmailAddress,
3133
string inviteRegistrationUrl,
@@ -39,6 +41,8 @@ Task<RestApiResponse<UserInvite>> SendInviteAsync(string userAccessToken, Guid m
3941
Task<RestApiResponse> ResendUserInviteAsync(string accessToken, Guid userInviteID);
4042

4143
Task<RestApiResponse> DeleteUserInviteAsync(string accessToken, Guid inviteID);
44+
45+
Task<RestApiResponse> AuthoriseUserInviteAsync(string strongUserAccessToken, Guid inviteID);
4246
}
4347

4448
public class UserInviteClient : IUserInviteClient
@@ -102,6 +106,25 @@ public Task<RestApiResponse<UserInvite>> GetUserInviteAsync(string accessToken,
102106
};
103107
}
104108

109+
/// <summary>
110+
/// Calls the MoneyMoov Merchant get user invite details endpoint to get a single user invite by ID.
111+
/// </summary>
112+
/// <param name="accessToken">A User scoped JWT access token.</param>
113+
/// <param name="userInviteID">The ID of the user invite to retrieve.</param>
114+
/// <returns>If successful, a user invite object.</returns>
115+
public Task<RestApiResponse<UserInvite>> GetUserInviteDetailsAsync(string accessToken, Guid userInviteID)
116+
{
117+
var url = MoneyMoovUrlBuilder.UserInvitesApi.UserInviteDetailsUrl(_apiClient.GetBaseUri().ToString(), userInviteID);
118+
119+
var prob = _apiClient.CheckAccessToken(accessToken, nameof(GetUserInviteDetailsAsync));
120+
121+
return prob switch
122+
{
123+
var p when p.IsEmpty => _apiClient.GetAsync<UserInvite>(url, accessToken),
124+
_ => Task.FromResult(new RestApiResponse<UserInvite>(HttpStatusCode.PreconditionFailed, new Uri(url), prob))
125+
};
126+
}
127+
105128
/// <summary>
106129
/// Calls the MoneyMoov account endpoint to create and send an email invite to register
107130
/// and join a merchant account.
@@ -192,4 +215,25 @@ public Task<RestApiResponse> DeleteUserInviteAsync(string accessToken, Guid invi
192215
_ => Task.FromResult(new RestApiResponse(HttpStatusCode.PreconditionFailed, new Uri(url), prob))
193216
};
194217
}
218+
219+
/// <summary>
220+
/// Calls the MoneyMoov user invites endpoint to authorise a user invite.
221+
/// </summary>
222+
/// <param name="strongUserAccessToken">The strong user access token acquired to authorise the user invite. Strong
223+
/// tokens can only be acquired from a strong customer authentication flow, are short lived (typically 5 minute expiry)
224+
/// and are specific to the user invite.</param>
225+
/// <param name="inviteID">The ID of the user invite to authorise.</param>
226+
/// <returns>An API response indicating the result of the authorise attempt.</returns>
227+
public Task<RestApiResponse> AuthoriseUserInviteAsync(string strongUserAccessToken, Guid inviteID)
228+
{
229+
var url = MoneyMoovUrlBuilder.UserInvitesApi.AuthoriseUserInviteUrl(_apiClient.GetBaseUri().ToString(), inviteID);
230+
231+
var prob = _apiClient.CheckAccessToken(strongUserAccessToken, nameof(AuthoriseUserInviteAsync));
232+
233+
return prob switch
234+
{
235+
var p when p.IsEmpty => _apiClient.PostAsync(url, strongUserAccessToken),
236+
_ => Task.FromResult(new RestApiResponse(HttpStatusCode.PreconditionFailed, new Uri(url), prob))
237+
};
238+
}
195239
}

src/NoFrixion.MoneyMoov/Enums/ApprovalTypesEnum.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,7 @@ public enum ApproveTypesEnum
3535

3636
Payrun = 8,
3737

38-
MerchantToken = 9
38+
MerchantToken = 9,
39+
40+
UserInvite = 10,
3941
}

src/NoFrixion.MoneyMoov/Enums/AuthorisationType.cs

100644100755
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ public enum AuthorisationType
2222
Rule = 2,
2323
Beneficiary = 3,
2424
Payrun = 4,
25-
MerchantToken = 5
25+
MerchantToken = 5,
26+
UserInvite = 6
2627
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// -----------------------------------------------------------------------------
2+
// Filename: RoleEventTypeEnum.cs
3+
//
4+
// Description: List of the types of events that can occur in a role:
5+
//
6+
// Author(s):
7+
// Axel Granillo ([email protected])
8+
//
9+
// History:
10+
// 17 07 2025 Axel Granillo Created, Remote, Mexico City, Mexico.
11+
//
12+
// License:
13+
// MIT.
14+
// -----------------------------------------------------------------------------
15+
16+
namespace NoFrixion.MoneyMoov.Enums;
17+
18+
/// <summary>
19+
/// Events that can occur in a role.
20+
/// </summary>
21+
public enum RoleEventTypeEnum
22+
{
23+
None = 0,
24+
25+
Created = 1,
26+
27+
Edited = 2,
28+
29+
Archived = 3,
30+
31+
Unarchived = 4,
32+
33+
AssignedToUser = 5,
34+
35+
RemovedFromUser = 6,
36+
37+
UpdatedUserAssignment = 7
38+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//-----------------------------------------------------------------------------
2+
// Filename: UserInviteEventTypeEnum.cs
3+
//
4+
// Description: Enum for the different types of user invite events that can
5+
// occur.
6+
//
7+
// Author(s):
8+
// Aaron Clauson ([email protected])
9+
//
10+
// History:
11+
// 06 Aug 2025 Aaron Clauson Created, Carnesore Point, Wexford, Ireland.
12+
//
13+
// License:
14+
// MIT.
15+
//-----------------------------------------------------------------------------
16+
17+
namespace NoFrixion.MoneyMoov.Enums;
18+
19+
public enum UserInviteEventTypeEnum
20+
{
21+
/// <summary>
22+
/// Something went wrong and the event type is unknown.
23+
/// </summary>
24+
Unknown = 0,
25+
26+
/// <summary>
27+
/// A user invite was authorised by an approver.
28+
/// </summary>
29+
Authorise = 1
30+
}

src/NoFrixion.MoneyMoov/Enums/UserInviteStatusEnum.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,10 @@ public enum UserInviteStatusEnum
3131
/// <summary>
3232
/// User has accepted the invite but the role is pending.
3333
/// </summary>
34-
Accepted = 2
34+
Accepted = 2,
35+
36+
/// <summary>
37+
/// The invite needs to be authorised before being activated.
38+
/// </summary>
39+
AuthorisationRequired = 3,
3540
}

src/NoFrixion.MoneyMoov/Extensions/PaymentRequestEventExtensions.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,43 @@ private static List<PaymentRequestEvent> GetAllCardSaleEvents(
368368
.Where(x => x.EventType == PaymentRequestEventTypesEnum.card_sale)
369369
.ToList() : new List<PaymentRequestEvent>();
370370
}
371+
372+
private static bool IsPispRelatedEvent(this PaymentRequestEvent paymentRequestEvent)
373+
{
374+
return
375+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_initiate ||
376+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_callback ||
377+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_webhook ||
378+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_settle ||
379+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_settle_failure ||
380+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_refund_initiated ||
381+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.pisp_refund_settled;
382+
}
383+
384+
private static bool IsDirectDebitRelatedEvent(this PaymentRequestEvent paymentRequestEvent)
385+
{
386+
return paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.direct_debit_create ||
387+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.direct_debit_failed ||
388+
paymentRequestEvent.EventType == PaymentRequestEventTypesEnum.direct_debit_paid;
389+
}
390+
391+
public static PaymentMethodTypeEnum GetPaymentMethodType(this PaymentRequestEvent paymentRequestEvent)
392+
{
393+
if (paymentRequestEvent.IsCardRelatedEvent())
394+
{
395+
return PaymentMethodTypeEnum.card;
396+
}
397+
398+
if (paymentRequestEvent.IsPispRelatedEvent())
399+
{
400+
return PaymentMethodTypeEnum.pisp;
401+
}
402+
403+
if (paymentRequestEvent.IsDirectDebitRelatedEvent())
404+
{
405+
return PaymentMethodTypeEnum.directDebit;
406+
}
407+
408+
return PaymentMethodTypeEnum.None;
409+
}
371410
}

src/NoFrixion.MoneyMoov/Extensions/PaymentRequestExtensions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ public static List<PaymentRequestPaymentAttempt> GetPaymentAttempts(this IEnumer
3535
paymentAttempts.AddRange(GetPispPaymentAttempts(events));
3636
paymentAttempts.AddRange(GetLightningPaymentAttempts(events));
3737
paymentAttempts.AddRange(GetDirectDebitPaymentAttempts(events));
38+
39+
paymentAttempts.Sort(
40+
(x, y) => y.InitiatedAt.CompareTo(x.InitiatedAt));
3841

3942
return paymentAttempts;
4043
}

src/NoFrixion.MoneyMoov/Models/Account/PaymentAccountMinimal.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,14 @@ public class PaymentAccountMinimal
6666
/// Externally connected account can be used to view account balances and transactions.
6767
/// </summary>
6868
public bool IsConnectedAccount { get; set; }
69+
70+
/// <summary>
71+
/// Total of the payouts that have been submitted for processing.
72+
/// </summary>
73+
public decimal SubmittedPayoutsBalance { get; set; }
74+
75+
/// <summary>
76+
/// The current available balance of the account. Calculated by subtracting any submitted payments from the current balance.
77+
/// </summary>
78+
public decimal AvailableBalance => Balance - SubmittedPayoutsBalance;
6979
}

0 commit comments

Comments
 (0)