Skip to content

Commit 7c35b41

Browse files
refactor: move merchant projection into model factory
Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com>
1 parent 8f2b292 commit 7c35b41

3 files changed

Lines changed: 46 additions & 31 deletions

File tree

EstateReportingAPI.BusinessLogic/DatabaseModels.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,8 @@ internal sealed class MerchantContactData {
2929
public string? EmailAddress { get; init; }
3030
public string? PhoneNumber { get; init; }
3131
}
32+
33+
internal sealed class MerchantWithAddressData {
34+
public required TransactionProcessor.Database.Entities.Merchant Merchant { get; init; }
35+
public required TransactionProcessor.Database.Entities.MerchantAddress MerchantAddress { get; init; }
36+
}

EstateReportingAPI.BusinessLogic/ModelFactory.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,24 @@ internal static Merchant ConvertFrom(MerchantData merchant,
2626
ContactPhone = merchant.ContactInfo.PhoneNumber
2727
};
2828
}
29+
30+
internal static Merchant ConvertFrom(MerchantWithAddressData merchant,
31+
decimal balance) {
32+
return new Merchant {
33+
Balance = balance,
34+
CreatedDateTime = merchant.Merchant.CreatedDateTime,
35+
Name = merchant.Merchant.Name,
36+
Region = merchant.MerchantAddress.Region,
37+
Reference = merchant.Merchant.Reference,
38+
PostCode = merchant.MerchantAddress.PostalCode,
39+
SettlementSchedule = merchant.Merchant.SettlementSchedule,
40+
MerchantId = merchant.Merchant.MerchantId,
41+
AddressId = merchant.MerchantAddress.AddressId,
42+
AddressLine1 = merchant.MerchantAddress.AddressLine1,
43+
AddressLine2 = merchant.MerchantAddress.AddressLine2,
44+
Town = merchant.MerchantAddress.Town,
45+
Country = merchant.MerchantAddress.Country,
46+
MerchantReportingId = merchant.Merchant.MerchantReportingId
47+
};
48+
}
2949
}

EstateReportingAPI.BusinessLogic/ReportingManager.cs

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,12 @@ public async Task<Result<List<Merchant>>> GetMerchants(MerchantQueries.GetMercha
953953
if (balanceQueryResults.IsFailed)
954954
return ResultHelpers.CreateFailure(balanceQueryResults);
955955

956-
return Result.Success(BuildMerchantResponse(merchants, balanceQueryResults.Data));
956+
Dictionary<Guid, decimal> balanceLookup = BuildMerchantBalanceLookup(balanceQueryResults.Data);
957+
List<Merchant> response = merchants.Select(merchant =>
958+
ModelFactory.ConvertFrom(merchant, GetMerchantBalance(balanceLookup, merchant.Merchant.MerchantId)))
959+
.ToList();
960+
961+
return Result.Success(response);
957962
}
958963

959964
public async Task<Result<Merchant>> GetMerchant(MerchantQueries.GetMerchantQuery request, CancellationToken cancellationToken) {
@@ -1014,7 +1019,7 @@ private static IQueryable<MerchantWithAddressData> BuildMerchantWithAddressQuery
10141019
.GroupJoin(context.MerchantAddresses,
10151020
m => m.MerchantId,
10161021
a => a.MerchantId,
1017-
(m, addresses) => new MerchantWithAddressData { Merchant = m, Address = addresses.First() });
1022+
(m, addresses) => new MerchantWithAddressData { Merchant = m, MerchantAddress = addresses.First() });
10181023
}
10191024

10201025
private static IQueryable<MerchantWithAddressData> ApplyMerchantFilters(IQueryable<MerchantWithAddressData> query,
@@ -1029,44 +1034,34 @@ private static IQueryable<MerchantWithAddressData> ApplyMerchantFilters(IQueryab
10291034
query = query.Where(m => m.Merchant.SettlementSchedule == queryOptions.SettlementSchedule);
10301035

10311036
if (String.IsNullOrEmpty(queryOptions.Region) == false)
1032-
query = query.Where(m => m.Address.Region.Contains(queryOptions.Region));
1037+
query = query.Where(m => m.MerchantAddress.Region.Contains(queryOptions.Region));
10331038

10341039
if (String.IsNullOrEmpty(queryOptions.PostCode) == false)
1035-
query = query.Where(m => m.Address.PostalCode == queryOptions.PostCode);
1040+
query = query.Where(m => m.MerchantAddress.PostalCode == queryOptions.PostCode);
10361041

10371042
return query;
10381043
}
10391044

1040-
private static List<Merchant> BuildMerchantResponse(List<MerchantWithAddressData> merchants,
1041-
List<MerchantBalanceProjectionState> balances) {
1045+
private static Dictionary<Guid, decimal> BuildMerchantBalanceLookup(List<MerchantBalanceProjectionState> balances) {
10421046
Dictionary<Guid, decimal> balanceLookup = new();
10431047
foreach (var balance in balances) {
10441048
if (balanceLookup.TryAdd(balance.MerchantId, balance.Balance) == false)
1045-
throw new InvalidOperationException("Sequence contains more than one matching element");
1049+
throw new InvalidOperationException($"Duplicate balance entry found for merchant {balance.MerchantId}");
10461050
}
10471051

1048-
return merchants.Select(merchant => new Merchant {
1049-
Balance = balanceLookup.TryGetValue(merchant.Merchant.MerchantId, out var balance)
1050-
? balance
1051-
: throw new InvalidOperationException("Sequence contains no matching element"),
1052-
CreatedDateTime = merchant.Merchant.CreatedDateTime,
1053-
Name = merchant.Merchant.Name,
1054-
Region = merchant.Address.Region,
1055-
Reference = merchant.Merchant.Reference,
1056-
PostCode = merchant.Address.PostalCode,
1057-
SettlementSchedule = merchant.Merchant.SettlementSchedule,
1058-
MerchantId = merchant.Merchant.MerchantId,
1059-
AddressId = merchant.Address.AddressId,
1060-
AddressLine1 = merchant.Address.AddressLine1,
1061-
AddressLine2 = merchant.Address.AddressLine2,
1062-
Town = merchant.Address.Town,
1063-
Country = merchant.Address.Country,
1064-
MerchantReportingId = merchant.Merchant.MerchantReportingId
1065-
}).ToList();
1052+
return balanceLookup;
1053+
}
1054+
1055+
private static decimal GetMerchantBalance(Dictionary<Guid, decimal> balanceLookup,
1056+
Guid merchantId) {
1057+
if (balanceLookup.TryGetValue(merchantId, out var balance))
1058+
return balance;
1059+
1060+
throw new InvalidOperationException($"No balance entry found for merchant {merchantId}");
10661061
}
10671062

10681063
public async Task<Result<List<MerchantOperator>>> GetMerchantOperators(MerchantQueries.GetMerchantOperatorsQuery request,
1069-
CancellationToken cancellationToken) {
1064+
CancellationToken cancellationToken) {
10701065
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
10711066
await using EstateManagementContext context = resolvedContext.Context;
10721067

@@ -1441,11 +1436,6 @@ private sealed class MerchantTransactionGroupProjection {
14411436
public int DeclinedCount { get; init; }
14421437
}
14431438

1444-
private sealed class MerchantWithAddressData {
1445-
public TransactionProcessor.Database.Entities.Merchant Merchant { get; init; }
1446-
public MerchantAddress Address { get; init; }
1447-
}
1448-
14491439
private sealed class MerchantTransactionFinalProjection {
14501440
public Guid MerchantId { get; init; }
14511441
public int MerchantReportingId { get; init; }

0 commit comments

Comments
 (0)