Skip to content

Commit e2cf14c

Browse files
authored
Merge pull request #44 from GarageGroup/feature/use-dataverse-db
Feature/use dataverse db
2 parents f2cbad7 + 0a49a14 commit e2cf14c

File tree

75 files changed

+1044
-1579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1044
-1579
lines changed
Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
using GarageGroup.Infra;
1+
using System;
2+
using System.Text;
3+
using GarageGroup.Infra;
24
using Microsoft.Azure.Functions.Worker;
5+
using Microsoft.Data.SqlClient;
6+
using Microsoft.Extensions.Configuration;
37
using Microsoft.Extensions.DependencyInjection;
48
using PrimeFuncPack;
59

@@ -9,12 +13,36 @@ partial class Application
913
{
1014
internal static void Configure(IFunctionsWorkerApplicationBuilder builder)
1115
=>
12-
builder.Services.RegisterDataverseApi();
16+
builder.Services.RegisterDataverseApi().RegisterSqlApi();
1317

1418
private static IServiceCollection RegisterDataverseApi(this IServiceCollection services)
1519
=>
1620
UseHttpMessageHandlerStandard("DataverseApi")
1721
.UseDataverseApiClient(DataverseSectionName)
1822
.ToRegistrar(services)
1923
.RegisterScoped();
24+
25+
private static IServiceCollection RegisterSqlApi(this IServiceCollection services)
26+
=>
27+
MicrosoftDbProvider.Configure(ResolveDataverseDbProviderOption)
28+
.UseSqlApi()
29+
.ToRegistrar(services)
30+
.RegisterScoped();
31+
32+
private static MicrosoftDbProviderOption ResolveDataverseDbProviderOption(IServiceProvider serviceProvider)
33+
{
34+
var configuration = serviceProvider.GetConfiguration();
35+
var option = configuration.GetDataverseApiClientAuthOption(DataverseSectionName);
36+
37+
var connectionStringBuilder = new StringBuilder()
38+
.Append("Server=").Append(new Uri(option.ServiceUrl).Host).Append(",5558;")
39+
.Append("Initial Catalog=").Append(configuration[$"{DataverseSectionName}:EnvironmentId"]).Append(';')
40+
.Append("Authentication=ActiveDirectoryServicePrincipal;")
41+
.Append("User ID=").Append(option.AuthClientId).Append(';')
42+
.Append("Password=").Append(option.AuthClientSecret).Append(';');
43+
44+
return new(
45+
connectionString: connectionStringBuilder.ToString(),
46+
retryOption: configuration.GetSection($"{DataverseSectionName}:DatabaseRetryPolicy").Get<SqlRetryLogicOption>());
47+
}
2048
}

src/app/AzureFunc/Applicaton/Applicaton.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,17 @@ private static Dependency<ICrmProjectApi> UseCrmProjectApi()
2525
=>
2626
Dependency.From(
2727
ServiceProviderServiceExtensions.GetRequiredService<IDataverseApiClient>,
28-
ResolveProjectApiOption)
28+
ServiceProviderServiceExtensions.GetRequiredService<ISqlApi>)
2929
.UseCrmProjectApi();
3030

3131
private static Dependency<ICrmTimesheetApi> UseCrmTimesheetApi()
3232
=>
3333
Dependency.From(
3434
ServiceProviderServiceExtensions.GetRequiredService<IDataverseApiClient>,
35+
ServiceProviderServiceExtensions.GetRequiredService<ISqlApi>,
3536
ResolveTimesheetApiOption)
3637
.UseCrmTimesheetApi();
3738

38-
private static CrmProjectApiOption ResolveProjectApiOption(IServiceProvider serviceProvider)
39-
=>
40-
serviceProvider.GetConfiguration().GetRequiredSection("CrmProjectApi").Get<CrmProjectApiOption>();
41-
4239
private static CrmTimesheetApiOption ResolveTimesheetApiOption(IServiceProvider serviceProvider)
4340
{
4441
var section = serviceProvider.GetConfiguration().GetRequiredSection("CrmTimesheetApi:ChannelCodes");

src/app/AzureFunc/AzureFunc.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
<PackageReference Include="GarageGroup.Infra.Dataverse.Api" Version="3.12.0" />
3939
<PackageReference Include="GarageGroup.Infra.Dataverse.DataverseUser.Api" Version="1.3.0" />
4040
<PackageReference Include="GarageGroup.Infra.Http.Polly" Version="1.1.1" />
41+
<PackageReference Include="GarageGroup.Infra.Sql.Api" Version="2.1.0" />
42+
<PackageReference Include="GarageGroup.Infra.Sql.Api.Provider.Microsoft" Version="2.1.0" />
4143
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.11.0" OutputItemType="Analyzer" />
4244
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
4345
<PackageReference Include="PrimeFuncPack.DependencyRegistry" Version="2.0.2" />

src/app/AzureFunc/appsettings.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,19 @@
1212
"BotStorageContainerTtlHours": 24,
1313
"MaxDegreeOfParallelism": 2
1414
},
15-
"CrmProjectApi": {
16-
"LastProjectItemsCount": 90,
17-
"LastProjectDaysCount": 30
15+
"Dataverse": {
16+
"ServiceUrl": "",
17+
"AuthTenantId": "",
18+
"AuthClientId": "",
19+
"AuthClientSecret": "",
20+
"EnvironmentId": "",
21+
"DatabaseRetryPolicy": {
22+
"NumberOfTries": 5,
23+
"DeltaTime": "00:00:01",
24+
"MinTimeInterval": "00:00:01",
25+
"MaxTimeInterval": "00:00:30",
26+
"TransientErrors": []
27+
}
1828
},
1929
"CrmTimesheetApi": {
2030
"ChannelCodes": {

src/endpoint/Timesheet.Create/FlowStep/Step.AwaitDescription.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ private static ValueTask<FlatArray<string>> GetTagsAsync(
8484
static state => new TimesheetTagSetGetIn(
8585
userId: state.UserId,
8686
projectId: state.ProjectId,
87-
minDate: GetDateUtc(-DescriptionTagDays)))
87+
minDate: state.Date.AddDays(-DescriptionTagDays),
88+
maxDate: state.Date))
8889
.PipeValue(
8990
crmTimesheetApi.GetTagSetAsync)
9091
.OnFailure(

src/endpoint/Timesheet.Create/FlowStep/Step.AwaitProject.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ private static ValueTask<LookupValueSetOption> GetLastProjectsAsync(
3131
.Pipe(
3232
static flowState => new LastProjectSetGetIn(
3333
userId: flowState.UserId,
34-
top: MaxProjectsCount))
34+
top: MaxProjectsCount,
35+
minDate: GetDateUtc(-ProjectDays)))
3536
.PipeValue(
3637
crmProjectApi.GetLastAsync)
3738
.Fold(

src/endpoint/Timesheet.Create/FlowStep/Step.CreateTimesheet.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ private static ValueTask<ChatFlowJump<TimesheetCreateFlowState>> CreateTimesheet
2424
flowState => new TimesheetCreateIn(
2525
userId: flowState.UserId,
2626
date: flowState.Date,
27-
projectId: flowState.ProjectId,
28-
projectType: flowState.ProjectType,
27+
project: new(
28+
id: flowState.ProjectId,
29+
type: flowState.ProjectType,
30+
displayName: flowState.ProjectName),
2931
duration: flowState.ValueHours,
3032
description: flowState.Description,
3133
channel: context.GetChannel()))

src/endpoint/Timesheet.Create/FlowStep/TimesheetCreateFlowStep.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal static partial class TimesheetCreateFlowStep
1818

1919
private const int DescriptionTagDays = 30;
2020

21+
private const int ProjectDays = 30;
22+
2123
private const string DatePlaceholder = "дд.мм.гг";
2224

2325
private const string DefaultProjectMessage = "Нужно выбрать проект. Введите часть названия для поиска";

src/service/CrmProject/Api/Api.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616

1717
<ItemGroup>
1818
<PackageReference Include="EarlyFuncPack.Core.AsyncPipeline" Version="0.3.0" />
19-
<PackageReference Include="GarageGroup.Infra.Dataverse.Api.Abstractions.EntitySetGet" Version="3.8.2" />
2019
<PackageReference Include="GarageGroup.Infra.Dataverse.Api.Abstractions.Impersonate" Version="2.1.1" />
2120
<PackageReference Include="GarageGroup.Infra.Dataverse.Api.Abstractions.Search" Version="3.8.2" />
22-
<PackageReference Include="GarageGroup.Infra.Dataverse.Api.Filter" Version="0.1.1" />
21+
<PackageReference Include="GarageGroup.Infra.Sql.Api.Abstractions.QueryEntitySet" Version="2.0.0" />
22+
<PackageReference Include="GarageGroup.Infra.Sql.Api.Core.DbRequest" Version="2.1.0" />
2323
<PackageReference Include="PrimeFuncPack.Core.Optional" Version="2.1.0" />
2424
<PackageReference Include="PrimeFuncPack.Dependency.Core" Version="2.0.2" />
25+
<PackageReference Include="PrimeFuncPack.Primitives.Pipeline" Version="2.0.2" />
2526
</ItemGroup>
2627

2728
</Project>
Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,47 @@
11
using System;
2-
using System.Linq;
32
using System.Threading;
43
using System.Threading.Tasks;
54
using GarageGroup.Infra;
65

76
namespace GarageGroup.Internal.Timesheet;
87

9-
partial class CrmProjectApi<TDataverseApi>
8+
partial class CrmProjectApi
109
{
1110
public ValueTask<Result<LastProjectSetGetOut, Failure<ProjectSetGetFailureCode>>> GetLastAsync(
1211
LastProjectSetGetIn input, CancellationToken cancellationToken)
1312
=>
1413
AsyncPipeline.Pipe(
1514
input, cancellationToken)
1615
.Pipe(
17-
@in => new DataverseEntitySetGetIn(
18-
entityPluralName: LastTimesheetItemJson.EntityPluralName,
19-
selectFields: LastTimesheetItemJson.SelectedFields,
20-
expandFields: LastTimesheetItemJson.ExpandedFields,
21-
orderBy: LastTimesheetItemJson.OrderFields,
22-
filter: BuildFilter(@in),
23-
top: option.LastProjectItemsCount))
16+
static @in => DbTimesheetProject.QueryAll with
17+
{
18+
Top = @in.Top,
19+
Filter = new DbCombinedFilter(DbLogicalOperator.And)
20+
{
21+
Filters = new(
22+
DbTimesheetProject.BuildOwnerFilter(@in.UserId),
23+
DbTimesheetProject.BuildMinDateFilter(@in.MinDate),
24+
AllowedProjectTypeSetFilter)
25+
},
26+
Orders = DbTimesheetProject.DefaultOrders
27+
})
2428
.PipeValue(
25-
dataverseApi.Impersonate(input.UserId).GetEntitySetAsync<LastTimesheetItemJson>)
29+
sqlApi.QueryEntitySetOrFailureAsync<DbTimesheetProject>)
2630
.Map(
27-
success => new LastProjectSetGetOut
31+
static success => new LastProjectSetGetOut
2832
{
29-
Projects = GetProjects(success.Value, input.Top)
33+
Projects = success.Map(MapProject)
3034
},
31-
static failure => failure.MapFailureCode(MapFailureCode));
32-
33-
private string BuildFilter(LastProjectSetGetIn input)
34-
{
35-
var today = todayProvider.GetToday();
36-
var maxDate = today.AddDays(1);
35+
static failure => failure.MapFailureCode(GetUnknownFailureCode));
3736

38-
DateOnly? minDate = option.LastProjectDaysCount switch
39-
{
40-
not null => today.AddDays(option.LastProjectDaysCount.Value * -1),
41-
_ => null
42-
};
43-
44-
return LastTimesheetItemJson.BuildFilter(input.UserId, maxDate, minDate);
45-
}
37+
private static ProjectSetGetItem MapProject(DbTimesheetProject dbTimesheetProject)
38+
=>
39+
new(
40+
id: dbTimesheetProject.ProjectId,
41+
name: dbTimesheetProject.Subject.OrNullIfEmpty() ?? dbTimesheetProject.ProjectName,
42+
type: (TimesheetProjectType)dbTimesheetProject.ProjectTypeCode);
4643

47-
private static FlatArray<ProjectSetGetItem> GetProjects(
48-
FlatArray<LastTimesheetItemJson> itemsJson, int? top)
44+
private static ProjectSetGetFailureCode GetUnknownFailureCode(Unit _)
4945
=>
50-
itemsJson.AsEnumerable()
51-
.Select(
52-
static item => item.GetProjectType())
53-
.NotNull()
54-
.GroupBy(
55-
static type => type.Id)
56-
.Select(
57-
static item => item.First())
58-
.Select(
59-
MapProjectItem)
60-
.TakeTop(
61-
top)
62-
.ToFlatArray();
46+
ProjectSetGetFailureCode.Unknown;
6347
}

0 commit comments

Comments
 (0)