Skip to content

Commit 5b386c4

Browse files
authored
Merge pull request #58 from Jackpieking/F18
feat(F18): Finish f18 module
2 parents fc0f42e + 8713239 commit 5b386c4

File tree

17 files changed

+421
-0
lines changed

17 files changed

+421
-0
lines changed

SetupProject.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F16", "Src\Core\F16\F16.csp
6161
EndProject
6262
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F17", "Src\Core\F17\F17.csproj", "{A4CC6A27-4EDE-4383-9956-B41A622D34D3}"
6363
EndProject
64+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F18", "Src\Core\F18\F18.csproj", "{53684635-F86C-4635-ABFA-B889CAF9308B}"
65+
EndProject
6466
Global
6567
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6668
Debug|Any CPU = Debug|Any CPU
@@ -167,6 +169,10 @@ Global
167169
{A4CC6A27-4EDE-4383-9956-B41A622D34D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
168170
{A4CC6A27-4EDE-4383-9956-B41A622D34D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
169171
{A4CC6A27-4EDE-4383-9956-B41A622D34D3}.Release|Any CPU.Build.0 = Release|Any CPU
172+
{53684635-F86C-4635-ABFA-B889CAF9308B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
173+
{53684635-F86C-4635-ABFA-B889CAF9308B}.Debug|Any CPU.Build.0 = Debug|Any CPU
174+
{53684635-F86C-4635-ABFA-B889CAF9308B}.Release|Any CPU.ActiveCfg = Release|Any CPU
175+
{53684635-F86C-4635-ABFA-B889CAF9308B}.Release|Any CPU.Build.0 = Release|Any CPU
170176
EndGlobalSection
171177
GlobalSection(SolutionProperties) = preSolution
172178
HideSolutionNode = FALSE
@@ -200,5 +206,6 @@ Global
200206
{5F6FC9E6-C713-471B-99E8-AACC3994C583} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
201207
{7373234F-7D82-49D3-BBCB-B8CFD84F6389} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
202208
{A4CC6A27-4EDE-4383-9956-B41A622D34D3} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
209+
{53684635-F86C-4635-ABFA-B889CAF9308B} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
203210
EndGlobalSection
204211
EndGlobal
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using F18.Common;
5+
using F18.DataAccess;
6+
using F18.Models;
7+
using FCommon.FeatureService;
8+
9+
namespace F18.BusinessLogic;
10+
11+
public sealed class F18Service : IServiceHandler<F18AppRequestModel, F18AppResponseModel>
12+
{
13+
private readonly Lazy<IF18Repository> _repository;
14+
15+
public F18Service(Lazy<IF18Repository> repository)
16+
{
17+
_repository = repository;
18+
}
19+
20+
public async Task<F18AppResponseModel> ExecuteAsync(
21+
F18AppRequestModel request,
22+
CancellationToken ct
23+
)
24+
{
25+
var doesTaskExist = await _repository.Value.DoesTodoTaskExistAsync(request.TodoTaskId, ct);
26+
if (!doesTaskExist)
27+
{
28+
return F18Constant.DefaultResponse.App.TASK_NOT_FOUND;
29+
}
30+
31+
var isSuccess = await _repository.Value.ModifyIsImportantStatusAsync(
32+
request.TodoTaskId,
33+
request.IsImportant,
34+
ct
35+
);
36+
if (!isSuccess)
37+
{
38+
return F18Constant.DefaultResponse.App.SERVER_ERROR;
39+
}
40+
41+
return new() { AppCode = F18Constant.AppCode.SUCCESS };
42+
}
43+
}

Src/Core/F18/Common/F18Constant.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using F18.Models;
2+
using F18.Presentation;
3+
using Microsoft.AspNetCore.Http;
4+
5+
namespace F18.Common;
6+
7+
public static class F18Constant
8+
{
9+
public const string ENDPOINT_PATH = "f18";
10+
11+
public const string REQUEST_ARGUMENT_NAME = "request";
12+
13+
public static class DefaultResponse
14+
{
15+
public static class App
16+
{
17+
public static readonly F18AppResponseModel TASK_NOT_FOUND = new()
18+
{
19+
AppCode = AppCode.TASK_NOT_FOUND,
20+
};
21+
22+
public static readonly F18AppResponseModel SERVER_ERROR = new()
23+
{
24+
AppCode = AppCode.SERVER_ERROR,
25+
};
26+
}
27+
28+
public static class Http
29+
{
30+
public static readonly F18Response VALIDATION_FAILED = new()
31+
{
32+
AppCode = (int)AppCode.VALIDATION_FAILED,
33+
HttpCode = StatusCodes.Status400BadRequest,
34+
};
35+
36+
public static readonly F18Response TASK_NOT_FOUND = new()
37+
{
38+
AppCode = (int)AppCode.TASK_NOT_FOUND,
39+
HttpCode = StatusCodes.Status404NotFound,
40+
};
41+
42+
public static readonly F18Response SERVER_ERROR = new()
43+
{
44+
AppCode = (int)AppCode.SERVER_ERROR,
45+
HttpCode = StatusCodes.Status500InternalServerError,
46+
};
47+
}
48+
}
49+
50+
public enum AppCode
51+
{
52+
SUCCESS = 1,
53+
54+
VALIDATION_FAILED,
55+
56+
TASK_NOT_FOUND,
57+
58+
SERVER_ERROR,
59+
}
60+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System.Data;
2+
using System.Linq;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using FA1.DbContext;
6+
using FA1.Entities;
7+
using Microsoft.EntityFrameworkCore;
8+
9+
namespace F18.DataAccess;
10+
11+
public sealed class F18Repository : IF18Repository
12+
{
13+
private readonly AppDbContext _appContext;
14+
15+
public F18Repository(AppDbContext context)
16+
{
17+
_appContext = context;
18+
}
19+
20+
public async Task<bool> ModifyIsImportantStatusAsync(
21+
long taskId,
22+
bool isImportant,
23+
CancellationToken ct
24+
)
25+
{
26+
var dbResult = true;
27+
28+
await _appContext
29+
.Database.CreateExecutionStrategy()
30+
.ExecuteAsync(async () =>
31+
{
32+
await using var dbTransaction = await _appContext.Database.BeginTransactionAsync(
33+
IsolationLevel.ReadCommitted,
34+
ct
35+
);
36+
37+
try
38+
{
39+
await _appContext
40+
.Set<TodoTaskEntity>()
41+
.Where(task => task.Id == taskId)
42+
.ExecuteUpdateAsync(
43+
setProp =>
44+
setProp.SetProperty(entity => entity.IsImportant, isImportant),
45+
ct
46+
);
47+
48+
await dbTransaction.CommitAsync(ct);
49+
}
50+
catch (DbUpdateException)
51+
{
52+
await dbTransaction.RollbackAsync(ct);
53+
54+
dbResult = false;
55+
}
56+
});
57+
58+
return dbResult;
59+
}
60+
61+
public Task<bool> DoesTodoTaskExistAsync(long taskId, CancellationToken ct)
62+
{
63+
return _appContext.Set<TodoTaskEntity>().AnyAsync(entity => entity.Id == taskId, ct);
64+
}
65+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace F18.DataAccess;
5+
6+
public interface IF18Repository
7+
{
8+
Task<bool> DoesTodoTaskExistAsync(long taskId, CancellationToken ct);
9+
10+
Task<bool> ModifyIsImportantStatusAsync(long taskId, bool isImportant, CancellationToken ct);
11+
}

Src/Core/F18/F18.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>

Src/Core/F18/F18Register.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using F18.BusinessLogic;
2+
using F18.DataAccess;
3+
using FACommon.DependencyInjection;
4+
using FluentValidation;
5+
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.DependencyInjection;
7+
8+
namespace F18;
9+
10+
public sealed class F18Register : IServiceRegister
11+
{
12+
public IServiceCollection Register(IServiceCollection services, IConfiguration configuration)
13+
{
14+
var currentAssembly = typeof(F18Register).Assembly;
15+
16+
#region Filters
17+
services.RegisterFiltersFromAssembly(currentAssembly);
18+
#endregion
19+
20+
#region Validation
21+
services.AddValidatorsFromAssembly(currentAssembly, ServiceLifetime.Singleton);
22+
#endregion
23+
24+
#region Core
25+
services
26+
.AddScoped<IF18Repository, F18Repository>()
27+
.MakeScopedLazy<IF18Repository>()
28+
.AddScoped<F18Service>();
29+
#endregion
30+
31+
return services;
32+
}
33+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using F18.Common;
4+
using F18.Models;
5+
using F18.Presentation;
6+
using Microsoft.AspNetCore.Http;
7+
8+
namespace F17.Mapper;
9+
10+
public static class F17HttpResponseMapper
11+
{
12+
private static ConcurrentDictionary<
13+
F18Constant.AppCode,
14+
Func<F18AppRequestModel, F18AppResponseModel, F18Response>
15+
> _httpResponseMapper;
16+
17+
private static void Init()
18+
{
19+
if (Equals(_httpResponseMapper, null))
20+
{
21+
_httpResponseMapper = new();
22+
}
23+
24+
_httpResponseMapper.TryAdd(
25+
F18Constant.AppCode.SUCCESS,
26+
(appRequest, appResponse) =>
27+
new()
28+
{
29+
AppCode = (int)F18Constant.AppCode.SUCCESS,
30+
HttpCode = StatusCodes.Status200OK,
31+
}
32+
);
33+
34+
_httpResponseMapper.TryAdd(
35+
F18Constant.AppCode.TASK_NOT_FOUND,
36+
(appRequest, appResponse) => F18Constant.DefaultResponse.Http.TASK_NOT_FOUND
37+
);
38+
39+
_httpResponseMapper.TryAdd(
40+
F18Constant.AppCode.SERVER_ERROR,
41+
(appRequest, appResponse) => F18Constant.DefaultResponse.Http.SERVER_ERROR
42+
);
43+
}
44+
45+
public static F18Response Get(F18AppRequestModel appRequest, F18AppResponseModel appResponse)
46+
{
47+
Init();
48+
49+
return _httpResponseMapper[appResponse.AppCode](appRequest, appResponse);
50+
}
51+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using FCommon.FeatureService;
2+
3+
namespace F18.Models;
4+
5+
public sealed class F18AppRequestModel : IServiceRequest<F18AppResponseModel>
6+
{
7+
public long TodoTaskId { get; set; }
8+
9+
public bool IsImportant { get; set; }
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using F18.Common;
2+
using FCommon.FeatureService;
3+
4+
namespace F18.Models;
5+
6+
public sealed class F18AppResponseModel : IServiceResponse
7+
{
8+
public F18Constant.AppCode AppCode { get; set; }
9+
10+
public BodyModel Body { get; set; }
11+
12+
public sealed class BodyModel { }
13+
}

0 commit comments

Comments
 (0)