Skip to content

Commit 8d41c5c

Browse files
Merge branch 'main' into task/#530_workflow_tweaks
2 parents aeb8484 + e4696cb commit 8d41c5c

18 files changed

Lines changed: 367 additions & 2843 deletions

File tree

.github/workflows/pushtomaster.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ jobs:
6767

6868
- name: Publish Windows Images to Docker Hub
6969
run: |
70-
docker build . --file EstateReportingAPI/Dockerfilewindows --tag stuartferguson/estatereportingapi:master
70+
docker build . --file EstateReportingAPI/Dockerfilewindows --tag stuartferguson/estatereportingapiwindoes:master
7171
docker login --username=${{ secrets.DOCKER_USERNAME }} --password=${{ secrets.DOCKER_PASSWORD }}
72-
docker push stuartferguson/estatereportingapi:master
72+
docker push stuartferguson/estatereportingapiwindoes:master

EstateReportingAPI.BusinessLogic/EstateReportingAPI.BusinessLogic.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<PackageReference Include="Microsoft.EntityFrameworkCore.DynamicLinq" Version="10.7.1" />
1212
<PackageReference Include="Shared" Version="2026.3.1" />
1313
<PackageReference Include="Shared.Results" Version="2026.3.1" />
14-
<PackageReference Include="TransactionProcessor.Database" Version="2026.3.1" />
14+
<PackageReference Include="TransactionProcessor.Database" Version="2026.4.2-build346" />
1515
</ItemGroup>
1616

1717
<ItemGroup>

EstateReportingAPI.BusinessLogic/ModelFactory.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
namespace EstateReportingAPI.BusinessLogic;
22

3+
using TransactionProcessor.Database.Entities;
34
using Merchant = EstateReportingAPI.Models.Merchant;
45

56
internal static class ModelFactory {
67
internal static Merchant ConvertFrom(MerchantData merchant,
7-
decimal balance) {
8+
decimal balance,
9+
List<MerchantOpeningHours> openingHours) {
810
return new Merchant {
911
Balance = balance,
1012
CreatedDateTime = merchant.CreatedDateTime,
@@ -23,7 +25,8 @@ internal static Merchant ConvertFrom(MerchantData merchant,
2325
ContactId = merchant.ContactInfo.ContactId,
2426
ContactName = merchant.ContactInfo.Name,
2527
ContactEmail = merchant.ContactInfo.EmailAddress,
26-
ContactPhone = merchant.ContactInfo.PhoneNumber
28+
ContactPhone = merchant.ContactInfo.PhoneNumber,
29+
2730
};
2831
}
2932

EstateReportingAPI.BusinessLogic/Queries/MerchantQueries.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public record GetMerchantQuery(Guid EstateId, Guid MerchantId) : IRequest<Result
1414
public record GetMerchantOperatorsQuery(Guid EstateId, Guid MerchantId) : IRequest<Result<List<MerchantOperator>>>;
1515
public record GetMerchantContractsQuery(Guid EstateId, Guid MerchantId) : IRequest<Result<List<MerchantContract>>>;
1616
public record GetMerchantDevicesQuery(Guid EstateId, Guid MerchantId) : IRequest<Result<List<MerchantDevice>>>;
17-
17+
public record GetMerchantOpeningHoursQuery(Guid EstateId, Guid MerchantId) : IRequest<Result<List<MerchantOpeningHour>>>;
18+
public record GetMerchantScheduleQuery(Guid EstateId, Guid MerchantId, Int32 Year) : IRequest<Result<MerchantScheduleResponse>>;
1819
public record MerchantQueryOptions(String Name,String Reference,Int32? SettlementSchedule,String Region, String PostCode);
1920
}

EstateReportingAPI.BusinessLogic/ReportingManager.cs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public interface IReportingManager
4343
Task<Result<List<MerchantOperator>>> GetMerchantOperators(MerchantQueries.GetMerchantOperatorsQuery request, CancellationToken cancellationToken);
4444
Task<Result<List<MerchantContract>>> GetMerchantContracts(MerchantQueries.GetMerchantContractsQuery request, CancellationToken cancellationToken);
4545
Task<Result<List<MerchantDevice>>> GetMerchantDevices(MerchantQueries.GetMerchantDevicesQuery request, CancellationToken cancellationToken);
46+
Task<Result<List<MerchantOpeningHour>>> GetMerchantOpeningHours(MerchantQueries.GetMerchantOpeningHoursQuery request, CancellationToken cancellationToken);
4647
Task<Result<Operator>> GetOperator(OperatorQueries.GetOperatorQuery request, CancellationToken cancellationToken);
4748
Task<Result<TransactionDetailReportResponse>> GetTransactionDetailReport(TransactionQueries.TransactionDetailReportQuery request,
4849
CancellationToken cancellationToken);
@@ -58,6 +59,9 @@ Task<Result<List<TodaysSalesByHour>>> GetTodaysSalesByHour(TransactionQueries.To
5859
Task<Result<TodaysSettlement>> GetTodaysSettlement(SettlementQueries.TodaysSettlementQuery request,
5960
CancellationToken cancellationToken);
6061
#endregion
62+
63+
Task<Result<MerchantScheduleResponse>> GetMerchantSchedule(MerchantQueries.GetMerchantScheduleQuery request,
64+
CancellationToken cancellationToken);
6165
}
6266

6367
public class ReportingManager : IReportingManager {
@@ -625,6 +629,47 @@ public async Task<Result<List<Operator>>> GetOperators(OperatorQueries.GetOperat
625629
return Result.Success(operators);
626630
}
627631

632+
public async Task<Result<List<MerchantOpeningHour>>> GetMerchantOpeningHours(MerchantQueries.GetMerchantOpeningHoursQuery request,
633+
CancellationToken cancellationToken) {
634+
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
635+
await using EstateManagementContext context = resolvedContext.Context;
636+
637+
var openingHoursQuery = (from mo in context.MerchantOpeningHours
638+
where mo.MerchantId == request.MerchantId
639+
select new {
640+
SundayOpen = mo.SundayOpening,
641+
SundayClose = mo.SundayClosing,
642+
MondayOpen = mo.MondayOpening,
643+
MondayClose = mo.MondayClosing,
644+
TuesdayOpen = mo.TuesdayOpening,
645+
TuesdayClose = mo.TuesdayClosing,
646+
WednesdayOpen = mo.WednesdayOpening,
647+
WednesdayClose = mo.WednesdayClosing,
648+
ThursdayOpen = mo.ThursdayOpening,
649+
ThursdayClose = mo.ThursdayClosing,
650+
FridayOpen = mo.FridayOpening,
651+
FridayClose = mo.FridayClosing,
652+
SaturdayOpen = mo.SaturdayOpening,
653+
SaturdayClose = mo.SaturdayClosing,
654+
});
655+
656+
var openingHoursResult = await ExecuteQuerySafeSingleOrDefault(openingHoursQuery, cancellationToken, "Error retrieving merchant opening hours");
657+
658+
if (openingHoursResult.IsFailed)
659+
return ResultHelpers.CreateFailure(openingHoursResult);
660+
661+
List<MerchantOpeningHour> openingHours = new List<MerchantOpeningHour>();
662+
openingHours.Add(new MerchantOpeningHour {OpeningTime = openingHoursResult.Data.SundayOpen, ClosingTime = openingHoursResult.Data.SundayClose, DayOfWeek = DayOfWeek.Sunday, MerchantId = request.MerchantId});
663+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.MondayOpen, ClosingTime = openingHoursResult.Data.MondayClose, DayOfWeek = DayOfWeek.Monday, MerchantId = request.MerchantId });
664+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.TuesdayOpen, ClosingTime = openingHoursResult.Data.TuesdayClose, DayOfWeek = DayOfWeek.Tuesday, MerchantId = request.MerchantId });
665+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.WednesdayOpen, ClosingTime = openingHoursResult.Data.WednesdayClose, DayOfWeek = DayOfWeek.Wednesday, MerchantId = request.MerchantId });
666+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.ThursdayOpen, ClosingTime = openingHoursResult.Data.ThursdayClose, DayOfWeek = DayOfWeek.Thursday, MerchantId = request.MerchantId });
667+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.FridayOpen, ClosingTime = openingHoursResult.Data.FridayClose, DayOfWeek = DayOfWeek.Friday, MerchantId = request.MerchantId });
668+
openingHours.Add(new MerchantOpeningHour { OpeningTime = openingHoursResult.Data.SaturdayOpen, ClosingTime = openingHoursResult.Data.SaturdayClose, DayOfWeek = DayOfWeek.Saturday, MerchantId = request.MerchantId });
669+
670+
return Result.Success(openingHours);
671+
}
672+
628673
public async Task<Result<Operator>> GetOperator(OperatorQueries.GetOperatorQuery request,
629674
CancellationToken cancellationToken) {
630675
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
@@ -966,16 +1011,19 @@ public async Task<Result<Merchant>> GetMerchant(MerchantQueries.GetMerchantQuery
9661011
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
9671012
await using EstateManagementContext context = resolvedContext.Context;
9681013

969-
var merchantQuery = BuildMerchantQuery(context, request.MerchantId);
970-
var merchantQueryResult = await ExecuteQuerySafeSingleOrDefault(merchantQuery, cancellationToken, "Error getting merchant");
1014+
IQueryable<MerchantData> merchantQuery = BuildMerchantQuery(context, request.MerchantId);
1015+
Result<MerchantData> merchantQueryResult = await ExecuteQuerySafeSingleOrDefault(merchantQuery, cancellationToken, "Error getting merchant");
9711016
if (merchantQueryResult.IsFailed) {
9721017
return ResultHelpers.CreateFailure(merchantQueryResult);
9731018
}
9741019

975-
var merchantStateQueryResult = await ExecuteQuerySafeSingleOrDefault(context.MerchantBalanceProjectionState.Where(ms => ms.MerchantId == request.MerchantId), cancellationToken, "Error getting merchant state");
1020+
Result<List<MerchantOpeningHours>> openingHoursQueryResult = await ExecuteQuerySafeToList(context.MerchantOpeningHours.Where(m => m.MerchantId == request.MerchantId), cancellationToken, "Error getting merchant opening hours");
1021+
if (openingHoursQueryResult.IsFailed) return ResultHelpers.CreateFailure(openingHoursQueryResult);
1022+
1023+
Result<MerchantBalanceProjectionState> merchantStateQueryResult = await ExecuteQuerySafeSingleOrDefault(context.MerchantBalanceProjectionState.Where(ms => ms.MerchantId == request.MerchantId), cancellationToken, "Error getting merchant state");
9761024
if (merchantStateQueryResult.IsFailed) return ResultHelpers.CreateFailure(merchantStateQueryResult);
9771025

978-
return Result.Success(ModelFactory.ConvertFrom(merchantQueryResult.Data, merchantStateQueryResult.Data.Balance));
1026+
return Result.Success(ModelFactory.ConvertFrom(merchantQueryResult.Data, merchantStateQueryResult.Data.Balance, openingHoursQueryResult.Data));
9791027
}
9801028

9811029
private static IQueryable<MerchantData> BuildMerchantQuery(EstateManagementContext context,
@@ -1303,8 +1351,47 @@ public async Task<Result<TodaysSettlement>> GetTodaysSettlement(SettlementQuerie
13031351
return response;
13041352
}
13051353

1306-
private async Task<DatabaseProjections.SettlementGroupProjection> GetSettlementSummary(IQueryable<DatabaseProjections.ComparisonSettlementTransactionProjection> query,
1307-
CancellationToken cancellationToken) {
1354+
public async Task<Result<MerchantScheduleResponse>> GetMerchantSchedule(MerchantQueries.GetMerchantScheduleQuery request,
1355+
CancellationToken cancellationToken) {
1356+
using ResolvedDbContext<EstateManagementContext>? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString());
1357+
await using EstateManagementContext context = resolvedContext.Context;
1358+
1359+
var merchantScheduleQuery = from s in context.MerchantSchedules
1360+
join d in context.MerchantScheduleMonths on s.MerchantScheduleId equals d.MerchantScheduleId
1361+
where s.MerchantId == request.MerchantId && s.Year == request.Year
1362+
select new {
1363+
s.MerchantId,
1364+
s.MerchantScheduleId,
1365+
s.Year,
1366+
d.Month,
1367+
d.ClosedDays
1368+
};
1369+
1370+
var merchantScheduleQueryResult = await ExecuteQuerySafeToList(merchantScheduleQuery, cancellationToken, "Error getting merchant schedule");
1371+
if (merchantScheduleQueryResult.IsFailed)
1372+
return ResultHelpers.CreateFailure(merchantScheduleQueryResult);
1373+
1374+
MerchantScheduleResponse response = new MerchantScheduleResponse();
1375+
foreach (var item in merchantScheduleQueryResult.Data) {
1376+
1377+
List<Int32> closedDaysList = item.ClosedDays
1378+
.Split(',', StringSplitOptions.RemoveEmptyEntries)
1379+
.Select(s => int.TryParse(s, out var n) ? n : (int?)null)
1380+
.Where(n => n.HasValue)
1381+
.Select(n => n.Value)
1382+
.ToList();
1383+
1384+
MerchantScheduleMonthResponse? monthSchedule = new() { ClosedDays = closedDaysList, Month = item.Month };
1385+
1386+
response.Months.Add(monthSchedule);
1387+
}
1388+
response.Year = request.Year;
1389+
1390+
return response;
1391+
}
1392+
1393+
private async Task<DatabaseProjections.SettlementGroupProjection> GetSettlementSummary(IQueryable<DatabaseProjections.ComparisonSettlementTransactionProjection> query,
1394+
CancellationToken cancellationToken) {
13081395
// Get the settleed fees summary
13091396
DatabaseProjections.SettlementGroupProjection summary = await BuildSettlementSummaryQuery(query).SingleOrDefaultAsync(cancellationToken);
13101397

EstateReportingAPI.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ public class MerchantRequestHandler : IRequestHandler<MerchantQueries.GetRecentM
1111
IRequestHandler<MerchantQueries.GetMerchantQuery, Result<Merchant>>,
1212
IRequestHandler<MerchantQueries.GetMerchantContractsQuery, Result<List<MerchantContract>>>,
1313
IRequestHandler<MerchantQueries.GetMerchantOperatorsQuery, Result<List<MerchantOperator>>>,
14-
IRequestHandler<MerchantQueries.GetMerchantDevicesQuery, Result<List<MerchantDevice>>>
14+
IRequestHandler<MerchantQueries.GetMerchantDevicesQuery, Result<List<MerchantDevice>>>,
15+
IRequestHandler<MerchantQueries.GetMerchantOpeningHoursQuery, Result<List<MerchantOpeningHour>>>,
16+
IRequestHandler<MerchantQueries.GetMerchantScheduleQuery, Result<MerchantScheduleResponse>>
1517
{
1618
private readonly IReportingManager Manager;
1719
public MerchantRequestHandler(IReportingManager manager)
@@ -53,4 +55,14 @@ public async Task<Result<List<MerchantDevice>>> Handle(MerchantQueries.GetMercha
5355
CancellationToken cancellationToken) {
5456
return await this.Manager.GetMerchantDevices(request, cancellationToken);
5557
}
58+
59+
public async Task<Result<List<MerchantOpeningHour>>> Handle(MerchantQueries.GetMerchantOpeningHoursQuery request,
60+
CancellationToken cancellationToken) {
61+
return await this.Manager.GetMerchantOpeningHours(request, cancellationToken);
62+
}
63+
64+
public async Task<Result<MerchantScheduleResponse>> Handle(MerchantQueries.GetMerchantScheduleQuery request,
65+
CancellationToken cancellationToken) {
66+
return await this.Manager.GetMerchantSchedule(request, cancellationToken);
67+
}
5668
}

EstateReportingAPI.DataTrasferObjects/Merchant.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,21 @@ public class Merchant{
4545
[JsonProperty("contact_phone")]
4646
public String ContactPhone { get; set; }
4747

48-
4948
#endregion
5049
}
5150

51+
public class OpeningHoursResponse
52+
{
53+
[JsonProperty("day_of_week")]
54+
public Int32 DayOfWeek { get; set; }
55+
56+
[JsonProperty("opening")]
57+
public string Opening { get; set; }
58+
59+
[JsonProperty("closing")]
60+
public string Closing { get; set; }
61+
}
62+
5263
public class MerchantOperator
5364
{
5465
[JsonProperty("merchant_id")]
@@ -110,4 +121,34 @@ public class MerchantDevice
110121
[JsonProperty("is_deleted")]
111122
public Boolean IsDeleted { get; set; }
112123
}
124+
125+
public class MerchantOpeningHour
126+
{
127+
[JsonProperty("merchant_id")]
128+
public Guid MerchantId { get; set; }
129+
[JsonProperty("day_of_week")]
130+
public DayOfWeek DayOfWeek { get; set; }
131+
[JsonProperty("opening_time")]
132+
public String OpeningTime { get; set; }
133+
[JsonProperty("closing_time")]
134+
public String ClosingTime { get; set; }
135+
}
136+
137+
public class MerchantScheduleResponse
138+
{
139+
[JsonProperty("year")]
140+
public int Year { get; set; }
141+
142+
[JsonProperty("months")]
143+
public List<MerchantScheduleMonthResponse> Months { get; set; }
144+
}
145+
146+
public class MerchantScheduleMonthResponse
147+
{
148+
[JsonProperty("month")]
149+
public int Month { get; set; }
150+
151+
[JsonProperty("closed_days")]
152+
public List<int> ClosedDays { get; set; }
153+
}
113154
}

0 commit comments

Comments
 (0)