Skip to content

Commit a6442e1

Browse files
committed
feat(F16): Finish f16 module
1 parent 4830447 commit a6442e1

File tree

17 files changed

+420
-0
lines changed

17 files changed

+420
-0
lines changed

SetupProject.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F14", "Src\Core\F14\F14.csp
5757
EndProject
5858
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F15", "Src\Core\F15\F15.csproj", "{5F6FC9E6-C713-471B-99E8-AACC3994C583}"
5959
EndProject
60+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "F16", "Src\Core\F16\F16.csproj", "{7373234F-7D82-49D3-BBCB-B8CFD84F6389}"
61+
EndProject
6062
Global
6163
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6264
Debug|Any CPU = Debug|Any CPU
@@ -155,6 +157,10 @@ Global
155157
{5F6FC9E6-C713-471B-99E8-AACC3994C583}.Debug|Any CPU.Build.0 = Debug|Any CPU
156158
{5F6FC9E6-C713-471B-99E8-AACC3994C583}.Release|Any CPU.ActiveCfg = Release|Any CPU
157159
{5F6FC9E6-C713-471B-99E8-AACC3994C583}.Release|Any CPU.Build.0 = Release|Any CPU
160+
{7373234F-7D82-49D3-BBCB-B8CFD84F6389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
161+
{7373234F-7D82-49D3-BBCB-B8CFD84F6389}.Debug|Any CPU.Build.0 = Debug|Any CPU
162+
{7373234F-7D82-49D3-BBCB-B8CFD84F6389}.Release|Any CPU.ActiveCfg = Release|Any CPU
163+
{7373234F-7D82-49D3-BBCB-B8CFD84F6389}.Release|Any CPU.Build.0 = Release|Any CPU
158164
EndGlobalSection
159165
GlobalSection(SolutionProperties) = preSolution
160166
HideSolutionNode = FALSE
@@ -186,5 +192,6 @@ Global
186192
{95E410E2-9C9C-4ED3-B927-3E2951197829} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
187193
{C044FCB9-18E7-4EE2-AA37-19E658387971} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
188194
{5F6FC9E6-C713-471B-99E8-AACC3994C583} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
195+
{7373234F-7D82-49D3-BBCB-B8CFD84F6389} = {F7C07F6C-C2ED-4E06-9025-AD33B4BBBB51}
189196
EndGlobalSection
190197
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 F16.Common;
5+
using F16.DataAccess;
6+
using F16.Models;
7+
using FCommon.FeatureService;
8+
9+
namespace F16.BusinessLogic;
10+
11+
public sealed class F16Service : IServiceHandler<F16AppRequestModel, F16AppResponseModel>
12+
{
13+
private readonly Lazy<IF16Repository> _repository;
14+
15+
public F16Service(Lazy<IF16Repository> repository)
16+
{
17+
_repository = repository;
18+
}
19+
20+
public async Task<F16AppResponseModel> ExecuteAsync(
21+
F16AppRequestModel request,
22+
CancellationToken ct
23+
)
24+
{
25+
var doesTaskExist = await _repository.Value.DoesTodoTaskExistAsync(request.TodoTaskId, ct);
26+
if (!doesTaskExist)
27+
{
28+
return F16Constant.DefaultResponse.App.TASK_NOT_FOUND;
29+
}
30+
31+
var isSuccess = await _repository.Value.ModifyIsInMyDayStatusAsync(
32+
request.TodoTaskId,
33+
request.IsInMyDay,
34+
ct
35+
);
36+
if (!isSuccess)
37+
{
38+
return F16Constant.DefaultResponse.App.SERVER_ERROR;
39+
}
40+
41+
return new() { AppCode = F16Constant.AppCode.SUCCESS };
42+
}
43+
}

Src/Core/F16/Common/F16Constant.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using F16.Models;
2+
using F16.Presentation;
3+
using Microsoft.AspNetCore.Http;
4+
5+
namespace F16.Common;
6+
7+
public static class F16Constant
8+
{
9+
public const string ENDPOINT_PATH = "f16";
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 F16AppResponseModel TASK_NOT_FOUND = new()
18+
{
19+
AppCode = AppCode.TASK_NOT_FOUND,
20+
};
21+
22+
public static readonly F16AppResponseModel SERVER_ERROR = new()
23+
{
24+
AppCode = AppCode.SERVER_ERROR,
25+
};
26+
}
27+
28+
public static class Http
29+
{
30+
public static readonly F16Response VALIDATION_FAILED = new()
31+
{
32+
AppCode = (int)AppCode.VALIDATION_FAILED,
33+
HttpCode = StatusCodes.Status400BadRequest,
34+
};
35+
36+
public static readonly F16Response TASK_NOT_FOUND = new()
37+
{
38+
AppCode = (int)AppCode.TASK_NOT_FOUND,
39+
HttpCode = StatusCodes.Status404NotFound,
40+
};
41+
42+
public static readonly F16Response 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: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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 F16.DataAccess;
10+
11+
public sealed class F16Repository : IF16Repository
12+
{
13+
private readonly AppDbContext _appContext;
14+
15+
public F16Repository(AppDbContext context)
16+
{
17+
_appContext = context;
18+
}
19+
20+
public async Task<bool> ModifyIsInMyDayStatusAsync(
21+
long taskId,
22+
bool isInMyDay,
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 => setProp.SetProperty(entity => entity.IsInMyDay, isInMyDay),
44+
ct
45+
);
46+
47+
await dbTransaction.CommitAsync(ct);
48+
}
49+
catch (DbUpdateException)
50+
{
51+
await dbTransaction.RollbackAsync(ct);
52+
53+
dbResult = false;
54+
}
55+
});
56+
57+
return dbResult;
58+
}
59+
60+
public Task<bool> DoesTodoTaskExistAsync(long taskId, CancellationToken ct)
61+
{
62+
return _appContext.Set<TodoTaskEntity>().AnyAsync(entity => entity.Id == taskId, ct);
63+
}
64+
}
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 F16.DataAccess;
5+
6+
public interface IF16Repository
7+
{
8+
Task<bool> DoesTodoTaskExistAsync(long taskId, CancellationToken ct);
9+
10+
Task<bool> ModifyIsInMyDayStatusAsync(long taskId, bool isInMyDay, CancellationToken ct);
11+
}

Src/Core/F16/F16.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/F16/F16Register.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using F16.BusinessLogic;
2+
using F16.DataAccess;
3+
using FACommon.DependencyInjection;
4+
using FluentValidation;
5+
using Microsoft.Extensions.Configuration;
6+
using Microsoft.Extensions.DependencyInjection;
7+
8+
namespace F16;
9+
10+
public sealed class F16Register : IServiceRegister
11+
{
12+
public IServiceCollection Register(IServiceCollection services, IConfiguration configuration)
13+
{
14+
var currentAssembly = typeof(F16Register).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<IF16Repository, F16Repository>()
27+
.MakeScopedLazy<IF16Repository>()
28+
.AddScoped<F16Service>();
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 F16.Common;
4+
using F16.Models;
5+
using F16.Presentation;
6+
using Microsoft.AspNetCore.Http;
7+
8+
namespace F16.Mapper;
9+
10+
public static class F16HttpResponseMapper
11+
{
12+
private static ConcurrentDictionary<
13+
F16Constant.AppCode,
14+
Func<F16AppRequestModel, F16AppResponseModel, F16Response>
15+
> _httpResponseMapper;
16+
17+
private static void Init()
18+
{
19+
if (Equals(_httpResponseMapper, null))
20+
{
21+
_httpResponseMapper = new();
22+
}
23+
24+
_httpResponseMapper.TryAdd(
25+
F16Constant.AppCode.SUCCESS,
26+
(appRequest, appResponse) =>
27+
new()
28+
{
29+
AppCode = (int)F16Constant.AppCode.SUCCESS,
30+
HttpCode = StatusCodes.Status200OK,
31+
}
32+
);
33+
34+
_httpResponseMapper.TryAdd(
35+
F16Constant.AppCode.TASK_NOT_FOUND,
36+
(appRequest, appResponse) => F16Constant.DefaultResponse.Http.TASK_NOT_FOUND
37+
);
38+
39+
_httpResponseMapper.TryAdd(
40+
F16Constant.AppCode.SERVER_ERROR,
41+
(appRequest, appResponse) => F16Constant.DefaultResponse.Http.SERVER_ERROR
42+
);
43+
}
44+
45+
public static F16Response Get(F16AppRequestModel appRequest, F16AppResponseModel 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 F16.Models;
4+
5+
public sealed class F16AppRequestModel : IServiceRequest<F16AppResponseModel>
6+
{
7+
public long TodoTaskId { get; set; }
8+
9+
public bool IsInMyDay { get; set; }
10+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using F16.Common;
2+
using FCommon.FeatureService;
3+
4+
namespace F16.Models;
5+
6+
public sealed class F16AppResponseModel : IServiceResponse
7+
{
8+
public F16Constant.AppCode AppCode { get; set; }
9+
10+
public BodyModel Body { get; set; }
11+
12+
public sealed class BodyModel { }
13+
}

0 commit comments

Comments
 (0)