Skip to content

Commit

Permalink
Merge pull request #7 from is-oop-y25/lab-6
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Butenko authored Dec 24, 2022
2 parents 48f9dc6 + 9329d05 commit 3b02413
Show file tree
Hide file tree
Showing 37 changed files with 706 additions and 0 deletions.
27 changes: 27 additions & 0 deletions ApplicationTier/ApplicationTier.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WarningLevel>5</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\.editorconfig" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\DataAccessTier\DataAccessTier.csproj" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions ApplicationTier/DTO/EmployeeDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using DataAccessTier.Models;

namespace ApplicationTier.DTO;

public record EmployeeDto(Guid Id, string Name, IReadOnlyCollection<EmployeeDto> LedEmployees, IReadOnlyCollection<MessageDto> Messages);
5 changes: 5 additions & 0 deletions ApplicationTier/DTO/MessageDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using DataAccessTier.Models;

namespace ApplicationTier.DTO;

public record MessageDto(Guid Id, Guid EmployeeId, string Text, MessageState State, DateTime HandledTime);
5 changes: 5 additions & 0 deletions ApplicationTier/DTO/ReportDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using DataAccessTier.Models;

namespace ApplicationTier.DTO;

public record ReportDto(Guid Id, Guid EmployeeId, DateTime FormedDate, string FullText);
18 changes: 18 additions & 0 deletions ApplicationTier/Extensions/DbSetExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;

namespace ApplicationTier.Extensions;

public static class DbSetExtensions
{
public static async Task<T> GetEntityAsync<T>(this DbSet<T> set, Guid id, CancellationToken cancellationToken)
where T : class
{
T? entity = await set.FindAsync(new object[] { id }, cancellationToken);

if (entity is null)
throw new Exception("shit.................");
/*throw EntityNotFoundException<T>.Create(id);*/

return entity;
}
}
17 changes: 17 additions & 0 deletions ApplicationTier/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using ApplicationTier.Services;
using ApplicationTier.Services.Implementations;
using DataAccessTier.Models;
using Microsoft.Extensions.DependencyInjection;

namespace ApplicationTier.Extensions;

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApplication(this IServiceCollection collection)
{
collection.AddScoped<IEmployee, EmployeeService>();
collection.AddScoped<IMessage, MessageService>();
collection.AddScoped<IReport, ReportService>();
return collection;
}
}
14 changes: 14 additions & 0 deletions ApplicationTier/Mapping/EmployeeMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using ApplicationTier.DTO;
using DataAccessTier.Models;

namespace ApplicationTier.Mapping;

public static class EmployeeMapping
{
public static EmployeeDto AsDto(this Employee employee)
=> new EmployeeDto(
employee.Id,
employee.Name,
employee.LedEmployees.Select(x => x.AsDto()).ToArray(),
employee.Messages.Select(x => x.AsDto()).ToArray());
}
15 changes: 15 additions & 0 deletions ApplicationTier/Mapping/MessageMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using ApplicationTier.DTO;
using DataAccessTier.Models;

namespace ApplicationTier.Mapping;

public static class MessageMapping
{
public static MessageDto AsDto(this Message message)
=> new MessageDto(
message.Id,
message.Employee.Id,
message.Text,
message.State,
message.HandledTime);
}
14 changes: 14 additions & 0 deletions ApplicationTier/Mapping/ReportMapping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using ApplicationTier.DTO;
using DataAccessTier.Models;

namespace ApplicationTier.Mapping;

public static class ReportMapping
{
public static ReportDto AsDto(this Report report)
=> new ReportDto(
report.Id,
report.Employee.Id,
report.FormedDate,
report.FullText);
}
11 changes: 11 additions & 0 deletions ApplicationTier/Services/IEmployee.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using ApplicationTier.DTO;

namespace ApplicationTier.Services;

public interface IEmployee
{
Task<EmployeeDto> CreateEmployeeAsync(string name, CancellationToken cancellationToken);
Task CheckMessageAsync(Guid employeeId, Guid messageId, CancellationToken cancellationToken);
Task AddLedEmployeeAsync(Guid id, Guid bossId, CancellationToken cancellationToken);
Task<ICollection<KeyValuePair<string, Guid>>> GetAllEmployeeGuids();
}
10 changes: 10 additions & 0 deletions ApplicationTier/Services/IMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using ApplicationTier.DTO;
using DataAccessTier.Models;

namespace ApplicationTier.Services;

public interface IMessage
{
Task<MessageDto> CreateMessageAsync(string text, Guid employeeId, CancellationToken cancellationToken);
Task<ICollection<MessageDto>> GetAllMessageGuids(Guid employeeId, CancellationToken cancellationToken);
}
9 changes: 9 additions & 0 deletions ApplicationTier/Services/IReport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using ApplicationTier.DTO;

namespace ApplicationTier.Services;

public interface IReport
{
Task<ReportDto> GetReportAsync(Guid employeeId, DateTime spanStart, DateTime spanEnd, CancellationToken cancellationToken);
Task<ICollection<ReportDto>> GetAllReportsAsync(Guid employeeId, CancellationToken cancellationToken);
}
49 changes: 49 additions & 0 deletions ApplicationTier/Services/Implementations/EmployeeService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using ApplicationTier.DTO;
using ApplicationTier.Extensions;
using ApplicationTier.Mapping;
using DataAccessTier;
using DataAccessTier.Models;

namespace ApplicationTier.Services.Implementations;

internal class EmployeeService : IEmployee
{
private readonly DatabaseContext _context;

public EmployeeService(DatabaseContext context)
{
_context = context;
}

public async Task<EmployeeDto> CreateEmployeeAsync(string name, CancellationToken cancellationToken)
{
var employee = new Employee(Guid.NewGuid(), name);
_context.Employees.Add(employee);
await _context.SaveChangesAsync(cancellationToken);
return employee.AsDto();
}

public async Task CheckMessageAsync(Guid employeeId, Guid messageId, CancellationToken cancellationToken)
{
var employee = await _context.Employees.GetEntityAsync(employeeId, cancellationToken);
var message = await _context.Messages.GetEntityAsync(messageId, cancellationToken);
if (!employee.Messages.Contains(message))
throw new Exception("this message is not subscribed to person");
message.State = MessageState.Checked;
message.HandledTime = DateTime.Now;
await _context.SaveChangesAsync(cancellationToken);
}

public async Task AddLedEmployeeAsync(Guid id, Guid bossId, CancellationToken cancellationToken)
{
var boss = await _context.Employees.GetEntityAsync(bossId, cancellationToken);
var employee = await _context.Employees.GetEntityAsync(id, cancellationToken);
boss.LedEmployees.Add(employee);
await _context.SaveChangesAsync(cancellationToken);
}

public Task<ICollection<KeyValuePair<string, Guid>>> GetAllEmployeeGuids()
=> Task.FromResult<ICollection<KeyValuePair<string, Guid>>>(_context.Employees
.Select(employee => KeyValuePair.Create<string, Guid>(employee.Name, employee.Id))
.ToList());
}
33 changes: 33 additions & 0 deletions ApplicationTier/Services/Implementations/MessageService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using ApplicationTier.DTO;
using ApplicationTier.Extensions;
using ApplicationTier.Mapping;
using DataAccessTier;
using DataAccessTier.Models;

namespace ApplicationTier.Services.Implementations;

internal class MessageService : IMessage
{
private readonly DatabaseContext _context;

public MessageService(DatabaseContext context)
{
_context = context;
}

public async Task<MessageDto> CreateMessageAsync(string text, Guid employeeId, CancellationToken cancellationToken)
{
var employee = await _context.Employees.GetEntityAsync(employeeId, cancellationToken);
var message = new Message(Guid.NewGuid(), employee, text);
employee.Messages.Add(message);
_context.Messages.Add(message);
await _context.SaveChangesAsync(cancellationToken);
return message.AsDto();
}

public async Task<ICollection<MessageDto>> GetAllMessageGuids(Guid employeeId, CancellationToken cancellationToken)
{
var employee = await _context.Employees.GetEntityAsync(employeeId, cancellationToken);
return employee.Messages.Select(message => message.AsDto()).ToArray();
}
}
43 changes: 43 additions & 0 deletions ApplicationTier/Services/Implementations/ReportService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using ApplicationTier.DTO;
using ApplicationTier.Extensions;
using ApplicationTier.Mapping;
using DataAccessTier;
using DataAccessTier.Models;

namespace ApplicationTier.Services.Implementations;

internal class ReportService : IReport
{
private readonly DatabaseContext _context;

public ReportService(DatabaseContext context)
{
_context = context;
}

public async Task<ReportDto> GetReportAsync(Guid employeeId, DateTime spanStart, DateTime spanEnd, CancellationToken cancellationToken)
{
var employee = await _context.Employees.GetEntityAsync(employeeId, cancellationToken);
string reportString = $"Report (from {spanStart} to {spanEnd}) for {employee.Id}\n" +
$"Quantity of subordinate employees: {employee.LedEmployees.Count}\n" +
$"Total handled messages: {employee.LedEmployees.Sum(e => e.Messages.Count(m => IsInRange(m.HandledTime, spanStart, spanEnd) && m.State.Equals(MessageState.Checked)))}\n" +
$"Total messages: {employee.LedEmployees.Sum(e => e.Messages.Count)}";
var report = new Report(Guid.NewGuid(), DateTime.Now, employee, reportString);
_context.Reports.Add(report);
await _context.SaveChangesAsync(cancellationToken);
return report.AsDto();
}

public async Task<ICollection<ReportDto>> GetAllReportsAsync(Guid employeeId, CancellationToken cancellationToken)
{
var employee = await _context.Employees.GetEntityAsync(employeeId, cancellationToken);
return _context.Reports
.ToArray()
.Select(r => r.AsDto())
.Where(dto => dto.EmployeeId.Equals(employee.Id))
.ToArray();
}

private static bool IsInRange(DateTime observedTime, DateTime spanStart, DateTime spanEnd)
=> observedTime >= spanStart && observedTime <= spanEnd;
}
23 changes: 23 additions & 0 deletions DataAccessTier/DataAccessTier.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<WarningLevel>5</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\.editorconfig" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions DataAccessTier/DatabaseContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using DataAccessTier.Models;
using Microsoft.EntityFrameworkCore;

namespace DataAccessTier;

public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options)
: base(options)
{
Database.EnsureCreated();
}

public DbSet<Employee> Employees { get; set; } = null!;
public DbSet<Message> Messages { get; set; } = null!;

public DbSet<Report> Reports { get; set; } = null!;

// TODO: decomposition
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>(builder =>
{
builder.HasMany(x => x.LedEmployees).WithOne().HasForeignKey("BossId");
builder.HasMany(x => x.Messages).WithOne().HasForeignKey("EmployeeId");
});
modelBuilder.Entity<Report>(builder =>
{
builder.HasOne(x => x.Employee);
});
}
}
13 changes: 13 additions & 0 deletions DataAccessTier/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace DataAccessTier.Extensions;

public static class ServiceCollectionExtensions
{
public static IServiceCollection AddDataAccess(this IServiceCollection collection, Action<DbContextOptionsBuilder> configuration)
{
collection.AddDbContext<DatabaseContext>(configuration);
return collection;
}
}
Loading

0 comments on commit 3b02413

Please sign in to comment.